From 48d854365d275c7384db6faebc0a7dcae03b8839 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 7 Jun 2019 18:45:57 +0100 Subject: [PATCH] Move AddXFBAnnotations into common SPIR-V code so it can be shared --- .../driver/shaders/spirv/spirv_reflect.cpp | 132 ++++++++++++++++++ .../driver/shaders/spirv/spirv_reflect.h | 4 + renderdoc/driver/vulkan/vk_postvs.cpp | 132 ------------------ 3 files changed, 136 insertions(+), 132 deletions(-) diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp index 2f7eacd74..d19946e0a 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.cpp @@ -24,6 +24,7 @@ #include "spirv_reflect.h" #include "replay/replay_driver.h" +#include "spirv_editor.h" void FillSpecConstantVariables(const rdcarray &invars, rdcarray &outvars, @@ -52,3 +53,134 @@ void FillSpecConstantVariables(const rdcarray &invars, } } } + +void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData &patchData, + const char *entryName, std::vector &modSpirv, uint32_t &xfbStride) +{ + SPIRVEditor editor(modSpirv); + + rdcarray outsig = refl.outputSignature; + std::vector outpatch = patchData.outputs; + + rdcspv::Id entryid; + for(const SPIRVEntry &entry : editor.GetEntries()) + { + if(entry.name == entryName) + { + entryid = entry.id; + break; + } + } + + bool hasXFB = false; + + for(rdcspv::Iter it = editor.Begin(SPIRVSection::ExecutionMode); + it < editor.End(SPIRVSection::ExecutionMode); ++it) + { + if(it.opcode() == spv::OpExecutionMode && rdcspv::Id::fromWord(it.word(1)) == entryid && + it.word(2) == spv::ExecutionModeXfb) + { + hasXFB = true; + break; + } + } + + if(hasXFB) + { + for(rdcspv::Iter it = editor.Begin(SPIRVSection::Annotations); + it < editor.End(SPIRVSection::Annotations); ++it) + { + // remove any existing xfb decorations + if(it.opcode() == spv::OpDecorate && + (it.word(2) == spv::DecorationXfbBuffer || it.word(2) == spv::DecorationXfbStride)) + { + editor.Remove(it); + } + + // offset is trickier, need to see if it'll match one we want later + if((it.opcode() == spv::OpDecorate && it.word(2) == spv::DecorationOffset) || + (it.opcode() == spv::OpMemberDecorate && it.word(3) == spv::DecorationOffset)) + { + for(size_t i = 0; i < outsig.size(); i++) + { + if(outpatch[i].structID && !outpatch[i].accessChain.empty()) + { + if(it.opcode() == spv::OpMemberDecorate && it.word(1) == outpatch[i].structID && + it.word(2) == outpatch[i].accessChain.back()) + { + editor.Remove(it); + } + } + else + { + if(it.opcode() == spv::OpDecorate && it.word(1) == outpatch[i].ID) + { + editor.Remove(it); + } + } + } + } + } + } + else + { + editor.AddExecutionMode(entryid, spv::ExecutionModeXfb); + } + + editor.AddCapability(spv::CapabilityTransformFeedback); + + // find the position output and move it to the front + for(size_t i = 0; i < outsig.size(); i++) + { + if(outsig[i].systemValue == ShaderBuiltin::Position) + { + outsig.insert(0, outsig[i]); + outsig.erase(i + 1); + + outpatch.insert(outpatch.begin(), outpatch[i]); + outpatch.erase(outpatch.begin() + i + 1); + break; + } + } + + for(size_t i = 0; i < outsig.size(); i++) + { + if(outpatch[i].isArraySubsequentElement) + { + // do not patch anything as we only patch the base array, but reserve space in the stride + } + else if(outpatch[i].structID && !outpatch[i].accessChain.empty()) + { + editor.AddDecoration(rdcspv::Operation( + spv::OpMemberDecorate, + {outpatch[i].structID, outpatch[i].accessChain.back(), spv::DecorationOffset, xfbStride})); + } + else if(outpatch[i].ID) + { + editor.AddDecoration(rdcspv::Operation( + spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationOffset, xfbStride})); + } + + uint32_t compByteSize = 4; + + if(outsig[i].compType == CompType::Double) + compByteSize = 8; + + xfbStride += outsig[i].compCount * compByteSize; + } + + std::set vars; + + for(size_t i = 0; i < outpatch.size(); i++) + { + if(outpatch[i].ID && !outpatch[i].isArraySubsequentElement && + vars.find(outpatch[i].ID) == vars.end()) + { + editor.AddDecoration(rdcspv::Operation( + spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationXfbBuffer, 0})); + editor.AddDecoration(rdcspv::Operation( + spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationXfbStride, xfbStride})); + vars.insert(outpatch[i].ID); + } + } +} diff --git a/renderdoc/driver/shaders/spirv/spirv_reflect.h b/renderdoc/driver/shaders/spirv/spirv_reflect.h index 7c5458eec..1921faa2e 100644 --- a/renderdoc/driver/shaders/spirv/spirv_reflect.h +++ b/renderdoc/driver/shaders/spirv/spirv_reflect.h @@ -128,3 +128,7 @@ struct SpecConstant void FillSpecConstantVariables(const rdcarray &invars, rdcarray &outvars, const std::vector &specInfo); + +// common function used by any API that utilises SPIR-V +void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData &patchData, + const char *entryName, std::vector &modSpirv, uint32_t &xfbStride); \ No newline at end of file diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index 36e062a1b..be3b80837 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -1160,138 +1160,6 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } } -static void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData &patchData, - const char *entryName, std::vector &modSpirv, - uint32_t &xfbStride) -{ - SPIRVEditor editor(modSpirv); - - rdcarray outsig = refl.outputSignature; - std::vector outpatch = patchData.outputs; - - rdcspv::Id entryid; - for(const SPIRVEntry &entry : editor.GetEntries()) - { - if(entry.name == entryName) - { - entryid = entry.id; - break; - } - } - - bool hasXFB = false; - - for(rdcspv::Iter it = editor.Begin(SPIRVSection::ExecutionMode); - it < editor.End(SPIRVSection::ExecutionMode); ++it) - { - if(it.opcode() == spv::OpExecutionMode && rdcspv::Id::fromWord(it.word(1)) == entryid && - it.word(2) == spv::ExecutionModeXfb) - { - hasXFB = true; - break; - } - } - - if(hasXFB) - { - for(rdcspv::Iter it = editor.Begin(SPIRVSection::Annotations); - it < editor.End(SPIRVSection::Annotations); ++it) - { - // remove any existing xfb decorations - if(it.opcode() == spv::OpDecorate && - (it.word(2) == spv::DecorationXfbBuffer || it.word(2) == spv::DecorationXfbStride)) - { - editor.Remove(it); - } - - // offset is trickier, need to see if it'll match one we want later - if((it.opcode() == spv::OpDecorate && it.word(2) == spv::DecorationOffset) || - (it.opcode() == spv::OpMemberDecorate && it.word(3) == spv::DecorationOffset)) - { - for(size_t i = 0; i < outsig.size(); i++) - { - if(outpatch[i].structID && !outpatch[i].accessChain.empty()) - { - if(it.opcode() == spv::OpMemberDecorate && it.word(1) == outpatch[i].structID && - it.word(2) == outpatch[i].accessChain.back()) - { - editor.Remove(it); - } - } - else - { - if(it.opcode() == spv::OpDecorate && it.word(1) == outpatch[i].ID) - { - editor.Remove(it); - } - } - } - } - } - } - else - { - editor.AddExecutionMode(entryid, spv::ExecutionModeXfb); - } - - editor.AddCapability(spv::CapabilityTransformFeedback); - - // find the position output and move it to the front - for(size_t i = 0; i < outsig.size(); i++) - { - if(outsig[i].systemValue == ShaderBuiltin::Position) - { - outsig.insert(0, outsig[i]); - outsig.erase(i + 1); - - outpatch.insert(outpatch.begin(), outpatch[i]); - outpatch.erase(outpatch.begin() + i + 1); - break; - } - } - - for(size_t i = 0; i < outsig.size(); i++) - { - if(outpatch[i].isArraySubsequentElement) - { - // do not patch anything as we only patch the base array, but reserve space in the stride - } - else if(outpatch[i].structID && !outpatch[i].accessChain.empty()) - { - editor.AddDecoration(rdcspv::Operation( - spv::OpMemberDecorate, - {outpatch[i].structID, outpatch[i].accessChain.back(), spv::DecorationOffset, xfbStride})); - } - else if(outpatch[i].ID) - { - editor.AddDecoration(rdcspv::Operation( - spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationOffset, xfbStride})); - } - - uint32_t compByteSize = 4; - - if(outsig[i].compType == CompType::Double) - compByteSize = 8; - - xfbStride += outsig[i].compCount * compByteSize; - } - - std::set vars; - - for(size_t i = 0; i < outpatch.size(); i++) - { - if(outpatch[i].ID && !outpatch[i].isArraySubsequentElement && - vars.find(outpatch[i].ID) == vars.end()) - { - editor.AddDecoration(rdcspv::Operation( - spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationXfbBuffer, 0})); - editor.AddDecoration(rdcspv::Operation( - spv::OpDecorate, {outpatch[i].ID, (uint32_t)spv::DecorationXfbStride, xfbStride})); - vars.insert(outpatch[i].ID); - } - } -} - void VulkanReplay::ClearPostVSCache() { VkDevice dev = m_Device;