From e3a63d4faa70531cabf5603a0572e5d4c7b4d5bc Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 2 Jul 2022 21:23:00 +0200 Subject: [PATCH] [dxvk] Bump state cache version to v12 And remove its reliance on the old render pass format struct. --- src/dxvk/dxvk_graphics.cpp | 35 ++++---- src/dxvk/dxvk_graphics.h | 26 ++---- src/dxvk/dxvk_state_cache.cpp | 144 ++++++++++++------------------ src/dxvk/dxvk_state_cache.h | 12 +-- src/dxvk/dxvk_state_cache_types.h | 38 +++++++- 5 files changed, 115 insertions(+), 140 deletions(-) diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index e1644d103..756abad41 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -51,7 +51,7 @@ namespace dxvk { VkPipeline DxvkGraphicsPipeline::getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state, const DxvkRenderPass* renderPass) { - DxvkGraphicsPipelineInstance* instance = this->findInstance(state, renderPass); + DxvkGraphicsPipelineInstance* instance = this->findInstance(state); if (unlikely(!instance)) { // Exit early if the state vector is invalid @@ -60,13 +60,13 @@ namespace dxvk { // Prevent other threads from adding new instances and check again std::lock_guard lock(m_mutex); - instance = this->findInstance(state, renderPass); + instance = this->findInstance(state); if (!instance) { // Keep pipeline object locked, at worst we're going to stall // a state cache worker and the current thread needs priority. - instance = this->createInstance(state, renderPass); - this->writePipelineStateToCache(state, renderPass->format()); + instance = this->createInstance(state); + this->writePipelineStateToCache(state); } } @@ -75,8 +75,7 @@ namespace dxvk { void DxvkGraphicsPipeline::compilePipeline( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass) { + const DxvkGraphicsPipelineStateInfo& state) { // Exit early if the state vector is invalid if (!this->validatePipelineState(state, false)) return; @@ -85,26 +84,24 @@ namespace dxvk { // similar pipelines concurrently is fragile on some drivers std::lock_guard lock(m_mutex); - if (!this->findInstance(state, renderPass)) - this->createInstance(state, renderPass); + if (!this->findInstance(state)) + this->createInstance(state); } DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::createInstance( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass) { - VkPipeline pipeline = this->createPipeline(state, renderPass); + const DxvkGraphicsPipelineStateInfo& state) { + VkPipeline pipeline = this->createPipeline(state); m_pipeMgr->m_numGraphicsPipelines += 1; - return &(*m_pipelines.emplace(state, renderPass, pipeline)); + return &(*m_pipelines.emplace(state, pipeline)); } DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass) { + const DxvkGraphicsPipelineStateInfo& state) { for (auto& instance : m_pipelines) { - if (instance.isCompatible(state, renderPass)) + if (instance.isCompatible(state)) return &instance; } @@ -113,8 +110,7 @@ namespace dxvk { VkPipeline DxvkGraphicsPipeline::createPipeline( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass) const { + const DxvkGraphicsPipelineStateInfo& state) const { if (Logger::logLevel() <= LogLevel::Debug) { Logger::debug("Compiling graphics pipeline..."); this->logPipelineState(LogLevel::Debug, state); @@ -551,8 +547,7 @@ namespace dxvk { void DxvkGraphicsPipeline::writePipelineStateToCache( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPassFormat& format) const { + const DxvkGraphicsPipelineStateInfo& state) const { if (m_pipeMgr->m_stateCache == nullptr) return; @@ -563,7 +558,7 @@ namespace dxvk { if (m_shaders.gs != nullptr) key.gs = m_shaders.gs->getShaderKey(); if (m_shaders.fs != nullptr) key.fs = m_shaders.fs->getShaderKey(); - m_pipeMgr->m_stateCache->addGraphicsPipeline(key, state, format); + m_pipeMgr->m_stateCache->addGraphicsPipeline(key, state); } diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 574d5d2cd..9d61570ca 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -94,15 +94,12 @@ namespace dxvk { DxvkGraphicsPipelineInstance() : m_stateVector (), - m_renderPass (nullptr), m_pipeline (VK_NULL_HANDLE) { } DxvkGraphicsPipelineInstance( const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* rp, VkPipeline pipe) : m_stateVector (state), - m_renderPass (rp), m_pipeline (pipe) { } /** @@ -113,10 +110,8 @@ namespace dxvk { * \returns \c true if the specialization is compatible */ bool isCompatible( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* rp) { - return m_renderPass == rp - && m_stateVector == state; + const DxvkGraphicsPipelineStateInfo& state) { + return m_stateVector == state; } /** @@ -130,7 +125,6 @@ namespace dxvk { private: DxvkGraphicsPipelineStateInfo m_stateVector; - const DxvkRenderPass* m_renderPass; VkPipeline m_pipeline; }; @@ -212,11 +206,9 @@ namespace dxvk { * Asynchronously compiles the given pipeline * and stores the result for future use. * \param [in] state Pipeline state vector - * \param [in] renderPass The render pass */ void compilePipeline( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass); + const DxvkGraphicsPipelineStateInfo& state); private: @@ -238,16 +230,13 @@ namespace dxvk { sync::List m_pipelines; DxvkGraphicsPipelineInstance* createInstance( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass); + const DxvkGraphicsPipelineStateInfo& state); DxvkGraphicsPipelineInstance* findInstance( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass); + const DxvkGraphicsPipelineStateInfo& state); VkPipeline createPipeline( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPass* renderPass) const; + const DxvkGraphicsPipelineStateInfo& state) const; void destroyPipeline( VkPipeline pipeline) const; @@ -264,8 +253,7 @@ namespace dxvk { bool trusted) const; void writePipelineStateToCache( - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPassFormat& format) const; + const DxvkGraphicsPipelineStateInfo& state) const; void logPipelineState( LogLevel level, diff --git a/src/dxvk/dxvk_state_cache.cpp b/src/dxvk/dxvk_state_cache.cpp index 16f965ba6..b9a708330 100644 --- a/src/dxvk/dxvk_state_cache.cpp +++ b/src/dxvk/dxvk_state_cache.cpp @@ -62,6 +62,14 @@ namespace dxvk { return read(data); } + bool read(DxvkRtInfo& data, uint32_t version) { + // v12 introduced this field + if (version < 12) + return true; + + return read(data); + } + bool read(DxvkIlBinding& data, uint32_t version) { if (version < 10) { DxvkIlBindingV9 v9; @@ -76,6 +84,34 @@ namespace dxvk { return read(data); } + + bool read(DxvkRenderPassFormatV11& data, uint32_t version) { + uint8_t sampleCount = 0; + uint8_t imageFormat = 0; + uint8_t imageLayout = 0; + + if (!read(sampleCount) + || !read(imageFormat) + || !read(imageLayout)) + return false; + + data.sampleCount = VkSampleCountFlagBits(sampleCount); + data.depth.format = VkFormat(imageFormat); + data.depth.layout = unpackImageLayoutV11(imageLayout); + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (!read(imageFormat) + || !read(imageLayout)) + return false; + + data.color[i].format = VkFormat(imageFormat); + data.color[i].layout = unpackImageLayoutV11(imageLayout); + } + + return true; + } + + template bool write(const T& data) { if (m_size + sizeof(T) > MaxSize) @@ -114,6 +150,15 @@ namespace dxvk { return true; } + static VkImageLayout unpackImageLayoutV11( + uint8_t layout) { + switch (layout) { + case 0x80: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; + case 0x81: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; + default: return VkImageLayout(layout); + } + } + }; @@ -199,8 +244,7 @@ namespace dxvk { void DxvkStateCache::addGraphicsPipeline( const DxvkStateCacheKey& shaders, - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPassFormat& format) { + const DxvkGraphicsPipelineStateInfo& state) { if (shaders.vs.eq(g_nullShaderKey)) return; @@ -210,7 +254,7 @@ namespace dxvk { for (auto e = entries.first; e != entries.second; e++) { const DxvkStateCacheEntry& entry = m_entries[e->second]; - if (entry.format.eq(format) && entry.gpState == state) + if (entry.gpState == state) return; } @@ -218,8 +262,7 @@ namespace dxvk { std::unique_lock lock(m_writerLock); m_writerQueue.push({ shaders, state, - DxvkComputePipelineStateInfo(), - format, g_nullHash }); + DxvkComputePipelineStateInfo(), g_nullHash }); m_writerCond.notify_one(); createWriter(); @@ -244,8 +287,7 @@ namespace dxvk { std::unique_lock lock(m_writerLock); m_writerQueue.push({ shaders, - DxvkGraphicsPipelineStateInfo(), state, - DxvkRenderPassFormat(), g_nullHash }); + DxvkGraphicsPipelineStateInfo(), state, g_nullHash }); m_writerCond.notify_one(); createWriter(); @@ -360,11 +402,7 @@ namespace dxvk { for (auto e = entries.first; e != entries.second; e++) { const auto& entry = m_entries[e->second]; - - if (m_passManager->validateRenderPassFormat(entry.format)) { - auto rp = m_passManager->getRenderPass(entry.format); - pipeline->compilePipeline(entry.gpState, rp); - } + pipeline->compilePipeline(entry.gpState); } } else { auto pipeline = m_pipeManager->createComputePipeline(item.cp); @@ -504,31 +542,12 @@ namespace dxvk { return false; } else { // Read packed render pass format - uint8_t sampleCount = 0; - uint8_t imageFormat = 0; - uint8_t imageLayout = 0; - - if (!data.read(sampleCount, version) - || !data.read(imageFormat, version) - || !data.read(imageLayout, version)) - return false; - - entry.format.sampleCount = VkSampleCountFlagBits(sampleCount); - entry.format.depth.format = VkFormat(imageFormat); - entry.format.depth.layout = unpackImageLayout(imageLayout); - - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - if (!data.read(imageFormat, version) - || !data.read(imageLayout, version)) - return false; - - entry.format.color[i].format = VkFormat(imageFormat); - entry.format.color[i].layout = unpackImageLayout(imageLayout); + if (version < 12) { + DxvkRenderPassFormatV11 v11; + data.read(v11, version); + entry.gpState.rt = v11.convert(); } - if (!validateRenderPassFormat(entry.format)) - return false; - // Read common pipeline state if (!data.read(dummyBindingMask, version) || !data.read(entry.gpState.ia, version) @@ -537,6 +556,7 @@ namespace dxvk { || !data.read(entry.gpState.ms, version) || !data.read(entry.gpState.ds, version) || !data.read(entry.gpState.om, version) + || !data.read(entry.gpState.rt, version) || !data.read(entry.gpState.dsFront, version) || !data.read(entry.gpState.dsBack, version)) return false; @@ -608,16 +628,6 @@ namespace dxvk { } if (!(stageMask & VK_SHADER_STAGE_COMPUTE_BIT)) { - // Pack render pass format - data.write(uint8_t(entry.format.sampleCount)); - data.write(uint8_t(entry.format.depth.format)); - data.write(packImageLayout(entry.format.depth.layout)); - - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - data.write(uint8_t(entry.format.color[i].format)); - data.write(packImageLayout(entry.format.color[i].layout)); - } - // Write out common pipeline state data.write(entry.gpState.ia); data.write(entry.gpState.il); @@ -625,6 +635,7 @@ namespace dxvk { data.write(entry.gpState.ms); data.write(entry.gpState.ds); data.write(entry.gpState.om); + data.write(entry.gpState.rt); data.write(entry.gpState.dsFront); data.write(entry.gpState.dsBack); @@ -785,47 +796,4 @@ namespace dxvk { return env::getEnvVar("DXVK_STATE_CACHE_PATH"); } - - uint8_t DxvkStateCache::packImageLayout( - VkImageLayout layout) { - switch (layout) { - case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: return 0x80; - case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: return 0x81; - default: return uint8_t(layout); - } - } - - - VkImageLayout DxvkStateCache::unpackImageLayout( - uint8_t layout) { - switch (layout) { - case 0x80: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; - case 0x81: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; - default: return VkImageLayout(layout); - } - } - - - bool DxvkStateCache::validateRenderPassFormat( - const DxvkRenderPassFormat& format) { - bool valid = true; - - if (format.depth.format) { - valid &= format.depth.layout == VK_IMAGE_LAYOUT_GENERAL - || format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL - || format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL - || format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL - || format.depth.layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; - } - - for (uint32_t i = 0; i < MaxNumRenderTargets && valid; i++) { - if (format.color[i].format) { - valid &= format.color[i].layout == VK_IMAGE_LAYOUT_GENERAL - || format.color[i].layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - } - - return valid; - } - } diff --git a/src/dxvk/dxvk_state_cache.h b/src/dxvk/dxvk_state_cache.h index 6419a797f..11cbac986 100644 --- a/src/dxvk/dxvk_state_cache.h +++ b/src/dxvk/dxvk_state_cache.h @@ -45,8 +45,7 @@ namespace dxvk { */ void addGraphicsPipeline( const DxvkStateCacheKey& shaders, - const DxvkGraphicsPipelineStateInfo& state, - const DxvkRenderPassFormat& format); + const DxvkGraphicsPipelineStateInfo& state); /** * Adds a compute pipeline to the cache @@ -170,15 +169,6 @@ namespace dxvk { std::string getCacheDir() const; - static uint8_t packImageLayout( - VkImageLayout layout); - - static VkImageLayout unpackImageLayout( - uint8_t layout); - - static bool validateRenderPassFormat( - const DxvkRenderPassFormat& format); - }; } diff --git a/src/dxvk/dxvk_state_cache_types.h b/src/dxvk/dxvk_state_cache_types.h index a9c33b2d3..758f7cf65 100644 --- a/src/dxvk/dxvk_state_cache_types.h +++ b/src/dxvk/dxvk_state_cache_types.h @@ -38,7 +38,6 @@ namespace dxvk { DxvkStateCacheKey shaders; DxvkGraphicsPipelineStateInfo gpState; DxvkComputePipelineStateInfo cpState; - DxvkRenderPassFormat format; Sha1Hash hash; }; @@ -52,7 +51,7 @@ namespace dxvk { */ struct DxvkStateCacheHeader { char magic[4] = { 'D', 'X', 'V', 'K' }; - uint32_t version = 11; + uint32_t version = 12; uint32_t entrySize = 0; /* no longer meaningful */ }; @@ -89,4 +88,39 @@ namespace dxvk { }; + /** + * \brief Old attachment format struct + */ + struct DxvkAttachmentFormatV11 { + VkFormat format = VK_FORMAT_UNDEFINED; + VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; + }; + + + /** + * \brief Old render pass format struct + */ + struct DxvkRenderPassFormatV11 { + VkSampleCountFlagBits sampleCount; + DxvkAttachmentFormatV11 depth; + DxvkAttachmentFormatV11 color[MaxNumRenderTargets]; + + DxvkRtInfo convert() const { + VkImageAspectFlags readOnlyAspects = 0; + auto depthFormatInfo = imageFormatInfo(depth.format); + + if (depth.format && depthFormatInfo) { + readOnlyAspects = depthFormatInfo->aspectMask + & ~vk::getWritableAspectsForLayout(depth.layout); + } + + std::array colorFormats; + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) + colorFormats[i] = color[i].format; + + return DxvkRtInfo(MaxNumRenderTargets, colorFormats.data(), + depth.format, readOnlyAspects); + } + }; + }