1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[d3d9] Support for graphics pipeline libraries

This commit is contained in:
Joshua Ashton 2022-08-06 01:20:01 +00:00
parent 9108f8c76c
commit 65da0da954
7 changed files with 119 additions and 26 deletions

View File

@ -111,6 +111,8 @@ namespace dxvk {
}
}
m_usingGraphicsPipelines = dxvkDevice->features().extGraphicsPipelineLibrary.graphicsPipelineLibrary;
CreateConstantBuffers();
m_availableMemory = DetermineInitialTextureMemory();
@ -4862,6 +4864,13 @@ namespace dxvk {
CanSWVP()
? sizeof(D3D9FixedFunctionVertexBlendDataSW)
: sizeof(D3D9FixedFunctionVertexBlendDataHW));
if (m_usingGraphicsPipelines) {
m_specBuffer = D3D9ConstantBuffer(this,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
getSpecConstantBufferSlot(),
sizeof(D3D9SpecializationInfo));
}
}
@ -7303,6 +7312,13 @@ namespace dxvk {
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, i, cSpecInfo.data[i]);
});
if (m_usingGraphicsPipelines) {
// 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);
}

View File

@ -1188,6 +1188,7 @@ namespace dxvk {
D3D9ConstantBuffer m_vsVertexBlend;
D3D9ConstantBuffer m_psFixedFunction;
D3D9ConstantBuffer m_psShared;
D3D9ConstantBuffer m_specBuffer;
Rc<DxvkBuffer> m_upBuffer;
VkDeviceSize m_upBufferOffset = 0ull;
@ -1266,6 +1267,8 @@ namespace dxvk {
VkImageLayout m_hazardLayout = VK_IMAGE_LAYOUT_GENERAL;
bool m_usingGraphicsPipelines = false;
float m_depthBiasScale = 0.0f;
uint32_t m_robustSSBOAlignment = 1;

View File

@ -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,7 @@ namespace dxvk {
uint32_t m_entryPointId;
uint32_t m_rsBlock;
uint32_t m_specUbo;
uint32_t m_mainFuncLabel;
D3D9FixedFunctionOptions m_options;
@ -1155,7 +1192,7 @@ namespace dxvk {
fogCtx.Specular = m_vs.in.COLOR[1];
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);
@ -1946,6 +1983,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 +1993,7 @@ namespace dxvk {
void D3D9FFShaderCompiler::setupPS() {
setupRenderStateInfo();
m_specUbo = SetupSpecUBO(m_module, m_bindings);
// PS Caps
m_module.enableCapability(spv::CapabilityDerivativeControl);
@ -1963,7 +2002,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 +2221,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;

View File

@ -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;

View File

@ -89,14 +89,20 @@ namespace dxvk {
class D3D9ShaderSpecConstantManager {
public:
uint32_t get(SpirvModule &module, D3D9SpecConstantId id) {
return get(module, id, 0, 32);
uint32_t get(SpirvModule &module, uint32_t specUbo, D3D9SpecConstantId id) {
return get(module, specUbo, id, 0, 32);
}
uint32_t get(SpirvModule &module, D3D9SpecConstantId id, uint32_t bitOffset, uint32_t bitCount) {
uint32_t get(SpirvModule &module, uint32_t specUbo, D3D9SpecConstantId id, uint32_t bitOffset, uint32_t bitCount) {
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);
bitCount = std::min(bitCount, layout.sizeInBits - bitOffset);
if (bitCount == 32)
@ -118,7 +124,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 = {};
};
}

View File

@ -480,6 +480,8 @@ namespace dxvk {
this->setupRenderStateInfo();
m_specUbo = SetupSpecUBO(m_module, m_bindings);
this->emitFunctionBegin(
m_vs.functionId,
m_module.defVoidType(),
@ -1036,7 +1038,7 @@ namespace dxvk {
uintType, bitfield, bitIdx, m_module.consti32(1));
}
else {
bit = m_spec.get(m_module,
bit = m_spec.get(m_module, m_specUbo,
m_programInfo.type() == DxsoProgramType::VertexShader
? SpecVertexShaderBools
: SpecPixelShaderBools,
@ -2761,7 +2763,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
// Of course it does...
uint32_t bool_t = m_module.defBoolType();
uint32_t shouldProj = m_spec.get(m_module, SpecProjectionType, samplerIdx, 1);
uint32_t shouldProj = m_spec.get(m_module, m_specUbo, SpecProjectionType, samplerIdx, 1);
shouldProj = m_module.opINotEqual(bool_t, shouldProj, m_module.constu32(0));
uint32_t bvec4_t = m_module.defVectorType(bool_t, 4);
@ -2925,7 +2927,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t fetch4 = 0;
if (m_programInfo.type() == DxsoProgramType::PixelShader && samplerType != SamplerTypeTexture3D) {
fetch4 = m_spec.get(m_module, SpecFetch4, samplerIdx, 1);
fetch4 = m_spec.get(m_module, m_specUbo, SpecFetch4, samplerIdx, 1);
uint32_t bool_t = m_module.defBoolType();
fetch4 = m_module.opINotEqual(bool_t, fetch4, m_module.constu32(0));
@ -2956,7 +2958,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
fetch4,
imageOperands);
uint32_t shouldProj = m_spec.get(m_module, SpecProjectionType, samplerIdx, 1);
uint32_t shouldProj = m_spec.get(m_module, m_specUbo, SpecProjectionType, samplerIdx, 1);
shouldProj = m_module.opINotEqual(m_module.defBoolType(), shouldProj, m_module.constu32(0));
// Depth -> .x
@ -3017,7 +3019,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
? samplerIdx + caps::MaxTexturesPS
: samplerIdx;
uint32_t isNull = m_spec.get(m_module, SpecSamplerNull, bitOffset, 1);
uint32_t isNull = m_spec.get(m_module, m_specUbo, SpecSamplerNull, bitOffset, 1);
isNull = m_module.opINotEqual(m_module.defBoolType(), isNull, m_module.constu32(0));
// Only do the check for depth comp. samplers
@ -3027,7 +3029,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t depthLabel = m_module.allocateId();
uint32_t endLabel = m_module.allocateId();
uint32_t isDepth = m_spec.get(m_module, SpecSamplerDepthMode, bitOffset, 1);
uint32_t isDepth = m_spec.get(m_module, m_specUbo, SpecSamplerDepthMode, bitOffset, 1);
isDepth = m_module.opINotEqual(m_module.defBoolType(), isDepth, m_module.constu32(0));
m_module.opSelectionMerge(endLabel, spv::SelectionControlMaskNone);
@ -3062,7 +3064,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
}};
uint32_t switchEndLabel = m_module.allocateId();
uint32_t type = m_spec.get(m_module, SpecSamplerType, samplerIdx * 2, 2);
uint32_t type = m_spec.get(m_module, m_specUbo, SpecSamplerType, samplerIdx * 2, 2);
m_module.opSelectionMerge(switchEndLabel, spv::SelectionControlMaskNone);
m_module.opSwitch(type,
@ -3326,7 +3328,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++) {
@ -3556,7 +3558,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(
@ -3707,6 +3709,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));
}
@ -3717,7 +3720,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;

View File

@ -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;