From 3b10efbc3034da8dbd8ef2f476093c8a6b004682 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 5 Jul 2022 12:56:56 +0200 Subject: [PATCH] [dxvk] Implement fragment output pipeline libraries --- src/dxvk/dxvk_graphics.cpp | 60 ++++++++++++++++++++++++++++++++++- src/dxvk/dxvk_graphics.h | 31 ++++++++++++++++++ src/dxvk/dxvk_pipemanager.cpp | 16 ++++++++++ src/dxvk/dxvk_pipemanager.h | 14 ++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 2f76185f3..b1338970f 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -141,7 +141,7 @@ namespace dxvk { auto vk = m_device->vkd(); VkGraphicsPipelineLibraryCreateInfoEXT libInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT }; - libInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT; + libInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT; VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo }; info.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; @@ -250,6 +250,21 @@ namespace dxvk { } + bool DxvkGraphicsPipelineFragmentOutputState::useDynamicBlendConstants() const { + bool result = false; + + for (uint32_t i = 0; i < MaxNumRenderTargets && !result; i++) { + result = cbAttachments[i].blendEnable + && (util::isBlendConstantBlendFactor(cbAttachments[i].srcColorBlendFactor) + || util::isBlendConstantBlendFactor(cbAttachments[i].dstColorBlendFactor) + || util::isBlendConstantBlendFactor(cbAttachments[i].srcAlphaBlendFactor) + || util::isBlendConstantBlendFactor(cbAttachments[i].dstAlphaBlendFactor)); + } + + return result; + } + + bool DxvkGraphicsPipelineFragmentOutputState::eq(const DxvkGraphicsPipelineFragmentOutputState& other) const { bool eq = rtInfo.colorAttachmentCount == other.rtInfo.colorAttachmentCount && rtInfo.depthAttachmentFormat == other.rtInfo.depthAttachmentFormat @@ -322,6 +337,49 @@ namespace dxvk { } + DxvkGraphicsPipelineFragmentOutputLibrary::DxvkGraphicsPipelineFragmentOutputLibrary( + DxvkDevice* device, + const DxvkGraphicsPipelineFragmentOutputState& state, + VkPipelineCache cache) + : m_device(device) { + auto vk = m_device->vkd(); + + VkDynamicState dynamicState = VK_DYNAMIC_STATE_BLEND_CONSTANTS; + VkPipelineDynamicStateCreateInfo dyInfo = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; + + if (state.useDynamicBlendConstants()) { + dyInfo.dynamicStateCount = 1; + dyInfo.pDynamicStates = &dynamicState; + } + + // pNext is non-const for some reason, but this is only an input + // structure, so we should be able to safely use const_cast. + VkGraphicsPipelineLibraryCreateInfoEXT libInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT }; + libInfo.pNext = const_cast(&state.rtInfo); + libInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT; + + VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo }; + info.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; + info.pColorBlendState = &state.cbInfo; + info.pMultisampleState = &state.msInfo; + info.pDynamicState = &dyInfo; + info.basePipelineIndex = -1; + + VkResult vr = vk->vkCreateGraphicsPipelines(vk->device(), + cache, 1, &info, nullptr, &m_pipeline); + + if (vr) + throw DxvkError("Failed to create vertex input pipeline library"); + } + + + DxvkGraphicsPipelineFragmentOutputLibrary::~DxvkGraphicsPipelineFragmentOutputLibrary() { + auto vk = m_device->vkd(); + + vk->vkDestroyPipeline(vk->device(), m_pipeline, nullptr); + } + + DxvkGraphicsPipelinePreRasterizationState::DxvkGraphicsPipelinePreRasterizationState() { } diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index e640c1be9..f2757f2be 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -99,12 +99,43 @@ namespace dxvk { std::array cbAttachments = { }; std::array rtColorFormats = { }; + bool useDynamicBlendConstants() const; + bool eq(const DxvkGraphicsPipelineFragmentOutputState& other) const; size_t hash() const; }; + /** + * \brief Vertex input pipeline library + * + * Creates a Vulkan pipeline object for a + * given vertex input state vector. + */ + class DxvkGraphicsPipelineFragmentOutputLibrary { + + public: + + DxvkGraphicsPipelineFragmentOutputLibrary( + DxvkDevice* device, + const DxvkGraphicsPipelineFragmentOutputState& state, + VkPipelineCache cache); + + ~DxvkGraphicsPipelineFragmentOutputLibrary(); + + VkPipeline getHandle() const { + return m_pipeline; + } + + private: + + DxvkDevice* m_device; + VkPipeline m_pipeline; + + }; + + /** * \brief Pre-rasterization info for graphics pipelines * diff --git a/src/dxvk/dxvk_pipemanager.cpp b/src/dxvk/dxvk_pipemanager.cpp index 9fca1ccb7..5c58cc134 100644 --- a/src/dxvk/dxvk_pipemanager.cpp +++ b/src/dxvk/dxvk_pipemanager.cpp @@ -93,6 +93,22 @@ namespace dxvk { } + DxvkGraphicsPipelineFragmentOutputLibrary* DxvkPipelineManager::createFragmentOutputLibrary( + const DxvkGraphicsPipelineFragmentOutputState& state) { + std::lock_guard lock(m_mutex); + + auto pair = m_fragmentOutputLibraries.find(state); + if (pair != m_fragmentOutputLibraries.end()) + return &pair->second; + + auto iter = m_fragmentOutputLibraries.emplace( + std::piecewise_construct, + std::tuple(state), + std::tuple(m_device, state, m_cache->handle())); + return &iter.first->second; + } + + void DxvkPipelineManager::registerShader( const Rc& shader) { if (m_stateCache != nullptr) diff --git a/src/dxvk/dxvk_pipemanager.h b/src/dxvk/dxvk_pipemanager.h index 508e8ac72..fbb764522 100644 --- a/src/dxvk/dxvk_pipemanager.h +++ b/src/dxvk/dxvk_pipemanager.h @@ -75,6 +75,15 @@ namespace dxvk { DxvkGraphicsPipelineVertexInputLibrary* createVertexInputLibrary( const DxvkGraphicsPipelineVertexInputState& state); + /** + * \brief Retrieves a fragment output pipeline library + * + * \param [in] state Fragment output state + * \returns Pipeline library object + */ + DxvkGraphicsPipelineFragmentOutputLibrary* createFragmentOutputLibrary( + const DxvkGraphicsPipelineFragmentOutputState& state); + /* * \brief Registers a shader * @@ -139,6 +148,11 @@ namespace dxvk { DxvkGraphicsPipelineVertexInputLibrary, DxvkHash, DxvkEq> m_vertexInputLibraries; + std::unordered_map< + DxvkGraphicsPipelineFragmentOutputState, + DxvkGraphicsPipelineFragmentOutputLibrary, + DxvkHash, DxvkEq> m_fragmentOutputLibraries; + DxvkBindingSetLayout* createDescriptorSetLayout( const DxvkBindingSetLayoutKey& key);