1 /*
2 * Copyright 2024 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "vk_util_compiler.h"
7 #include "compiler/spirv/nir_spirv.h"
8
9 struct nir_spirv_specialization*
vk_spec_info_to_nir_spirv(const VkSpecializationInfo * spec_info,uint32_t * out_num_spec_entries)10 vk_spec_info_to_nir_spirv(const VkSpecializationInfo *spec_info,
11 uint32_t *out_num_spec_entries)
12 {
13 if (spec_info == NULL || spec_info->mapEntryCount == 0)
14 return NULL;
15
16 uint32_t num_spec_entries = spec_info->mapEntryCount;
17 struct nir_spirv_specialization *spec_entries =
18 calloc(num_spec_entries, sizeof(*spec_entries));
19
20 for (uint32_t i = 0; i < num_spec_entries; i++) {
21 VkSpecializationMapEntry entry = spec_info->pMapEntries[i];
22 const void *data = (uint8_t *)spec_info->pData + entry.offset;
23 assert((uint8_t *)data + entry.size <=
24 (uint8_t *)spec_info->pData + spec_info->dataSize);
25
26 spec_entries[i].id = spec_info->pMapEntries[i].constantID;
27 switch (entry.size) {
28 case 8:
29 spec_entries[i].value.u64 = *(const uint64_t *)data;
30 break;
31 case 4:
32 spec_entries[i].value.u32 = *(const uint32_t *)data;
33 break;
34 case 2:
35 spec_entries[i].value.u16 = *(const uint16_t *)data;
36 break;
37 case 1:
38 spec_entries[i].value.u8 = *(const uint8_t *)data;
39 break;
40 case 0:
41 default:
42 /* The Vulkan spec says:
43 *
44 * "For a constantID specialization constant declared in a
45 * shader, size must match the byte size of the constantID. If
46 * the specialization constant is of type boolean, size must be
47 * the byte size of VkBool32."
48 *
49 * Therefore, since only scalars can be decorated as
50 * specialization constants, we can assume that if it doesn't have
51 * a size of 1, 2, 4, or 8, any use in a shader would be invalid
52 * usage. The spec further says:
53 *
54 * "If a constantID value is not a specialization constant ID
55 * used in the shader, that map entry does not affect the
56 * behavior of the pipeline."
57 *
58 * so we should ignore any invalid specialization constants rather
59 * than crash or error out when we see one.
60 */
61 break;
62 }
63 }
64
65 *out_num_spec_entries = num_spec_entries;
66 return spec_entries;
67 }
68