1 /*
2  * Copyright © 2017 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "vk_shader_module.h"
25 
26 #include "vk_alloc.h"
27 #include "vk_common_entrypoints.h"
28 #include "vk_device.h"
29 #include "vk_log.h"
30 #include "vk_nir.h"
31 #include "vk_pipeline.h"
32 #include "vk_util.h"
33 
vk_shader_module_init(struct vk_device * device,struct vk_shader_module * module,const VkShaderModuleCreateInfo * create_info)34 void vk_shader_module_init(struct vk_device *device,
35                            struct vk_shader_module *module,
36                            const VkShaderModuleCreateInfo *create_info)
37 {
38    vk_object_base_init(device, &module->base, VK_OBJECT_TYPE_SHADER_MODULE);
39 
40    module->nir = NULL;
41 
42    module->size = create_info->codeSize;
43    memcpy(module->data, create_info->pCode, module->size);
44 
45    _mesa_blake3_compute(module->data, module->size, module->hash);
46 }
47 
48 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateShaderModule(VkDevice _device,const VkShaderModuleCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkShaderModule * pShaderModule)49 vk_common_CreateShaderModule(VkDevice _device,
50                              const VkShaderModuleCreateInfo *pCreateInfo,
51                              const VkAllocationCallbacks *pAllocator,
52                              VkShaderModule *pShaderModule)
53 {
54     VK_FROM_HANDLE(vk_device, device, _device);
55     struct vk_shader_module *module;
56 
57     assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
58     assert(pCreateInfo->flags == 0);
59 
60     module = vk_alloc2(&device->alloc, pAllocator,
61                        sizeof(*module) + pCreateInfo->codeSize, 8,
62                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
63     if (module == NULL)
64        return VK_ERROR_OUT_OF_HOST_MEMORY;
65 
66     vk_shader_module_init(device, module, pCreateInfo);
67 
68     *pShaderModule = vk_shader_module_to_handle(module);
69 
70     return VK_SUCCESS;
71 }
72 
73 const uint8_t vk_shaderModuleIdentifierAlgorithmUUID[VK_UUID_SIZE] = "MESA-BLAKE3";
74 
75 VKAPI_ATTR void VKAPI_CALL
vk_common_GetShaderModuleIdentifierEXT(VkDevice _device,VkShaderModule _module,VkShaderModuleIdentifierEXT * pIdentifier)76 vk_common_GetShaderModuleIdentifierEXT(VkDevice _device,
77                                        VkShaderModule _module,
78                                        VkShaderModuleIdentifierEXT *pIdentifier)
79 {
80    VK_FROM_HANDLE(vk_shader_module, module, _module);
81    memcpy(pIdentifier->identifier, module->hash, sizeof(module->hash));
82    pIdentifier->identifierSize = sizeof(module->hash);
83 }
84 
85 VKAPI_ATTR void VKAPI_CALL
vk_common_GetShaderModuleCreateInfoIdentifierEXT(VkDevice _device,const VkShaderModuleCreateInfo * pCreateInfo,VkShaderModuleIdentifierEXT * pIdentifier)86 vk_common_GetShaderModuleCreateInfoIdentifierEXT(VkDevice _device,
87                                                  const VkShaderModuleCreateInfo *pCreateInfo,
88                                                  VkShaderModuleIdentifierEXT *pIdentifier)
89 {
90    _mesa_blake3_compute(pCreateInfo->pCode, pCreateInfo->codeSize,
91                         pIdentifier->identifier);
92    pIdentifier->identifierSize = sizeof(blake3_hash);
93 }
94 
95 VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyShaderModule(VkDevice _device,VkShaderModule _module,const VkAllocationCallbacks * pAllocator)96 vk_common_DestroyShaderModule(VkDevice _device,
97                               VkShaderModule _module,
98                               const VkAllocationCallbacks *pAllocator)
99 {
100    VK_FROM_HANDLE(vk_device, device, _device);
101    VK_FROM_HANDLE(vk_shader_module, module, _module);
102 
103    if (!module)
104       return;
105 
106    /* NIR modules (which are only created internally by the driver) are not
107     * dynamically allocated so we should never call this for them.
108     * Instead the driver is responsible for freeing the NIR code when it is
109     * no longer needed.
110     */
111    assert(module->nir == NULL);
112 
113    vk_object_free(device, pAllocator, module);
114 }
115 
116 #define SPIR_V_MAGIC_NUMBER 0x07230203
117 
118 uint32_t
vk_shader_module_spirv_version(const struct vk_shader_module * mod)119 vk_shader_module_spirv_version(const struct vk_shader_module *mod)
120 {
121    if (mod->nir != NULL)
122       return 0;
123 
124    return vk_spirv_version((uint32_t *)mod->data, mod->size);
125 }
126 
127 VkResult
vk_shader_module_to_nir(struct vk_device * device,const struct vk_shader_module * mod,gl_shader_stage stage,const char * entrypoint_name,const VkSpecializationInfo * spec_info,const struct spirv_to_nir_options * spirv_options,const nir_shader_compiler_options * nir_options,void * mem_ctx,nir_shader ** nir_out)128 vk_shader_module_to_nir(struct vk_device *device,
129                         const struct vk_shader_module *mod,
130                         gl_shader_stage stage,
131                         const char *entrypoint_name,
132                         const VkSpecializationInfo *spec_info,
133                         const struct spirv_to_nir_options *spirv_options,
134                         const nir_shader_compiler_options *nir_options,
135                         void *mem_ctx, nir_shader **nir_out)
136 {
137    const VkPipelineShaderStageCreateInfo info = {
138       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
139       .stage = mesa_to_vk_shader_stage(stage),
140       .module = vk_shader_module_to_handle((struct vk_shader_module *)mod),
141       .pName = entrypoint_name,
142       .pSpecializationInfo = spec_info,
143    };
144    return vk_pipeline_shader_stage_to_nir(device, &info,
145                                           spirv_options, nir_options,
146                                           mem_ctx, nir_out);
147 }
148