From cb274e040d9e6b858e1f8b0e604064ee7e5de4d5 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 1 Sep 2018 17:53:45 +0200 Subject: [PATCH] [dxvk] Add spec constants for pixel shader output mapping --- src/dxvk/dxvk_graphics.cpp | 5 +++++ src/dxvk/dxvk_shader.h | 7 ++++++- src/dxvk/dxvk_spec_const.cpp | 23 ++++++++++++++++++++--- src/dxvk/dxvk_spec_const.h | 9 ++++++++- src/dxvk/dxvk_util.cpp | 13 +++++++++++++ src/dxvk/dxvk_util.h | 11 +++++++++++ 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 19e3e476..4ba0b274 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -237,6 +237,11 @@ namespace dxvk { omBlendAttachments[i].colorWriteMask = util::remapComponentMask( state.omBlendAttachments[i].colorWriteMask, state.omComponentMapping[i]); + + specData.outputMappings[4 * i + 0] = util::getComponentIndex(state.omComponentMapping[i].r, 0); + specData.outputMappings[4 * i + 1] = util::getComponentIndex(state.omComponentMapping[i].g, 1); + specData.outputMappings[4 * i + 2] = util::getComponentIndex(state.omComponentMapping[i].b, 2); + specData.outputMappings[4 * i + 3] = util::getComponentIndex(state.omComponentMapping[i].a, 3); } // Generate per-instance attribute divisors diff --git a/src/dxvk/dxvk_shader.h b/src/dxvk/dxvk_shader.h index 5170390b..fd515545 100644 --- a/src/dxvk/dxvk_shader.h +++ b/src/dxvk/dxvk_shader.h @@ -21,7 +21,12 @@ namespace dxvk { */ enum class DxvkSpecConstantId : uint32_t { RasterizerSampleCount = 0x10000, - + + /// Special constant ranges that do not count + /// towards the spec constant min/max values + ColorComponentMappings = 0x20000, + + /// Lowest and highest known spec constant IDs SpecConstantIdMin = RasterizerSampleCount, SpecConstantIdMax = RasterizerSampleCount, }; diff --git a/src/dxvk/dxvk_spec_const.cpp b/src/dxvk/dxvk_spec_const.cpp index ab4ade66..e1c69e2a 100644 --- a/src/dxvk/dxvk_spec_const.cpp +++ b/src/dxvk/dxvk_spec_const.cpp @@ -11,9 +11,12 @@ namespace dxvk { DxvkSpecConstantMap::DxvkSpecConstantMap() { SET_CONSTANT_ENTRY(DxvkSpecConstantId::RasterizerSampleCount, rasterizerSampleCount); - + for (uint32_t i = 0; i < MaxNumActiveBindings; i++) this->setBindingEntry(i); + + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) + this->setOutputMappingEntry(i); } @@ -27,8 +30,8 @@ namespace dxvk { entry.size = size; m_mapEntries[uint32_t(specId) - uint32_t(DxvkSpecConstantId::SpecConstantIdMin)] = entry; } - - + + void DxvkSpecConstantMap::setBindingEntry( uint32_t binding) { VkSpecializationMapEntry entry; @@ -37,5 +40,19 @@ namespace dxvk { entry.size = sizeof(VkBool32); m_mapEntries[MaxNumSpecConstants + binding] = entry; } + + + void DxvkSpecConstantMap::setOutputMappingEntry( + uint32_t output) { + for (uint32_t i = 0; i < 4; i++) { + uint32_t constId = 4 * output + i; + + VkSpecializationMapEntry entry; + entry.constantID = uint32_t(DxvkSpecConstantId::ColorComponentMappings) + constId; + entry.offset = sizeof(uint32_t) * constId + offsetof(DxvkSpecConstantData, outputMappings); + entry.size = sizeof(uint32_t); + m_mapEntries[MaxNumSpecConstants + MaxNumActiveBindings + constId] = entry; + } + } } \ No newline at end of file diff --git a/src/dxvk/dxvk_spec_const.h b/src/dxvk/dxvk_spec_const.h index 445fba9e..e851e891 100644 --- a/src/dxvk/dxvk_spec_const.h +++ b/src/dxvk/dxvk_spec_const.h @@ -18,6 +18,7 @@ namespace dxvk { */ struct DxvkSpecConstantData { uint32_t rasterizerSampleCount; + uint32_t outputMappings[MaxNumRenderTargets * 4]; VkBool32 activeBindings[MaxNumActiveBindings]; }; @@ -55,7 +56,10 @@ namespace dxvk { private: - std::array m_mapEntries; + std::array m_mapEntries; void setConstantEntry( DxvkSpecConstantId specId, @@ -65,6 +69,9 @@ namespace dxvk { void setBindingEntry( uint32_t binding); + void setOutputMappingEntry( + uint32_t output); + }; extern DxvkSpecConstantMap g_specConstantMap; diff --git a/src/dxvk/dxvk_util.cpp b/src/dxvk/dxvk_util.cpp index 6208d3c3..603e9c94 100644 --- a/src/dxvk/dxvk_util.cpp +++ b/src/dxvk/dxvk_util.cpp @@ -136,4 +136,17 @@ namespace dxvk::util { return result; } + + uint32_t getComponentIndex( + VkComponentSwizzle component, + uint32_t identity) { + switch (component) { + case VK_COMPONENT_SWIZZLE_R: return 0; + case VK_COMPONENT_SWIZZLE_G: return 1; + case VK_COMPONENT_SWIZZLE_B: return 2; + case VK_COMPONENT_SWIZZLE_A: return 3; + default: return identity; /* identity, zero, one */ + } + } + } diff --git a/src/dxvk/dxvk_util.h b/src/dxvk/dxvk_util.h index a12f702f..029ec3e2 100644 --- a/src/dxvk/dxvk_util.h +++ b/src/dxvk/dxvk_util.h @@ -201,6 +201,17 @@ namespace dxvk::util { VkComponentMapping invertComponentMapping( VkComponentMapping mapping); + /** + * \brief Computes component index for a component swizzle + * + * \param [in] component The component swizzle + * \param [in] identity Value for SWIZZLE_IDENTITY + * \returns Component index + */ + uint32_t getComponentIndex( + VkComponentSwizzle component, + uint32_t identity); + }