1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2024 Collabora, Ltd.
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker #include "vk_shader.h"
25*61046927SAndroid Build Coastguard Worker
26*61046927SAndroid Build Coastguard Worker #include "vk_alloc.h"
27*61046927SAndroid Build Coastguard Worker #include "vk_command_buffer.h"
28*61046927SAndroid Build Coastguard Worker #include "vk_common_entrypoints.h"
29*61046927SAndroid Build Coastguard Worker #include "vk_descriptor_set_layout.h"
30*61046927SAndroid Build Coastguard Worker #include "vk_device.h"
31*61046927SAndroid Build Coastguard Worker #include "vk_nir.h"
32*61046927SAndroid Build Coastguard Worker #include "vk_physical_device.h"
33*61046927SAndroid Build Coastguard Worker #include "vk_pipeline.h"
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker #include "util/mesa-sha1.h"
36*61046927SAndroid Build Coastguard Worker
37*61046927SAndroid Build Coastguard Worker void *
vk_shader_zalloc(struct vk_device * device,const struct vk_shader_ops * ops,gl_shader_stage stage,const VkAllocationCallbacks * alloc,size_t size)38*61046927SAndroid Build Coastguard Worker vk_shader_zalloc(struct vk_device *device,
39*61046927SAndroid Build Coastguard Worker const struct vk_shader_ops *ops,
40*61046927SAndroid Build Coastguard Worker gl_shader_stage stage,
41*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks *alloc,
42*61046927SAndroid Build Coastguard Worker size_t size)
43*61046927SAndroid Build Coastguard Worker {
44*61046927SAndroid Build Coastguard Worker /* For internal allocations, we need to allocate from the device scope
45*61046927SAndroid Build Coastguard Worker * because they might be put in pipeline caches. Importantly, it is
46*61046927SAndroid Build Coastguard Worker * impossible for the client to get at this pointer and we apply this
47*61046927SAndroid Build Coastguard Worker * heuristic before we account for allocation fallbacks so this will only
48*61046927SAndroid Build Coastguard Worker * ever happen for internal shader objectx.
49*61046927SAndroid Build Coastguard Worker */
50*61046927SAndroid Build Coastguard Worker const VkSystemAllocationScope alloc_scope =
51*61046927SAndroid Build Coastguard Worker alloc == &device->alloc ? VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
52*61046927SAndroid Build Coastguard Worker : VK_SYSTEM_ALLOCATION_SCOPE_OBJECT;
53*61046927SAndroid Build Coastguard Worker
54*61046927SAndroid Build Coastguard Worker struct vk_shader *shader = vk_zalloc2(&device->alloc, alloc, size, 8,
55*61046927SAndroid Build Coastguard Worker alloc_scope);
56*61046927SAndroid Build Coastguard Worker if (shader == NULL)
57*61046927SAndroid Build Coastguard Worker return NULL;
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker vk_object_base_init(device, &shader->base, VK_OBJECT_TYPE_SHADER_EXT);
60*61046927SAndroid Build Coastguard Worker shader->ops = ops;
61*61046927SAndroid Build Coastguard Worker shader->stage = stage;
62*61046927SAndroid Build Coastguard Worker
63*61046927SAndroid Build Coastguard Worker return shader;
64*61046927SAndroid Build Coastguard Worker }
65*61046927SAndroid Build Coastguard Worker
66*61046927SAndroid Build Coastguard Worker void
vk_shader_free(struct vk_device * device,const VkAllocationCallbacks * alloc,struct vk_shader * shader)67*61046927SAndroid Build Coastguard Worker vk_shader_free(struct vk_device *device,
68*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks *alloc,
69*61046927SAndroid Build Coastguard Worker struct vk_shader *shader)
70*61046927SAndroid Build Coastguard Worker {
71*61046927SAndroid Build Coastguard Worker vk_object_base_finish(&shader->base);
72*61046927SAndroid Build Coastguard Worker vk_free2(&device->alloc, alloc, shader);
73*61046927SAndroid Build Coastguard Worker }
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Worker int
vk_shader_cmp_graphics_stages(gl_shader_stage a,gl_shader_stage b)76*61046927SAndroid Build Coastguard Worker vk_shader_cmp_graphics_stages(gl_shader_stage a, gl_shader_stage b)
77*61046927SAndroid Build Coastguard Worker {
78*61046927SAndroid Build Coastguard Worker static const int stage_order[MESA_SHADER_MESH + 1] = {
79*61046927SAndroid Build Coastguard Worker [MESA_SHADER_VERTEX] = 1,
80*61046927SAndroid Build Coastguard Worker [MESA_SHADER_TESS_CTRL] = 2,
81*61046927SAndroid Build Coastguard Worker [MESA_SHADER_TESS_EVAL] = 3,
82*61046927SAndroid Build Coastguard Worker [MESA_SHADER_GEOMETRY] = 4,
83*61046927SAndroid Build Coastguard Worker [MESA_SHADER_TASK] = 5,
84*61046927SAndroid Build Coastguard Worker [MESA_SHADER_MESH] = 6,
85*61046927SAndroid Build Coastguard Worker [MESA_SHADER_FRAGMENT] = 7,
86*61046927SAndroid Build Coastguard Worker };
87*61046927SAndroid Build Coastguard Worker
88*61046927SAndroid Build Coastguard Worker assert(a < ARRAY_SIZE(stage_order) && stage_order[a] > 0);
89*61046927SAndroid Build Coastguard Worker assert(b < ARRAY_SIZE(stage_order) && stage_order[b] > 0);
90*61046927SAndroid Build Coastguard Worker
91*61046927SAndroid Build Coastguard Worker return stage_order[a] - stage_order[b];
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker
94*61046927SAndroid Build Coastguard Worker struct stage_idx {
95*61046927SAndroid Build Coastguard Worker gl_shader_stage stage;
96*61046927SAndroid Build Coastguard Worker uint32_t idx;
97*61046927SAndroid Build Coastguard Worker };
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Worker static int
cmp_stage_idx(const void * _a,const void * _b)100*61046927SAndroid Build Coastguard Worker cmp_stage_idx(const void *_a, const void *_b)
101*61046927SAndroid Build Coastguard Worker {
102*61046927SAndroid Build Coastguard Worker const struct stage_idx *a = _a, *b = _b;
103*61046927SAndroid Build Coastguard Worker return vk_shader_cmp_graphics_stages(a->stage, b->stage);
104*61046927SAndroid Build Coastguard Worker }
105*61046927SAndroid Build Coastguard Worker
106*61046927SAndroid Build Coastguard Worker static nir_shader *
vk_shader_to_nir(struct vk_device * device,const VkShaderCreateInfoEXT * info,const struct vk_pipeline_robustness_state * rs)107*61046927SAndroid Build Coastguard Worker vk_shader_to_nir(struct vk_device *device,
108*61046927SAndroid Build Coastguard Worker const VkShaderCreateInfoEXT *info,
109*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state *rs)
110*61046927SAndroid Build Coastguard Worker {
111*61046927SAndroid Build Coastguard Worker const struct vk_device_shader_ops *ops = device->shader_ops;
112*61046927SAndroid Build Coastguard Worker
113*61046927SAndroid Build Coastguard Worker const gl_shader_stage stage = vk_to_mesa_shader_stage(info->stage);
114*61046927SAndroid Build Coastguard Worker const nir_shader_compiler_options *nir_options =
115*61046927SAndroid Build Coastguard Worker ops->get_nir_options(device->physical, stage, rs);
116*61046927SAndroid Build Coastguard Worker struct spirv_to_nir_options spirv_options =
117*61046927SAndroid Build Coastguard Worker ops->get_spirv_options(device->physical, stage, rs);
118*61046927SAndroid Build Coastguard Worker
119*61046927SAndroid Build Coastguard Worker enum gl_subgroup_size subgroup_size = vk_get_subgroup_size(
120*61046927SAndroid Build Coastguard Worker vk_spirv_version(info->pCode, info->codeSize),
121*61046927SAndroid Build Coastguard Worker stage, info->pNext,
122*61046927SAndroid Build Coastguard Worker info->flags & VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT,
123*61046927SAndroid Build Coastguard Worker info->flags &VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT);
124*61046927SAndroid Build Coastguard Worker
125*61046927SAndroid Build Coastguard Worker nir_shader *nir = vk_spirv_to_nir(device,
126*61046927SAndroid Build Coastguard Worker info->pCode, info->codeSize,
127*61046927SAndroid Build Coastguard Worker stage, info->pName,
128*61046927SAndroid Build Coastguard Worker subgroup_size,
129*61046927SAndroid Build Coastguard Worker info->pSpecializationInfo,
130*61046927SAndroid Build Coastguard Worker &spirv_options, nir_options,
131*61046927SAndroid Build Coastguard Worker false /* internal */, NULL);
132*61046927SAndroid Build Coastguard Worker if (nir == NULL)
133*61046927SAndroid Build Coastguard Worker return NULL;
134*61046927SAndroid Build Coastguard Worker
135*61046927SAndroid Build Coastguard Worker if (ops->preprocess_nir != NULL)
136*61046927SAndroid Build Coastguard Worker ops->preprocess_nir(device->physical, nir);
137*61046927SAndroid Build Coastguard Worker
138*61046927SAndroid Build Coastguard Worker return nir;
139*61046927SAndroid Build Coastguard Worker }
140*61046927SAndroid Build Coastguard Worker
141*61046927SAndroid Build Coastguard Worker struct set_layouts {
142*61046927SAndroid Build Coastguard Worker struct vk_descriptor_set_layout *set_layouts[MESA_VK_MAX_DESCRIPTOR_SETS];
143*61046927SAndroid Build Coastguard Worker };
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker static void
vk_shader_compile_info_init(struct vk_shader_compile_info * info,struct set_layouts * set_layouts,const VkShaderCreateInfoEXT * vk_info,const struct vk_pipeline_robustness_state * rs,nir_shader * nir)146*61046927SAndroid Build Coastguard Worker vk_shader_compile_info_init(struct vk_shader_compile_info *info,
147*61046927SAndroid Build Coastguard Worker struct set_layouts *set_layouts,
148*61046927SAndroid Build Coastguard Worker const VkShaderCreateInfoEXT *vk_info,
149*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state *rs,
150*61046927SAndroid Build Coastguard Worker nir_shader *nir)
151*61046927SAndroid Build Coastguard Worker {
152*61046927SAndroid Build Coastguard Worker for (uint32_t sl = 0; sl < vk_info->setLayoutCount; sl++) {
153*61046927SAndroid Build Coastguard Worker set_layouts->set_layouts[sl] =
154*61046927SAndroid Build Coastguard Worker vk_descriptor_set_layout_from_handle(vk_info->pSetLayouts[sl]);
155*61046927SAndroid Build Coastguard Worker }
156*61046927SAndroid Build Coastguard Worker
157*61046927SAndroid Build Coastguard Worker *info = (struct vk_shader_compile_info) {
158*61046927SAndroid Build Coastguard Worker .stage = nir->info.stage,
159*61046927SAndroid Build Coastguard Worker .flags = vk_info->flags,
160*61046927SAndroid Build Coastguard Worker .next_stage_mask = vk_info->nextStage,
161*61046927SAndroid Build Coastguard Worker .nir = nir,
162*61046927SAndroid Build Coastguard Worker .robustness = rs,
163*61046927SAndroid Build Coastguard Worker .set_layout_count = vk_info->setLayoutCount,
164*61046927SAndroid Build Coastguard Worker .set_layouts = set_layouts->set_layouts,
165*61046927SAndroid Build Coastguard Worker .push_constant_range_count = vk_info->pushConstantRangeCount,
166*61046927SAndroid Build Coastguard Worker .push_constant_ranges = vk_info->pPushConstantRanges,
167*61046927SAndroid Build Coastguard Worker };
168*61046927SAndroid Build Coastguard Worker }
169*61046927SAndroid Build Coastguard Worker
170*61046927SAndroid Build Coastguard Worker PRAGMA_DIAGNOSTIC_PUSH
171*61046927SAndroid Build Coastguard Worker PRAGMA_DIAGNOSTIC_ERROR(-Wpadded)
172*61046927SAndroid Build Coastguard Worker struct vk_shader_bin_header {
173*61046927SAndroid Build Coastguard Worker char mesavkshaderbin[16];
174*61046927SAndroid Build Coastguard Worker VkDriverId driver_id;
175*61046927SAndroid Build Coastguard Worker uint8_t uuid[VK_UUID_SIZE];
176*61046927SAndroid Build Coastguard Worker uint32_t version;
177*61046927SAndroid Build Coastguard Worker uint64_t size;
178*61046927SAndroid Build Coastguard Worker uint8_t sha1[SHA1_DIGEST_LENGTH];
179*61046927SAndroid Build Coastguard Worker uint32_t _pad;
180*61046927SAndroid Build Coastguard Worker };
181*61046927SAndroid Build Coastguard Worker PRAGMA_DIAGNOSTIC_POP
182*61046927SAndroid Build Coastguard Worker static_assert(sizeof(struct vk_shader_bin_header) == 72,
183*61046927SAndroid Build Coastguard Worker "This struct has no holes");
184*61046927SAndroid Build Coastguard Worker
185*61046927SAndroid Build Coastguard Worker static void
vk_shader_bin_header_init(struct vk_shader_bin_header * header,struct vk_physical_device * device)186*61046927SAndroid Build Coastguard Worker vk_shader_bin_header_init(struct vk_shader_bin_header *header,
187*61046927SAndroid Build Coastguard Worker struct vk_physical_device *device)
188*61046927SAndroid Build Coastguard Worker {
189*61046927SAndroid Build Coastguard Worker *header = (struct vk_shader_bin_header) {
190*61046927SAndroid Build Coastguard Worker .mesavkshaderbin = "MesaVkShaderBin",
191*61046927SAndroid Build Coastguard Worker .driver_id = device->properties.driverID,
192*61046927SAndroid Build Coastguard Worker };
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker memcpy(header->uuid, device->properties.shaderBinaryUUID, VK_UUID_SIZE);
195*61046927SAndroid Build Coastguard Worker header->version = device->properties.shaderBinaryVersion;
196*61046927SAndroid Build Coastguard Worker }
197*61046927SAndroid Build Coastguard Worker
198*61046927SAndroid Build Coastguard Worker static VkResult
vk_shader_serialize(struct vk_device * device,struct vk_shader * shader,struct blob * blob)199*61046927SAndroid Build Coastguard Worker vk_shader_serialize(struct vk_device *device,
200*61046927SAndroid Build Coastguard Worker struct vk_shader *shader,
201*61046927SAndroid Build Coastguard Worker struct blob *blob)
202*61046927SAndroid Build Coastguard Worker {
203*61046927SAndroid Build Coastguard Worker struct vk_shader_bin_header header;
204*61046927SAndroid Build Coastguard Worker vk_shader_bin_header_init(&header, device->physical);
205*61046927SAndroid Build Coastguard Worker
206*61046927SAndroid Build Coastguard Worker ASSERTED intptr_t header_offset = blob_reserve_bytes(blob, sizeof(header));
207*61046927SAndroid Build Coastguard Worker assert(header_offset == 0);
208*61046927SAndroid Build Coastguard Worker
209*61046927SAndroid Build Coastguard Worker bool success = shader->ops->serialize(device, shader, blob);
210*61046927SAndroid Build Coastguard Worker if (!success || blob->out_of_memory)
211*61046927SAndroid Build Coastguard Worker return VK_INCOMPLETE;
212*61046927SAndroid Build Coastguard Worker
213*61046927SAndroid Build Coastguard Worker /* Finalize and write the header */
214*61046927SAndroid Build Coastguard Worker header.size = blob->size;
215*61046927SAndroid Build Coastguard Worker if (blob->data != NULL) {
216*61046927SAndroid Build Coastguard Worker assert(sizeof(header) <= blob->size);
217*61046927SAndroid Build Coastguard Worker
218*61046927SAndroid Build Coastguard Worker struct mesa_sha1 sha1_ctx;
219*61046927SAndroid Build Coastguard Worker _mesa_sha1_init(&sha1_ctx);
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker /* Hash the header with a zero SHA1 */
222*61046927SAndroid Build Coastguard Worker _mesa_sha1_update(&sha1_ctx, &header, sizeof(header));
223*61046927SAndroid Build Coastguard Worker
224*61046927SAndroid Build Coastguard Worker /* Hash the serialized data */
225*61046927SAndroid Build Coastguard Worker _mesa_sha1_update(&sha1_ctx, blob->data + sizeof(header),
226*61046927SAndroid Build Coastguard Worker blob->size - sizeof(header));
227*61046927SAndroid Build Coastguard Worker
228*61046927SAndroid Build Coastguard Worker _mesa_sha1_final(&sha1_ctx, header.sha1);
229*61046927SAndroid Build Coastguard Worker
230*61046927SAndroid Build Coastguard Worker blob_overwrite_bytes(blob, header_offset, &header, sizeof(header));
231*61046927SAndroid Build Coastguard Worker }
232*61046927SAndroid Build Coastguard Worker
233*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
234*61046927SAndroid Build Coastguard Worker }
235*61046927SAndroid Build Coastguard Worker
236*61046927SAndroid Build Coastguard Worker static VkResult
vk_shader_deserialize(struct vk_device * device,size_t data_size,const void * data,const VkAllocationCallbacks * pAllocator,struct vk_shader ** shader_out)237*61046927SAndroid Build Coastguard Worker vk_shader_deserialize(struct vk_device *device,
238*61046927SAndroid Build Coastguard Worker size_t data_size, const void *data,
239*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks* pAllocator,
240*61046927SAndroid Build Coastguard Worker struct vk_shader **shader_out)
241*61046927SAndroid Build Coastguard Worker {
242*61046927SAndroid Build Coastguard Worker const struct vk_device_shader_ops *ops = device->shader_ops;
243*61046927SAndroid Build Coastguard Worker
244*61046927SAndroid Build Coastguard Worker struct blob_reader blob;
245*61046927SAndroid Build Coastguard Worker blob_reader_init(&blob, data, data_size);
246*61046927SAndroid Build Coastguard Worker
247*61046927SAndroid Build Coastguard Worker struct vk_shader_bin_header header, ref_header;
248*61046927SAndroid Build Coastguard Worker blob_copy_bytes(&blob, &header, sizeof(header));
249*61046927SAndroid Build Coastguard Worker if (blob.overrun)
250*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
251*61046927SAndroid Build Coastguard Worker
252*61046927SAndroid Build Coastguard Worker vk_shader_bin_header_init(&ref_header, device->physical);
253*61046927SAndroid Build Coastguard Worker
254*61046927SAndroid Build Coastguard Worker if (memcmp(header.mesavkshaderbin, ref_header.mesavkshaderbin,
255*61046927SAndroid Build Coastguard Worker sizeof(header.mesavkshaderbin)))
256*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
257*61046927SAndroid Build Coastguard Worker
258*61046927SAndroid Build Coastguard Worker if (header.driver_id != ref_header.driver_id)
259*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
260*61046927SAndroid Build Coastguard Worker
261*61046927SAndroid Build Coastguard Worker if (memcmp(header.uuid, ref_header.uuid, sizeof(header.uuid)))
262*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
263*61046927SAndroid Build Coastguard Worker
264*61046927SAndroid Build Coastguard Worker /* From the Vulkan 1.3.276 spec:
265*61046927SAndroid Build Coastguard Worker *
266*61046927SAndroid Build Coastguard Worker * "Guaranteed compatibility of shader binaries is expressed through a
267*61046927SAndroid Build Coastguard Worker * combination of the shaderBinaryUUID and shaderBinaryVersion members
268*61046927SAndroid Build Coastguard Worker * of the VkPhysicalDeviceShaderObjectPropertiesEXT structure queried
269*61046927SAndroid Build Coastguard Worker * from a physical device. Binary shaders retrieved from a physical
270*61046927SAndroid Build Coastguard Worker * device with a certain shaderBinaryUUID are guaranteed to be
271*61046927SAndroid Build Coastguard Worker * compatible with all other physical devices reporting the same
272*61046927SAndroid Build Coastguard Worker * shaderBinaryUUID and the same or higher shaderBinaryVersion."
273*61046927SAndroid Build Coastguard Worker *
274*61046927SAndroid Build Coastguard Worker * We handle the version check here on behalf of the driver and then pass
275*61046927SAndroid Build Coastguard Worker * the version into the driver's deserialize callback.
276*61046927SAndroid Build Coastguard Worker *
277*61046927SAndroid Build Coastguard Worker * If a driver doesn't want to mess with versions, they can always make the
278*61046927SAndroid Build Coastguard Worker * UUID a hash and always report version 0 and that will make this check
279*61046927SAndroid Build Coastguard Worker * effectively a no-op.
280*61046927SAndroid Build Coastguard Worker */
281*61046927SAndroid Build Coastguard Worker if (header.version > ref_header.version)
282*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
283*61046927SAndroid Build Coastguard Worker
284*61046927SAndroid Build Coastguard Worker /* Reject shader binaries that are the wrong size. */
285*61046927SAndroid Build Coastguard Worker if (header.size != data_size)
286*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker assert(blob.current == (uint8_t *)data + sizeof(header));
289*61046927SAndroid Build Coastguard Worker blob.end = (uint8_t *)data + data_size;
290*61046927SAndroid Build Coastguard Worker
291*61046927SAndroid Build Coastguard Worker struct mesa_sha1 sha1_ctx;
292*61046927SAndroid Build Coastguard Worker _mesa_sha1_init(&sha1_ctx);
293*61046927SAndroid Build Coastguard Worker
294*61046927SAndroid Build Coastguard Worker /* Hash the header with a zero SHA1 */
295*61046927SAndroid Build Coastguard Worker struct vk_shader_bin_header sha1_header = header;
296*61046927SAndroid Build Coastguard Worker memset(sha1_header.sha1, 0, sizeof(sha1_header.sha1));
297*61046927SAndroid Build Coastguard Worker _mesa_sha1_update(&sha1_ctx, &sha1_header, sizeof(sha1_header));
298*61046927SAndroid Build Coastguard Worker
299*61046927SAndroid Build Coastguard Worker /* Hash the serialized data */
300*61046927SAndroid Build Coastguard Worker _mesa_sha1_update(&sha1_ctx, (uint8_t *)data + sizeof(header),
301*61046927SAndroid Build Coastguard Worker data_size - sizeof(header));
302*61046927SAndroid Build Coastguard Worker
303*61046927SAndroid Build Coastguard Worker _mesa_sha1_final(&sha1_ctx, ref_header.sha1);
304*61046927SAndroid Build Coastguard Worker if (memcmp(header.sha1, ref_header.sha1, sizeof(header.sha1)))
305*61046927SAndroid Build Coastguard Worker return vk_error(device, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
306*61046927SAndroid Build Coastguard Worker
307*61046927SAndroid Build Coastguard Worker /* We've now verified that the header matches and that the data has the
308*61046927SAndroid Build Coastguard Worker * right SHA1 hash so it's safe to call into the driver.
309*61046927SAndroid Build Coastguard Worker */
310*61046927SAndroid Build Coastguard Worker return ops->deserialize(device, &blob, header.version,
311*61046927SAndroid Build Coastguard Worker pAllocator, shader_out);
312*61046927SAndroid Build Coastguard Worker }
313*61046927SAndroid Build Coastguard Worker
314*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_GetShaderBinaryDataEXT(VkDevice _device,VkShaderEXT _shader,size_t * pDataSize,void * pData)315*61046927SAndroid Build Coastguard Worker vk_common_GetShaderBinaryDataEXT(VkDevice _device,
316*61046927SAndroid Build Coastguard Worker VkShaderEXT _shader,
317*61046927SAndroid Build Coastguard Worker size_t *pDataSize,
318*61046927SAndroid Build Coastguard Worker void *pData)
319*61046927SAndroid Build Coastguard Worker {
320*61046927SAndroid Build Coastguard Worker VK_FROM_HANDLE(vk_device, device, _device);
321*61046927SAndroid Build Coastguard Worker VK_FROM_HANDLE(vk_shader, shader, _shader);
322*61046927SAndroid Build Coastguard Worker VkResult result;
323*61046927SAndroid Build Coastguard Worker
324*61046927SAndroid Build Coastguard Worker /* From the Vulkan 1.3.275 spec:
325*61046927SAndroid Build Coastguard Worker *
326*61046927SAndroid Build Coastguard Worker * "If pData is NULL, then the size of the binary shader code of the
327*61046927SAndroid Build Coastguard Worker * shader object, in bytes, is returned in pDataSize. Otherwise,
328*61046927SAndroid Build Coastguard Worker * pDataSize must point to a variable set by the user to the size of the
329*61046927SAndroid Build Coastguard Worker * buffer, in bytes, pointed to by pData, and on return the variable is
330*61046927SAndroid Build Coastguard Worker * overwritten with the amount of data actually written to pData. If
331*61046927SAndroid Build Coastguard Worker * pDataSize is less than the size of the binary shader code, nothing is
332*61046927SAndroid Build Coastguard Worker * written to pData, and VK_INCOMPLETE will be returned instead of
333*61046927SAndroid Build Coastguard Worker * VK_SUCCESS."
334*61046927SAndroid Build Coastguard Worker *
335*61046927SAndroid Build Coastguard Worker * This is annoying. Unlike basically every other Vulkan data return
336*61046927SAndroid Build Coastguard Worker * method, we're not allowed to overwrite the client-provided memory region
337*61046927SAndroid Build Coastguard Worker * on VK_INCOMPLETE. This means we either need to query the blob size
338*61046927SAndroid Build Coastguard Worker * up-front by serializing twice or we need to serialize into temporary
339*61046927SAndroid Build Coastguard Worker * memory and memcpy into the client-provided region. We choose the first
340*61046927SAndroid Build Coastguard Worker * approach.
341*61046927SAndroid Build Coastguard Worker *
342*61046927SAndroid Build Coastguard Worker * In the common case, this means that vk_shader_ops::serialize will get
343*61046927SAndroid Build Coastguard Worker * called 3 times: Once for the client to get the size, once for us to
344*61046927SAndroid Build Coastguard Worker * validate the client's size, and once to actually write the data. It's a
345*61046927SAndroid Build Coastguard Worker * bit heavy-weight but this shouldn't be in a hot path and this is better
346*61046927SAndroid Build Coastguard Worker * for memory efficiency. Also, the vk_shader_ops::serialize should be
347*61046927SAndroid Build Coastguard Worker * pretty fast on a null blob.
348*61046927SAndroid Build Coastguard Worker */
349*61046927SAndroid Build Coastguard Worker struct blob blob;
350*61046927SAndroid Build Coastguard Worker blob_init_fixed(&blob, NULL, SIZE_MAX);
351*61046927SAndroid Build Coastguard Worker result = vk_shader_serialize(device, shader, &blob);
352*61046927SAndroid Build Coastguard Worker assert(result == VK_SUCCESS);
353*61046927SAndroid Build Coastguard Worker
354*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
355*61046927SAndroid Build Coastguard Worker *pDataSize = 0;
356*61046927SAndroid Build Coastguard Worker return result;
357*61046927SAndroid Build Coastguard Worker } else if (pData == NULL) {
358*61046927SAndroid Build Coastguard Worker *pDataSize = blob.size;
359*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
360*61046927SAndroid Build Coastguard Worker } else if (blob.size > *pDataSize) {
361*61046927SAndroid Build Coastguard Worker /* No data written */
362*61046927SAndroid Build Coastguard Worker *pDataSize = 0;
363*61046927SAndroid Build Coastguard Worker return VK_INCOMPLETE;
364*61046927SAndroid Build Coastguard Worker }
365*61046927SAndroid Build Coastguard Worker
366*61046927SAndroid Build Coastguard Worker blob_init_fixed(&blob, pData, *pDataSize);
367*61046927SAndroid Build Coastguard Worker result = vk_shader_serialize(device, shader, &blob);
368*61046927SAndroid Build Coastguard Worker assert(result == VK_SUCCESS);
369*61046927SAndroid Build Coastguard Worker
370*61046927SAndroid Build Coastguard Worker *pDataSize = blob.size;
371*61046927SAndroid Build Coastguard Worker
372*61046927SAndroid Build Coastguard Worker return result;
373*61046927SAndroid Build Coastguard Worker }
374*61046927SAndroid Build Coastguard Worker
375*61046927SAndroid Build Coastguard Worker /* The only place where we have "real" linking is graphics shaders and there
376*61046927SAndroid Build Coastguard Worker * is a limit as to how many of them can be linked together at one time.
377*61046927SAndroid Build Coastguard Worker */
378*61046927SAndroid Build Coastguard Worker #define VK_MAX_LINKED_SHADER_STAGES MESA_VK_MAX_GRAPHICS_PIPELINE_STAGES
379*61046927SAndroid Build Coastguard Worker
380*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateShadersEXT(VkDevice _device,uint32_t createInfoCount,const VkShaderCreateInfoEXT * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkShaderEXT * pShaders)381*61046927SAndroid Build Coastguard Worker vk_common_CreateShadersEXT(VkDevice _device,
382*61046927SAndroid Build Coastguard Worker uint32_t createInfoCount,
383*61046927SAndroid Build Coastguard Worker const VkShaderCreateInfoEXT *pCreateInfos,
384*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks *pAllocator,
385*61046927SAndroid Build Coastguard Worker VkShaderEXT *pShaders)
386*61046927SAndroid Build Coastguard Worker {
387*61046927SAndroid Build Coastguard Worker VK_FROM_HANDLE(vk_device, device, _device);
388*61046927SAndroid Build Coastguard Worker const struct vk_device_shader_ops *ops = device->shader_ops;
389*61046927SAndroid Build Coastguard Worker VkResult first_fail_or_success = VK_SUCCESS;
390*61046927SAndroid Build Coastguard Worker
391*61046927SAndroid Build Coastguard Worker struct vk_pipeline_robustness_state rs = {
392*61046927SAndroid Build Coastguard Worker .storage_buffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT,
393*61046927SAndroid Build Coastguard Worker .uniform_buffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT,
394*61046927SAndroid Build Coastguard Worker .vertex_inputs = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT,
395*61046927SAndroid Build Coastguard Worker .images = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT,
396*61046927SAndroid Build Coastguard Worker /* From the Vulkan 1.3.292 spec:
397*61046927SAndroid Build Coastguard Worker *
398*61046927SAndroid Build Coastguard Worker * "This extension [VK_EXT_robustness2] also adds support for “null
399*61046927SAndroid Build Coastguard Worker * descriptors”, where VK_NULL_HANDLE can be used instead of a valid
400*61046927SAndroid Build Coastguard Worker * handle. Accesses to null descriptors have well-defined behavior,
401*61046927SAndroid Build Coastguard Worker * and do not rely on robustness."
402*61046927SAndroid Build Coastguard Worker *
403*61046927SAndroid Build Coastguard Worker * For now, default these to true.
404*61046927SAndroid Build Coastguard Worker */
405*61046927SAndroid Build Coastguard Worker .null_uniform_buffer_descriptor = true,
406*61046927SAndroid Build Coastguard Worker .null_storage_buffer_descriptor = true,
407*61046927SAndroid Build Coastguard Worker };
408*61046927SAndroid Build Coastguard Worker
409*61046927SAndroid Build Coastguard Worker /* From the Vulkan 1.3.274 spec:
410*61046927SAndroid Build Coastguard Worker *
411*61046927SAndroid Build Coastguard Worker * "When this function returns, whether or not it succeeds, it is
412*61046927SAndroid Build Coastguard Worker * guaranteed that every element of pShaders will have been overwritten
413*61046927SAndroid Build Coastguard Worker * by either VK_NULL_HANDLE or a valid VkShaderEXT handle."
414*61046927SAndroid Build Coastguard Worker *
415*61046927SAndroid Build Coastguard Worker * Zeroing up-front makes the error path easier.
416*61046927SAndroid Build Coastguard Worker */
417*61046927SAndroid Build Coastguard Worker memset(pShaders, 0, createInfoCount * sizeof(*pShaders));
418*61046927SAndroid Build Coastguard Worker
419*61046927SAndroid Build Coastguard Worker bool has_linked_spirv = false;
420*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < createInfoCount; i++) {
421*61046927SAndroid Build Coastguard Worker if (pCreateInfos[i].codeType == VK_SHADER_CODE_TYPE_SPIRV_EXT &&
422*61046927SAndroid Build Coastguard Worker (pCreateInfos[i].flags & VK_SHADER_CREATE_LINK_STAGE_BIT_EXT))
423*61046927SAndroid Build Coastguard Worker has_linked_spirv = true;
424*61046927SAndroid Build Coastguard Worker }
425*61046927SAndroid Build Coastguard Worker
426*61046927SAndroid Build Coastguard Worker uint32_t linked_count = 0;
427*61046927SAndroid Build Coastguard Worker struct stage_idx linked[VK_MAX_LINKED_SHADER_STAGES];
428*61046927SAndroid Build Coastguard Worker
429*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < createInfoCount; i++) {
430*61046927SAndroid Build Coastguard Worker const VkShaderCreateInfoEXT *vk_info = &pCreateInfos[i];
431*61046927SAndroid Build Coastguard Worker VkResult result = VK_SUCCESS;
432*61046927SAndroid Build Coastguard Worker
433*61046927SAndroid Build Coastguard Worker switch (vk_info->codeType) {
434*61046927SAndroid Build Coastguard Worker case VK_SHADER_CODE_TYPE_BINARY_EXT: {
435*61046927SAndroid Build Coastguard Worker /* This isn't required by Vulkan but we're allowed to fail binary
436*61046927SAndroid Build Coastguard Worker * import for basically any reason. This seems like a pretty good
437*61046927SAndroid Build Coastguard Worker * reason.
438*61046927SAndroid Build Coastguard Worker */
439*61046927SAndroid Build Coastguard Worker if (has_linked_spirv &&
440*61046927SAndroid Build Coastguard Worker (vk_info->flags & VK_SHADER_CREATE_LINK_STAGE_BIT_EXT)) {
441*61046927SAndroid Build Coastguard Worker result = vk_errorf(device, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT,
442*61046927SAndroid Build Coastguard Worker "Cannot mix linked binary and SPIR-V");
443*61046927SAndroid Build Coastguard Worker break;
444*61046927SAndroid Build Coastguard Worker }
445*61046927SAndroid Build Coastguard Worker
446*61046927SAndroid Build Coastguard Worker struct vk_shader *shader;
447*61046927SAndroid Build Coastguard Worker result = vk_shader_deserialize(device, vk_info->codeSize,
448*61046927SAndroid Build Coastguard Worker vk_info->pCode, pAllocator,
449*61046927SAndroid Build Coastguard Worker &shader);
450*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
451*61046927SAndroid Build Coastguard Worker break;
452*61046927SAndroid Build Coastguard Worker
453*61046927SAndroid Build Coastguard Worker pShaders[i] = vk_shader_to_handle(shader);
454*61046927SAndroid Build Coastguard Worker break;
455*61046927SAndroid Build Coastguard Worker }
456*61046927SAndroid Build Coastguard Worker
457*61046927SAndroid Build Coastguard Worker case VK_SHADER_CODE_TYPE_SPIRV_EXT: {
458*61046927SAndroid Build Coastguard Worker if (vk_info->flags & VK_SHADER_CREATE_LINK_STAGE_BIT_EXT) {
459*61046927SAndroid Build Coastguard Worker /* Stash it and compile later */
460*61046927SAndroid Build Coastguard Worker assert(linked_count < ARRAY_SIZE(linked));
461*61046927SAndroid Build Coastguard Worker linked[linked_count++] = (struct stage_idx) {
462*61046927SAndroid Build Coastguard Worker .stage = vk_to_mesa_shader_stage(vk_info->stage),
463*61046927SAndroid Build Coastguard Worker .idx = i,
464*61046927SAndroid Build Coastguard Worker };
465*61046927SAndroid Build Coastguard Worker } else {
466*61046927SAndroid Build Coastguard Worker nir_shader *nir = vk_shader_to_nir(device, vk_info, &rs);
467*61046927SAndroid Build Coastguard Worker if (nir == NULL) {
468*61046927SAndroid Build Coastguard Worker result = vk_errorf(device, VK_ERROR_UNKNOWN,
469*61046927SAndroid Build Coastguard Worker "Failed to compile shader to NIR");
470*61046927SAndroid Build Coastguard Worker break;
471*61046927SAndroid Build Coastguard Worker }
472*61046927SAndroid Build Coastguard Worker
473*61046927SAndroid Build Coastguard Worker struct vk_shader_compile_info info;
474*61046927SAndroid Build Coastguard Worker struct set_layouts set_layouts;
475*61046927SAndroid Build Coastguard Worker vk_shader_compile_info_init(&info, &set_layouts,
476*61046927SAndroid Build Coastguard Worker vk_info, &rs, nir);
477*61046927SAndroid Build Coastguard Worker
478*61046927SAndroid Build Coastguard Worker struct vk_shader *shader;
479*61046927SAndroid Build Coastguard Worker result = ops->compile(device, 1, &info, NULL /* state */,
480*61046927SAndroid Build Coastguard Worker pAllocator, &shader);
481*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
482*61046927SAndroid Build Coastguard Worker break;
483*61046927SAndroid Build Coastguard Worker
484*61046927SAndroid Build Coastguard Worker pShaders[i] = vk_shader_to_handle(shader);
485*61046927SAndroid Build Coastguard Worker }
486*61046927SAndroid Build Coastguard Worker break;
487*61046927SAndroid Build Coastguard Worker }
488*61046927SAndroid Build Coastguard Worker
489*61046927SAndroid Build Coastguard Worker default:
490*61046927SAndroid Build Coastguard Worker unreachable("Unknown shader code type");
491*61046927SAndroid Build Coastguard Worker }
492*61046927SAndroid Build Coastguard Worker
493*61046927SAndroid Build Coastguard Worker if (first_fail_or_success == VK_SUCCESS)
494*61046927SAndroid Build Coastguard Worker first_fail_or_success = result;
495*61046927SAndroid Build Coastguard Worker }
496*61046927SAndroid Build Coastguard Worker
497*61046927SAndroid Build Coastguard Worker if (linked_count > 0) {
498*61046927SAndroid Build Coastguard Worker struct set_layouts set_layouts[VK_MAX_LINKED_SHADER_STAGES];
499*61046927SAndroid Build Coastguard Worker struct vk_shader_compile_info infos[VK_MAX_LINKED_SHADER_STAGES];
500*61046927SAndroid Build Coastguard Worker VkResult result = VK_SUCCESS;
501*61046927SAndroid Build Coastguard Worker
502*61046927SAndroid Build Coastguard Worker /* Sort so we guarantee the driver always gets them in-order */
503*61046927SAndroid Build Coastguard Worker qsort(linked, linked_count, sizeof(*linked), cmp_stage_idx);
504*61046927SAndroid Build Coastguard Worker
505*61046927SAndroid Build Coastguard Worker /* Memset for easy error handling */
506*61046927SAndroid Build Coastguard Worker memset(infos, 0, sizeof(infos));
507*61046927SAndroid Build Coastguard Worker
508*61046927SAndroid Build Coastguard Worker for (uint32_t l = 0; l < linked_count; l++) {
509*61046927SAndroid Build Coastguard Worker const VkShaderCreateInfoEXT *vk_info = &pCreateInfos[linked[l].idx];
510*61046927SAndroid Build Coastguard Worker
511*61046927SAndroid Build Coastguard Worker nir_shader *nir = vk_shader_to_nir(device, vk_info, &rs);
512*61046927SAndroid Build Coastguard Worker if (nir == NULL) {
513*61046927SAndroid Build Coastguard Worker result = vk_errorf(device, VK_ERROR_UNKNOWN,
514*61046927SAndroid Build Coastguard Worker "Failed to compile shader to NIR");
515*61046927SAndroid Build Coastguard Worker break;
516*61046927SAndroid Build Coastguard Worker }
517*61046927SAndroid Build Coastguard Worker
518*61046927SAndroid Build Coastguard Worker vk_shader_compile_info_init(&infos[l], &set_layouts[l],
519*61046927SAndroid Build Coastguard Worker vk_info, &rs, nir);
520*61046927SAndroid Build Coastguard Worker }
521*61046927SAndroid Build Coastguard Worker
522*61046927SAndroid Build Coastguard Worker if (result == VK_SUCCESS) {
523*61046927SAndroid Build Coastguard Worker struct vk_shader *shaders[VK_MAX_LINKED_SHADER_STAGES];
524*61046927SAndroid Build Coastguard Worker
525*61046927SAndroid Build Coastguard Worker result = ops->compile(device, linked_count, infos, NULL /* state */,
526*61046927SAndroid Build Coastguard Worker pAllocator, shaders);
527*61046927SAndroid Build Coastguard Worker if (result == VK_SUCCESS) {
528*61046927SAndroid Build Coastguard Worker for (uint32_t l = 0; l < linked_count; l++)
529*61046927SAndroid Build Coastguard Worker pShaders[linked[l].idx] = vk_shader_to_handle(shaders[l]);
530*61046927SAndroid Build Coastguard Worker }
531*61046927SAndroid Build Coastguard Worker } else {
532*61046927SAndroid Build Coastguard Worker for (uint32_t l = 0; l < linked_count; l++) {
533*61046927SAndroid Build Coastguard Worker if (infos[l].nir != NULL)
534*61046927SAndroid Build Coastguard Worker ralloc_free(infos[l].nir);
535*61046927SAndroid Build Coastguard Worker }
536*61046927SAndroid Build Coastguard Worker }
537*61046927SAndroid Build Coastguard Worker
538*61046927SAndroid Build Coastguard Worker if (first_fail_or_success == VK_SUCCESS)
539*61046927SAndroid Build Coastguard Worker first_fail_or_success = result;
540*61046927SAndroid Build Coastguard Worker }
541*61046927SAndroid Build Coastguard Worker
542*61046927SAndroid Build Coastguard Worker return first_fail_or_success;
543*61046927SAndroid Build Coastguard Worker }
544*61046927SAndroid Build Coastguard Worker
545*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyShaderEXT(VkDevice _device,VkShaderEXT _shader,const VkAllocationCallbacks * pAllocator)546*61046927SAndroid Build Coastguard Worker vk_common_DestroyShaderEXT(VkDevice _device,
547*61046927SAndroid Build Coastguard Worker VkShaderEXT _shader,
548*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks *pAllocator)
549*61046927SAndroid Build Coastguard Worker {
550*61046927SAndroid Build Coastguard Worker VK_FROM_HANDLE(vk_device, device, _device);
551*61046927SAndroid Build Coastguard Worker VK_FROM_HANDLE(vk_shader, shader, _shader);
552*61046927SAndroid Build Coastguard Worker
553*61046927SAndroid Build Coastguard Worker if (shader == NULL)
554*61046927SAndroid Build Coastguard Worker return;
555*61046927SAndroid Build Coastguard Worker
556*61046927SAndroid Build Coastguard Worker vk_shader_destroy(device, shader, pAllocator);
557*61046927SAndroid Build Coastguard Worker }
558*61046927SAndroid Build Coastguard Worker
559*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindShadersEXT(VkCommandBuffer commandBuffer,uint32_t stageCount,const VkShaderStageFlagBits * pStages,const VkShaderEXT * pShaders)560*61046927SAndroid Build Coastguard Worker vk_common_CmdBindShadersEXT(VkCommandBuffer commandBuffer,
561*61046927SAndroid Build Coastguard Worker uint32_t stageCount,
562*61046927SAndroid Build Coastguard Worker const VkShaderStageFlagBits *pStages,
563*61046927SAndroid Build Coastguard Worker const VkShaderEXT *pShaders)
564*61046927SAndroid Build Coastguard Worker {
565*61046927SAndroid Build Coastguard Worker VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
566*61046927SAndroid Build Coastguard Worker struct vk_device *device = cmd_buffer->base.device;
567*61046927SAndroid Build Coastguard Worker const struct vk_device_shader_ops *ops = device->shader_ops;
568*61046927SAndroid Build Coastguard Worker
569*61046927SAndroid Build Coastguard Worker STACK_ARRAY(gl_shader_stage, stages, stageCount);
570*61046927SAndroid Build Coastguard Worker STACK_ARRAY(struct vk_shader *, shaders, stageCount);
571*61046927SAndroid Build Coastguard Worker
572*61046927SAndroid Build Coastguard Worker VkShaderStageFlags vk_stages = 0;
573*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < stageCount; i++) {
574*61046927SAndroid Build Coastguard Worker vk_stages |= pStages[i];
575*61046927SAndroid Build Coastguard Worker stages[i] = vk_to_mesa_shader_stage(pStages[i]);
576*61046927SAndroid Build Coastguard Worker shaders[i] = pShaders != NULL ? vk_shader_from_handle(pShaders[i]) : NULL;
577*61046927SAndroid Build Coastguard Worker }
578*61046927SAndroid Build Coastguard Worker
579*61046927SAndroid Build Coastguard Worker vk_cmd_unbind_pipelines_for_stages(cmd_buffer, vk_stages);
580*61046927SAndroid Build Coastguard Worker if (vk_stages & ~VK_SHADER_STAGE_COMPUTE_BIT)
581*61046927SAndroid Build Coastguard Worker vk_cmd_set_rp_attachments(cmd_buffer, ~0);
582*61046927SAndroid Build Coastguard Worker
583*61046927SAndroid Build Coastguard Worker ops->cmd_bind_shaders(cmd_buffer, stageCount, stages, shaders);
584*61046927SAndroid Build Coastguard Worker }
585