From d53f717fd3490b790f43e0af2037a0b23612c400 Mon Sep 17 00:00:00 2001 From: steve-lunarg Date: Wed, 27 Jul 2016 15:46:48 -0600 Subject: [PATCH] HLSL: add Buffer support for Load method --- .../hlsl.load.buffer.dx10.frag.out | 204 ++++++++++++++++++ Test/hlsl.load.buffer.dx10.frag | 38 ++++ gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslGrammar.cpp | 21 +- hlsl/hlslParseHelper.cpp | 13 +- hlsl/hlslParseables.cpp | 67 +++--- 6 files changed, 309 insertions(+), 35 deletions(-) create mode 100644 Test/baseResults/hlsl.load.buffer.dx10.frag.out create mode 100644 Test/hlsl.load.buffer.dx10.frag diff --git a/Test/baseResults/hlsl.load.buffer.dx10.frag.out b/Test/baseResults/hlsl.load.buffer.dx10.frag.out new file mode 100644 index 000000000..13d00f796 --- /dev/null +++ b/Test/baseResults/hlsl.load.buffer.dx10.frag.out @@ -0,0 +1,204 @@ +hlsl.load.buffer.dx10.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:39 Function Definition: main( (global structure{temp 4-component vector of float Color, temp float FragDepth Depth}) +0:24 Function Parameters: +0:? Sequence +0:28 Sequence +0:28 move second child to first child (temp 4-component vector of float) +0:28 'r00' (temp 4-component vector of float) +0:28 textureFetch (global 4-component vector of float) +0:28 'g_tTexbf4' (uniform samplerBuffer) +0:28 'c1' (uniform int) +0:29 Sequence +0:29 move second child to first child (temp 4-component vector of int) +0:29 'r01' (temp 4-component vector of int) +0:29 textureFetch (global 4-component vector of int) +0:29 'g_tTexbi4' (uniform isamplerBuffer) +0:29 'c1' (uniform int) +0:30 Sequence +0:30 move second child to first child (temp 4-component vector of uint) +0:30 'r02' (temp 4-component vector of uint) +0:30 textureFetch (global 4-component vector of uint) +0:30 'g_tTexbu4' (uniform usamplerBuffer) +0:30 'c1' (uniform int) +0:35 move second child to first child (temp float) +0:35 Depth: direct index for structure (temp float FragDepth) +0:35 'psout' (temp structure{temp 4-component vector of float Color, temp float FragDepth Depth}) +0:35 Constant: +0:35 1 (const int) +0:35 Constant: +0:35 1.000000 +0:37 Branch: Return with expression +0:37 'psout' (temp structure{temp 4-component vector of float Color, temp float FragDepth Depth}) +0:? Linker Objects +0:? 'g_tTexbf4_test' (uniform samplerBuffer) +0:? 'g_tTexbf4' (uniform samplerBuffer) +0:? 'g_tTexbi4' (uniform isamplerBuffer) +0:? 'g_tTexbu4' (uniform usamplerBuffer) +0:? 'c1' (uniform int) +0:? 'c2' (uniform 2-component vector of int) +0:? 'c3' (uniform 3-component vector of int) +0:? 'c4' (uniform 4-component vector of int) +0:? 'o1' (uniform int) +0:? 'o2' (uniform 2-component vector of int) +0:? 'o3' (uniform 3-component vector of int) +0:? 'o4' (uniform 4-component vector of int) + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:39 Function Definition: main( (global structure{temp 4-component vector of float Color, temp float FragDepth Depth}) +0:24 Function Parameters: +0:? Sequence +0:28 Sequence +0:28 move second child to first child (temp 4-component vector of float) +0:28 'r00' (temp 4-component vector of float) +0:28 textureFetch (global 4-component vector of float) +0:28 'g_tTexbf4' (uniform samplerBuffer) +0:28 'c1' (uniform int) +0:29 Sequence +0:29 move second child to first child (temp 4-component vector of int) +0:29 'r01' (temp 4-component vector of int) +0:29 textureFetch (global 4-component vector of int) +0:29 'g_tTexbi4' (uniform isamplerBuffer) +0:29 'c1' (uniform int) +0:30 Sequence +0:30 move second child to first child (temp 4-component vector of uint) +0:30 'r02' (temp 4-component vector of uint) +0:30 textureFetch (global 4-component vector of uint) +0:30 'g_tTexbu4' (uniform usamplerBuffer) +0:30 'c1' (uniform int) +0:35 move second child to first child (temp float) +0:35 Depth: direct index for structure (temp float FragDepth) +0:35 'psout' (temp structure{temp 4-component vector of float Color, temp float FragDepth Depth}) +0:35 Constant: +0:35 1 (const int) +0:35 Constant: +0:35 1.000000 +0:37 Branch: Return with expression +0:37 'psout' (temp structure{temp 4-component vector of float Color, temp float FragDepth Depth}) +0:? Linker Objects +0:? 'g_tTexbf4_test' (uniform samplerBuffer) +0:? 'g_tTexbf4' (uniform samplerBuffer) +0:? 'g_tTexbi4' (uniform isamplerBuffer) +0:? 'g_tTexbu4' (uniform usamplerBuffer) +0:? 'c1' (uniform int) +0:? 'c2' (uniform 2-component vector of int) +0:? 'c3' (uniform 3-component vector of int) +0:? 'c4' (uniform 4-component vector of int) +0:? 'o1' (uniform int) +0:? 'o2' (uniform 2-component vector of int) +0:? 'o3' (uniform 3-component vector of int) +0:? 'o4' (uniform 4-component vector of int) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 66 + + Capability Shader + Capability SampledBuffer + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" + ExecutionMode 4 OriginUpperLeft + Source HLSL 450 + Name 4 "main" + Name 9 "r00" + Name 13 "g_tTexbf4" + Name 17 "c1" + Name 23 "r01" + Name 27 "g_tTexbi4" + Name 35 "r02" + Name 39 "g_tTexbu4" + Name 44 "PS_OUTPUT" + MemberName 44(PS_OUTPUT) 0 "Color" + MemberName 44(PS_OUTPUT) 1 "Depth" + Name 46 "psout" + Name 53 "g_tTexbf4_test" + Name 56 "c2" + Name 59 "c3" + Name 61 "c4" + Name 62 "o1" + Name 63 "o2" + Name 64 "o3" + Name 65 "o4" + Decorate 13(g_tTexbf4) DescriptorSet 0 + Decorate 27(g_tTexbi4) DescriptorSet 0 + Decorate 39(g_tTexbu4) DescriptorSet 0 + MemberDecorate 44(PS_OUTPUT) 1 BuiltIn FragDepth + Decorate 53(g_tTexbf4_test) DescriptorSet 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypePointer Function 7(fvec4) + 10: TypeImage 6(float) Buffer sampled format:Unknown + 11: TypeSampledImage 10 + 12: TypePointer UniformConstant 11 + 13(g_tTexbf4): 12(ptr) Variable UniformConstant + 15: TypeInt 32 1 + 16: TypePointer UniformConstant 15(int) + 17(c1): 16(ptr) Variable UniformConstant + 21: TypeVector 15(int) 4 + 22: TypePointer Function 21(ivec4) + 24: TypeImage 15(int) Buffer sampled format:Unknown + 25: TypeSampledImage 24 + 26: TypePointer UniformConstant 25 + 27(g_tTexbi4): 26(ptr) Variable UniformConstant + 32: TypeInt 32 0 + 33: TypeVector 32(int) 4 + 34: TypePointer Function 33(ivec4) + 36: TypeImage 32(int) Buffer sampled format:Unknown + 37: TypeSampledImage 36 + 38: TypePointer UniformConstant 37 + 39(g_tTexbu4): 38(ptr) Variable UniformConstant + 44(PS_OUTPUT): TypeStruct 7(fvec4) 6(float) + 45: TypePointer Function 44(PS_OUTPUT) + 47: 15(int) Constant 1 + 48: 6(float) Constant 1065353216 + 49: TypePointer Function 6(float) +53(g_tTexbf4_test): 12(ptr) Variable UniformConstant + 54: TypeVector 15(int) 2 + 55: TypePointer UniformConstant 54(ivec2) + 56(c2): 55(ptr) Variable UniformConstant + 57: TypeVector 15(int) 3 + 58: TypePointer UniformConstant 57(ivec3) + 59(c3): 58(ptr) Variable UniformConstant + 60: TypePointer UniformConstant 21(ivec4) + 61(c4): 60(ptr) Variable UniformConstant + 62(o1): 16(ptr) Variable UniformConstant + 63(o2): 55(ptr) Variable UniformConstant + 64(o3): 58(ptr) Variable UniformConstant + 65(o4): 60(ptr) Variable UniformConstant + 4(main): 2 Function None 3 + 5: Label + 9(r00): 8(ptr) Variable Function + 23(r01): 22(ptr) Variable Function + 35(r02): 34(ptr) Variable Function + 46(psout): 45(ptr) Variable Function + 14: 11 Load 13(g_tTexbf4) + 18: 15(int) Load 17(c1) + 19: 10 Image 14 + 20: 7(fvec4) ImageFetch 19 18 + Store 9(r00) 20 + 28: 25 Load 27(g_tTexbi4) + 29: 15(int) Load 17(c1) + 30: 24 Image 28 + 31: 21(ivec4) ImageFetch 30 29 + Store 23(r01) 31 + 40: 37 Load 39(g_tTexbu4) + 41: 15(int) Load 17(c1) + 42: 36 Image 40 + 43: 33(ivec4) ImageFetch 42 41 + Store 35(r02) 43 + 50: 49(ptr) AccessChain 46(psout) 47 + Store 50 48 + 51:44(PS_OUTPUT) Load 46(psout) + ReturnValue 51 + FunctionEnd diff --git a/Test/hlsl.load.buffer.dx10.frag b/Test/hlsl.load.buffer.dx10.frag new file mode 100644 index 000000000..60a61df67 --- /dev/null +++ b/Test/hlsl.load.buffer.dx10.frag @@ -0,0 +1,38 @@ +uniform Buffer g_tTexbf4_test : register(t0); + +Buffer g_tTexbf4; // default is float4 +Buffer g_tTexbi4; +Buffer g_tTexbu4; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; + float Depth : SV_Depth; +}; + +uniform int c1; +uniform int2 c2; +uniform int3 c3; +uniform int4 c4; + +uniform int o1; +uniform int2 o2; +uniform int3 o3; +uniform int4 o4; + +PS_OUTPUT main() +{ + PS_OUTPUT psout; + + // Buffer + float4 r00 = g_tTexbf4.Load(c1); + int4 r01 = g_tTexbi4.Load(c1); + uint4 r02 = g_tTexbu4.Load(c1); + + // TODO: other types that can be put in sampler buffers, like float2x2, and float3. + + psout.Color = 1.0; + psout.Depth = 1.0; + + return psout; +} diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index e4cb4b06a..e9d378868 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -110,6 +110,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.load.array.dx10.frag", "main"}, {"hlsl.load.basic.dx10.frag", "main"}, {"hlsl.load.basic.dx10.vert", "main"}, + {"hlsl.load.buffer.dx10.frag", "main"}, {"hlsl.load.offset.dx10.frag", "main"}, {"hlsl.load.offsetarray.dx10.frag", "main"}, {"hlsl.pp.line.frag", "main"}, diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 3c9656006..fd81916d1 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -754,6 +754,18 @@ bool HlslGrammar::acceptTextureType(TType& type) return false; } + // Buffers can handle small mats if they fit in 4 components + if (dim == EsdBuffer && txType.isMatrix()) { + if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) { + expected("components < 4 in matrix buffer type"); + return false; + } + + // TODO: except we don't handle it yet... + unimplemented("matrix type in buffer"); + return false; + } + if (!txType.isScalar() && !txType.isVector()) { expected("scalar or vector type"); return false; @@ -789,7 +801,14 @@ bool HlslGrammar::acceptTextureType(TType& type) const bool shadow = txType.isScalar() || (txType.isVector() && txType.getVectorSize() == 1); TSampler sampler; - sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms); + + // Buffers are combined. + if (dim == EsdBuffer) { + sampler.set(txType.getBasicType(), dim, array); + } else { + // DX10 textures are separated. TODO: DX9. + sampler.setTexture(txType.getBasicType(), dim, array, shadow, ms); + } type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index d695ca17d..c95616d72 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -1154,11 +1154,12 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType TIntermTyped* coordSwizzle = nullptr; const bool isMS = argTex->getType().getSampler().isMultiSample(); + const bool isBuffer = argTex->getType().getSampler().dim == EsdBuffer; const TBasicType coordBaseType = argCoord->getType().getBasicType(); // Last component of coordinate is the mip level, for non-MS. we separate them here: - if (isMS) { - // MS has no LOD + if (isMS || isBuffer) { + // MS and Buffer have no LOD coordSwizzle = argCoord; } else { // Extract coordinate @@ -1181,10 +1182,6 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType const TOperator fetchOp = (hasOffset ? EOpTextureFetchOffset : EOpTextureFetch); TIntermAggregate* txfetch = new TIntermAggregate(fetchOp); - const TSamplerDim dim = argTex->getType().getSampler().dim; - if (dim == EsdBuffer) // TODO: buffers - assert(0); - // Build up the fetch txfetch->getSequence().push_back(argTex); txfetch->getSequence().push_back(coordSwizzle); @@ -1193,8 +1190,10 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType // add 2DMS sample index TIntermTyped* argSampleIdx = argAggregate->getSequence()[2]->getAsTyped(); txfetch->getSequence().push_back(argSampleIdx); + } else if (isBuffer) { + // Nothing else to do for buffers. } else { - // 2DMS has no LOD, but everything else does. + // 2DMS and buffer have no LOD, but everything else does. txfetch->getSequence().push_back(lodComponent); } diff --git a/hlsl/hlslParseables.cpp b/hlsl/hlslParseables.cpp index edfba9cbb..1d184a194 100755 --- a/hlsl/hlslParseables.cpp +++ b/hlsl/hlslParseables.cpp @@ -70,7 +70,11 @@ const char* BaseTypeName(const char argOrder, const char* scalarName, const char bool IsSamplerType(const char argType) { return argType == 'S' || argType == 's'; } bool IsTextureArrayed(const char argOrder) { return argOrder == '@' || argOrder == '&'; } bool IsTextureMS(const char argOrder) { return argOrder == '$' || argOrder == '&'; } -bool IsTextureType(const char argOrder) { return argOrder == '%' || argOrder == '@' || IsTextureMS(argOrder); } +bool IsBuffer(const char argOrder) { return argOrder == '*'; } +bool IsTextureType(const char argOrder) +{ + return argOrder == '%' || argOrder == '@' || IsTextureMS(argOrder) || IsBuffer(argOrder); +} // Reject certain combinations that are illegal sample methods. For example, // 3D arrays. @@ -78,6 +82,7 @@ bool IsIllegalSample(const glslang::TString& name, const char* argOrder, int dim { const bool isArrayed = IsTextureArrayed(*argOrder); const bool isMS = IsTextureMS(*argOrder); + const bool isBuffer = IsBuffer(*argOrder); // there are no 3D arrayed textures, or 3D SampleCmp(LevelZero) if (dim0 == 3 && (isArrayed || name == "SampleCmp" || name == "SampleCmpLevelZero")) @@ -112,6 +117,10 @@ bool IsIllegalSample(const glslang::TString& name, const char* argOrder, int dim if (isMS && dim0 != 2) return true; + // Buffer are only 1D + if (isBuffer && dim0 != 1) + return true; + return false; } @@ -127,9 +136,9 @@ int CoordinateArgPos(const glslang::TString& name, bool isTexture) } // Some texture methods use an addition coordinate dimension for the mip -bool HasMipInCoord(const glslang::TString& name, bool isMS) +bool HasMipInCoord(const glslang::TString& name, bool isMS, bool isBuffer) { - return name == "Load" && !isMS; + return name == "Load" && !isMS && !isBuffer; } // LOD calculations don't pass the array level in the coordinate. @@ -197,6 +206,7 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons const bool isArrayed = IsTextureArrayed(argOrder[0]); const bool isSampler = IsSamplerType(argType[0]); const bool isMS = IsTextureMS(argOrder[0]); + const bool isBuffer = IsBuffer(argOrder[0]); char type = *argType; @@ -219,37 +229,38 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons char order = *argOrder; if (UseHlslTypes) { + // TODO: handle sub-vec4 returns switch (type) { - case '-': s += "void"; break; - case 'F': s += "float"; break; - case 'D': s += "double"; break; - case 'I': s += "int"; break; - case 'U': s += "uint"; break; - case 'B': s += "bool"; break; - case 'S': s += "sampler"; break; - case 's': s += "SamplerComparisonState"; break; - case 'T': s += "Texture"; break; - case 'i': s += "Texture "; break; - case 'u': s += "Texture "; break; - default: s += "UNKNOWN_TYPE"; break; + case '-': s += "void"; break; + case 'F': s += "float"; break; + case 'D': s += "double"; break; + case 'I': s += "int"; break; + case 'U': s += "uint"; break; + case 'B': s += "bool"; break; + case 'S': s += "sampler"; break; + case 's': s += "SamplerComparisonState"; break; + case 'T': s += (isBuffer ? "Buffer" : "Texture"); break; + case 'i': s += (isBuffer ? "Buffer " : "Texture "); break; + case 'u': s += (isBuffer ? "Buffer " : "Texture "); break; + default: s += "UNKNOWN_TYPE"; break; } } else { switch (type) { case '-': s += "void"; break; - case 'F': s += BaseTypeName(order, "float", "vec", "mat"); break; - case 'D': s += BaseTypeName(order, "double", "dvec", "dmat"); break; - case 'I': s += BaseTypeName(order, "int", "ivec", "imat"); break; - case 'U': s += BaseTypeName(order, "uint", "uvec", "umat"); break; - case 'B': s += BaseTypeName(order, "bool", "bvec", "bmat"); break; - case 'S': s += "sampler"; break; - case 's': s += "samplerShadow"; break; + case 'F': s += BaseTypeName(order, "float", "vec", "mat"); break; + case 'D': s += BaseTypeName(order, "double", "dvec", "dmat"); break; + case 'I': s += BaseTypeName(order, "int", "ivec", "imat"); break; + case 'U': s += BaseTypeName(order, "uint", "uvec", "umat"); break; + case 'B': s += BaseTypeName(order, "bool", "bvec", "bmat"); break; + case 'S': s += "sampler"; break; + case 's': s += "samplerShadow"; break; case 'T': // fall through case 'i': // ... case 'u': // ... - if (type != 'T') + if (type != 'T') // create itexture, utexture, etc s += type; - s += "texture"; + s += (isBuffer ? "samplerBuffer" : "texture"); break; default: s += "UNKNOWN_TYPE"; break; @@ -263,7 +274,7 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons // Add sampler dimensions if (isSampler || isTexture) { - if (order == 'V' || isTexture) { + if ((order == 'V' || isTexture) && !isBuffer) { switch (dim0) { case 1: s += "1D"; break; case 2: s += (isMS ? "2DMS" : "2D"); break; @@ -442,6 +453,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c // '%' as first letter of order creates texture of given F/I/U type (texture, itexture, etc) // '@' as first letter of order creates arrayed texture of given type // '$' / '&' as first letter of order creates 2DMS / 2DMSArray textures + // '*' as first letter of order creates buffer object static const struct { const char* name; // intrinsic name @@ -630,7 +642,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c { "SampleLevel", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,S,F,", EShLangAll }, { "SampleLevel", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,S,F,,I", EShLangAll }, - { "Load", /*!O*/ "V4", nullptr, "%@,V", "FIU,I", EShLangAll }, + { "Load", /*!O*/ "V4", nullptr, "%@*,V", "FIU,I", EShLangAll }, { "Load", /* O*/ "V4", nullptr, "%@,V,V", "FIU,I,I", EShLangAll }, { "Load", /* +sampleidex*/ "V4", nullptr, "$&,V,S", "FIU,I,I", EShLangAll }, { "Load", /* +samplindex, offset*/ "V4", nullptr, "$&,V,S,V", "FIU,I,I,I", EShLangAll }, @@ -724,7 +736,8 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c const bool isTexture = IsTextureType(*argOrder); const bool isArrayed = IsTextureArrayed(*argOrder); const bool isMS = IsTextureMS(*argOrder); - const bool mipInCoord = HasMipInCoord(intrinsic.name, isMS); + const bool isBuffer = IsBuffer(*argOrder); + const bool mipInCoord = HasMipInCoord(intrinsic.name, isMS, isBuffer); const int fixedVecSize = FixedVecSize(argOrder); const int coordArg = CoordinateArgPos(intrinsic.name, isTexture);