diff --git a/renderdoc/driver/shaders/spirv/spirv_editor.cpp b/renderdoc/driver/shaders/spirv/spirv_editor.cpp index 57ad314f4..d65d32729 100644 --- a/renderdoc/driver/shaders/spirv/spirv_editor.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_editor.cpp @@ -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 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) diff --git a/renderdoc/driver/shaders/spirv/spirv_editor.h b/renderdoc/driver/shaders/spirv/spirv_editor.h index 75abd86e9..1fbae226d 100644 --- a/renderdoc/driver/shaders/spirv/spirv_editor.h +++ b/renderdoc/driver/shaders/spirv/spirv_editor.h @@ -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 sampledImageTypeToId; std::map functionTypeToId; + StorageClass m_StorageBufferClass = rdcspv::StorageClass::Uniform; + template std::map &GetTable(); diff --git a/renderdoc/driver/vulkan/vk_bindless_feedback.cpp b/renderdoc/driver/vulkan/vk_bindless_feedback.cpp index f96b01fec..d8c9f0540 100644 --- a/renderdoc/driver/vulkan/vk_bindless_feedback.cpp +++ b/renderdoc/driver/vulkan/vk_bindless_feedback.cpp @@ -118,9 +118,8 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, { rdcspv::Id id = varLookup[var.id] = editor.AddConstantImmediate(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(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(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(0U); diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index 80c5b5aec..6f43ebdad 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -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(); - 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(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;