<p>I don't know why, but using any loop while using D3D12_DXIL_LIBRARY_DESC is causing problems. It doesn't seem that it goes out of scope, because current code is seperate by blocks with seperate scops already. Therefore I don't think that's what causes problem.</p>
<p>I've dealt with it by simply copy-pasting code and changing index of used data, guarded with (if array.size() &gt; 1). For now, I need only two arrays, but in future, I might add multiple copy-pastes like that. Ideal solution would be either using macros or reaching dxc developers to know what causes problem. <strong>However, for my usage purposes</strong> it is enough solution.</p>
<p>Also, please take a look at this link - <a href="https://www.willusher.io/graphics/2019/11/20/the-sbt-three-ways" rel="nofollow noreferrer">https://www.willusher.io/graphics/2019/11/20/the-sbt-three-ways</a> - it turns to be very useful to understand indexing of miss shader/hit groups data.</p>

CC BY-SA 4.0
2020-08-28T12:27:42.213Z
2020-08-28T12:27:42.213Z
DirectX_Programmer
<p>I am getting this error when creating RTPSO with multiple hit groups:</p>
<pre><code>D3D12 ERROR: ID3D12Device::CreateStateObject: Export &quot;MissIndirect&quot; (mangled name: &quot;\01?MissIndirect@@YAXURayPayload@@@Z&quot;) already defined. [ STATE_CREATION ERROR #1194: CREATE_STATE_OBJECT_ERROR]
</code></pre>
<p>With single hit group I am not getting any errors and code below works correctly:</p>
<pre><code>void RaytracingResources::CreateRTPSO(ID3D12Device5* device, size_t maxPayloadSize)
{
    // Need 11 subobjects:
    // 1 for RGS program
    // 1 for Miss program
    // 1 for CHS program
    // 1 for AHS program
    // 1 for Hit Group
    // 2 for RayGen Root Signature (root-signature and association)
    // 2 for Shader Config (config and association)
    // 1 for Global Root Signature
    // 1 for Pipeline Config    
    UINT index = 0;
    std::vector&lt;D3D12_STATE_SUBOBJECT&gt; subobjects;
    size_t size = 0;
    size += 1; // rgs
    for (auto&amp; hitGroup : m_hitGroups)
    {
        size += 2; // chs, miss
        size += (hitGroup.hitShader.ahs.name != nullptr) ? 1 : 0; // ahs
        size += 1; // hit group
        size += 2; // payload + association
        size += 2; // local root + association
    }
    size += 2; // global root + pipeline config
    subobjects.resize(size);

    std::vector&lt;LPCWSTR&gt; usedNames;
    std::vector&lt;IDxcBlob&gt; usedBlobs;

    // Add state subobject for the RGS
    {
        D3D12_EXPORT_DESC rgsExportDesc = { m_hitGroups[0].rayGenShader.name, nullptr, D3D12_EXPORT_FLAG_NONE };

        D3D12_DXIL_LIBRARY_DESC rgsLibDesc = {};
        rgsLibDesc.DXILLibrary.BytecodeLength = m_hitGroups[0].rayGenShader.blob-&gt;GetBufferSize();
        rgsLibDesc.DXILLibrary.pShaderBytecode = m_hitGroups[0].rayGenShader.blob-&gt;GetBufferPointer();
        rgsLibDesc.NumExports = 1;
        rgsLibDesc.pExports = &amp;rgsExportDesc;

        D3D12_STATE_SUBOBJECT rgs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;rgsLibDesc };
        subobjects[index++] = rgs;
        usedNames.push_back(m_hitGroups[0].rayGenShader.name);
    }

    for (auto&amp; hitGroup : m_hitGroups)
    {
        //Add state subobject for the Miss shader
        {
            D3D12_EXPORT_DESC msExportDesc = { hitGroup.missShader.name, hitGroup.missShader.exportToRename, D3D12_EXPORT_FLAG_NONE };

            D3D12_DXIL_LIBRARY_DESC msLibDesc = {};
            msLibDesc.DXILLibrary.BytecodeLength = hitGroup.missShader.blob-&gt;GetBufferSize();
            msLibDesc.DXILLibrary.pShaderBytecode = hitGroup.missShader.blob-&gt;GetBufferPointer();
            msLibDesc.NumExports = 1;
            msLibDesc.pExports = &amp;msExportDesc;

            D3D12_STATE_SUBOBJECT ms = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;msLibDesc };
            subobjects[index++] = ms;
        }

        // Add state subobject for the Closest Hit shader
        {
            D3D12_EXPORT_DESC chsExportDesc = { hitGroup.hitShader.chs.name, hitGroup.hitShader.chs.exportToRename, D3D12_EXPORT_FLAG_NONE };

            D3D12_DXIL_LIBRARY_DESC chsLibDesc = {};
            chsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.chs.blob-&gt;GetBufferSize();
            chsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.chs.blob-&gt;GetBufferPointer();
            chsLibDesc.NumExports = 1;
            chsLibDesc.pExports = &amp;chsExportDesc;

            D3D12_STATE_SUBOBJECT chs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;chsLibDesc };
            subobjects[index++] = chs;
        }

        // Add state subobject for the Any Hit shader
        if (hitGroup.hitShader.ahs.name != nullptr)
        {
            D3D12_EXPORT_DESC ahsExportDesc = { hitGroup.hitShader.ahs.name, hitGroup.hitShader.ahs.exportToRename, D3D12_EXPORT_FLAG_NONE };

            D3D12_DXIL_LIBRARY_DESC ahsLibDesc = {};
            ahsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.ahs.blob-&gt;GetBufferSize();
            ahsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.ahs.blob-&gt;GetBufferPointer();
            ahsLibDesc.NumExports = 1;
            ahsLibDesc.pExports = &amp;ahsExportDesc;

            D3D12_STATE_SUBOBJECT ahs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;ahsLibDesc };
            subobjects[index++] = ahs;
        }

        // Add a state subobject for the hit group
        {
            D3D12_HIT_GROUP_DESC hitGroupDesc = {};
            hitGroupDesc.ClosestHitShaderImport = hitGroup.hitShader.chs.name;
            if (hitGroup.hitShader.ahs.name != nullptr) hitGroupDesc.AnyHitShaderImport = hitGroup.hitShader.ahs.name;
            hitGroupDesc.HitGroupExport = hitGroup.hitGroupName;

            D3D12_STATE_SUBOBJECT hitGroup = { D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &amp;hitGroupDesc };
            subobjects[index++] = hitGroup;
        }

        // Add a state subobject for the shader payload configuration
        {
            D3D12_RAYTRACING_SHADER_CONFIG shaderDesc = { static_cast&lt;UINT&gt;(maxPayloadSize), D3D12_RAYTRACING_MAX_ATTRIBUTE_SIZE_IN_BYTES };
            D3D12_STATE_SUBOBJECT shaderConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &amp;shaderDesc };
            subobjects[index++] = shaderConfigObject;
        }

        // Create a list of the shader export names that use the payload
        {
            D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION shaderPayloadAssociation = {};
            if (hitGroup.hitShader.ahs.name != nullptr) {
                const WCHAR* shaderExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };
                shaderPayloadAssociation = { &amp;subobjects[(index - 1)], _countof(shaderExports), shaderExports };
            }
            else {
                const WCHAR* shaderExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };
                shaderPayloadAssociation = { &amp;subobjects[(index - 1)], _countof(shaderExports), shaderExports };
            }

            D3D12_STATE_SUBOBJECT shaderPayloadAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;shaderPayloadAssociation };
            subobjects[index++] = shaderPayloadAssociationObject;
        }

        // Add a state subobject for the shared root signature 
        {
            D3D12_STATE_SUBOBJECT rayGenRootSigObject = { D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &amp;hitGroup.rayGenShader.pRootSignature };
            subobjects[index++] = rayGenRootSigObject;
        }

        // Create a list of the shader export names that use the root signature
        {
            D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION rayGenShaderRootSigAssociation = {};
            if (hitGroup.hitShader.ahs.name != nullptr)
            {
                const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };
                rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };
            }
            else
            {
                const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };
                rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };
            }

            D3D12_STATE_SUBOBJECT rayGenShaderRootSigAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;rayGenShaderRootSigAssociation };
            subobjects[index++] = rayGenShaderRootSigAssociationObject;
        }
    }

    // Setup global root signature
    {
        D3D12_STATE_SUBOBJECT globalRootSig = { D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &amp;m_hitGroups[0].missShader.pRootSignature };
        subobjects[index++] = globalRootSig;
    }

    // Add a state subobject for the ray tracing pipeline config
    {
        D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = { 1 }; // Max Trace Recursion Depth
        D3D12_STATE_SUBOBJECT pipelineConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG, &amp;pipelineConfig };
        subobjects[index++] = pipelineConfigObject; 
    }

    // Finish rtpso creation and store in variable
    {
        // Describe RTPSO
        D3D12_STATE_OBJECT_DESC pipelineDesc = { D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE, static_cast&lt;UINT&gt;(subobjects.size()), subobjects.data() };

        // Create the RT Pipeline State Object (RTPSO) / Get the RTPSO properties
        ThrowIfFailed(device-&gt;CreateStateObject(&amp;pipelineDesc, IID_PPV_ARGS(&amp;m_rtpso)));
        ThrowIfFailed(m_rtpso-&gt;QueryInterface(IID_PPV_ARGS(&amp;m_rtpsoInfo)));
    }
}
</code></pre>
<p>I am calling it with code below:</p>
<pre><code>CreateRayGenShader(rayGenShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, 2, 1, 5, {}, L&quot;RayGen&quot;);
CreateMissShader(missShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, L&quot;Miss&quot;);
CreateClosestHitShader(hitShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, L&quot;ClosestHit&quot;);

CreateMissShader(missShader_new, m_shaderCompiler, L&quot;Shaders/RT_Lambertian_Indirect.hlsl&quot;, L&quot;MissIndirect&quot;);
CreateClosestHitShader(hitShader_new, m_shaderCompiler, L&quot;Shaders/RT_Lambertian_Indirect.hlsl&quot;, L&quot;ClosestHitIndirect&quot;);

HitGroup group = { rayGenShader, missShader, hitShader, L&quot;GroupLambert&quot; };
HitGroup group_new = { rayGenShader, missShader_new, hitShader_new, L&quot;GroupLambert_new&quot; };

m_raytracingLambert = std::shared_ptr&lt;RaytracingResources&gt;(new RaytracingResources(m_device.Get(), m_commandList, model, { group, group_new }));
</code></pre>
<p><strong>However, even when I'm trying to create single group, but I am using std::vector to iterate over rgs, ms, chs - it causes same error:</strong> (i.e. export &quot;name&quot; already defined [ STATE_CREATION ERROR #1194: CREATE_STATE_OBJECT_ERROR]). Therefore, I am using lengthy code which is called seperately for ms, rgs, chs (and ahs if present).</p>
<pre><code>std::vector&lt;RtProgram&gt; rtPrograms;
HitGroup hitGroup = m_hitGroups[0];
rtPrograms.push_back(hitGroup.rayGenShader);
rtPrograms.push_back(hitGroup.missShader);
rtPrograms.push_back(hitGroup.hitShader.chs);

for (auto&amp; shader : rtPrograms)
{
    D3D12_EXPORT_DESC exportDesc = { shader.name, shader.exportToRename, D3D12_EXPORT_FLAG_NONE };

    D3D12_DXIL_LIBRARY_DESC libDesc = {};
    libDesc.DXILLibrary.BytecodeLength = shader.blob-&gt;GetBufferSize();
    libDesc.DXILLibrary.pShaderBytecode = shader.blob-&gt;GetBufferPointer();
    libDesc.NumExports = 1;
    libDesc.pExports = &amp;exportDesc;

    D3D12_STATE_SUBOBJECT stateSubobject = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;libDesc };
    subobjects[index++] = stateSubobject;
}
</code></pre>
<p>Repo with this code can be found here - <a href="https://github.com/komilll/RTCP/blob/0b81a41f95ae3fa536324b27201a5fce94f92f24/RTCP/Renderer.cpp#L1039" rel="nofollow noreferrer">https://github.com/komilll/RTCP/blob/0b81a41f95ae3fa536324b27201a5fce94f92f24/RTCP/Renderer.cpp#L1039</a></p>

<raytracing><c++><directx12>
Hit group - export already defined
DirectX_Programmer
# Hit group - export already defined

(Asked by: username_0 on 2020-08-26)

I am getting this error when creating RTPSO with multiple hit groups:

```
D3D12 ERROR: ID3D12Device::CreateStateObject: Export "MissIndirect" (mangled name: "\01?MissIndirect@@YAXURayPayload@@@Z") already defined. [ STATE_CREATION ERROR #1194: CREATE_STATE_OBJECT_ERROR]

```

With single hit group I am not getting any errors and code below works correctly:

```
void RaytracingResources::CreateRTPSO(ID3D12Device5* device, size_t maxPayloadSize)
{
    // Need 11 subobjects:
    // 1 for RGS program
    // 1 for Miss program
    // 1 for CHS program
    // 1 for AHS program
    // 1 for Hit Group
    // 2 for RayGen Root Signature (root-signature and association)
    // 2 for Shader Config (config and association)
    // 1 for Global Root Signature
    // 1 for Pipeline Config    
    UINT index = 0;
    std::vector<D3D12_STATE_SUBOBJECT> subobjects;
    size_t size = 0;
    size += 1; // rgs
    for (auto& hitGroup : m_hitGroups)
    {
        size += 2; // chs, miss
        size += (hitGroup.hitShader.ahs.name != nullptr) ? 1 : 0; // ahs
        size += 1; // hit group
        size += 2; // payload + association
        size += 2; // local root + association
    }
    size += 2; // global root + pipeline config
    subobjects.resize(size);

    std::vector<LPCWSTR> usedNames;
    std::vector<IDxcBlob> usedBlobs;

    // Add state subobject for the RGS
    {
        D3D12_EXPORT_DESC rgsExportDesc = { m_hitGroups[0].rayGenShader.name, nullptr, D3D12_EXPORT_FLAG_NONE };

        D3D12_DXIL_LIBRARY_DESC rgsLibDesc = {};
        rgsLibDesc.DXILLibrary.BytecodeLength = m_hitGroups[0].rayGenShader.blob->GetBufferSize();
        rgsLibDesc.DXILLibrary.pShaderBytecode = m_hitGroups[0].rayGenShader.blob->GetBufferPointer();
        rgsLibDesc.NumExports = 1;
        rgsLibDesc.pExports = &rgsExportDesc;

        D3D12_STATE_SUBOBJECT rgs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &rgsLibDesc };
        subobjects[index++] = rgs;
        usedNames.push_back(m_hitGroups[0].rayGenShader.name);
    }

    for (auto& hitGroup : m_hitGroups)
    {
        //Add state subobject for the Miss shader
        {
            D3D12_EXPORT_DESC msExportDesc = { hitGroup.missShader.name, hitGroup.missShader.exportToRename, D3D12_EXPORT_FLAG_NONE };

            D3D12_DXIL_LIBRARY_DESC msLibDesc = {};
            msLibDesc.DXILLibrary.BytecodeLength = hitGroup.missShader.blob->GetBufferSize();
            msLibDesc.DXILLibrary.pShaderBytecode = hitGroup.missShader.blob->GetBufferPointer();
            msLibDesc.NumExports = 1;
            msLibDesc.pExports = &msExportDesc;

            D3D12_STATE_SUBOBJECT ms = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &msLibDesc };
            subobjects[index++] = ms;
        }

        // Add state subobject for the Closest Hit shader
        {
            D3D12_EXPORT_DESC chsExportDesc = { hitGroup.hitShader.chs.name, hitGroup.hitShader.chs.exportToRename, D3D12_EXPORT_FLAG_NONE };

            D3D12_DXIL_LIBRARY_DESC chsLibDesc = {};
            chsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.chs.blob->GetBufferSize();
            chsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.chs.blob->GetBufferPointer();
            chsLibDesc.NumExports = 1;
            chsLibDesc.pExports = &chsExportDesc;

            D3D12_STATE_SUBOBJECT chs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &chsLibDesc };
            subobjects[index++] = chs;
        }

        // Add state subobject for the Any Hit shader
        if (hitGroup.hitShader.ahs.name != nullptr)
        {
            D3D12_EXPORT_DESC ahsExportDesc = { hitGroup.hitShader.ahs.name, hitGroup.hitShader.ahs.exportToRename, D3D12_EXPORT_FLAG_NONE };

            D3D12_DXIL_LIBRARY_DESC ahsLibDesc = {};
            ahsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.ahs.blob->GetBufferSize();
            ahsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.ahs.blob->GetBufferPointer();
            ahsLibDesc.NumExports = 1;
            ahsLibDesc.pExports = &ahsExportDesc;

            D3D12_STATE_SUBOBJECT ahs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &ahsLibDesc };
            subobjects[index++] = ahs;
        }

        // Add a state subobject for the hit group
        {
            D3D12_HIT_GROUP_DESC hitGroupDesc = {};
            hitGroupDesc.ClosestHitShaderImport = hitGroup.hitShader.chs.name;
            if (hitGroup.hitShader.ahs.name != nullptr) hitGroupDesc.AnyHitShaderImport = hitGroup.hitShader.ahs.name;
            hitGroupDesc.HitGroupExport = hitGroup.hitGroupName;

            D3D12_STATE_SUBOBJECT hitGroup = { D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &hitGroupDesc };
            subobjects[index++] = hitGroup;
        }

        // Add a state subobject for the shader payload configuration
        {
            D3D12_RAYTRACING_SHADER_CONFIG shaderDesc = { static_cast<UINT>(maxPayloadSize), D3D12_RAYTRACING_MAX_ATTRIBUTE_SIZE_IN_BYTES };
            D3D12_STATE_SUBOBJECT shaderConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &shaderDesc };
            subobjects[index++] = shaderConfigObject;
        }

        // Create a list of the shader export names that use the payload
        {
            D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION shaderPayloadAssociation = {};
            if (hitGroup.hitShader.ahs.name != nullptr) {
                const WCHAR* shaderExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };
                shaderPayloadAssociation = { &subobjects[(index - 1)], _countof(shaderExports), shaderExports };
            }
            else {
                const WCHAR* shaderExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };
                shaderPayloadAssociation = { &subobjects[(index - 1)], _countof(shaderExports), shaderExports };
            }

            D3D12_STATE_SUBOBJECT shaderPayloadAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &shaderPayloadAssociation };
            subobjects[index++] = shaderPayloadAssociationObject;
        }

        // Add a state subobject for the shared root signature 
        {
            D3D12_STATE_SUBOBJECT rayGenRootSigObject = { D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &hitGroup.rayGenShader.pRootSignature };
            subobjects[index++] = rayGenRootSigObject;
        }

        // Create a list of the shader export names that use the root signature
        {
            D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION rayGenShaderRootSigAssociation = {};
            if (hitGroup.hitShader.ahs.name != nullptr)
            {
                const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };
                rayGenShaderRootSigAssociation = { &subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };
            }
            else
            {
                const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };
                rayGenShaderRootSigAssociation = { &subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };
            }

            D3D12_STATE_SUBOBJECT rayGenShaderRootSigAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &rayGenShaderRootSigAssociation };
            subobjects[index++] = rayGenShaderRootSigAssociationObject;
        }
    }

    // Setup global root signature
    {
        D3D12_STATE_SUBOBJECT globalRootSig = { D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &m_hitGroups[0].missShader.pRootSignature };
        subobjects[index++] = globalRootSig;
    }

    // Add a state subobject for the ray tracing pipeline config
    {
        D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = { 1 }; // Max Trace Recursion Depth
        D3D12_STATE_SUBOBJECT pipelineConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG, &pipelineConfig };
        subobjects[index++] = pipelineConfigObject; 
    }

    // Finish rtpso creation and store in variable
    {
        // Describe RTPSO
        D3D12_STATE_OBJECT_DESC pipelineDesc = { D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE, static_cast<UINT>(subobjects.size()), subobjects.data() };

        // Create the RT Pipeline State Object (RTPSO) / Get the RTPSO properties
        ThrowIfFailed(device->CreateStateObject(&pipelineDesc, IID_PPV_ARGS(&m_rtpso)));
        ThrowIfFailed(m_rtpso->QueryInterface(IID_PPV_ARGS(&m_rtpsoInfo)));
    }
}

```

I am calling it with code below:

```
CreateRayGenShader(rayGenShader, m_shaderCompiler, L"Shaders/RT_Lambertian.hlsl", 2, 1, 5, {}, L"RayGen");
CreateMissShader(missShader, m_shaderCompiler, L"Shaders/RT_Lambertian.hlsl", L"Miss");
CreateClosestHitShader(hitShader, m_shaderCompiler, L"Shaders/RT_Lambertian.hlsl", L"ClosestHit");

CreateMissShader(missShader_new, m_shaderCompiler, L"Shaders/RT_Lambertian_Indirect.hlsl", L"MissIndirect");
CreateClosestHitShader(hitShader_new, m_shaderCompiler, L"Shaders/RT_Lambertian_Indirect.hlsl", L"ClosestHitIndirect");

HitGroup group = { rayGenShader, missShader, hitShader, L"GroupLambert" };
HitGroup group_new = { rayGenShader, missShader_new, hitShader_new, L"GroupLambert_new" };

m_raytracingLambert = std::shared_ptr<RaytracingResources>(new RaytracingResources(m_device.Get(), m_commandList, model, { group, group_new }));

```

**However, even when I'm trying to create single group, but I am using std::vector to iterate over rgs, ms, chs - it causes same error:** (i.e. export "name" already defined [ STATE\_CREATION ERROR #1194: CREATE\_STATE\_OBJECT\_ERROR]). Therefore, I am using lengthy code which is called seperately for ms, rgs, chs (and ahs if present).

```
std::vector<RtProgram> rtPrograms;
HitGroup hitGroup = m_hitGroups[0];
rtPrograms.push_back(hitGroup.rayGenShader);
rtPrograms.push_back(hitGroup.missShader);
rtPrograms.push_back(hitGroup.hitShader.chs);

for (auto& shader : rtPrograms)
{
    D3D12_EXPORT_DESC exportDesc = { shader.name, shader.exportToRename, D3D12_EXPORT_FLAG_NONE };

    D3D12_DXIL_LIBRARY_DESC libDesc = {};
    libDesc.DXILLibrary.BytecodeLength = shader.blob->GetBufferSize();
    libDesc.DXILLibrary.pShaderBytecode = shader.blob->GetBufferPointer();
    libDesc.NumExports = 1;
    libDesc.pExports = &exportDesc;

    D3D12_STATE_SUBOBJECT stateSubobject = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &libDesc };
    subobjects[index++] = stateSubobject;
}

```

Repo with this code can be found here - <https://github.com/komilll/RTCP/blob/0b81a41f95ae3fa536324b27201a5fce94f92f24/RTCP/Renderer.cpp#L1039>

**Tags:** raytracing, c++, directx12


---

## 1 answers

### Answer by username_0 on 2020-08-28. Score: 0 | Accepted answer

I don't know why, but using any loop while using D3D12\_DXIL\_LIBRARY\_DESC is causing problems. It doesn't seem that it goes out of scope, because current code is seperate by blocks with seperate scops already. Therefore I don't think that's what causes problem.

I've dealt with it by simply copy-pasting code and changing index of used data, guarded with (if array.size() > 1). For now, I need only two arrays, but in future, I might add multiple copy-pastes like that. Ideal solution would be either using macros or reaching dxc developers to know what causes problem. **However, for my usage purposes** it is enough solution.

Also, please take a look at this link - <https://www.willusher.io/graphics/2019/11/20/the-sbt-three-ways> - it turns to be very useful to understand indexing of miss shader/hit groups data.


---

