From 2efd6c6d0cf89004a10aebd195de9855ab1fd8dd Mon Sep 17 00:00:00 2001 From: steve-lunarg Date: Thu, 6 Apr 2017 20:22:20 -0600 Subject: [PATCH] HLSL: cast bracket dereference index to int type if not. HLSL can index arrays using operator[] with non-integer types, and inserts a conversion to a uint if needed. --- Test/baseResults/hlsl.nonint-index.frag.out | 151 ++++++++++++++++++++ Test/hlsl.nonint-index.frag | 9 ++ gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslGrammar.cpp | 2 + hlsl/hlslParseHelper.cpp | 12 ++ 5 files changed, 175 insertions(+) create mode 100644 Test/baseResults/hlsl.nonint-index.frag.out create mode 100644 Test/hlsl.nonint-index.frag diff --git a/Test/baseResults/hlsl.nonint-index.frag.out b/Test/baseResults/hlsl.nonint-index.frag.out new file mode 100644 index 000000000..68c02a392 --- /dev/null +++ b/Test/baseResults/hlsl.nonint-index.frag.out @@ -0,0 +1,151 @@ +hlsl.nonint-index.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:4 Function Definition: @main(f1; ( temp float) +0:4 Function Parameters: +0:4 'input' ( in float) +0:? Sequence +0:7 Branch: Return with expression +0:7 add ( temp float) +0:7 add ( temp float) +0:7 add ( temp float) +0:7 indirect index ( temp float) +0:7 Constant: +0:7 1.000000 +0:7 2.000000 +0:7 3.000000 +0:7 Convert float to uint ( temp uint) +0:7 'input' ( in float) +0:7 Constant: +0:7 3.000000 +0:7 Constant: +0:7 2.000000 +0:7 Constant: +0:7 1.000000 +0:4 Function Definition: main( ( temp void) +0:4 Function Parameters: +0:? Sequence +0:4 move second child to first child ( temp float) +0:? 'input' ( temp float) +0:? 'input' (layout( location=0) in float) +0:4 move second child to first child ( temp float) +0:? '@entryPointOutput' (layout( location=0) out float) +0:4 Function Call: @main(f1; ( temp float) +0:? 'input' ( temp float) +0:? Linker Objects +0:? 'array' ( const 3-element array of float) +0:? 1.000000 +0:? 2.000000 +0:? 3.000000 +0:? '@entryPointOutput' (layout( location=0) out float) +0:? 'input' (layout( location=0) in float) + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:4 Function Definition: @main(f1; ( temp float) +0:4 Function Parameters: +0:4 'input' ( in float) +0:? Sequence +0:7 Branch: Return with expression +0:7 add ( temp float) +0:7 add ( temp float) +0:7 add ( temp float) +0:7 indirect index ( temp float) +0:7 Constant: +0:7 1.000000 +0:7 2.000000 +0:7 3.000000 +0:7 Convert float to uint ( temp uint) +0:7 'input' ( in float) +0:7 Constant: +0:7 3.000000 +0:7 Constant: +0:7 2.000000 +0:7 Constant: +0:7 1.000000 +0:4 Function Definition: main( ( temp void) +0:4 Function Parameters: +0:? Sequence +0:4 move second child to first child ( temp float) +0:? 'input' ( temp float) +0:? 'input' (layout( location=0) in float) +0:4 move second child to first child ( temp float) +0:? '@entryPointOutput' (layout( location=0) out float) +0:4 Function Call: @main(f1; ( temp float) +0:? 'input' ( temp float) +0:? Linker Objects +0:? 'array' ( const 3-element array of float) +0:? 1.000000 +0:? 2.000000 +0:? 3.000000 +0:? '@entryPointOutput' (layout( location=0) out float) +0:? 'input' (layout( location=0) in float) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 39 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main" 32 35 + ExecutionMode 4 OriginUpperLeft + Name 4 "main" + Name 10 "@main(f1;" + Name 9 "input" + Name 22 "indexable" + Name 30 "input" + Name 32 "input" + Name 35 "@entryPointOutput" + Name 36 "param" + Decorate 32(input) Location 0 + Decorate 35(@entryPointOutput) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypePointer Function 6(float) + 8: TypeFunction 6(float) 7(ptr) + 12: TypeInt 32 0 + 13: 12(int) Constant 3 + 14: TypeArray 6(float) 13 + 15: 6(float) Constant 1065353216 + 16: 6(float) Constant 1073741824 + 17: 6(float) Constant 1077936128 + 18: 14 ConstantComposite 15 16 17 + 21: TypePointer Function 14 + 31: TypePointer Input 6(float) + 32(input): 31(ptr) Variable Input + 34: TypePointer Output 6(float) +35(@entryPointOutput): 34(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 30(input): 7(ptr) Variable Function + 36(param): 7(ptr) Variable Function + 33: 6(float) Load 32(input) + Store 30(input) 33 + 37: 6(float) Load 30(input) + Store 36(param) 37 + 38: 6(float) FunctionCall 10(@main(f1;) 36(param) + Store 35(@entryPointOutput) 38 + Return + FunctionEnd + 10(@main(f1;): 6(float) Function None 8 + 9(input): 7(ptr) FunctionParameter + 11: Label + 22(indexable): 21(ptr) Variable Function + 19: 6(float) Load 9(input) + 20: 12(int) ConvertFToU 19 + Store 22(indexable) 18 + 23: 7(ptr) AccessChain 22(indexable) 20 + 24: 6(float) Load 23 + 25: 6(float) FAdd 24 17 + 26: 6(float) FAdd 25 16 + 27: 6(float) FAdd 26 15 + ReturnValue 27 + FunctionEnd diff --git a/Test/hlsl.nonint-index.frag b/Test/hlsl.nonint-index.frag new file mode 100644 index 000000000..c7a751e30 --- /dev/null +++ b/Test/hlsl.nonint-index.frag @@ -0,0 +1,9 @@ +static const float array[3] = { 1, 2, 3 }; + +float main(float input : IN) : SV_Target0 +{ + // non-integer indexes get converted to uints: + // uint(input) 3.0 2.0 1.0 + return array[input] + array[2.0] + array[true] + array[false]; +} + diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index db5bc2ac6..6bbc16b9b 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -171,6 +171,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.logicalConvert.frag", "main"}, {"hlsl.logical.unary.frag", "main"}, {"hlsl.namespace.frag", "main"}, + {"hlsl.nonint-index.frag", "main"}, {"hlsl.matNx1.frag", "main"}, {"hlsl.matrixSwizzle.vert", "ShaderFunction"}, {"hlsl.mintypes.frag", "main"}, diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 3b4bb4cd8..b8932cea3 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -2816,6 +2816,8 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node) } advanceToken(); node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode); + if (node == nullptr) + return false; break; } case EOpPostIncrement: diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 935365c8e..ca0d7b7f4 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -722,6 +722,18 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc, if (result != nullptr) return result; // it was handled as an operator[] + const TBasicType indexBasicType = index->getType().getBasicType(); + + // Cast index to unsigned integer if it isn't one. + if (indexBasicType != EbtInt && indexBasicType != EbtUint && + indexBasicType != EbtInt64 && indexBasicType != EbtUint64) + index = intermediate.addConversion(EOpConstructUint, TType(EbtUint), index); + + if (index == nullptr) { + error(loc, " unknown undex type ", "", ""); + return nullptr; + } + bool flattened = false; int indexValue = 0; if (index->getQualifier().storage == EvqConst) {