New command line option --shift-ssbo-binding mirrors --shift-ubo-binding, etc.
New reflection query getLocalSize(int dim) queries local size, e.g, CS threads.
std::array<unsigned int, EShLangCount> baseTextureBinding;
std::array<unsigned int, EShLangCount> baseImageBinding;
std::array<unsigned int, EShLangCount> baseUboBinding;
+std::array<unsigned int, EShLangCount> baseSsboBinding;
//
// Create the default name for saving a binary if -o is not provided.
baseTextureBinding.fill(0);
baseImageBinding.fill(0);
baseUboBinding.fill(0);
+ baseSsboBinding.fill(0);
ExecutableName = argv[0];
NumWorkItems = argc; // will include some empties where the '-' options were, but it doesn't matter, they'll be 0
lowerword == "shift-ubo-binding" ||
lowerword == "sub") {
ProcessBindingBase(argc, argv, baseUboBinding);
+ } else if (lowerword == "shift-ssbo-bindings" || // synonyms
+ lowerword == "shift-ssbo-binding" ||
+ lowerword == "sbb") {
+ ProcessBindingBase(argc, argv, baseSsboBinding);
} else if (lowerword == "auto-map-bindings" || // synonyms
lowerword == "auto-map-binding" ||
lowerword == "amb") {
shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
shader->setShiftImageBinding(baseImageBinding[compUnit.stage]);
shader->setShiftUboBinding(baseUboBinding[compUnit.stage]);
+ shader->setShiftSsboBinding(baseSsboBinding[compUnit.stage]);
shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0);
shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0);
" --shift-UBO-binding [stage] num set base binding number for UBOs\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"
" --auto-map-bindings automatically bind uniform variables without\n"
" explicit bindings.\n"
" --amb synonym for --auto-map-bindings\n"
--- /dev/null
+spv.ssbo.autoassign.frag
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 95
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main" 88 91
+ ExecutionMode 4 OriginUpperLeft
+ Name 4 "main"
+ Name 11 "@main(vf4;"
+ Name 10 "pos"
+ Name 13 "vTmp"
+ Name 14 "BufType"
+ MemberName 14(BufType) 0 "va"
+ MemberName 14(BufType) 1 "vb"
+ Name 16 "SB0"
+ MemberName 16(SB0) 0 "SB0"
+ Name 18 ""
+ Name 26 "TestCB"
+ MemberName 26(TestCB) 0 "W"
+ MemberName 26(TestCB) 1 "H"
+ Name 28 ""
+ Name 55 "SB1"
+ MemberName 55(SB1) 0 "SB1"
+ Name 57 ""
+ Name 86 "pos"
+ Name 88 "pos"
+ Name 91 "@entryPointOutput"
+ Name 92 "param"
+ MemberDecorate 14(BufType) 0 NonWritable
+ MemberDecorate 14(BufType) 0 Offset 0
+ MemberDecorate 14(BufType) 1 NonWritable
+ MemberDecorate 14(BufType) 1 Offset 16
+ Decorate 15 ArrayStride 32
+ MemberDecorate 16(SB0) 0 NonWritable
+ MemberDecorate 16(SB0) 0 Offset 0
+ Decorate 16(SB0) BufferBlock
+ Decorate 18 DescriptorSet 0
+ Decorate 18 Binding 30
+ MemberDecorate 26(TestCB) 0 Offset 0
+ MemberDecorate 26(TestCB) 1 Offset 4
+ Decorate 26(TestCB) Block
+ Decorate 28 DescriptorSet 0
+ Decorate 28 Binding 15
+ Decorate 54 ArrayStride 32
+ MemberDecorate 55(SB1) 0 Offset 0
+ Decorate 55(SB1) BufferBlock
+ Decorate 57 DescriptorSet 0
+ Decorate 57 Binding 31
+ Decorate 88(pos) Location 0
+ Decorate 91(@entryPointOutput) Location 0
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8: TypePointer Function 7(fvec4)
+ 9: TypeFunction 7(fvec4) 8(ptr)
+ 14(BufType): TypeStruct 7(fvec4) 7(fvec4)
+ 15: TypeRuntimeArray 14(BufType)
+ 16(SB0): TypeStruct 15
+ 17: TypePointer Uniform 16(SB0)
+ 18: 17(ptr) Variable Uniform
+ 19: TypeInt 32 1
+ 20: 19(int) Constant 0
+ 21: TypeInt 32 0
+ 22: 21(int) Constant 1
+ 23: TypePointer Function 6(float)
+ 26(TestCB): TypeStruct 21(int) 21(int)
+ 27: TypePointer Uniform 26(TestCB)
+ 28: 27(ptr) Variable Uniform
+ 29: TypePointer Uniform 21(int)
+ 34: 21(int) Constant 0
+ 38: TypePointer Uniform 7(fvec4)
+ 50: 19(int) Constant 1
+ 54: TypeRuntimeArray 14(BufType)
+ 55(SB1): TypeStruct 54
+ 56: TypePointer Uniform 55(SB1)
+ 57: 56(ptr) Variable Uniform
+ 87: TypePointer Input 7(fvec4)
+ 88(pos): 87(ptr) Variable Input
+ 90: TypePointer Output 7(fvec4)
+91(@entryPointOutput): 90(ptr) Variable Output
+ 4(main): 2 Function None 3
+ 5: Label
+ 86(pos): 8(ptr) Variable Function
+ 92(param): 8(ptr) Variable Function
+ 89: 7(fvec4) Load 88(pos)
+ Store 86(pos) 89
+ 93: 7(fvec4) Load 86(pos)
+ Store 92(param) 93
+ 94: 7(fvec4) FunctionCall 11(@main(vf4;) 92(param)
+ Store 91(@entryPointOutput) 94
+ Return
+ FunctionEnd
+ 11(@main(vf4;): 7(fvec4) Function None 9
+ 10(pos): 8(ptr) FunctionParameter
+ 12: Label
+ 13(vTmp): 8(ptr) Variable Function
+ 24: 23(ptr) AccessChain 10(pos) 22
+ 25: 6(float) Load 24
+ 30: 29(ptr) AccessChain 28 20
+ 31: 21(int) Load 30
+ 32: 6(float) ConvertUToF 31
+ 33: 6(float) FMul 25 32
+ 35: 23(ptr) AccessChain 10(pos) 34
+ 36: 6(float) Load 35
+ 37: 6(float) FAdd 33 36
+ 39: 38(ptr) AccessChain 18 20 37 20
+ 40: 7(fvec4) Load 39
+ 41: 23(ptr) AccessChain 10(pos) 22
+ 42: 6(float) Load 41
+ 43: 29(ptr) AccessChain 28 20
+ 44: 21(int) Load 43
+ 45: 6(float) ConvertUToF 44
+ 46: 6(float) FMul 42 45
+ 47: 23(ptr) AccessChain 10(pos) 34
+ 48: 6(float) Load 47
+ 49: 6(float) FAdd 46 48
+ 51: 38(ptr) AccessChain 18 20 49 50
+ 52: 7(fvec4) Load 51
+ 53: 7(fvec4) FAdd 40 52
+ Store 13(vTmp) 53
+ 58: 23(ptr) AccessChain 10(pos) 22
+ 59: 6(float) Load 58
+ 60: 29(ptr) AccessChain 28 20
+ 61: 21(int) Load 60
+ 62: 6(float) ConvertUToF 61
+ 63: 6(float) FMul 59 62
+ 64: 23(ptr) AccessChain 10(pos) 34
+ 65: 6(float) Load 64
+ 66: 6(float) FAdd 63 65
+ 67: 38(ptr) AccessChain 57 20 66 20
+ 68: 7(fvec4) Load 67
+ 69: 23(ptr) AccessChain 10(pos) 22
+ 70: 6(float) Load 69
+ 71: 29(ptr) AccessChain 28 20
+ 72: 21(int) Load 71
+ 73: 6(float) ConvertUToF 72
+ 74: 6(float) FMul 70 73
+ 75: 23(ptr) AccessChain 10(pos) 34
+ 76: 6(float) Load 75
+ 77: 6(float) FAdd 74 76
+ 78: 38(ptr) AccessChain 57 20 77 50
+ 79: 7(fvec4) Load 78
+ 80: 7(fvec4) FAdd 68 79
+ 81: 7(fvec4) Load 13(vTmp)
+ 82: 7(fvec4) FAdd 81 80
+ Store 13(vTmp) 82
+ 83: 7(fvec4) Load 13(vTmp)
+ ReturnValue 83
+ FunctionEnd
--- /dev/null
+
+cbuffer TestCB
+{
+ uint W;
+ uint H;
+};
+
+struct BufType
+{
+ float4 va;
+ float4 vb;
+};
+
+StructuredBuffer < BufType > SB0;
+RWStructuredBuffer < BufType > SB1;
+
+float4 main(float4 pos : POS) : SV_Target0
+{
+ float4 vTmp = SB0[pos.y * W + pos.x].va + SB0[pos.y * W + pos.x].vb;
+
+ vTmp += SB1[pos.y * W + pos.x].va + SB1[pos.y * W + pos.x].vb;
+
+ return vTmp;
+}
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::setShiftSsboBinding(unsigned int base) { intermediate->setShiftSsboBinding(base); }
void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); }
void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); }
void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); }
const TType* TProgram::getAttributeTType(int index) const { return reflection->getAttribute(index).getType(); }
const TType* TProgram::getUniformTType(int index) const { return reflection->getUniform(index).getType(); }
const TType* TProgram::getUniformBlockTType(int index) const { return reflection->getUniformBlock(index).getType(); }
+unsigned TProgram::getLocalSize(int dim) const { return reflection->getLocalSize(dim); }
void TProgram::dumpReflection() { reflection->dump(); }
virtual void visitSymbol(TIntermSymbol* base)
{
- if (base->getQualifier().storage == EvqUniform) {
+ if (base->getType().getQualifier().isUniformOrBuffer()) {
TVarEntryInfo ent = { base->getId(), base, !traverseAll };
TVarLiveMap::iterator at = std::lower_bound(varLiveList.begin(), varLiveList.end(), ent, TVarEntryInfo::TOrderById());
if (at != varLiveList.end() && at->id == ent.id)
int baseTextureBinding;
int baseImageBinding;
int baseUboBinding;
+ int baseSsboBinding;
bool doAutoMapping;
typedef std::vector<int> TSlotSet;
typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
return checkEmpty(set, baseTextureBinding + type.getQualifier().layoutBinding);
}
- if (type.getQualifier().isUniformOrBuffer())
+ 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;
}
return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
}
- if (type.getQualifier().isUniformOrBuffer())
+ 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
return getFreeSlot(set, baseTextureBinding);
}
- if (type.getQualifier().isUniformOrBuffer())
+ if (type.getQualifier().storage == EvqUniform)
return getFreeSlot(set, baseUboBinding);
+
+ if (type.getQualifier().storage == EvqBuffer)
+ return getFreeSlot(set, baseSsboBinding);
}
return -1;
intermediate.getShiftTextureBinding() == 0 &&
intermediate.getShiftImageBinding() == 0 &&
intermediate.getShiftUboBinding() == 0 &&
+ intermediate.getShiftSsboBinding() == 0 &&
intermediate.getAutoMapBindings() == false &&
resolver == nullptr)
return true;
defaultResolver.baseTextureBinding = intermediate.getShiftTextureBinding();
defaultResolver.baseImageBinding = intermediate.getShiftImageBinding();
defaultResolver.baseUboBinding = intermediate.getShiftUboBinding();
+ defaultResolver.baseSsboBinding = intermediate.getShiftSsboBinding();
defaultResolver.doAutoMapping = intermediate.getAutoMapBindings();
resolver = &defaultResolver;
shiftTextureBinding(0),
shiftImageBinding(0),
shiftUboBinding(0),
+ shiftSsboBinding(0),
autoMapBindings(false),
flattenUniformArrays(false),
useUnknownFormat(false)
unsigned int getShiftImageBinding() const { return shiftImageBinding; }
void setShiftUboBinding(unsigned int shift) { shiftUboBinding = shift; }
unsigned int getShiftUboBinding() const { return shiftUboBinding; }
+ void setShiftSsboBinding(unsigned int shift) { shiftSsboBinding = shift; }
+ unsigned int getShiftSsboBinding() const { return shiftSsboBinding; }
void setAutoMapBindings(bool map) { autoMapBindings = map; }
bool getAutoMapBindings() const { return autoMapBindings; }
void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; }
unsigned int shiftTextureBinding;
unsigned int shiftImageBinding;
unsigned int shiftUboBinding;
+ unsigned int shiftSsboBinding;
bool autoMapBindings;
bool flattenUniformArrays;
bool useUnknownFormat;
// Implement TReflection methods.
//
+// Track any required attribute reflection, such as compute shader numthreads.
+//
+void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediate& intermediate)
+{
+ if (stage == EShLangCompute) {
+ // Remember thread dimensions
+ for (int dim=0; dim<3; ++dim)
+ localSize[dim] = intermediate.getLocalSize(dim);
+ }
+}
+
// Merge live symbols from 'intermediate' into the existing reflection database.
//
// Returns false if the input is too malformed to do this.
-bool TReflection::addStage(EShLanguage, const TIntermediate& intermediate)
+bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
{
if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
return false;
+ buildAttributeReflection(stage, intermediate);
+
TReflectionTraverser it(intermediate, *this);
// put the entry point on the list of functions to process
indexToAttribute[i].dump();
printf("\n");
+ if (getLocalSize(0) > 1) {
+ static const char* axis[] = { "X", "Y", "Z" };
+
+ for (int dim=0; dim<3; ++dim)
+ if (getLocalSize(dim) > 1)
+ printf("Local size %s: %d\n", axis[dim], getLocalSize(dim));
+
+ printf("\n");
+ }
+
// printf("Live names\n");
// for (TNameToIndex::const_iterator it = nameToIndex.begin(); it != nameToIndex.end(); ++it)
// printf("%s: %d\n", it->first.c_str(), it->second);
// The full reflection database
class TReflection {
public:
- TReflection() : badReflection(TObjectReflection::badReflection()) { }
+ TReflection() : badReflection(TObjectReflection::badReflection())
+ {
+ for (int dim=0; dim<3; ++dim)
+ localSize[dim] = 0;
+ }
+
virtual ~TReflection() {}
// grow the reflection stage by stage
return it->second;
}
+ // Thread local size
+ unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; }
+
void dump();
protected:
friend class glslang::TReflectionTraverser;
+ void buildAttributeReflection(EShLanguage, const TIntermediate&);
+
// Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
typedef std::map<TString, int> TNameToIndex;
typedef std::vector<TObjectReflection> TMapIndexToReflection;
TMapIndexToReflection indexToUniform;
TMapIndexToReflection indexToUniformBlock;
TMapIndexToReflection indexToAttribute;
+
+ unsigned int localSize[3];
};
} // end namespace glslang
void setShiftTextureBinding(unsigned int base);
void setShiftImageBinding(unsigned int base);
void setShiftUboBinding(unsigned int base);
+ void setShiftSsboBinding(unsigned int base);
void setAutoMapBindings(bool map);
void setFlattenUniformArrays(bool flatten);
void setNoStorageFormat(bool useUnknownFormat);
int getUniformBufferOffset(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET)
int getUniformArraySize(int index) const; // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE)
int getNumLiveAttributes() const; // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES)
+ unsigned getLocalSize(int dim) const; // return dim'th local size
const char *getAttributeName(int index) const; // can be used for glGetActiveAttrib()
int getAttributeType(int index) const; // can be used for glGetActiveAttrib()
const TType* getUniformTType(int index) const; // returns a TType*
int baseTextureBinding;
int baseImageBinding;
int baseUboBinding;
+ int baseSsboBinding;
bool autoMapBindings;
bool flattenUniforms;
};
GetParam().baseTextureBinding,
GetParam().baseImageBinding,
GetParam().baseUboBinding,
+ GetParam().baseSsboBinding,
GetParam().autoMapBindings,
GetParam().flattenUniforms);
}
GetParam().baseTextureBinding,
GetParam().baseImageBinding,
GetParam().baseUboBinding,
+ GetParam().baseSsboBinding,
GetParam().autoMapBindings,
GetParam().flattenUniforms);
}
INSTANTIATE_TEST_CASE_P(
Hlsl, HlslIoMap,
::testing::ValuesIn(std::vector<IoMapData>{
- { "spv.register.autoassign.frag", "main_ep", 5, 10, 0, 20, true, false },
- { "spv.register.noautoassign.frag", "main_ep", 5, 10, 0, 15, false, false },
- { "spv.register.autoassign-2.frag", "main", 5, 10, 0, 15, true, true },
- { "spv.buffer.autoassign.frag", "main", 5, 10, 0, 15, true, true },
- { "spv.rw.autoassign.frag", "main", 5, 10, 20, 15, true, true },
+ { "spv.register.autoassign.frag", "main_ep", 5, 10, 0, 20, 30, true, false },
+ { "spv.register.noautoassign.frag", "main_ep", 5, 10, 0, 15, 30, false, false },
+ { "spv.register.autoassign-2.frag", "main", 5, 10, 0, 15, 30, true, true },
+ { "spv.buffer.autoassign.frag", "main", 5, 10, 0, 15, 30, true, true },
+ { "spv.ssbo.autoassign.frag", "main", 5, 10, 0, 15, 30, true, true },
+ { "spv.rw.autoassign.frag", "main", 5, 10, 20, 15, 30, true, true },
{ "spv.register.autoassign.rangetest.frag", "main",
glslang::TQualifier::layoutBindingEnd-2,
glslang::TQualifier::layoutBindingEnd+5,
- 20, true, false },
+ 20, 30, true, false },
}),
FileNameAsCustomTestSuffixIoMap
);
INSTANTIATE_TEST_CASE_P(
Hlsl, GlslIoMap,
::testing::ValuesIn(std::vector<IoMapData>{
- { "spv.glsl.register.autoassign.frag", "main", 5, 10, 0, 20, true, false },
- { "spv.glsl.register.noautoassign.frag", "main", 5, 10, 0, 15, false, false },
+ { "spv.glsl.register.autoassign.frag", "main", 5, 10, 0, 20, 30, true, false },
+ { "spv.glsl.register.noautoassign.frag", "main", 5, 10, 0, 15, 30, false, false },
}),
FileNameAsCustomTestSuffixIoMap
);
int baseTextureBinding,
int baseImageBinding,
int baseUboBinding,
+ int baseSsboBinding,
bool autoMapBindings,
bool flattenUniformArrays)
{
shader.setShiftTextureBinding(baseTextureBinding);
shader.setShiftImageBinding(baseImageBinding);
shader.setShiftUboBinding(baseUboBinding);
+ shader.setShiftSsboBinding(baseSsboBinding);
shader.setAutoMapBindings(autoMapBindings);
shader.setFlattenUniformArrays(flattenUniformArrays);
int baseTextureBinding,
int baseImageBinding,
int baseUboBinding,
+ int baseSsboBinding,
bool autoMapBindings,
bool flattenUniformArrays)
{
const EShMessages controls = DeriveOptions(source, semantics, target);
GlslangResult result = compileLinkIoMap(testName, input, entryPointName, controls,
- baseSamplerBinding, baseTextureBinding, baseImageBinding, baseUboBinding,
+ baseSamplerBinding, baseTextureBinding, baseImageBinding,
+ baseUboBinding, baseSsboBinding,
autoMapBindings,
flattenUniformArrays);