From 8ce7faab47a77377a6a1313a80580828b052f878 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 22 Jun 2022 16:40:34 -0500 Subject: [PATCH] vulkan: Add a vk_pipeline_shader_stage_to_nir helper This is similar to vk_shader_module_to_nir only it takes a VkPipelineShaderStageCreateInfo and handles VK_KHR_graphics_pipeline_library semantics for when a VkShaderModuleCreateInfo is provided instead of an actual module. Reviewed-by: Boris Brezillon Acked-by: Lionel Landwerlin Part-of: --- src/vulkan/runtime/meson.build | 2 + src/vulkan/runtime/vk_pipeline.c | 88 +++++++++++++++++++++++++++ src/vulkan/runtime/vk_pipeline.h | 49 +++++++++++++++ src/vulkan/runtime/vk_shader_module.c | 42 ++++--------- 4 files changed, 151 insertions(+), 30 deletions(-) create mode 100644 src/vulkan/runtime/vk_pipeline.c create mode 100644 src/vulkan/runtime/vk_pipeline.h diff --git a/src/vulkan/runtime/meson.build b/src/vulkan/runtime/meson.build index 9d8e29d28d0..b705a566917 100644 --- a/src/vulkan/runtime/meson.build +++ b/src/vulkan/runtime/meson.build @@ -56,6 +56,8 @@ vulkan_runtime_files = files( 'vk_nir.h', 'vk_object.c', 'vk_object.h', + 'vk_pipeline.c', + 'vk_pipeline.h', 'vk_pipeline_cache.c', 'vk_pipeline_cache.h', 'vk_physical_device.c', diff --git a/src/vulkan/runtime/vk_pipeline.c b/src/vulkan/runtime/vk_pipeline.c new file mode 100644 index 00000000000..9eac775b7f2 --- /dev/null +++ b/src/vulkan/runtime/vk_pipeline.c @@ -0,0 +1,88 @@ +/* + * Copyright © 2022 Collabora, LTD + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "vk_pipeline.h" + +#include "vk_log.h" +#include "vk_nir.h" +#include "vk_shader_module.h" +#include "vk_util.h" + +VkResult +vk_pipeline_shader_stage_to_nir(struct vk_device *device, + const VkPipelineShaderStageCreateInfo *info, + const struct spirv_to_nir_options *spirv_options, + const struct nir_shader_compiler_options *nir_options, + void *mem_ctx, nir_shader **nir_out) +{ + VK_FROM_HANDLE(vk_shader_module, module, info->module); + const gl_shader_stage stage = vk_to_mesa_shader_stage(info->stage); + + assert(info->sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO); + + if (module != NULL && module->nir != NULL) { + assert(module->nir->info.stage == stage); + assert(exec_list_length(&module->nir->functions) == 1); + ASSERTED const char *nir_name = + nir_shader_get_entrypoint(module->nir)->function->name; + assert(strcmp(nir_name, info->pName) == 0); + + nir_validate_shader(module->nir, "internal shader"); + + nir_shader *clone = nir_shader_clone(mem_ctx, module->nir); + if (clone == NULL) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + assert(clone->options == NULL || clone->options == nir_options); + clone->options = nir_options; + + *nir_out = clone; + return VK_SUCCESS; + } + + const uint32_t *spirv_data; + uint32_t spirv_size; + if (module != NULL) { + spirv_data = (uint32_t *)module->data; + spirv_size = module->size; + } else { + const VkShaderModuleCreateInfo *minfo = + vk_find_struct_const(info->pNext, SHADER_MODULE_CREATE_INFO); + if (unlikely(minfo == NULL)) { + return vk_errorf(device, VK_ERROR_UNKNOWN, + "No shader module provided"); + } + spirv_data = minfo->pCode; + spirv_size = minfo->codeSize; + } + + nir_shader *nir = vk_spirv_to_nir(device, spirv_data, spirv_size, stage, + info->pName, info->pSpecializationInfo, + spirv_options, nir_options, mem_ctx); + if (nir == NULL) + return vk_errorf(device, VK_ERROR_UNKNOWN, "spirv_to_nir failed"); + + *nir_out = nir; + + return VK_SUCCESS; +} diff --git a/src/vulkan/runtime/vk_pipeline.h b/src/vulkan/runtime/vk_pipeline.h new file mode 100644 index 00000000000..41f99880379 --- /dev/null +++ b/src/vulkan/runtime/vk_pipeline.h @@ -0,0 +1,49 @@ +/* + * Copyright © 2022 Collabora, LTD + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef VK_PIPELINE_H +#define VK_PIPELINE_H + +#include "vulkan/vulkan_core.h" + +struct nir_shader; +struct nir_shader_compiler_options; +struct spirv_to_nir_options; +struct vk_device; + +#ifdef __cplusplus +extern "C" { +#endif + +VkResult +vk_pipeline_shader_stage_to_nir(struct vk_device *device, + const VkPipelineShaderStageCreateInfo *info, + const struct spirv_to_nir_options *spirv_options, + const struct nir_shader_compiler_options *nir_options, + void *mem_ctx, struct nir_shader **nir_out); + +#ifdef __cplusplus +} +#endif + +#endif /* VK_PIPELINE_H */ diff --git a/src/vulkan/runtime/vk_shader_module.c b/src/vulkan/runtime/vk_shader_module.c index de896229b96..e50d26550be 100644 --- a/src/vulkan/runtime/vk_shader_module.c +++ b/src/vulkan/runtime/vk_shader_module.c @@ -28,6 +28,8 @@ #include "vk_device.h" #include "vk_log.h" #include "vk_nir.h" +#include "vk_pipeline.h" +#include "vk_util.h" VKAPI_ATTR VkResult VKAPI_CALL vk_common_CreateShaderModule(VkDevice _device, @@ -100,36 +102,16 @@ vk_shader_module_to_nir(struct vk_device *device, const nir_shader_compiler_options *nir_options, void *mem_ctx, nir_shader **nir_out) { - if (mod->nir != NULL) { - assert(mod->nir->info.stage == stage); - assert(exec_list_length(&mod->nir->functions) == 1); - ASSERTED const char *nir_name = - nir_shader_get_entrypoint(mod->nir)->function->name; - assert(strcmp(nir_name, entrypoint_name) == 0); - - nir_validate_shader(mod->nir, "internal shader"); - - nir_shader *clone = nir_shader_clone(mem_ctx, mod->nir); - if (clone == NULL) - return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - - assert(clone->options == NULL || clone->options == nir_options); - clone->options = nir_options; - - *nir_out = clone; - return VK_SUCCESS; - } else { - nir_shader *nir = vk_spirv_to_nir(device, - (uint32_t *)mod->data, mod->size, - stage, entrypoint_name, spec_info, - spirv_options, nir_options, - mem_ctx); - if (nir == NULL) - return vk_errorf(device, VK_ERROR_UNKNOWN, "spirv_to_nir failed"); - - *nir_out = nir; - return VK_SUCCESS; - } + const VkPipelineShaderStageCreateInfo info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = mesa_to_vk_shader_stage(stage), + .module = vk_shader_module_to_handle((struct vk_shader_module *)mod), + .pName = entrypoint_name, + .pSpecializationInfo = spec_info, + }; + return vk_pipeline_shader_stage_to_nir(device, &info, + spirv_options, nir_options, + mem_ctx, nir_out); } struct vk_shader_module *