yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
22.5 KiB558 linesraw
1// d3d12-ray-tracing.cpp
2#include "d3d12-pipeline-state.h"
3
4#ifdef GFX_NVAPI
5#include "../nvapi/nvapi-include.h"
6#endif
7
8#include "../nvapi/nvapi-util.h"
9#include "d3d12-device.h"
10#include "d3d12-framebuffer.h"
11#include "d3d12-pipeline-state-stream.h"
12#include "d3d12-shader-program.h"
13#include "d3d12-vertex-layout.h"
14
15#include <climits>
16
17namespace gfx
18{
19namespace d3d12
20{
21
22using namespace Slang;
23
24void PipelineStateImpl::init(const GraphicsPipelineStateDesc& inDesc)
25{
26    PipelineStateDesc pipelineDesc;
27    pipelineDesc.type = PipelineType::Graphics;
28    pipelineDesc.graphics = inDesc;
29    initializeBase(pipelineDesc);
30}
31
32void PipelineStateImpl::init(const ComputePipelineStateDesc& inDesc)
33{
34    PipelineStateDesc pipelineDesc;
35    pipelineDesc.type = PipelineType::Compute;
36    pipelineDesc.compute = inDesc;
37    initializeBase(pipelineDesc);
38}
39
40Result PipelineStateImpl::getNativeHandle(InteropHandle* outHandle)
41{
42    SLANG_RETURN_ON_FAIL(ensureAPIPipelineStateCreated());
43    outHandle->api = InteropHandleAPI::D3D12;
44    outHandle->handleValue = reinterpret_cast<uint64_t>(m_pipelineState.get());
45    return SLANG_OK;
46}
47
48Result PipelineStateImpl::ensureAPIPipelineStateCreated()
49{
50    if (m_pipelineState)
51        return SLANG_OK;
52
53    auto programImpl = static_cast<ShaderProgramImpl*>(m_program.Ptr());
54    if (programImpl->m_shaders.getCount() == 0)
55    {
56        SLANG_RETURN_ON_FAIL(programImpl->compileShaders(m_device));
57    }
58    if (desc.type == PipelineType::Graphics)
59    {
60        // Only actually create a D3D12 pipeline state if the pipeline is fully specialized.
61        auto inputLayoutImpl = (InputLayoutImpl*)desc.graphics.inputLayout;
62
63        // A helper to fill common fields between graphics and mesh pipeline descs
64        const auto fillCommonGraphicsState = [&](auto& psoDesc)
65        {
66            psoDesc.pRootSignature = programImpl->m_rootObjectLayout->m_rootSignature;
67
68            psoDesc.PrimitiveTopologyType = D3DUtil::getPrimitiveType(desc.graphics.primitiveType);
69
70            {
71                auto framebufferLayout =
72                    static_cast<FramebufferLayoutImpl*>(desc.graphics.framebufferLayout);
73                const int numRenderTargets = int(framebufferLayout->m_renderTargets.getCount());
74
75                if (framebufferLayout->m_hasDepthStencil)
76                {
77                    psoDesc.DSVFormat =
78                        D3DUtil::getMapFormat(framebufferLayout->m_depthStencil.format);
79                    psoDesc.SampleDesc.Count = framebufferLayout->m_depthStencil.sampleCount;
80                }
81                else
82                {
83                    psoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
84                    if (framebufferLayout->m_renderTargets.getCount())
85                    {
86                        psoDesc.SampleDesc.Count =
87                            framebufferLayout->m_renderTargets[0].sampleCount;
88                    }
89                }
90                psoDesc.NumRenderTargets = numRenderTargets;
91                for (Int i = 0; i < numRenderTargets; i++)
92                {
93                    psoDesc.RTVFormats[i] =
94                        D3DUtil::getMapFormat(framebufferLayout->m_renderTargets[i].format);
95                }
96
97                psoDesc.SampleDesc.Quality = 0;
98                psoDesc.SampleMask = UINT_MAX;
99            }
100
101            {
102                auto& rs = psoDesc.RasterizerState;
103                rs.FillMode = D3DUtil::getFillMode(desc.graphics.rasterizer.fillMode);
104                rs.CullMode = D3DUtil::getCullMode(desc.graphics.rasterizer.cullMode);
105                rs.FrontCounterClockwise =
106                    desc.graphics.rasterizer.frontFace == gfx::FrontFaceMode::CounterClockwise
107                        ? TRUE
108                        : FALSE;
109                rs.DepthBias = desc.graphics.rasterizer.depthBias;
110                rs.DepthBiasClamp = desc.graphics.rasterizer.depthBiasClamp;
111                rs.SlopeScaledDepthBias = desc.graphics.rasterizer.slopeScaledDepthBias;
112                rs.DepthClipEnable = desc.graphics.rasterizer.depthClipEnable ? TRUE : FALSE;
113                rs.MultisampleEnable = desc.graphics.rasterizer.multisampleEnable ? TRUE : FALSE;
114                rs.AntialiasedLineEnable =
115                    desc.graphics.rasterizer.antialiasedLineEnable ? TRUE : FALSE;
116                rs.ForcedSampleCount = desc.graphics.rasterizer.forcedSampleCount;
117                rs.ConservativeRaster = desc.graphics.rasterizer.enableConservativeRasterization
118                                            ? D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON
119                                            : D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
120            }
121
122            {
123                D3D12_BLEND_DESC& blend = psoDesc.BlendState;
124                blend.IndependentBlendEnable = FALSE;
125                blend.AlphaToCoverageEnable =
126                    desc.graphics.blend.alphaToCoverageEnable ? TRUE : FALSE;
127                blend.RenderTarget[0].RenderTargetWriteMask =
128                    (uint8_t)RenderTargetWriteMask::EnableAll;
129                for (GfxIndex i = 0; i < desc.graphics.blend.targetCount; i++)
130                {
131                    auto& d3dDesc = blend.RenderTarget[i];
132                    d3dDesc.BlendEnable = desc.graphics.blend.targets[i].enableBlend ? TRUE : FALSE;
133                    d3dDesc.BlendOp = D3DUtil::getBlendOp(desc.graphics.blend.targets[i].color.op);
134                    d3dDesc.BlendOpAlpha =
135                        D3DUtil::getBlendOp(desc.graphics.blend.targets[i].alpha.op);
136                    d3dDesc.DestBlend =
137                        D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].color.dstFactor);
138                    d3dDesc.DestBlendAlpha =
139                        D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].alpha.dstFactor);
140                    d3dDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
141                    d3dDesc.LogicOpEnable = FALSE;
142                    d3dDesc.RenderTargetWriteMask = desc.graphics.blend.targets[i].writeMask;
143                    d3dDesc.SrcBlend =
144                        D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].color.srcFactor);
145                    d3dDesc.SrcBlendAlpha =
146                        D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].alpha.srcFactor);
147                }
148                for (GfxIndex i = 1; i < desc.graphics.blend.targetCount; i++)
149                {
150                    if (memcmp(
151                            &desc.graphics.blend.targets[i],
152                            &desc.graphics.blend.targets[0],
153                            sizeof(desc.graphics.blend.targets[0])) != 0)
154                    {
155                        blend.IndependentBlendEnable = TRUE;
156                        break;
157                    }
158                }
159                for (uint32_t i = (uint32_t)desc.graphics.blend.targetCount;
160                     i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT;
161                     ++i)
162                {
163                    blend.RenderTarget[i] = blend.RenderTarget[0];
164                }
165            }
166
167            {
168                auto& ds = psoDesc.DepthStencilState;
169
170                ds.DepthEnable = desc.graphics.depthStencil.depthTestEnable;
171                ds.DepthWriteMask = desc.graphics.depthStencil.depthWriteEnable
172                                        ? D3D12_DEPTH_WRITE_MASK_ALL
173                                        : D3D12_DEPTH_WRITE_MASK_ZERO;
174                ds.DepthFunc = D3DUtil::getComparisonFunc(desc.graphics.depthStencil.depthFunc);
175                ds.StencilEnable = desc.graphics.depthStencil.stencilEnable;
176                ds.StencilReadMask = (UINT8)desc.graphics.depthStencil.stencilReadMask;
177                ds.StencilWriteMask = (UINT8)desc.graphics.depthStencil.stencilWriteMask;
178                ds.FrontFace =
179                    D3DUtil::translateStencilOpDesc(desc.graphics.depthStencil.frontFace);
180                ds.BackFace = D3DUtil::translateStencilOpDesc(desc.graphics.depthStencil.backFace);
181            }
182
183            psoDesc.PrimitiveTopologyType = D3DUtil::getPrimitiveType(desc.graphics.primitiveType);
184        };
185
186        if (m_program->isMeshShaderProgram())
187        {
188            D3DX12_MESH_SHADER_PIPELINE_STATE_DESC meshDesc = {};
189            for (auto& shaderBin : programImpl->m_shaders)
190            {
191                switch (shaderBin.stage)
192                {
193                case SLANG_STAGE_FRAGMENT:
194                    meshDesc.PS = {shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount())};
195                    break;
196                case SLANG_STAGE_AMPLIFICATION:
197                    meshDesc.AS = {shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount())};
198                    break;
199                case SLANG_STAGE_MESH:
200                    meshDesc.MS = {shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount())};
201                    break;
202                default:
203                    getDebugCallback()->handleMessage(
204                        DebugMessageType::Error,
205                        DebugMessageSource::Layer,
206                        "Unsupported shader stage.");
207                    return SLANG_E_NOT_AVAILABLE;
208                }
209            }
210            fillCommonGraphicsState(meshDesc);
211            if (m_device->m_pipelineCreationAPIDispatcher)
212            {
213                SLANG_RETURN_ON_FAIL(
214                    m_device->m_pipelineCreationAPIDispatcher->createMeshPipelineState(
215                        m_device,
216                        programImpl->linkedProgram.get(),
217                        &meshDesc,
218                        (void**)m_pipelineState.writeRef()));
219            }
220            else
221            {
222                CD3DX12_PIPELINE_STATE_STREAM2 meshStateStream{meshDesc};
223                D3D12_PIPELINE_STATE_STREAM_DESC streamDesc{
224                    sizeof(meshStateStream),
225                    &meshStateStream};
226
227                SLANG_RETURN_ON_FAIL(m_device->m_device5->CreatePipelineState(
228                    &streamDesc,
229                    IID_PPV_ARGS(m_pipelineState.writeRef())));
230            }
231        }
232        else
233        {
234            D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicsDesc = {};
235            for (auto& shaderBin : programImpl->m_shaders)
236            {
237                switch (shaderBin.stage)
238                {
239                case SLANG_STAGE_VERTEX:
240                    graphicsDesc.VS = {
241                        shaderBin.code.getBuffer(),
242                        SIZE_T(shaderBin.code.getCount())};
243                    break;
244                case SLANG_STAGE_FRAGMENT:
245                    graphicsDesc.PS = {
246                        shaderBin.code.getBuffer(),
247                        SIZE_T(shaderBin.code.getCount())};
248                    break;
249                case SLANG_STAGE_DOMAIN:
250                    graphicsDesc.DS = {
251                        shaderBin.code.getBuffer(),
252                        SIZE_T(shaderBin.code.getCount())};
253                    break;
254                case SLANG_STAGE_HULL:
255                    graphicsDesc.HS = {
256                        shaderBin.code.getBuffer(),
257                        SIZE_T(shaderBin.code.getCount())};
258                    break;
259                case SLANG_STAGE_GEOMETRY:
260                    graphicsDesc.GS = {
261                        shaderBin.code.getBuffer(),
262                        SIZE_T(shaderBin.code.getCount())};
263                    break;
264                default:
265                    getDebugCallback()->handleMessage(
266                        DebugMessageType::Error,
267                        DebugMessageSource::Layer,
268                        "Unsupported shader stage.");
269                    return SLANG_E_NOT_AVAILABLE;
270                }
271            }
272
273            if (inputLayoutImpl)
274            {
275                graphicsDesc.InputLayout = {
276                    inputLayoutImpl->m_elements.getBuffer(),
277                    UINT(inputLayoutImpl->m_elements.getCount())};
278            }
279
280            fillCommonGraphicsState(graphicsDesc);
281
282            if (m_device->m_pipelineCreationAPIDispatcher)
283            {
284                SLANG_RETURN_ON_FAIL(
285                    m_device->m_pipelineCreationAPIDispatcher->createGraphicsPipelineState(
286                        m_device,
287                        programImpl->linkedProgram.get(),
288                        &graphicsDesc,
289                        (void**)m_pipelineState.writeRef()));
290            }
291            else
292            {
293                SLANG_RETURN_ON_FAIL(m_device->m_device->CreateGraphicsPipelineState(
294                    &graphicsDesc,
295                    IID_PPV_ARGS(m_pipelineState.writeRef())));
296            }
297        }
298    }
299    else
300    {
301
302        // Only actually create a D3D12 pipeline state if the pipeline is fully specialized.
303        ComPtr<ID3D12PipelineState> pipelineState;
304        if (!programImpl->isSpecializable())
305        {
306            // Describe and create the compute pipeline state object
307            D3D12_COMPUTE_PIPELINE_STATE_DESC computeDesc = {};
308            computeDesc.pRootSignature =
309                desc.compute.d3d12RootSignatureOverride
310                    ? static_cast<ID3D12RootSignature*>(desc.compute.d3d12RootSignatureOverride)
311                    : programImpl->m_rootObjectLayout->m_rootSignature;
312            computeDesc.CS = {
313                programImpl->m_shaders[0].code.getBuffer(),
314                SIZE_T(programImpl->m_shaders[0].code.getCount())};
315
316#ifdef GFX_NVAPI
317            if (m_device->m_nvapi)
318            {
319                // Also fill the extension structure.
320                // Use the same UAV slot index and register space that are declared in the shader.
321
322                // For simplicities sake we just use u0
323                NVAPI_D3D12_PSO_SET_SHADER_EXTENSION_SLOT_DESC extensionDesc;
324                extensionDesc.baseVersion = NV_PSO_EXTENSION_DESC_VER;
325                extensionDesc.version = NV_SET_SHADER_EXTENSION_SLOT_DESC_VER;
326                extensionDesc.uavSlot = 0;
327                extensionDesc.registerSpace = 0;
328
329                // Put the pointer to the extension into an array - there can be multiple extensions
330                // enabled at once.
331                const NVAPI_D3D12_PSO_EXTENSION_DESC* extensions[] = {&extensionDesc};
332
333                // Now create the PSO.
334                const NvAPI_Status nvapiStatus = NvAPI_D3D12_CreateComputePipelineState(
335                    m_device->m_device,
336                    &computeDesc,
337                    SLANG_COUNT_OF(extensions),
338                    extensions,
339                    m_pipelineState.writeRef());
340
341                if (nvapiStatus != NVAPI_OK)
342                {
343                    return SLANG_FAIL;
344                }
345            }
346            else
347#endif
348            {
349                if (m_device->m_pipelineCreationAPIDispatcher)
350                {
351                    SLANG_RETURN_ON_FAIL(
352                        m_device->m_pipelineCreationAPIDispatcher->createComputePipelineState(
353                            m_device,
354                            programImpl->linkedProgram.get(),
355                            &computeDesc,
356                            (void**)m_pipelineState.writeRef()));
357                }
358                else
359                {
360                    SLANG_RETURN_ON_FAIL(m_device->m_device->CreateComputePipelineState(
361                        &computeDesc,
362                        IID_PPV_ARGS(m_pipelineState.writeRef())));
363                }
364            }
365        }
366    }
367
368    return SLANG_OK;
369}
370
371#if SLANG_GFX_HAS_DXR_SUPPORT
372
373RayTracingPipelineStateImpl::RayTracingPipelineStateImpl(DeviceImpl* device)
374    : m_device(device)
375{
376}
377
378void RayTracingPipelineStateImpl::init(const RayTracingPipelineStateDesc& inDesc)
379{
380    PipelineStateDesc pipelineDesc;
381    pipelineDesc.type = PipelineType::RayTracing;
382    pipelineDesc.rayTracing.set(inDesc);
383    initializeBase(pipelineDesc);
384}
385
386Result RayTracingPipelineStateImpl::getNativeHandle(InteropHandle* outHandle)
387{
388    SLANG_RETURN_ON_FAIL(ensureAPIPipelineStateCreated());
389    outHandle->api = InteropHandleAPI::D3D12;
390    outHandle->handleValue = reinterpret_cast<uint64_t>(m_stateObject.get());
391    return SLANG_OK;
392}
393
394Result RayTracingPipelineStateImpl::ensureAPIPipelineStateCreated()
395{
396    if (m_stateObject)
397        return SLANG_OK;
398
399    auto program = static_cast<ShaderProgramImpl*>(m_program.Ptr());
400    auto slangGlobalScope = program->linkedProgram;
401    auto programLayout = slangGlobalScope->getLayout();
402
403    List<D3D12_STATE_SUBOBJECT> subObjects;
404    ChunkedList<D3D12_DXIL_LIBRARY_DESC> dxilLibraries;
405    ChunkedList<D3D12_HIT_GROUP_DESC> hitGroups;
406    ChunkedList<ComPtr<ISlangBlob>> codeBlobs;
407    ChunkedList<D3D12_EXPORT_DESC> exports;
408    ChunkedList<const wchar_t*> strPtrs;
409    ComPtr<ISlangBlob> diagnostics;
410    ChunkedList<OSString> stringPool;
411    auto getWStr = [&](const char* name)
412    {
413        String str = String(name);
414        auto wstr = str.toWString();
415        return stringPool.add(wstr)->begin();
416    };
417
418    D3D12_RAYTRACING_PIPELINE_CONFIG1 pipelineConfig = {};
419    pipelineConfig.MaxTraceRecursionDepth = desc.rayTracing.maxRecursion;
420    if (desc.rayTracing.flags & RayTracingPipelineFlags::SkipTriangles)
421        pipelineConfig.Flags |= D3D12_RAYTRACING_PIPELINE_FLAG_SKIP_TRIANGLES;
422    if (desc.rayTracing.flags & RayTracingPipelineFlags::SkipProcedurals)
423        pipelineConfig.Flags |= D3D12_RAYTRACING_PIPELINE_FLAG_SKIP_PROCEDURAL_PRIMITIVES;
424
425    D3D12_STATE_SUBOBJECT pipelineConfigSubobject = {};
426    pipelineConfigSubobject.Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG1;
427    pipelineConfigSubobject.pDesc = &pipelineConfig;
428    subObjects.add(pipelineConfigSubobject);
429
430    auto compileShader = [&](slang::EntryPointLayout* entryPointInfo,
431                             slang::IComponentType* component,
432                             SlangInt entryPointIndex)
433    {
434        ComPtr<ISlangBlob> codeBlob;
435        auto compileResult = m_device->getEntryPointCodeFromShaderCache(
436            component,
437            entryPointIndex,
438            0,
439            codeBlob.writeRef(),
440            diagnostics.writeRef());
441        if (diagnostics.get())
442        {
443            getDebugCallback()->handleMessage(
444                compileResult == SLANG_OK ? DebugMessageType::Warning : DebugMessageType::Error,
445                DebugMessageSource::Slang,
446                (char*)diagnostics->getBufferPointer());
447        }
448        SLANG_RETURN_ON_FAIL(compileResult);
449        codeBlobs.add(codeBlob);
450        D3D12_DXIL_LIBRARY_DESC library = {};
451        library.DXILLibrary.BytecodeLength = codeBlob->getBufferSize();
452        library.DXILLibrary.pShaderBytecode = codeBlob->getBufferPointer();
453        library.NumExports = 1;
454        D3D12_EXPORT_DESC exportDesc = {};
455        exportDesc.Name = getWStr(entryPointInfo->getNameOverride());
456        exportDesc.ExportToRename = nullptr;
457        exportDesc.Flags = D3D12_EXPORT_FLAG_NONE;
458        library.pExports = exports.add(exportDesc);
459
460        D3D12_STATE_SUBOBJECT dxilSubObject = {};
461        dxilSubObject.Type = D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY;
462        dxilSubObject.pDesc = dxilLibraries.add(library);
463        subObjects.add(dxilSubObject);
464        return SLANG_OK;
465    };
466    if (program->linkedEntryPoints.getCount() == 0)
467    {
468        for (SlangUInt i = 0; i < programLayout->getEntryPointCount(); i++)
469        {
470            SLANG_RETURN_ON_FAIL(compileShader(
471                programLayout->getEntryPointByIndex(i),
472                program->linkedProgram,
473                (SlangInt)i));
474        }
475    }
476    else
477    {
478        for (auto& entryPoint : program->linkedEntryPoints)
479        {
480            SLANG_RETURN_ON_FAIL(
481                compileShader(entryPoint->getLayout()->getEntryPointByIndex(0), entryPoint, 0));
482        }
483    }
484
485    for (Index i = 0; i < desc.rayTracing.hitGroupDescs.getCount(); i++)
486    {
487        auto& hitGroup = desc.rayTracing.hitGroups[i];
488        D3D12_HIT_GROUP_DESC hitGroupDesc = {};
489        hitGroupDesc.Type = hitGroup.intersectionEntryPoint.getLength() == 0
490                                ? D3D12_HIT_GROUP_TYPE_TRIANGLES
491                                : D3D12_HIT_GROUP_TYPE_PROCEDURAL_PRIMITIVE;
492
493        if (hitGroup.anyHitEntryPoint.getLength())
494        {
495            hitGroupDesc.AnyHitShaderImport = getWStr(hitGroup.anyHitEntryPoint.getBuffer());
496        }
497        if (hitGroup.closestHitEntryPoint.getLength())
498        {
499            hitGroupDesc.ClosestHitShaderImport =
500                getWStr(hitGroup.closestHitEntryPoint.getBuffer());
501        }
502        if (hitGroup.intersectionEntryPoint.getLength())
503        {
504            hitGroupDesc.IntersectionShaderImport =
505                getWStr(hitGroup.intersectionEntryPoint.getBuffer());
506        }
507        hitGroupDesc.HitGroupExport = getWStr(hitGroup.hitGroupName.getBuffer());
508
509        D3D12_STATE_SUBOBJECT hitGroupSubObject = {};
510        hitGroupSubObject.Type = D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP;
511        hitGroupSubObject.pDesc = hitGroups.add(hitGroupDesc);
512        subObjects.add(hitGroupSubObject);
513    }
514
515    D3D12_RAYTRACING_SHADER_CONFIG shaderConfig = {};
516    // According to DXR spec, fixed function triangle intersections must use float2 as ray
517    // attributes that defines the barycentric coordinates at intersection.
518    shaderConfig.MaxAttributeSizeInBytes = (UINT)desc.rayTracing.maxAttributeSizeInBytes;
519    shaderConfig.MaxPayloadSizeInBytes = (UINT)desc.rayTracing.maxRayPayloadSize;
520    D3D12_STATE_SUBOBJECT shaderConfigSubObject = {};
521    shaderConfigSubObject.Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG;
522    shaderConfigSubObject.pDesc = &shaderConfig;
523    subObjects.add(shaderConfigSubObject);
524
525    D3D12_GLOBAL_ROOT_SIGNATURE globalSignatureDesc = {};
526    globalSignatureDesc.pGlobalRootSignature = program->m_rootObjectLayout->m_rootSignature.get();
527    D3D12_STATE_SUBOBJECT globalSignatureSubobject = {};
528    globalSignatureSubobject.Type = D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE;
529    globalSignatureSubobject.pDesc = &globalSignatureDesc;
530    subObjects.add(globalSignatureSubobject);
531
532    if (m_device->m_pipelineCreationAPIDispatcher)
533    {
534        m_device->m_pipelineCreationAPIDispatcher->beforeCreateRayTracingState(
535            m_device,
536            slangGlobalScope);
537    }
538
539    D3D12_STATE_OBJECT_DESC rtpsoDesc = {};
540    rtpsoDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE;
541    rtpsoDesc.NumSubobjects = (UINT)subObjects.getCount();
542    rtpsoDesc.pSubobjects = subObjects.getBuffer();
543    SLANG_RETURN_ON_FAIL(
544        m_device->m_device5->CreateStateObject(&rtpsoDesc, IID_PPV_ARGS(m_stateObject.writeRef())));
545
546    if (m_device->m_pipelineCreationAPIDispatcher)
547    {
548        m_device->m_pipelineCreationAPIDispatcher->afterCreateRayTracingState(
549            m_device,
550            slangGlobalScope);
551    }
552    return SLANG_OK;
553}
554
555#endif
556
557} // namespace d3d12
558} // namespace gfx