2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
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:
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
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
28 #include "libresoc_shader.h"
30 static const struct nir_shader_compiler_options nir_options_llvm
= {
31 .vertex_id_zero_based
= true,
36 .lower_device_index_to_zero
= true,
40 .lower_bitfield_insert_to_bitfield_select
= true,
41 .lower_bitfield_extract
= 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,
55 .lower_mul_2x32_64
= 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
|
68 .lower_doubles_options
= nir_lower_drcp
|
75 libresoc_dump_nir_shaders(struct nir_shader
* const *shaders
,
81 FILE *f
= open_memstream(&data
, &size
);
83 for (int i
= 0; i
< shader_count
; ++i
)
84 nir_print_shader(shaders
[i
], f
);
88 ret
= malloc(size
+ 1);
90 memcpy(ret
, data
, size
);
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
)
107 const nir_shader_compiler_options
*nir_options
=
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 */
115 nir
->options
= nir_options
;
116 nir_validate_shader(nir
, "in internal shader");
118 assert(exec_list_length(&nir
->functions
) == 1);
120 uint32_t *spirv
= (uint32_t *) module
->data
;
121 assert(module
->size
% 4 == 0);
123 if (device
->instance
->debug_flags
& LIBRESOC_DEBUG_DUMP_SPIRV
)
124 libresoc_print_spirv(module
->data
, module
->size
, stderr
);
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
);
136 spec_entries
[i
].id
= spec_info
->pMapEntries
[i
].constantID
;
137 switch (entry
.size
) {
139 spec_entries
[i
].value
.u64
= *(const uint64_t *)data
;
142 spec_entries
[i
].value
.u32
= *(const uint32_t *)data
;
145 spec_entries
[i
].value
.u16
= *(const uint16_t *)data
;
148 spec_entries
[i
].value
.u8
= *(const uint8_t *)data
;
151 assert(!"Invalid spec constant size");
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");
165 if (device
->instance
->debug_flags
& LIBRESOC_DEBUG_DUMP_NIR
)
166 nir_print_shader(nir
, stderr
);
173 libresoc_CreateShaderModule(VkDevice _device
,
174 const VkShaderModuleCreateInfo
*pCreateInfo
,
175 const VkAllocationCallbacks
*pAllocator
,
176 VkShaderModule
*pShaderModule
)
178 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
179 struct libresoc_shader_module
*module
;
181 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO
);
182 assert(pCreateInfo
->flags
== 0);
184 module
= vk_alloc2(&device
->vk
.alloc
, pAllocator
,
185 sizeof(*module
) + pCreateInfo
->codeSize
, 8,
186 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
188 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
190 vk_object_base_init(&device
->vk
, &module
->base
,
191 VK_OBJECT_TYPE_SHADER_MODULE
);
194 module
->size
= pCreateInfo
->codeSize
;
195 memcpy(module
->data
, pCreateInfo
->pCode
, module
->size
);
197 _mesa_sha1_compute(module
->data
, module
->size
, module
->sha1
);
199 *pShaderModule
= libresoc_shader_module_to_handle(module
);
205 libresoc_DestroyShaderModule(VkDevice _device
,
206 VkShaderModule _module
,
207 const VkAllocationCallbacks
*pAllocator
)
209 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
210 LIBRESOC_FROM_HANDLE(libresoc_shader_module
, module
, _module
);
215 vk_object_base_finish(&module
->base
);
216 vk_free2(&device
->vk
.alloc
, pAllocator
, module
);