Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / libre-soc / vulkan / libresoc_shader.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 */
27
28 #include "libresoc_shader.h"
29
30 static const struct nir_shader_compiler_options nir_options_llvm = {
31 .vertex_id_zero_based = true,
32 .lower_scmp = true,
33 .lower_flrp16 = true,
34 .lower_flrp32 = true,
35 .lower_flrp64 = true,
36 .lower_device_index_to_zero = true,
37 .lower_fsat = true,
38 .lower_fdiv = true,
39 .lower_fmod = true,
40 .lower_bitfield_insert_to_bitfield_select = true,
41 .lower_bitfield_extract = true,
42 .lower_sub = true,
43 .lower_pack_snorm_2x16 = true,
44 .lower_pack_snorm_4x8 = true,
45 .lower_pack_unorm_2x16 = true,
46 .lower_pack_unorm_4x8 = true,
47 .lower_unpack_snorm_2x16 = true,
48 .lower_unpack_snorm_4x8 = true,
49 .lower_unpack_unorm_2x16 = true,
50 .lower_unpack_unorm_4x8 = true,
51 .lower_extract_byte = true,
52 .lower_extract_word = true,
53 .lower_ffma = true,
54 .lower_fpow = true,
55 .lower_mul_2x32_64 = true,
56 .lower_rotate = true,
57 .use_scoped_barrier = true,
58 .max_unroll_iterations = 32,
59 .use_interpolated_input_intrinsics = true,
60 /* nir_lower_int64() isn't actually called for the LLVM backend, but
61 * this helps the loop unrolling heuristics. */
62 .lower_int64_options = nir_lower_imul64 |
63 nir_lower_imul_high64 |
64 nir_lower_imul_2x32_64 |
65 nir_lower_divmod64 |
66 nir_lower_minmax64 |
67 nir_lower_iabs64,
68 .lower_doubles_options = nir_lower_drcp |
69 nir_lower_dsqrt |
70 nir_lower_drsq |
71 nir_lower_ddiv,
72 };
73
74 static char *
75 libresoc_dump_nir_shaders(struct nir_shader * const *shaders,
76 int shader_count)
77 {
78 char *data = NULL;
79 char *ret = NULL;
80 size_t size = 0;
81 FILE *f = open_memstream(&data, &size);
82 if (f) {
83 for (int i = 0; i < shader_count; ++i)
84 nir_print_shader(shaders[i], f);
85 fclose(f);
86 }
87
88 ret = malloc(size + 1);
89 if (ret) {
90 memcpy(ret, data, size);
91 ret[size] = 0;
92 }
93 free(data);
94 return ret;
95 }
96
97 nir_shader *
98 libresoc_shader_compile_to_nir(struct libresoc_device *device,
99 struct libresoc_shader_module *module,
100 const char *entrypoint_name,
101 gl_shader_stage stage,
102 const VkSpecializationInfo *spec_info,
103 const VkPipelineCreateFlags flags,
104 unsigned subgroup_size, unsigned ballot_bit_size)
105 {
106 nir_shader *nir;
107 const nir_shader_compiler_options *nir_options =
108 &nir_options_llvm;
109
110 if (module->nir) {
111 /* Some things such as our meta clear/blit code will give us a NIR
112 * shader directly. In that case, we just ignore the SPIR-V entirely
113 * and just use the NIR shader */
114 nir = module->nir;
115 nir->options = nir_options;
116 nir_validate_shader(nir, "in internal shader");
117
118 assert(exec_list_length(&nir->functions) == 1);
119 } else {
120 uint32_t *spirv = (uint32_t *) module->data;
121 assert(module->size % 4 == 0);
122
123 if (device->instance->debug_flags & LIBRESOC_DEBUG_DUMP_SPIRV)
124 libresoc_print_spirv(module->data, module->size, stderr);
125
126 uint32_t num_spec_entries = 0;
127 struct nir_spirv_specialization *spec_entries = NULL;
128 if (spec_info && spec_info->mapEntryCount > 0) {
129 num_spec_entries = spec_info->mapEntryCount;
130 spec_entries = calloc(num_spec_entries, sizeof(*spec_entries));
131 for (uint32_t i = 0; i < num_spec_entries; i++) {
132 VkSpecializationMapEntry entry = spec_info->pMapEntries[i];
133 const void *data = spec_info->pData + entry.offset;
134 assert(data + entry.size <= spec_info->pData + spec_info->dataSize);
135
136 spec_entries[i].id = spec_info->pMapEntries[i].constantID;
137 switch (entry.size) {
138 case 8:
139 spec_entries[i].value.u64 = *(const uint64_t *)data;
140 break;
141 case 4:
142 spec_entries[i].value.u32 = *(const uint32_t *)data;
143 break;
144 case 2:
145 spec_entries[i].value.u16 = *(const uint16_t *)data;
146 break;
147 case 1:
148 spec_entries[i].value.u8 = *(const uint8_t *)data;
149 break;
150 default:
151 assert(!"Invalid spec constant size");
152 break;
153 }
154 }
155 }
156
157 const struct spirv_to_nir_options spirv_options = {0};
158 nir = spirv_to_nir(spirv, module->size / 4,
159 spec_entries, num_spec_entries,
160 stage, entrypoint_name,
161 &spirv_options, nir_options);
162 assert(nir->info.stage == stage);
163 nir_validate_shader(nir, "after spirv_to_nir");
164
165 if (device->instance->debug_flags & LIBRESOC_DEBUG_DUMP_NIR)
166 nir_print_shader(nir, stderr);
167 free(spec_entries);
168 }
169 return nir;
170 }
171
172 VkResult
173 libresoc_CreateShaderModule(VkDevice _device,
174 const VkShaderModuleCreateInfo *pCreateInfo,
175 const VkAllocationCallbacks *pAllocator,
176 VkShaderModule *pShaderModule)
177 {
178 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
179 struct libresoc_shader_module *module;
180
181 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
182 assert(pCreateInfo->flags == 0);
183
184 module = vk_alloc2(&device->vk.alloc, pAllocator,
185 sizeof(*module) + pCreateInfo->codeSize, 8,
186 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
187 if (module == NULL)
188 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
189
190 vk_object_base_init(&device->vk, &module->base,
191 VK_OBJECT_TYPE_SHADER_MODULE);
192
193 module->nir = NULL;
194 module->size = pCreateInfo->codeSize;
195 memcpy(module->data, pCreateInfo->pCode, module->size);
196
197 _mesa_sha1_compute(module->data, module->size, module->sha1);
198
199 *pShaderModule = libresoc_shader_module_to_handle(module);
200
201 return VK_SUCCESS;
202 }
203
204 void
205 libresoc_DestroyShaderModule(VkDevice _device,
206 VkShaderModule _module,
207 const VkAllocationCallbacks *pAllocator)
208 {
209 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
210 LIBRESOC_FROM_HANDLE(libresoc_shader_module, module, _module);
211
212 if (!module)
213 return;
214
215 vk_object_base_finish(&module->base);
216 vk_free2(&device->vk.alloc, pAllocator, module);
217 }