diff --git a/src/dxvk/dxvk_pipelayout.cpp b/src/dxvk/dxvk_pipelayout.cpp index bb60cde2e..407366358 100644 --- a/src/dxvk/dxvk_pipelayout.cpp +++ b/src/dxvk/dxvk_pipelayout.cpp @@ -208,8 +208,8 @@ namespace dxvk { } - DxvkBindingLayout::DxvkBindingLayout() - : m_pushConst { 0, 0, 0 } { + DxvkBindingLayout::DxvkBindingLayout(VkShaderStageFlags stages) + : m_pushConst { 0, 0, 0 }, m_stages(stages) { } @@ -219,6 +219,21 @@ namespace dxvk { } + uint32_t DxvkBindingLayout::getSetMask() const { + uint32_t mask = 0; + + if (m_stages & (VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)) { + mask |= (1u << DxvkDescriptorSets::FsViews) + | (1u << DxvkDescriptorSets::FsBuffers); + } + + if (m_stages & (VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT)) + mask |= (1u << DxvkDescriptorSets::VsAll); + + return mask; + } + + void DxvkBindingLayout::addBinding(const DxvkBindingInfo& binding) { uint32_t set = binding.computeSetIndex(); m_bindings[set].addBinding(binding); @@ -244,6 +259,9 @@ namespace dxvk { bool DxvkBindingLayout::eq(const DxvkBindingLayout& other) const { + if (m_stages != other.m_stages) + return false; + for (uint32_t i = 0; i < m_bindings.size(); i++) { if (!m_bindings[i].eq(other.m_bindings[i])) return false; @@ -260,6 +278,7 @@ namespace dxvk { size_t DxvkBindingLayout::hash() const { DxvkHashState hash; + hash.add(m_stages); for (uint32_t i = 0; i < m_bindings.size(); i++) hash.add(m_bindings[i].hash()); @@ -278,26 +297,30 @@ namespace dxvk { : m_device(device), m_layout(layout) { auto vk = m_device->vkd(); - std::array setLayouts; + std::array setLayouts = { }; for (uint32_t i = 0; i < DxvkDescriptorSets::SetCount; i++) { m_bindingObjects[i] = setObjects[i]; - setLayouts[i] = setObjects[i]->getSetLayout(); - uint32_t bindingCount = m_layout.getBindingCount(i); + // Sets can be null for partial layouts + if (setObjects[i]) { + setLayouts[i] = setObjects[i]->getSetLayout(); - for (uint32_t j = 0; j < bindingCount; j++) { - const DxvkBindingInfo& binding = m_layout.getBinding(i, j); + uint32_t bindingCount = m_layout.getBindingCount(i); - DxvkBindingMapping mapping; - mapping.set = i; - mapping.binding = j; + for (uint32_t j = 0; j < bindingCount; j++) { + const DxvkBindingInfo& binding = m_layout.getBinding(i, j); - m_mapping.insert({ binding.resourceBinding, mapping }); + DxvkBindingMapping mapping; + mapping.set = i; + mapping.binding = j; + + m_mapping.insert({ binding.resourceBinding, mapping }); + } + + if (bindingCount) + m_setMask |= 1u << i; } - - if (bindingCount) - m_setMask |= 1u << i; } VkPushConstantRange pushConst = m_layout.getPushConstantRange(); @@ -306,6 +329,9 @@ namespace dxvk { 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; diff --git a/src/dxvk/dxvk_pipelayout.h b/src/dxvk/dxvk_pipelayout.h index 46717bc9d..ae4ad78f9 100644 --- a/src/dxvk/dxvk_pipelayout.h +++ b/src/dxvk/dxvk_pipelayout.h @@ -261,7 +261,7 @@ namespace dxvk { public: - DxvkBindingLayout(); + DxvkBindingLayout(VkShaderStageFlags stages); ~DxvkBindingLayout(); /** @@ -304,6 +304,14 @@ namespace dxvk { return m_pushConst; } + /** + * \brief Queries defined descriptor set layouts + * + * Any set layout not included in this must be null. + * \returns Bit mask of defined descriptor sets + */ + uint32_t getSetMask() const; + /** * \brief Adds a binding to the layout * \param [in] binding Binding info @@ -345,6 +353,7 @@ namespace dxvk { std::array m_bindings; VkPushConstantRange m_pushConst; + VkShaderStageFlags m_stages; }; diff --git a/src/dxvk/dxvk_pipemanager.cpp b/src/dxvk/dxvk_pipemanager.cpp index 5c58cc134..3e4d92b82 100644 --- a/src/dxvk/dxvk_pipemanager.cpp +++ b/src/dxvk/dxvk_pipemanager.cpp @@ -52,7 +52,7 @@ namespace dxvk { if (pair != m_graphicsPipelines.end()) return &pair->second; - DxvkBindingLayout mergedLayout; + DxvkBindingLayout mergedLayout(VK_SHADER_STAGE_ALL_GRAPHICS); mergedLayout.merge(shaders.vs->getBindings()); if (shaders.tcs != nullptr) @@ -157,9 +157,12 @@ namespace dxvk { return &pair->second; std::array setLayouts = { }; + uint32_t setMask = layout.getSetMask(); - for (uint32_t i = 0; i < setLayouts.size(); i++) - setLayouts[i] = createDescriptorSetLayout(layout.getBindingList(i)); + for (uint32_t i = 0; i < setLayouts.size(); i++) { + if (setMask & (1u << i)) + setLayouts[i] = createDescriptorSetLayout(layout.getBindingList(i)); + } auto iter = m_pipelineLayouts.emplace( std::piecewise_construct, diff --git a/src/dxvk/dxvk_shader.cpp b/src/dxvk/dxvk_shader.cpp index f8c5fdce9..a3ed01d73 100644 --- a/src/dxvk/dxvk_shader.cpp +++ b/src/dxvk/dxvk_shader.cpp @@ -63,7 +63,7 @@ namespace dxvk { DxvkShader::DxvkShader( const DxvkShaderCreateInfo& info, SpirvCodeBuffer&& spirv) - : m_info(info), m_code(spirv) { + : m_info(info), m_code(spirv), m_bindings(info.stage) { m_info.uniformData = nullptr; m_info.bindings = nullptr;