From 9a6c378f3d7219961706f73dc85c8fcfa9a23e0c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 10 Aug 2022 17:58:04 +0200 Subject: [PATCH] [dxvk] Only use one descriptor set for compute shaders Simplifies things a bit and avoids redundant sets in the pipeline layout. --- src/dxvk/dxvk_pipelayout.cpp | 23 +++++++++++++++++------ src/dxvk/dxvk_pipelayout.h | 9 +++++---- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/dxvk/dxvk_pipelayout.cpp b/src/dxvk/dxvk_pipelayout.cpp index ff3b097e..67c01ca8 100644 --- a/src/dxvk/dxvk_pipelayout.cpp +++ b/src/dxvk/dxvk_pipelayout.cpp @@ -9,7 +9,10 @@ namespace dxvk { uint32_t DxvkBindingInfo::computeSetIndex() const { - if (stages & (VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT)) { + if (stages & VK_SHADER_STAGE_COMPUTE_BIT) { + // Use one single set for compute shaders + return DxvkDescriptorSets::CsAll; + } else if (stages & VK_SHADER_STAGE_FRAGMENT_BIT) { // For fragment shaders, create a separate set for UBOs if (descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) @@ -215,12 +218,15 @@ namespace dxvk { uint32_t DxvkBindingLayout::getSetMask() const { uint32_t mask = 0; - if (m_stages & (VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)) { + if (m_stages & VK_SHADER_STAGE_COMPUTE_BIT) + mask |= (1u << DxvkDescriptorSets::CsAll); + + if (m_stages & 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)) + if (m_stages & VK_SHADER_STAGE_VERTEX_BIT) mask |= (1u << DxvkDescriptorSets::VsAll); return mask; @@ -292,7 +298,12 @@ namespace dxvk { std::array setLayouts = { }; - for (uint32_t i = 0; i < DxvkDescriptorSets::SetCount; i++) { + // Use minimum number of sets for the given pipeline layout type + uint32_t setCount = m_layout.getStages() == VK_SHADER_STAGE_COMPUTE_BIT + ? DxvkDescriptorSets::CsSetCount + : DxvkDescriptorSets::SetCount; + + for (uint32_t i = 0; i < setCount; i++) { m_bindingObjects[i] = setObjects[i]; // Sets can be null for partial layouts @@ -322,7 +333,7 @@ namespace dxvk { VkPushConstantRange pushConst = m_layout.getPushConstantRange(); VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; - pipelineLayoutInfo.setLayoutCount = setLayouts.size(); + pipelineLayoutInfo.setLayoutCount = setCount; pipelineLayoutInfo.pSetLayouts = setLayouts.data(); if (pushConst.stageFlags && pushConst.size) { @@ -331,7 +342,7 @@ namespace dxvk { } // If the full set is defined, create a layout without INDEPENDENT_SET_BITS - if (m_layout.getSetMask() == (1u << DxvkDescriptorSets::SetCount) - 1) { + if (m_layout.getSetMask() == (1u << setCount) - 1) { if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_completeLayout)) throw DxvkError("DxvkBindingLayoutObjects: Failed to create pipeline layout"); } diff --git a/src/dxvk/dxvk_pipelayout.h b/src/dxvk/dxvk_pipelayout.h index f559e6c0..b7b16c35 100644 --- a/src/dxvk/dxvk_pipelayout.h +++ b/src/dxvk/dxvk_pipelayout.h @@ -19,6 +19,9 @@ namespace dxvk { static constexpr uint32_t FsBuffers = 1; static constexpr uint32_t VsAll = 2; static constexpr uint32_t SetCount = 3; + + static constexpr uint32_t CsAll = 0; + static constexpr uint32_t CsSetCount = 1; }; /** @@ -535,10 +538,8 @@ namespace dxvk { uint32_t getDirtyComputeSets() const { uint32_t result = 0; - if (m_dirtyBuffers & VK_SHADER_STAGE_COMPUTE_BIT) - result |= (1u << DxvkDescriptorSets::FsBuffers); - if (m_dirtyViews & VK_SHADER_STAGE_COMPUTE_BIT) - result |= (1u << DxvkDescriptorSets::FsViews) | (1u << DxvkDescriptorSets::FsBuffers); + if ((m_dirtyBuffers | m_dirtyViews) & VK_SHADER_STAGE_COMPUTE_BIT) + result |= (1u << DxvkDescriptorSets::CsAll); return result; }