From 6d3ba1b7d74fe2c3d8565ebbaff4d2c968330ae1 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 6 May 2022 16:05:43 +0200 Subject: [PATCH] [dxvk] Perform validation on render pass formats read from state cache --- src/dxvk/dxvk_renderpass.cpp | 41 +++++++++++++++++++++++++++++++++-- src/dxvk/dxvk_renderpass.h | 13 +++++++++-- src/dxvk/dxvk_state_cache.cpp | 6 +++-- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index ee07945b..2bac1708 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -269,7 +269,7 @@ namespace dxvk { DxvkRenderPassPool::DxvkRenderPassPool(const DxvkDevice* device) - : m_vkd(device->vkd()) { + : m_device(device) { } @@ -288,8 +288,45 @@ namespace dxvk { auto result = m_renderPasses.emplace(std::piecewise_construct, std::tuple(fmt), - std::tuple(m_vkd, fmt)); + std::tuple(m_device->vkd(), fmt)); return &result.first->second; } + + + bool DxvkRenderPassPool::validateRenderPassFormat( + const DxvkRenderPassFormat& fmt) { + Rc adapter = m_device->adapter(); + + if (fmt.depth.format) { + VkFormatProperties depthInfo = adapter->formatProperties(fmt.depth.format); + VkFormatFeatureFlags depthFlags = depthInfo.linearTilingFeatures | depthInfo.optimalTilingFeatures; + + if (!(depthFlags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) + return false; + + if (fmt.depth.layout != VK_IMAGE_LAYOUT_GENERAL + && fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL + && fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL + && fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL + && fmt.depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) + return false; + } + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + if (fmt.color[i].format) { + VkFormatProperties colorInfo = adapter->formatProperties(fmt.color[i].format); + VkFormatFeatureFlags colorFlags = colorInfo.linearTilingFeatures | colorInfo.optimalTilingFeatures; + + if (!(colorFlags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) + return false; + + if (fmt.color[i].layout != VK_IMAGE_LAYOUT_GENERAL + && fmt.color[i].layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + return false; + } + } + + return true; + } } \ No newline at end of file diff --git a/src/dxvk/dxvk_renderpass.h b/src/dxvk/dxvk_renderpass.h index ea265b84..2dff8788 100644 --- a/src/dxvk/dxvk_renderpass.h +++ b/src/dxvk/dxvk_renderpass.h @@ -219,10 +219,19 @@ namespace dxvk { */ DxvkRenderPass* getRenderPass( const DxvkRenderPassFormat& fmt); - + + /** + * \brief Validates render pass format + * + * \param [in] fmt The render pass format + * \returns \c true if the format is supported + */ + bool validateRenderPassFormat( + const DxvkRenderPassFormat& fmt); + private: - const Rc m_vkd; + const DxvkDevice* m_device; dxvk::mutex m_mutex; std::unordered_map< diff --git a/src/dxvk/dxvk_state_cache.cpp b/src/dxvk/dxvk_state_cache.cpp index acc57468..15bec171 100644 --- a/src/dxvk/dxvk_state_cache.cpp +++ b/src/dxvk/dxvk_state_cache.cpp @@ -371,8 +371,10 @@ namespace dxvk { for (auto e = entries.first; e != entries.second; e++) { const auto& entry = m_entries[e->second]; - auto rp = m_passManager->getRenderPass(entry.format); - pipeline->compilePipeline(entry.gpState, rp); + if (m_passManager->validateRenderPassFormat(entry.format)) { + auto rp = m_passManager->getRenderPass(entry.format); + pipeline->compilePipeline(entry.gpState, rp); + } } } else { auto pipeline = m_pipeManager->createComputePipeline(item.cp);