From d35ff6ca130dc0bbd9578036e234658d32d87758 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 22 Jun 2018 00:29:04 +0200 Subject: [PATCH] [dxvk] Implement pipeline layout support for dynamic descriptors --- src/dxvk/dxvk_pipelayout.cpp | 38 ++++++++++++++++++++++ src/dxvk/dxvk_pipelayout.h | 63 +++++++++++++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/src/dxvk/dxvk_pipelayout.cpp b/src/dxvk/dxvk_pipelayout.cpp index bb38fa80..8b8a4c16 100644 --- a/src/dxvk/dxvk_pipelayout.cpp +++ b/src/dxvk/dxvk_pipelayout.cpp @@ -42,6 +42,38 @@ namespace dxvk { } + void DxvkDescriptorSlotMapping::makeDescriptorsDynamic( + uint32_t uniformBuffers, + uint32_t storageBuffers) { + if (this->countDescriptors(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) <= uniformBuffers) + this->replaceDescriptors(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC); + + if (this->countDescriptors(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) <= storageBuffers) + this->replaceDescriptors(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC); + } + + + uint32_t DxvkDescriptorSlotMapping::countDescriptors( + VkDescriptorType type) const { + uint32_t count = 0; + + for (const auto& slot : m_descriptorSlots) + count += slot.type == type ? 1 : 0; + + return count; + } + + + void DxvkDescriptorSlotMapping::replaceDescriptors( + VkDescriptorType oldType, + VkDescriptorType newType) { + for (auto& slot : m_descriptorSlots) { + if (slot.type == oldType) + slot.type = newType; + } + } + + DxvkPipelineLayout::DxvkPipelineLayout( const Rc& vkd, uint32_t bindingCount, @@ -68,6 +100,12 @@ namespace dxvk { tEntries[i].descriptorType = bindingInfos[i].type; tEntries[i].offset = sizeof(DxvkDescriptorInfo) * i; tEntries[i].stride = 0; + + if (bindingInfos[i].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + || bindingInfos[i].type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) + m_dynamicSlots.push_back(i); + + m_descriptorTypes.set(bindingInfos[i].type); } // Create descriptor set layout. We do not need to diff --git a/src/dxvk/dxvk_pipelayout.h b/src/dxvk/dxvk_pipelayout.h index e89a006e..6c8f1444 100644 --- a/src/dxvk/dxvk_pipelayout.h +++ b/src/dxvk/dxvk_pipelayout.h @@ -5,7 +5,7 @@ #include "dxvk_include.h" namespace dxvk { - + /** * \brief Resource slot * @@ -91,9 +91,30 @@ namespace dxvk { uint32_t getBindingId( uint32_t slot) const; + /** + * \brief Makes static descriptors dynamic + * + * Replaces static uniform and storage buffer bindings by + * their dynamic equivalent if the number of bindings of + * the respective type lies within supported device limits. + * Using dynamic descriptor types may improve performance. + * \param [in] uniformBuffers Max number of uniform buffers + * \param [in] storageBuffers Max number of storage buffers + */ + void makeDescriptorsDynamic( + uint32_t uniformBuffers, + uint32_t storageBuffers); + private: std::vector m_descriptorSlots; + + uint32_t countDescriptors( + VkDescriptorType type) const; + + void replaceDescriptors( + VkDescriptorType oldType, + VkDescriptorType newType); }; @@ -165,16 +186,50 @@ namespace dxvk { VkDescriptorUpdateTemplateKHR descriptorTemplate() const { return m_descriptorTemplate; } + + /** + * \brief Number of dynamic bindings + * \returns Dynamic binding count + */ + uint32_t dynamicBindingCount() const { + return m_dynamicSlots.size(); + } + + /** + * \brief Returns a dynamic binding + * + * \param [in] id Dynamic binding ID + * \returns Reference to that binding + */ + const DxvkDescriptorSlot& dynamicBinding(uint32_t id) const { + return this->binding(m_dynamicSlots[id]); + } + /** + * \brief Checks for static buffer bindings + * + * Returns \c true if there is at least one + * descriptor of the static uniform or storage + * buffer type. + */ + bool hasStaticBufferBindings() const { + return m_descriptorTypes.any( + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); + } + private: Rc m_vkd; - VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE; - VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; - VkDescriptorUpdateTemplateKHR m_descriptorTemplate = VK_NULL_HANDLE; + VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE; + VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; + VkDescriptorUpdateTemplateKHR m_descriptorTemplate = VK_NULL_HANDLE; std::vector m_bindingSlots; + std::vector m_dynamicSlots; + + Flags m_descriptorTypes; };