diff --git a/Test/baseResults/hlsl.structbuffer.fn2.comp.out b/Test/baseResults/hlsl.structbuffer.fn2.comp.out new file mode 100644 index 00000000..686a0a2b --- /dev/null +++ b/Test/baseResults/hlsl.structbuffer.fn2.comp.out @@ -0,0 +1,243 @@ +hlsl.structbuffer.fn2.comp +Shader version: 500 +local_size = (256, 1, 1) +0:? Sequence +0:5 Function Definition: testLoad(u1;block--u1[0]1; ( temp 2-component vector of uint) +0:5 Function Parameters: +0:5 'loc' ( in uint) +0:5 'buffer' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:? Sequence +0:6 Sequence +0:6 move second child to first child ( temp 2-component vector of uint) +0:6 'result' ( temp 2-component vector of uint) +0:? Sequence +0:6 move second child to first child ( temp int) +0:6 'byteAddrTemp' ( temp int) +0:6 right-shift ( temp int) +0:6 'loc' ( in uint) +0:6 Constant: +0:6 2 (const int) +0:? Construct vec2 ( temp 2-component vector of uint) +0:6 indirect index ( temp float) +0:6 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint) +0:6 'buffer' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:6 Constant: +0:6 0 (const uint) +0:6 'byteAddrTemp' ( temp int) +0:6 indirect index ( temp float) +0:6 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint) +0:6 'buffer' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:6 Constant: +0:6 0 (const uint) +0:6 add ( temp int) +0:6 'byteAddrTemp' ( temp int) +0:6 Constant: +0:6 1 (const int) +0:7 Branch: Return with expression +0:7 'result' ( temp 2-component vector of uint) +0:12 Function Definition: @main(u1; ( temp void) +0:12 Function Parameters: +0:12 'dispatchId' ( in uint) +0:? Sequence +0:13 Sequence +0:13 move second child to first child ( temp 2-component vector of uint) +0:13 'result' ( temp 2-component vector of uint) +0:13 Function Call: testLoad(u1;block--u1[0]1; ( temp 2-component vector of uint) +0:13 'dispatchId' ( in uint) +0:13 'g_input' (layout( binding=0 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:14 Sequence +0:14 imageStore ( temp void) +0:14 'g_output' (layout( binding=1 rg32ui) uniform uimageBuffer) +0:14 'dispatchId' ( in uint) +0:14 'result' ( temp 2-component vector of uint) +0:14 'result' ( temp 2-component vector of uint) +0:12 Function Definition: main( ( temp void) +0:12 Function Parameters: +0:? Sequence +0:12 move second child to first child ( temp uint) +0:? 'dispatchId' ( temp uint) +0:? 'dispatchId' ( in uint GlobalInvocationID) +0:12 Function Call: @main(u1; ( temp void) +0:? 'dispatchId' ( temp uint) +0:? Linker Objects +0:? 'g_input' (layout( binding=0 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:? 'g_output' (layout( binding=1 rg32ui) uniform uimageBuffer) +0:? 'dispatchId' ( in uint GlobalInvocationID) + + +Linked compute stage: + + +Shader version: 500 +local_size = (256, 1, 1) +0:? Sequence +0:5 Function Definition: testLoad(u1;block--u1[0]1; ( temp 2-component vector of uint) +0:5 Function Parameters: +0:5 'loc' ( in uint) +0:5 'buffer' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:? Sequence +0:6 Sequence +0:6 move second child to first child ( temp 2-component vector of uint) +0:6 'result' ( temp 2-component vector of uint) +0:? Sequence +0:6 move second child to first child ( temp int) +0:6 'byteAddrTemp' ( temp int) +0:6 right-shift ( temp int) +0:6 'loc' ( in uint) +0:6 Constant: +0:6 2 (const int) +0:? Construct vec2 ( temp 2-component vector of uint) +0:6 indirect index ( temp float) +0:6 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint) +0:6 'buffer' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:6 Constant: +0:6 0 (const uint) +0:6 'byteAddrTemp' ( temp int) +0:6 indirect index ( temp float) +0:6 @data: direct index for structure (layout( row_major std430) buffer implicitly-sized array of uint) +0:6 'buffer' (layout( row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:6 Constant: +0:6 0 (const uint) +0:6 add ( temp int) +0:6 'byteAddrTemp' ( temp int) +0:6 Constant: +0:6 1 (const int) +0:7 Branch: Return with expression +0:7 'result' ( temp 2-component vector of uint) +0:12 Function Definition: @main(u1; ( temp void) +0:12 Function Parameters: +0:12 'dispatchId' ( in uint) +0:? Sequence +0:13 Sequence +0:13 move second child to first child ( temp 2-component vector of uint) +0:13 'result' ( temp 2-component vector of uint) +0:13 Function Call: testLoad(u1;block--u1[0]1; ( temp 2-component vector of uint) +0:13 'dispatchId' ( in uint) +0:13 'g_input' (layout( binding=0 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:14 Sequence +0:14 imageStore ( temp void) +0:14 'g_output' (layout( binding=1 rg32ui) uniform uimageBuffer) +0:14 'dispatchId' ( in uint) +0:14 'result' ( temp 2-component vector of uint) +0:14 'result' ( temp 2-component vector of uint) +0:12 Function Definition: main( ( temp void) +0:12 Function Parameters: +0:? Sequence +0:12 move second child to first child ( temp uint) +0:? 'dispatchId' ( temp uint) +0:? 'dispatchId' ( in uint GlobalInvocationID) +0:12 Function Call: @main(u1; ( temp void) +0:? 'dispatchId' ( temp uint) +0:? Linker Objects +0:? 'g_input' (layout( binding=0 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of uint @data}) +0:? 'g_output' (layout( binding=1 rg32ui) uniform uimageBuffer) +0:? 'dispatchId' ( in uint GlobalInvocationID) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 61 + + Capability Shader + Capability SampledBuffer + Capability StorageImageExtendedFormats + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 56 + ExecutionMode 4 LocalSize 256 1 1 + Source HLSL 500 + Name 4 "main" + Name 9 "" + MemberName 9 0 "@data" + Name 15 "testLoad(u1;block--u1[0]1;" + Name 13 "loc" + Name 14 "buffer" + Name 19 "@main(u1;" + Name 18 "dispatchId" + Name 22 "result" + Name 25 "byteAddrTemp" + Name 43 "result" + Name 44 "g_input" + Name 45 "param" + Name 50 "g_output" + Name 54 "dispatchId" + Name 56 "dispatchId" + Name 58 "param" + Decorate 8 ArrayStride 4 + MemberDecorate 9 0 NonWritable + MemberDecorate 9 0 Offset 0 + Decorate 9 BufferBlock + Decorate 44(g_input) DescriptorSet 0 + Decorate 44(g_input) Binding 0 + Decorate 50(g_output) DescriptorSet 0 + Decorate 50(g_output) Binding 1 + Decorate 56(dispatchId) BuiltIn GlobalInvocationId + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 0 + 7: TypePointer Function 6(int) + 8: TypeRuntimeArray 6(int) + 9: TypeStruct 8 + 10: TypePointer Uniform 9(struct) + 11: TypeVector 6(int) 2 + 12: TypeFunction 11(ivec2) 7(ptr) 10(ptr) + 17: TypeFunction 2 7(ptr) + 21: TypePointer Function 11(ivec2) + 23: TypeInt 32 1 + 24: TypePointer Function 23(int) + 27: 23(int) Constant 2 + 29: 23(int) Constant 0 + 31: TypePointer Uniform 6(int) + 35: 23(int) Constant 1 + 44(g_input): 10(ptr) Variable Uniform + 48: TypeImage 6(int) Buffer nonsampled format:Rg32ui + 49: TypePointer UniformConstant 48 + 50(g_output): 49(ptr) Variable UniformConstant + 55: TypePointer Input 6(int) + 56(dispatchId): 55(ptr) Variable Input + 4(main): 2 Function None 3 + 5: Label + 54(dispatchId): 7(ptr) Variable Function + 58(param): 7(ptr) Variable Function + 57: 6(int) Load 56(dispatchId) + Store 54(dispatchId) 57 + 59: 6(int) Load 54(dispatchId) + Store 58(param) 59 + 60: 2 FunctionCall 19(@main(u1;) 58(param) + Return + FunctionEnd +15(testLoad(u1;block--u1[0]1;): 11(ivec2) Function None 12 + 13(loc): 7(ptr) FunctionParameter + 14(buffer): 10(ptr) FunctionParameter + 16: Label + 22(result): 21(ptr) Variable Function +25(byteAddrTemp): 24(ptr) Variable Function + 26: 6(int) Load 13(loc) + 28: 23(int) ShiftRightLogical 26 27 + Store 25(byteAddrTemp) 28 + 30: 23(int) Load 25(byteAddrTemp) + 32: 31(ptr) AccessChain 14(buffer) 29 30 + 33: 6(int) Load 32 + 34: 23(int) Load 25(byteAddrTemp) + 36: 23(int) IAdd 34 35 + 37: 31(ptr) AccessChain 14(buffer) 29 36 + 38: 6(int) Load 37 + 39: 11(ivec2) CompositeConstruct 33 38 + Store 22(result) 39 + 40: 11(ivec2) Load 22(result) + ReturnValue 40 + FunctionEnd + 19(@main(u1;): 2 Function None 17 + 18(dispatchId): 7(ptr) FunctionParameter + 20: Label + 43(result): 21(ptr) Variable Function + 45(param): 7(ptr) Variable Function + 46: 6(int) Load 18(dispatchId) + Store 45(param) 46 + 47: 11(ivec2) FunctionCall 15(testLoad(u1;block--u1[0]1;) 45(param) 44(g_input) + Store 43(result) 47 + 51: 48 Load 50(g_output) + 52: 6(int) Load 18(dispatchId) + 53: 11(ivec2) Load 43(result) + ImageWrite 51 52 53 + Return + FunctionEnd diff --git a/Test/hlsl.structbuffer.fn2.comp b/Test/hlsl.structbuffer.fn2.comp new file mode 100644 index 00000000..e651e919 --- /dev/null +++ b/Test/hlsl.structbuffer.fn2.comp @@ -0,0 +1,15 @@ +ByteAddressBuffer g_input: register(t0); +RWBuffer g_output : register(u1); + +uint2 testLoad(uint loc, ByteAddressBuffer buffer) +{ + uint2 result = buffer.Load2(loc); + return result; +} + +[numthreads(256, 1, 1)] +void main(uint dispatchId : SV_DispatchThreadID) +{ + uint2 result = testLoad(dispatchId, g_input); + g_output[dispatchId] = result; +} diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 165e2712..a8f01e86 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -251,6 +251,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.structbuffer.coherent.frag", "main"}, {"hlsl.structbuffer.incdec.frag", "main"}, {"hlsl.structbuffer.fn.frag", "main"}, + {"hlsl.structbuffer.fn2.comp", "main"}, {"hlsl.structbuffer.rw.frag", "main"}, {"hlsl.structbuffer.rwbyte.frag", "main"}, {"hlsl.structin.vert", "main"}, diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 173f6b65..7fcd787c 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -1612,6 +1612,8 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*variable, loc), loc); + + // TODO: for struct buffers with counters, pass counter buffer as hidden parameter } else paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); } @@ -2536,13 +2538,7 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte if (bufferObj == nullptr || bufferObj->getAsSymbolNode() == nullptr) return; - TString bufferName(bufferObj->getAsSymbolNode()->getName()); - - const auto bivIt = structBufferBuiltIn.find(bufferName); - if (bivIt == structBufferBuiltIn.end()) - return; - - const TBuiltInVariable builtInType = bivIt->second; + const TString bufferName(bufferObj->getAsSymbolNode()->getName()); // Some methods require a hidden internal counter, obtained via getStructBufferCounter(). // This lambda adds something to it and returns the old value. @@ -2572,10 +2568,21 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte { TIntermTyped* argIndex = argAggregate->getSequence()[1]->getAsTyped(); // index + const auto bivIt = structBufferBuiltIn.find(bufferName); + + const TBuiltInVariable builtInType = (bivIt != structBufferBuiltIn.end()) ? bivIt->second : EbvNone; + + const TType& bufferType = bufferObj->getType(); + // Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address // buffer then, but that's what it calls itself. - const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer || - builtInType == EbvRWByteAddressBuffer); + // TODO: it would be easier to track the declared (pre-sanitized) builtInType in the TType. + // If/when that happens, this should be simplified to look *only* at the builtin type. + const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer || + builtInType == EbvRWByteAddressBuffer || + (builtInType == EbvNone && !bufferType.isVector() && + bufferType.getBasicType() == EbtUint)); + if (isByteAddressBuffer) argIndex = intermediate.addBinaryNode(EOpRightShift, argIndex, intermediate.addConstantUnion(2, loc, true), @@ -4141,6 +4148,8 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct arg0 = arguments->getAsSymbolNode(); if (arg0 != nullptr && isStructBufferType(arg0->getType())) { + // TODO: for struct buffers with counters, pass counter buffer as hidden parameter + static const int methodPrefixSize = sizeof(BUILTIN_PREFIX)-1; if (function->getName().length() > methodPrefixSize &&