Skip to content

Commit 87fa067

Browse files
committed
[d3d9] Hook up new compiler
1 parent 790b358 commit 87fa067

5 files changed

Lines changed: 178 additions & 13 deletions

File tree

src/d3d9/d3d9_device.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8103,11 +8103,20 @@ namespace dxvk {
81038103

81048104

81058105
void D3D9DeviceEx::InitShaderOptions() {
8106+
if (m_d3d9Options.useDxbcSpirv)
8107+
Logger::info("Using DXBC-SPIRV!");
8108+
81068109
m_dxvkShaderOptions = m_dxvkDevice->getShaderCompileOptions();
8110+
m_dxvkShaderOptions.flags.set(DxvkShaderCompileFlag::SemanticIo);
81078111

81088112
if (m_d3d9Options.forceSampleRateShading)
81098113
m_dxvkShaderOptions.flags.set(DxvkShaderCompileFlag::EnableSampleRateShading);
81108114

8115+
if (!m_d3d9Options.useFP16)
8116+
m_dxvkShaderOptions.flags.clr(DxvkShaderCompileFlag::Supports16BitArithmetic);
8117+
else
8118+
Logger::info("Using FP16.");
8119+
81118120
m_shaderOptions.d3d9FloatEmulation = m_d3d9Options.d3d9FloatEmulation;
81128121
m_shaderOptions.isSWVP = CanSWVP();
81138122
m_shaderOptions.forceSamplerTypeSpecConstants = m_d3d9Options.forceSamplerTypeSpecConstants;
@@ -8251,9 +8260,10 @@ namespace dxvk {
82518260
D3D9CommonShader commonShader = { };
82528261

82538262
D3D9ShaderCreateInfo moduleInfo;
8254-
moduleInfo.irCreateInfo = {};
8255-
moduleInfo.irCreateInfo.options = m_dxvkShaderOptions;
8256-
moduleInfo.shaderOptions = m_shaderOptions;
8263+
moduleInfo.irCreateInfo = {};
8264+
moduleInfo.irCreateInfo.options = m_dxvkShaderOptions;
8265+
moduleInfo.irCreateInfo.flatShadingInputs = analysis.GetFlatShadingMask();
8266+
moduleInfo.shaderOptions = m_shaderOptions;
82578267

82588268
HRESULT hr = m_shaderModules->GetShaderModule(this,
82598269
key, std::move(analysis), moduleInfo, pShaderBytecode, &commonShader);

src/d3d9/d3d9_options.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ namespace dxvk {
7676
this->extraFrontbuffer = config.getOption<bool> ("d3d9.extraFrontbuffer", false);
7777
this->ffUbershaderVS = config.getOption<bool> ("d3d9.ffUbershaderVS", true);
7878
this->ffUbershaderFS = config.getOption<bool> ("d3d9.ffUbershaderFS", true);
79+
this->useDxbcSpirv = config.getOption<bool> ("d3d9.useDxbcSpirv", false);
7980

8081
// D3D8 options
8182
this->drefScaling = config.getOption<int32_t> ("d3d8.scaleDref", 0);
@@ -85,6 +86,11 @@ namespace dxvk {
8586
// Clamp LOD bias so that people don't abuse this in unintended ways
8687
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);
8788

89+
bool hasMulz = adapter != nullptr
90+
&& (adapter->matchesDriver(VK_DRIVER_ID_MESA_RADV)
91+
|| adapter->matchesDriver(VK_DRIVER_ID_MESA_NVK)
92+
|| adapter->matchesDriver(VK_DRIVER_ID_AMD_OPEN_SOURCE, Version(2, 0, 316), Version())
93+
|| adapter->matchesDriver(VK_DRIVER_ID_NVIDIA_PROPRIETARY, Version(565, 57, 1), Version()));
8894
std::string floatEmulation = Config::toLower(config.getOption<std::string>("d3d9.floatEmulation", "auto"));
8995
if (floatEmulation == "strict") {
9096
this->d3d9FloatEmulation = D3D9FloatEmulation::Strict;
@@ -93,14 +99,16 @@ namespace dxvk {
9399
} else if (floatEmulation == "true") {
94100
this->d3d9FloatEmulation = D3D9FloatEmulation::Enabled;
95101
} else {
96-
bool hasMulz = adapter != nullptr
97-
&& (adapter->matchesDriver(VK_DRIVER_ID_MESA_RADV)
98-
|| adapter->matchesDriver(VK_DRIVER_ID_MESA_NVK)
99-
|| adapter->matchesDriver(VK_DRIVER_ID_AMD_OPEN_SOURCE, Version(2, 0, 316), Version())
100-
|| adapter->matchesDriver(VK_DRIVER_ID_NVIDIA_PROPRIETARY, Version(565, 57, 1), Version()));
101102
this->d3d9FloatEmulation = hasMulz ? D3D9FloatEmulation::Strict : D3D9FloatEmulation::Enabled;
102103
}
103104

105+
Tristate useFP16 = config.getOption<Tristate>("d3d9.useFP16", Tristate::Auto);
106+
if (useFP16 == Tristate::Auto) {
107+
this->useFP16 = !hasMulz;
108+
} else {
109+
this->useFP16 = useFP16 == Tristate::True;
110+
}
111+
104112
this->shaderDumpPath = env::getEnvVar("DXVK_SHADER_DUMP_PATH");
105113
}
106114

src/d3d9/d3d9_options.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
namespace dxvk {
77

8-
enum class D3D9FloatEmulation {
9-
Disabled,
10-
Enabled,
11-
Strict
8+
enum class D3D9FloatEmulation : uint8_t {
9+
Disabled = 0,
10+
Enabled = 1,
11+
Strict = 2
1212
};
1313

1414
struct D3D9Options {
@@ -73,6 +73,9 @@ namespace dxvk {
7373
/// D3D9 Floating Point Emulation (anything * 0 = 0)
7474
D3D9FloatEmulation d3d9FloatEmulation;
7575

76+
/// Whether shaders use FP16 for partial precision instructions
77+
bool useFP16;
78+
7679
/// Support the DF16 & DF24 texture format
7780
bool supportDFFormats;
7881

@@ -167,6 +170,9 @@ namespace dxvk {
167170

168171
/// Use the uber shader for fixed function fragment shaders.
169172
bool ffUbershaderFS;
173+
174+
// Use the new DXBC-SPIRV based shader compiler.
175+
bool useDxbcSpirv;
170176
};
171177

172178
}

src/d3d9/d3d9_shader.cpp

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,116 @@ namespace dxvk {
3232

3333
};
3434

35+
class D3D9ShaderConverter : public DxvkIrShaderConverter {
36+
37+
public:
38+
39+
D3D9ShaderConverter(
40+
const DxvkShaderHash& ShaderKey,
41+
const D3D9ShaderOptions& Options,
42+
const void* pShaderBytecode,
43+
size_t BytecodeLength)
44+
: m_key(ShaderKey), m_options(Options) {
45+
m_dxbc.resize(BytecodeLength);
46+
std::memcpy(m_dxbc.data(), pShaderBytecode, BytecodeLength);
47+
}
48+
49+
~D3D9ShaderConverter() { }
50+
51+
void convertShader(
52+
dxbc_spv::ir::Builder& builder) {
53+
auto debugName = m_key.toString();
54+
55+
dxbc_spv::sm3::Converter::Options options = { };
56+
options.name = debugName.c_str();
57+
options.includeDebugNames = true;
58+
options.fastFloatEmulation = m_options.d3d9FloatEmulation == D3D9FloatEmulation::Enabled;
59+
options.isSWVP = m_options.isSWVP && m_key.stage() == VK_SHADER_STAGE_VERTEX_BIT;
60+
61+
dxbc_spv::util::ByteReader reader(m_dxbc.data(), m_dxbc.size());
62+
63+
D3D9SpecializationConstantLayout specConstLayout;
64+
65+
dxbc_spv::sm3::Converter converter(reader, specConstLayout, options);
66+
67+
if (!converter.convertShader(builder))
68+
throw DxvkError(str::format("Failed to convert shader: ", m_key.toString()));
69+
}
70+
71+
uint32_t determineResourceIndex(
72+
dxbc_spv::ir::ShaderStage stage,
73+
dxbc_spv::ir::ScalarType type,
74+
uint32_t regSpace,
75+
uint32_t regIndex) const {
76+
77+
// D3D9ShaderType has pixel shaders at 1, dxbc_spv has vertex shaders at 1.
78+
D3D9ShaderType shaderType = stage == dxbc_spv::ir::ShaderStage::ePixel
79+
? D3D9ShaderType::PixelShader
80+
: D3D9ShaderType::VertexShader;
81+
82+
switch (type) {
83+
case dxbc_spv::ir::ScalarType::eCbv:
84+
switch (regIndex) {
85+
case dxbc_spv::sm3::FastSpecConstCbvRegIdx:
86+
return D3D9ShaderResourceMapping::getSpecConstantBufferSlot();
87+
88+
case dxbc_spv::sm3::PSSharedDataCbvRegIdx: {
89+
if (shaderType == D3D9ShaderType::PixelShader) {
90+
return D3D9ShaderResourceMapping::computeCbvBinding(shaderType,
91+
D3D9ShaderResourceMapping::ConstantBuffers::PSShared);
92+
} else { //case dxbc_spv::sm3::VSClipPlanesCbvRegIdx: (same index)
93+
return D3D9ShaderResourceMapping::computeCbvBinding(shaderType,
94+
D3D9ShaderResourceMapping::ConstantBuffers::VSClipPlanes);
95+
}
96+
}
97+
98+
// the index for the D3D9 constant buffer are is the same for VS and PS */
99+
case dxbc_spv::sm3::FloatIntCbvRegIdx:
100+
return D3D9ShaderResourceMapping::computeCbvBinding(shaderType,
101+
D3D9ShaderResourceMapping::ConstantBuffers::VSConstantBuffer);
102+
103+
case dxbc_spv::sm3::SWVPIntCbvRegIdx:
104+
return D3D9ShaderResourceMapping::computeCbvBinding(shaderType,
105+
D3D9ShaderResourceMapping::ConstantBuffers::VSIntConstantBuffer);
106+
107+
case dxbc_spv::sm3::SWVPBoolCbvRegIdx:
108+
return D3D9ShaderResourceMapping::computeCbvBinding(shaderType,
109+
D3D9ShaderResourceMapping::ConstantBuffers::VSBoolConstantBuffer);
110+
111+
default: break;
112+
}
113+
break;
114+
115+
case dxbc_spv::ir::ScalarType::eSrv:
116+
case dxbc_spv::ir::ScalarType::eSampler:
117+
return D3D9ShaderResourceMapping::computeTextureBinding(shaderType, regIndex);
118+
119+
default: break;
120+
}
121+
122+
Logger::err(str::format("Missing Resource index. Stage: ", stage, ", regSpace: ", regSpace, ", regIndex: ", regIndex));
123+
return -1u;
124+
}
125+
126+
void dumpSource(const std::string& path) const {
127+
std::ofstream file(str::topath(str::format(path, "/", m_key.toString(), ".sm3_dxbc").c_str()).c_str(), std::ios_base::trunc | std::ios_base::binary);
128+
file.write(reinterpret_cast<const char*>(m_dxbc.data()), m_dxbc.size());
129+
}
130+
131+
std::string getDebugName() const {
132+
return m_key.toString();
133+
}
134+
135+
private:
136+
137+
std::vector<uint8_t> m_dxbc;
138+
139+
DxvkShaderHash m_key;
140+
141+
D3D9ShaderOptions m_options;
142+
143+
};
144+
35145
D3D9CommonShader::D3D9CommonShader(
36146
D3D9DeviceEx* pDevice,
37147
const DxvkShaderHash& ShaderKey,
@@ -53,7 +163,10 @@ namespace dxvk {
53163
file.write(reinterpret_cast<const char*>(pShaderBytecode), bytecodeLength);
54164
}
55165

56-
CreateLegacyShader(pDevice, ShaderKey, ModuleInfo, pShaderBytecode);
166+
if (pDevice->GetOptions()->useDxbcSpirv)
167+
CreateIrShader(pDevice, ShaderKey, ModuleInfo, pShaderBytecode, m_analysis.GetLength());
168+
else
169+
CreateLegacyShader(pDevice, ShaderKey, ModuleInfo, pShaderBytecode);
57170

58171
if (!dumpPath.empty()) {
59172
std::ofstream dumpStream(
@@ -66,6 +179,25 @@ namespace dxvk {
66179
}
67180

68181

182+
void D3D9CommonShader::CreateIrShader(
183+
D3D9DeviceEx* pDevice,
184+
const DxvkShaderHash& ShaderKey,
185+
const D3D9ShaderCreateInfo& ModuleInfo,
186+
const void* pShaderBytecode,
187+
size_t BytecodeLength) {
188+
m_shader = pDevice->GetDXVKDevice()->createCachedShader(
189+
ShaderKey.toString(), ModuleInfo.irCreateInfo, nullptr);
190+
191+
if (!m_shader) {
192+
Rc<D3D9ShaderConverter> converter = new D3D9ShaderConverter(ShaderKey, ModuleInfo.shaderOptions,
193+
pShaderBytecode, BytecodeLength);
194+
195+
m_shader = pDevice->GetDXVKDevice()->createCachedShader(
196+
ShaderKey.toString(), ModuleInfo.irCreateInfo, std::move(converter));
197+
}
198+
}
199+
200+
69201
void D3D9CommonShader::CreateLegacyShader(
70202
D3D9DeviceEx* pDevice,
71203
const DxvkShaderHash& ShaderKey,

src/d3d9/d3d9_shader.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ namespace dxvk {
4242
bool forceSamplerTypeSpecConstants;
4343
};
4444

45+
static_assert(sizeof(D3D9ShaderOptions) == 3u);
46+
4547
struct D3D9ShaderCreateInfo {
4648
DxvkIrShaderCreateInfo irCreateInfo;
4749

@@ -149,6 +151,13 @@ namespace dxvk {
149151

150152
private:
151153

154+
void CreateIrShader(
155+
D3D9DeviceEx* pDevice,
156+
const DxvkShaderHash& ShaderKey,
157+
const D3D9ShaderCreateInfo& ModuleInfo,
158+
const void* pShaderBytecode,
159+
size_t BytecodeLength);
160+
152161
void CreateLegacyShader(
153162
D3D9DeviceEx* pDevice,
154163
const DxvkShaderHash& ShaderKey,

0 commit comments

Comments
 (0)