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:
parent
9108f8c76c
commit
65da0da954
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 = {};
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user