Repository: shader-slang/slang
File: source/slang/slang-emit.cpp (C++)

Code before:
        //
        //  1. Any `ExistentialBox<...>` fields need to be moved
        //  out of their enclosing `struct` type, so that the layout
        //  of the enclosing type is computed as if the field had
        //  zero size.
        //
        //  2. Once an `ExistentialBox<X>` has been floated out
        //  of its parent and landed somwhere permanent (e.g., either
        //  a dedicated variable, or a field of constant buffer),
        //  we need to replace it with just an `X`, after which we
        //  will have (more) legal shader code.
        //
        // For DXIL/HLSL with NVAPI: add dummy fields to empty ray payloads,
        // then unwrap ForceVarIntoRayPayloadStructTemporarily instructions
        if (isD3DTarget(targetRequest))
        {
            SLANG_PASS(legalizeEmptyRayPayloadsForHLSL);
            SLANG_PASS(legalizeNonStructParameterToStructForHLSL);
        }

        // For SPIRV: also add dummy fields to empty ray payloads
        if (isSPIRV(targetRequest->getTarget()))
        {
            SLANG_PASS(legalizeEmptyRayPayloadsForHLSL);
        }

        if (requiredLoweringPassSet.existentialTypeLayout)
        {
            SLANG_PASS(legalizeExistentialTypeLayout, targetProgram, sink);
        }

        validateIRModuleIfEnabled(codeGenContext, irModule);

        if (!validateStructuredBufferResourceTypes(irModule, sink, targetRequest))
            return SLANG_FAIL;

        // Many of our target languages and/or downstream compilers
        // don't support `struct` types that have resource-type fields.
        // In order to work around this limitation, we will rewrite the
        // IR so that any structure types with resource-type fields get
        // split into a "tuple" that comprises the ordinary fields (still
        // bundles up as a `struct`) and one element for each resource-type
        // field (recursively).
        //
        // What used to be individual variables/parameters/arguments/etc.
        // then become multiple variables/parameters/arguments/etc.
        //
        // Note: For DXIL, legalizeNonStructParameterToStructForHLSL is called earlier
        // (before legalizeExistentialTypeLayout) to unwrap ForceVarIntoRayPayloadStructTemporarily.

        SLANG_PASS(legalizeResourceTypes, targetProgram, sink);

Review comment (suggestion):
I think this will be better for a longer term:
```
if (isD3DTarget(targetRequest) || isSPIRV(targetRequest->getTarget()))
{
    SLANG_PASS(legalizeEmptyRayPayloadsForHLSL);
}

if (isD3DTarget(targetRequest))
{
    SLANG_PASS(legalizeNonStructParameterToStructForHLSL);
}
```

Code after:
        // We need to legalize these pointer-like types away,
        // which involves two main changes:
        //
        //  1. Any `ExistentialBox<...>` fields need to be moved
        //  out of their enclosing `struct` type, so that the layout
        //  of the enclosing type is computed as if the field had
        //  zero size.
        //
        //  2. Once an `ExistentialBox<X>` has been floated out
        //  of its parent and landed somwhere permanent (e.g., either
        //  a dedicated variable, or a field of constant buffer),
        //  we need to replace it with just an `X`, after which we
        //  will have (more) legal shader code.
        //
        // For DXIL/HLSL with NVAPI and SPIRV: add dummy fields to empty ray payloads
        if (isD3DTarget(targetRequest) || isSPIRV(targetRequest->getTarget()))
        {
            SLANG_PASS(legalizeEmptyRayPayloadsForHLSL);
        }

        // For DXIL only: unwrap ForceVarIntoRayPayloadStructTemporarily instructions
        // (must run before legalizeExistentialTypeLayout removes empty struct parameters)
        if (isD3DTarget(targetRequest))
        {
            SLANG_PASS(legalizeNonStructParameterToStructForHLSL);
        }

        if (requiredLoweringPassSet.existentialTypeLayout)
        {
            SLANG_PASS(legalizeExistentialTypeLayout, targetProgram, sink);
        }

        validateIRModuleIfEnabled(codeGenContext, irModule);

        if (!validateStructuredBufferResourceTypes(irModule, sink, targetRequest))
            return SLANG_FAIL;

        // Many of our target languages and/or downstream compilers
        // don't support `struct` types that have resource-type fields.
        // In order to work around this limitation, we will rewrite the
        // IR so that any structure types with resource-type fields get
        // split into a "tuple" that comprises the ordinary fields (still
        // bundles up as a `struct`) and one element for each resource-type
        // field (recursively).
        //
        // What used to be individual variables/parameters/arguments/etc.
        // then become multiple variables/parameters/arguments/etc.
        //
        SLANG_PASS(legalizeResourceTypes, targetProgram, sink);

        // We also need to legalize empty types for Metal targets.