#include <cctype>
#include <cmath>
#include <array>
+#include <map>
#include <memory>
#include <thread>
unsigned int TargetVersion = 0x00001000; // maps to, say, SPIR-V 1.0
std::vector<std::string> Processes; // what should be recorded by OpModuleProcessed, or equivalent
-std::array<unsigned int, EShLangCount> baseSamplerBinding;
-std::array<unsigned int, EShLangCount> baseTextureBinding;
-std::array<unsigned int, EShLangCount> baseImageBinding;
-std::array<unsigned int, EShLangCount> baseUboBinding;
-std::array<unsigned int, EShLangCount> baseSsboBinding;
-std::array<unsigned int, EShLangCount> baseUavBinding;
+// Per descriptor-set binding base data
+typedef std::map<unsigned int, unsigned int> TPerSetBaseBinding;
+
+std::array<std::array<unsigned int, EShLangCount>, glslang::EResCount> baseBinding;
+std::array<std::array<TPerSetBaseBinding, EShLangCount>, glslang::EResCount> baseBindingForSet;
std::array<std::vector<std::string>, EShLangCount> baseResourceSetBinding;
// Add things like "#define ..." to a preamble to use in the beginning of the shader.
}
//
-// Process an optional binding base of the form:
-// --argname [stage] base
+// Process an optional binding base of one the forms:
+// --argname [stage] base // base for stage (if given) or all stages (if not)
+// --argname [stage] [set base]... // set/base pairs: set the base for given binding set.
+
// Where stage is one of the forms accepted by FindLanguage, and base is an integer
//
-void ProcessBindingBase(int& argc, char**& argv, std::array<unsigned int, EShLangCount>& base)
+void ProcessBindingBase(int& argc, char**& argv, glslang::TResourceType res)
{
if (argc < 2)
usage();
- if (!isdigit(argv[1][0])) {
+ EShLanguage lang = EShLangCount;
+ int singleBase = 0;
+ TPerSetBaseBinding perSetBase;
+ int arg = 1;
+
+ // Parse stage, if given
+ if (!isdigit(argv[arg][0])) {
if (argc < 3) // this form needs one more argument
usage();
- // Parse form: --argname stage base
- const EShLanguage lang = FindLanguage(argv[1], false);
- base[lang] = atoi(argv[2]);
- argc-= 2;
- argv+= 2;
+ lang = FindLanguage(argv[arg++], false);
+ }
+
+ if ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) {
+ // Parse a per-set binding base
+ while ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) {
+ const int setNum = atoi(argv[arg++]);
+ const int baseNum = atoi(argv[arg++]);
+ perSetBase[setNum] = baseNum;
+ }
} else {
- // Parse form: --argname base
- for (int lang=0; lang<EShLangCount; ++lang)
- base[lang] = atoi(argv[1]);
+ // Parse single binding base
+ singleBase = atoi(argv[arg++]);
+ }
- argc--;
- argv++;
+ argc -= (arg-1);
+ argv += (arg-1);
+
+ // Set one or all languages
+ const int langMin = (lang < EShLangCount) ? lang+0 : 0;
+ const int langMax = (lang < EShLangCount) ? lang+1 : EShLangCount;
+
+ for (int lang = langMin; lang < langMax; ++lang) {
+ if (!perSetBase.empty())
+ baseBindingForSet[res][lang] = perSetBase;
+ else
+ baseBinding[res][lang] = singleBase;
}
}
//
void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItems, int argc, char* argv[])
{
- baseSamplerBinding.fill(0);
- baseTextureBinding.fill(0);
- baseImageBinding.fill(0);
- baseUboBinding.fill(0);
- baseSsboBinding.fill(0);
- baseUavBinding.fill(0);
+ for (int res = 0; res < glslang::EResCount; ++res)
+ baseBinding[res].fill(0);
ExecutableName = argv[0];
workItems.reserve(argc);
} else if (lowerword == "shift-image-bindings" || // synonyms
lowerword == "shift-image-binding" ||
lowerword == "sib") {
- ProcessBindingBase(argc, argv, baseImageBinding);
+ ProcessBindingBase(argc, argv, glslang::EResImage);
} else if (lowerword == "shift-sampler-bindings" || // synonyms
lowerword == "shift-sampler-binding" ||
lowerword == "ssb") {
- ProcessBindingBase(argc, argv, baseSamplerBinding);
+ ProcessBindingBase(argc, argv, glslang::EResSampler);
} else if (lowerword == "shift-uav-bindings" || // synonyms
lowerword == "shift-uav-binding" ||
lowerword == "suavb") {
- ProcessBindingBase(argc, argv, baseUavBinding);
+ ProcessBindingBase(argc, argv, glslang::EResUav);
} else if (lowerword == "shift-texture-bindings" || // synonyms
lowerword == "shift-texture-binding" ||
lowerword == "stb") {
- ProcessBindingBase(argc, argv, baseTextureBinding);
+ ProcessBindingBase(argc, argv, glslang::EResTexture);
} else if (lowerword == "shift-ubo-bindings" || // synonyms
lowerword == "shift-ubo-binding" ||
lowerword == "shift-cbuffer-bindings" ||
lowerword == "shift-cbuffer-binding" ||
lowerword == "sub" ||
lowerword == "scb") {
- ProcessBindingBase(argc, argv, baseUboBinding);
+ ProcessBindingBase(argc, argv, glslang::EResUbo);
} else if (lowerword == "shift-ssbo-bindings" || // synonyms
lowerword == "shift-ssbo-binding" ||
lowerword == "sbb") {
- ProcessBindingBase(argc, argv, baseSsboBinding);
+ ProcessBindingBase(argc, argv, glslang::EResSsbo);
} else if (lowerword == "source-entrypoint" || // synonyms
lowerword == "sep") {
if (argc <= 1)
shader->setPreamble(UserPreamble.get());
shader->addProcesses(Processes);
- shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]);
- shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
- shader->setShiftImageBinding(baseImageBinding[compUnit.stage]);
- shader->setShiftUboBinding(baseUboBinding[compUnit.stage]);
- shader->setShiftSsboBinding(baseSsboBinding[compUnit.stage]);
- shader->setShiftUavBinding(baseUavBinding[compUnit.stage]);
+ // Set IO mapper binding shift values
+ for (int r = 0; r < glslang::EResCount; ++r) {
+ const glslang::TResourceType res = glslang::TResourceType(r);
+
+ // Set base bindings
+ shader->setShiftBinding(res, baseBinding[res][compUnit.stage]);
+
+ // Set bindings for particular resource sets
+ // TODO: use a range based for loop here, when available in all environments.
+ for (auto i = baseBindingForSet[res][compUnit.stage].begin();
+ i != baseBindingForSet[res][compUnit.stage].end(); ++i)
+ shader->setShiftBindingForSet(res, i->first, i->second);
+ }
+
shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0);
shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0);
shader->setResourceSetBinding(baseResourceSetBinding[compUnit.stage]);
" Set descriptor set for all resources\n"
" --rsb [stage] type set binding synonym for --resource-set-binding\n"
" --shift-image-binding [stage] num base binding number for images (uav)\n"
+ " --shift-image-binding [stage] [set num]... per-descriptor-set shift values\n"
" --sib [stage] num synonym for --shift-image-binding\n"
" --shift-sampler-binding [stage] num base binding number for samplers\n"
+ " --shift-sampler-binding [stage] [set num]... per-descriptor-set shift values\n"
" --ssb [stage] num synonym for --shift-sampler-binding\n"
" --shift-ssbo-binding [stage] num base binding number for SSBOs\n"
+ " --shift-ssbo-binding [stage] [set num]... per-descriptor-set shift values\n"
" --sbb [stage] num synonym for --shift-ssbo-binding\n"
" --shift-texture-binding [stage] num base binding number for textures\n"
+ " --shift-texture-binding [stage] [set num]... per-descriptor-set shift values\n"
" --stb [stage] num synonym for --shift-texture-binding\n"
" --shift-uav-binding [stage] num base binding number for UAVs\n"
+ " --shift-uav-binding [stage] [set num]... per-descriptor-set shift values\n"
" --suavb [stage] num synonym for --shift-uav-binding\n"
" --shift-UBO-binding [stage] num base binding number for UBOs\n"
+ " --shift-UBO-binding [stage] [set num]... per-descriptor-set shift values\n"
" --shift-cbuffer-binding [stage] num synonym for --shift-UBO-binding\n"
+ " --shift-cbuffer-binding [stage] [set num]... per-descriptor-set shift values\n"
" --sub [stage] num synonym for --shift-UBO-binding\n"
" --source-entrypoint <name> the given shader source function is\n"
" renamed to be the <name> given in -e\n"
--- /dev/null
+hlsl.shift.per-set.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:34 Function Definition: @main( ( temp 4-component vector of float)
+0:34 Function Parameters:
+0:? Sequence
+0:35 't1' (layout( set=1 binding=1) uniform texture1D)
+0:36 't2' (layout( set=1 binding=2) uniform texture2D)
+0:37 't3' (layout( set=2 binding=1) uniform texture3D)
+0:38 direct index (layout( row_major std430) buffer 4-component vector of float)
+0:38 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of float)
+0:38 't4' (layout( set=3 binding=1 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:38 Constant:
+0:38 0 (const uint)
+0:38 Constant:
+0:38 0 (const int)
+0:39 indirect index (layout( row_major std430) buffer uint)
+0:39 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
+0:39 't5' (layout( set=3 binding=2 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
+0:39 Constant:
+0:39 0 (const uint)
+0:39 right-shift ( temp int)
+0:39 Constant:
+0:39 0 (const int)
+0:39 Constant:
+0:39 2 (const int)
+0:40 't6' (layout( set=3 binding=3 rgba32f) uniform textureBuffer)
+0:42 's1' (layout( set=1 binding=1) uniform sampler)
+0:43 's2' (layout( set=2 binding=2) uniform sampler)
+0:45 'u1' (layout( set=1 binding=1 rgba32f) uniform image1D)
+0:46 'u2' (layout( set=2 binding=2 rgba32f) uniform image2D)
+0:47 'u3' (layout( set=2 binding=3 rgba32f) uniform image3D)
+0:49 imageLoad ( temp float)
+0:49 'u4' (layout( set=1 binding=4 r32f) uniform imageBuffer)
+0:49 Constant:
+0:49 0 (const int)
+0:50 indirect index (layout( row_major std430) buffer uint)
+0:50 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
+0:50 'u5' (layout( set=2 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
+0:50 Constant:
+0:50 0 (const uint)
+0:50 right-shift ( temp int)
+0:50 Constant:
+0:50 0 (const int)
+0:50 Constant:
+0:50 2 (const int)
+0:51 direct index (layout( row_major std430) buffer float)
+0:51 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of float)
+0:51 'u6' (layout( set=3 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:51 Constant:
+0:51 0 (const uint)
+0:51 Constant:
+0:51 0 (const int)
+0:52 'u7' (layout( set=4 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:53 'u8' (layout( set=5 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:55 cb1: direct index for structure (layout( row_major std140) uniform int)
+0:55 'anon@0' (layout( set=6 binding=1 row_major std140) uniform block{layout( row_major std140) uniform int cb1})
+0:55 Constant:
+0:55 0 (const uint)
+0:56 tb1: direct index for structure (layout( row_major std430) buffer int)
+0:56 'anon@1' (layout( binding=7 row_major std430) readonly buffer block{layout( row_major std430) buffer int tb1})
+0:56 Constant:
+0:56 0 (const uint)
+0:58 Branch: Return with expression
+0:58 Constant:
+0:58 0.000000
+0:58 0.000000
+0:58 0.000000
+0:58 0.000000
+0:34 Function Definition: main( ( temp void)
+0:34 Function Parameters:
+0:? Sequence
+0:34 move second child to first child ( temp 4-component vector of float)
+0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:34 Function Call: @main( ( temp 4-component vector of float)
+0:? Linker Objects
+0:? 's1' (layout( set=1 binding=1) uniform sampler)
+0:? 's2' (layout( set=2 binding=2) uniform sampler)
+0:? 't1' (layout( set=1 binding=1) uniform texture1D)
+0:? 't2' (layout( set=1 binding=2) uniform texture2D)
+0:? 't3' (layout( set=2 binding=1) uniform texture3D)
+0:? 't4' (layout( set=3 binding=1 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:? 't5' (layout( set=3 binding=2 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
+0:? 't6' (layout( set=3 binding=3 rgba32f) uniform textureBuffer)
+0:? 'u1' (layout( set=1 binding=1 rgba32f) uniform image1D)
+0:? 'u2' (layout( set=2 binding=2 rgba32f) uniform image2D)
+0:? 'u3' (layout( set=2 binding=3 rgba32f) uniform image3D)
+0:? 'u4' (layout( set=1 binding=4 r32f) uniform imageBuffer)
+0:? 'u5' (layout( set=2 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
+0:? 'u6' (layout( set=3 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:? 'u7' (layout( set=4 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:? 'u8' (layout( set=5 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:? 'anon@0' (layout( set=6 binding=1 row_major std140) uniform block{layout( row_major std140) uniform int cb1})
+0:? 'anon@1' (layout( binding=7 row_major std430) readonly buffer block{layout( row_major std430) buffer int tb1})
+0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:34 Function Definition: @main( ( temp 4-component vector of float)
+0:34 Function Parameters:
+0:? Sequence
+0:35 't1' (layout( set=1 binding=1) uniform texture1D)
+0:36 't2' (layout( set=1 binding=2) uniform texture2D)
+0:37 't3' (layout( set=2 binding=1) uniform texture3D)
+0:38 direct index (layout( row_major std430) buffer 4-component vector of float)
+0:38 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of 4-component vector of float)
+0:38 't4' (layout( set=3 binding=1 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:38 Constant:
+0:38 0 (const uint)
+0:38 Constant:
+0:38 0 (const int)
+0:39 indirect index (layout( row_major std430) buffer uint)
+0:39 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
+0:39 't5' (layout( set=3 binding=2 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
+0:39 Constant:
+0:39 0 (const uint)
+0:39 right-shift ( temp int)
+0:39 Constant:
+0:39 0 (const int)
+0:39 Constant:
+0:39 2 (const int)
+0:40 't6' (layout( set=3 binding=3 rgba32f) uniform textureBuffer)
+0:42 's1' (layout( set=1 binding=1) uniform sampler)
+0:43 's2' (layout( set=2 binding=2) uniform sampler)
+0:45 'u1' (layout( set=1 binding=1 rgba32f) uniform image1D)
+0:46 'u2' (layout( set=2 binding=2 rgba32f) uniform image2D)
+0:47 'u3' (layout( set=2 binding=3 rgba32f) uniform image3D)
+0:49 imageLoad ( temp float)
+0:49 'u4' (layout( set=1 binding=4 r32f) uniform imageBuffer)
+0:49 Constant:
+0:49 0 (const int)
+0:50 indirect index (layout( row_major std430) buffer uint)
+0:50 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint)
+0:50 'u5' (layout( set=2 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
+0:50 Constant:
+0:50 0 (const uint)
+0:50 right-shift ( temp int)
+0:50 Constant:
+0:50 0 (const int)
+0:50 Constant:
+0:50 2 (const int)
+0:51 direct index (layout( row_major std430) buffer float)
+0:51 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of float)
+0:51 'u6' (layout( set=3 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:51 Constant:
+0:51 0 (const uint)
+0:51 Constant:
+0:51 0 (const int)
+0:52 'u7' (layout( set=4 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:53 'u8' (layout( set=5 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:55 cb1: direct index for structure (layout( row_major std140) uniform int)
+0:55 'anon@0' (layout( set=6 binding=1 row_major std140) uniform block{layout( row_major std140) uniform int cb1})
+0:55 Constant:
+0:55 0 (const uint)
+0:56 tb1: direct index for structure (layout( row_major std430) buffer int)
+0:56 'anon@1' (layout( binding=7 row_major std430) readonly buffer block{layout( row_major std430) buffer int tb1})
+0:56 Constant:
+0:56 0 (const uint)
+0:58 Branch: Return with expression
+0:58 Constant:
+0:58 0.000000
+0:58 0.000000
+0:58 0.000000
+0:58 0.000000
+0:34 Function Definition: main( ( temp void)
+0:34 Function Parameters:
+0:? Sequence
+0:34 move second child to first child ( temp 4-component vector of float)
+0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:34 Function Call: @main( ( temp 4-component vector of float)
+0:? Linker Objects
+0:? 's1' (layout( set=1 binding=1) uniform sampler)
+0:? 's2' (layout( set=2 binding=2) uniform sampler)
+0:? 't1' (layout( set=1 binding=1) uniform texture1D)
+0:? 't2' (layout( set=1 binding=2) uniform texture2D)
+0:? 't3' (layout( set=2 binding=1) uniform texture3D)
+0:? 't4' (layout( set=3 binding=1 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:? 't5' (layout( set=3 binding=2 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
+0:? 't6' (layout( set=3 binding=3 rgba32f) uniform textureBuffer)
+0:? 'u1' (layout( set=1 binding=1 rgba32f) uniform image1D)
+0:? 'u2' (layout( set=2 binding=2 rgba32f) uniform image2D)
+0:? 'u3' (layout( set=2 binding=3 rgba32f) uniform image3D)
+0:? 'u4' (layout( set=1 binding=4 r32f) uniform imageBuffer)
+0:? 'u5' (layout( set=2 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data})
+0:? 'u6' (layout( set=3 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:? 'u7' (layout( set=4 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:? 'u8' (layout( set=5 binding=4 row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of float @data})
+0:? 'anon@0' (layout( set=6 binding=1 row_major std140) uniform block{layout( row_major std140) uniform int cb1})
+0:? 'anon@1' (layout( binding=7 row_major std430) readonly buffer block{layout( row_major std430) buffer int tb1})
+0:? '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+Uniform reflection:
+t1: offset -1, type 8b5d, size 1, index -1, binding 21
+t2: offset -1, type 8b5e, size 1, index -1, binding 22
+t3: offset -1, type 8b5f, size 1, index -1, binding 26
+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 23
+s1: offset -1, type 0, size 1, index -1, binding 11
+s2: offset -1, type 0, size 1, index -1, binding 17
+u1: offset -1, type 904c, size 1, index -1, binding 31
+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 34
+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 21
+t5: offset -1, type ffffffff, size 0, index -1, binding 22
+u5: offset -1, type ffffffff, size 0, index -1, binding 44
+u6: offset -1, type ffffffff, size 0, index -1, binding 34
+cb: offset -1, type ffffffff, size 4, index -1, binding 51
+tb: offset -1, type ffffffff, size 4, index -1, binding 27
+
+Vertex attribute reflection:
+
--- /dev/null
+// Test register class offsets for different resource types
+
+SamplerState s1 : register(s1, space1);
+SamplerComparisonState s2 : register(s2, space2);
+
+Texture1D <float4> t1 : register(t1, space1);
+Texture2D <float4> t2 : register(t2, space1);
+Texture3D <float4> t3 : register(t1, space2);
+
+StructuredBuffer<float4> t4 : register(t1, space3);
+
+ByteAddressBuffer t5 : register(t2, space3);
+Buffer<float4> t6 : register(t3, space3);
+
+RWTexture1D <float4> u1 : register(u1, space1);
+RWTexture2D <float4> u2 : register(u2, space2);
+RWTexture3D <float4> u3 : register(u3, space2);
+
+RWBuffer <float> u4 : register(u4, space1);
+RWByteAddressBuffer u5 : register(u4, space2);
+RWStructuredBuffer<float> u6 : register(u4, space3);
+AppendStructuredBuffer<float> u7 : register(u4, space4);
+ConsumeStructuredBuffer<float> u8 : register(u4, space5);
+
+cbuffer cb : register(b1, space6) {
+ 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;
+ u8;
+
+ cb1;
+ tb1;
+
+ return 0;
+}
diff -b $BASEDIR/hlsl.explicitDescriptorSet-2.frag.out $TARGETDIR/hlsl.explicitDescriptorSet-2.frag.out || HASERROR=1
#
+# Testing per-descriptor-set IO map shift
+#
+echo 'Testing per-descriptor-set IO map shift'
+$EXE -e main --hlsl-iomap --ssb 1 10 2 15 --stb 20 --stb 2 25 --suavb 30 --suavb 2 40 --sub 6 50 -i -q -D -V hlsl.shift.per-set.frag > $TARGETDIR/hlsl.shift.per-set.frag.out || HASERROR=1
+diff -b $BASEDIR/hlsl.shift.per-set.frag.out $TARGETDIR/hlsl.shift.per-set.frag.out || HASERROR=1
+
+#
# Testing location error
#
echo Testing SPV no location
root->traverse(&transform);
}
+const char* TIntermediate::getResourceName(TResourceType res)
+{
+ switch (res) {
+ case EResSampler: return "shift-sampler-binding";
+ case EResTexture: return "shift-texture-binding";
+ case EResImage: return "shift-image-binding";
+ case EResUbo: return "shift-UBO-binding";
+ case EResSsbo: return "shift-ssbo-binding";
+ case EResUav: return "shift-uav-binding";
+ default:
+ assert(0); // internal error: should only be called with valid resource types.
+ return nullptr;
+ }
+}
+
+
} // end namespace glslang
intermediate->addProcesses(p);
}
+// Set binding base for given resource type
+void TShader::setShiftBinding(TResourceType res, unsigned int base) {
+ intermediate->setShiftBinding(res, base);
+}
+
+// Set binding base for given resource type for a given binding set.
+void TShader::setShiftBindingForSet(TResourceType res, unsigned int set, unsigned int base) {
+ intermediate->setShiftBindingForSet(res, set, base);
+}
+
// Set binding base for sampler types
-void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); }
+void TShader::setShiftSamplerBinding(unsigned int base) { setShiftBinding(EResSampler, base); }
// Set binding base for texture types (SRV)
-void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
+void TShader::setShiftTextureBinding(unsigned int base) { setShiftBinding(EResTexture, base); }
// Set binding base for image types
-void TShader::setShiftImageBinding(unsigned int base) { intermediate->setShiftImageBinding(base); }
+void TShader::setShiftImageBinding(unsigned int base) { setShiftBinding(EResImage, base); }
// Set binding base for uniform buffer objects (CBV)
-void TShader::setShiftUboBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
+void TShader::setShiftUboBinding(unsigned int base) { setShiftBinding(EResUbo, base); }
// Synonym for setShiftUboBinding, to match HLSL language.
-void TShader::setShiftCbufferBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
+void TShader::setShiftCbufferBinding(unsigned int base) { setShiftBinding(EResUbo, base); }
// Set binding base for UAV (unordered access view)
-void TShader::setShiftUavBinding(unsigned int base) { intermediate->setShiftUavBinding(base); }
+void TShader::setShiftUavBinding(unsigned int base) { setShiftBinding(EResUav, base); }
// Set binding base for SSBOs
-void TShader::setShiftSsboBinding(unsigned int base) { intermediate->setShiftSsboBinding(base); }
+void TShader::setShiftSsboBinding(unsigned int base) { setShiftBinding(EResSsbo, base); }
// Enables binding automapping using TIoMapper
void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); }
// Fragile: currently within one stage: simple auto-assignment of location
// 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;
- std::vector<std::string> baseResourceSetBinding;
- bool doAutoBindingMapping;
- bool doAutoLocationMapping;
- int nextUniformLocation;
+ TDefaultIoResolverBase(const TIntermediate &intermediate) :
+ intermediate(intermediate),
+ nextUniformLocation(0)
+ { }
+
+ int getBaseBinding(TResourceType res, unsigned int set) const {
+ return selectBaseBinding(intermediate.getShiftBinding(res),
+ intermediate.getShiftBindingForSet(res, set));
+ }
+
+ const std::vector<std::string>& getResourceSetBinding() const { return intermediate.getResourceSetBinding(); }
+
+ bool doAutoBindingMapping() const { return intermediate.getAutoMapBindings(); }
+ bool doAutoLocationMapping() const { return intermediate.getAutoMapLocations(); }
+
typedef std::vector<int> TSlotSet;
typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
TSlotSetMap slots;
return type.getQualifier().layoutSet;
// If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
- if (baseResourceSetBinding.size() == 1)
- return atoi(baseResourceSetBinding[0].c_str());
+ if (getResourceSetBinding().size() == 1)
+ return atoi(getResourceSetBinding()[0].c_str());
return 0;
}
int resolveUniformLocation(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override
{
// kick out of not doing this
- if (!doAutoLocationMapping)
+ if (!doAutoLocationMapping())
return -1;
// no locations added if already present, a built-in variable, a block, or an opaque
int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& type, bool /*is_live*/) override
{
// kick out of not doing this
- if (!doAutoLocationMapping)
+ if (!doAutoLocationMapping())
return -1;
// no locations added if already present, or a built-in variable
void endResolve(EShLanguage) override {}
protected:
+ const TIntermediate &intermediate;
+ int nextUniformLocation;
+
+ // Return descriptor set specific base if there is one, and the generic base otherwise.
+ int selectBaseBinding(int base, int descriptorSetBase) const {
+ return descriptorSetBase != -1 ? descriptorSetBase : base;
+ }
+
static int getLayoutSet(const glslang::TType& type) {
if (type.getQualifier().hasSet())
return type.getQualifier().layoutSet;
*/
struct TDefaultIoResolver : public TDefaultIoResolverBase
{
+ TDefaultIoResolver(const TIntermediate &intermediate) : TDefaultIoResolverBase(intermediate) { }
+
bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
{
return true;
if (type.getQualifier().hasBinding()) {
if (isImageType(type))
- return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding);
+ return reserveSlot(set, getBaseBinding(EResImage, set) + type.getQualifier().layoutBinding);
if (isTextureType(type))
- return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
+ return reserveSlot(set, getBaseBinding(EResTexture, set) + type.getQualifier().layoutBinding);
if (isSsboType(type))
- return reserveSlot(set, baseSsboBinding + type.getQualifier().layoutBinding);
+ return reserveSlot(set, getBaseBinding(EResSsbo, set) + type.getQualifier().layoutBinding);
if (isSamplerType(type))
- return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
+ return reserveSlot(set, getBaseBinding(EResSampler, set) + type.getQualifier().layoutBinding);
if (isUboType(type))
- return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
- } else if (is_live && doAutoBindingMapping) {
+ return reserveSlot(set, getBaseBinding(EResUbo, set) + type.getQualifier().layoutBinding);
+ } else if (is_live && doAutoBindingMapping()) {
// 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);
+ return getFreeSlot(set, getBaseBinding(EResImage, set));
if (isTextureType(type))
- return getFreeSlot(set, baseTextureBinding);
+ return getFreeSlot(set, getBaseBinding(EResTexture, set));
if (isSsboType(type))
- return getFreeSlot(set, baseSsboBinding);
+ return getFreeSlot(set, getBaseBinding(EResSsbo, set));
if (isSamplerType(type))
- return getFreeSlot(set, baseSamplerBinding);
+ return getFreeSlot(set, getBaseBinding(EResSampler, set));
if (isUboType(type))
- return getFreeSlot(set, baseUboBinding);
+ return getFreeSlot(set, getBaseBinding(EResUbo, set));
}
return -1;
********************************************************************************/
struct TDefaultHlslIoResolver : public TDefaultIoResolverBase
{
+ TDefaultHlslIoResolver(const TIntermediate &intermediate) : TDefaultIoResolverBase(intermediate) { }
+
bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
{
return true;
if (type.getQualifier().hasBinding()) {
if (isUavType(type))
- return reserveSlot(set, baseUavBinding + type.getQualifier().layoutBinding);
+ return reserveSlot(set, getBaseBinding(EResUav, set) + type.getQualifier().layoutBinding);
if (isSrvType(type))
- return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
+ return reserveSlot(set, getBaseBinding(EResTexture, set) + type.getQualifier().layoutBinding);
if (isSamplerType(type))
- return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
+ return reserveSlot(set, getBaseBinding(EResSampler, set) + type.getQualifier().layoutBinding);
if (isUboType(type))
- return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
- } else if (is_live && doAutoBindingMapping) {
+ return reserveSlot(set, getBaseBinding(EResUbo, set) + type.getQualifier().layoutBinding);
+ } else if (is_live && doAutoBindingMapping()) {
// 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);
+ return getFreeSlot(set, getBaseBinding(EResUav, set));
if (isSrvType(type))
- return getFreeSlot(set, baseTextureBinding);
+ return getFreeSlot(set, getBaseBinding(EResTexture, set));
if (isSamplerType(type))
- return getFreeSlot(set, baseSamplerBinding);
+ return getFreeSlot(set, getBaseBinding(EResSampler, set));
if (isUboType(type))
- return getFreeSlot(set, baseUboBinding);
+ return getFreeSlot(set, getBaseBinding(EResUbo, set));
}
return -1;
// Returns false if the input is too malformed to do this.
bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSink &infoSink, TIoMapResolver *resolver)
{
- // Trivial return if there is nothing to do.
- if (intermediate.getShiftSamplerBinding() == 0 &&
- intermediate.getShiftTextureBinding() == 0 &&
- intermediate.getShiftImageBinding() == 0 &&
- intermediate.getShiftUboBinding() == 0 &&
- intermediate.getShiftSsboBinding() == 0 &&
- intermediate.getShiftUavBinding() == 0 &&
- intermediate.getResourceSetBinding().empty() &&
- intermediate.getAutoMapBindings() == false &&
- intermediate.getAutoMapLocations() == false &&
- resolver == nullptr)
+ bool somethingToDo = !intermediate.getResourceSetBinding().empty() ||
+ intermediate.getAutoMapBindings() ||
+ intermediate.getAutoMapLocations();
+
+ for (int res = 0; res < EResCount; ++res) {
+ somethingToDo = somethingToDo ||
+ (intermediate.getShiftBinding(TResourceType(res)) != 0) ||
+ intermediate.hasShiftBindingForSet(TResourceType(res));
+ }
+
+ if (!somethingToDo && resolver == nullptr)
return true;
if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
return false;
// if no resolver is provided, use the default resolver with the given shifts and auto map settings
- TDefaultIoResolver defaultResolver;
- TDefaultHlslIoResolver defaultHlslResolver;
+ TDefaultIoResolver defaultResolver(intermediate);
+ TDefaultHlslIoResolver defaultHlslResolver(intermediate);
if (resolver == nullptr) {
- TDefaultIoResolverBase* resolverBase;
-
// TODO: use a passed in IO mapper for this
if (intermediate.usingHlslIoMapping())
- resolverBase = &defaultHlslResolver;
+ resolver = &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->baseResourceSetBinding = intermediate.getResourceSetBinding();
- resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings();
- resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations();
- resolverBase->nextUniformLocation = 0;
-
- resolver = resolverBase;
+ resolver = &defaultResolver;
}
TVarLiveMap inVarMap, outVarMap, uniformVarMap;
#include <algorithm>
#include <set>
+#include <array>
class TInfoSink;
layoutOverrideCoverage(false),
geoPassthroughEXT(false),
#endif
- shiftSamplerBinding(0),
- shiftTextureBinding(0),
- shiftImageBinding(0),
- shiftUboBinding(0),
- shiftSsboBinding(0),
- shiftUavBinding(0),
autoMapBindings(false),
autoMapLocations(false),
flattenUniformArrays(false),
localSizeSpecId[1] = TQualifier::layoutNotSet;
localSizeSpecId[2] = TQualifier::layoutNotSet;
xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
+
+ shiftBinding.fill(0);
}
void setLimits(const TBuiltInResource& r) { resources = r; }
const std::string& getEntryPointName() const { return entryPointName; }
const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
- void setShiftSamplerBinding(unsigned int shift)
- {
- shiftSamplerBinding = shift;
- processes.addIfNonZero("shift-sampler-binding", shift);
- }
- unsigned int getShiftSamplerBinding() const { return shiftSamplerBinding; }
- void setShiftTextureBinding(unsigned int shift)
- {
- shiftTextureBinding = shift;
- processes.addIfNonZero("shift-texture-binding", shift);
- }
- unsigned int getShiftTextureBinding() const { return shiftTextureBinding; }
- void setShiftImageBinding(unsigned int shift)
+ void setShiftBinding(TResourceType res, unsigned int shift)
{
- shiftImageBinding = shift;
- processes.addIfNonZero("shift-image-binding", shift);
- }
- unsigned int getShiftImageBinding() const { return shiftImageBinding; }
- void setShiftUboBinding(unsigned int shift)
- {
- shiftUboBinding = shift;
- processes.addIfNonZero("shift-UBO-binding", shift);
+ shiftBinding[res] = shift;
+
+ const char* name = getResourceName(res);
+ if (name != nullptr)
+ processes.addIfNonZero(name, shift);
}
- unsigned int getShiftUboBinding() const { return shiftUboBinding; }
- void setShiftSsboBinding(unsigned int shift)
+
+ unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; }
+
+ void setShiftBindingForSet(TResourceType res, unsigned int set, unsigned int shift)
{
- shiftSsboBinding = shift;
- processes.addIfNonZero("shift-ssbo-binding", shift);
+ if (shift == 0) // ignore if there's no shift: it's a no-op.
+ return;
+
+ shiftBindingForSet[res][set] = shift;
+
+ const char* name = getResourceName(res);
+ if (name != nullptr) {
+ processes.addProcess(name);
+ processes.addArgument(set);
+ processes.addArgument(shift);
+ }
}
- unsigned int getShiftSsboBinding() const { return shiftSsboBinding; }
- void setShiftUavBinding(unsigned int shift)
+
+ int getShiftBindingForSet(TResourceType res, unsigned int set) const
{
- shiftUavBinding = shift;
- processes.addIfNonZero("shift-uav-binding", shift);
+ const auto shift = shiftBindingForSet[res].find(set);
+ return shift == shiftBindingForSet[res].end() ? -1 : shift->second;
}
- unsigned int getShiftUavBinding() const { return shiftUavBinding; }
+ bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); }
+
void setResourceSetBinding(const std::vector<std::string>& shift)
{
resourceSetBinding = shift;
void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
+ static const char* getResourceName(TResourceType);
const EShLanguage language; // stage, known at construction time
EShSource source; // source language, known a bit later
bool geoPassthroughEXT;
#endif
- unsigned int shiftSamplerBinding;
- unsigned int shiftTextureBinding;
- unsigned int shiftImageBinding;
- unsigned int shiftUboBinding;
- unsigned int shiftSsboBinding;
- unsigned int shiftUavBinding;
+ // Base shift values
+ std::array<unsigned int, EResCount> shiftBinding;
+
+ // Per-descriptor-set shift values
+ typedef std::map<int, int> TDescriptorSetShift;
+ TDescriptorSetShift shiftBindingForSet[EResCount];
+
std::vector<std::string> resourceSetBinding;
bool autoMapBindings;
bool autoMapLocations;
// Call once per process to tear down everything
void FinalizeProcess();
+// Resource type for IO resolver
+enum TResourceType {
+ EResSampler,
+ EResTexture,
+ EResImage,
+ EResUbo,
+ EResSsbo,
+ EResUav,
+ EResCount
+};
+
// Make one TShader per shader that you will link into a program. Then provide
// the shader through setStrings() or setStringsWithLengths(), then call parse(),
// then query the info logs.
void setEntryPoint(const char* entryPoint);
void setSourceEntryPoint(const char* sourceEntryPointName);
void addProcesses(const std::vector<std::string>&);
- void setShiftSamplerBinding(unsigned int base);
- 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);
+
+ // IO resolver binding data: see comments in ShaderLang.cpp
+ void setShiftBinding(TResourceType res, unsigned int base);
+ void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
+ void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
+ void setShiftBindingForSet(TResourceType res, unsigned int set, unsigned int base);
void setResourceSetBinding(const std::vector<std::string>& base);
void setAutoMapBindings(bool map);
void setAutoMapLocations(bool map);