From be2835501915861c316697eb41fbfa077faa6768 Mon Sep 17 00:00:00 2001 From: steve-lunarg Date: Tue, 18 Apr 2017 12:18:01 -0600 Subject: [PATCH 1/2] WIP: HLSL: hlsl register class iomapping Adds --hlsl-iomap option to perform IO mapping in HLSL register space. --shift-cbuffer-binding is now a synonym for --shift-ubo-binding. The idea way to do this seems to be passing in a dedicated IO resolver, but that would require more intrusive restructuring, so maybe best for its own PR. The TDefaultHlslIoResolver class and the former TDefaultIoResolver class share quite a bit of mechanism in a common base class. TODO: tbuffers are landing in the wrong register class, which needs some investigation. They're either wrong upstream, or the detection in the resolver is wrong. --- StandAlone/StandAlone.cpp | 26 +- Test/baseResults/hlsl.automap.frag.out | 27 ++ Test/hlsl.automap.frag | 57 ++++ Test/runtests | 3 +- glslang/MachineIndependent/ShaderLang.cpp | 3 + glslang/MachineIndependent/iomapper.cpp | 302 ++++++++++++------ .../MachineIndependent/localintermediate.h | 10 +- glslang/Public/ShaderLang.h | 3 + 8 files changed, 335 insertions(+), 96 deletions(-) create mode 100644 Test/baseResults/hlsl.automap.frag.out create mode 100644 Test/hlsl.automap.frag diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 60dbc4da..3faadecf 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -87,6 +87,7 @@ enum TOptions { EOptionNoStorageFormat = (1 << 21), EOptionKeepUncalled = (1 << 22), EOptionHlslOffsets = (1 << 23), + EOptionHlslIoMapping = (1 << 24), }; // @@ -166,6 +167,7 @@ std::array baseTextureBinding; std::array baseImageBinding; std::array baseUboBinding; std::array baseSsboBinding; +std::array baseUavBinding; // // Create the default name for saving a binary if -o is not provided. @@ -256,6 +258,7 @@ void ProcessArguments(std::vector>& workItem baseImageBinding.fill(0); baseUboBinding.fill(0); baseSsboBinding.fill(0); + baseUavBinding.fill(0); ExecutableName = argv[0]; workItems.reserve(argc); @@ -285,12 +288,19 @@ void ProcessArguments(std::vector>& workItem ProcessBindingBase(argc, argv, baseImageBinding); } else if (lowerword == "shift-ubo-bindings" || // synonyms lowerword == "shift-ubo-binding" || - lowerword == "sub") { + lowerword == "shift-cbuffer-bindings" || + lowerword == "shift-cbuffer-binding" || + lowerword == "sub" || + lowerword == "scb") { ProcessBindingBase(argc, argv, baseUboBinding); } else if (lowerword == "shift-ssbo-bindings" || // synonyms lowerword == "shift-ssbo-binding" || lowerword == "sbb") { ProcessBindingBase(argc, argv, baseSsboBinding); + } else if (lowerword == "shift-uav-bindings" || // synonyms + lowerword == "shift-uav-binding" || + lowerword == "suavb") { + ProcessBindingBase(argc, argv, baseUavBinding); } else if (lowerword == "auto-map-bindings" || // synonyms lowerword == "auto-map-binding" || lowerword == "amb") { @@ -326,6 +336,10 @@ void ProcessArguments(std::vector>& workItem Options |= EOptionKeepUncalled; } else if (lowerword == "hlsl-offsets") { Options |= EOptionHlslOffsets; + } else if (lowerword == "hlsl-iomap" || + lowerword == "hlsl-iomapper" || + lowerword == "hlsl-iomapping") { + Options |= EOptionHlslIoMapping; } else { usage(); } @@ -577,9 +591,13 @@ void CompileAndLinkShaderUnits(std::vector compUnits) shader->setShiftImageBinding(baseImageBinding[compUnit.stage]); shader->setShiftUboBinding(baseUboBinding[compUnit.stage]); shader->setShiftSsboBinding(baseSsboBinding[compUnit.stage]); + shader->setShiftUavBinding(baseUavBinding[compUnit.stage]); shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0); shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0); + if (Options & EOptionHlslIoMapping) + shader->setHlslIoMapping(true); + if (Options & EOptionAutoMapBindings) shader->setAutoMapBindings(true); @@ -982,11 +1000,15 @@ void usage() " --sib [stage] num synonym for --shift-image-binding\n" "\n" " --shift-UBO-binding [stage] num set base binding number for UBOs\n" + " --shift-cbuffer-binding [stage] num synonym for --shift-UBO-binding\n" " --sub [stage] num synonym for --shift-UBO-binding\n" "\n" " --shift-ssbo-binding [stage] num set base binding number for SSBOs\n" " --sbb [stage] num synonym for --shift-ssbo-binding\n" "\n" + " --shift-uav-binding [stage] num set base binding number for UAVs\n" + " --suavb [stage] num synonym for --shift-uav-binding\n" + "\n" " --auto-map-bindings automatically bind uniform variables without\n" " explicit bindings.\n" " --amb synonym for --auto-map-bindings\n" @@ -1009,6 +1031,8 @@ void usage() "\n" " --hlsl-offsets Allow block offsets to follow HLSL rules instead of GLSL rules.\n" " Works independently of source language.\n" + "\n" + " --hlsl-iomap Perform IO mapping in HLSL register space.\n" ); exit(EFailUsage); diff --git a/Test/baseResults/hlsl.automap.frag.out b/Test/baseResults/hlsl.automap.frag.out new file mode 100644 index 00000000..ca7d285b --- /dev/null +++ b/Test/baseResults/hlsl.automap.frag.out @@ -0,0 +1,27 @@ +hlsl.automap.frag +Uniform reflection: +t1: offset -1, type 8b5d, size 1, index -1, binding 11 +t2: offset -1, type 8b5e, size 1, index -1, binding 12 +t3: offset -1, type 8b5f, size 1, index -1, binding 13 +t4.@data: offset 0, type 8b52, size 1, index 0, binding -1 +t5.@data: offset 0, type 1405, size 0, index 1, binding -1 +t6: offset -1, type 8dc2, size 1, index -1, binding 16 +s1: offset -1, type 0, size 1, index -1, binding 31 +s2: offset -1, type 0, size 1, index -1, binding 32 +u1: offset -1, type 904c, size 1, index -1, binding 41 +u2: offset -1, type 904d, size 1, index -1, binding 42 +u3: offset -1, type 904e, size 1, index -1, binding 43 +u4: offset -1, type 9051, size 1, index -1, binding 44 +u5.@data: offset 0, type 1405, size 0, index 2, binding -1 +u6.@data: offset 0, type 1406, size 1, index 3, binding -1 +cb1: offset 0, type 1404, size 1, index 4, binding -1 + +Uniform block reflection: +t4: offset -1, type ffffffff, size 0, index -1, binding 14 +t5: offset -1, type ffffffff, size 0, index -1, binding 15 +u5: offset -1, type ffffffff, size 0, index -1, binding 45 +u6: offset -1, type ffffffff, size 0, index -1, binding 46 +cb: offset -1, type ffffffff, size 4, index -1, binding 51 + +Vertex attribute reflection: + diff --git a/Test/hlsl.automap.frag b/Test/hlsl.automap.frag new file mode 100644 index 00000000..fbb45451 --- /dev/null +++ b/Test/hlsl.automap.frag @@ -0,0 +1,57 @@ +// Test register class offsets for different resource types + +SamplerState s1 : register(s1); +SamplerComparisonState s2 : register(s2); + +Texture1D t1 : register(t1); +Texture2D t2 : register(t2); +Texture3D t3 : register(t3); +StructuredBuffer t4 : register(t4); +ByteAddressBuffer t5 : register(t5); +Buffer t6 : register(t6); + +RWTexture1D u1 : register(u1); +RWTexture2D u2 : register(u2); +RWTexture3D u3 : register(u3); + +RWBuffer u4 : register(u4); +RWByteAddressBuffer u5 : register(u5); +RWStructuredBuffer u6 : register(u6); +AppendStructuredBuffer u7 : register(u7); +ConsumeStructuredBuffer u8 : register(u8); + +cbuffer cb : register(b1) { + int cb1; +}; + +// tbuffer tb : register(t7) { +// int tb1; +// }; + +float4 main() : SV_Target0 +{ + t1; + t2; + t3; + t4[0]; + t5.Load(0); + t6; + + s1; + s2; + + u1; + u2; + u3; + + u4[0]; + u5.Load(0); + u6[0]; + u7[0]; + u8[0]; + + cb1; + // tb1; TODO: wrong type? + + return 0; +} diff --git a/Test/runtests b/Test/runtests index efc449d9..176e73ff 100755 --- a/Test/runtests +++ b/Test/runtests @@ -35,7 +35,8 @@ $EXE -D -e flizv -l -q -C -V hlsl.reflection.vert > $TARGETDIR/hlsl.reflection.v diff -b $BASEDIR/hlsl.reflection.vert.out $TARGETDIR/hlsl.reflection.vert.out || HASERROR=1 $EXE -D -e main -l -q -C -V hlsl.reflection.binding.frag > $TARGETDIR/hlsl.reflection.binding.frag.out diff -b $BASEDIR/hlsl.reflection.binding.frag.out $TARGETDIR/hlsl.reflection.binding.frag.out || HASERROR=1 - +$EXE -D -e main -l -q --hlsl-iomap --auto-map-bindings --stb 10 --sbb 20 --ssb 30 --suavb 40 --scb 50 -D -V -e main hlsl.automap.frag > $TARGETDIR/hlsl.automap.frag.out +diff -b $BASEDIR/hlsl.automap.frag.out $TARGETDIR/hlsl.automap.frag.out || HASERROR=1 # # multi-threaded test diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 95c16e80..99203833 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -1559,8 +1559,11 @@ void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShift void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); } void TShader::setShiftImageBinding(unsigned int base) { intermediate->setShiftImageBinding(base); } void TShader::setShiftUboBinding(unsigned int base) { intermediate->setShiftUboBinding(base); } +void TShader::setShiftCbufferBinding(unsigned int base) { intermediate->setShiftUboBinding(base); } +void TShader::setShiftUavBinding(unsigned int base) { intermediate->setShiftUavBinding(base); } void TShader::setShiftSsboBinding(unsigned int base) { intermediate->setShiftSsboBinding(base); } void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } +void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); } diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp index 9a6613e2..355cc428 100644 --- a/glslang/MachineIndependent/iomapper.cpp +++ b/glslang/MachineIndependent/iomapper.cpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2016 LunarG, Inc. +// Copyright (C) 2016-2017 LunarG, Inc. // // All rights reserved. // @@ -310,20 +310,15 @@ private: TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&); }; -/* - * Basic implementation of glslang::TIoMapResolver that replaces the - * previous offset behavior. - * It does the same, uses the offsets for the corresponding uniform - * types. Also respects the EOptionAutoMapBindings flag and binds - * them if needed. - */ -struct TDefaultIoResolver : public glslang::TIoMapResolver +// Base class for shared TIoMapResolver services, used by several derivations. +struct TDefaultIoResolverBase : public glslang::TIoMapResolver { int baseSamplerBinding; int baseTextureBinding; int baseImageBinding; int baseUboBinding; int baseSsboBinding; + int baseUavBinding; bool doAutoMapping; typedef std::vector TSlotSet; typedef std::unordered_map TSlotSetMap; @@ -360,83 +355,9 @@ struct TDefaultIoResolver : public glslang::TIoMapResolver return reserveSlot(set, base); } - bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override - { - if (type.getQualifier().hasBinding()) { - int set; - if (type.getQualifier().hasSet()) - set = type.getQualifier().layoutSet; - else - set = 0; + virtual bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override = 0; - if (type.getBasicType() == glslang::EbtSampler) { - const glslang::TSampler& sampler = type.getSampler(); - if (sampler.isPureSampler()) - return checkEmpty(set, baseSamplerBinding + type.getQualifier().layoutBinding); - - if (sampler.isTexture()) - return checkEmpty(set, baseTextureBinding + type.getQualifier().layoutBinding); - } - - if (type.getQualifier().storage == EvqUniform) - return checkEmpty(set, baseUboBinding + type.getQualifier().layoutBinding); - - if (type.getQualifier().storage == EvqBuffer) - return checkEmpty(set, baseSsboBinding + type.getQualifier().layoutBinding); - } - return true; - } - - int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override - { - int set; - if (type.getQualifier().hasSet()) - set = type.getQualifier().layoutSet; - else - set = 0; - - if (type.getQualifier().hasBinding()) { - if (type.getBasicType() == glslang::EbtSampler) { - const glslang::TSampler& sampler = type.getSampler(); - if (sampler.isImage()) - return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding); - - if (sampler.isPureSampler()) - return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding); - - if (sampler.isTexture()) - return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding); - } - - if (type.getQualifier().storage == EvqUniform) - return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding); - - if (type.getQualifier().storage == EvqBuffer) - return reserveSlot(set, baseSsboBinding + type.getQualifier().layoutBinding); - } else if (is_live && doAutoMapping) { - // find free slot, the caller did make sure it passes all vars with binding - // first and now all are passed that do not have a binding and needs one - if (type.getBasicType() == glslang::EbtSampler) { - const glslang::TSampler& sampler = type.getSampler(); - if (sampler.isImage()) - return getFreeSlot(set, baseImageBinding); - - if (sampler.isPureSampler()) - return getFreeSlot(set, baseSamplerBinding); - - if (sampler.isTexture()) - return getFreeSlot(set, baseTextureBinding); - } - - if (type.getQualifier().storage == EvqUniform) - return getFreeSlot(set, baseUboBinding); - - if (type.getQualifier().storage == EvqBuffer) - return getFreeSlot(set, baseSsboBinding); - } - - return -1; - } + virtual int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override = 0; int resolveSet(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override { @@ -461,8 +382,191 @@ struct TDefaultIoResolver : public glslang::TIoMapResolver { return -1; } + +protected: + static int getLayoutSet(const glslang::TType& type) { + if (type.getQualifier().hasSet()) + return type.getQualifier().layoutSet; + else + return 0; + } + + static bool isSamplerType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler(); + } + + static bool isTextureType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isTexture(); + } + + static bool isUboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqUniform; + } }; +/* + * Basic implementation of glslang::TIoMapResolver that replaces the + * previous offset behavior. + * It does the same, uses the offsets for the corresponding uniform + * types. Also respects the EOptionAutoMapBindings flag and binds + * them if needed. + */ +/* + * Default resolver + */ +struct TDefaultIoResolver : public TDefaultIoResolverBase +{ + bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override + { + if (type.getQualifier().hasBinding()) { + const int set = getLayoutSet(type); + + if (isImageType(type)) + return checkEmpty(set, baseImageBinding + type.getQualifier().layoutBinding); + + if (isTextureType(type)) + return checkEmpty(set, baseTextureBinding + type.getQualifier().layoutBinding); + + if (isSsboType(type)) + return checkEmpty(set, baseSsboBinding + type.getQualifier().layoutBinding); + + if (isSamplerType(type)) + return checkEmpty(set, baseSamplerBinding + type.getQualifier().layoutBinding); + + if (isUboType(type)) + return checkEmpty(set, baseUboBinding + type.getQualifier().layoutBinding); + } + return true; + } + + int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override + { + const int set = getLayoutSet(type); + + if (type.getQualifier().hasBinding()) { + if (isImageType(type)) + return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding); + + if (isTextureType(type)) + return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding); + + if (isSsboType(type)) + return reserveSlot(set, baseSsboBinding + type.getQualifier().layoutBinding); + + if (isSamplerType(type)) + return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding); + + if (isUboType(type)) + return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding); + } else if (is_live && doAutoMapping) { + // find free slot, the caller did make sure it passes all vars with binding + // first and now all are passed that do not have a binding and needs one + + if (isImageType(type)) + return getFreeSlot(set, baseImageBinding); + + if (isTextureType(type)) + return getFreeSlot(set, baseTextureBinding); + + if (isSsboType(type)) + return getFreeSlot(set, baseSsboBinding); + + if (isSamplerType(type)) + return getFreeSlot(set, baseSamplerBinding); + + if (isUboType(type)) + return getFreeSlot(set, baseUboBinding); + } + + return -1; + } + +protected: + static bool isImageType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage(); + } + + static bool isSsboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqBuffer; + } +}; + +struct TDefaultHlslIoResolver : public TDefaultIoResolverBase +{ + bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override + { + if (type.getQualifier().hasBinding()) { + const int set = getLayoutSet(type); + + // Use Uav binding if requested: else will pass through to old behavior + if (isUavType(type)) + return checkEmpty(set, baseUavBinding + type.getQualifier().layoutBinding); + + if (isSrvType(type)) + return checkEmpty(set, baseTextureBinding + type.getQualifier().layoutBinding); + + if (isSamplerType(type)) + return checkEmpty(set, baseSamplerBinding + type.getQualifier().layoutBinding); + + if (isUboType(type)) + return checkEmpty(set, baseUboBinding + type.getQualifier().layoutBinding); + } + return true; + } + + int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override + { + const int set = getLayoutSet(type); + + if (type.getQualifier().hasBinding()) { + if (isUavType(type)) + return reserveSlot(set, baseUavBinding + type.getQualifier().layoutBinding); + + if (isSrvType(type)) + return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding); + + if (isSamplerType(type)) + return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding); + + if (isUboType(type)) + return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding); + } else if (is_live && doAutoMapping) { + // find free slot, the caller did make sure it passes all vars with binding + // first and now all are passed that do not have a binding and needs one + + if (isUavType(type)) + return getFreeSlot(set, baseUavBinding); + + if (isSrvType(type)) + return getFreeSlot(set, baseTextureBinding); + + if (isSamplerType(type)) + return getFreeSlot(set, baseSamplerBinding); + + if (isUboType(type)) + return getFreeSlot(set, baseUboBinding); + } + + return -1; + } + +protected: + // Return true if this is a SRV (shader resource view) type: + static bool isSrvType(const glslang::TType& type) { + return isTextureType(type) || type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a UAV (unordered access view) type: + static bool isUavType(const glslang::TType& type) { + if (type.getQualifier().readonly) + return false; + + return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || + (type.getQualifier().storage == EvqBuffer); + } +}; + + // Map I/O variables to provided offsets, and make bindings for // unbound but live variables. // @@ -475,6 +579,7 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi intermediate.getShiftImageBinding() == 0 && intermediate.getShiftUboBinding() == 0 && intermediate.getShiftSsboBinding() == 0 && + intermediate.getShiftUavBinding() == 0 && intermediate.getAutoMapBindings() == false && resolver == nullptr) return true; @@ -488,15 +593,26 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi // if no resolver is provided, use the default resolver with the given shifts and auto map settings TDefaultIoResolver defaultResolver; - if (resolver == nullptr) { - defaultResolver.baseSamplerBinding = intermediate.getShiftSamplerBinding(); - defaultResolver.baseTextureBinding = intermediate.getShiftTextureBinding(); - defaultResolver.baseImageBinding = intermediate.getShiftImageBinding(); - defaultResolver.baseUboBinding = intermediate.getShiftUboBinding(); - defaultResolver.baseSsboBinding = intermediate.getShiftSsboBinding(); - defaultResolver.doAutoMapping = intermediate.getAutoMapBindings(); + TDefaultHlslIoResolver defaultHlslResolver; - resolver = &defaultResolver; + if (resolver == nullptr) { + TDefaultIoResolverBase* resolverBase; + + // TODO: use a passed in IO mapper for this + if (intermediate.usingHlslIoMapping()) + resolverBase = &defaultHlslResolver; + else + resolverBase = &defaultResolver; + + resolverBase->baseSamplerBinding = intermediate.getShiftSamplerBinding(); + resolverBase->baseTextureBinding = intermediate.getShiftTextureBinding(); + resolverBase->baseImageBinding = intermediate.getShiftImageBinding(); + resolverBase->baseUboBinding = intermediate.getShiftUboBinding(); + resolverBase->baseSsboBinding = intermediate.getShiftSsboBinding(); + resolverBase->baseUavBinding = intermediate.getShiftUavBinding(); + resolverBase->doAutoMapping = intermediate.getAutoMapBindings(); + + resolver = resolverBase; } TVarLiveMap inVarMap, outVarMap, uniformVarMap; diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 0bd9d161..2fd2e9fd 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -175,11 +175,13 @@ public: shiftImageBinding(0), shiftUboBinding(0), shiftSsboBinding(0), + shiftUavBinding(0), autoMapBindings(false), flattenUniformArrays(false), useUnknownFormat(false), hlslOffsets(false), - useStorageBuffer(false) + useStorageBuffer(false), + hlslIoMapping(false) { localSize[0] = 1; localSize[1] = 1; @@ -212,6 +214,8 @@ public: unsigned int getShiftUboBinding() const { return shiftUboBinding; } void setShiftSsboBinding(unsigned int shift) { shiftSsboBinding = shift; } unsigned int getShiftSsboBinding() const { return shiftSsboBinding; } + void setShiftUavBinding(unsigned int shift) { shiftUavBinding = shift; } + unsigned int getShiftUavBinding() const { return shiftUavBinding; } void setAutoMapBindings(bool map) { autoMapBindings = map; } bool getAutoMapBindings() const { return autoMapBindings; } void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; } @@ -222,6 +226,8 @@ public: bool usingHlslOFfsets() const { return hlslOffsets; } void setUseStorageBuffer() { useStorageBuffer = true; } bool usingStorageBuffer() const { return useStorageBuffer; } + void setHlslIoMapping(bool b) { hlslIoMapping = b; } + bool usingHlslIoMapping() { return hlslIoMapping; } void setVersion(int v) { version = v; } int getVersion() const { return version; } @@ -505,11 +511,13 @@ protected: unsigned int shiftImageBinding; unsigned int shiftUboBinding; unsigned int shiftSsboBinding; + unsigned int shiftUavBinding; bool autoMapBindings; bool flattenUniformArrays; bool useUnknownFormat; bool hlslOffsets; bool useStorageBuffer; + bool hlslIoMapping; typedef std::list TGraph; TGraph callGraph; diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index e5e50508..432329ce 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -303,8 +303,11 @@ public: void setShiftTextureBinding(unsigned int base); void setShiftImageBinding(unsigned int base); void setShiftUboBinding(unsigned int base); + void setShiftUavBinding(unsigned int base); + void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding void setShiftSsboBinding(unsigned int base); void setAutoMapBindings(bool map); + void setHlslIoMapping(bool hlslIoMap); void setFlattenUniformArrays(bool flatten); void setNoStorageFormat(bool useUnknownFormat); From 7b1dcd6693c009066114246475fa99a1ae21044e Mon Sep 17 00:00:00 2001 From: steve-lunarg Date: Thu, 20 Apr 2017 13:16:23 -0600 Subject: [PATCH 2/2] HLSL: add readonly qualifier to tbuffer, so they end up as SRV --- Test/baseResults/hlsl.automap.frag.out | 2 ++ Test/baseResults/hlsl.buffer.frag.out | 29 ++++++++++----- Test/baseResults/hlsl.layout.frag.out | 27 +++++++------- Test/hlsl.automap.frag | 12 +++---- glslang/MachineIndependent/ShaderLang.cpp | 9 +++++ glslang/MachineIndependent/iomapper.cpp | 43 ++++++++++++++++++++++- hlsl/hlslGrammar.cpp | 8 +++-- 7 files changed, 101 insertions(+), 29 deletions(-) diff --git a/Test/baseResults/hlsl.automap.frag.out b/Test/baseResults/hlsl.automap.frag.out index ca7d285b..7664bf64 100644 --- a/Test/baseResults/hlsl.automap.frag.out +++ b/Test/baseResults/hlsl.automap.frag.out @@ -15,6 +15,7 @@ u4: offset -1, type 9051, size 1, index -1, binding 44 u5.@data: offset 0, type 1405, size 0, index 2, binding -1 u6.@data: offset 0, type 1406, size 1, index 3, binding -1 cb1: offset 0, type 1404, size 1, index 4, binding -1 +tb1: offset 0, type 1404, size 1, index 5, binding -1 Uniform block reflection: t4: offset -1, type ffffffff, size 0, index -1, binding 14 @@ -22,6 +23,7 @@ t5: offset -1, type ffffffff, size 0, index -1, binding 15 u5: offset -1, type ffffffff, size 0, index -1, binding 45 u6: offset -1, type ffffffff, size 0, index -1, binding 46 cb: offset -1, type ffffffff, size 4, index -1, binding 51 +tb: offset -1, type ffffffff, size 4, index -1, binding 17 Vertex attribute reflection: diff --git a/Test/baseResults/hlsl.buffer.frag.out b/Test/baseResults/hlsl.buffer.frag.out index 623480c5..faa2ad63 100755 --- a/Test/baseResults/hlsl.buffer.frag.out +++ b/Test/baseResults/hlsl.buffer.frag.out @@ -17,7 +17,7 @@ gl_FragCoord origin is upper left 0:31 Constant: 0:31 0 (const uint) 0:31 v2: direct index for structure (layout( row_major std430) buffer 4-component vector of float) -0:31 'anon@1' (layout( row_major std430) buffer block{layout( row_major std430) buffer 4-component vector of float v2}) +0:31 'anon@1' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer 4-component vector of float v2}) 0:31 Constant: 0:31 0 (const uint) 0:31 v3: direct index for structure (layout( row_major std140) uniform 4-component vector of float) @@ -25,7 +25,7 @@ gl_FragCoord origin is upper left 0:31 Constant: 0:31 0 (const uint) 0:31 v4: direct index for structure (layout( row_major std430 offset=16) buffer 4-component vector of float) -0:31 'anon@3' (layout( binding=8 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v4, layout( row_major std430 offset=48) buffer int i4, layout( row_major std430 offset=60) buffer float f1, layout( row_major std430 offset=64) buffer float f3, layout( row_major std430 offset=68) buffer float f4, layout( row_major std430 offset=72) buffer float f5, layout( row_major std430) buffer float f6, layout( row_major std430) buffer float f7, layout( row_major std430) buffer 3X4 matrix of float m1, layout( column_major std430) buffer 3X4 matrix of float m2, layout( row_major std430) buffer 3X4 matrix of float m3, layout( row_major std430) buffer 3X4 matrix of float m4}) +0:31 'anon@3' (layout( binding=8 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v4, layout( row_major std430 offset=48) buffer int i4, layout( row_major std430 offset=60) buffer float f1, layout( row_major std430 offset=64) buffer float f3, layout( row_major std430 offset=68) buffer float f4, layout( row_major std430 offset=72) buffer float f5, layout( row_major std430) buffer float f6, layout( row_major std430) buffer float f7, layout( row_major std430) buffer 3X4 matrix of float m1, layout( column_major std430) buffer 3X4 matrix of float m2, layout( row_major std430) buffer 3X4 matrix of float m3, layout( row_major std430) buffer 3X4 matrix of float m4}) 0:31 Constant: 0:31 0 (const uint) 0:30 Function Definition: PixelShaderFunction( ( temp void) @@ -40,9 +40,9 @@ gl_FragCoord origin is upper left 0:? 'input' ( temp 4-component vector of float) 0:? Linker Objects 0:? 'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform 4-component vector of float v1}) -0:? 'anon@1' (layout( row_major std430) buffer block{layout( row_major std430) buffer 4-component vector of float v2}) +0:? 'anon@1' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer 4-component vector of float v2}) 0:? 'anon@2' (layout( set=10 binding=2 row_major std140) uniform block{layout( row_major std140) uniform 4-component vector of float v3, layout( row_major std140 offset=20) uniform int i3}) -0:? 'anon@3' (layout( binding=8 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v4, layout( row_major std430 offset=48) buffer int i4, layout( row_major std430 offset=60) buffer float f1, layout( row_major std430 offset=64) buffer float f3, layout( row_major std430 offset=68) buffer float f4, layout( row_major std430 offset=72) buffer float f5, layout( row_major std430) buffer float f6, layout( row_major std430) buffer float f7, layout( row_major std430) buffer 3X4 matrix of float m1, layout( column_major std430) buffer 3X4 matrix of float m2, layout( row_major std430) buffer 3X4 matrix of float m3, layout( row_major std430) buffer 3X4 matrix of float m4}) +0:? 'anon@3' (layout( binding=8 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v4, layout( row_major std430 offset=48) buffer int i4, layout( row_major std430 offset=60) buffer float f1, layout( row_major std430 offset=64) buffer float f3, layout( row_major std430 offset=68) buffer float f4, layout( row_major std430 offset=72) buffer float f5, layout( row_major std430) buffer float f6, layout( row_major std430) buffer float f7, layout( row_major std430) buffer 3X4 matrix of float m1, layout( column_major std430) buffer 3X4 matrix of float m2, layout( row_major std430) buffer 3X4 matrix of float m3, layout( row_major std430) buffer 3X4 matrix of float m4}) 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? 'input' (layout( location=0) in 4-component vector of float) @@ -68,7 +68,7 @@ gl_FragCoord origin is upper left 0:31 Constant: 0:31 0 (const uint) 0:31 v2: direct index for structure (layout( row_major std430) buffer 4-component vector of float) -0:31 'anon@1' (layout( row_major std430) buffer block{layout( row_major std430) buffer 4-component vector of float v2}) +0:31 'anon@1' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer 4-component vector of float v2}) 0:31 Constant: 0:31 0 (const uint) 0:31 v3: direct index for structure (layout( row_major std140) uniform 4-component vector of float) @@ -76,7 +76,7 @@ gl_FragCoord origin is upper left 0:31 Constant: 0:31 0 (const uint) 0:31 v4: direct index for structure (layout( row_major std430 offset=16) buffer 4-component vector of float) -0:31 'anon@3' (layout( binding=8 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v4, layout( row_major std430 offset=48) buffer int i4, layout( row_major std430 offset=60) buffer float f1, layout( row_major std430 offset=64) buffer float f3, layout( row_major std430 offset=68) buffer float f4, layout( row_major std430 offset=72) buffer float f5, layout( row_major std430) buffer float f6, layout( row_major std430) buffer float f7, layout( row_major std430) buffer 3X4 matrix of float m1, layout( column_major std430) buffer 3X4 matrix of float m2, layout( row_major std430) buffer 3X4 matrix of float m3, layout( row_major std430) buffer 3X4 matrix of float m4}) +0:31 'anon@3' (layout( binding=8 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v4, layout( row_major std430 offset=48) buffer int i4, layout( row_major std430 offset=60) buffer float f1, layout( row_major std430 offset=64) buffer float f3, layout( row_major std430 offset=68) buffer float f4, layout( row_major std430 offset=72) buffer float f5, layout( row_major std430) buffer float f6, layout( row_major std430) buffer float f7, layout( row_major std430) buffer 3X4 matrix of float m1, layout( column_major std430) buffer 3X4 matrix of float m2, layout( row_major std430) buffer 3X4 matrix of float m3, layout( row_major std430) buffer 3X4 matrix of float m4}) 0:31 Constant: 0:31 0 (const uint) 0:30 Function Definition: PixelShaderFunction( ( temp void) @@ -91,9 +91,9 @@ gl_FragCoord origin is upper left 0:? 'input' ( temp 4-component vector of float) 0:? Linker Objects 0:? 'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform 4-component vector of float v1}) -0:? 'anon@1' (layout( row_major std430) buffer block{layout( row_major std430) buffer 4-component vector of float v2}) +0:? 'anon@1' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer 4-component vector of float v2}) 0:? 'anon@2' (layout( set=10 binding=2 row_major std140) uniform block{layout( row_major std140) uniform 4-component vector of float v3, layout( row_major std140 offset=20) uniform int i3}) -0:? 'anon@3' (layout( binding=8 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v4, layout( row_major std430 offset=48) buffer int i4, layout( row_major std430 offset=60) buffer float f1, layout( row_major std430 offset=64) buffer float f3, layout( row_major std430 offset=68) buffer float f4, layout( row_major std430 offset=72) buffer float f5, layout( row_major std430) buffer float f6, layout( row_major std430) buffer float f7, layout( row_major std430) buffer 3X4 matrix of float m1, layout( column_major std430) buffer 3X4 matrix of float m2, layout( row_major std430) buffer 3X4 matrix of float m3, layout( row_major std430) buffer 3X4 matrix of float m4}) +0:? 'anon@3' (layout( binding=8 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v4, layout( row_major std430 offset=48) buffer int i4, layout( row_major std430 offset=60) buffer float f1, layout( row_major std430 offset=64) buffer float f3, layout( row_major std430 offset=68) buffer float f4, layout( row_major std430 offset=72) buffer float f5, layout( row_major std430) buffer float f6, layout( row_major std430) buffer float f7, layout( row_major std430) buffer 3X4 matrix of float m1, layout( column_major std430) buffer 3X4 matrix of float m2, layout( row_major std430) buffer 3X4 matrix of float m3, layout( row_major std430) buffer 3X4 matrix of float m4}) 0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float) 0:? 'input' (layout( location=0) in 4-component vector of float) @@ -141,6 +141,7 @@ gl_FragCoord origin is upper left MemberDecorate 14 0 Offset 0 Decorate 14 Block Decorate 16 DescriptorSet 0 + MemberDecorate 23 0 NonWritable MemberDecorate 23 0 Offset 0 Decorate 23 BufferBlock Decorate 25 DescriptorSet 0 @@ -149,24 +150,36 @@ gl_FragCoord origin is upper left Decorate 29(cbufName) Block Decorate 31 DescriptorSet 10 Decorate 31 Binding 2 + MemberDecorate 36(tbufName) 0 NonWritable MemberDecorate 36(tbufName) 0 Offset 16 + MemberDecorate 36(tbufName) 1 NonWritable MemberDecorate 36(tbufName) 1 Offset 48 + MemberDecorate 36(tbufName) 2 NonWritable MemberDecorate 36(tbufName) 2 Offset 60 + MemberDecorate 36(tbufName) 3 NonWritable MemberDecorate 36(tbufName) 3 Offset 64 + MemberDecorate 36(tbufName) 4 NonWritable MemberDecorate 36(tbufName) 4 Offset 68 + MemberDecorate 36(tbufName) 5 NonWritable MemberDecorate 36(tbufName) 5 Offset 72 + MemberDecorate 36(tbufName) 6 NonWritable MemberDecorate 36(tbufName) 6 Offset 76 + MemberDecorate 36(tbufName) 7 NonWritable MemberDecorate 36(tbufName) 7 Offset 80 MemberDecorate 36(tbufName) 8 RowMajor + MemberDecorate 36(tbufName) 8 NonWritable MemberDecorate 36(tbufName) 8 Offset 96 MemberDecorate 36(tbufName) 8 MatrixStride 16 MemberDecorate 36(tbufName) 9 ColMajor + MemberDecorate 36(tbufName) 9 NonWritable MemberDecorate 36(tbufName) 9 Offset 160 MemberDecorate 36(tbufName) 9 MatrixStride 16 MemberDecorate 36(tbufName) 10 RowMajor + MemberDecorate 36(tbufName) 10 NonWritable MemberDecorate 36(tbufName) 10 Offset 208 MemberDecorate 36(tbufName) 10 MatrixStride 16 MemberDecorate 36(tbufName) 11 RowMajor + MemberDecorate 36(tbufName) 11 NonWritable MemberDecorate 36(tbufName) 11 Offset 272 MemberDecorate 36(tbufName) 11 MatrixStride 16 Decorate 36(tbufName) BufferBlock diff --git a/Test/baseResults/hlsl.layout.frag.out b/Test/baseResults/hlsl.layout.frag.out index b8a96cfa..bfbfaafa 100755 --- a/Test/baseResults/hlsl.layout.frag.out +++ b/Test/baseResults/hlsl.layout.frag.out @@ -12,23 +12,23 @@ gl_FragCoord origin is upper left 0:17 add ( temp 4-component vector of float) 0:17 'input' ( in 4-component vector of float) 0:17 v1: direct index for structure (layout( row_major std430 offset=16) buffer 4-component vector of float) -0:17 'anon@0' (layout( set=3 binding=5 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1}) +0:17 'anon@0' (layout( set=3 binding=5 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1}) 0:17 Constant: 0:17 0 (const uint) 0:17 v5: direct index for structure (layout( row_major std430 offset=0) buffer 4-component vector of float) -0:17 'anon@1' (layout( row_major std430 push_constant) buffer block{layout( row_major std430 offset=0) buffer 4-component vector of float v5}) +0:17 'anon@1' (layout( row_major std430 push_constant) readonly buffer block{layout( row_major std430 offset=0) buffer 4-component vector of float v5}) 0:17 Constant: 0:17 0 (const uint) 0:17 v1PostLayout: direct index for structure (layout( row_major std430 offset=16) buffer 4-component vector of float) -0:17 'anon@2' (layout( set=4 binding=7 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1PostLayout}) +0:17 'anon@2' (layout( set=4 binding=7 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1PostLayout}) 0:17 Constant: 0:17 0 (const uint) 0:? Linker Objects -0:? 'anon@0' (layout( set=3 binding=5 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1}) -0:? 'anon@1' (layout( row_major std430 push_constant) buffer block{layout( row_major std430 offset=0) buffer 4-component vector of float v5}) +0:? 'anon@0' (layout( set=3 binding=5 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1}) +0:? 'anon@1' (layout( row_major std430 push_constant) readonly buffer block{layout( row_major std430 offset=0) buffer 4-component vector of float v5}) 0:? 'specConst' ( specialization-constant const int) 0:? 10 (const int) -0:? 'anon@2' (layout( set=4 binding=7 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1PostLayout}) +0:? 'anon@2' (layout( set=4 binding=7 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1PostLayout}) Linked fragment stage: @@ -48,23 +48,23 @@ gl_FragCoord origin is upper left 0:17 add ( temp 4-component vector of float) 0:17 'input' ( in 4-component vector of float) 0:17 v1: direct index for structure (layout( row_major std430 offset=16) buffer 4-component vector of float) -0:17 'anon@0' (layout( set=3 binding=5 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1}) +0:17 'anon@0' (layout( set=3 binding=5 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1}) 0:17 Constant: 0:17 0 (const uint) 0:17 v5: direct index for structure (layout( row_major std430 offset=0) buffer 4-component vector of float) -0:17 'anon@1' (layout( row_major std430 push_constant) buffer block{layout( row_major std430 offset=0) buffer 4-component vector of float v5}) +0:17 'anon@1' (layout( row_major std430 push_constant) readonly buffer block{layout( row_major std430 offset=0) buffer 4-component vector of float v5}) 0:17 Constant: 0:17 0 (const uint) 0:17 v1PostLayout: direct index for structure (layout( row_major std430 offset=16) buffer 4-component vector of float) -0:17 'anon@2' (layout( set=4 binding=7 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1PostLayout}) +0:17 'anon@2' (layout( set=4 binding=7 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1PostLayout}) 0:17 Constant: 0:17 0 (const uint) 0:? Linker Objects -0:? 'anon@0' (layout( set=3 binding=5 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1}) -0:? 'anon@1' (layout( row_major std430 push_constant) buffer block{layout( row_major std430 offset=0) buffer 4-component vector of float v5}) +0:? 'anon@0' (layout( set=3 binding=5 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1}) +0:? 'anon@1' (layout( row_major std430 push_constant) readonly buffer block{layout( row_major std430 offset=0) buffer 4-component vector of float v5}) 0:? 'specConst' ( specialization-constant const int) 0:? 10 (const int) -0:? 'anon@2' (layout( set=4 binding=7 row_major std430) buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1PostLayout}) +0:? 'anon@2' (layout( set=4 binding=7 row_major std430) readonly buffer block{layout( row_major std430 offset=16) buffer 4-component vector of float v1PostLayout}) // Module Version 10000 // Generated by (magic number): 80001 @@ -89,12 +89,15 @@ gl_FragCoord origin is upper left MemberName 30(tbufName2) 0 "v1PostLayout" Name 32 "" Name 38 "specConst" + MemberDecorate 14(tbufName) 0 NonWritable MemberDecorate 14(tbufName) 0 Offset 16 Decorate 14(tbufName) BufferBlock Decorate 16 DescriptorSet 3 Decorate 16 Binding 5 + MemberDecorate 23(tbufName2) 0 NonWritable MemberDecorate 23(tbufName2) 0 Offset 0 Decorate 23(tbufName2) BufferBlock + MemberDecorate 30(tbufName2) 0 NonWritable MemberDecorate 30(tbufName2) 0 Offset 16 Decorate 30(tbufName2) BufferBlock Decorate 32 DescriptorSet 4 diff --git a/Test/hlsl.automap.frag b/Test/hlsl.automap.frag index fbb45451..da1e885f 100644 --- a/Test/hlsl.automap.frag +++ b/Test/hlsl.automap.frag @@ -24,9 +24,9 @@ cbuffer cb : register(b1) { int cb1; }; -// tbuffer tb : register(t7) { -// int tb1; -// }; +tbuffer tb : register(t7) { + int tb1; +}; float4 main() : SV_Target0 { @@ -47,11 +47,11 @@ float4 main() : SV_Target0 u4[0]; u5.Load(0); u6[0]; - u7[0]; - u8[0]; + u7; + u8; cb1; - // tb1; TODO: wrong type? + tb1; return 0; } diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 99203833..c3a1164d 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -1555,14 +1555,23 @@ void TShader::setSourceEntryPoint(const char* name) sourceEntryPointName = name; } +// Set binding base for sampler types void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); } +// Set binding base for texture types (SRV) void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); } +// Set binding base for image types void TShader::setShiftImageBinding(unsigned int base) { intermediate->setShiftImageBinding(base); } +// Set binding base for uniform buffer objects (CBV) void TShader::setShiftUboBinding(unsigned int base) { intermediate->setShiftUboBinding(base); } +// Synonym for setShiftUboBinding, to match HLSL language. void TShader::setShiftCbufferBinding(unsigned int base) { intermediate->setShiftUboBinding(base); } +// Set binding base for UAV (unordered access view) void TShader::setShiftUavBinding(unsigned int base) { intermediate->setShiftUavBinding(base); } +// Set binding base for SSBOs void TShader::setShiftSsboBinding(unsigned int base) { intermediate->setShiftSsboBinding(base); } +// Enables binding automapping using TIoMapper void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } +// See comment above TDefaultHlslIoMapper in iomapper.cpp: void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); } diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp index 355cc428..54972e78 100644 --- a/glslang/MachineIndependent/iomapper.cpp +++ b/glslang/MachineIndependent/iomapper.cpp @@ -491,6 +491,48 @@ protected: } }; +/******************************************************************************** +The following IO resolver maps types in HLSL register space, as follows: + +t – for shader resource views (SRV) + TEXTURE1D + TEXTURE1DARRAY + TEXTURE2D + TEXTURE2DARRAY + TEXTURE3D + TEXTURECUBE + TEXTURECUBEARRAY + TEXTURE2DMS + TEXTURE2DMSARRAY + STRUCTUREDBUFFER + BYTEADDRESSBUFFER + BUFFER + TBUFFER + +s – for samplers + SAMPLER + SAMPLER1D + SAMPLER2D + SAMPLER3D + SAMPLERCUBE + SAMPLERSTATE + SAMPLERCOMPARISONSTATE + +u – for unordered access views (UAV) + RWBYTEADDRESSBUFFER + RWSTRUCTUREDBUFFER + APPENDSTRUCTUREDBUFFER + CONSUMESTRUCTUREDBUFFER + RWBUFFER + RWTEXTURE1D + RWTEXTURE1DARRAY + RWTEXTURE2D + RWTEXTURE2DARRAY + RWTEXTURE3D + +b – for constant buffer views (CBV) + CBUFFER + ********************************************************************************/ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase { bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override @@ -498,7 +540,6 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase if (type.getQualifier().hasBinding()) { const int set = getLayoutSet(type); - // Use Uav binding if requested: else will pass through to old behavior if (isUavType(type)) return checkEmpty(set, baseUavBinding + type.getQualifier().layoutBinding); diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 3a1627b9..63b78bf3 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -1846,13 +1846,16 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) // This storage qualifier will tell us whether it's an AST // block type or just a generic structure type. TStorageQualifier storageQualifier = EvqTemporary; + bool readonly = false; // CBUFFER - if (acceptTokenClass(EHTokCBuffer)) + if (acceptTokenClass(EHTokCBuffer)) { storageQualifier = EvqUniform; // TBUFFER - else if (acceptTokenClass(EHTokTBuffer)) + } else if (acceptTokenClass(EHTokTBuffer)) { storageQualifier = EvqBuffer; + readonly = true; + } // CLASS // STRUCT else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) @@ -1908,6 +1911,7 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) new(&type) TType(typeList, structName); else { postDeclQualifier.storage = storageQualifier; + postDeclQualifier.readonly = readonly; new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock }