From edc85fc4631782d42e113f00dfbbd113dcd8c96f Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 12 Mar 2024 13:47:14 -0700 Subject: Make type names spec-conformant in SPIRV reflect. (#3748) * Preserve ByteAddressBuffer user type name. * Make user type lowercase. * Make typenames conform to spec. * Use `SpvOpDecorateString`. --- build/visual-studio/slang/slang.vcxproj | 2 ++ build/visual-studio/slang/slang.vcxproj.filters | 6 ++++ source/slang/slang-emit-spirv-ops.h | 4 +-- source/slang/slang-emit-spirv.cpp | 20 ++++++++++++- source/slang/slang-emit.cpp | 3 ++ source/slang/slang-ir-byte-address-legalize.cpp | 2 ++ source/slang/slang-ir-insts.h | 5 ++++ ...g-ir-lower-append-consume-structured-buffer.cpp | 6 ++-- source/slang/slang-ir-spirv-legalize.cpp | 15 ---------- source/slang/slang-ir-user-type-hint.cpp | 34 ++++++++++++++++++++++ source/slang/slang-ir-user-type-hint.h | 7 +++++ tests/spirv/spirv-reflection.slang | 22 +++++++------- 12 files changed, 95 insertions(+), 31 deletions(-) create mode 100644 source/slang/slang-ir-user-type-hint.cpp create mode 100644 source/slang/slang-ir-user-type-hint.h diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj index 6ca03e63a..9277df88f 100644 --- a/build/visual-studio/slang/slang.vcxproj +++ b/build/visual-studio/slang/slang.vcxproj @@ -472,6 +472,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla + @@ -693,6 +694,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla + diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters index eceb57b9f..a427febb5 100644 --- a/build/visual-studio/slang/slang.vcxproj.filters +++ b/build/visual-studio/slang/slang.vcxproj.filters @@ -504,6 +504,9 @@ Header Files + + Header Files + Header Files @@ -1163,6 +1166,9 @@ Source Files + + Source Files + Source Files diff --git a/source/slang/slang-emit-spirv-ops.h b/source/slang/slang-emit-spirv-ops.h index f8c96bb30..42aeb8316 100644 --- a/source/slang/slang-emit-spirv-ops.h +++ b/source/slang/slang-emit-spirv-ops.h @@ -733,7 +733,7 @@ SpvInst* emitOpMemberDecorateString( ) { static_assert(isSingular); - return emitInst(parent, inst, SpvOpMemberDecorate, target, index, decoration, text); + return emitInst(parent, inst, SpvOpMemberDecorateString, target, index, decoration, text); } // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpDecorate @@ -747,7 +747,7 @@ SpvInst* emitOpDecorateString( ) { static_assert(isSingular); - return emitInst(parent, inst, SpvOpDecorate, target, decoration, text); + return emitInst(parent, inst, SpvOpDecorateString, target, decoration, text); } // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpDecorate diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 252f0e917..79f324988 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -2919,6 +2919,24 @@ struct SPIRVEmitContext } } + // Make user type name conform to `SPV_GOOGLE_user_type` spec. + // https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/GOOGLE/SPV_GOOGLE_user_type.asciidoc + String legalizeUserTypeName(UnownedStringSlice typeName) + { + String result = typeName; + auto index = typeName.indexOf('<'); + if (index == -1) + index = typeName.getLength(); + StringBuilder sb; + sb << String(typeName.head(index)).toLower(); + if (index != typeName.getLength()) + { + sb << ":"; + sb << typeName.tail(index); + } + return sb.produceString(); + } + /// Emit an appropriate SPIR-V decoration for the given IR `decoration`, if necessary and possible. /// /// The given `dstID` should be the `` of the SPIR-V instruction being decorated, @@ -3246,7 +3264,7 @@ struct SPIRVEmitContext decoration, dstID, SpvDecorationUserTypeGOOGLE, - cast(decoration)->getUserTypeName()->getStringSlice()); + legalizeUserTypeName(cast(decoration)->getUserTypeName()->getStringSlice()).getUnownedSlice()); } break; case kIROp_CounterBufferDecoration: diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 0ec9b0c1a..43f54d04f 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -32,6 +32,7 @@ #include "slang-ir-legalize-varying-params.h" #include "slang-ir-link.h" #include "slang-ir-com-interface.h" +#include "slang-ir-user-type-hint.h" #include "slang-ir-lower-append-consume-structured-buffer.h" #include "slang-ir-lower-binding-query.h" #include "slang-ir-lower-generics.h" @@ -537,6 +538,8 @@ Result linkAndOptimizeIR( lowerAppendConsumeStructuredBuffers(targetProgram, irModule, sink); } + addUserTypeHintDecorations(irModule); + // We don't need the legalize pass for C/C++ based types if(options.shouldLegalizeExistentialAndResourceTypes ) { diff --git a/source/slang/slang-ir-byte-address-legalize.cpp b/source/slang/slang-ir-byte-address-legalize.cpp index c1e22c89f..d5fc7ed5c 100644 --- a/source/slang/slang-ir-byte-address-legalize.cpp +++ b/source/slang/slang-ir-byte-address-legalize.cpp @@ -759,6 +759,8 @@ struct ByteAddressBufferLegalizationContext auto structuredBufferParam = paramBuilder.createGlobalParam(structuredBufferParamType); if (auto nameHint = byteAddressBufferParam->findDecoration()) paramBuilder.addNameHintDecoration(structuredBufferParam, nameHint->getName()); + if (auto typeHint = byteAddressBufferParam->findDecoration()) + paramBuilder.addUserTypeNameDecoration(structuredBufferParam, typeHint->getUserTypeName()); // The new parameter needs to be given a layout to match the existing // parameter, so that it is given the same `binding` in the generated code. diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 0a7f8c33b..195bf577c 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -4287,6 +4287,11 @@ public: addNameHintDecoration(value, getStringValue(text)); } + void addUserTypeNameDecoration(IRInst* value, IRStringLit* name) + { + addDecoration(value, kIROp_UserTypeNameDecoration, name); + } + void addBinaryInterfaceTypeDecoration(IRInst* value) { addDecoration(value, kIROp_BinaryInterfaceTypeDecoration); diff --git a/source/slang/slang-ir-lower-append-consume-structured-buffer.cpp b/source/slang/slang-ir-lower-append-consume-structured-buffer.cpp index 6fb1e3140..da6b8d34d 100644 --- a/source/slang/slang-ir-lower-append-consume-structured-buffer.cpp +++ b/source/slang/slang-ir-lower-append-consume-structured-buffer.cpp @@ -18,11 +18,11 @@ namespace Slang auto structType = builder.createStructType(); StringBuilder nameSb; if (type->getOp() == kIROp_HLSLAppendStructuredBufferType) - nameSb << "AppendStructuredBuffer_"; + nameSb << "AppendStructuredBuffer<"; else - nameSb << "ConsumeStructuredBuffer_"; + nameSb << "ConsumeStructuredBuffer<"; getTypeNameHint(nameSb, elementType); - nameSb << "_t"; + nameSb << ">"; builder.addNameHintDecoration(structType, nameSb.produceString().getUnownedSlice()); auto elementBufferKey = builder.createStructKey(); diff --git a/source/slang/slang-ir-spirv-legalize.cpp b/source/slang/slang-ir-spirv-legalize.cpp index b387a67f6..d072e2da0 100644 --- a/source/slang/slang-ir-spirv-legalize.cpp +++ b/source/slang/slang-ir-spirv-legalize.cpp @@ -496,21 +496,6 @@ struct SPIRVLegalizationContext : public SourceEmitterBase void processGlobalParam(IRGlobalParam* inst) { - if (inst->getDataType()) - { - // Preserve the original type name as a decoration before we do any type lowering. - // This is needed to implement -fspv-reflect, which allows the compiler to output the - // original user-friendly type name of each shader parameter as a SPIRV decoration. - // - StringBuilder sb; - getTypeNameHint(sb, inst->getDataType()); - if (sb.getLength()) - { - IRBuilder builder(inst); - builder.addDecoration(inst, kIROp_UserTypeNameDecoration, builder.getStringValue(sb.produceString().getUnownedSlice())); - } - } - // If the param is a texture, infer its format. if (auto textureType = as(unwrapArray(inst->getDataType()))) { diff --git a/source/slang/slang-ir-user-type-hint.cpp b/source/slang/slang-ir-user-type-hint.cpp new file mode 100644 index 000000000..3003d56f6 --- /dev/null +++ b/source/slang/slang-ir-user-type-hint.cpp @@ -0,0 +1,34 @@ +#include "slang-ir-user-type-hint.h" + +#include "slang-ir.h" +#include "slang-ir-insts.h" +#include "slang-ir-util.h" + +namespace Slang +{ + +void addUserTypeHintDecorations(IRModule* module) +{ + for (auto globalInst : module->getGlobalInsts()) + { + auto inst = as(globalInst); + if (!inst) + continue; + if (inst->getDataType()) + { + // Preserve the original type name as a decoration before we do any type lowering. + // This is needed to implement -fspv-reflect, which allows the compiler to output the + // original user-friendly type name of each shader parameter as a SPIRV decoration. + // + StringBuilder sb; + getTypeNameHint(sb, inst->getDataType()); + if (sb.getLength()) + { + IRBuilder builder(inst); + builder.addDecoration(inst, kIROp_UserTypeNameDecoration, builder.getStringValue(sb.produceString().getUnownedSlice())); + } + } + } +} + +} diff --git a/source/slang/slang-ir-user-type-hint.h b/source/slang/slang-ir-user-type-hint.h new file mode 100644 index 000000000..2fbfbd5e0 --- /dev/null +++ b/source/slang/slang-ir-user-type-hint.h @@ -0,0 +1,7 @@ +#pragma once + +namespace Slang +{ + struct IRModule; + void addUserTypeHintDecorations(IRModule* module); +} diff --git a/tests/spirv/spirv-reflection.slang b/tests/spirv/spirv-reflection.slang index 90414eb59..d1de9e974 100644 --- a/tests/spirv/spirv-reflection.slang +++ b/tests/spirv/spirv-reflection.slang @@ -9,25 +9,27 @@ struct MyElement } StructuredBuffer myBuffer : MY_HLSL_SEMANTIC1; AppendStructuredBuffer myAppendBuffer : MY_HLSL_SEMANTIC2; - +ByteAddressBuffer bw; [numthreads(8, 8, 1)] void computeMain() { float4 color = mTexture.Load(int3(0, 0, 0)); - myAppendBuffer.Append(color.x + myBuffer[0].x); + myAppendBuffer.Append(color.x + myBuffer[0].x + bw.Load(0)); } // SPIRV-DAG: OpExtension "SPV_GOOGLE_user_type" -// SPIRV-DAG: OpDecorate %mTexture UserTypeGOOGLE "Texture2D" -// SPIRV-DAG: OpDecorate %mTexture UserSemantic "MY_HLSL_SEMANTIC" +// SPIRV-DAG: OpDecorateString %mTexture UserTypeGOOGLE "texture2d" +// SPIRV-DAG: OpDecorateString %mTexture UserSemantic "MY_HLSL_SEMANTIC" -// SPIRV-DAG: OpDecorate %myBuffer UserTypeGOOGLE "StructuredBuffer" -// SPIRV-DAG: OpDecorate %myBuffer UserSemantic "MY_HLSL_SEMANTIC1" +// SPIRV-DAG: OpDecorateString %myBuffer UserTypeGOOGLE "structuredbuffer:" +// SPIRV-DAG: OpDecorateString %myBuffer UserSemantic "MY_HLSL_SEMANTIC1" -// SPIRV-DAG: OpDecorate %myAppendBuffer_counter UserTypeGOOGLE "RWStructuredBuffer" -// SPIRV-DAG: OpDecorate %myAppendBuffer_counter UserSemantic "MY_HLSL_SEMANTIC2" +// SPIRV-DAG: OpDecorateString %myAppendBuffer_counter UserTypeGOOGLE "appendstructuredbuffer:" +// SPIRV-DAG: OpDecorateString %myAppendBuffer_counter UserSemantic "MY_HLSL_SEMANTIC2" -// SPIRV-DAG: OpDecorate %myAppendBuffer_elements UserTypeGOOGLE "RWStructuredBuffer" -// SPIRV-DAG: OpDecorate %myAppendBuffer_elements UserSemantic "MY_HLSL_SEMANTIC2" +// SPIRV-DAG: OpDecorateString %myAppendBuffer_elements UserTypeGOOGLE "appendstructuredbuffer:" +// SPIRV-DAG: OpDecorateString %myAppendBuffer_elements UserSemantic "MY_HLSL_SEMANTIC2" // SPIRV-DAG: OpDecorateId %myAppendBuffer_elements CounterBuffer %myAppendBuffer_counter + +// SPIRV-DAG: OpDecorateString %bw UserTypeGOOGLE "byteaddressbuffer" \ No newline at end of file -- cgit v1.2.3