aboutsummaryrefslogtreecommitdiff
path: root/src/vulkan/util/vk_util_compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vulkan/util/vk_util_compiler.c')
-rw-r--r--src/vulkan/util/vk_util_compiler.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/vulkan/util/vk_util_compiler.c b/src/vulkan/util/vk_util_compiler.c
new file mode 100644
index 00000000000..619644ca830
--- /dev/null
+++ b/src/vulkan/util/vk_util_compiler.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2024 Google LLC
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "vk_util_compiler.h"
+#include "compiler/spirv/nir_spirv.h"
+
+struct nir_spirv_specialization*
+vk_spec_info_to_nir_spirv(const VkSpecializationInfo *spec_info,
+ uint32_t *out_num_spec_entries)
+{
+ if (spec_info == NULL || spec_info->mapEntryCount == 0)
+ return NULL;
+
+ uint32_t num_spec_entries = spec_info->mapEntryCount;
+ struct nir_spirv_specialization *spec_entries =
+ calloc(num_spec_entries, sizeof(*spec_entries));
+
+ for (uint32_t i = 0; i < num_spec_entries; i++) {
+ VkSpecializationMapEntry entry = spec_info->pMapEntries[i];
+ const void *data = (uint8_t *)spec_info->pData + entry.offset;
+ assert((uint8_t *)data + entry.size <=
+ (uint8_t *)spec_info->pData + spec_info->dataSize);
+
+ spec_entries[i].id = spec_info->pMapEntries[i].constantID;
+ switch (entry.size) {
+ case 8:
+ spec_entries[i].value.u64 = *(const uint64_t *)data;
+ break;
+ case 4:
+ spec_entries[i].value.u32 = *(const uint32_t *)data;
+ break;
+ case 2:
+ spec_entries[i].value.u16 = *(const uint16_t *)data;
+ break;
+ case 1:
+ spec_entries[i].value.u8 = *(const uint8_t *)data;
+ break;
+ case 0:
+ default:
+ /* The Vulkan spec says:
+ *
+ * "For a constantID specialization constant declared in a
+ * shader, size must match the byte size of the constantID. If
+ * the specialization constant is of type boolean, size must be
+ * the byte size of VkBool32."
+ *
+ * Therefore, since only scalars can be decorated as
+ * specialization constants, we can assume that if it doesn't have
+ * a size of 1, 2, 4, or 8, any use in a shader would be invalid
+ * usage. The spec further says:
+ *
+ * "If a constantID value is not a specialization constant ID
+ * used in the shader, that map entry does not affect the
+ * behavior of the pipeline."
+ *
+ * so we should ignore any invalid specialization constants rather
+ * than crash or error out when we see one.
+ */
+ break;
+ }
+ }
+
+ *out_num_spec_entries = num_spec_entries;
+ return spec_entries;
+}