1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-14 00:48:44 +01:00

[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 }; VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
info.stage = *stageInfo.getStageInfos(); info.stage = *stageInfo.getStageInfos();
info.layout = m_bindings->getPipelineLayout(); info.layout = m_bindings->getPipelineLayout(false);
info.basePipelineIndex = -1; info.basePipelineIndex = -1;
// Time pipeline compilation for debugging purposes // Time pipeline compilation for debugging purposes

View File

@ -84,7 +84,8 @@ namespace dxvk {
// before any draw or dispatch command is recorded. // before any draw or dispatch command is recorded.
m_flags.clr( m_flags.clr(
DxvkContextFlag::GpRenderPassBound, DxvkContextFlag::GpRenderPassBound,
DxvkContextFlag::GpXfbActive); DxvkContextFlag::GpXfbActive,
DxvkContextFlag::GpIndependentSets);
m_flags.set( m_flags.set(
DxvkContextFlag::GpDirtyFramebuffer, DxvkContextFlag::GpDirtyFramebuffer,
@ -3995,6 +3996,7 @@ namespace dxvk {
m_flags.set( m_flags.set(
DxvkContextFlag::GpRenderPassBound, DxvkContextFlag::GpRenderPassBound,
DxvkContextFlag::GpDirtyPipeline,
DxvkContextFlag::GpDirtyPipelineState, DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyVertexBuffers, DxvkContextFlag::GpDirtyVertexBuffers,
DxvkContextFlag::GpDirtyIndexBuffer, DxvkContextFlag::GpDirtyIndexBuffer,
@ -4006,7 +4008,9 @@ namespace dxvk {
DxvkContextFlag::GpDirtyDepthBounds, DxvkContextFlag::GpDirtyDepthBounds,
DxvkContextFlag::DirtyPushConstants); DxvkContextFlag::DirtyPushConstants);
m_flags.clr(DxvkContextFlag::GpRenderPassSuspended); m_flags.clr(
DxvkContextFlag::GpRenderPassSuspended,
DxvkContextFlag::GpIndependentSets);
this->renderPassBindFramebuffer( this->renderPassBindFramebuffer(
m_state.om.framebufferInfo, m_state.om.framebufferInfo,
@ -4470,6 +4474,8 @@ namespace dxvk {
bool DxvkContext::updateGraphicsPipelineState(DxvkGlobalPipelineBarrier srcBarrier) { bool DxvkContext::updateGraphicsPipelineState(DxvkGlobalPipelineBarrier srcBarrier) {
bool oldIndependentSets = m_flags.test(DxvkContextFlag::GpIndependentSets);
// Set up vertex buffer strides for active bindings // Set up vertex buffer strides for active bindings
for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) { for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) {
const uint32_t binding = m_state.gp.state.ilBindings[i].binding(); const uint32_t binding = m_state.gp.state.ilBindings[i].binding();
@ -4481,7 +4487,8 @@ namespace dxvk {
m_flags.clr(DxvkContextFlag::GpDynamicBlendConstants, m_flags.clr(DxvkContextFlag::GpDynamicBlendConstants,
DxvkContextFlag::GpDynamicDepthBias, DxvkContextFlag::GpDynamicDepthBias,
DxvkContextFlag::GpDynamicDepthBounds, DxvkContextFlag::GpDynamicDepthBounds,
DxvkContextFlag::GpDynamicStencilRef); DxvkContextFlag::GpDynamicStencilRef,
DxvkContextFlag::GpIndependentSets);
m_flags.set(m_state.gp.state.useDynamicBlendConstants() m_flags.set(m_state.gp.state.useDynamicBlendConstants()
? DxvkContextFlag::GpDynamicBlendConstants ? DxvkContextFlag::GpDynamicBlendConstants
@ -4533,8 +4540,16 @@ namespace dxvk {
if (!m_state.gp.state.rs.depthBiasEnable()) if (!m_state.gp.state.rs.depthBiasEnable())
m_cmd->cmdSetDepthBias(0.0f, 0.0f, 0.0f); 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 // Emit barrier based on pipeline properties, in order to avoid
// accidental write-after-read hazards after the render pass. // accidental write-after-read hazards after the render pass.
DxvkGlobalPipelineBarrier pipelineBarrier = m_state.gp.pipeline->getGlobalBarrier(m_state.gp.state); 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. // For 64-bit applications, using templates is slower on some drivers.
constexpr bool useDescriptorTemplates = env::is32BitHostPlatform(); 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 layoutSetMask = layout->getSetMask();
uint32_t dirtySetMask = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS uint32_t dirtySetMask = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
? m_descriptorState.getDirtyGraphicsSets() ? m_descriptorState.getDirtyGraphicsSets()
@ -4752,7 +4770,7 @@ namespace dxvk {
uint32_t firstSet = setIndex + 1 - bindCount; uint32_t firstSet = setIndex + 1 - bindCount;
m_cmd->cmdBindDescriptorSets(BindPoint, m_cmd->cmdBindDescriptorSets(BindPoint,
layout->getPipelineLayout(), layout->getPipelineLayout(independentSets),
firstSet, bindCount, &sets[firstSet], firstSet, bindCount, &sets[firstSet],
0, nullptr); 0, nullptr);
@ -5148,8 +5166,10 @@ namespace dxvk {
if (!pushConstRange.size) if (!pushConstRange.size)
return; return;
// Push constants should be compatible between complete and
// independent layouts, so always ask for the complete one
m_cmd->cmdPushConstants( m_cmd->cmdPushConstants(
bindings->getPipelineLayout(), bindings->getPipelineLayout(false),
pushConstRange.stageFlags, pushConstRange.stageFlags,
pushConstRange.offset, pushConstRange.offset,
pushConstRange.size, pushConstRange.size,

View File

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

View File

@ -164,14 +164,14 @@ namespace dxvk {
DxvkDescriptorSetMap* DxvkDescriptorPool::getSetMap( DxvkDescriptorSetMap* DxvkDescriptorPool::getSetMap(
const DxvkBindingLayoutObjects* layout) { const DxvkBindingLayoutObjects* layout) {
auto pair = m_setMaps.find(layout->getPipelineLayout()); auto pair = m_setMaps.find(layout->getPipelineLayout(false));
if (likely(pair != m_setMaps.end())) { if (likely(pair != m_setMaps.end())) {
return &pair->second; return &pair->second;
} }
auto iter = m_setMaps.emplace( auto iter = m_setMaps.emplace(
std::piecewise_construct, std::piecewise_construct,
std::tuple(layout->getPipelineLayout()), std::tuple(layout->getPipelineLayout(false)),
std::tuple()); std::tuple());
for (uint32_t i = 0; i < DxvkDescriptorSets::SetCount; i++) { 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 }; VkPipelineLibraryCreateInfoKHR libInfo = { VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR };
libInfo.libraryCount = libraries.size(); libInfo.libraryCount = libraries.size();
libInfo.pLibraries = libraries.data(); libInfo.pLibraries = libraries.data();
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo }; VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo };
info.layout = m_bindings->getPipelineLayout(true);
info.basePipelineIndex = -1;
VkPipeline pipeline = VK_NULL_HANDLE; VkPipeline pipeline = VK_NULL_HANDLE;
@ -790,7 +792,7 @@ namespace dxvk {
info.pDepthStencilState = &fsState.dsInfo; info.pDepthStencilState = &fsState.dsInfo;
info.pColorBlendState = &foState.cbInfo; info.pColorBlendState = &foState.cbInfo;
info.pDynamicState = &dyInfo; info.pDynamicState = &dyInfo;
info.layout = m_bindings->getPipelineLayout(); info.layout = m_bindings->getPipelineLayout(false);
info.basePipelineIndex = -1; info.basePipelineIndex = -1;
if (!prState.tsInfo.patchControlPoints) if (!prState.tsInfo.patchControlPoints)

View File

@ -323,29 +323,40 @@ namespace dxvk {
} }
} }
// Create pipeline layout objects
VkPushConstantRange pushConst = m_layout.getPushConstantRange(); VkPushConstantRange pushConst = m_layout.getPushConstantRange();
VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
pipelineLayoutInfo.setLayoutCount = setLayouts.size(); pipelineLayoutInfo.setLayoutCount = setLayouts.size();
pipelineLayoutInfo.pSetLayouts = setLayouts.data(); 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) { if (pushConst.stageFlags && pushConst.size) {
pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConst; pipelineLayoutInfo.pPushConstantRanges = &pushConst;
} }
if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_pipelineLayout)) // If the full set is defined, create a layout without INDEPENDENT_SET_BITS
throw DxvkError("DxvkBindingLayoutObjects: Failed to create pipeline layout"); 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() { DxvkBindingLayoutObjects::~DxvkBindingLayoutObjects() {
auto vk = m_device->vkd(); 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; return m_pushConst;
} }
/**
* \brief Queries shader stages
* \returns Shader stages
*/
VkShaderStageFlags getStages() const {
return m_stages;
}
/** /**
* \brief Queries defined descriptor set layouts * \brief Queries defined descriptor set layouts
* *
@ -433,10 +441,14 @@ namespace dxvk {
/** /**
* \brief Retrieves pipeline layout * \brief Retrieves pipeline layout
* \returns Pipeline layout *
* \param [in] independent Request INDEPENDENT_SETS_BIT
* \returns Pipeline layout handle
*/ */
VkPipelineLayout getPipelineLayout() const { VkPipelineLayout getPipelineLayout(bool independent) const {
return m_pipelineLayout; return independent
? m_independentLayout
: m_completeLayout;
} }
/** /**
@ -468,9 +480,10 @@ namespace dxvk {
DxvkDevice* m_device; DxvkDevice* m_device;
DxvkBindingLayout m_layout; 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 = { }; std::array<const DxvkBindingSetLayout*, DxvkDescriptorSets::SetCount> m_bindingObjects = { };

View File

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