Skip to content

[SPIR-V] Task shader OpEmitMeshTasksEXT always emitted without payload parameter #7082

Closed
@baldurk

Description

@baldurk

Description
In task shaders, the OpEmitMeshTasksEXT will never have a payload attached even when it should. This is possibly leftover from the NV extension where the payload was implicit and not a parameter to the emit instruction.

Steps to Reproduce
You can compile the test shader from this repository ./tools/clang/test/CodeGenSPIRV/meshshading.ext.amplification.hlsl to see the problem.

The checks there are not complete (I'm not sure if they're intended to be a partial match or not) but the OpEmitMeshTasksEXT produced does not reference the payload when it should. This is not completely invalid but it doesn't match the HLSL which is outputting a payload.

On godbolt here is a shorter example: https://godbolt.org/z/6ajvse7jW

struct payloadType { uint a; };

groupshared payloadType payload;

[numthreads(1, 1, 1)]
void main()
{
	payload.a = 12;
	DispatchMesh(1, 1, 1, payload);
}
         ; ...
    %payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT_payloadType TaskPayloadWorkgroupEXT
         ; ...
         %18 = OpLoad %payloadType %payload
               OpStore %payload %18
               OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1
               OpFunctionEnd

Actual Behavior
OpEmitMeshTasksEXT is always produced without a payload regardless of whether the HLSL shader used one or not.

Environment

  • dxcompiler.dll: 1.8 - 1.8.2407.7 (416fab6b5); dxil.dll: 1.8(101.8.2407.12) & libdxcompiler.so: 1.8(dev;1-e4636f06); libdxil.so: 1.8
  • Windows 10 22H2

Theory
The code in SpirvEmitter::processDispatchMesh seems to do most of the work of declaring the payload but doesn't associate it with the emit, instead always passing NULL. This patch fixes it for me though I don't know if it's complete:

diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp
index 94952b3c3..9ae16619e 100644
--- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp
+++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp
@@ -12593,7 +12593,7 @@ void SpirvEmitter::processDispatchMesh(const CallExpr *callExpr) {
           : spv::StorageClass::Output;
   auto *payloadArg = doExpr(args[3]);
   bool isValid = false;
-  const VarDecl *param = nullptr;
+  SpirvInstruction *param = nullptr;
   if (const auto *implCastExpr = dyn_cast<CastExpr>(args[3])) {
     if (const auto *arg = dyn_cast<DeclRefExpr>(implCastExpr->getSubExpr())) {
       if (const auto *paramDecl = dyn_cast<VarDecl>(arg->getDecl())) {
@@ -12601,7 +12601,8 @@ void SpirvEmitter::processDispatchMesh(const CallExpr *callExpr) {
           isValid = declIdMapper.createPayloadStageVars(
               sigPoint, sc, paramDecl, /*asInput=*/false, paramDecl->getType(),
               "out.var", &payloadArg);
-          param = paramDecl;
+          param =
+              declIdMapper.getDeclEvalInfo(paramDecl, paramDecl->getLocation());
         }
       }
     }
@@ -12618,7 +12619,7 @@ void SpirvEmitter::processDispatchMesh(const CallExpr *callExpr) {

   if (featureManager.isExtensionEnabled(Extension::EXT_mesh_shader)) {
     // for EXT_mesh_shader, create opEmitMeshTasksEXT.
-    spvBuilder.createEmitMeshTasksEXT(threadX, threadY, threadZ, loc, nullptr,
+    spvBuilder.createEmitMeshTasksEXT(threadX, threadY, threadZ, loc, param,
                                       range);
   } else {
     // for NV_mesh_shader, set TaskCountNV = threadX * threadY * threadZ.

Metadata

Metadata

Assignees

Labels

bugBug, regression, crashspirvWork related to SPIR-V

Type

No type

Projects

Status

Done

Status

Triaged

Relationships

None yet

Development

No branches or pull requests

Issue actions