yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
b118451e3
master
1// vk-pipeline-state.cpp 2#include "vk-pipeline-state.h" 3 4#include "vk-device.h" 5#include "vk-helper-functions.h" 6#include "vk-shader-object-layout.h" 7#include "vk-shader-program.h" 8#include "vk-vertex-layout.h" 9 10namespace gfx 11{ 12 13using namespace Slang ; 14 15namespace vk 16{ 17 18PipelineStateImpl ::PipelineStateImpl (DeviceImpl * device ) 19{ 20// Only weakly reference `device` at start. 21// We make it a strong reference only when the pipeline state is exposed to the user. 22// Note that `PipelineState`s may also be created via implicit specialization that 23// happens behind the scenes, and the user will not have access to those specialized 24// pipeline states. Only those pipeline states that are returned to the user needs to 25// hold a strong reference to `device`. 26m_device .setWeakReference (device ); 27} 28 29PipelineStateImpl ::~PipelineStateImpl () 30{ 31if (m_pipeline != VK_NULL_HANDLE ) 32 { 33m_device -> m_api .vkDestroyPipeline (m_device -> m_api .m_device ,m_pipeline ,nullptr ); 34 } 35} 36 37void PipelineStateImpl ::establishStrongDeviceReference () 38{ 39m_device .establishStrongReference (); 40} 41 42void PipelineStateImpl ::comFree () 43{ 44m_device .breakStrongReference (); 45} 46 47void PipelineStateImpl ::init (const GraphicsPipelineStateDesc & inDesc ) 48{ 49PipelineStateDesc pipelineDesc ; 50pipelineDesc .type = PipelineType ::Graphics ; 51pipelineDesc .graphics = inDesc ; 52initializeBase (pipelineDesc ); 53} 54 55void PipelineStateImpl ::init (const ComputePipelineStateDesc & inDesc ) 56{ 57PipelineStateDesc pipelineDesc ; 58pipelineDesc .type = PipelineType ::Compute ; 59pipelineDesc .compute = inDesc ; 60initializeBase (pipelineDesc ); 61} 62 63void PipelineStateImpl ::init (const RayTracingPipelineStateDesc & inDesc ) 64{ 65PipelineStateDesc pipelineDesc ; 66pipelineDesc .type = PipelineType ::RayTracing ; 67pipelineDesc .rayTracing .set (inDesc ); 68initializeBase (pipelineDesc ); 69} 70 71Result PipelineStateImpl ::createVKGraphicsPipelineState () 72{ 73VkPipelineCache pipelineCache = VK_NULL_HANDLE ; 74 75auto inputLayoutImpl = (InputLayoutImpl * )desc .graphics .inputLayout ; 76 77// VertexBuffer/s 78VkPipelineVertexInputStateCreateInfo vertexInputInfo = { 79VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; 80vertexInputInfo .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO ; 81vertexInputInfo .vertexBindingDescriptionCount = 0 ; 82vertexInputInfo .vertexAttributeDescriptionCount = 0 ; 83 84if (inputLayoutImpl ) 85 { 86const auto & srcAttributeDescs = inputLayoutImpl -> m_attributeDescs ; 87const auto & srcStreamDescs = inputLayoutImpl -> m_streamDescs ; 88 89vertexInputInfo .vertexBindingDescriptionCount = (uint32_t )srcStreamDescs .getCount (); 90vertexInputInfo .pVertexBindingDescriptions = srcStreamDescs .getBuffer (); 91 92vertexInputInfo .vertexAttributeDescriptionCount = (uint32_t )srcAttributeDescs .getCount (); 93vertexInputInfo .pVertexAttributeDescriptions = srcAttributeDescs .getBuffer (); 94 } 95 96VkPipelineInputAssemblyStateCreateInfo inputAssembly = {}; 97inputAssembly .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO ; 98// All other forms of primitive toplogies are specified via dynamic state. 99inputAssembly .topology = 100VulkanUtil ::translatePrimitiveTypeToListTopology (desc .graphics .primitiveType ); 101inputAssembly .primitiveRestartEnable = VK_FALSE ;// TODO: Currently unsupported 102 103VkViewport viewport = {}; 104viewport .x = 0.0f ; 105viewport .y = 0.0f ; 106// We are using dynamic viewport and scissor state. 107// Here we specify an arbitrary size, actual viewport will be set at `beginRenderPass` 108// time. 109viewport .width = 16.0f ; 110viewport .height = 16.0f ; 111viewport .minDepth = 0.0f ; 112viewport .maxDepth = 1.0f ; 113 114VkRect2D scissor = {}; 115scissor .offset = {0 ,0 }; 116scissor .extent = {uint32_t (16 ),uint32_t (16 )}; 117 118VkPipelineViewportStateCreateInfo viewportState = {}; 119viewportState .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO ; 120viewportState .viewportCount = 1 ; 121viewportState .pViewports = & viewport ; 122viewportState .scissorCount = 1 ; 123viewportState .pScissors = & scissor ; 124 125auto rasterizerDesc = desc .graphics .rasterizer ; 126 127VkPipelineRasterizationStateCreateInfo rasterizer = {}; 128rasterizer .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO ; 129rasterizer .depthClampEnable = 130VK_TRUE ;// TODO: Depth clipping and clamping are different between Vk and D3D12 131rasterizer .rasterizerDiscardEnable = VK_FALSE ;// TODO: Currently unsupported 132rasterizer .polygonMode = VulkanUtil ::translateFillMode (rasterizerDesc .fillMode ); 133rasterizer .cullMode = VulkanUtil ::translateCullMode (rasterizerDesc .cullMode ); 134rasterizer .frontFace = VulkanUtil ::translateFrontFaceMode (rasterizerDesc .frontFace ); 135rasterizer .depthBiasEnable = (rasterizerDesc .depthBias == 0 ) ?VK_FALSE :VK_TRUE ; 136rasterizer .depthBiasConstantFactor = (float )rasterizerDesc .depthBias ; 137rasterizer .depthBiasClamp = rasterizerDesc .depthBiasClamp ; 138rasterizer .depthBiasSlopeFactor = rasterizerDesc .slopeScaledDepthBias ; 139rasterizer .lineWidth = 1.0f ;// TODO: Currently unsupported 140 141VkPipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterInfo = {}; 142conservativeRasterInfo .sType = 143VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT ; 144conservativeRasterInfo .conservativeRasterizationMode = 145VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT ; 146if (desc .graphics .rasterizer .enableConservativeRasterization ) 147 { 148rasterizer .pNext = & conservativeRasterInfo ; 149 } 150 151auto framebufferLayoutImpl = 152static_cast < FramebufferLayoutImpl *> (desc .graphics .framebufferLayout ); 153auto forcedSampleCount = rasterizerDesc .forcedSampleCount ; 154auto blendDesc = desc .graphics .blend ; 155 156VkPipelineMultisampleStateCreateInfo multisampling = {}; 157multisampling .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO ; 158multisampling .rasterizationSamples = (forcedSampleCount == 0 ) 159 ?framebufferLayoutImpl -> m_sampleCount 160 :VulkanUtil ::translateSampleCount (forcedSampleCount ); 161multisampling .sampleShadingEnable = 162VK_FALSE ;// TODO: Should check if fragment shader needs this 163// TODO: Sample mask is dynamic in D3D12 but PSO state in Vulkan 164multisampling .alphaToCoverageEnable = blendDesc .alphaToCoverageEnable ; 165multisampling .alphaToOneEnable = VK_FALSE ; 166 167auto targetCount = GfxCount ( 168Math ::Min (framebufferLayoutImpl -> m_renderTargetCount , (uint32_t )blendDesc .targetCount )); 169List < VkPipelineColorBlendAttachmentState > colorBlendTargets ; 170 171// Regardless of whether blending is enabled, Vulkan always applies the color write mask 172// operation, so if there is no blending then we need to add an attachment that defines 173// the color write mask to ensure colors are actually written. 174if (targetCount == 0 ) 175 { 176colorBlendTargets .setCount (1 ); 177auto & vkBlendDesc = colorBlendTargets [0 ]; 178memset (& vkBlendDesc ,0 ,sizeof (vkBlendDesc )); 179vkBlendDesc .blendEnable = VK_FALSE ; 180vkBlendDesc .srcColorBlendFactor = VK_BLEND_FACTOR_ONE ; 181vkBlendDesc .dstColorBlendFactor = VK_BLEND_FACTOR_ONE ; 182vkBlendDesc .colorBlendOp = VK_BLEND_OP_ADD ; 183vkBlendDesc .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE ; 184vkBlendDesc .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE ; 185vkBlendDesc .alphaBlendOp = VK_BLEND_OP_ADD ; 186vkBlendDesc .colorWriteMask = (VkColorComponentFlags )RenderTargetWriteMask ::EnableAll ; 187 } 188else 189 { 190colorBlendTargets .setCount (targetCount ); 191for (GfxIndex i = 0 ;i < targetCount ;++ i ) 192 { 193auto & gfxBlendDesc = blendDesc .targets [i ]; 194auto & vkBlendDesc = colorBlendTargets [i ]; 195 196vkBlendDesc .blendEnable = gfxBlendDesc .enableBlend ; 197vkBlendDesc .srcColorBlendFactor = 198VulkanUtil ::translateBlendFactor (gfxBlendDesc .color .srcFactor ); 199vkBlendDesc .dstColorBlendFactor = 200VulkanUtil ::translateBlendFactor (gfxBlendDesc .color .dstFactor ); 201vkBlendDesc .colorBlendOp = VulkanUtil ::translateBlendOp (gfxBlendDesc .color .op ); 202vkBlendDesc .srcAlphaBlendFactor = 203VulkanUtil ::translateBlendFactor (gfxBlendDesc .alpha .srcFactor ); 204vkBlendDesc .dstAlphaBlendFactor = 205VulkanUtil ::translateBlendFactor (gfxBlendDesc .alpha .dstFactor ); 206vkBlendDesc .alphaBlendOp = VulkanUtil ::translateBlendOp (gfxBlendDesc .alpha .op ); 207vkBlendDesc .colorWriteMask = (VkColorComponentFlags )gfxBlendDesc .writeMask ; 208 } 209 } 210 211VkPipelineColorBlendStateCreateInfo colorBlending = {}; 212colorBlending .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO ; 213colorBlending .logicOpEnable = VK_FALSE ;// TODO: D3D12 has per attachment logic op (and 214// both have way more than one op) 215colorBlending .logicOp = VK_LOGIC_OP_COPY ; 216colorBlending .attachmentCount = (uint32_t )colorBlendTargets .getCount (); 217colorBlending .pAttachments = colorBlendTargets .getBuffer (); 218colorBlending .blendConstants [0 ]= 0.0f ; 219colorBlending .blendConstants [1 ]= 0.0f ; 220colorBlending .blendConstants [2 ]= 0.0f ; 221colorBlending .blendConstants [3 ]= 0.0f ; 222 223Array < VkDynamicState ,8 > dynamicStates ; 224dynamicStates .add (VK_DYNAMIC_STATE_VIEWPORT ); 225dynamicStates .add (VK_DYNAMIC_STATE_SCISSOR ); 226dynamicStates .add (VK_DYNAMIC_STATE_STENCIL_REFERENCE ); 227dynamicStates .add (VK_DYNAMIC_STATE_BLEND_CONSTANTS ); 228// It's not valid to specify VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT when 229// the pipeline contains a mesh shader. 230if (!m_program -> isMeshShaderProgram ()&& 231m_device -> m_api .m_extendedFeatures .extendedDynamicStateFeatures .extendedDynamicState ) 232 233 { 234dynamicStates .add (VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT ); 235 } 236VkPipelineDynamicStateCreateInfo dynamicStateInfo = {}; 237dynamicStateInfo .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO ; 238dynamicStateInfo .dynamicStateCount = (uint32_t )dynamicStates .getCount (); 239dynamicStateInfo .pDynamicStates = dynamicStates .getBuffer (); 240 241VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = {}; 242depthStencilStateInfo .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO ; 243depthStencilStateInfo .depthTestEnable = desc .graphics .depthStencil .depthTestEnable ?1 :0 ; 244depthStencilStateInfo .back = 245VulkanUtil ::translateStencilState (desc .graphics .depthStencil .backFace ); 246depthStencilStateInfo .front = 247VulkanUtil ::translateStencilState (desc .graphics .depthStencil .frontFace ); 248depthStencilStateInfo .back .compareMask = desc .graphics .depthStencil .stencilReadMask ; 249depthStencilStateInfo .back .writeMask = desc .graphics .depthStencil .stencilWriteMask ; 250depthStencilStateInfo .front .compareMask = desc .graphics .depthStencil .stencilReadMask ; 251depthStencilStateInfo .front .writeMask = desc .graphics .depthStencil .stencilWriteMask ; 252depthStencilStateInfo .depthBoundsTestEnable = 0 ;// TODO: Currently unsupported 253depthStencilStateInfo .depthCompareOp = 254VulkanUtil ::translateComparisonFunc (desc .graphics .depthStencil .depthFunc ); 255depthStencilStateInfo .depthWriteEnable = desc .graphics .depthStencil .depthWriteEnable ?1 :0 ; 256depthStencilStateInfo .stencilTestEnable = desc .graphics .depthStencil .stencilEnable ?1 :0 ; 257 258VkGraphicsPipelineCreateInfo pipelineInfo = {VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; 259 260auto programImpl = static_cast < ShaderProgramImpl *> (m_program .Ptr ()); 261if (programImpl -> m_stageCreateInfos .getCount ()== 0 ) 262 { 263SLANG_RETURN_ON_FAIL (programImpl -> compileShaders (m_device )); 264 } 265 266pipelineInfo .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ; 267pipelineInfo .stageCount = (uint32_t )programImpl -> m_stageCreateInfos .getCount (); 268pipelineInfo .pStages = programImpl -> m_stageCreateInfos .getBuffer (); 269pipelineInfo .pVertexInputState = & vertexInputInfo ; 270pipelineInfo .pInputAssemblyState = & inputAssembly ; 271pipelineInfo .pViewportState = & viewportState ; 272pipelineInfo .pRasterizationState = & rasterizer ; 273pipelineInfo .pMultisampleState = & multisampling ; 274pipelineInfo .pColorBlendState = & colorBlending ; 275pipelineInfo .pDepthStencilState = & depthStencilStateInfo ; 276pipelineInfo .layout = programImpl -> m_rootObjectLayout -> m_pipelineLayout ; 277pipelineInfo .renderPass = framebufferLayoutImpl -> m_renderPass ; 278pipelineInfo .subpass = 0 ; 279pipelineInfo .basePipelineHandle = VK_NULL_HANDLE ; 280pipelineInfo .pDynamicState = & dynamicStateInfo ; 281 282if (m_device -> m_pipelineCreationAPIDispatcher ) 283 { 284SLANG_RETURN_ON_FAIL (m_device -> m_pipelineCreationAPIDispatcher -> createGraphicsPipelineState ( 285m_device , 286programImpl -> linkedProgram .get (), 287& pipelineInfo , 288 (void ** )& m_pipeline )); 289 } 290else 291 { 292SLANG_VK_RETURN_ON_FAIL (m_device -> m_api .vkCreateGraphicsPipelines ( 293m_device -> m_device , 294pipelineCache , 2951 , 296& pipelineInfo , 297nullptr , 298& m_pipeline )); 299 } 300 301return SLANG_OK ; 302} 303 304Result PipelineStateImpl ::createVKComputePipelineState () 305{ 306auto programImpl = static_cast < ShaderProgramImpl *> (m_program .Ptr ()); 307if (programImpl -> m_stageCreateInfos .getCount ()== 0 ) 308 { 309SLANG_RETURN_ON_FAIL (programImpl -> compileShaders (m_device )); 310 } 311 312VkComputePipelineCreateInfo computePipelineInfo = { 313VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; 314computePipelineInfo .stage = programImpl -> m_stageCreateInfos [0 ]; 315computePipelineInfo .layout = programImpl -> m_rootObjectLayout -> m_pipelineLayout ; 316 317if (m_device -> m_pipelineCreationAPIDispatcher ) 318 { 319SLANG_RETURN_ON_FAIL (m_device -> m_pipelineCreationAPIDispatcher -> createComputePipelineState ( 320m_device , 321programImpl -> linkedProgram .get (), 322& computePipelineInfo , 323 (void ** )& m_pipeline )); 324 } 325else 326 { 327VkPipelineCache pipelineCache = VK_NULL_HANDLE ; 328SLANG_VK_RETURN_ON_FAIL (m_device -> m_api .vkCreateComputePipelines ( 329m_device -> m_device , 330pipelineCache , 3311 , 332& computePipelineInfo , 333nullptr , 334& m_pipeline )); 335 } 336return SLANG_OK ; 337} 338 339Result PipelineStateImpl ::ensureAPIPipelineStateCreated () 340{ 341if (m_pipeline ) 342return SLANG_OK ; 343 344switch (desc .type ) 345 { 346case PipelineType ::Compute : 347return createVKComputePipelineState (); 348case PipelineType ::Graphics : 349return createVKGraphicsPipelineState (); 350default : 351SLANG_UNREACHABLE ("Unknown pipeline type." ); 352return SLANG_FAIL ; 353 } 354} 355SLANG_NO_THROW Result SLANG_MCALL PipelineStateImpl ::getNativeHandle (InteropHandle * outHandle ) 356{ 357SLANG_RETURN_ON_FAIL (ensureAPIPipelineStateCreated ()); 358outHandle -> api = InteropHandleAPI ::Vulkan ; 359outHandle -> handleValue = 0 ; 360memcpy (& outHandle -> handleValue ,& m_pipeline ,sizeof (m_pipeline )); 361return SLANG_OK ; 362} 363 364RayTracingPipelineStateImpl ::RayTracingPipelineStateImpl (DeviceImpl * device ) 365 :PipelineStateImpl (device ) 366{ 367} 368uint32_t RayTracingPipelineStateImpl ::findEntryPointIndexByName ( 369const Dictionary < String ,Index >& entryPointNameToIndex , 370const char * name ) 371{ 372if (!name ) 373return VK_SHADER_UNUSED_KHR ; 374 375auto indexPtr = entryPointNameToIndex .tryGetValue (String (name )); 376if (indexPtr ) 377return (uint32_t )* indexPtr ; 378// TODO: Error reporting? 379return VK_SHADER_UNUSED_KHR ; 380} 381Result RayTracingPipelineStateImpl ::createVKRayTracingPipelineState () 382{ 383auto programImpl = static_cast < ShaderProgramImpl *> (m_program .Ptr ()); 384if (programImpl -> m_stageCreateInfos .getCount ()== 0 ) 385 { 386SLANG_RETURN_ON_FAIL (programImpl -> compileShaders (m_device )); 387 } 388 389VkRayTracingPipelineCreateInfoKHR raytracingPipelineInfo = { 390VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR }; 391raytracingPipelineInfo .pNext = nullptr ; 392raytracingPipelineInfo .flags = translateRayTracingPipelineFlags (desc .rayTracing .flags ); 393 394raytracingPipelineInfo .stageCount = (uint32_t )programImpl -> m_stageCreateInfos .getCount (); 395raytracingPipelineInfo .pStages = programImpl -> m_stageCreateInfos .getBuffer (); 396 397// Build Dictionary from entry point name to entry point index (stageCreateInfos index) 398// for all hit shaders - findShaderIndexByName 399Dictionary < String ,Index > entryPointNameToIndex ; 400 401List < VkRayTracingShaderGroupCreateInfoKHR > shaderGroupInfos ; 402for (uint32_t i = 0 ;i < raytracingPipelineInfo .stageCount ;++ i ) 403 { 404auto stageCreateInfo = programImpl -> m_stageCreateInfos [i ]; 405auto entryPointName = programImpl -> m_entryPointNames [i ]; 406entryPointNameToIndex .add (entryPointName ,i ); 407if (stageCreateInfo .stage & 408 (VK_SHADER_STAGE_ANY_HIT_BIT_KHR |VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | 409VK_SHADER_STAGE_INTERSECTION_BIT_KHR )) 410continue ; 411 412VkRayTracingShaderGroupCreateInfoKHR shaderGroupInfo = { 413VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR }; 414shaderGroupInfo .pNext = nullptr ; 415shaderGroupInfo .type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR ; 416shaderGroupInfo .generalShader = i ; 417shaderGroupInfo .closestHitShader = VK_SHADER_UNUSED_KHR ; 418shaderGroupInfo .anyHitShader = VK_SHADER_UNUSED_KHR ; 419shaderGroupInfo .intersectionShader = VK_SHADER_UNUSED_KHR ; 420shaderGroupInfo .pShaderGroupCaptureReplayHandle = nullptr ; 421 422// For groups with a single entry point, the group name is the entry point name. 423auto shaderGroupName = entryPointName ; 424auto shaderGroupIndex = shaderGroupInfos .getCount (); 425shaderGroupInfos .add (shaderGroupInfo ); 426shaderGroupNameToIndex .add (shaderGroupName ,shaderGroupIndex ); 427 } 428 429for (int32_t i = 0 ;i < desc .rayTracing .hitGroupDescs .getCount ();++ i ) 430 { 431VkRayTracingShaderGroupCreateInfoKHR shaderGroupInfo = { 432VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR }; 433auto & groupDesc = desc .rayTracing .hitGroupDescs [i ]; 434 435shaderGroupInfo .pNext = nullptr ; 436shaderGroupInfo .type = (groupDesc .intersectionEntryPoint ) 437 ?VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR 438 :VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR ; 439shaderGroupInfo .generalShader = VK_SHADER_UNUSED_KHR ; 440shaderGroupInfo .closestHitShader = 441findEntryPointIndexByName (entryPointNameToIndex ,groupDesc .closestHitEntryPoint ); 442shaderGroupInfo .anyHitShader = 443findEntryPointIndexByName (entryPointNameToIndex ,groupDesc .anyHitEntryPoint ); 444shaderGroupInfo .intersectionShader = 445findEntryPointIndexByName (entryPointNameToIndex ,groupDesc .intersectionEntryPoint ); 446shaderGroupInfo .pShaderGroupCaptureReplayHandle = nullptr ; 447 448auto shaderGroupIndex = shaderGroupInfos .getCount (); 449shaderGroupInfos .add (shaderGroupInfo ); 450shaderGroupNameToIndex .add (String (groupDesc .hitGroupName ),shaderGroupIndex ); 451 } 452 453raytracingPipelineInfo .groupCount = (uint32_t )shaderGroupInfos .getCount (); 454raytracingPipelineInfo .pGroups = shaderGroupInfos .getBuffer (); 455 456raytracingPipelineInfo .maxPipelineRayRecursionDepth = (uint32_t )desc .rayTracing .maxRecursion ; 457 458raytracingPipelineInfo .pLibraryInfo = nullptr ; 459raytracingPipelineInfo .pLibraryInterface = nullptr ; 460 461raytracingPipelineInfo .pDynamicState = nullptr ; 462 463raytracingPipelineInfo .layout = programImpl -> m_rootObjectLayout -> m_pipelineLayout ; 464raytracingPipelineInfo .basePipelineHandle = VK_NULL_HANDLE ; 465raytracingPipelineInfo .basePipelineIndex = 0 ; 466 467if (m_device -> m_pipelineCreationAPIDispatcher ) 468 { 469m_device -> m_pipelineCreationAPIDispatcher -> beforeCreateRayTracingState ( 470m_device , 471programImpl -> linkedProgram .get ()); 472 } 473 474VkPipelineCache pipelineCache = VK_NULL_HANDLE ; 475SLANG_VK_RETURN_ON_FAIL (m_device -> m_api .vkCreateRayTracingPipelinesKHR ( 476m_device -> m_device , 477VK_NULL_HANDLE , 478pipelineCache , 4791 , 480& raytracingPipelineInfo , 481nullptr , 482& m_pipeline )); 483shaderGroupCount = shaderGroupInfos .getCount (); 484 485if (m_device -> m_pipelineCreationAPIDispatcher ) 486 { 487m_device -> m_pipelineCreationAPIDispatcher -> afterCreateRayTracingState ( 488m_device , 489programImpl -> linkedProgram .get ()); 490 } 491return SLANG_OK ; 492} 493Result RayTracingPipelineStateImpl ::ensureAPIPipelineStateCreated () 494{ 495if (m_pipeline ) 496return SLANG_OK ; 497 498switch (desc .type ) 499 { 500case PipelineType ::RayTracing : 501return createVKRayTracingPipelineState (); 502default : 503SLANG_UNREACHABLE ("Unknown pipeline type." ); 504return SLANG_FAIL ; 505 } 506} 507Result RayTracingPipelineStateImpl ::getNativeHandle (InteropHandle * outHandle ) 508{ 509SLANG_RETURN_ON_FAIL (ensureAPIPipelineStateCreated ()); 510outHandle -> api = InteropHandleAPI ::Vulkan ; 511outHandle -> handleValue = 0 ; 512memcpy (& outHandle -> handleValue ,& m_pipeline ,sizeof (m_pipeline )); 513return SLANG_OK ; 514} 515 516}// namespace vk 517}// namespace gfx