1 /*
2 * Copyright © 2024 Valve Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "vk_log.h"
8
9 #include "radv_device.h"
10 #include "radv_entrypoints.h"
11 #include "radv_physical_device.h"
12 #include "radv_pipeline_cache.h"
13 #include "radv_pipeline_compute.h"
14 #include "radv_pipeline_graphics.h"
15 #include "radv_shader_object.h"
16
17 static void
radv_shader_object_destroy_variant(struct radv_device * device,VkShaderCodeTypeEXT code_type,struct radv_shader * shader,struct radv_shader_binary * binary)18 radv_shader_object_destroy_variant(struct radv_device *device, VkShaderCodeTypeEXT code_type,
19 struct radv_shader *shader, struct radv_shader_binary *binary)
20 {
21 if (shader)
22 radv_shader_unref(device, shader);
23
24 if (code_type == VK_SHADER_CODE_TYPE_SPIRV_EXT)
25 free(binary);
26 }
27
28 static void
radv_shader_object_destroy(struct radv_device * device,struct radv_shader_object * shader_obj,const VkAllocationCallbacks * pAllocator)29 radv_shader_object_destroy(struct radv_device *device, struct radv_shader_object *shader_obj,
30 const VkAllocationCallbacks *pAllocator)
31 {
32 radv_shader_object_destroy_variant(device, shader_obj->code_type, shader_obj->as_ls.shader,
33 shader_obj->as_ls.binary);
34 radv_shader_object_destroy_variant(device, shader_obj->code_type, shader_obj->as_es.shader,
35 shader_obj->as_es.binary);
36 radv_shader_object_destroy_variant(device, shader_obj->code_type, shader_obj->gs.copy_shader,
37 shader_obj->gs.copy_binary);
38 radv_shader_object_destroy_variant(device, shader_obj->code_type, shader_obj->shader, shader_obj->binary);
39
40 vk_object_base_finish(&shader_obj->base);
41 vk_free2(&device->vk.alloc, pAllocator, shader_obj);
42 }
43
44 VKAPI_ATTR void VKAPI_CALL
radv_DestroyShaderEXT(VkDevice _device,VkShaderEXT shader,const VkAllocationCallbacks * pAllocator)45 radv_DestroyShaderEXT(VkDevice _device, VkShaderEXT shader, const VkAllocationCallbacks *pAllocator)
46 {
47 VK_FROM_HANDLE(radv_device, device, _device);
48 VK_FROM_HANDLE(radv_shader_object, shader_obj, shader);
49
50 if (!shader)
51 return;
52
53 radv_shader_object_destroy(device, shader_obj, pAllocator);
54 }
55
56 static void
radv_shader_stage_init(const VkShaderCreateInfoEXT * sinfo,struct radv_shader_stage * out_stage)57 radv_shader_stage_init(const VkShaderCreateInfoEXT *sinfo, struct radv_shader_stage *out_stage)
58 {
59 uint16_t dynamic_shader_stages = 0;
60
61 memset(out_stage, 0, sizeof(*out_stage));
62
63 out_stage->stage = vk_to_mesa_shader_stage(sinfo->stage);
64 out_stage->next_stage = MESA_SHADER_NONE;
65 out_stage->entrypoint = sinfo->pName;
66 out_stage->spec_info = sinfo->pSpecializationInfo;
67 out_stage->feedback.flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT;
68 out_stage->spirv.data = (const char *)sinfo->pCode;
69 out_stage->spirv.size = sinfo->codeSize;
70
71 for (uint32_t i = 0; i < sinfo->setLayoutCount; i++) {
72 VK_FROM_HANDLE(radv_descriptor_set_layout, set_layout, sinfo->pSetLayouts[i]);
73
74 if (set_layout == NULL)
75 continue;
76
77 out_stage->layout.num_sets = MAX2(i + 1, out_stage->layout.num_sets);
78 out_stage->layout.set[i].layout = set_layout;
79
80 out_stage->layout.set[i].dynamic_offset_start = out_stage->layout.dynamic_offset_count;
81 out_stage->layout.dynamic_offset_count += set_layout->dynamic_offset_count;
82
83 dynamic_shader_stages |= set_layout->dynamic_shader_stages;
84 }
85
86 if (out_stage->layout.dynamic_offset_count && (dynamic_shader_stages & sinfo->stage)) {
87 out_stage->layout.use_dynamic_descriptors = true;
88 }
89
90 for (unsigned i = 0; i < sinfo->pushConstantRangeCount; ++i) {
91 const VkPushConstantRange *range = sinfo->pPushConstantRanges + i;
92 out_stage->layout.push_constant_size = MAX2(out_stage->layout.push_constant_size, range->offset + range->size);
93 }
94
95 out_stage->layout.push_constant_size = align(out_stage->layout.push_constant_size, 16);
96
97 const VkShaderRequiredSubgroupSizeCreateInfoEXT *const subgroup_size =
98 vk_find_struct_const(sinfo->pNext, SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT);
99
100 if (subgroup_size) {
101 if (subgroup_size->requiredSubgroupSize == 32)
102 out_stage->key.subgroup_required_size = RADV_REQUIRED_WAVE32;
103 else if (subgroup_size->requiredSubgroupSize == 64)
104 out_stage->key.subgroup_required_size = RADV_REQUIRED_WAVE64;
105 else
106 unreachable("Unsupported required subgroup size.");
107 }
108
109 if (sinfo->flags & VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT) {
110 out_stage->key.subgroup_require_full = 1;
111 }
112
113 if (sinfo->flags & VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT)
114 out_stage->key.indirect_bindable = 1;
115
116 if (out_stage->stage == MESA_SHADER_MESH) {
117 out_stage->key.has_task_shader = !(sinfo->flags & VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT);
118 }
119 }
120
121 static VkResult
radv_shader_object_init_graphics(struct radv_shader_object * shader_obj,struct radv_device * device,const VkShaderCreateInfoEXT * pCreateInfo)122 radv_shader_object_init_graphics(struct radv_shader_object *shader_obj, struct radv_device *device,
123 const VkShaderCreateInfoEXT *pCreateInfo)
124 {
125 gl_shader_stage stage = vk_to_mesa_shader_stage(pCreateInfo->stage);
126 struct radv_shader_stage stages[MESA_VULKAN_SHADER_STAGES];
127
128 for (unsigned i = 0; i < MESA_VULKAN_SHADER_STAGES; i++) {
129 stages[i].entrypoint = NULL;
130 stages[i].nir = NULL;
131 stages[i].spirv.size = 0;
132 stages[i].next_stage = MESA_SHADER_NONE;
133 }
134
135 radv_shader_stage_init(pCreateInfo, &stages[stage]);
136
137 struct radv_graphics_state_key gfx_state = {0};
138
139 gfx_state.vs.has_prolog = true;
140 gfx_state.ps.has_epilog = true;
141 gfx_state.dynamic_rasterization_samples = true;
142 gfx_state.unknown_rast_prim = true;
143 gfx_state.dynamic_provoking_vtx_mode = true;
144 gfx_state.dynamic_line_rast_mode = true;
145 gfx_state.ps.exports_mrtz_via_epilog = true;
146
147 for (uint32_t i = 0; i < MAX_RTS; i++)
148 gfx_state.ps.epilog.color_map[i] = i;
149
150 struct radv_shader *shader = NULL;
151 struct radv_shader_binary *binary = NULL;
152
153 if (!pCreateInfo->nextStage) {
154 struct radv_shader *shaders[MESA_VULKAN_SHADER_STAGES] = {NULL};
155 struct radv_shader_binary *binaries[MESA_VULKAN_SHADER_STAGES] = {NULL};
156
157 radv_graphics_shaders_compile(device, NULL, stages, &gfx_state, false, false, false, true, NULL, false, shaders,
158 binaries, &shader_obj->gs.copy_shader, &shader_obj->gs.copy_binary);
159
160 shader = shaders[stage];
161 binary = binaries[stage];
162
163 ralloc_free(stages[stage].nir);
164
165 shader_obj->shader = shader;
166 shader_obj->binary = binary;
167 } else {
168 VkShaderStageFlags next_stages = pCreateInfo->nextStage;
169
170 /* The last VGT stage can always be used with rasterization enabled and a null fragment shader
171 * (ie. depth-only rendering). Because we don't want to have two variants for NONE and
172 * FRAGMENT, let's compile only one variant that works for both.
173 */
174 if (stage == MESA_SHADER_VERTEX || stage == MESA_SHADER_TESS_EVAL || stage == MESA_SHADER_GEOMETRY)
175 next_stages |= VK_SHADER_STAGE_FRAGMENT_BIT;
176
177 radv_foreach_stage(next_stage, next_stages)
178 {
179 struct radv_shader *shaders[MESA_VULKAN_SHADER_STAGES] = {NULL};
180 struct radv_shader_binary *binaries[MESA_VULKAN_SHADER_STAGES] = {NULL};
181
182 radv_shader_stage_init(pCreateInfo, &stages[stage]);
183 stages[stage].next_stage = next_stage;
184
185 radv_graphics_shaders_compile(device, NULL, stages, &gfx_state, false, false, false, true, NULL, false,
186 shaders, binaries, &shader_obj->gs.copy_shader, &shader_obj->gs.copy_binary);
187
188 shader = shaders[stage];
189 binary = binaries[stage];
190
191 ralloc_free(stages[stage].nir);
192
193 if (stage == MESA_SHADER_VERTEX) {
194 if (next_stage == MESA_SHADER_TESS_CTRL) {
195 shader_obj->as_ls.shader = shader;
196 shader_obj->as_ls.binary = binary;
197 } else if (next_stage == MESA_SHADER_GEOMETRY) {
198 shader_obj->as_es.shader = shader;
199 shader_obj->as_es.binary = binary;
200 } else {
201 shader_obj->shader = shader;
202 shader_obj->binary = binary;
203 }
204 } else if (stage == MESA_SHADER_TESS_EVAL) {
205 if (next_stage == MESA_SHADER_GEOMETRY) {
206 shader_obj->as_es.shader = shader;
207 shader_obj->as_es.binary = binary;
208 } else {
209 shader_obj->shader = shader;
210 shader_obj->binary = binary;
211 }
212 } else {
213 shader_obj->shader = shader;
214 shader_obj->binary = binary;
215 }
216 }
217 }
218
219 return VK_SUCCESS;
220 }
221
222 static VkResult
radv_shader_object_init_compute(struct radv_shader_object * shader_obj,struct radv_device * device,const VkShaderCreateInfoEXT * pCreateInfo)223 radv_shader_object_init_compute(struct radv_shader_object *shader_obj, struct radv_device *device,
224 const VkShaderCreateInfoEXT *pCreateInfo)
225 {
226 struct radv_shader_binary *cs_binary;
227 struct radv_shader_stage stage = {0};
228
229 radv_shader_stage_init(pCreateInfo, &stage);
230
231 struct radv_shader *cs_shader = radv_compile_cs(device, NULL, &stage, false, false, false, true, &cs_binary);
232
233 ralloc_free(stage.nir);
234
235 shader_obj->shader = cs_shader;
236 shader_obj->binary = cs_binary;
237
238 return VK_SUCCESS;
239 }
240
241 static void
radv_get_shader_layout(const VkShaderCreateInfoEXT * pCreateInfo,struct radv_shader_layout * layout)242 radv_get_shader_layout(const VkShaderCreateInfoEXT *pCreateInfo, struct radv_shader_layout *layout)
243 {
244 uint16_t dynamic_shader_stages = 0;
245
246 memset(layout, 0, sizeof(*layout));
247
248 layout->dynamic_offset_count = 0;
249
250 for (uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++) {
251 VK_FROM_HANDLE(radv_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[i]);
252
253 if (set_layout == NULL)
254 continue;
255
256 layout->num_sets = MAX2(i + 1, layout->num_sets);
257
258 layout->set[i].layout = set_layout;
259 layout->set[i].dynamic_offset_start = layout->dynamic_offset_count;
260
261 layout->dynamic_offset_count += set_layout->dynamic_offset_count;
262 dynamic_shader_stages |= set_layout->dynamic_shader_stages;
263 }
264
265 if (layout->dynamic_offset_count && (dynamic_shader_stages & pCreateInfo->stage)) {
266 layout->use_dynamic_descriptors = true;
267 }
268
269 layout->push_constant_size = 0;
270
271 for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
272 const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
273 layout->push_constant_size = MAX2(layout->push_constant_size, range->offset + range->size);
274 }
275
276 layout->push_constant_size = align(layout->push_constant_size, 16);
277 }
278
279 static VkResult
radv_shader_object_init_binary(struct radv_device * device,struct blob_reader * blob,struct radv_shader ** shader_out,struct radv_shader_binary ** binary_out)280 radv_shader_object_init_binary(struct radv_device *device, struct blob_reader *blob, struct radv_shader **shader_out,
281 struct radv_shader_binary **binary_out)
282 {
283 const char *binary_sha1 = blob_read_bytes(blob, SHA1_DIGEST_LENGTH);
284 const uint32_t binary_size = blob_read_uint32(blob);
285 const struct radv_shader_binary *binary = blob_read_bytes(blob, binary_size);
286 unsigned char sha1[SHA1_DIGEST_LENGTH];
287
288 _mesa_sha1_compute(binary, binary->total_size, sha1);
289 if (memcmp(sha1, binary_sha1, SHA1_DIGEST_LENGTH))
290 return VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT;
291
292 *shader_out = radv_shader_create(device, NULL, binary, true);
293 *binary_out = (struct radv_shader_binary *)binary;
294
295 return VK_SUCCESS;
296 }
297
298 static VkResult
radv_shader_object_init(struct radv_shader_object * shader_obj,struct radv_device * device,const VkShaderCreateInfoEXT * pCreateInfo)299 radv_shader_object_init(struct radv_shader_object *shader_obj, struct radv_device *device,
300 const VkShaderCreateInfoEXT *pCreateInfo)
301 {
302 const struct radv_physical_device *pdev = radv_device_physical(device);
303 struct radv_shader_layout layout;
304 VkResult result;
305
306 radv_get_shader_layout(pCreateInfo, &layout);
307
308 shader_obj->stage = vk_to_mesa_shader_stage(pCreateInfo->stage);
309 shader_obj->code_type = pCreateInfo->codeType;
310 shader_obj->push_constant_size = layout.push_constant_size;
311 shader_obj->dynamic_offset_count = layout.dynamic_offset_count;
312
313 if (pCreateInfo->codeType == VK_SHADER_CODE_TYPE_BINARY_EXT) {
314 if (pCreateInfo->codeSize < VK_UUID_SIZE + sizeof(uint32_t)) {
315 return VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT;
316 }
317
318 struct blob_reader blob;
319 blob_reader_init(&blob, pCreateInfo->pCode, pCreateInfo->codeSize);
320
321 const uint8_t *cache_uuid = blob_read_bytes(&blob, VK_UUID_SIZE);
322
323 if (memcmp(cache_uuid, pdev->cache_uuid, VK_UUID_SIZE))
324 return VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT;
325
326 const bool has_main_binary = blob_read_uint32(&blob);
327
328 if (has_main_binary) {
329 result = radv_shader_object_init_binary(device, &blob, &shader_obj->shader, &shader_obj->binary);
330 if (result != VK_SUCCESS)
331 return result;
332 }
333
334 if (shader_obj->stage == MESA_SHADER_VERTEX) {
335 const bool has_es_binary = blob_read_uint32(&blob);
336 if (has_es_binary) {
337 result =
338 radv_shader_object_init_binary(device, &blob, &shader_obj->as_es.shader, &shader_obj->as_es.binary);
339 if (result != VK_SUCCESS)
340 return result;
341 }
342
343 const bool has_ls_binary = blob_read_uint32(&blob);
344 if (has_ls_binary) {
345 result =
346 radv_shader_object_init_binary(device, &blob, &shader_obj->as_ls.shader, &shader_obj->as_ls.binary);
347 if (result != VK_SUCCESS)
348 return result;
349 }
350 } else if (shader_obj->stage == MESA_SHADER_TESS_EVAL) {
351 const bool has_es_binary = blob_read_uint32(&blob);
352 if (has_es_binary) {
353 result =
354 radv_shader_object_init_binary(device, &blob, &shader_obj->as_es.shader, &shader_obj->as_es.binary);
355 if (result != VK_SUCCESS)
356 return result;
357 }
358 } else if (shader_obj->stage == MESA_SHADER_GEOMETRY) {
359 const bool has_gs_copy_binary = blob_read_uint32(&blob);
360 if (has_gs_copy_binary) {
361 result =
362 radv_shader_object_init_binary(device, &blob, &shader_obj->gs.copy_shader, &shader_obj->gs.copy_binary);
363 if (result != VK_SUCCESS)
364 return result;
365 }
366 }
367 } else {
368 assert(pCreateInfo->codeType == VK_SHADER_CODE_TYPE_SPIRV_EXT);
369
370 if (pCreateInfo->stage == VK_SHADER_STAGE_COMPUTE_BIT) {
371 result = radv_shader_object_init_compute(shader_obj, device, pCreateInfo);
372 } else {
373 result = radv_shader_object_init_graphics(shader_obj, device, pCreateInfo);
374 }
375
376 if (result != VK_SUCCESS)
377 return result;
378 }
379
380 return VK_SUCCESS;
381 }
382
383 static VkResult
radv_shader_object_create(VkDevice _device,const VkShaderCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkShaderEXT * pShader)384 radv_shader_object_create(VkDevice _device, const VkShaderCreateInfoEXT *pCreateInfo,
385 const VkAllocationCallbacks *pAllocator, VkShaderEXT *pShader)
386 {
387 VK_FROM_HANDLE(radv_device, device, _device);
388 struct radv_shader_object *shader_obj;
389 VkResult result;
390
391 shader_obj = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*shader_obj), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
392 if (shader_obj == NULL)
393 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
394
395 vk_object_base_init(&device->vk, &shader_obj->base, VK_OBJECT_TYPE_SHADER_EXT);
396
397 result = radv_shader_object_init(shader_obj, device, pCreateInfo);
398 if (result != VK_SUCCESS) {
399 radv_shader_object_destroy(device, shader_obj, pAllocator);
400 return result;
401 }
402
403 *pShader = radv_shader_object_to_handle(shader_obj);
404
405 return VK_SUCCESS;
406 }
407
408 static VkResult
radv_shader_object_create_linked(VkDevice _device,uint32_t createInfoCount,const VkShaderCreateInfoEXT * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkShaderEXT * pShaders)409 radv_shader_object_create_linked(VkDevice _device, uint32_t createInfoCount, const VkShaderCreateInfoEXT *pCreateInfos,
410 const VkAllocationCallbacks *pAllocator, VkShaderEXT *pShaders)
411 {
412 VK_FROM_HANDLE(radv_device, device, _device);
413 struct radv_shader_stage stages[MESA_VULKAN_SHADER_STAGES];
414
415 for (unsigned i = 0; i < MESA_VULKAN_SHADER_STAGES; i++) {
416 stages[i].entrypoint = NULL;
417 stages[i].nir = NULL;
418 stages[i].spirv.size = 0;
419 stages[i].next_stage = MESA_SHADER_NONE;
420 }
421
422 struct radv_graphics_state_key gfx_state = {0};
423
424 gfx_state.vs.has_prolog = true;
425 gfx_state.ps.has_epilog = true;
426 gfx_state.dynamic_rasterization_samples = true;
427 gfx_state.unknown_rast_prim = true;
428 gfx_state.dynamic_provoking_vtx_mode = true;
429 gfx_state.dynamic_line_rast_mode = true;
430 gfx_state.ps.exports_mrtz_via_epilog = true;
431
432 for (uint32_t i = 0; i < MAX_RTS; i++)
433 gfx_state.ps.epilog.color_map[i] = i;
434
435 for (unsigned i = 0; i < createInfoCount; i++) {
436 const VkShaderCreateInfoEXT *pCreateInfo = &pCreateInfos[i];
437 gl_shader_stage s = vk_to_mesa_shader_stage(pCreateInfo->stage);
438
439 radv_shader_stage_init(pCreateInfo, &stages[s]);
440 }
441
442 /* Determine next stage. */
443 for (unsigned i = 0; i < MESA_VULKAN_SHADER_STAGES; i++) {
444 if (!stages[i].entrypoint)
445 continue;
446
447 switch (stages[i].stage) {
448 case MESA_SHADER_VERTEX:
449 if (stages[MESA_SHADER_TESS_CTRL].entrypoint) {
450 stages[i].next_stage = MESA_SHADER_TESS_CTRL;
451 } else if (stages[MESA_SHADER_GEOMETRY].entrypoint) {
452 stages[i].next_stage = MESA_SHADER_GEOMETRY;
453 } else if (stages[MESA_SHADER_FRAGMENT].entrypoint) {
454 stages[i].next_stage = MESA_SHADER_FRAGMENT;
455 }
456 break;
457 case MESA_SHADER_TESS_CTRL:
458 stages[i].next_stage = MESA_SHADER_TESS_EVAL;
459 break;
460 case MESA_SHADER_TESS_EVAL:
461 if (stages[MESA_SHADER_GEOMETRY].entrypoint) {
462 stages[i].next_stage = MESA_SHADER_GEOMETRY;
463 } else if (stages[MESA_SHADER_FRAGMENT].entrypoint) {
464 stages[i].next_stage = MESA_SHADER_FRAGMENT;
465 }
466 break;
467 case MESA_SHADER_GEOMETRY:
468 case MESA_SHADER_MESH:
469 if (stages[MESA_SHADER_FRAGMENT].entrypoint) {
470 stages[i].next_stage = MESA_SHADER_FRAGMENT;
471 }
472 break;
473 case MESA_SHADER_FRAGMENT:
474 stages[i].next_stage = MESA_SHADER_NONE;
475 break;
476 case MESA_SHADER_TASK:
477 stages[i].next_stage = MESA_SHADER_MESH;
478 break;
479 default:
480 assert(0);
481 }
482 }
483
484 struct radv_shader *shaders[MESA_VULKAN_SHADER_STAGES] = {NULL};
485 struct radv_shader_binary *binaries[MESA_VULKAN_SHADER_STAGES] = {NULL};
486 struct radv_shader *gs_copy_shader = NULL;
487 struct radv_shader_binary *gs_copy_binary = NULL;
488
489 radv_graphics_shaders_compile(device, NULL, stages, &gfx_state, false, false, false, true, NULL, false, shaders,
490 binaries, &gs_copy_shader, &gs_copy_binary);
491
492 for (unsigned i = 0; i < createInfoCount; i++) {
493 const VkShaderCreateInfoEXT *pCreateInfo = &pCreateInfos[i];
494 gl_shader_stage s = vk_to_mesa_shader_stage(pCreateInfo->stage);
495 struct radv_shader_object *shader_obj;
496
497 shader_obj = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*shader_obj), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
498 if (shader_obj == NULL)
499 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
500
501 vk_object_base_init(&device->vk, &shader_obj->base, VK_OBJECT_TYPE_SHADER_EXT);
502
503 shader_obj->stage = s;
504 shader_obj->code_type = pCreateInfo->codeType;
505 shader_obj->push_constant_size = stages[s].layout.push_constant_size;
506 shader_obj->dynamic_offset_count = stages[s].layout.dynamic_offset_count;
507
508 if (s == MESA_SHADER_VERTEX) {
509 if (stages[s].next_stage == MESA_SHADER_TESS_CTRL) {
510 shader_obj->as_ls.shader = shaders[s];
511 shader_obj->as_ls.binary = binaries[s];
512 } else if (stages[s].next_stage == MESA_SHADER_GEOMETRY) {
513 shader_obj->as_es.shader = shaders[s];
514 shader_obj->as_es.binary = binaries[s];
515 } else {
516 shader_obj->shader = shaders[s];
517 shader_obj->binary = binaries[s];
518 }
519 } else if (s == MESA_SHADER_TESS_EVAL) {
520 if (stages[s].next_stage == MESA_SHADER_GEOMETRY) {
521 shader_obj->as_es.shader = shaders[s];
522 shader_obj->as_es.binary = binaries[s];
523 } else {
524 shader_obj->shader = shaders[s];
525 shader_obj->binary = binaries[s];
526 }
527 } else {
528 shader_obj->shader = shaders[s];
529 shader_obj->binary = binaries[s];
530 }
531
532 if (s == MESA_SHADER_GEOMETRY) {
533 shader_obj->gs.copy_shader = gs_copy_shader;
534 shader_obj->gs.copy_binary = gs_copy_binary;
535 }
536
537 ralloc_free(stages[s].nir);
538
539 pShaders[i] = radv_shader_object_to_handle(shader_obj);
540 }
541
542 return VK_SUCCESS;
543 }
544
545 static bool
radv_shader_object_linking_enabled(uint32_t createInfoCount,const VkShaderCreateInfoEXT * pCreateInfos)546 radv_shader_object_linking_enabled(uint32_t createInfoCount, const VkShaderCreateInfoEXT *pCreateInfos)
547 {
548 const bool has_linked_spirv = createInfoCount > 1 &&
549 !!(pCreateInfos[0].flags & VK_SHADER_CREATE_LINK_STAGE_BIT_EXT) &&
550 pCreateInfos[0].codeType == VK_SHADER_CODE_TYPE_SPIRV_EXT;
551
552 if (!has_linked_spirv)
553 return false;
554
555 /* Gather the available shader stages. */
556 VkShaderStageFlagBits stages = 0;
557 for (unsigned i = 0; i < createInfoCount; i++) {
558 const VkShaderCreateInfoEXT *pCreateInfo = &pCreateInfos[i];
559 stages |= pCreateInfo->stage;
560 }
561
562 for (unsigned i = 0; i < createInfoCount; i++) {
563 const VkShaderCreateInfoEXT *pCreateInfo = &pCreateInfos[i];
564
565 /* Force disable shaders linking when the next stage of VS/TES isn't present because the
566 * driver would need to compile all shaders twice due to shader variants. This is probably
567 * less optimal than compiling unlinked shaders.
568 */
569 if ((pCreateInfo->stage & VK_SHADER_STAGE_VERTEX_BIT) &&
570 (pCreateInfo->nextStage & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_GEOMETRY_BIT)) &&
571 !(stages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_GEOMETRY_BIT)))
572 return false;
573
574 if ((pCreateInfo->stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) &&
575 (pCreateInfo->nextStage & VK_SHADER_STAGE_GEOMETRY_BIT) && !(stages & VK_SHADER_STAGE_GEOMETRY_BIT))
576 return false;
577
578 assert(pCreateInfo->flags & VK_SHADER_CREATE_LINK_STAGE_BIT_EXT);
579 }
580
581 return true;
582 }
583
584 VKAPI_ATTR VkResult VKAPI_CALL
radv_CreateShadersEXT(VkDevice _device,uint32_t createInfoCount,const VkShaderCreateInfoEXT * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkShaderEXT * pShaders)585 radv_CreateShadersEXT(VkDevice _device, uint32_t createInfoCount, const VkShaderCreateInfoEXT *pCreateInfos,
586 const VkAllocationCallbacks *pAllocator, VkShaderEXT *pShaders)
587 {
588 VkResult result = VK_SUCCESS;
589 unsigned i = 0;
590
591 if (radv_shader_object_linking_enabled(createInfoCount, pCreateInfos))
592 return radv_shader_object_create_linked(_device, createInfoCount, pCreateInfos, pAllocator, pShaders);
593
594 for (; i < createInfoCount; i++) {
595 VkResult r;
596
597 r = radv_shader_object_create(_device, &pCreateInfos[i], pAllocator, &pShaders[i]);
598 if (r != VK_SUCCESS) {
599 result = r;
600 pShaders[i] = VK_NULL_HANDLE;
601 }
602 }
603
604 for (; i < createInfoCount; ++i)
605 pShaders[i] = VK_NULL_HANDLE;
606
607 return result;
608 }
609
610 static size_t
radv_get_shader_binary_size(const struct radv_shader_binary * binary)611 radv_get_shader_binary_size(const struct radv_shader_binary *binary)
612 {
613 size_t size = sizeof(uint32_t); /* has_binary */
614
615 if (binary)
616 size += SHA1_DIGEST_LENGTH + 4 + ALIGN(binary->total_size, 4);
617
618 return size;
619 }
620
621 static size_t
radv_get_shader_object_size(const struct radv_shader_object * shader_obj)622 radv_get_shader_object_size(const struct radv_shader_object *shader_obj)
623 {
624 size_t size = VK_UUID_SIZE;
625
626 size += radv_get_shader_binary_size(shader_obj->binary);
627
628 if (shader_obj->stage == MESA_SHADER_VERTEX) {
629 size += radv_get_shader_binary_size(shader_obj->as_es.binary);
630 size += radv_get_shader_binary_size(shader_obj->as_ls.binary);
631 } else if (shader_obj->stage == MESA_SHADER_TESS_EVAL) {
632 size += radv_get_shader_binary_size(shader_obj->as_es.binary);
633 } else if (shader_obj->stage == MESA_SHADER_GEOMETRY) {
634 size += radv_get_shader_binary_size(shader_obj->gs.copy_binary);
635 }
636
637 return size;
638 }
639
640 static void
radv_write_shader_binary(struct blob * blob,const struct radv_shader_binary * binary)641 radv_write_shader_binary(struct blob *blob, const struct radv_shader_binary *binary)
642 {
643 unsigned char binary_sha1[SHA1_DIGEST_LENGTH];
644
645 blob_write_uint32(blob, !!binary);
646
647 if (binary) {
648 _mesa_sha1_compute(binary, binary->total_size, binary_sha1);
649
650 blob_write_bytes(blob, binary_sha1, sizeof(binary_sha1));
651 blob_write_uint32(blob, binary->total_size);
652 blob_write_bytes(blob, binary, binary->total_size);
653 }
654 }
655
656 VKAPI_ATTR VkResult VKAPI_CALL
radv_GetShaderBinaryDataEXT(VkDevice _device,VkShaderEXT shader,size_t * pDataSize,void * pData)657 radv_GetShaderBinaryDataEXT(VkDevice _device, VkShaderEXT shader, size_t *pDataSize, void *pData)
658 {
659 VK_FROM_HANDLE(radv_device, device, _device);
660 VK_FROM_HANDLE(radv_shader_object, shader_obj, shader);
661 const struct radv_physical_device *pdev = radv_device_physical(device);
662 const size_t size = radv_get_shader_object_size(shader_obj);
663
664 if (!pData) {
665 *pDataSize = size;
666 return VK_SUCCESS;
667 }
668
669 if (*pDataSize < size) {
670 *pDataSize = 0;
671 return VK_INCOMPLETE;
672 }
673
674 struct blob blob;
675 blob_init_fixed(&blob, pData, *pDataSize);
676 blob_write_bytes(&blob, pdev->cache_uuid, VK_UUID_SIZE);
677
678 radv_write_shader_binary(&blob, shader_obj->binary);
679
680 if (shader_obj->stage == MESA_SHADER_VERTEX) {
681 radv_write_shader_binary(&blob, shader_obj->as_es.binary);
682 radv_write_shader_binary(&blob, shader_obj->as_ls.binary);
683 } else if (shader_obj->stage == MESA_SHADER_TESS_EVAL) {
684 radv_write_shader_binary(&blob, shader_obj->as_es.binary);
685 } else if (shader_obj->stage == MESA_SHADER_GEOMETRY) {
686 radv_write_shader_binary(&blob, shader_obj->gs.copy_binary);
687 }
688
689 assert(!blob.out_of_memory);
690
691 return VK_SUCCESS;
692 }
693