1/* 2 * Copyright © 2019 Red Hat. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "lvp_private.h" 25#include "vk_util.h" 26#include "glsl_types.h" 27#include "spirv/nir_spirv.h" 28#include "nir/nir_builder.h" 29#include "lvp_lower_vulkan_resource.h" 30#include "pipe/p_state.h" 31#include "pipe/p_context.h" 32#include "nir/nir_xfb_info.h" 33 34#define SPIR_V_MAGIC_NUMBER 0x07230203 35 36#define LVP_PIPELINE_DUP(dst, src, type, count) do { \ 37 type *temp = ralloc_array(mem_ctx, type, count); \ 38 if (!temp) return VK_ERROR_OUT_OF_HOST_MEMORY; \ 39 memcpy(temp, (src), sizeof(type) * count); \ 40 dst = temp; \ 41 } while(0) 42 43VKAPI_ATTR void VKAPI_CALL lvp_DestroyPipeline( 44 VkDevice _device, 45 VkPipeline _pipeline, 46 const VkAllocationCallbacks* pAllocator) 47{ 48 LVP_FROM_HANDLE(lvp_device, device, _device); 49 LVP_FROM_HANDLE(lvp_pipeline, pipeline, _pipeline); 50 51 if (!_pipeline) 52 return; 53 54 if (pipeline->shader_cso[PIPE_SHADER_VERTEX]) 55 device->queue.ctx->delete_vs_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_VERTEX]); 56 if (pipeline->shader_cso[PIPE_SHADER_FRAGMENT]) 57 device->queue.ctx->delete_fs_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_FRAGMENT]); 58 if (pipeline->shader_cso[PIPE_SHADER_GEOMETRY]) 59 device->queue.ctx->delete_gs_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_GEOMETRY]); 60 if (pipeline->shader_cso[PIPE_SHADER_TESS_CTRL]) 61 device->queue.ctx->delete_tcs_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_TESS_CTRL]); 62 if (pipeline->shader_cso[PIPE_SHADER_TESS_EVAL]) 63 device->queue.ctx->delete_tes_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_TESS_EVAL]); 64 if (pipeline->shader_cso[PIPE_SHADER_COMPUTE]) 65 device->queue.ctx->delete_compute_state(device->queue.ctx, pipeline->shader_cso[PIPE_SHADER_COMPUTE]); 66 67 ralloc_free(pipeline->mem_ctx); 68 vk_object_base_finish(&pipeline->base); 69 vk_free2(&device->vk.alloc, pAllocator, pipeline); 70} 71 72static VkResult 73deep_copy_shader_stage(void *mem_ctx, 74 struct VkPipelineShaderStageCreateInfo *dst, 75 const struct VkPipelineShaderStageCreateInfo *src) 76{ 77 dst->sType = src->sType; 78 dst->pNext = NULL; 79 dst->flags = src->flags; 80 dst->stage = src->stage; 81 dst->module = src->module; 82 dst->pName = src->pName; 83 dst->pSpecializationInfo = NULL; 84 if (src->pSpecializationInfo) { 85 const VkSpecializationInfo *src_spec = src->pSpecializationInfo; 86 VkSpecializationInfo *dst_spec = ralloc_size(mem_ctx, sizeof(VkSpecializationInfo) + 87 src_spec->mapEntryCount * sizeof(VkSpecializationMapEntry) + 88 src_spec->dataSize); 89 VkSpecializationMapEntry *maps = (VkSpecializationMapEntry *)(dst_spec + 1); 90 dst_spec->pMapEntries = maps; 91 void *pdata = (void *)(dst_spec->pMapEntries + src_spec->mapEntryCount); 92 dst_spec->pData = pdata; 93 94 95 dst_spec->mapEntryCount = src_spec->mapEntryCount; 96 dst_spec->dataSize = src_spec->dataSize; 97 memcpy(pdata, src_spec->pData, src->pSpecializationInfo->dataSize); 98 memcpy(maps, src_spec->pMapEntries, src_spec->mapEntryCount * sizeof(VkSpecializationMapEntry)); 99 dst->pSpecializationInfo = dst_spec; 100 } 101 return VK_SUCCESS; 102} 103 104static VkResult 105deep_copy_vertex_input_state(void *mem_ctx, 106 struct VkPipelineVertexInputStateCreateInfo *dst, 107 const struct VkPipelineVertexInputStateCreateInfo *src) 108{ 109 dst->sType = src->sType; 110 dst->pNext = NULL; 111 dst->flags = src->flags; 112 dst->vertexBindingDescriptionCount = src->vertexBindingDescriptionCount; 113 114 LVP_PIPELINE_DUP(dst->pVertexBindingDescriptions, 115 src->pVertexBindingDescriptions, 116 VkVertexInputBindingDescription, 117 src->vertexBindingDescriptionCount); 118 119 dst->vertexAttributeDescriptionCount = src->vertexAttributeDescriptionCount; 120 121 LVP_PIPELINE_DUP(dst->pVertexAttributeDescriptions, 122 src->pVertexAttributeDescriptions, 123 VkVertexInputAttributeDescription, 124 src->vertexAttributeDescriptionCount); 125 126 if (src->pNext) { 127 vk_foreach_struct(ext, src->pNext) { 128 switch (ext->sType) { 129 case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: { 130 VkPipelineVertexInputDivisorStateCreateInfoEXT *ext_src = (VkPipelineVertexInputDivisorStateCreateInfoEXT *)ext; 131 VkPipelineVertexInputDivisorStateCreateInfoEXT *ext_dst = ralloc(mem_ctx, VkPipelineVertexInputDivisorStateCreateInfoEXT); 132 133 ext_dst->sType = ext_src->sType; 134 ext_dst->vertexBindingDivisorCount = ext_src->vertexBindingDivisorCount; 135 136 LVP_PIPELINE_DUP(ext_dst->pVertexBindingDivisors, 137 ext_src->pVertexBindingDivisors, 138 VkVertexInputBindingDivisorDescriptionEXT, 139 ext_src->vertexBindingDivisorCount); 140 141 dst->pNext = ext_dst; 142 break; 143 } 144 default: 145 break; 146 } 147 } 148 } 149 return VK_SUCCESS; 150} 151 152static bool 153dynamic_state_contains(const VkPipelineDynamicStateCreateInfo *src, VkDynamicState state) 154{ 155 if (!src) 156 return false; 157 158 for (unsigned i = 0; i < src->dynamicStateCount; i++) 159 if (src->pDynamicStates[i] == state) 160 return true; 161 return false; 162} 163 164static VkResult 165deep_copy_viewport_state(void *mem_ctx, 166 const VkPipelineDynamicStateCreateInfo *dyn_state, 167 VkPipelineViewportStateCreateInfo *dst, 168 const VkPipelineViewportStateCreateInfo *src) 169{ 170 dst->sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 171 dst->pNext = NULL; 172 dst->pViewports = NULL; 173 dst->pScissors = NULL; 174 175 if (!dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_VIEWPORT) && 176 !dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT)) { 177 LVP_PIPELINE_DUP(dst->pViewports, 178 src->pViewports, 179 VkViewport, 180 src->viewportCount); 181 } 182 if (!dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT)) 183 dst->viewportCount = src->viewportCount; 184 else 185 dst->viewportCount = 0; 186 187 if (!dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_SCISSOR) && 188 !dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT)) { 189 if (src->pScissors) 190 LVP_PIPELINE_DUP(dst->pScissors, 191 src->pScissors, 192 VkRect2D, 193 src->scissorCount); 194 } 195 if (!dynamic_state_contains(dyn_state, VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT)) 196 dst->scissorCount = src->scissorCount; 197 else 198 dst->scissorCount = 0; 199 200 return VK_SUCCESS; 201} 202 203static VkResult 204deep_copy_color_blend_state(void *mem_ctx, 205 VkPipelineColorBlendStateCreateInfo *dst, 206 const VkPipelineColorBlendStateCreateInfo *src) 207{ 208 dst->sType = src->sType; 209 dst->pNext = NULL; 210 dst->flags = src->flags; 211 dst->logicOpEnable = src->logicOpEnable; 212 dst->logicOp = src->logicOp; 213 214 LVP_PIPELINE_DUP(dst->pAttachments, 215 src->pAttachments, 216 VkPipelineColorBlendAttachmentState, 217 src->attachmentCount); 218 dst->attachmentCount = src->attachmentCount; 219 220 memcpy(&dst->blendConstants, &src->blendConstants, sizeof(float) * 4); 221 222 return VK_SUCCESS; 223} 224 225static VkResult 226deep_copy_dynamic_state(void *mem_ctx, 227 VkPipelineDynamicStateCreateInfo *dst, 228 const VkPipelineDynamicStateCreateInfo *src) 229{ 230 dst->sType = src->sType; 231 dst->pNext = NULL; 232 dst->flags = src->flags; 233 234 LVP_PIPELINE_DUP(dst->pDynamicStates, 235 src->pDynamicStates, 236 VkDynamicState, 237 src->dynamicStateCount); 238 dst->dynamicStateCount = src->dynamicStateCount; 239 return VK_SUCCESS; 240} 241 242 243static VkResult 244deep_copy_rasterization_state(void *mem_ctx, 245 VkPipelineRasterizationStateCreateInfo *dst, 246 const VkPipelineRasterizationStateCreateInfo *src) 247{ 248 memcpy(dst, src, sizeof(VkPipelineRasterizationStateCreateInfo)); 249 dst->pNext = NULL; 250 251 if (src->pNext) { 252 vk_foreach_struct(ext, src->pNext) { 253 switch (ext->sType) { 254 case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT: { 255 VkPipelineRasterizationDepthClipStateCreateInfoEXT *ext_src = (VkPipelineRasterizationDepthClipStateCreateInfoEXT *)ext; 256 VkPipelineRasterizationDepthClipStateCreateInfoEXT *ext_dst = ralloc(mem_ctx, VkPipelineRasterizationDepthClipStateCreateInfoEXT); 257 ext_dst->sType = ext_src->sType; 258 ext_dst->flags = ext_src->flags; 259 ext_dst->depthClipEnable = ext_src->depthClipEnable; 260 dst->pNext = ext_dst; 261 break; 262 } 263 default: 264 break; 265 } 266 } 267 } 268 return VK_SUCCESS; 269} 270 271static VkResult 272deep_copy_graphics_create_info(void *mem_ctx, 273 VkGraphicsPipelineCreateInfo *dst, 274 const VkGraphicsPipelineCreateInfo *src) 275{ 276 int i; 277 VkResult result; 278 VkPipelineShaderStageCreateInfo *stages; 279 VkPipelineVertexInputStateCreateInfo *vertex_input; 280 VkPipelineRasterizationStateCreateInfo *rasterization_state; 281 LVP_FROM_HANDLE(lvp_render_pass, pass, src->renderPass); 282 283 dst->sType = src->sType; 284 dst->pNext = NULL; 285 dst->flags = src->flags; 286 dst->layout = src->layout; 287 dst->renderPass = src->renderPass; 288 dst->subpass = src->subpass; 289 dst->basePipelineHandle = src->basePipelineHandle; 290 dst->basePipelineIndex = src->basePipelineIndex; 291 292 /* pStages */ 293 VkShaderStageFlags stages_present = 0; 294 dst->stageCount = src->stageCount; 295 stages = ralloc_array(mem_ctx, VkPipelineShaderStageCreateInfo, dst->stageCount); 296 for (i = 0 ; i < dst->stageCount; i++) { 297 result = deep_copy_shader_stage(mem_ctx, &stages[i], &src->pStages[i]); 298 if (result != VK_SUCCESS) 299 return result; 300 stages_present |= src->pStages[i].stage; 301 } 302 dst->pStages = stages; 303 304 /* pVertexInputState */ 305 if (!dynamic_state_contains(src->pDynamicState, VK_DYNAMIC_STATE_VERTEX_INPUT_EXT)) { 306 vertex_input = ralloc(mem_ctx, VkPipelineVertexInputStateCreateInfo); 307 result = deep_copy_vertex_input_state(mem_ctx, vertex_input, 308 src->pVertexInputState); 309 if (result != VK_SUCCESS) 310 return result; 311 dst->pVertexInputState = vertex_input; 312 } else 313 dst->pVertexInputState = NULL; 314 315 /* pInputAssemblyState */ 316 LVP_PIPELINE_DUP(dst->pInputAssemblyState, 317 src->pInputAssemblyState, 318 VkPipelineInputAssemblyStateCreateInfo, 319 1); 320 321 /* pTessellationState */ 322 if (src->pTessellationState && 323 (stages_present & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) == 324 (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 325 LVP_PIPELINE_DUP(dst->pTessellationState, 326 src->pTessellationState, 327 VkPipelineTessellationStateCreateInfo, 328 1); 329 } 330 331 /* pViewportState */ 332 bool rasterization_disabled = !dynamic_state_contains(src->pDynamicState, VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT) && 333 src->pRasterizationState->rasterizerDiscardEnable; 334 if (src->pViewportState && !rasterization_disabled) { 335 VkPipelineViewportStateCreateInfo *viewport_state; 336 viewport_state = ralloc(mem_ctx, VkPipelineViewportStateCreateInfo); 337 if (!viewport_state) 338 return VK_ERROR_OUT_OF_HOST_MEMORY; 339 deep_copy_viewport_state(mem_ctx, src->pDynamicState, 340 viewport_state, src->pViewportState); 341 dst->pViewportState = viewport_state; 342 } else 343 dst->pViewportState = NULL; 344 345 /* pRasterizationState */ 346 rasterization_state = ralloc(mem_ctx, VkPipelineRasterizationStateCreateInfo); 347 if (!rasterization_state) 348 return VK_ERROR_OUT_OF_HOST_MEMORY; 349 deep_copy_rasterization_state(mem_ctx, rasterization_state, src->pRasterizationState); 350 dst->pRasterizationState = rasterization_state; 351 352 /* pMultisampleState */ 353 if (src->pMultisampleState && !rasterization_disabled) { 354 VkPipelineMultisampleStateCreateInfo* ms_state; 355 ms_state = ralloc_size(mem_ctx, sizeof(VkPipelineMultisampleStateCreateInfo) + sizeof(VkSampleMask)); 356 if (!ms_state) 357 return VK_ERROR_OUT_OF_HOST_MEMORY; 358 /* does samplemask need deep copy? */ 359 memcpy(ms_state, src->pMultisampleState, sizeof(VkPipelineMultisampleStateCreateInfo)); 360 if (src->pMultisampleState->pSampleMask) { 361 VkSampleMask *sample_mask = (VkSampleMask *)(ms_state + 1); 362 sample_mask[0] = src->pMultisampleState->pSampleMask[0]; 363 ms_state->pSampleMask = sample_mask; 364 } 365 dst->pMultisampleState = ms_state; 366 } else 367 dst->pMultisampleState = NULL; 368 369 /* pDepthStencilState */ 370 if (src->pDepthStencilState && !rasterization_disabled && pass->has_zs_attachment) { 371 LVP_PIPELINE_DUP(dst->pDepthStencilState, 372 src->pDepthStencilState, 373 VkPipelineDepthStencilStateCreateInfo, 374 1); 375 } else 376 dst->pDepthStencilState = NULL; 377 378 /* pColorBlendState */ 379 if (src->pColorBlendState && !rasterization_disabled && pass->has_color_attachment) { 380 VkPipelineColorBlendStateCreateInfo* cb_state; 381 382 cb_state = ralloc(mem_ctx, VkPipelineColorBlendStateCreateInfo); 383 if (!cb_state) 384 return VK_ERROR_OUT_OF_HOST_MEMORY; 385 deep_copy_color_blend_state(mem_ctx, cb_state, src->pColorBlendState); 386 dst->pColorBlendState = cb_state; 387 } else 388 dst->pColorBlendState = NULL; 389 390 if (src->pDynamicState) { 391 VkPipelineDynamicStateCreateInfo* dyn_state; 392 393 /* pDynamicState */ 394 dyn_state = ralloc(mem_ctx, VkPipelineDynamicStateCreateInfo); 395 if (!dyn_state) 396 return VK_ERROR_OUT_OF_HOST_MEMORY; 397 deep_copy_dynamic_state(mem_ctx, dyn_state, src->pDynamicState); 398 dst->pDynamicState = dyn_state; 399 } else 400 dst->pDynamicState = NULL; 401 402 return VK_SUCCESS; 403} 404 405static VkResult 406deep_copy_compute_create_info(void *mem_ctx, 407 VkComputePipelineCreateInfo *dst, 408 const VkComputePipelineCreateInfo *src) 409{ 410 VkResult result; 411 dst->sType = src->sType; 412 dst->pNext = NULL; 413 dst->flags = src->flags; 414 dst->layout = src->layout; 415 dst->basePipelineHandle = src->basePipelineHandle; 416 dst->basePipelineIndex = src->basePipelineIndex; 417 418 result = deep_copy_shader_stage(mem_ctx, &dst->stage, &src->stage); 419 if (result != VK_SUCCESS) 420 return result; 421 return VK_SUCCESS; 422} 423 424static inline unsigned 425st_shader_stage_to_ptarget(gl_shader_stage stage) 426{ 427 switch (stage) { 428 case MESA_SHADER_VERTEX: 429 return PIPE_SHADER_VERTEX; 430 case MESA_SHADER_FRAGMENT: 431 return PIPE_SHADER_FRAGMENT; 432 case MESA_SHADER_GEOMETRY: 433 return PIPE_SHADER_GEOMETRY; 434 case MESA_SHADER_TESS_CTRL: 435 return PIPE_SHADER_TESS_CTRL; 436 case MESA_SHADER_TESS_EVAL: 437 return PIPE_SHADER_TESS_EVAL; 438 case MESA_SHADER_COMPUTE: 439 return PIPE_SHADER_COMPUTE; 440 default: 441 break; 442 } 443 444 assert(!"should not be reached"); 445 return PIPE_SHADER_VERTEX; 446} 447 448static void 449shared_var_info(const struct glsl_type *type, unsigned *size, unsigned *align) 450{ 451 assert(glsl_type_is_vector_or_scalar(type)); 452 453 uint32_t comp_size = glsl_type_is_boolean(type) 454 ? 4 : glsl_get_bit_size(type) / 8; 455 unsigned length = glsl_get_vector_elements(type); 456 *size = comp_size * length, 457 *align = comp_size; 458} 459 460static void 461lvp_shader_compile_to_ir(struct lvp_pipeline *pipeline, 462 struct vk_shader_module *module, 463 const char *entrypoint_name, 464 gl_shader_stage stage, 465 const VkSpecializationInfo *spec_info) 466{ 467 nir_shader *nir; 468 const nir_shader_compiler_options *drv_options = pipeline->device->pscreen->get_compiler_options(pipeline->device->pscreen, PIPE_SHADER_IR_NIR, st_shader_stage_to_ptarget(stage)); 469 bool progress; 470 uint32_t *spirv = (uint32_t *) module->data; 471 assert(spirv[0] == SPIR_V_MAGIC_NUMBER); 472 assert(module->size % 4 == 0); 473 474 uint32_t num_spec_entries = 0; 475 struct nir_spirv_specialization *spec_entries = 476 vk_spec_info_to_nir_spirv(spec_info, &num_spec_entries); 477 478 struct lvp_device *pdevice = pipeline->device; 479 const struct spirv_to_nir_options spirv_options = { 480 .environment = NIR_SPIRV_VULKAN, 481 .caps = { 482 .float64 = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DOUBLES) == 1), 483 .int16 = true, 484 .int64 = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_INT64) == 1), 485 .tessellation = true, 486 .float_controls = true, 487 .image_ms_array = true, 488 .image_read_without_format = true, 489 .image_write_without_format = true, 490 .storage_image_ms = true, 491 .geometry_streams = true, 492 .storage_8bit = true, 493 .storage_16bit = true, 494 .variable_pointers = true, 495 .stencil_export = true, 496 .post_depth_coverage = true, 497 .transform_feedback = true, 498 .device_group = true, 499 .draw_parameters = true, 500 .shader_viewport_index_layer = true, 501 .multiview = true, 502 .physical_storage_buffer_address = true, 503 .int64_atomics = true, 504 .subgroup_arithmetic = true, 505 .subgroup_basic = true, 506 .subgroup_ballot = true, 507 .subgroup_quad = true, 508 .subgroup_vote = true, 509 .int8 = true, 510 .float16 = true, 511 }, 512 .ubo_addr_format = nir_address_format_32bit_index_offset, 513 .ssbo_addr_format = nir_address_format_32bit_index_offset, 514 .phys_ssbo_addr_format = nir_address_format_64bit_global, 515 .push_const_addr_format = nir_address_format_logical, 516 .shared_addr_format = nir_address_format_32bit_offset, 517 }; 518 519 nir = spirv_to_nir(spirv, module->size / 4, 520 spec_entries, num_spec_entries, 521 stage, entrypoint_name, &spirv_options, drv_options); 522 523 if (!nir) { 524 free(spec_entries); 525 return; 526 } 527 nir_validate_shader(nir, NULL); 528 529 free(spec_entries); 530 531 const struct nir_lower_sysvals_to_varyings_options sysvals_to_varyings = { 532 .frag_coord = true, 533 .point_coord = true, 534 }; 535 NIR_PASS_V(nir, nir_lower_sysvals_to_varyings, &sysvals_to_varyings); 536 537 NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp); 538 NIR_PASS_V(nir, nir_lower_returns); 539 NIR_PASS_V(nir, nir_inline_functions); 540 NIR_PASS_V(nir, nir_copy_prop); 541 NIR_PASS_V(nir, nir_opt_deref); 542 543 /* Pick off the single entrypoint that we want */ 544 foreach_list_typed_safe(nir_function, func, node, &nir->functions) { 545 if (!func->is_entrypoint) 546 exec_node_remove(&func->node); 547 } 548 assert(exec_list_length(&nir->functions) == 1); 549 550 NIR_PASS_V(nir, nir_lower_variable_initializers, ~0); 551 NIR_PASS_V(nir, nir_split_var_copies); 552 NIR_PASS_V(nir, nir_split_per_member_structs); 553 554 NIR_PASS_V(nir, nir_remove_dead_variables, 555 nir_var_shader_in | nir_var_shader_out | nir_var_system_value, NULL); 556 557 if (stage == MESA_SHADER_FRAGMENT) 558 lvp_lower_input_attachments(nir, false); 559 NIR_PASS_V(nir, nir_lower_system_values); 560 NIR_PASS_V(nir, nir_lower_compute_system_values, NULL); 561 562 NIR_PASS_V(nir, nir_lower_clip_cull_distance_arrays); 563 NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_uniform, NULL); 564 565 lvp_lower_pipeline_layout(pipeline->device, pipeline->layout, nir); 566 567 NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir), true, true); 568 NIR_PASS_V(nir, nir_split_var_copies); 569 NIR_PASS_V(nir, nir_lower_global_vars_to_local); 570 571 NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_push_const, 572 nir_address_format_32bit_offset); 573 574 NIR_PASS_V(nir, nir_lower_explicit_io, 575 nir_var_mem_ubo | nir_var_mem_ssbo, 576 nir_address_format_32bit_index_offset); 577 578 NIR_PASS_V(nir, nir_lower_explicit_io, 579 nir_var_mem_global, 580 nir_address_format_64bit_global); 581 582 if (nir->info.stage == MESA_SHADER_COMPUTE) { 583 NIR_PASS_V(nir, nir_lower_vars_to_explicit_types, nir_var_mem_shared, shared_var_info); 584 NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_shared, nir_address_format_32bit_offset); 585 } 586 587 NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL); 588 589 if (nir->info.stage == MESA_SHADER_VERTEX || 590 nir->info.stage == MESA_SHADER_GEOMETRY) { 591 NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false); 592 } else if (nir->info.stage == MESA_SHADER_FRAGMENT) { 593 NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, true); 594 } 595 596 do { 597 progress = false; 598 599 NIR_PASS(progress, nir, nir_lower_flrp, 32|64, true); 600 NIR_PASS(progress, nir, nir_split_array_vars, nir_var_function_temp); 601 NIR_PASS(progress, nir, nir_shrink_vec_array_vars, nir_var_function_temp); 602 NIR_PASS(progress, nir, nir_opt_deref); 603 NIR_PASS(progress, nir, nir_lower_vars_to_ssa); 604 605 NIR_PASS(progress, nir, nir_copy_prop); 606 NIR_PASS(progress, nir, nir_opt_dce); 607 NIR_PASS(progress, nir, nir_opt_peephole_select, 8, true, true); 608 609 NIR_PASS(progress, nir, nir_opt_algebraic); 610 NIR_PASS(progress, nir, nir_opt_constant_folding); 611 612 NIR_PASS(progress, nir, nir_opt_remove_phis); 613 bool trivial_continues = false; 614 NIR_PASS(trivial_continues, nir, nir_opt_trivial_continues); 615 progress |= trivial_continues; 616 if (trivial_continues) { 617 /* If nir_opt_trivial_continues makes progress, then we need to clean 618 * things up if we want any hope of nir_opt_if or nir_opt_loop_unroll 619 * to make progress. 620 */ 621 NIR_PASS(progress, nir, nir_copy_prop); 622 NIR_PASS(progress, nir, nir_opt_dce); 623 NIR_PASS(progress, nir, nir_opt_remove_phis); 624 } 625 NIR_PASS(progress, nir, nir_opt_if, true); 626 NIR_PASS(progress, nir, nir_opt_dead_cf); 627 NIR_PASS(progress, nir, nir_opt_conditional_discard); 628 NIR_PASS(progress, nir, nir_opt_remove_phis); 629 NIR_PASS(progress, nir, nir_opt_cse); 630 NIR_PASS(progress, nir, nir_opt_undef); 631 632 NIR_PASS(progress, nir, nir_opt_deref); 633 NIR_PASS(progress, nir, nir_lower_alu_to_scalar, NULL, NULL); 634 } while (progress); 635 636 NIR_PASS_V(nir, nir_lower_var_copies); 637 NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL); 638 NIR_PASS_V(nir, nir_opt_dce); 639 nir_sweep(nir); 640 641 nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir)); 642 643 if (nir->info.stage != MESA_SHADER_VERTEX) 644 nir_assign_io_var_locations(nir, nir_var_shader_in, &nir->num_inputs, nir->info.stage); 645 else { 646 nir->num_inputs = util_last_bit64(nir->info.inputs_read); 647 nir_foreach_shader_in_variable(var, nir) { 648 var->data.driver_location = var->data.location - VERT_ATTRIB_GENERIC0; 649 } 650 } 651 nir_assign_io_var_locations(nir, nir_var_shader_out, &nir->num_outputs, 652 nir->info.stage); 653 pipeline->pipeline_nir[stage] = nir; 654} 655 656static void fill_shader_prog(struct pipe_shader_state *state, gl_shader_stage stage, struct lvp_pipeline *pipeline) 657{ 658 state->type = PIPE_SHADER_IR_NIR; 659 state->ir.nir = pipeline->pipeline_nir[stage]; 660} 661 662static void 663merge_tess_info(struct shader_info *tes_info, 664 const struct shader_info *tcs_info) 665{ 666 /* The Vulkan 1.0.38 spec, section 21.1 Tessellator says: 667 * 668 * "PointMode. Controls generation of points rather than triangles 669 * or lines. This functionality defaults to disabled, and is 670 * enabled if either shader stage includes the execution mode. 671 * 672 * and about Triangles, Quads, IsoLines, VertexOrderCw, VertexOrderCcw, 673 * PointMode, SpacingEqual, SpacingFractionalEven, SpacingFractionalOdd, 674 * and OutputVertices, it says: 675 * 676 * "One mode must be set in at least one of the tessellation 677 * shader stages." 678 * 679 * So, the fields can be set in either the TCS or TES, but they must 680 * agree if set in both. Our backend looks at TES, so bitwise-or in 681 * the values from the TCS. 682 */ 683 assert(tcs_info->tess.tcs_vertices_out == 0 || 684 tes_info->tess.tcs_vertices_out == 0 || 685 tcs_info->tess.tcs_vertices_out == tes_info->tess.tcs_vertices_out); 686 tes_info->tess.tcs_vertices_out |= tcs_info->tess.tcs_vertices_out; 687 688 assert(tcs_info->tess.spacing == TESS_SPACING_UNSPECIFIED || 689 tes_info->tess.spacing == TESS_SPACING_UNSPECIFIED || 690 tcs_info->tess.spacing == tes_info->tess.spacing); 691 tes_info->tess.spacing |= tcs_info->tess.spacing; 692 693 assert(tcs_info->tess.primitive_mode == 0 || 694 tes_info->tess.primitive_mode == 0 || 695 tcs_info->tess.primitive_mode == tes_info->tess.primitive_mode); 696 tes_info->tess.primitive_mode |= tcs_info->tess.primitive_mode; 697 tes_info->tess.ccw |= tcs_info->tess.ccw; 698 tes_info->tess.point_mode |= tcs_info->tess.point_mode; 699} 700 701static gl_shader_stage 702lvp_shader_stage(VkShaderStageFlagBits stage) 703{ 704 switch (stage) { 705 case VK_SHADER_STAGE_VERTEX_BIT: 706 return MESA_SHADER_VERTEX; 707 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: 708 return MESA_SHADER_TESS_CTRL; 709 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: 710 return MESA_SHADER_TESS_EVAL; 711 case VK_SHADER_STAGE_GEOMETRY_BIT: 712 return MESA_SHADER_GEOMETRY; 713 case VK_SHADER_STAGE_FRAGMENT_BIT: 714 return MESA_SHADER_FRAGMENT; 715 case VK_SHADER_STAGE_COMPUTE_BIT: 716 return MESA_SHADER_COMPUTE; 717 default: 718 unreachable("invalid VkShaderStageFlagBits"); 719 return MESA_SHADER_NONE; 720 } 721} 722 723static VkResult 724lvp_pipeline_compile(struct lvp_pipeline *pipeline, 725 gl_shader_stage stage) 726{ 727 struct lvp_device *device = pipeline->device; 728 device->physical_device->pscreen->finalize_nir(device->physical_device->pscreen, pipeline->pipeline_nir[stage]); 729 if (stage == MESA_SHADER_COMPUTE) { 730 struct pipe_compute_state shstate = {0}; 731 shstate.prog = (void *)pipeline->pipeline_nir[MESA_SHADER_COMPUTE]; 732 shstate.ir_type = PIPE_SHADER_IR_NIR; 733 shstate.req_local_mem = pipeline->pipeline_nir[MESA_SHADER_COMPUTE]->info.shared_size; 734 pipeline->shader_cso[PIPE_SHADER_COMPUTE] = device->queue.ctx->create_compute_state(device->queue.ctx, &shstate); 735 } else { 736 struct pipe_shader_state shstate = {0}; 737 fill_shader_prog(&shstate, stage, pipeline); 738 739 if (stage == MESA_SHADER_VERTEX || 740 stage == MESA_SHADER_GEOMETRY || 741 stage == MESA_SHADER_TESS_EVAL) { 742 nir_xfb_info *xfb_info = nir_gather_xfb_info(pipeline->pipeline_nir[stage], NULL); 743 if (xfb_info) { 744 uint8_t output_mapping[VARYING_SLOT_TESS_MAX]; 745 memset(output_mapping, 0, sizeof(output_mapping)); 746 747 nir_foreach_shader_out_variable(var, pipeline->pipeline_nir[stage]) { 748 unsigned slots = var->data.compact ? DIV_ROUND_UP(glsl_get_length(var->type), 4) 749 : glsl_count_attribute_slots(var->type, false); 750 for (unsigned i = 0; i < slots; i++) 751 output_mapping[var->data.location + i] = var->data.driver_location + i; 752 } 753 754 shstate.stream_output.num_outputs = xfb_info->output_count; 755 for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { 756 if (xfb_info->buffers_written & (1 << i)) { 757 shstate.stream_output.stride[i] = xfb_info->buffers[i].stride / 4; 758 } 759 } 760 for (unsigned i = 0; i < xfb_info->output_count; i++) { 761 shstate.stream_output.output[i].output_buffer = xfb_info->outputs[i].buffer; 762 shstate.stream_output.output[i].dst_offset = xfb_info->outputs[i].offset / 4; 763 shstate.stream_output.output[i].register_index = output_mapping[xfb_info->outputs[i].location]; 764 shstate.stream_output.output[i].num_components = util_bitcount(xfb_info->outputs[i].component_mask); 765 shstate.stream_output.output[i].start_component = ffs(xfb_info->outputs[i].component_mask) - 1; 766 shstate.stream_output.output[i].stream = xfb_info->buffer_to_stream[xfb_info->outputs[i].buffer]; 767 } 768 769 ralloc_free(xfb_info); 770 } 771 } 772 773 switch (stage) { 774 case MESA_SHADER_FRAGMENT: 775 pipeline->shader_cso[PIPE_SHADER_FRAGMENT] = device->queue.ctx->create_fs_state(device->queue.ctx, &shstate); 776 break; 777 case MESA_SHADER_VERTEX: 778 pipeline->shader_cso[PIPE_SHADER_VERTEX] = device->queue.ctx->create_vs_state(device->queue.ctx, &shstate); 779 break; 780 case MESA_SHADER_GEOMETRY: 781 pipeline->shader_cso[PIPE_SHADER_GEOMETRY] = device->queue.ctx->create_gs_state(device->queue.ctx, &shstate); 782 break; 783 case MESA_SHADER_TESS_CTRL: 784 pipeline->shader_cso[PIPE_SHADER_TESS_CTRL] = device->queue.ctx->create_tcs_state(device->queue.ctx, &shstate); 785 break; 786 case MESA_SHADER_TESS_EVAL: 787 pipeline->shader_cso[PIPE_SHADER_TESS_EVAL] = device->queue.ctx->create_tes_state(device->queue.ctx, &shstate); 788 break; 789 default: 790 unreachable("illegal shader"); 791 break; 792 } 793 } 794 return VK_SUCCESS; 795} 796 797static VkResult 798lvp_graphics_pipeline_init(struct lvp_pipeline *pipeline, 799 struct lvp_device *device, 800 struct lvp_pipeline_cache *cache, 801 const VkGraphicsPipelineCreateInfo *pCreateInfo, 802 const VkAllocationCallbacks *alloc) 803{ 804 if (alloc == NULL) 805 alloc = &device->vk.alloc; 806 pipeline->device = device; 807 pipeline->layout = lvp_pipeline_layout_from_handle(pCreateInfo->layout); 808 pipeline->force_min_sample = false; 809 810 pipeline->mem_ctx = ralloc_context(NULL); 811 /* recreate createinfo */ 812 deep_copy_graphics_create_info(pipeline->mem_ctx, &pipeline->graphics_create_info, pCreateInfo); 813 pipeline->is_compute_pipeline = false; 814 815 const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *pv_state = 816 vk_find_struct_const(pCreateInfo->pRasterizationState, 817 PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT); 818 pipeline->provoking_vertex_last = pv_state && pv_state->provokingVertexMode == VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT; 819 820 const VkPipelineRasterizationLineStateCreateInfoEXT *line_state = 821 vk_find_struct_const(pCreateInfo->pRasterizationState, 822 PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT); 823 if (line_state) { 824 /* always draw bresenham if !smooth */ 825 pipeline->line_stipple_enable = line_state->stippledLineEnable; 826 pipeline->line_smooth = line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT; 827 pipeline->disable_multisample = line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT || 828 line_state->lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT; 829 pipeline->line_rectangular = line_state->lineRasterizationMode != VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT; 830 if (pipeline->line_stipple_enable) { 831 if (!dynamic_state_contains(pipeline->graphics_create_info.pDynamicState, VK_DYNAMIC_STATE_LINE_STIPPLE_EXT)) { 832 pipeline->line_stipple_factor = line_state->lineStippleFactor - 1; 833 pipeline->line_stipple_pattern = line_state->lineStipplePattern; 834 } else { 835 pipeline->line_stipple_factor = 0; 836 pipeline->line_stipple_pattern = UINT16_MAX; 837 } 838 } 839 } else 840 pipeline->line_rectangular = true; 841 842 bool rasterization_disabled = !dynamic_state_contains(pipeline->graphics_create_info.pDynamicState, VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT) && 843 pipeline->graphics_create_info.pRasterizationState->rasterizerDiscardEnable; 844 LVP_FROM_HANDLE(lvp_render_pass, pass, pipeline->graphics_create_info.renderPass); 845 if (!dynamic_state_contains(pipeline->graphics_create_info.pDynamicState, VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT) && 846 !rasterization_disabled && pass->has_color_attachment) { 847 const VkPipelineColorWriteCreateInfoEXT *cw_state = 848 vk_find_struct_const(pCreateInfo->pColorBlendState, PIPELINE_COLOR_WRITE_CREATE_INFO_EXT); 849 if (cw_state) { 850 for (unsigned i = 0; i < cw_state->attachmentCount; i++) 851 if (!cw_state->pColorWriteEnables[i]) { 852 VkPipelineColorBlendAttachmentState *att = (void*)&pipeline->graphics_create_info.pColorBlendState->pAttachments[i]; 853 att->colorWriteMask = 0; 854 } 855 } 856 } 857 858 859 for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 860 VK_FROM_HANDLE(vk_shader_module, module, 861 pCreateInfo->pStages[i].module); 862 gl_shader_stage stage = lvp_shader_stage(pCreateInfo->pStages[i].stage); 863 lvp_shader_compile_to_ir(pipeline, module, 864 pCreateInfo->pStages[i].pName, 865 stage, 866 pCreateInfo->pStages[i].pSpecializationInfo); 867 if (!pipeline->pipeline_nir[stage]) 868 return VK_ERROR_FEATURE_NOT_PRESENT; 869 } 870 871 if (pipeline->pipeline_nir[MESA_SHADER_FRAGMENT]) { 872 if (pipeline->pipeline_nir[MESA_SHADER_FRAGMENT]->info.fs.uses_sample_qualifier || 873 BITSET_TEST(pipeline->pipeline_nir[MESA_SHADER_FRAGMENT]->info.system_values_read, SYSTEM_VALUE_SAMPLE_ID) || 874 BITSET_TEST(pipeline->pipeline_nir[MESA_SHADER_FRAGMENT]->info.system_values_read, SYSTEM_VALUE_SAMPLE_POS)) 875 pipeline->force_min_sample = true; 876 } 877 if (pipeline->pipeline_nir[MESA_SHADER_TESS_CTRL]) { 878 nir_lower_patch_vertices(pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL], pipeline->pipeline_nir[MESA_SHADER_TESS_CTRL]->info.tess.tcs_vertices_out, NULL); 879 merge_tess_info(&pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info, &pipeline->pipeline_nir[MESA_SHADER_TESS_CTRL]->info); 880 const VkPipelineTessellationDomainOriginStateCreateInfo *domain_origin_state = 881 vk_find_struct_const(pCreateInfo->pTessellationState, 882 PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO); 883 if (!domain_origin_state || domain_origin_state->domainOrigin == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT) 884 pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info.tess.ccw = !pipeline->pipeline_nir[MESA_SHADER_TESS_EVAL]->info.tess.ccw; 885 } 886 887 pipeline->gs_output_lines = pipeline->pipeline_nir[MESA_SHADER_GEOMETRY] && 888 pipeline->pipeline_nir[MESA_SHADER_GEOMETRY]->info.gs.output_primitive == GL_LINES; 889 890 891 bool has_fragment_shader = false; 892 for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 893 gl_shader_stage stage = lvp_shader_stage(pCreateInfo->pStages[i].stage); 894 lvp_pipeline_compile(pipeline, stage); 895 if (stage == MESA_SHADER_FRAGMENT) 896 has_fragment_shader = true; 897 } 898 899 if (has_fragment_shader == false) { 900 /* create a dummy fragment shader for this pipeline. */ 901 nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, NULL, 902 "dummy_frag"); 903 904 pipeline->pipeline_nir[MESA_SHADER_FRAGMENT] = b.shader; 905 struct pipe_shader_state shstate = {0}; 906 shstate.type = PIPE_SHADER_IR_NIR; 907 shstate.ir.nir = pipeline->pipeline_nir[MESA_SHADER_FRAGMENT]; 908 pipeline->shader_cso[PIPE_SHADER_FRAGMENT] = device->queue.ctx->create_fs_state(device->queue.ctx, &shstate); 909 } 910 return VK_SUCCESS; 911} 912 913static VkResult 914lvp_graphics_pipeline_create( 915 VkDevice _device, 916 VkPipelineCache _cache, 917 const VkGraphicsPipelineCreateInfo *pCreateInfo, 918 const VkAllocationCallbacks *pAllocator, 919 VkPipeline *pPipeline) 920{ 921 LVP_FROM_HANDLE(lvp_device, device, _device); 922 LVP_FROM_HANDLE(lvp_pipeline_cache, cache, _cache); 923 struct lvp_pipeline *pipeline; 924 VkResult result; 925 926 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO); 927 928 pipeline = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8, 929 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 930 if (pipeline == NULL) 931 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 932 933 vk_object_base_init(&device->vk, &pipeline->base, 934 VK_OBJECT_TYPE_PIPELINE); 935 result = lvp_graphics_pipeline_init(pipeline, device, cache, pCreateInfo, 936 pAllocator); 937 if (result != VK_SUCCESS) { 938 vk_free2(&device->vk.alloc, pAllocator, pipeline); 939 return result; 940 } 941 942 *pPipeline = lvp_pipeline_to_handle(pipeline); 943 944 return VK_SUCCESS; 945} 946 947VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateGraphicsPipelines( 948 VkDevice _device, 949 VkPipelineCache pipelineCache, 950 uint32_t count, 951 const VkGraphicsPipelineCreateInfo* pCreateInfos, 952 const VkAllocationCallbacks* pAllocator, 953 VkPipeline* pPipelines) 954{ 955 VkResult result = VK_SUCCESS; 956 unsigned i = 0; 957 958 for (; i < count; i++) { 959 VkResult r; 960 r = lvp_graphics_pipeline_create(_device, 961 pipelineCache, 962 &pCreateInfos[i], 963 pAllocator, &pPipelines[i]); 964 if (r != VK_SUCCESS) { 965 result = r; 966 pPipelines[i] = VK_NULL_HANDLE; 967 } 968 } 969 970 return result; 971} 972 973static VkResult 974lvp_compute_pipeline_init(struct lvp_pipeline *pipeline, 975 struct lvp_device *device, 976 struct lvp_pipeline_cache *cache, 977 const VkComputePipelineCreateInfo *pCreateInfo, 978 const VkAllocationCallbacks *alloc) 979{ 980 VK_FROM_HANDLE(vk_shader_module, module, 981 pCreateInfo->stage.module); 982 if (alloc == NULL) 983 alloc = &device->vk.alloc; 984 pipeline->device = device; 985 pipeline->layout = lvp_pipeline_layout_from_handle(pCreateInfo->layout); 986 pipeline->force_min_sample = false; 987 988 pipeline->mem_ctx = ralloc_context(NULL); 989 deep_copy_compute_create_info(pipeline->mem_ctx, 990 &pipeline->compute_create_info, pCreateInfo); 991 pipeline->is_compute_pipeline = true; 992 993 lvp_shader_compile_to_ir(pipeline, module, 994 pCreateInfo->stage.pName, 995 MESA_SHADER_COMPUTE, 996 pCreateInfo->stage.pSpecializationInfo); 997 if (!pipeline->pipeline_nir[MESA_SHADER_COMPUTE]) 998 return VK_ERROR_FEATURE_NOT_PRESENT; 999 lvp_pipeline_compile(pipeline, MESA_SHADER_COMPUTE); 1000 return VK_SUCCESS; 1001} 1002 1003static VkResult 1004lvp_compute_pipeline_create( 1005 VkDevice _device, 1006 VkPipelineCache _cache, 1007 const VkComputePipelineCreateInfo *pCreateInfo, 1008 const VkAllocationCallbacks *pAllocator, 1009 VkPipeline *pPipeline) 1010{ 1011 LVP_FROM_HANDLE(lvp_device, device, _device); 1012 LVP_FROM_HANDLE(lvp_pipeline_cache, cache, _cache); 1013 struct lvp_pipeline *pipeline; 1014 VkResult result; 1015 1016 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO); 1017 1018 pipeline = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline), 8, 1019 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1020 if (pipeline == NULL) 1021 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1022 1023 vk_object_base_init(&device->vk, &pipeline->base, 1024 VK_OBJECT_TYPE_PIPELINE); 1025 result = lvp_compute_pipeline_init(pipeline, device, cache, pCreateInfo, 1026 pAllocator); 1027 if (result != VK_SUCCESS) { 1028 vk_free2(&device->vk.alloc, pAllocator, pipeline); 1029 return result; 1030 } 1031 1032 *pPipeline = lvp_pipeline_to_handle(pipeline); 1033 1034 return VK_SUCCESS; 1035} 1036 1037VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateComputePipelines( 1038 VkDevice _device, 1039 VkPipelineCache pipelineCache, 1040 uint32_t count, 1041 const VkComputePipelineCreateInfo* pCreateInfos, 1042 const VkAllocationCallbacks* pAllocator, 1043 VkPipeline* pPipelines) 1044{ 1045 VkResult result = VK_SUCCESS; 1046 unsigned i = 0; 1047 1048 for (; i < count; i++) { 1049 VkResult r; 1050 r = lvp_compute_pipeline_create(_device, 1051 pipelineCache, 1052 &pCreateInfos[i], 1053 pAllocator, &pPipelines[i]); 1054 if (r != VK_SUCCESS) { 1055 result = r; 1056 pPipelines[i] = VK_NULL_HANDLE; 1057 } 1058 } 1059 1060 return result; 1061} 1062