From 30fa9df868bb90808bbd5b6708f0822f82f66891 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 30 Jul 2022 23:38:22 +0200 Subject: [PATCH] [dxvk] Introduce DxvkGraphicsPipelineSpecConstantState --- src/dxvk/dxvk_compute.cpp | 16 ++---- src/dxvk/dxvk_graphics.cpp | 99 +++++++++++++++++++++++++++++--------- src/dxvk/dxvk_graphics.h | 29 ++++++++++- 3 files changed, 106 insertions(+), 38 deletions(-) diff --git a/src/dxvk/dxvk_compute.cpp b/src/dxvk/dxvk_compute.cpp index 02249771e..d475ace8a 100644 --- a/src/dxvk/dxvk_compute.cpp +++ b/src/dxvk/dxvk_compute.cpp @@ -4,6 +4,7 @@ #include "dxvk_compute.h" #include "dxvk_device.h" +#include "dxvk_graphics.h" #include "dxvk_pipemanager.h" #include "dxvk_spec_const.h" #include "dxvk_state_cache.h" @@ -106,23 +107,12 @@ namespace dxvk { Logger::debug(str::format(" cs : ", m_shaders.cs->debugName())); } - uint32_t specConstantMask = m_shaders.cs->getSpecConstantMask(); - DxvkSpecConstants specData; - - for (uint32_t i = 0; i < MaxNumSpecConstants; i++) { - if (specConstantMask & (1u << i)) - specData.set(i, state.sc.specConstants[i], 0u); - } - - if (specConstantMask & (1u << MaxNumSpecConstants)) - specData.set(MaxNumSpecConstants, 1u, 0u); - - VkSpecializationInfo specInfo = specData.getSpecInfo(); + DxvkPipelineSpecConstantState scState(m_shaders.cs->getSpecConstantMask(), state.sc); DxvkShaderStageInfo stageInfo(m_device); stageInfo.addStage(VK_SHADER_STAGE_COMPUTE_BIT, m_shaders.cs->getCode(m_bindings, DxvkShaderModuleCreateInfo()), - &specInfo); + &scState.scInfo); VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; info.stage = *stageInfo.getStageInfos(); diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index c79bee70e..6ab86914f 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -601,6 +601,68 @@ namespace dxvk { } + DxvkPipelineSpecConstantState::DxvkPipelineSpecConstantState() { + + } + + + DxvkPipelineSpecConstantState::DxvkPipelineSpecConstantState( + uint32_t mask, + const DxvkScInfo& state) { + for (uint32_t i = 0; i < MaxNumSpecConstants; i++) { + if (mask & (1u << i)) + addConstant(i, state.specConstants[i]); + } + + if (mask & (1u << MaxNumSpecConstants)) + addConstant(MaxNumSpecConstants, VK_TRUE); + + if (scInfo.mapEntryCount) { + scInfo.pMapEntries = scConstantMap.data(); + scInfo.dataSize = scInfo.mapEntryCount * sizeof(uint32_t); + scInfo.pData = scConstantData.data(); + } + } + + + bool DxvkPipelineSpecConstantState::eq(const DxvkPipelineSpecConstantState& other) const { + bool eq = scInfo.mapEntryCount == other.scInfo.mapEntryCount; + + for (uint32_t i = 0; i < scInfo.mapEntryCount && eq; i++) { + eq = scConstantMap[i].constantID == other.scConstantMap[i].constantID + && scConstantData[i] == other.scConstantData[i]; + } + + return eq; + } + + + size_t DxvkPipelineSpecConstantState::hash() const { + DxvkHashState hash; + hash.add(scInfo.mapEntryCount); + + for (uint32_t i = 0; i < scInfo.mapEntryCount; i++) { + hash.add(scConstantMap[i].constantID); + hash.add(scConstantData[i]); + } + + return hash; + } + + + void DxvkPipelineSpecConstantState::addConstant(uint32_t id, uint32_t value) { + if (value) { + uint32_t index = scInfo.mapEntryCount++; + + scConstantMap[index].constantID = id; + scConstantMap[index].offset = sizeof(uint32_t) * index; + scConstantMap[index].size = sizeof(uint32_t); + + scConstantData[index] = value; + } + } + + DxvkGraphicsPipeline::DxvkGraphicsPipeline( DxvkDevice* device, DxvkPipelineManager* pipeMgr, @@ -915,45 +977,34 @@ namespace dxvk { dynamicStates[dynamicStateCount++] = VK_DYNAMIC_STATE_FRONT_FACE; } - // Set up some specialization constants - DxvkSpecConstants specData; - - for (uint32_t i = 0; i < MaxNumSpecConstants; i++) { - if (m_specConstantMask & (1u << i)) - specData.set(i, state.sc.specConstants[i], 0u); - } - - if (m_specConstantMask & (1u << MaxNumSpecConstants)) - specData.set(MaxNumSpecConstants, 1u, 0u); - - VkSpecializationInfo specInfo = specData.getSpecInfo(); + // Set up pipeline state + DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders.vs.ptr()); + DxvkGraphicsPipelinePreRasterizationState prState(m_device, state, m_shaders.gs.ptr()); + DxvkGraphicsPipelineFragmentShaderState fsState(m_device, state); + DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders.fs.ptr()); + DxvkPipelineSpecConstantState scState(m_specConstantMask, state.sc); // Build stage infos for all provided shaders DxvkShaderStageInfo stageInfo(m_device); if (flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) { - stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, m_vsLibrary->getModuleIdentifier(), &specInfo); + stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, m_vsLibrary->getModuleIdentifier(), &scState.scInfo); if (m_shaders.fs != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, m_fsLibrary->getModuleIdentifier(), &specInfo); + stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, m_fsLibrary->getModuleIdentifier(), &scState.scInfo); } else { - stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, state), &specInfo); + stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, state), &scState.scInfo); if (m_shaders.tcs != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, state), &specInfo); + stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, state), &scState.scInfo); if (m_shaders.tes != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, state), &specInfo); + stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, state), &scState.scInfo); if (m_shaders.gs != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, state), &specInfo); + stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, state), &scState.scInfo); if (m_shaders.fs != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, state), &specInfo); + stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, state), &scState.scInfo); } - DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders.vs.ptr()); - DxvkGraphicsPipelinePreRasterizationState prState(m_device, state, m_shaders.gs.ptr()); - DxvkGraphicsPipelineFragmentShaderState fsState(m_device, state); - DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders.fs.ptr()); - VkPipelineDynamicStateCreateInfo dyInfo = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; dyInfo.dynamicStateCount = dynamicStateCount; dyInfo.pDynamicStates = dynamicStates.data(); diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 58489c016..614633c81 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -186,7 +186,34 @@ namespace dxvk { size_t hash() const; }; - + + /** + * \brief Specialization constant state for pipelines + * + * Can only be used when all pipeline state is known. + */ + struct DxvkPipelineSpecConstantState { + DxvkPipelineSpecConstantState(); + + DxvkPipelineSpecConstantState( + uint32_t mask, + const DxvkScInfo& state); + + VkSpecializationInfo scInfo = { }; + std::array scConstantMap = { }; + std::array scConstantData = { }; + + bool eq(const DxvkPipelineSpecConstantState& other) const; + + size_t hash() const; + + private: + + void addConstant(uint32_t id, uint32_t value); + + }; + + /** * \brief Flags that describe pipeline properties */