summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-06-28 16:09:06 -0700
committerGitHub <noreply@github.com>2023-06-28 16:09:06 -0700
commitb45e5aa07cf5e2e0bd23cf4c14bb40104b0b641c (patch)
tree52477da6fb0c75fd4e424a68850fdb703006f153
parent97963c5c119a3445fa6353809669d4553952e66c (diff)
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 <yhe@nvidia.com>
-rw-r--r--source/slang/hlsl.meta.slang4
-rw-r--r--source/slang/slang-emit.cpp3
-rw-r--r--source/slang/slang-ir-glsl-legalize.cpp44
-rw-r--r--source/slang/slang-ir-glsl-legalize.h2
-rw-r--r--tests/bugs/parameter-block-load.slang31
-rw-r--r--tests/bugs/parameter-block-load.slang.expected.txt2
6 files changed, 81 insertions, 5 deletions
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 <let rayFlagsGeneric : RAY_FLAG = RAY_FLAG_NONE>
// must obey any API-imposed restrictions.
//
__target_intrinsic(hlsl)
- [__NoSideEffect]
[mutating]
void TraceRayInline(
RaytracingAccelerationStructure accelerationStructure,
@@ -5773,7 +5772,6 @@ struct RayQuery <let rayFlagsGeneric : RAY_FLAG = RAY_FLAG_NONE>
[__unsafeForceInlineEarly]
__specialized_for_target(glsl)
- [__NoSideEffect]
[mutating]
void TraceRayInline(
RaytracingAccelerationStructure accelerationStructure,
@@ -5808,7 +5806,6 @@ struct RayQuery <let rayFlagsGeneric : RAY_FLAG = RAY_FLAG_NONE>
__target_intrinsic(glsl, rayQueryProceedEXT)
__glsl_extension(GL_EXT_ray_query)
__glsl_version(460)
- [__NoSideEffect]
[mutating]
bool Proceed();
@@ -5821,7 +5818,6 @@ struct RayQuery <let rayFlagsGeneric : RAY_FLAG = RAY_FLAG_NONE>
__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<IRGlobalValueWithCode>(globalInst))
+ {
+ for (auto block : func->getBlocks())
+ {
+ for (auto inst = block->getFirstInst(); inst;)
+ {
+ auto load = as<IRLoad>(inst);
+ inst = inst->next;
+ if (!load) continue;
+ auto bufferType = load->getPtr()->getDataType();
+ if (as<IRConstantBufferType>(bufferType) || as<IRParameterBlockType>(bufferType))
+ {
+ auto parameterGroupType = as<IRUniformParameterGroupType>(bufferType);
+ auto elementType = as<IRStructType>(parameterGroupType->getElementType());
+ if (!elementType) continue;
+ List<IRInst*> 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<int> gOutputBuffer;
+
+struct MyParameters
+{
+ int x;
+ int y;
+ StructuredBuffer<float> buffer1;
+
+ RWStructuredBuffer<uint3> buffer;
+ int calc()
+ {
+ buffer[0].x = 3;
+ return x + y + buffer[0].x;
+ }
+}
+
+//TEST_INPUT: set gObj = new MyParameters{2, 3, new StructuredBuffer<float>{0.0}, new RWStructuredBuffer<uint3>{{0,0,0}}}
+ParameterBlock<MyParameters> 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