vulkan: add vk_spec_info_to_nir_spirv util method

All vulkan drivers have been copying anv's code to convert
VkSpecializationInfo into nir_spirv_specialization.

Recently there was a Vulkan spec change on allowed values for
VkSpecializationInfo, and all drivers got affected.

This commits creates a new helper, and uses it on all Vulkan Mesa
drivers.

v2: use (uint8_t*) castings, instead of void*, to avoid C2036 with
    MSVC (detected by the CI, inspired on what radv was doing)

Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Samuel Iglesias Gonsálvez <siglesias@igalia.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Juan A. Suarez <jasuarez@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12047>
This commit is contained in:
Alejandro Piñeiro
2021-07-21 10:36:38 +02:00
committed by Marge Bot
parent fec1a04c53
commit 476dc3c050
9 changed files with 81 additions and 237 deletions
+1 -1
View File
@@ -113,7 +113,7 @@ libvulkan_util = static_library(
[files_vulkan_util, vk_common_entrypoints, vk_dispatch_table,
vk_enum_to_str, vk_extensions],
include_directories : [inc_include, inc_src, inc_gallium],
dependencies : [vulkan_wsi_deps, idep_mesautil],
dependencies : [vulkan_wsi_deps, idep_mesautil, idep_nir_headers],
# For glsl_type_singleton
link_with : libcompiler,
c_args : [vulkan_wsi_args],
+62
View File
@@ -29,6 +29,8 @@
#include "vk_util.h"
#include "util/debug.h"
#include "compiler/spirv/nir_spirv.h"
uint32_t vk_get_driver_version(void)
{
const char *minor_string = strchr(PACKAGE_VERSION, '.');
@@ -79,3 +81,63 @@ vk_warn_non_conformant_implementation(const char *driver_name)
fprintf(stderr, "WARNING: %s is not a conformant Vulkan implementation, "
"testing use only.\n", driver_name);
}
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;
}
+6
View File
@@ -272,6 +272,12 @@ mesa_to_vk_shader_stage(gl_shader_stage mesa_stage)
(_i)++, (_draw) = (const VkMultiDrawInfoEXT*)((const uint8_t*)(_draw) + (_stride)))
struct nir_spirv_specialization;
struct nir_spirv_specialization*
vk_spec_info_to_nir_spirv(const VkSpecializationInfo *spec_info,
uint32_t *out_num_spec_entries);
#ifdef __cplusplus
}
#endif