diff --git a/src/dxvk/dxvk_compute.cpp b/src/dxvk/dxvk_compute.cpp index 4e060908..7dba4f99 100644 --- a/src/dxvk/dxvk_compute.cpp +++ b/src/dxvk/dxvk_compute.cpp @@ -12,9 +12,10 @@ namespace dxvk { DxvkComputePipeline::DxvkComputePipeline( DxvkPipelineManager* pipeMgr, - DxvkComputePipelineShaders shaders) + DxvkComputePipelineShaders shaders, + DxvkBindingLayoutObjects* layout) : m_vkd(pipeMgr->m_device->vkd()), m_pipeMgr(pipeMgr), - m_shaders(std::move(shaders)) { + m_shaders(std::move(shaders)), m_bindings(layout) { m_shaders.cs->defineResourceSlots(m_slotMapping); m_slotMapping.makeDescriptorsDynamic( diff --git a/src/dxvk/dxvk_compute.h b/src/dxvk/dxvk_compute.h index 186d17ef..74fd778e 100644 --- a/src/dxvk/dxvk_compute.h +++ b/src/dxvk/dxvk_compute.h @@ -91,7 +91,8 @@ namespace dxvk { DxvkComputePipeline( DxvkPipelineManager* pipeMgr, - DxvkComputePipelineShaders shaders); + DxvkComputePipelineShaders shaders, + DxvkBindingLayoutObjects* layout); ~DxvkComputePipeline(); @@ -114,6 +115,18 @@ namespace dxvk { DxvkPipelineLayout* layout() const { return m_layout.ptr(); } + + /** + * \brief Pipeline layout + * + * Stores the pipeline layout and the descriptor set + * layouts, as well as information on the resource + * slots used by the pipeline. + * \returns Pipeline layout + */ + DxvkBindingLayoutObjects* getBindings() const { + return m_bindings; + } /** * \brief Retrieves pipeline handle @@ -142,6 +155,7 @@ namespace dxvk { DxvkComputePipelineShaders m_shaders; DxvkDescriptorSlotMapping m_slotMapping; + DxvkBindingLayoutObjects* m_bindings; Rc m_layout; alignas(CACHE_LINE_SIZE) diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 66c4131e..1b1b9f7d 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -10,9 +10,10 @@ namespace dxvk { DxvkGraphicsPipeline::DxvkGraphicsPipeline( DxvkPipelineManager* pipeMgr, - DxvkGraphicsPipelineShaders shaders) + DxvkGraphicsPipelineShaders shaders, + DxvkBindingLayoutObjects* layout) : m_vkd(pipeMgr->m_device->vkd()), m_pipeMgr(pipeMgr), - m_shaders(std::move(shaders)) { + m_shaders(std::move(shaders)), m_bindings(layout) { if (m_shaders.vs != nullptr) m_shaders.vs ->defineResourceSlots(m_slotMapping); if (m_shaders.tcs != nullptr) m_shaders.tcs->defineResourceSlots(m_slotMapping); if (m_shaders.tes != nullptr) m_shaders.tes->defineResourceSlots(m_slotMapping); diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 50d16b1e..1136a06d 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -149,7 +149,8 @@ namespace dxvk { DxvkGraphicsPipeline( DxvkPipelineManager* pipeMgr, - DxvkGraphicsPipelineShaders shaders); + DxvkGraphicsPipelineShaders shaders, + DxvkBindingLayoutObjects* layout); ~DxvkGraphicsPipeline(); @@ -181,6 +182,18 @@ namespace dxvk { return m_layout.ptr(); } + /** + * \brief Pipeline layout + * + * Stores the pipeline layout and the descriptor set + * layout, as well as information on the resource + * slots used by the pipeline. + * \returns Pipeline layout + */ + DxvkBindingLayoutObjects* getBindings() const { + return m_bindings; + } + /** * \brief Queries shader for a given stage * @@ -225,6 +238,7 @@ namespace dxvk { DxvkGraphicsPipelineShaders m_shaders; DxvkDescriptorSlotMapping m_slotMapping; + DxvkBindingLayoutObjects* m_bindings; Rc m_layout; uint32_t m_vsIn = 0; diff --git a/src/dxvk/dxvk_pipemanager.cpp b/src/dxvk/dxvk_pipemanager.cpp index 4c5ea32f..3f0120cc 100644 --- a/src/dxvk/dxvk_pipemanager.cpp +++ b/src/dxvk/dxvk_pipemanager.cpp @@ -31,11 +31,13 @@ namespace dxvk { auto pair = m_computePipelines.find(shaders); if (pair != m_computePipelines.end()) return &pair->second; - + + auto layout = createPipelineLayout(shaders.cs->getBindings()); + auto iter = m_computePipelines.emplace( std::piecewise_construct, std::tuple(shaders), - std::tuple(this, shaders)); + std::tuple(this, shaders, layout)); return &iter.first->second; } @@ -50,11 +52,28 @@ namespace dxvk { auto pair = m_graphicsPipelines.find(shaders); if (pair != m_graphicsPipelines.end()) return &pair->second; - + + DxvkBindingLayout mergedLayout; + mergedLayout.merge(shaders.vs->getBindings()); + + if (shaders.tcs != nullptr) + mergedLayout.merge(shaders.tcs->getBindings()); + + if (shaders.tes != nullptr) + mergedLayout.merge(shaders.tes->getBindings()); + + if (shaders.gs != nullptr) + mergedLayout.merge(shaders.gs->getBindings()); + + if (shaders.fs != nullptr) + mergedLayout.merge(shaders.fs->getBindings()); + + auto layout = createPipelineLayout(mergedLayout); + auto iter = m_graphicsPipelines.emplace( std::piecewise_construct, std::tuple(shaders), - std::tuple(this, shaders)); + std::tuple(this, shaders, layout)); return &iter.first->second; } @@ -84,5 +103,38 @@ namespace dxvk { if (m_stateCache != nullptr) m_stateCache->stopWorkerThreads(); } + + + DxvkBindingSetLayout* DxvkPipelineManager::createDescriptorSetLayout( + const DxvkBindingSetLayoutKey& key) { + auto pair = m_descriptorSetLayouts.find(key); + if (pair != m_descriptorSetLayouts.end()) + return &pair->second; + + auto iter = m_descriptorSetLayouts.emplace( + std::piecewise_construct, + std::tuple(key), + std::tuple(m_device, key)); + return &iter.first->second; + } + + + DxvkBindingLayoutObjects* DxvkPipelineManager::createPipelineLayout( + const DxvkBindingLayout& layout) { + auto pair = m_pipelineLayouts.find(layout); + if (pair != m_pipelineLayouts.end()) + return &pair->second; + + std::array setLayouts = { }; + + for (uint32_t i = 0; i < setLayouts.size(); i++) + setLayouts[i] = createDescriptorSetLayout(layout.getBindingList(i)); + + auto iter = m_pipelineLayouts.emplace( + std::piecewise_construct, + std::tuple(layout), + std::tuple(m_device, layout, setLayouts.data())); + return &iter.first->second; + } } diff --git a/src/dxvk/dxvk_pipemanager.h b/src/dxvk/dxvk_pipemanager.h index 08c79e0a..35e71102 100644 --- a/src/dxvk/dxvk_pipemanager.h +++ b/src/dxvk/dxvk_pipemanager.h @@ -106,6 +106,16 @@ namespace dxvk { dxvk::mutex m_mutex; + std::unordered_map< + DxvkBindingSetLayoutKey, + DxvkBindingSetLayout, + DxvkHash, DxvkEq> m_descriptorSetLayouts; + + std::unordered_map< + DxvkBindingLayout, + DxvkBindingLayoutObjects, + DxvkHash, DxvkEq> m_pipelineLayouts; + std::unordered_map< DxvkComputePipelineShaders, DxvkComputePipeline, @@ -115,7 +125,13 @@ namespace dxvk { DxvkGraphicsPipelineShaders, DxvkGraphicsPipeline, DxvkHash, DxvkEq> m_graphicsPipelines; - + + DxvkBindingSetLayout* createDescriptorSetLayout( + const DxvkBindingSetLayoutKey& key); + + DxvkBindingLayoutObjects* createPipelineLayout( + const DxvkBindingLayout& layout); + }; } \ No newline at end of file