Move AddXFBAnnotations into common SPIR-V code so it can be shared

This commit is contained in:
baldurk
2019-06-07 18:45:57 +01:00
parent c15693d149
commit 48d854365d
3 changed files with 136 additions and 132 deletions
@@ -24,6 +24,7 @@
#include "spirv_reflect.h"
#include "replay/replay_driver.h"
#include "spirv_editor.h"
void FillSpecConstantVariables(const rdcarray<ShaderConstant> &invars,
rdcarray<ShaderVariable> &outvars,
@@ -52,3 +53,134 @@ void FillSpecConstantVariables(const rdcarray<ShaderConstant> &invars,
}
}
}
void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData &patchData,
const char *entryName, std::vector<uint32_t> &modSpirv, uint32_t &xfbStride)
{
SPIRVEditor editor(modSpirv);
rdcarray<SigParameter> outsig = refl.outputSignature;
std::vector<SPIRVPatchData::InterfaceAccess> 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<uint32_t> 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);
}
}
}
@@ -128,3 +128,7 @@ struct SpecConstant
void FillSpecConstantVariables(const rdcarray<ShaderConstant> &invars,
rdcarray<ShaderVariable> &outvars,
const std::vector<SpecConstant> &specInfo);
// common function used by any API that utilises SPIR-V
void AddXFBAnnotations(const ShaderReflection &refl, const SPIRVPatchData &patchData,
const char *entryName, std::vector<uint32_t> &modSpirv, uint32_t &xfbStride);
-132
View File
@@ -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<uint32_t> &modSpirv,
uint32_t &xfbStride)
{
SPIRVEditor editor(modSpirv);
rdcarray<SigParameter> outsig = refl.outputSignature;
std::vector<SPIRVPatchData::InterfaceAccess> 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<uint32_t> 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;