Use StorageBuffer storage class when editing 1.3+ SPIR-V modules

This commit is contained in:
baldurk
2020-03-31 15:47:46 +01:00
parent 24ff94ea3c
commit 11a4a8f3d1
4 changed files with 62 additions and 35 deletions
@@ -65,6 +65,11 @@ void Editor::Prepare()
if(m_SPIRV.empty())
return;
// In 1.3 and after we can (and should - it's gone in 1.4+) use the real SSBO storage class
// instead of Uniform + BufferBlock
if(m_MajorVersion > 1 || m_MinorVersion >= 3)
m_StorageBufferClass = rdcspv::StorageClass::StorageBuffer;
// find any empty sections and insert a nop into the stream there. We need to fixup later section
// offsets by hand as addWords doesn't handle empty sections properly (it thinks we're inserting
// into the later section by offset since the offsets overlap). That's why we're adding these
@@ -138,19 +143,38 @@ Id Editor::MakeId()
return Id::fromWord(ret);
}
void Editor::SetName(Id id, const char *name)
void Editor::DecorateStorageBufferStruct(Id id)
{
size_t sz = strlen(name);
rdcarray<uint32_t> uintName((sz / 4) + 1);
memcpy(&uintName[0], name, sz);
// set bufferblock if needed
if(m_StorageBufferClass == rdcspv::StorageClass::Uniform)
AddDecoration(rdcspv::OpDecorate(id, rdcspv::Decoration::BufferBlock));
}
uintName.insert(0, id.value());
Operation op(Op::Name, uintName);
void Editor::SetName(Id id, const rdcstr &name)
{
Operation op = OpName(id, name);
Iter it;
// OpName must be before OpModuleProcessed.
// OpName/OpMemberName must be before OpModuleProcessed.
for(it = Begin(Section::Debug); it < End(Section::Debug); ++it)
{
if(it.opcode() == Op::ModuleProcessed)
break;
}
op.insertInto(m_SPIRV, it.offs());
RegisterOp(Iter(m_SPIRV, it.offs()));
addWords(it.offs(), op.size());
}
void Editor::SetMemberName(Id id, uint32_t member, const rdcstr &name)
{
Operation op = OpMemberName(id, member, name);
Iter it;
// OpName/OpMemberName must be before OpModuleProcessed.
for(it = Begin(Section::Debug); it < End(Section::Debug); ++it)
{
if(it.opcode() == Op::ModuleProcessed)
@@ -84,7 +84,10 @@ public:
iter.nopRemove();
}
void SetName(Id id, const char *name);
StorageClass StorageBufferClass() { return m_StorageBufferClass; }
void DecorateStorageBufferStruct(Id id);
void SetName(Id id, const rdcstr &name);
void SetMemberName(Id id, uint32_t member, const rdcstr &name);
void AddDecoration(const Operation &op);
void AddCapability(Capability cap);
void AddExtension(const rdcstr &extension);
@@ -205,6 +208,8 @@ private:
std::map<SampledImage, Id> sampledImageTypeToId;
std::map<FunctionType, Id> functionTypeToId;
StorageClass m_StorageBufferClass = rdcspv::StorageClass::Uniform;
template <typename SPIRVType>
std::map<SPIRVType, Id> &GetTable();
@@ -118,9 +118,8 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
{
rdcspv::Id id = varLookup[var.id] = editor.AddConstantImmediate<uint64_t>(it->second.offset);
editor.SetName(
id, StringFormat::Fmt("__feedbackOffset_set%u_bind%u", it->first.set, it->first.binding)
.c_str());
editor.SetName(id, StringFormat::Fmt("__feedbackOffset_set%u_bind%u", it->first.set,
it->first.binding));
}
else
{
@@ -130,8 +129,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
rdcspv::Id id = varLookup[var.id] = editor.AddConstantImmediate<uint32_t>(uint32_t(index));
editor.SetName(
id, StringFormat::Fmt("__feedbackIndex_set%u_bind%u", it->first.set, it->first.binding)
.c_str());
id, StringFormat::Fmt("__feedbackIndex_set%u_bind%u", it->first.set, it->first.binding));
}
}
}
@@ -166,10 +164,11 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
}
else
{
// the pointers are uniform pointers
rdcspv::Id bufptrtype =
editor.DeclareType(rdcspv::Pointer(uint32StructID, rdcspv::StorageClass::Uniform));
uint32ptrtype = editor.DeclareType(rdcspv::Pointer(uint32ID, rdcspv::StorageClass::Uniform));
rdcspv::StorageClass ssboClass = editor.StorageBufferClass();
// the pointers are SSBO pointers
rdcspv::Id bufptrtype = editor.DeclareType(rdcspv::Pointer(uint32StructID, ssboClass));
uint32ptrtype = editor.DeclareType(rdcspv::Pointer(uint32ID, ssboClass));
// patch all bindings up by 1
for(rdcspv::Iter it = editor.Begin(rdcspv::Section::Annotations),
@@ -197,7 +196,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
// add our SSBO variable, at set 0 binding 0
ssboVar = editor.MakeId();
editor.AddVariable(rdcspv::OpVariable(bufptrtype, ssboVar, rdcspv::StorageClass::Uniform));
editor.AddVariable(rdcspv::OpVariable(bufptrtype, ssboVar, ssboClass));
editor.AddDecoration(
rdcspv::OpDecorate(ssboVar, rdcspv::DecorationParam<rdcspv::Decoration::DescriptorSet>(0)));
editor.AddDecoration(
@@ -205,8 +204,7 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName,
editor.SetName(ssboVar, "__rd_feedbackBuffer");
// struct is bufferblock decorated
editor.AddDecoration(rdcspv::OpDecorate(uint32StructID, rdcspv::Decoration::BufferBlock));
editor.DecorateStorageBufferStruct(uint32StructID);
}
rdcspv::Id rtarrayOffset = editor.AddConstantImmediate<uint32_t>(0U);
+14 -14
View File
@@ -113,7 +113,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// gvec4 type for this input, used as result type when fetching from tbuffer
rdcspv::Id vec4ID;
// Uniform Pointer ID for this output. Used only for output data, to write to output SSBO
rdcspv::Id uniformPtrID;
rdcspv::Id ssboPtrID;
// Output Pointer ID for this attribute.
// For inputs, used to 'write' to the global at the start.
// For outputs, used to 'read' from the global at the end.
@@ -421,7 +421,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
{
editor.Remove(it);
if(typeReplacements.find(name.target) == typeReplacements.end())
editor.SetName(name.target, ("emulated_" + name.name).c_str());
editor.SetName(name.target, "emulated_" + name.name);
}
// remove any OpName for the old entry points
@@ -434,6 +434,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
}
}
rdcspv::StorageClass ssboStorageClass = editor.StorageBufferClass();
// declare necessary variables per-output, types and constants. We do this last so that we don't
// add a private pointer that we later try and deduplicate when collapsing output/input pointers
// to private
@@ -470,13 +472,12 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
io.basetypeID = editor.DeclareType(scalarType);
}
io.uniformPtrID =
editor.DeclareType(rdcspv::Pointer(io.basetypeID, rdcspv::StorageClass::Uniform));
io.ssboPtrID = editor.DeclareType(rdcspv::Pointer(io.basetypeID, ssboStorageClass));
io.privatePtrID =
editor.DeclareType(rdcspv::Pointer(io.basetypeID, rdcspv::StorageClass::Private));
RDCASSERT(io.basetypeID && io.vec4ID && io.constID && io.privatePtrID && io.uniformPtrID,
io.basetypeID, io.vec4ID, io.constID, io.privatePtrID, io.uniformPtrID);
RDCASSERT(io.basetypeID && io.vec4ID && io.constID && io.privatePtrID && io.ssboPtrID,
io.basetypeID, io.vec4ID, io.constID, io.privatePtrID, io.ssboPtrID);
}
// repeat for inputs
@@ -548,7 +549,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
for(tbufferType tb : {tbuffer_float, tbuffer_sint, tbuffer_uint})
{
rdcspv::Scalar scalarType = rdcspv::scalar<float>();
const char *name = "float_vbuffers";
rdcstr name = "float_vbuffers";
if(tb == tbuffer_sint)
{
@@ -650,12 +651,12 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// meshOutput *
rdcspv::Id outputStructPtrID =
editor.DeclareType(rdcspv::Pointer(outputStructID, rdcspv::StorageClass::Uniform));
editor.DeclareType(rdcspv::Pointer(outputStructID, ssboStorageClass));
editor.SetName(outputStructPtrID, "meshOutput_ptr");
// meshOutput *outputData;
outBufferVarID = editor.AddVariable(
rdcspv::OpVariable(outputStructPtrID, editor.MakeId(), rdcspv::StorageClass::Uniform));
outBufferVarID =
editor.AddVariable(rdcspv::OpVariable(outputStructPtrID, editor.MakeId(), ssboStorageClass));
editor.SetName(outBufferVarID, "outputData");
uint32_t memberOffset = 0;
@@ -701,8 +702,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
editor.AddDecoration(rdcspv::OpDecorate(
runtimeArrayID, rdcspv::DecorationParam<rdcspv::Decoration::ArrayStride>(bufStride)));
// set object type
editor.AddDecoration(rdcspv::OpDecorate(outputStructID, rdcspv::Decoration::BufferBlock));
editor.DecorateStorageBufferStruct(outputStructID);
// set binding
editor.AddDecoration(rdcspv::OpDecorate(
@@ -1066,7 +1066,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
char swizzle[] = "xyzw";
editor.SetName(packed, StringFormat::Fmt("packed_%c", swizzle[c]).c_str());
editor.SetName(packed, StringFormat::Fmt("packed_%c", swizzle[c]));
// double comp = PackDouble2x32(packed);
comps[c] = editor.MakeId();
@@ -1194,7 +1194,7 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV
// access chain the destination
// type *writePtr = outBuffer.verts[arraySlot].outputN
rdcspv::Id writePtr = editor.MakeId();
ops.push_back(rdcspv::OpAccessChain(outs[o].uniformPtrID, writePtr, outBufferVarID,
ops.push_back(rdcspv::OpAccessChain(outs[o].ssboPtrID, writePtr, outBufferVarID,
{zero, arraySlotID, outs[o].constID}));
// *writePtr = loaded;