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