From b45e5aa07cf5e2e0bd23cf4c14bb40104b0b641c Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 28 Jun 2023 16:09:06 -0700 Subject: Fix parameter block loads in GLSL emit. (#2946) * Fix parameter block loads in GLSL emit. * Revert `[NoSideEffect]` declarations in DXR1.1 API. * fix. --------- Co-authored-by: Yong He --- source/slang/hlsl.meta.slang | 4 -- source/slang/slang-emit.cpp | 3 +- source/slang/slang-ir-glsl-legalize.cpp | 44 ++++++++++++++++++++++ source/slang/slang-ir-glsl-legalize.h | 2 + tests/bugs/parameter-block-load.slang | 31 +++++++++++++++ tests/bugs/parameter-block-load.slang.expected.txt | 2 + 6 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 tests/bugs/parameter-block-load.slang create mode 100644 tests/bugs/parameter-block-load.slang.expected.txt diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index b42e17fbe..89a34588c 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -5750,7 +5750,6 @@ struct RayQuery // must obey any API-imposed restrictions. // __target_intrinsic(hlsl) - [__NoSideEffect] [mutating] void TraceRayInline( RaytracingAccelerationStructure accelerationStructure, @@ -5773,7 +5772,6 @@ struct RayQuery [__unsafeForceInlineEarly] __specialized_for_target(glsl) - [__NoSideEffect] [mutating] void TraceRayInline( RaytracingAccelerationStructure accelerationStructure, @@ -5808,7 +5806,6 @@ struct RayQuery __target_intrinsic(glsl, rayQueryProceedEXT) __glsl_extension(GL_EXT_ray_query) __glsl_version(460) - [__NoSideEffect] [mutating] bool Proceed(); @@ -5821,7 +5818,6 @@ struct RayQuery __target_intrinsic(glsl, rayQueryTerminateEXT) __glsl_extension(GL_EXT_ray_query) __glsl_version(460) - [__NoSideEffect] [mutating] void Abort(); diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index f1ec402dd..b34483cf2 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -783,12 +783,13 @@ Result linkAndOptimizeIR( break; } - // Legalize `ImageSubscript` for GLSL. + // Legalize `ImageSubscript` and constant buffer loads for GLSL. switch (target) { case CodeGenTarget::GLSL: { legalizeImageSubscriptForGLSL(irModule); + legalizeConstantBufferLoadForGLSL(irModule); } break; default: diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index f02360416..216471d65 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -2778,4 +2778,48 @@ void legalizeEntryPointsForGLSL( } } +void legalizeConstantBufferLoadForGLSL(IRModule* module) +{ + // Constant buffers and parameter blocks are represented as `uniform` blocks + // in GLSL. These uniform blocks can't be used directly as a value of the underlying + // struct type. If we see a direct load of the constant buffer pointer, + // we need to replace it with a `MakeStruct` inst where each field is separately + // loaded. + IRBuilder builder(module); + for (auto globalInst : module->getGlobalInsts()) + { + if (auto func = as(globalInst)) + { + for (auto block : func->getBlocks()) + { + for (auto inst = block->getFirstInst(); inst;) + { + auto load = as(inst); + inst = inst->next; + if (!load) continue; + auto bufferType = load->getPtr()->getDataType(); + if (as(bufferType) || as(bufferType)) + { + auto parameterGroupType = as(bufferType); + auto elementType = as(parameterGroupType->getElementType()); + if (!elementType) continue; + List elements; + builder.setInsertBefore(load); + for (auto field : elementType->getFields()) + { + auto fieldAddr = builder.emitFieldAddress(field->getFieldType(), load->getPtr(), field->getKey()); + auto fieldValue = builder.emitLoad(field->getFieldType(), fieldAddr); + elements.add(fieldValue); + } + auto makeStruct = builder.emitMakeStruct(elementType, elements.getCount(), elements.getBuffer()); + load->replaceUsesWith(makeStruct); + load->removeAndDeallocate(); + } + } + } + } + } +} + + } // namespace Slang diff --git a/source/slang/slang-ir-glsl-legalize.h b/source/slang/slang-ir-glsl-legalize.h index 8a49fb2ec..1816df1f2 100644 --- a/source/slang/slang-ir-glsl-legalize.h +++ b/source/slang/slang-ir-glsl-legalize.h @@ -23,4 +23,6 @@ void legalizeEntryPointsForGLSL( void legalizeImageSubscriptForGLSL(IRModule* module); +void legalizeConstantBufferLoadForGLSL(IRModule* module); + } diff --git a/tests/bugs/parameter-block-load.slang b/tests/bugs/parameter-block-load.slang new file mode 100644 index 000000000..5828d021e --- /dev/null +++ b/tests/bugs/parameter-block-load.slang @@ -0,0 +1,31 @@ +// Test reading parameter block from a member function. + +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -vk -output-using-type +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx11 -profile sm_5_0 -output-using-type + +//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=gOutputBuffer +RWStructuredBuffer gOutputBuffer; + +struct MyParameters +{ + int x; + int y; + StructuredBuffer buffer1; + + RWStructuredBuffer buffer; + int calc() + { + buffer[0].x = 3; + return x + y + buffer[0].x; + } +} + +//TEST_INPUT: set gObj = new MyParameters{2, 3, new StructuredBuffer{0.0}, new RWStructuredBuffer{{0,0,0}}} +ParameterBlock gObj; + +[numthreads(1, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + float result = 0.0; + gOutputBuffer[dispatchThreadID.x] = gObj.calc(); +} diff --git a/tests/bugs/parameter-block-load.slang.expected.txt b/tests/bugs/parameter-block-load.slang.expected.txt new file mode 100644 index 000000000..e6751c365 --- /dev/null +++ b/tests/bugs/parameter-block-load.slang.expected.txt @@ -0,0 +1,2 @@ +type: int32_t +8 -- cgit v1.2.3