• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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