Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/doitsujin/dxvk.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Ashton <joshua@froggi.es>2022-07-31 04:24:13 +0300
committerJoshua Ashton <joshua@froggi.es>2022-07-31 19:05:36 +0300
commit9dda7c8c849a85e772fd4208d2579f7cb2d3e7f2 (patch)
tree29b7d7b8d904fd29f893519dd7df5d0ad587008f
parent4905c6a0e1261063773bf31f0cdcbb303c16a7dc (diff)
-rw-r--r--src/d3d9/d3d9_device.cpp10
-rw-r--r--src/d3d9/d3d9_device.h1
-rw-r--r--src/d3d9/d3d9_fixed_function.cpp60
-rw-r--r--src/d3d9/d3d9_fixed_function.h7
-rw-r--r--src/d3d9/d3d9_spec_constants.h38
-rw-r--r--src/dxso/dxso_compiler.cpp26
-rw-r--r--src/dxso/dxso_compiler.h2
7 files changed, 117 insertions, 27 deletions
diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp
index 7f5ca44c..e3aead38 100644
--- a/src/d3d9/d3d9_device.cpp
+++ b/src/d3d9/d3d9_device.cpp
@@ -4874,6 +4874,11 @@ namespace dxvk {
CanSWVP()
? sizeof(D3D9FixedFunctionVertexBlendDataSW)
: sizeof(D3D9FixedFunctionVertexBlendDataHW));
+
+ m_specBuffer = D3D9ConstantBuffer(this,
+ VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
+ getSpecConstantBufferSlot(),
+ sizeof(D3D9SpecializationInfo));
}
@@ -7284,6 +7289,11 @@ namespace dxvk {
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, i, cSpecInfo.data[i]);
});
+ // TODO: Make uploading specialization information less naive.
+ auto mapPtr = m_specBuffer.AllocSlice();
+ auto dst = reinterpret_cast<D3D9SpecializationInfo*>(mapPtr);
+ *dst = m_specInfo;
+
m_flags.clr(D3D9DeviceFlag::DirtySpecializationEntries);
}
diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h
index 0e1b5401..02be7e31 100644
--- a/src/d3d9/d3d9_device.h
+++ b/src/d3d9/d3d9_device.h
@@ -1186,6 +1186,7 @@ namespace dxvk {
D3D9ConstantBuffer m_vsVertexBlend;
D3D9ConstantBuffer m_psFixedFunction;
D3D9ConstantBuffer m_psShared;
+ D3D9ConstantBuffer m_specBuffer;
Rc<DxvkBuffer> m_upBuffer;
VkDeviceSize m_upBufferOffset = 0ull;
diff --git a/src/d3d9/d3d9_fixed_function.cpp b/src/d3d9/d3d9_fixed_function.cpp
index 45224b74..350bda75 100644
--- a/src/d3d9/d3d9_fixed_function.cpp
+++ b/src/d3d9/d3d9_fixed_function.cpp
@@ -40,10 +40,10 @@ namespace dxvk {
spvModule.opAccessChain(floatPtr, fogCtx.RenderState, 1, &fogDensityMember));
uint32_t fogMode = spec.get(
- spvModule,
+ spvModule, fogCtx.SpecUBO,
fogCtx.IsPixel ? SpecPixelFogMode : SpecVertexFogMode);
- uint32_t fogEnabled = spec.get(spvModule, SpecFogEnabled);
+ uint32_t fogEnabled = spec.get(spvModule, fogCtx.SpecUBO, SpecFogEnabled);
fogEnabled = spvModule.opINotEqual(spvModule.defBoolType(), fogEnabled, spvModule.constu32(0));
uint32_t doFog = spvModule.allocateId();
@@ -244,7 +244,43 @@ namespace dxvk {
}
- D3D9PointSizeInfoVS GetPointSizeInfoVS(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, uint32_t vPos, uint32_t vtx, uint32_t perVertPointSize, uint32_t rsBlock, bool isFixedFunction) {
+ uint32_t SetupSpecUBO(SpirvModule& spvModule, std::vector<DxvkBindingInfo>& bindings) {
+ uint32_t uintType = spvModule.defIntType(32, 0);
+
+ std::array<uint32_t, SpecConstantCount> specMembers;
+ for (auto& x : specMembers)
+ x = uintType;
+
+ uint32_t specStruct = spvModule.defStructTypeUnique(uint32_t(specMembers.size()), specMembers.data());
+
+ spvModule.setDebugName (specStruct, "spec_state_t");
+ spvModule.decorate (specStruct, spv::DecorationBlock);
+
+ for (uint32_t i = 0; i < SpecConstantCount; i++) {
+ std::string name = str::format("dword", i);
+ spvModule.setDebugMemberName (specStruct, i, name.c_str());
+ spvModule.memberDecorateOffset (specStruct, i, sizeof(uint32_t) * i);
+ }
+
+ uint32_t specBlock = spvModule.newVar(
+ spvModule.defPointerType(specStruct, spv::StorageClassUniform),
+ spv::StorageClassUniform);
+
+ spvModule.setDebugName (specBlock, "spec_state");
+ spvModule.decorateDescriptorSet(specBlock, 0);
+ spvModule.decorateBinding (specBlock, getSpecConstantBufferSlot());
+
+ DxvkBindingInfo binding = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER };
+ binding.resourceBinding = getSpecConstantBufferSlot();
+ binding.viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
+ binding.access = VK_ACCESS_UNIFORM_READ_BIT;
+ bindings.push_back(binding);
+
+ return specBlock;
+ }
+
+
+ D3D9PointSizeInfoVS GetPointSizeInfoVS(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, uint32_t vPos, uint32_t vtx, uint32_t perVertPointSize, uint32_t rsBlock, uint32_t specUbo, bool isFixedFunction) {
uint32_t floatType = spvModule.defFloatType(32);
uint32_t floatPtr = spvModule.defPointerType(floatType, spv::StorageClassPushConstant);
uint32_t vec3Type = spvModule.defVectorType(floatType, 3);
@@ -260,7 +296,7 @@ namespace dxvk {
uint32_t value = perVertPointSize != 0 ? perVertPointSize : LoadFloat(D3D9RenderStateItem::PointSize);
if (isFixedFunction) {
- uint32_t pointMode = spec.get(spvModule, SpecPointMode);
+ uint32_t pointMode = spec.get(spvModule, specUbo, SpecPointMode);
uint32_t scaleBit = spvModule.opBitFieldUExtract(uint32Type, pointMode, spvModule.consti32(0), spvModule.consti32(1));
uint32_t isScale = spvModule.opIEqual(boolType, scaleBit, spvModule.constu32(1));
@@ -306,12 +342,12 @@ namespace dxvk {
}
- D3D9PointSizeInfoPS GetPointSizeInfoPS(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, uint32_t rsBlock) {
+ D3D9PointSizeInfoPS GetPointSizeInfoPS(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, uint32_t rsBlock, uint32_t specUbo) {
uint32_t uint32Type = spvModule.defIntType(32, 0);
uint32_t boolType = spvModule.defBoolType();
uint32_t boolVec4 = spvModule.defVectorType(boolType, 4);
- uint32_t pointMode = spec.get(spvModule, SpecPointMode);
+ uint32_t pointMode = spec.get(spvModule, specUbo, SpecPointMode);
uint32_t spriteBit = spvModule.opBitFieldUExtract(uint32Type, pointMode, spvModule.consti32(1), spvModule.consti32(1));
uint32_t isSprite = spvModule.opIEqual(boolType, spriteBit, spvModule.constu32(1));
@@ -615,6 +651,8 @@ namespace dxvk {
uint32_t m_entryPointId;
uint32_t m_rsBlock;
+ uint32_t m_specUbo;
+
uint32_t m_mainFuncLabel;
D3D9FixedFunctionOptions m_options;
@@ -1153,9 +1191,10 @@ namespace dxvk {
fogCtx.IsPositionT = m_vsKey.Data.Contents.HasPositionT;
fogCtx.HasSpecular = m_vsKey.Data.Contents.HasColor1;
fogCtx.Specular = m_vs.in.COLOR[1];
+ fogCtx.SpecUBO = m_specUbo;
m_module.opStore(m_vs.out.FOG, DoFixedFunctionFog(m_spec, m_module, fogCtx));
- auto pointInfo = GetPointSizeInfoVS(m_spec, m_module, 0, vtx, m_vs.in.POINTSIZE, m_rsBlock, true);
+ auto pointInfo = GetPointSizeInfoVS(m_spec, m_module, 0, vtx, m_vs.in.POINTSIZE, m_rsBlock, m_specUbo, true);
uint32_t pointSize = m_module.opFClamp(m_floatType, pointInfo.defaultValue, pointInfo.min, pointInfo.max);
m_module.opStore(m_vs.out.POINTSIZE, pointSize);
@@ -1416,6 +1455,7 @@ namespace dxvk {
void D3D9FFShaderCompiler::setupVS() {
setupRenderStateInfo();
+ m_specUbo = SetupSpecUBO(m_module, m_bindings);
// VS Caps
m_module.enableCapability(spv::CapabilityClipDistance);
@@ -1946,6 +1986,7 @@ namespace dxvk {
fogCtx.IsPositionT = false;
fogCtx.HasSpecular = false;
fogCtx.Specular = 0;
+ fogCtx.SpecUBO = m_specUbo;
current = DoFixedFunctionFog(m_spec, m_module, fogCtx);
m_module.opStore(m_ps.out.COLOR, current);
@@ -1955,6 +1996,7 @@ namespace dxvk {
void D3D9FFShaderCompiler::setupPS() {
setupRenderStateInfo();
+ m_specUbo = SetupSpecUBO(m_module, m_bindings);
// PS Caps
m_module.enableCapability(spv::CapabilityDerivativeControl);
@@ -1963,7 +2005,7 @@ namespace dxvk {
spv::ExecutionModeOriginUpperLeft);
uint32_t pointCoord = GetPointCoord(m_module);
- auto pointInfo = GetPointSizeInfoPS(m_spec, m_module, m_rsBlock);
+ auto pointInfo = GetPointSizeInfoPS(m_spec, m_module, m_rsBlock, m_specUbo);
// We need to replace TEXCOORD inputs with gl_PointCoord
// if D3DRS_POINTSPRITEENABLE is set.
@@ -2182,7 +2224,7 @@ namespace dxvk {
uint32_t floatPtr = m_module.defPointerType(m_floatType, spv::StorageClassPushConstant);
// Declare spec constants for render states
- uint32_t alphaFuncId = m_spec.get(m_module, SpecAlphaCompareOp);
+ uint32_t alphaFuncId = m_spec.get(m_module, m_specUbo, SpecAlphaCompareOp);
// Implement alpha test
auto oC0 = m_ps.out.COLOR;
diff --git a/src/d3d9/d3d9_fixed_function.h b/src/d3d9/d3d9_fixed_function.h
index 0649f842..c6007791 100644
--- a/src/d3d9/d3d9_fixed_function.h
+++ b/src/d3d9/d3d9_fixed_function.h
@@ -35,6 +35,7 @@ namespace dxvk {
bool IsPositionT;
bool HasSpecular;
uint32_t Specular;
+ uint32_t SpecUBO;
};
struct D3D9FixedFunctionOptions {
@@ -57,18 +58,20 @@ namespace dxvk {
};
// Default point size and point scale magic!
- D3D9PointSizeInfoVS GetPointSizeInfoVS(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, uint32_t vPos, uint32_t vtx, uint32_t perVertPointSize, uint32_t rsBlock, bool isFixedFunction);
+ D3D9PointSizeInfoVS GetPointSizeInfoVS(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, uint32_t vPos, uint32_t vtx, uint32_t perVertPointSize, uint32_t rsBlock, uint32_t specUbo, bool isFixedFunction);
struct D3D9PointSizeInfoPS {
uint32_t isSprite;
};
- D3D9PointSizeInfoPS GetPointSizeInfoPS(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, uint32_t rsBlock);
+ D3D9PointSizeInfoPS GetPointSizeInfoPS(D3D9ShaderSpecConstantManager& spec, SpirvModule& spvModule, uint32_t rsBlock, uint32_t specUbo);
uint32_t GetPointCoord(SpirvModule& spvModule);
uint32_t GetSharedConstants(SpirvModule& spvModule);
+ uint32_t SetupSpecUBO(SpirvModule& spvModule, std::vector<DxvkBindingInfo>& bindings);
+
constexpr uint32_t TCIOffset = 16;
constexpr uint32_t TCIMask = 0b111 << TCIOffset;
diff --git a/src/d3d9/d3d9_spec_constants.h b/src/d3d9/d3d9_spec_constants.h
index 16c2f519..3c4eef70 100644
--- a/src/d3d9/d3d9_spec_constants.h
+++ b/src/d3d9/d3d9_spec_constants.h
@@ -4,6 +4,7 @@
#include <cstdint>
+#include "../dxvk/dxvk_limits.h"
#include "../spirv/spirv_module.h"
class D3D9DeviceEx;
@@ -89,22 +90,28 @@ namespace dxvk {
class D3D9ShaderSpecConstantManager {
public:
- uint32_t get(SpirvModule &module, D3D9SpecConstantId id) {
+ uint32_t get(SpirvModule &module, uint32_t specUbo, D3D9SpecConstantId id) {
const auto &layout = D3D9SpecializationInfo::Layout[id];
- uint32_t val = getSpecConstDword(module, layout.dwordOffset);
+ uint32_t uintType = module.defIntType(32, 0);
+ uint32_t optimized = getOptimizedBool(module);
+
+ uint32_t quickValue = getSpecUBODword(module, specUbo, layout.dwordOffset);
+ uint32_t optimizedValue = getSpecConstDword(module, layout.dwordOffset);
+
+ uint32_t val = module.opSelect(uintType, optimized, optimizedValue, quickValue);
if (layout.sizeInBits == 32)
return val;
return module.opBitFieldUExtract(
- module.defIntType(32, 0),
+ uintType,
val,
module.consti32(layout.bitOffset),
module.consti32(layout.sizeInBits));
}
private:
- uint32_t getSpecConstDword(SpirvModule &module, uint32_t idx) {
+ uint32_t getSpecConstDword(SpirvModule& module, uint32_t idx) {
if (!m_specConstantIds[idx]) {
m_specConstantIds[idx] = module.specConst32(module.defIntType(32, 0), 0);
module.decorateSpecId(m_specConstantIds[idx], idx);
@@ -113,7 +120,28 @@ namespace dxvk {
return m_specConstantIds[idx];
}
- std::array<uint32_t, D3D9SpecializationInfo::MaxSpecDwords> m_specConstantIds = {};
+ uint32_t getSpecUBODword(SpirvModule& module, uint32_t specUbo, uint32_t idx) {
+ uint32_t uintType = module.defIntType(32, 0);
+ uint32_t uintPtr = module.defPointerType(uintType, spv::StorageClassUniform);
+
+ uint32_t member = module.constu32(idx);
+ uint32_t dword = module.opLoad(uintType, module.opAccessChain(uintPtr, specUbo, 1, &member));
+
+ return dword;
+ }
+
+ uint32_t getOptimizedBool(SpirvModule& module) {
+ uint32_t boolType = module.defBoolType();
+
+ // The spec constant at MaxNumSpecConstants is set to True
+ // when this is an optimized pipeline.
+ uint32_t optimized = getSpecConstDword(module, MaxNumSpecConstants);
+ optimized = module.opINotEqual(boolType, optimized, module.constu32(0));
+
+ return optimized;
+ }
+
+ std::array<uint32_t, MaxNumSpecConstants + 1> m_specConstantIds = {};
};
} \ No newline at end of file
diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp
index 86937c27..1d5888bd 100644
--- a/src/dxso/dxso_compiler.cpp
+++ b/src/dxso/dxso_compiler.cpp
@@ -480,6 +480,8 @@ namespace dxvk {
this->setupRenderStateInfo();
+ m_specUbo = SetupSpecUBO(m_module, m_bindings);
+
this->emitFunctionBegin(
m_vs.functionId,
m_module.defVoidType(),
@@ -513,7 +515,6 @@ namespace dxvk {
m_module.setExecutionMode(m_entryPointId,
spv::ExecutionModeOriginUpperLeft);
-
// Main function of the pixel shader
m_ps.functionId = m_module.allocateId();
m_module.setDebugName(m_ps.functionId, "ps_main");
@@ -521,6 +522,8 @@ namespace dxvk {
this->setupRenderStateInfo();
this->emitPsSharedConstants();
+ m_specUbo = SetupSpecUBO(m_module, m_bindings);
+
this->emitFunctionBegin(
m_ps.functionId,
m_module.defVoidType(),
@@ -1029,7 +1032,7 @@ namespace dxvk {
bitfield = m_module.opLoad(accessType, ptrId);
}
else {
- bitfield = m_spec.get(m_module,
+ bitfield = m_spec.get(m_module, m_specUbo,
m_programInfo.type() == DxsoProgramType::VertexShader
? SpecVertexShaderBools
: SpecPixelShaderBools);
@@ -2763,7 +2766,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t bool_t = m_module.defBoolType();
uint32_t shouldProj = m_module.opBitFieldUExtract(
- m_module.defIntType(32, 0), m_spec.get(m_module, SpecProjectionType),
+ m_module.defIntType(32, 0), m_spec.get(m_module, m_specUbo, SpecProjectionType),
m_module.consti32(samplerIdx), m_module.consti32(1));
shouldProj = m_module.opINotEqual(bool_t, shouldProj, m_module.constu32(0));
@@ -2930,7 +2933,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t fetch4 = 0;
if (m_programInfo.type() == DxsoProgramType::PixelShader && samplerType != SamplerTypeTexture3D) {
fetch4 = m_module.opBitFieldUExtract(
- m_module.defIntType(32, 0), m_spec.get(m_module, SpecFetch4),
+ m_module.defIntType(32, 0), m_spec.get(m_module, m_specUbo, SpecFetch4),
m_module.consti32(samplerIdx), m_module.consti32(1));
uint32_t bool_t = m_module.defBoolType();
@@ -2963,7 +2966,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
imageOperands);
uint32_t shouldProj = m_module.opBitFieldUExtract(
- m_module.defIntType(32, 0), m_spec.get(m_module, SpecProjectionType),
+ m_module.defIntType(32, 0), m_spec.get(m_module, m_specUbo, SpecProjectionType),
m_module.consti32(samplerIdx), m_module.consti32(1));
shouldProj = m_module.opINotEqual(m_module.defBoolType(), shouldProj, m_module.constu32(0));
@@ -3026,7 +3029,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t offset = m_module.consti32(m_programInfo.type() == DxsoProgramTypes::VertexShader ? samplerIdx + 17 : samplerIdx);
uint32_t bitCnt = m_module.consti32(1);
- uint32_t isNull = m_module.opBitFieldUExtract(typeId, m_spec.get(m_module, SpecSamplerNull), offset, bitCnt);
+ uint32_t isNull = m_module.opBitFieldUExtract(typeId, m_spec.get(m_module, m_specUbo, SpecSamplerNull), offset, bitCnt);
isNull = m_module.opINotEqual(m_module.defBoolType(), isNull, m_module.constu32(0));
// Only do the check for depth comp. samplers
@@ -3036,7 +3039,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t depthLabel = m_module.allocateId();
uint32_t endLabel = m_module.allocateId();
- uint32_t isDepth = m_module.opBitFieldUExtract(typeId, m_spec.get(m_module, SpecSamplerDepthMode), offset, bitCnt);
+ uint32_t isDepth = m_module.opBitFieldUExtract(typeId, m_spec.get(m_module, m_specUbo, SpecSamplerDepthMode), offset, bitCnt);
isDepth = m_module.opINotEqual(m_module.defBoolType(), isDepth, m_module.constu32(0));
m_module.opSelectionMerge(endLabel, spv::SelectionControlMaskNone);
@@ -3076,7 +3079,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t offset = m_module.consti32(samplerIdx * 2);
uint32_t bitCnt = m_module.consti32(2);
- uint32_t type = m_module.opBitFieldUExtract(typeId, m_spec.get(m_module, SpecSamplerType), offset, bitCnt);
+ uint32_t type = m_module.opBitFieldUExtract(typeId, m_spec.get(m_module, m_specUbo, SpecSamplerType), offset, bitCnt);
m_module.opSelectionMerge(switchEndLabel, spv::SelectionControlMaskNone);
m_module.opSwitch(type,
@@ -3340,7 +3343,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
if (m_programInfo.type() == DxsoProgramType::PixelShader) {
pointCoord = GetPointCoord(m_module);
- pointInfo = GetPointSizeInfoPS(m_spec, m_module, m_rsBlock);
+ pointInfo = GetPointSizeInfoPS(m_spec, m_module, m_rsBlock, m_specUbo);
}
for (uint32_t i = 0; i < m_isgn.elemCount; i++) {
@@ -3570,7 +3573,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
if (!outputtedColor1)
OutputDefault(DxsoSemantic{ DxsoUsage::Color, 1 });
- auto pointInfo = GetPointSizeInfoVS(m_spec, m_module, m_vs.oPos.id, 0, 0, m_rsBlock, false);
+ auto pointInfo = GetPointSizeInfoVS(m_spec, m_module, m_vs.oPos.id, 0, 0, m_rsBlock, m_specUbo, false);
if (m_vs.oPSize.id == 0) {
m_vs.oPSize = this->emitRegisterPtr(
@@ -3721,6 +3724,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
fogCtx.IsPositionT = false;
fogCtx.HasSpecular = false;
fogCtx.Specular = 0;
+ fogCtx.SpecUBO = m_specUbo;
m_module.opStore(oColor0Ptr.id, DoFixedFunctionFog(m_spec, m_module, fogCtx));
}
@@ -3731,7 +3735,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t floatType = m_module.defFloatType(32);
uint32_t floatPtr = m_module.defPointerType(floatType, spv::StorageClassPushConstant);
- uint32_t alphaFuncId = m_spec.get(m_module, SpecAlphaCompareOp);
+ uint32_t alphaFuncId = m_spec.get(m_module, m_specUbo, SpecAlphaCompareOp);
// Implement alpha test and fog
DxsoRegister color0;
diff --git a/src/dxso/dxso_compiler.h b/src/dxso/dxso_compiler.h
index c5f1b8a8..4360e599 100644
--- a/src/dxso/dxso_compiler.h
+++ b/src/dxso/dxso_compiler.h
@@ -367,6 +367,8 @@ namespace dxvk {
uint32_t m_usedSamplers;
uint32_t m_usedRTs;
+ uint32_t m_specUbo = 0;
+
uint32_t m_rsBlock = 0;
uint32_t m_mainFuncLabel = 0;