mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-02 19:24:12 +01:00
[dxvk] Fix push constant compatibility for pipeline libraries
When linking pipelines, all pipeline libraries are required to declare the exact same set of push constants, even for stages not part of the respective libraries. This invalidates all fossilize databases.
This commit is contained in:
parent
462165da19
commit
2970645f33
@ -336,7 +336,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t SetupRenderStateBlock(SpirvModule& spvModule, uint32_t count) {
|
||||
uint32_t SetupRenderStateBlock(SpirvModule& spvModule) {
|
||||
uint32_t floatType = spvModule.defFloatType(32);
|
||||
uint32_t uintType = spvModule.defIntType(32, 0);
|
||||
uint32_t vec3Type = spvModule.defVectorType(floatType, 3);
|
||||
@ -357,7 +357,7 @@ namespace dxvk {
|
||||
floatType,
|
||||
}};
|
||||
|
||||
uint32_t rsStruct = spvModule.defStructTypeUnique(count, rsMembers.data());
|
||||
uint32_t rsStruct = spvModule.defStructTypeUnique(rsMembers.size(), rsMembers.data());
|
||||
uint32_t rsBlock = spvModule.newVar(
|
||||
spvModule.defPointerType(rsStruct, spv::StorageClassPushConstant),
|
||||
spv::StorageClassPushConstant);
|
||||
@ -369,9 +369,6 @@ namespace dxvk {
|
||||
|
||||
uint32_t memberIdx = 0;
|
||||
auto SetMemberName = [&](const char* name, uint32_t offset) {
|
||||
if (memberIdx >= count)
|
||||
return;
|
||||
|
||||
spvModule.setDebugMemberName (rsStruct, memberIdx, name);
|
||||
spvModule.memberDecorateOffset (rsStruct, memberIdx, offset);
|
||||
memberIdx++;
|
||||
@ -781,8 +778,6 @@ namespace dxvk {
|
||||
uint32_t m_inputMask = 0u;
|
||||
uint32_t m_outputMask = 0u;
|
||||
uint32_t m_flatShadingMask = 0u;
|
||||
uint32_t m_pushConstOffset = 0u;
|
||||
uint32_t m_pushConstSize = 0u;
|
||||
|
||||
DxsoProgramType m_programType;
|
||||
D3D9FFShaderKeyVS m_vsKey;
|
||||
@ -892,8 +887,8 @@ namespace dxvk {
|
||||
info.inputMask = m_inputMask;
|
||||
info.outputMask = m_outputMask;
|
||||
info.flatShadingInputs = m_flatShadingMask;
|
||||
info.pushConstOffset = m_pushConstOffset;
|
||||
info.pushConstSize = m_pushConstSize;
|
||||
info.pushConstStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
info.pushConstSize = sizeof(D3D9RenderStateInfo);
|
||||
|
||||
return new DxvkShader(info, m_module.compile());
|
||||
}
|
||||
@ -1384,20 +1379,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
void D3D9FFShaderCompiler::setupRenderStateInfo() {
|
||||
uint32_t count;
|
||||
|
||||
if (m_programType == DxsoProgramType::PixelShader) {
|
||||
m_pushConstOffset = 0;
|
||||
m_pushConstSize = offsetof(D3D9RenderStateInfo, pointSize);
|
||||
count = 5;
|
||||
}
|
||||
else {
|
||||
m_pushConstOffset = offsetof(D3D9RenderStateInfo, pointSize);
|
||||
m_pushConstSize = sizeof(float) * 6;
|
||||
count = 11;
|
||||
}
|
||||
|
||||
m_rsBlock = SetupRenderStateBlock(m_module, count);
|
||||
m_rsBlock = SetupRenderStateBlock(m_module);
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,7 +59,7 @@ namespace dxvk {
|
||||
void DoFixedFunctionAlphaTest(SpirvModule& spvModule, const D3D9AlphaTestContext& ctx);
|
||||
|
||||
// Returns a render state block
|
||||
uint32_t SetupRenderStateBlock(SpirvModule& spvModule, uint32_t count);
|
||||
uint32_t SetupRenderStateBlock(SpirvModule& spvModule);
|
||||
|
||||
struct D3D9PointSizeInfoVS {
|
||||
uint32_t defaultValue;
|
||||
|
@ -134,7 +134,7 @@ namespace dxvk {
|
||||
info.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
info.bindingCount = bindings.size();
|
||||
info.bindings = bindings.data();
|
||||
info.pushConstOffset = 0;
|
||||
info.pushConstStages = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
info.pushConstSize = sizeof(VkExtent2D);
|
||||
|
||||
return new DxvkShader(info, std::move(code));
|
||||
|
@ -257,14 +257,13 @@ namespace dxvk {
|
||||
info.outputMask = m_outputMask;
|
||||
info.uniformSize = m_immConstData.size();
|
||||
info.uniformData = m_immConstData.data();
|
||||
info.pushConstStages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
info.pushConstSize = sizeof(DxbcPushConstants);
|
||||
info.outputTopology = m_outputTopology;
|
||||
|
||||
if (m_programInfo.type() == DxbcProgramType::HullShader)
|
||||
info.patchVertexCount = m_hs.vertexCountIn;
|
||||
|
||||
if (m_programInfo.type() == DxbcProgramType::PixelShader && m_ps.pushConstantId)
|
||||
info.pushConstSize = sizeof(DxbcPushConstants);
|
||||
|
||||
if (m_moduleInfo.xfb) {
|
||||
info.xfbRasterizedStream = m_moduleInfo.xfb->rasterizedStream;
|
||||
|
||||
|
@ -228,8 +228,8 @@ namespace dxvk {
|
||||
info.bindings = m_bindings.data();
|
||||
info.inputMask = m_inputMask;
|
||||
info.outputMask = m_outputMask;
|
||||
info.pushConstOffset = m_pushConstOffset;
|
||||
info.pushConstSize = m_pushConstSize;
|
||||
info.pushConstStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
info.pushConstSize = sizeof(D3D9RenderStateInfo);
|
||||
|
||||
if (m_programInfo.type() == DxsoProgramTypes::PixelShader)
|
||||
info.flatShadingInputs = m_ps.flatShadingMask;
|
||||
@ -3561,30 +3561,7 @@ void DxsoCompiler::emitControlFlowGenericLoop(
|
||||
|
||||
|
||||
void DxsoCompiler::setupRenderStateInfo() {
|
||||
uint32_t count;
|
||||
|
||||
// Only need alpha ref for PS 3.
|
||||
// No FF fog component.
|
||||
if (m_programInfo.type() == DxsoProgramType::PixelShader) {
|
||||
if (m_programInfo.majorVersion() == 3) {
|
||||
m_pushConstOffset = offsetof(D3D9RenderStateInfo, alphaRef);
|
||||
m_pushConstSize = sizeof(float);
|
||||
}
|
||||
else {
|
||||
m_pushConstOffset = 0;
|
||||
m_pushConstSize = offsetof(D3D9RenderStateInfo, pointSize);
|
||||
}
|
||||
|
||||
count = 5;
|
||||
}
|
||||
else {
|
||||
m_pushConstOffset = offsetof(D3D9RenderStateInfo, pointSize);
|
||||
// Point scale never triggers on programmable
|
||||
m_pushConstSize = sizeof(float) * 3;
|
||||
count = 8;
|
||||
}
|
||||
|
||||
m_rsBlock = SetupRenderStateBlock(m_module, count);
|
||||
m_rsBlock = SetupRenderStateBlock(m_module);
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,8 +344,6 @@ namespace dxvk {
|
||||
// covers vertex input and fragment output.
|
||||
uint32_t m_inputMask = 0u;
|
||||
uint32_t m_outputMask = 0u;
|
||||
uint32_t m_pushConstOffset = 0u;
|
||||
uint32_t m_pushConstSize = 0u;
|
||||
|
||||
///////////////////////////////////
|
||||
// Shader-specific data structures
|
||||
|
@ -4984,7 +4984,7 @@ namespace dxvk {
|
||||
// Mark compute resources and push constants as dirty
|
||||
m_descriptorState.dirtyStages(VK_SHADER_STAGE_COMPUTE_BIT);
|
||||
|
||||
if (newPipeline->getBindings()->layout().getPushConstantRange().size)
|
||||
if (newPipeline->getBindings()->layout().getPushConstantRange(true).size)
|
||||
m_flags.set(DxvkContextFlag::DirtyPushConstants);
|
||||
|
||||
m_flags.clr(DxvkContextFlag::CpDirtyPipelineState);
|
||||
@ -5058,7 +5058,7 @@ namespace dxvk {
|
||||
|
||||
m_descriptorState.dirtyStages(VK_SHADER_STAGE_ALL_GRAPHICS);
|
||||
|
||||
if (newPipeline->getBindings()->layout().getPushConstantRange().size)
|
||||
if (newPipeline->getBindings()->layout().getPushConstantRange(true).size)
|
||||
m_flags.set(DxvkContextFlag::DirtyPushConstants);
|
||||
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);
|
||||
@ -5925,16 +5925,19 @@ namespace dxvk {
|
||||
auto bindings = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||
? m_state.gp.pipeline->getBindings()
|
||||
: m_state.cp.pipeline->getBindings();
|
||||
|
||||
VkPushConstantRange pushConstRange = bindings->layout().getPushConstantRange();
|
||||
|
||||
// Optimized pipelines may have push constants trimmed, so look up
|
||||
// the exact layout used for the currently bound pipeline.
|
||||
bool independentSets = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||
&& m_flags.test(DxvkContextFlag::GpIndependentSets);
|
||||
|
||||
VkPushConstantRange pushConstRange = bindings->layout().getPushConstantRange(independentSets);
|
||||
|
||||
if (!pushConstRange.size)
|
||||
return;
|
||||
|
||||
// Push constants should be compatible between complete and
|
||||
// independent layouts, so always ask for the complete one
|
||||
m_cmd->cmdPushConstants(
|
||||
bindings->getPipelineLayout(false),
|
||||
bindings->getPipelineLayout(independentSets),
|
||||
pushConstRange.stageFlags,
|
||||
pushConstRange.offset,
|
||||
pushConstRange.size,
|
||||
|
@ -205,7 +205,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkBindingLayout::DxvkBindingLayout(VkShaderStageFlags stages)
|
||||
: m_pushConst { 0, 0, 0 }, m_stages(stages) {
|
||||
: m_pushConst { 0, 0, 0 }, m_pushConstStages(0), m_stages(stages) {
|
||||
|
||||
}
|
||||
|
||||
@ -249,11 +249,17 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkBindingLayout::addPushConstantStage(VkShaderStageFlagBits stage) {
|
||||
m_pushConstStages |= stage;
|
||||
}
|
||||
|
||||
|
||||
void DxvkBindingLayout::merge(const DxvkBindingLayout& layout) {
|
||||
for (uint32_t i = 0; i < layout.m_bindings.size(); i++)
|
||||
m_bindings[i].merge(layout.m_bindings[i]);
|
||||
|
||||
addPushConstantRange(layout.m_pushConst);
|
||||
m_pushConstStages |= layout.m_pushConstStages;
|
||||
}
|
||||
|
||||
|
||||
@ -266,6 +272,9 @@ namespace dxvk {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_pushConstStages != other.m_pushConstStages)
|
||||
return false;
|
||||
|
||||
if (m_pushConst.stageFlags != other.m_pushConst.stageFlags
|
||||
|| m_pushConst.offset != other.m_pushConst.offset
|
||||
|| m_pushConst.size != other.m_pushConst.size)
|
||||
@ -282,6 +291,7 @@ namespace dxvk {
|
||||
for (uint32_t i = 0; i < m_bindings.size(); i++)
|
||||
hash.add(m_bindings[i].hash());
|
||||
|
||||
hash.add(m_pushConstStages);
|
||||
hash.add(m_pushConst.stageFlags);
|
||||
hash.add(m_pushConst.offset);
|
||||
hash.add(m_pushConst.size);
|
||||
@ -334,15 +344,16 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
// Create pipeline layout objects
|
||||
VkPushConstantRange pushConst = m_layout.getPushConstantRange();
|
||||
VkPushConstantRange pushConstComplete = m_layout.getPushConstantRange(false);
|
||||
VkPushConstantRange pushConstIndependent = m_layout.getPushConstantRange(true);
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
pipelineLayoutInfo.setLayoutCount = setCount;
|
||||
pipelineLayoutInfo.pSetLayouts = setLayouts.data();
|
||||
|
||||
if (pushConst.stageFlags && pushConst.size) {
|
||||
if (pushConstComplete.stageFlags && pushConstComplete.size) {
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||
pipelineLayoutInfo.pPushConstantRanges = &pushConst;
|
||||
pipelineLayoutInfo.pPushConstantRanges = &pushConstComplete;
|
||||
}
|
||||
|
||||
// If the full set is defined, create a layout without INDEPENDENT_SET_BITS
|
||||
@ -356,6 +367,11 @@ namespace dxvk {
|
||||
if (m_device->canUseGraphicsPipelineLibrary() && (m_layout.getStages() & VK_SHADER_STAGE_ALL_GRAPHICS)) {
|
||||
pipelineLayoutInfo.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
|
||||
|
||||
if (pushConstIndependent.stageFlags && pushConstIndependent.size) {
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||
pipelineLayoutInfo.pPushConstantRanges = &pushConstIndependent;
|
||||
}
|
||||
|
||||
if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_independentLayout))
|
||||
throw DxvkError("DxvkBindingLayoutObjects: Failed to create pipeline layout");
|
||||
}
|
||||
|
@ -292,8 +292,19 @@ namespace dxvk {
|
||||
* \brief Retrieves push constant range
|
||||
* \returns Push constant range
|
||||
*/
|
||||
VkPushConstantRange getPushConstantRange() const {
|
||||
return m_pushConst;
|
||||
VkPushConstantRange getPushConstantRange(bool independent) const {
|
||||
VkPushConstantRange result = m_pushConst;
|
||||
|
||||
if (!independent) {
|
||||
result.stageFlags &= m_pushConstStages;
|
||||
|
||||
if (!result.stageFlags) {
|
||||
result.offset = 0;
|
||||
result.size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -324,6 +335,12 @@ namespace dxvk {
|
||||
*/
|
||||
void addPushConstantRange(VkPushConstantRange range);
|
||||
|
||||
/**
|
||||
* \brief Adds a stage that actively uses push constants
|
||||
* \param [in] stage Shader stage
|
||||
*/
|
||||
void addPushConstantStage(VkShaderStageFlagBits stage);
|
||||
|
||||
/**
|
||||
* \brief Merges binding layouts
|
||||
*
|
||||
@ -353,6 +370,7 @@ namespace dxvk {
|
||||
|
||||
std::array<DxvkBindingList, DxvkDescriptorSets::SetCount> m_bindings;
|
||||
VkPushConstantRange m_pushConst;
|
||||
VkShaderStageFlags m_pushConstStages;
|
||||
VkShaderStageFlags m_stages;
|
||||
|
||||
};
|
||||
|
@ -59,8 +59,8 @@ namespace dxvk {
|
||||
|
||||
if (info.pushConstSize) {
|
||||
VkPushConstantRange pushConst;
|
||||
pushConst.stageFlags = info.stage;
|
||||
pushConst.offset = info.pushConstOffset;
|
||||
pushConst.stageFlags = info.pushConstStages;
|
||||
pushConst.offset = 0;
|
||||
pushConst.size = info.pushConstSize;
|
||||
|
||||
m_bindings.addPushConstantRange(pushConst);
|
||||
@ -75,6 +75,8 @@ namespace dxvk {
|
||||
|
||||
// Run an analysis pass over the SPIR-V code to gather some
|
||||
// info that we may need during pipeline compilation.
|
||||
bool usesPushConstants = false;
|
||||
|
||||
std::vector<BindingOffsets> bindingOffsets;
|
||||
std::vector<uint32_t> varIds;
|
||||
std::vector<uint32_t> sampleMaskIds;
|
||||
@ -154,6 +156,9 @@ namespace dxvk {
|
||||
if (std::find(sampleMaskIds.begin(), sampleMaskIds.end(), ins.arg(2)) != sampleMaskIds.end())
|
||||
m_flags.set(DxvkShaderFlag::ExportsSampleMask);
|
||||
}
|
||||
|
||||
if (ins.arg(3) == spv::StorageClassPushConstant)
|
||||
usesPushConstants = true;
|
||||
}
|
||||
|
||||
// Ignore the actual shader code, there's nothing interesting for us in there.
|
||||
@ -169,6 +174,11 @@ namespace dxvk {
|
||||
m_bindingOffsets.push_back(info);
|
||||
}
|
||||
|
||||
// Set flag for stages that actually use push constants
|
||||
// so that they can be trimmed for optimized pipelines.
|
||||
if (usesPushConstants)
|
||||
m_bindings.addPushConstantStage(info.stage);
|
||||
|
||||
// Don't set pipeline library flag if the shader
|
||||
// doesn't actually support pipeline libraries
|
||||
m_needsLibraryCompile = canUsePipelineLibrary(true);
|
||||
|
@ -52,7 +52,7 @@ namespace dxvk {
|
||||
/// Flat shading input mask
|
||||
uint32_t flatShadingInputs = 0;
|
||||
/// Push constant range
|
||||
uint32_t pushConstOffset = 0;
|
||||
VkShaderStageFlags pushConstStages = 0;
|
||||
uint32_t pushConstSize = 0;
|
||||
/// Uniform buffer data
|
||||
uint32_t uniformSize = 0;
|
||||
|
@ -329,6 +329,8 @@ namespace dxvk {
|
||||
|
||||
DxvkShaderCreateInfo vsInfo;
|
||||
vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
vsInfo.pushConstStages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
vsInfo.pushConstSize = sizeof(PresenterArgs);
|
||||
vsInfo.outputMask = 0x1;
|
||||
m_vs = new DxvkShader(vsInfo, std::move(vsCode));
|
||||
|
||||
@ -336,6 +338,7 @@ namespace dxvk {
|
||||
fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
fsInfo.bindingCount = fsBindings.size();
|
||||
fsInfo.bindings = fsBindings.data();
|
||||
fsInfo.pushConstStages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
fsInfo.pushConstSize = sizeof(PresenterArgs);
|
||||
fsInfo.inputMask = 0x1;
|
||||
fsInfo.outputMask = 0x1;
|
||||
|
@ -183,14 +183,17 @@ namespace dxvk::hud {
|
||||
vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
vsInfo.bindingCount = vsBindings.size();
|
||||
vsInfo.bindings = vsBindings.data();
|
||||
vsInfo.outputMask = 0x3;
|
||||
vsInfo.pushConstStages = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
vsInfo.pushConstSize = sizeof(HudTextPushConstants);
|
||||
vsInfo.outputMask = 0x3;
|
||||
result.vert = new DxvkShader(vsInfo, std::move(vsCode));
|
||||
|
||||
DxvkShaderCreateInfo fsInfo;
|
||||
fsInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
fsInfo.bindingCount = fsBindings.size();
|
||||
fsInfo.bindings = fsBindings.data();
|
||||
fsInfo.pushConstStages = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
fsInfo.pushConstSize = sizeof(HudTextPushConstants);
|
||||
fsInfo.inputMask = 0x3;
|
||||
fsInfo.outputMask = 0x1;
|
||||
result.frag = new DxvkShader(fsInfo, std::move(fsCode));
|
||||
@ -212,6 +215,7 @@ namespace dxvk::hud {
|
||||
DxvkShaderCreateInfo vsInfo;
|
||||
vsInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
vsInfo.outputMask = 0x1;
|
||||
vsInfo.pushConstStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
vsInfo.pushConstSize = sizeof(HudGraphPushConstants);
|
||||
result.vert = new DxvkShader(vsInfo, std::move(vsCode));
|
||||
|
||||
@ -221,6 +225,7 @@ namespace dxvk::hud {
|
||||
fsInfo.bindings = fsBindings.data();
|
||||
fsInfo.inputMask = 0x1;
|
||||
fsInfo.outputMask = 0x1;
|
||||
fsInfo.pushConstStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
fsInfo.pushConstSize = sizeof(HudGraphPushConstants);
|
||||
result.frag = new DxvkShader(fsInfo, std::move(fsCode));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user