[dxvk] Create full pipeline layout with INDEPENDENT_SETS_BIT

And use it to link pipelines as well as descriptor binding.
Should fix issues related to descriptors.
This commit is contained in:
Philip Rebohle 2022-07-07 10:38:39 +02:00
parent b51d7a3cc0
commit 5e1569593a
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
8 changed files with 74 additions and 27 deletions

View File

@ -119,7 +119,7 @@ namespace dxvk {
VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
info.stage = *stageInfo.getStageInfos();
info.layout = m_bindings->getPipelineLayout();
info.layout = m_bindings->getPipelineLayout(false);
info.basePipelineIndex = -1;
// Time pipeline compilation for debugging purposes

View File

@ -84,7 +84,8 @@ namespace dxvk {
// before any draw or dispatch command is recorded.
m_flags.clr(
DxvkContextFlag::GpRenderPassBound,
DxvkContextFlag::GpXfbActive);
DxvkContextFlag::GpXfbActive,
DxvkContextFlag::GpIndependentSets);
m_flags.set(
DxvkContextFlag::GpDirtyFramebuffer,
@ -3995,6 +3996,7 @@ namespace dxvk {
m_flags.set(
DxvkContextFlag::GpRenderPassBound,
DxvkContextFlag::GpDirtyPipeline,
DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyVertexBuffers,
DxvkContextFlag::GpDirtyIndexBuffer,
@ -4006,7 +4008,9 @@ namespace dxvk {
DxvkContextFlag::GpDirtyDepthBounds,
DxvkContextFlag::DirtyPushConstants);
m_flags.clr(DxvkContextFlag::GpRenderPassSuspended);
m_flags.clr(
DxvkContextFlag::GpRenderPassSuspended,
DxvkContextFlag::GpIndependentSets);
this->renderPassBindFramebuffer(
m_state.om.framebufferInfo,
@ -4470,18 +4474,21 @@ namespace dxvk {
bool DxvkContext::updateGraphicsPipelineState(DxvkGlobalPipelineBarrier srcBarrier) {
bool oldIndependentSets = m_flags.test(DxvkContextFlag::GpIndependentSets);
// Set up vertex buffer strides for active bindings
for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) {
const uint32_t binding = m_state.gp.state.ilBindings[i].binding();
m_state.gp.state.ilBindings[i].setStride(m_state.vi.vertexStrides[binding]);
}
// Check which dynamic states need to be active. States that
// are not dynamic will be invalidated in the command buffer.
m_flags.clr(DxvkContextFlag::GpDynamicBlendConstants,
DxvkContextFlag::GpDynamicDepthBias,
DxvkContextFlag::GpDynamicDepthBounds,
DxvkContextFlag::GpDynamicStencilRef);
DxvkContextFlag::GpDynamicStencilRef,
DxvkContextFlag::GpIndependentSets);
m_flags.set(m_state.gp.state.useDynamicBlendConstants()
? DxvkContextFlag::GpDynamicBlendConstants
@ -4533,8 +4540,16 @@ namespace dxvk {
if (!m_state.gp.state.rs.depthBiasEnable())
m_cmd->cmdSetDepthBias(0.0f, 0.0f, 0.0f);
m_flags.set(DxvkContextFlag::GpIndependentSets);
}
// If necessary, dirty descriptor sets due to layout incompatibilities
bool newIndependentSets = m_flags.test(DxvkContextFlag::GpIndependentSets);
if (newIndependentSets != oldIndependentSets)
m_descriptorState.dirtyStages(VK_SHADER_STAGE_ALL_GRAPHICS);
// Emit barrier based on pipeline properties, in order to avoid
// accidental write-after-read hazards after the render pass.
DxvkGlobalPipelineBarrier pipelineBarrier = m_state.gp.pipeline->getGlobalBarrier(m_state.gp.state);
@ -4570,6 +4585,9 @@ namespace dxvk {
// For 64-bit applications, using templates is slower on some drivers.
constexpr bool useDescriptorTemplates = env::is32BitHostPlatform();
bool independentSets = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
&& m_flags.test(DxvkContextFlag::GpIndependentSets);
uint32_t layoutSetMask = layout->getSetMask();
uint32_t dirtySetMask = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
? m_descriptorState.getDirtyGraphicsSets()
@ -4752,7 +4770,7 @@ namespace dxvk {
uint32_t firstSet = setIndex + 1 - bindCount;
m_cmd->cmdBindDescriptorSets(BindPoint,
layout->getPipelineLayout(),
layout->getPipelineLayout(independentSets),
firstSet, bindCount, &sets[firstSet],
0, nullptr);
@ -5147,9 +5165,11 @@ namespace dxvk {
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(),
bindings->getPipelineLayout(false),
pushConstRange.stageFlags,
pushConstRange.offset,
pushConstRange.size,

View File

@ -39,6 +39,7 @@ namespace dxvk {
GpDynamicDepthBias, ///< Depth bias is dynamic
GpDynamicDepthBounds, ///< Depth bounds are dynamic
GpDynamicStencilRef, ///< Stencil reference is dynamic
GpIndependentSets, ///< Graphics pipeline layout was created with independent sets
CpDirtyPipeline, ///< Compute pipeline binding are out of date
CpDirtyPipelineState, ///< Compute pipeline needs to be recompiled

View File

@ -164,14 +164,14 @@ namespace dxvk {
DxvkDescriptorSetMap* DxvkDescriptorPool::getSetMap(
const DxvkBindingLayoutObjects* layout) {
auto pair = m_setMaps.find(layout->getPipelineLayout());
auto pair = m_setMaps.find(layout->getPipelineLayout(false));
if (likely(pair != m_setMaps.end())) {
return &pair->second;
}
auto iter = m_setMaps.emplace(
std::piecewise_construct,
std::tuple(layout->getPipelineLayout()),
std::tuple(layout->getPipelineLayout(false)),
std::tuple());
for (uint32_t i = 0; i < DxvkDescriptorSets::SetCount; i++) {

View File

@ -698,10 +698,12 @@ namespace dxvk {
}};
VkPipelineLibraryCreateInfoKHR libInfo = { VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR };
libInfo.libraryCount = libraries.size();
libInfo.pLibraries = libraries.data();
libInfo.libraryCount = libraries.size();
libInfo.pLibraries = libraries.data();
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo };
info.layout = m_bindings->getPipelineLayout(true);
info.basePipelineIndex = -1;
VkPipeline pipeline = VK_NULL_HANDLE;
@ -790,7 +792,7 @@ namespace dxvk {
info.pDepthStencilState = &fsState.dsInfo;
info.pColorBlendState = &foState.cbInfo;
info.pDynamicState = &dyInfo;
info.layout = m_bindings->getPipelineLayout();
info.layout = m_bindings->getPipelineLayout(false);
info.basePipelineIndex = -1;
if (!prState.tsInfo.patchControlPoints)

View File

@ -323,29 +323,40 @@ namespace dxvk {
}
}
// Create pipeline layout objects
VkPushConstantRange pushConst = m_layout.getPushConstantRange();
VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
pipelineLayoutInfo.setLayoutCount = setLayouts.size();
pipelineLayoutInfo.pSetLayouts = setLayouts.data();
if (m_layout.getSetMask() != (1u << DxvkDescriptorSets::SetCount) - 1)
pipelineLayoutInfo.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
if (pushConst.stageFlags && pushConst.size) {
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConst;
}
if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_pipelineLayout))
throw DxvkError("DxvkBindingLayoutObjects: Failed to create pipeline layout");
// If the full set is defined, create a layout without INDEPENDENT_SET_BITS
if (m_layout.getSetMask() == (1u << DxvkDescriptorSets::SetCount) - 1) {
if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_completeLayout))
throw DxvkError("DxvkBindingLayoutObjects: Failed to create pipeline layout");
}
// If graphics pipeline libraries are supported, also create a variand with the
// bit. It will be used to create shader-based libraries and link pipelines.
if (m_device->canUseGraphicsPipelineLibrary() && (m_layout.getStages() & VK_SHADER_STAGE_ALL_GRAPHICS)) {
pipelineLayoutInfo.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_independentLayout))
throw DxvkError("DxvkBindingLayoutObjects: Failed to create pipeline layout");
}
}
DxvkBindingLayoutObjects::~DxvkBindingLayoutObjects() {
auto vk = m_device->vkd();
vk->vkDestroyPipelineLayout(vk->device(), m_pipelineLayout, nullptr);
vk->vkDestroyPipelineLayout(vk->device(), m_completeLayout, nullptr);
vk->vkDestroyPipelineLayout(vk->device(), m_independentLayout, nullptr);
}

View File

@ -304,6 +304,14 @@ namespace dxvk {
return m_pushConst;
}
/**
* \brief Queries shader stages
* \returns Shader stages
*/
VkShaderStageFlags getStages() const {
return m_stages;
}
/**
* \brief Queries defined descriptor set layouts
*
@ -433,10 +441,14 @@ namespace dxvk {
/**
* \brief Retrieves pipeline layout
* \returns Pipeline layout
*
* \param [in] independent Request INDEPENDENT_SETS_BIT
* \returns Pipeline layout handle
*/
VkPipelineLayout getPipelineLayout() const {
return m_pipelineLayout;
VkPipelineLayout getPipelineLayout(bool independent) const {
return independent
? m_independentLayout
: m_completeLayout;
}
/**
@ -468,9 +480,10 @@ namespace dxvk {
DxvkDevice* m_device;
DxvkBindingLayout m_layout;
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
VkPipelineLayout m_completeLayout = VK_NULL_HANDLE;
VkPipelineLayout m_independentLayout = VK_NULL_HANDLE;
uint32_t m_setMask = 0;
uint32_t m_setMask = 0;
std::array<const DxvkBindingSetLayout*, DxvkDescriptorSets::SetCount> m_bindingObjects = { };

View File

@ -547,7 +547,7 @@ namespace dxvk {
info.pViewportState = &vpInfo;
info.pRasterizationState = &rsInfo;
info.pDynamicState = &dyInfo;
info.layout = m_layout->getPipelineLayout();
info.layout = m_layout->getPipelineLayout(true);
info.basePipelineIndex = -1;
VkPipeline pipeline = VK_NULL_HANDLE;
@ -625,7 +625,7 @@ namespace dxvk {
info.pStages = stageInfo.getStageInfos();
info.pDepthStencilState = &dsInfo;
info.pDynamicState = &dyInfo;
info.layout = m_layout->getPipelineLayout();
info.layout = m_layout->getPipelineLayout(true);
info.basePipelineIndex = -1;
if (m_shader && m_shader->flags().test(DxvkShaderFlag::HasSampleRateShading))
@ -650,7 +650,7 @@ namespace dxvk {
// Compile the compute pipeline as normal
VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
info.stage = *stageInfo.getStageInfos();
info.layout = m_layout->getPipelineLayout();
info.layout = m_layout->getPipelineLayout(false);
info.basePipelineIndex = -1;
VkPipeline pipeline = VK_NULL_HANDLE;