diff --git a/renderdoc/driver/shaders/spirv/spirv_common.h b/renderdoc/driver/shaders/spirv/spirv_common.h index 68b3d838b..f9af0ba6d 100644 --- a/renderdoc/driver/shaders/spirv/spirv_common.h +++ b/renderdoc/driver/shaders/spirv/spirv_common.h @@ -179,6 +179,7 @@ public: return (uint32_t(op) & rdcspv::OpCodeMask) | (uint16_t(WordCount) << rdcspv::WordCountShift); } + ConstIter AsIter() const { return iter; } private: // everything is based around this iterator, which may point into our local storage or to external // storage. diff --git a/renderdoc/driver/shaders/spirv/spirv_editor.cpp b/renderdoc/driver/shaders/spirv/spirv_editor.cpp index d65d32729..ddb88a5f4 100644 --- a/renderdoc/driver/shaders/spirv/spirv_editor.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_editor.cpp @@ -54,6 +54,12 @@ Scalar::Scalar(Iter it) } } +Id OperationList::add(const rdcspv::Operation &op) +{ + push_back(op); + return OpDecoder(op.AsIter()).result; +} + Editor::Editor(rdcarray &spirvWords) : m_ExternalSPIRV(spirvWords) { } @@ -307,12 +313,12 @@ Id Editor::AddConstant(const Operation &op) return id; } -void Editor::AddFunction(const Operation *ops, size_t count) +void Editor::AddFunction(const OperationList &ops) { size_t offset = m_SPIRV.size(); - for(size_t i = 0; i < count; i++) - ops[i].appendTo(m_SPIRV); + for(const Operation &op : ops) + op.appendTo(m_SPIRV); RegisterOp(Iter(m_SPIRV, offset)); } @@ -351,16 +357,18 @@ Id Editor::DeclareStructType(const rdcarray &members) return typeId; } -void Editor::AddOperation(Iter iter, const Operation &op) +Id Editor::AddOperation(Iter iter, const Operation &op) { if(!iter) - return; + return Id(); // add op op.insertInto(m_SPIRV, iter.offs()); // update offsets addWords(iter.offs(), op.size()); + + return OpDecoder(iter).result; } void Editor::RegisterOp(Iter it) diff --git a/renderdoc/driver/shaders/spirv/spirv_editor.h b/renderdoc/driver/shaders/spirv/spirv_editor.h index 1fbae226d..a11bd04a9 100644 --- a/renderdoc/driver/shaders/spirv/spirv_editor.h +++ b/renderdoc/driver/shaders/spirv/spirv_editor.h @@ -34,6 +34,12 @@ namespace rdcspv { class Editor; +struct OperationList : public rdcarray +{ + // add an operation and return its result id + Id add(const rdcspv::Operation &op); +}; + struct Binding { Binding() = default; @@ -68,7 +74,7 @@ public: Id MakeId(); - void AddOperation(Iter iter, const Operation &op); + Id AddOperation(Iter iter, const Operation &op); // callbacks to allow us to update our internal structures over changes @@ -96,7 +102,7 @@ public: Id AddType(const Operation &op); Id AddVariable(const Operation &op); Id AddConstant(const Operation &op); - void AddFunction(const Operation *ops, size_t count); + void AddFunction(const OperationList &ops); Iter GetID(Id id); // the entry point has 'two' opcodes, the entrypoint declaration and the function. diff --git a/renderdoc/driver/vulkan/vk_bindless_feedback.cpp b/renderdoc/driver/vulkan/vk_bindless_feedback.cpp index d8c9f0540..9ee1afd0e 100644 --- a/renderdoc/driver/vulkan/vk_bindless_feedback.cpp +++ b/renderdoc/driver/vulkan/vk_bindless_feedback.cpp @@ -439,12 +439,9 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, { indexTypeData.signedness = false; - rdcspv::Id unsignedIndex = editor.MakeId(); - editor.AddOperation( - it, rdcspv::OpBitcast(editor.DeclareType(indexTypeData), unsignedIndex, index)); + index = editor.AddOperation( + it, rdcspv::OpBitcast(editor.DeclareType(indexTypeData), editor.MakeId(), index)); it++; - - index = unsignedIndex; } // if it's not wide enough, uconvert expand it @@ -452,11 +449,9 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, { rdcspv::Id extendedtype = editor.DeclareType(rdcspv::Scalar(rdcspv::Op::TypeInt, targetIndexWidth, false)); - rdcspv::Id extendedindex = editor.MakeId(); - editor.AddOperation(it, rdcspv::OpUConvert(extendedtype, extendedindex, index)); + index = + editor.AddOperation(it, rdcspv::OpUConvert(extendedtype, editor.MakeId(), index)); it++; - - index = extendedindex; } } @@ -467,18 +462,14 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, rdcspv::Id clampedtype = editor.DeclareType(rdcspv::Scalar(rdcspv::Op::TypeInt, targetIndexWidth, false)); - rdcspv::Id clampedindex = editor.MakeId(); - - editor.AddOperation( + index = editor.AddOperation( it, rdcspv::Operation( rdcspv::Op::ExtInst, { - clampedtype.value(), clampedindex.value(), glsl450.value(), + clampedtype.value(), editor.MakeId().value(), glsl450.value(), (uint32_t)rdcspv::GLSLstd450::UMin, index.value(), maxSlotID.value(), })); it++; - - index = clampedindex; } rdcspv::Id bufptr; @@ -489,28 +480,26 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // get our output slot address by adding an offset to the base pointer // baseaddr = bufferAddressConst + bindingOffset - rdcspv::Id baseaddr = editor.MakeId(); - editor.AddOperation( - it, rdcspv::OpIAdd(uint64ID, baseaddr, bufferAddressConst, varIt->second)); + rdcspv::Id baseaddr = editor.AddOperation( + it, rdcspv::OpIAdd(uint64ID, editor.MakeId(), bufferAddressConst, varIt->second)); it++; // shift the index since this is a byte offset // shiftedindex = index << uint32shift - rdcspv::Id shiftedindex = editor.MakeId(); - editor.AddOperation( - it, rdcspv::OpShiftLeftLogical(uint64ID, shiftedindex, index, uint32shift)); + rdcspv::Id shiftedindex = editor.AddOperation( + it, rdcspv::OpShiftLeftLogical(uint64ID, editor.MakeId(), index, uint32shift)); it++; // add the index on top of that // offsetaddr = baseaddr + shiftedindex - rdcspv::Id offsetaddr = editor.MakeId(); - editor.AddOperation(it, rdcspv::OpIAdd(uint64ID, offsetaddr, baseaddr, shiftedindex)); + rdcspv::Id offsetaddr = editor.AddOperation( + it, rdcspv::OpIAdd(uint64ID, editor.MakeId(), baseaddr, shiftedindex)); it++; // make a pointer out of it // uint32_t *bufptr = (uint32_t *)offsetaddr - bufptr = editor.MakeId(); - editor.AddOperation(it, rdcspv::OpConvertUToPtr(uint32ptrtype, bufptr, offsetaddr)); + bufptr = editor.AddOperation( + it, rdcspv::OpConvertUToPtr(uint32ptrtype, editor.MakeId(), offsetaddr)); it++; } else @@ -519,16 +508,16 @@ void AnnotateShader(const SPIRVPatchData &patchData, const char *entryName, // add the index to this binding's base index // ssboindex = bindingOffset + index - rdcspv::Id ssboindex = editor.MakeId(); - editor.AddOperation(it, rdcspv::OpIAdd(uint32ID, ssboindex, index, varIt->second)); + rdcspv::Id ssboindex = editor.AddOperation( + it, rdcspv::OpIAdd(uint32ID, editor.MakeId(), index, varIt->second)); it++; // accesschain to get the pointer we'll atomic into. // accesschain is 0 to access rtarray (first member) then ssboindex for array index // uint32_t *bufptr = (uint32_t *)&buf.rtarray[ssboindex]; - bufptr = editor.MakeId(); - editor.AddOperation(it, rdcspv::OpAccessChain(uint32ptrtype, bufptr, ssboVar, - {rtarrayOffset, ssboindex})); + bufptr = + editor.AddOperation(it, rdcspv::OpAccessChain(uint32ptrtype, editor.MakeId(), + ssboVar, {rtarrayOffset, ssboindex})); it++; } diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index 6f43ebdad..20d64d220 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -567,8 +567,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV tbuffers[tb].imageSampledTypeID = editor.DeclareType(rdcspv::SampledImage(tbuffers[tb].imageTypeID)); - rdcspv::Id arrayType = editor.MakeId(); - editor.AddType(rdcspv::OpTypeArray(arrayType, tbuffers[tb].imageSampledTypeID, arraySize)); + rdcspv::Id arrayType = editor.AddType( + rdcspv::OpTypeArray(editor.MakeId(), tbuffers[tb].imageSampledTypeID, arraySize)); rdcspv::Id arrayPtrType = editor.DeclareType(rdcspv::Pointer(arrayType, rdcspv::StorageClass::UniformConstant)); @@ -576,9 +576,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV tbuffers[tb].pointerTypeID = editor.DeclareType( rdcspv::Pointer(tbuffers[tb].imageSampledTypeID, rdcspv::StorageClass::UniformConstant)); - tbuffers[tb].variableID = editor.MakeId(); - editor.AddVariable(rdcspv::OpVariable(arrayPtrType, tbuffers[tb].variableID, - rdcspv::StorageClass::UniformConstant)); + tbuffers[tb].variableID = editor.AddVariable( + rdcspv::OpVariable(arrayPtrType, editor.MakeId(), rdcspv::StorageClass::UniformConstant)); editor.SetName(tbuffers[tb].variableID, name); @@ -604,9 +603,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV rdcspv::Id idxImagePtrType = editor.DeclareType(rdcspv::Pointer(idxSampledTypeID, rdcspv::StorageClass::UniformConstant)); - idxImagePtr = editor.MakeId(); - editor.AddVariable( - rdcspv::OpVariable(idxImagePtrType, idxImagePtr, rdcspv::StorageClass::UniformConstant)); + idxImagePtr = editor.AddVariable(rdcspv::OpVariable(idxImagePtrType, editor.MakeId(), + rdcspv::StorageClass::UniformConstant)); editor.SetName(idxImagePtr, "ibuffer"); @@ -792,22 +790,22 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // add the wrapper function { - rdcarray ops; + rdcspv::OperationList ops; rdcspv::Id voidType = editor.DeclareType(rdcspv::scalar()); rdcspv::Id funcType = editor.DeclareType(rdcspv::FunctionType(voidType, {})); - ops.push_back(rdcspv::OpFunction(voidType, wrapperEntry, rdcspv::FunctionControl::None, funcType)); + ops.add(rdcspv::OpFunction(voidType, wrapperEntry, rdcspv::FunctionControl::None, funcType)); - ops.push_back(rdcspv::OpLabel(editor.MakeId())); + ops.add(rdcspv::OpLabel(editor.MakeId())); { // uint3 invocationVec = gl_GlobalInvocationID; - rdcspv::Id invocationVector = editor.MakeId(); - ops.push_back(rdcspv::OpLoad(uint32Vec3ID, invocationVector, invocationId)); + rdcspv::Id invocationVector = + ops.add(rdcspv::OpLoad(uint32Vec3ID, editor.MakeId(), invocationId)); // uint invocation = invocationVec.x - rdcspv::Id uintInvocationID = editor.MakeId(); - ops.push_back(rdcspv::OpCompositeExtract(uint32ID, uintInvocationID, invocationVector, {0U})); + rdcspv::Id uintInvocationID = + ops.add(rdcspv::OpCompositeExtract(uint32ID, editor.MakeId(), invocationVector, {0U})); // arraySlotID = uintInvocationID; rdcspv::Id arraySlotID = uintInvocationID; @@ -815,39 +813,37 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV editor.SetName(uintInvocationID, "arraySlot"); // uint viewinst = uintInvocationID / numVerts - rdcspv::Id viewinstID = editor.MakeId(); - ops.push_back(rdcspv::OpUDiv(uint32ID, viewinstID, uintInvocationID, numVertsConstID)); + rdcspv::Id viewinstID = + ops.add(rdcspv::OpUDiv(uint32ID, editor.MakeId(), uintInvocationID, numVertsConstID)); editor.SetName(viewinstID, "viewInstance"); - rdcspv::Id instID = editor.MakeId(); - ops.push_back(rdcspv::OpUMod(uint32ID, instID, viewinstID, numInstConstID)); + rdcspv::Id instID = + ops.add(rdcspv::OpUMod(uint32ID, editor.MakeId(), viewinstID, numInstConstID)); editor.SetName(instID, "instanceID"); - rdcspv::Id viewID = editor.MakeId(); - ops.push_back(rdcspv::OpUDiv(uint32ID, viewID, viewinstID, numInstConstID)); + rdcspv::Id viewID = + ops.add(rdcspv::OpUDiv(uint32ID, editor.MakeId(), viewinstID, numInstConstID)); editor.SetName(viewID, "viewID"); // bool inBounds = viewID < numViews; - rdcspv::Id inBounds = editor.MakeId(); - ops.push_back(rdcspv::OpULessThan(editor.DeclareType(rdcspv::scalar()), inBounds, - viewID, numViewsConstID)); + rdcspv::Id inBounds = ops.add(rdcspv::OpULessThan(editor.DeclareType(rdcspv::scalar()), + editor.MakeId(), viewID, numViewsConstID)); // if(inBounds) goto continueLabel; else goto killLabel; rdcspv::Id killLabel = editor.MakeId(); rdcspv::Id continueLabel = editor.MakeId(); - ops.push_back(rdcspv::OpSelectionMerge(killLabel, rdcspv::SelectionControl::None)); - ops.push_back(rdcspv::OpBranchConditional(inBounds, continueLabel, killLabel)); + ops.add(rdcspv::OpSelectionMerge(killLabel, rdcspv::SelectionControl::None)); + ops.add(rdcspv::OpBranchConditional(inBounds, continueLabel, killLabel)); // continueLabel: - ops.push_back(rdcspv::OpLabel(continueLabel)); + ops.add(rdcspv::OpLabel(continueLabel)); // uint vtx = uintInvocationID % numVerts - rdcspv::Id vtxID = editor.MakeId(); - ops.push_back(rdcspv::OpUMod(uint32ID, vtxID, uintInvocationID, numVertsConstID)); - + rdcspv::Id vtxID = + ops.add(rdcspv::OpUMod(uint32ID, editor.MakeId(), uintInvocationID, numVertsConstID)); editor.SetName(vtxID, "vertexID"); rdcspv::Id vertexIndexID = vtxID; @@ -857,20 +853,17 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV if(draw->flags & DrawFlags::Indexed) { // sampledimage idximg = *idximgPtr; - rdcspv::Id loaded = editor.MakeId(); - ops.push_back(rdcspv::OpLoad(idxSampledTypeID, loaded, idxImagePtr)); + rdcspv::Id loaded = ops.add(rdcspv::OpLoad(idxSampledTypeID, editor.MakeId(), idxImagePtr)); // image rawimg = imageFromSampled(idximg); - rdcspv::Id rawimg = editor.MakeId(); - ops.push_back(rdcspv::OpImage(idxImageTypeID, rawimg, loaded)); + rdcspv::Id rawimg = ops.add(rdcspv::OpImage(idxImageTypeID, editor.MakeId(), loaded)); // uvec4 result = texelFetch(rawimg, vtxID); - rdcspv::Id result = editor.MakeId(); - ops.push_back(rdcspv::OpImageFetch(uint32Vec4ID, result, rawimg, vertexIndexID)); + rdcspv::Id result = + ops.add(rdcspv::OpImageFetch(uint32Vec4ID, editor.MakeId(), rawimg, vertexIndexID)); // vertexIndex = result.x; - vertexIndexID = editor.MakeId(); - ops.push_back(rdcspv::OpCompositeExtract(uint32ID, vertexIndexID, result, {0})); + vertexIndexID = ops.add(rdcspv::OpCompositeExtract(uint32ID, editor.MakeId(), result, {0})); } // we use the current value of vertexIndex and use instID, to lookup per-vertex and @@ -884,16 +877,16 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { // for non-indexed draws, we manually apply the vertex offset, but here after we used the // 0-based one to calculate the array slot - vertexIndexID = editor.MakeId(); - ops.push_back(rdcspv::OpIAdd(uint32ID, vertexIndexID, vtxID, - editor.AddConstantImmediate(draw->vertexOffset))); + vertexIndexID = + ops.add(rdcspv::OpIAdd(uint32ID, editor.MakeId(), vtxID, + editor.AddConstantImmediate(draw->vertexOffset))); } editor.SetName(vertexIndexID, "vertexIndex"); // instIndex = inst + instOffset - rdcspv::Id instIndexID = editor.MakeId(); - ops.push_back(rdcspv::OpIAdd(uint32ID, instIndexID, instID, - editor.AddConstantImmediate(draw->instanceOffset))); + rdcspv::Id instIndexID = + ops.add(rdcspv::OpIAdd(uint32ID, editor.MakeId(), instID, + editor.AddConstantImmediate(draw->instanceOffset))); editor.SetName(instIndexID, "instanceIndex"); rdcspv::Id idxs[64] = {}; @@ -953,14 +946,14 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV { if(refl.inputSignature[i].compType == compType) { - ops.push_back(rdcspv::OpStore(ins[i].variableID, valueID)); + ops.add(rdcspv::OpStore(ins[i].variableID, valueID)); } else { - rdcspv::Id castedValue = editor.MakeId(); // assume we can just bitcast - ops.push_back(rdcspv::OpBitcast(ins[i].basetypeID, castedValue, valueID)); - ops.push_back(rdcspv::OpStore(ins[i].variableID, castedValue)); + rdcspv::Id castedValue = + ops.add(rdcspv::OpBitcast(ins[i].basetypeID, editor.MakeId(), valueID)); + ops.add(rdcspv::OpStore(ins[i].variableID, castedValue)); } } else @@ -981,18 +974,16 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV uint32_t location = refl.inputSignature[i].regIndex; - rdcspv::Id ptrId = editor.MakeId(); // sampledimage *imgPtr = xxx_tbuffers[i]; - ops.push_back(rdcspv::OpAccessChain(tb.pointerTypeID, ptrId, tb.variableID, - {idxs[refl.inputSignature[i].regIndex]})); + rdcspv::Id ptrId = + ops.add(rdcspv::OpAccessChain(tb.pointerTypeID, editor.MakeId(), tb.variableID, + {idxs[refl.inputSignature[i].regIndex]})); // sampledimage img = *imgPtr; - rdcspv::Id loaded = editor.MakeId(); - ops.push_back(rdcspv::OpLoad(tb.imageSampledTypeID, loaded, ptrId)); + rdcspv::Id loaded = ops.add(rdcspv::OpLoad(tb.imageSampledTypeID, editor.MakeId(), ptrId)); // image rawimg = imageFromSampled(img); - rdcspv::Id rawimg = editor.MakeId(); - ops.push_back(rdcspv::OpImage(tb.imageTypeID, rawimg, loaded)); + rdcspv::Id rawimg = ops.add(rdcspv::OpImage(tb.imageTypeID, editor.MakeId(), loaded)); // vec4 result = texelFetch(rawimg, vtxID or instID); rdcspv::Id idx = vertexLookupID; @@ -1019,23 +1010,20 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV else { // otherwise we divide by the divisor - idx = editor.MakeId(); rdcspv::Id divisorId = editor.AddConstantImmediate(divisor); - ops.push_back(rdcspv::OpUDiv(uint32ID, idx, instanceLookupID, divisorId)); + idx = ops.add(rdcspv::OpUDiv(uint32ID, editor.MakeId(), instanceLookupID, divisorId)); } } if(refl.inputSignature[i].compType == CompType::Double) { // since doubles are packed into two uints, we need to multiply the index by two - rdcspv::Id doubled = editor.MakeId(); - ops.push_back( - rdcspv::OpIMul(uint32ID, doubled, idx, editor.AddConstantImmediate(2))); - idx = doubled; + idx = ops.add(rdcspv::OpIMul(uint32ID, editor.MakeId(), idx, + editor.AddConstantImmediate(2))); } - rdcspv::Id result = editor.MakeId(); - ops.push_back(rdcspv::OpImageFetch(ins[i].vec4ID, result, rawimg, idx)); + rdcspv::Id result = + ops.add(rdcspv::OpImageFetch(ins[i].vec4ID, editor.MakeId(), rawimg, idx)); if(refl.inputSignature[i].compType == CompType::Double) { @@ -1043,12 +1031,11 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // packing. We can fetch the data unconditionally since it's harmless to read out of the // bounds of the buffer - rdcspv::Id nextidx = editor.MakeId(); - ops.push_back( - rdcspv::OpIAdd(uint32ID, nextidx, idx, editor.AddConstantImmediate(1))); + rdcspv::Id nextidx = ops.add(rdcspv::OpIAdd(uint32ID, editor.MakeId(), idx, + editor.AddConstantImmediate(1))); - rdcspv::Id result2 = editor.MakeId(); - ops.push_back(rdcspv::OpImageFetch(ins[i].vec4ID, result2, rawimg, nextidx)); + rdcspv::Id result2 = + ops.add(rdcspv::OpImageFetch(ins[i].vec4ID, editor.MakeId(), rawimg, nextidx)); rdcspv::Id glsl450 = editor.ImportExtInst("GLSL.std.450"); @@ -1058,22 +1045,20 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV for(uint32_t c = 0; c < refl.inputSignature[i].compCount; c++) { // first extract the uvec2 we want - rdcspv::Id packed = editor.MakeId(); // uvec2 packed = result.[xy/zw] / result2.[xy/zw]; - ops.push_back(rdcspv::OpVectorShuffle(uvec2Type, packed, result, result2, - {c * 2 + 0, c * 2 + 1})); + rdcspv::Id packed = ops.add(rdcspv::OpVectorShuffle( + uvec2Type, editor.MakeId(), result, result2, {c * 2 + 0, c * 2 + 1})); char swizzle[] = "xyzw"; editor.SetName(packed, StringFormat::Fmt("packed_%c", swizzle[c])); // double comp = PackDouble2x32(packed); - comps[c] = editor.MakeId(); - ops.push_back(rdcspv::Operation( + comps[c] = ops.add(rdcspv::Operation( rdcspv::Op::ExtInst, { - editor.DeclareType(rdcspv::scalar()).value(), comps[c].value(), + editor.DeclareType(rdcspv::scalar()).value(), editor.MakeId().value(), glsl450.value(), (uint32_t)rdcspv::GLSLstd450::PackDouble2x32, packed.value(), })); } @@ -1085,32 +1070,26 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } else { - result = editor.MakeId(); - rdcarray ids; for(uint32_t c = 0; c < refl.inputSignature[i].compCount; c++) ids.push_back(comps[c]); // baseTypeN value = result.xyz; - ops.push_back(rdcspv::OpCompositeConstruct(ins[i].basetypeID, result, ids)); + result = ops.add(rdcspv::OpCompositeConstruct(ins[i].basetypeID, editor.MakeId(), ids)); } } else if(refl.inputSignature[i].compCount == 1) { // for one component, extract x - rdcspv::Id swizzleIn = result; - result = editor.MakeId(); - // baseType value = result.x; - ops.push_back(rdcspv::OpCompositeExtract(ins[i].basetypeID, result, swizzleIn, {0})); + result = + ops.add(rdcspv::OpCompositeExtract(ins[i].basetypeID, editor.MakeId(), result, {0})); } else if(refl.inputSignature[i].compCount != 4) { // for less than 4 components, extract the sub-vector - rdcspv::Id swizzleIn = result; - result = editor.MakeId(); rdcarray swizzle; @@ -1118,8 +1097,8 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV swizzle.push_back(c); // baseTypeN value = result.xyz; - ops.push_back( - rdcspv::OpVectorShuffle(ins[i].basetypeID, result, swizzleIn, swizzleIn, swizzle)); + result = ops.add(rdcspv::OpVectorShuffle(ins[i].basetypeID, editor.MakeId(), result, + result, swizzle)); } // copy the 4 component result directly @@ -1128,12 +1107,11 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV if(patchData.inputs[i].accessChain.empty()) { // *global = value - ops.push_back(rdcspv::OpStore(ins[i].variableID, result)); + ops.add(rdcspv::OpStore(ins[i].variableID, result)); } else { // for composite types we need to access chain first - rdcspv::Id subElement = editor.MakeId(); rdcarray chain; for(uint32_t accessIdx : patchData.inputs[i].accessChain) @@ -1144,16 +1122,16 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV chain.push_back(idxs[accessIdx]); } - ops.push_back(rdcspv::OpAccessChain(ins[i].privatePtrID, subElement, - patchData.inputs[i].ID, chain)); + rdcspv::Id subElement = ops.add(rdcspv::OpAccessChain( + ins[i].privatePtrID, editor.MakeId(), patchData.inputs[i].ID, chain)); - ops.push_back(rdcspv::OpStore(subElement, result)); + ops.add(rdcspv::OpStore(subElement, result)); } } } // real_main(); - ops.push_back(rdcspv::OpFunctionCall(voidType, editor.MakeId(), entryID)); + ops.add(rdcspv::OpFunctionCall(voidType, editor.MakeId(), entryID)); rdcspv::Id zero = editor.AddConstantImmediate(0); @@ -1164,15 +1142,12 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV // not a structure member or array child, can load directly if(patchData.outputs[o].accessChain.empty()) { - loaded = editor.MakeId(); // type loaded = *globalvar; - ops.push_back(rdcspv::OpLoad(outs[o].basetypeID, loaded, patchData.outputs[o].ID)); + loaded = + ops.add(rdcspv::OpLoad(outs[o].basetypeID, editor.MakeId(), patchData.outputs[o].ID)); } else { - rdcspv::Id readPtr = editor.MakeId(); - loaded = editor.MakeId(); - // structure member, need to access chain first rdcarray chain; @@ -1185,33 +1160,33 @@ static void ConvertToMeshOutputCompute(const ShaderReflection &refl, const SPIRV } // type *readPtr = globalvar.globalsub...; - ops.push_back( - rdcspv::OpAccessChain(outs[o].privatePtrID, readPtr, patchData.outputs[o].ID, chain)); + rdcspv::Id readPtr = ops.add(rdcspv::OpAccessChain(outs[o].privatePtrID, editor.MakeId(), + patchData.outputs[o].ID, chain)); // type loaded = *readPtr; - ops.push_back(rdcspv::OpLoad(outs[o].basetypeID, loaded, readPtr)); + loaded = ops.add(rdcspv::OpLoad(outs[o].basetypeID, editor.MakeId(), readPtr)); } // access chain the destination // type *writePtr = outBuffer.verts[arraySlot].outputN - rdcspv::Id writePtr = editor.MakeId(); - ops.push_back(rdcspv::OpAccessChain(outs[o].ssboPtrID, writePtr, outBufferVarID, - {zero, arraySlotID, outs[o].constID})); + rdcspv::Id writePtr = + ops.add(rdcspv::OpAccessChain(outs[o].ssboPtrID, editor.MakeId(), outBufferVarID, + {zero, arraySlotID, outs[o].constID})); // *writePtr = loaded; - ops.push_back(rdcspv::OpStore(writePtr, loaded)); + ops.add(rdcspv::OpStore(writePtr, loaded)); } // goto killLabel; - ops.push_back(rdcspv::OpBranch(killLabel)); + ops.add(rdcspv::OpBranch(killLabel)); // killLabel: - ops.push_back(rdcspv::OpLabel(killLabel)); + ops.add(rdcspv::OpLabel(killLabel)); } - ops.push_back(rdcspv::OpReturn()); + ops.add(rdcspv::OpReturn()); - ops.push_back(rdcspv::OpFunctionEnd()); + ops.add(rdcspv::OpFunctionEnd()); - editor.AddFunction(ops.data(), ops.size()); + editor.AddFunction(ops); } } diff --git a/renderdoc/driver/vulkan/vk_shaderdebug.cpp b/renderdoc/driver/vulkan/vk_shaderdebug.cpp index 5bca3f0fc..28a070bff 100644 --- a/renderdoc/driver/vulkan/vk_shaderdebug.cpp +++ b/renderdoc/driver/vulkan/vk_shaderdebug.cpp @@ -569,31 +569,30 @@ static void CreatePSInputFetcher(rdcarray &fragspv, uint32_t &structSt rdcspv::Id glsl450 = editor.ImportExtInst("GLSL.std.450"); { - rdcarray ops; + rdcspv::OperationList ops; rdcspv::Id voidType = editor.DeclareType(rdcspv::scalar()); - ops.push_back(rdcspv::OpFunction(voidType, entryID, rdcspv::FunctionControl::None, - editor.DeclareType(rdcspv::FunctionType(voidType, {})))); + ops.add(rdcspv::OpFunction(voidType, entryID, rdcspv::FunctionControl::None, + editor.DeclareType(rdcspv::FunctionType(voidType, {})))); - ops.push_back(rdcspv::OpLabel(editor.MakeId())); + ops.add(rdcspv::OpLabel(editor.MakeId())); { rdcspv::Id structPtr = ssboVar; if(structPtr == rdcspv::Id()) { // if we don't have the struct as a bind, we need to cast it from the pointer - structPtr = editor.MakeId(); - ops.push_back(rdcspv::OpConvertUToPtr(bufptrtype, structPtr, addressConstant)); + structPtr = ops.add(rdcspv::OpConvertUToPtr(bufptrtype, editor.MakeId(), addressConstant)); editor.SetName(structPtr, "HitBuffer"); } rdcspv::Id uintPtr = editor.DeclareType(rdcspv::Pointer(uint32Type, bufferClass)); - rdcspv::Id hit_count = editor.MakeId(); // get a pointer to buffer.hit_count - ops.push_back(rdcspv::OpAccessChain(uintPtr, hit_count, structPtr, {uintConsts[0]})); + rdcspv::Id hit_count = + ops.add(rdcspv::OpAccessChain(uintPtr, editor.MakeId(), structPtr, {uintConsts[0]})); rdcspv::Id scope = editor.AddConstantImmediate((uint32_t)rdcspv::Scope::Device); rdcspv::Id semantics = @@ -603,32 +602,30 @@ static void CreatePSInputFetcher(rdcarray &fragspv, uint32_t &structSt rdcspv::Id fragCoordLoaded = editor.MakeId(); if(fragCoord.member == ~0U) { - ops.push_back(rdcspv::OpLoad(float4Type, fragCoordLoaded, fragCoord.base)); + ops.add(rdcspv::OpLoad(float4Type, fragCoordLoaded, fragCoord.base)); } else { - rdcspv::Id posptr = editor.MakeId(); - ops.push_back(rdcspv::OpAccessChain(float4InPtr, posptr, fragCoord.base, - {editor.AddConstantImmediate(fragCoord.member)})); - ops.push_back(rdcspv::OpLoad(float4Type, fragCoordLoaded, posptr)); + rdcspv::Id posptr = + ops.add(rdcspv::OpAccessChain(float4InPtr, editor.MakeId(), fragCoord.base, + {editor.AddConstantImmediate(fragCoord.member)})); + ops.add(rdcspv::OpLoad(float4Type, fragCoordLoaded, posptr)); } rdcspv::Id bool2Type = editor.DeclareType(rdcspv::Vector(rdcspv::scalar(), 2)); // grab x and y - rdcspv::Id fragXY = editor.MakeId(); - ops.push_back( - rdcspv::OpVectorShuffle(float2Type, fragXY, fragCoordLoaded, fragCoordLoaded, {0, 1})); + rdcspv::Id fragXY = ops.add(rdcspv::OpVectorShuffle( + float2Type, editor.MakeId(), fragCoordLoaded, fragCoordLoaded, {0, 1})); // subtract from the destination co-ord - rdcspv::Id fragXYRelative = editor.MakeId(); - ops.push_back(rdcspv::OpFSub(float2Type, fragXYRelative, fragXY, destXY)); + rdcspv::Id fragXYRelative = + ops.add(rdcspv::OpFSub(float2Type, editor.MakeId(), fragXY, destXY)); // abs() - rdcspv::Id fragXYAbs = editor.MakeId(); - ops.push_back(rdcspv::Operation( + rdcspv::Id fragXYAbs = ops.add(rdcspv::Operation( rdcspv::Op::ExtInst, { - float2Type.value(), fragXYAbs.value(), glsl450.value(), + float2Type.value(), editor.MakeId().value(), glsl450.value(), (uint32_t)rdcspv::GLSLstd450::FAbs, fragXYRelative.value(), })); @@ -637,66 +634,62 @@ static void CreatePSInputFetcher(rdcarray &fragspv, uint32_t &structSt editor.AddConstant(rdcspv::OpConstantComposite(float2Type, editor.MakeId(), {half, half})); // less than 0.5 - rdcspv::Id inPixelXY = editor.MakeId(); - ops.push_back(rdcspv::OpFOrdLessThan(bool2Type, inPixelXY, fragXYAbs, threshold)); + rdcspv::Id inPixelXY = + ops.add(rdcspv::OpFOrdLessThan(bool2Type, editor.MakeId(), fragXYAbs, threshold)); // both less than 0.5 - rdcspv::Id inPixel = editor.MakeId(); - ops.push_back(rdcspv::OpAll(boolType, inPixel, inPixelXY)); + rdcspv::Id inPixel = ops.add(rdcspv::OpAll(boolType, editor.MakeId(), inPixelXY)); // bool inPixel = all(abs(gl_FragCoord.xy - dest.xy) < 0.5f); rdcspv::Id killLabel = editor.MakeId(); rdcspv::Id continueLabel = editor.MakeId(); - ops.push_back(rdcspv::OpSelectionMerge(killLabel, rdcspv::SelectionControl::None)); - ops.push_back(rdcspv::OpBranchConditional(inPixel, continueLabel, killLabel)); - ops.push_back(rdcspv::OpLabel(continueLabel)); + ops.add(rdcspv::OpSelectionMerge(killLabel, rdcspv::SelectionControl::None)); + ops.add(rdcspv::OpBranchConditional(inPixel, continueLabel, killLabel)); + ops.add(rdcspv::OpLabel(continueLabel)); // allocate a slot with atomic add - rdcspv::Id slot = editor.MakeId(); - ops.push_back( - rdcspv::OpAtomicIAdd(uint32Type, slot, hit_count, scope, semantics, uintConsts[1])); + rdcspv::Id slot = ops.add(rdcspv::OpAtomicIAdd(uint32Type, editor.MakeId(), hit_count, scope, + semantics, uintConsts[1])); editor.SetName(slot, "slot"); - rdcspv::Id inRange = editor.MakeId(); - ops.push_back(rdcspv::OpULessThan(boolType, inRange, slot, arrayLength)); + rdcspv::Id inRange = ops.add(rdcspv::OpULessThan(boolType, editor.MakeId(), slot, arrayLength)); rdcspv::Id killLabel2 = editor.MakeId(); continueLabel = editor.MakeId(); - ops.push_back(rdcspv::OpSelectionMerge(killLabel2, rdcspv::SelectionControl::None)); - ops.push_back(rdcspv::OpBranchConditional(inRange, continueLabel, killLabel2)); - ops.push_back(rdcspv::OpLabel(continueLabel)); + ops.add(rdcspv::OpSelectionMerge(killLabel2, rdcspv::SelectionControl::None)); + ops.add(rdcspv::OpBranchConditional(inRange, continueLabel, killLabel2)); + ops.add(rdcspv::OpLabel(continueLabel)); rdcspv::Id hitptr = editor.DeclareType(rdcspv::Pointer(PSHit, bufferClass)); // get a pointer to the hit for our slot - rdcspv::Id hit = editor.MakeId(); - ops.push_back(rdcspv::OpAccessChain(hitptr, hit, structPtr, {uintConsts[1], slot})); + rdcspv::Id hit = + ops.add(rdcspv::OpAccessChain(hitptr, editor.MakeId(), structPtr, {uintConsts[1], slot})); // store fixed properties rdcspv::MemoryAccessAndParamDatas alignedAccess; alignedAccess.setAligned(sizeof(uint32_t)); - rdcspv::Id storePtr = editor.MakeId(); - ops.push_back(rdcspv::OpAccessChain(float4BufPtr, storePtr, hit, {uintConsts[0]})); - ops.push_back(rdcspv::OpStore(storePtr, fragCoordLoaded, alignedAccess)); + rdcspv::Id storePtr = + ops.add(rdcspv::OpAccessChain(float4BufPtr, editor.MakeId(), hit, {uintConsts[0]})); + ops.add(rdcspv::OpStore(storePtr, fragCoordLoaded, alignedAccess)); - rdcspv::Id loaded = editor.MakeId(); + rdcspv::Id loaded; if(primitiveID.base != rdcspv::Id()) { - loaded = editor.MakeId(); if(primitiveID.member == ~0U) { - ops.push_back(rdcspv::OpLoad(uint32Type, loaded, primitiveID.base)); + loaded = ops.add(rdcspv::OpLoad(uint32Type, editor.MakeId(), primitiveID.base)); } else { - rdcspv::Id posptr = editor.MakeId(); - ops.push_back(rdcspv::OpAccessChain(uint32InPtr, posptr, primitiveID.base, - {editor.AddConstantImmediate(primitiveID.member)})); - ops.push_back(rdcspv::OpLoad(uint32Type, loaded, posptr)); + rdcspv::Id posptr = + ops.add(rdcspv::OpAccessChain(uint32InPtr, editor.MakeId(), primitiveID.base, + {editor.AddConstantImmediate(primitiveID.member)})); + loaded = ops.add(rdcspv::OpLoad(uint32Type, editor.MakeId(), posptr)); } } else @@ -705,23 +698,21 @@ static void CreatePSInputFetcher(rdcarray &fragspv, uint32_t &structSt loaded = uintConsts[0]; } - storePtr = editor.MakeId(); - ops.push_back(rdcspv::OpAccessChain(uint32BufPtr, storePtr, hit, {uintConsts[1]})); - ops.push_back(rdcspv::OpStore(storePtr, loaded, alignedAccess)); + storePtr = ops.add(rdcspv::OpAccessChain(uint32BufPtr, editor.MakeId(), hit, {uintConsts[1]})); + ops.add(rdcspv::OpStore(storePtr, loaded, alignedAccess)); if(sampleIndex.base != rdcspv::Id()) { - loaded = editor.MakeId(); if(sampleIndex.member == ~0U) { - ops.push_back(rdcspv::OpLoad(uint32Type, loaded, sampleIndex.base)); + loaded = ops.add(rdcspv::OpLoad(uint32Type, editor.MakeId(), sampleIndex.base)); } else { - rdcspv::Id posptr = editor.MakeId(); - ops.push_back(rdcspv::OpAccessChain(uint32InPtr, posptr, sampleIndex.base, - {editor.AddConstantImmediate(sampleIndex.member)})); - ops.push_back(rdcspv::OpLoad(uint32Type, loaded, posptr)); + rdcspv::Id posptr = + ops.add(rdcspv::OpAccessChain(uint32InPtr, editor.MakeId(), sampleIndex.base, + {editor.AddConstantImmediate(sampleIndex.member)})); + loaded = ops.add(rdcspv::OpLoad(uint32Type, editor.MakeId(), posptr)); } } else @@ -730,24 +721,23 @@ static void CreatePSInputFetcher(rdcarray &fragspv, uint32_t &structSt loaded = uintConsts[0]; } - storePtr = editor.MakeId(); - ops.push_back(rdcspv::OpAccessChain(uint32BufPtr, storePtr, hit, {uintConsts[2]})); - ops.push_back(rdcspv::OpStore(storePtr, loaded, alignedAccess)); + storePtr = ops.add(rdcspv::OpAccessChain(uint32BufPtr, editor.MakeId(), hit, {uintConsts[2]})); + ops.add(rdcspv::OpStore(storePtr, loaded, alignedAccess)); // TODO store custom properties, and derivatives // join up with the early-outs we did - ops.push_back(rdcspv::OpBranch(killLabel2)); - ops.push_back(rdcspv::OpLabel(killLabel2)); - ops.push_back(rdcspv::OpBranch(killLabel)); - ops.push_back(rdcspv::OpLabel(killLabel)); + ops.add(rdcspv::OpBranch(killLabel2)); + ops.add(rdcspv::OpLabel(killLabel2)); + ops.add(rdcspv::OpBranch(killLabel)); + ops.add(rdcspv::OpLabel(killLabel)); } // don't return, kill. This makes it well-defined that we don't write anything to our outputs - ops.push_back(rdcspv::OpKill()); + ops.add(rdcspv::OpKill()); - ops.push_back(rdcspv::OpFunctionEnd()); + ops.add(rdcspv::OpFunctionEnd()); - editor.AddFunction(ops.data(), ops.size()); + editor.AddFunction(ops); } }