xref: /aosp_15_r20/external/mesa3d/src/vulkan/runtime/vk_pipeline.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 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_pipeline.h"
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include "vk_alloc.h"
27*61046927SAndroid Build Coastguard Worker #include "vk_common_entrypoints.h"
28*61046927SAndroid Build Coastguard Worker #include "vk_command_buffer.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_graphics_state.h"
32*61046927SAndroid Build Coastguard Worker #include "vk_log.h"
33*61046927SAndroid Build Coastguard Worker #include "vk_nir.h"
34*61046927SAndroid Build Coastguard Worker #include "vk_physical_device.h"
35*61046927SAndroid Build Coastguard Worker #include "vk_pipeline_layout.h"
36*61046927SAndroid Build Coastguard Worker #include "vk_shader.h"
37*61046927SAndroid Build Coastguard Worker #include "vk_shader_module.h"
38*61046927SAndroid Build Coastguard Worker #include "vk_util.h"
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker #include "nir_serialize.h"
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker #include "util/mesa-sha1.h"
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker bool
vk_pipeline_shader_stage_is_null(const VkPipelineShaderStageCreateInfo * info)45*61046927SAndroid Build Coastguard Worker vk_pipeline_shader_stage_is_null(const VkPipelineShaderStageCreateInfo *info)
46*61046927SAndroid Build Coastguard Worker {
47*61046927SAndroid Build Coastguard Worker    if (info->module != VK_NULL_HANDLE)
48*61046927SAndroid Build Coastguard Worker       return false;
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker    vk_foreach_struct_const(ext, info->pNext) {
51*61046927SAndroid Build Coastguard Worker       if (ext->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ||
52*61046927SAndroid Build Coastguard Worker           ext->sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT)
53*61046927SAndroid Build Coastguard Worker          return false;
54*61046927SAndroid Build Coastguard Worker    }
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker    return true;
57*61046927SAndroid Build Coastguard Worker }
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker bool
vk_pipeline_shader_stage_has_identifier(const VkPipelineShaderStageCreateInfo * info)60*61046927SAndroid Build Coastguard Worker vk_pipeline_shader_stage_has_identifier(const VkPipelineShaderStageCreateInfo *info)
61*61046927SAndroid Build Coastguard Worker {
62*61046927SAndroid Build Coastguard Worker    const VkPipelineShaderStageModuleIdentifierCreateInfoEXT *id_info =
63*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(info->pNext, PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT);
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    return id_info && id_info->identifierSize != 0;
66*61046927SAndroid Build Coastguard Worker }
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker static nir_shader *
get_builtin_nir(const VkPipelineShaderStageCreateInfo * info)69*61046927SAndroid Build Coastguard Worker get_builtin_nir(const VkPipelineShaderStageCreateInfo *info)
70*61046927SAndroid Build Coastguard Worker {
71*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_shader_module, module, info->module);
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker    nir_shader *nir = NULL;
74*61046927SAndroid Build Coastguard Worker    if (module != NULL) {
75*61046927SAndroid Build Coastguard Worker       nir = module->nir;
76*61046927SAndroid Build Coastguard Worker    } else {
77*61046927SAndroid Build Coastguard Worker       const VkPipelineShaderStageNirCreateInfoMESA *nir_info =
78*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(info->pNext, PIPELINE_SHADER_STAGE_NIR_CREATE_INFO_MESA);
79*61046927SAndroid Build Coastguard Worker       if (nir_info != NULL)
80*61046927SAndroid Build Coastguard Worker          nir = nir_info->nir;
81*61046927SAndroid Build Coastguard Worker    }
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker    if (nir == NULL)
84*61046927SAndroid Build Coastguard Worker       return NULL;
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker    assert(nir->info.stage == vk_to_mesa_shader_stage(info->stage));
87*61046927SAndroid Build Coastguard Worker    ASSERTED nir_function_impl *entrypoint = nir_shader_get_entrypoint(nir);
88*61046927SAndroid Build Coastguard Worker    assert(strcmp(entrypoint->function->name, info->pName) == 0);
89*61046927SAndroid Build Coastguard Worker    assert(info->pSpecializationInfo == NULL);
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    return nir;
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker static uint32_t
get_required_subgroup_size(const void * info_pNext)95*61046927SAndroid Build Coastguard Worker get_required_subgroup_size(const void *info_pNext)
96*61046927SAndroid Build Coastguard Worker {
97*61046927SAndroid Build Coastguard Worker    const VkPipelineShaderStageRequiredSubgroupSizeCreateInfo *rss_info =
98*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(info_pNext,
99*61046927SAndroid Build Coastguard Worker                            PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO);
100*61046927SAndroid Build Coastguard Worker    return rss_info != NULL ? rss_info->requiredSubgroupSize : 0;
101*61046927SAndroid Build Coastguard Worker }
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker enum gl_subgroup_size
vk_get_subgroup_size(uint32_t spirv_version,gl_shader_stage stage,const void * info_pNext,bool allow_varying,bool require_full)104*61046927SAndroid Build Coastguard Worker vk_get_subgroup_size(uint32_t spirv_version,
105*61046927SAndroid Build Coastguard Worker                      gl_shader_stage stage,
106*61046927SAndroid Build Coastguard Worker                      const void *info_pNext,
107*61046927SAndroid Build Coastguard Worker                      bool allow_varying,
108*61046927SAndroid Build Coastguard Worker                      bool require_full)
109*61046927SAndroid Build Coastguard Worker {
110*61046927SAndroid Build Coastguard Worker    uint32_t req_subgroup_size = get_required_subgroup_size(info_pNext);
111*61046927SAndroid Build Coastguard Worker    if (req_subgroup_size > 0) {
112*61046927SAndroid Build Coastguard Worker       assert(util_is_power_of_two_nonzero(req_subgroup_size));
113*61046927SAndroid Build Coastguard Worker       assert(req_subgroup_size >= 4 && req_subgroup_size <= 128);
114*61046927SAndroid Build Coastguard Worker       return req_subgroup_size;
115*61046927SAndroid Build Coastguard Worker    } else if (allow_varying || spirv_version >= 0x10600) {
116*61046927SAndroid Build Coastguard Worker       /* Starting with SPIR-V 1.6, varying subgroup size the default */
117*61046927SAndroid Build Coastguard Worker       return SUBGROUP_SIZE_VARYING;
118*61046927SAndroid Build Coastguard Worker    } else if (require_full) {
119*61046927SAndroid Build Coastguard Worker       assert(stage == MESA_SHADER_COMPUTE ||
120*61046927SAndroid Build Coastguard Worker              stage == MESA_SHADER_MESH ||
121*61046927SAndroid Build Coastguard Worker              stage == MESA_SHADER_TASK);
122*61046927SAndroid Build Coastguard Worker       return SUBGROUP_SIZE_FULL_SUBGROUPS;
123*61046927SAndroid Build Coastguard Worker    } else {
124*61046927SAndroid Build Coastguard Worker       return SUBGROUP_SIZE_API_CONSTANT;
125*61046927SAndroid Build Coastguard Worker    }
126*61046927SAndroid Build Coastguard Worker }
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker VkResult
vk_pipeline_shader_stage_to_nir(struct vk_device * device,VkPipelineCreateFlags2KHR pipeline_flags,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)129*61046927SAndroid Build Coastguard Worker vk_pipeline_shader_stage_to_nir(struct vk_device *device,
130*61046927SAndroid Build Coastguard Worker                                 VkPipelineCreateFlags2KHR pipeline_flags,
131*61046927SAndroid Build Coastguard Worker                                 const VkPipelineShaderStageCreateInfo *info,
132*61046927SAndroid Build Coastguard Worker                                 const struct spirv_to_nir_options *spirv_options,
133*61046927SAndroid Build Coastguard Worker                                 const struct nir_shader_compiler_options *nir_options,
134*61046927SAndroid Build Coastguard Worker                                 void *mem_ctx, nir_shader **nir_out)
135*61046927SAndroid Build Coastguard Worker {
136*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_shader_module, module, info->module);
137*61046927SAndroid Build Coastguard Worker    const gl_shader_stage stage = vk_to_mesa_shader_stage(info->stage);
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    assert(info->sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker    nir_shader *builtin_nir = get_builtin_nir(info);
142*61046927SAndroid Build Coastguard Worker    if (builtin_nir != NULL) {
143*61046927SAndroid Build Coastguard Worker       nir_validate_shader(builtin_nir, "internal shader");
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker       nir_shader *clone = nir_shader_clone(mem_ctx, builtin_nir);
146*61046927SAndroid Build Coastguard Worker       if (clone == NULL)
147*61046927SAndroid Build Coastguard Worker          return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
148*61046927SAndroid Build Coastguard Worker 
149*61046927SAndroid Build Coastguard Worker       assert(clone->options == NULL || clone->options == nir_options);
150*61046927SAndroid Build Coastguard Worker       clone->options = nir_options;
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker       *nir_out = clone;
153*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
154*61046927SAndroid Build Coastguard Worker    }
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    const uint32_t *spirv_data;
157*61046927SAndroid Build Coastguard Worker    uint32_t spirv_size;
158*61046927SAndroid Build Coastguard Worker    if (module != NULL) {
159*61046927SAndroid Build Coastguard Worker       spirv_data = (uint32_t *)module->data;
160*61046927SAndroid Build Coastguard Worker       spirv_size = module->size;
161*61046927SAndroid Build Coastguard Worker    } else {
162*61046927SAndroid Build Coastguard Worker       const VkShaderModuleCreateInfo *minfo =
163*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(info->pNext, SHADER_MODULE_CREATE_INFO);
164*61046927SAndroid Build Coastguard Worker       if (unlikely(minfo == NULL)) {
165*61046927SAndroid Build Coastguard Worker          return vk_errorf(device, VK_ERROR_UNKNOWN,
166*61046927SAndroid Build Coastguard Worker                           "No shader module provided");
167*61046927SAndroid Build Coastguard Worker       }
168*61046927SAndroid Build Coastguard Worker       spirv_data = minfo->pCode;
169*61046927SAndroid Build Coastguard Worker       spirv_size = minfo->codeSize;
170*61046927SAndroid Build Coastguard Worker    }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker    enum gl_subgroup_size subgroup_size = vk_get_subgroup_size(
173*61046927SAndroid Build Coastguard Worker       vk_spirv_version(spirv_data, spirv_size),
174*61046927SAndroid Build Coastguard Worker       stage, info->pNext,
175*61046927SAndroid Build Coastguard Worker       info->flags & VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT,
176*61046927SAndroid Build Coastguard Worker       info->flags & VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT);
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker    nir_shader *nir = vk_spirv_to_nir(device, spirv_data, spirv_size, stage,
179*61046927SAndroid Build Coastguard Worker                                      info->pName, subgroup_size,
180*61046927SAndroid Build Coastguard Worker                                      info->pSpecializationInfo,
181*61046927SAndroid Build Coastguard Worker                                      spirv_options, nir_options,
182*61046927SAndroid Build Coastguard Worker                                      false /* internal */,
183*61046927SAndroid Build Coastguard Worker                                      mem_ctx);
184*61046927SAndroid Build Coastguard Worker    if (nir == NULL)
185*61046927SAndroid Build Coastguard Worker       return vk_errorf(device, VK_ERROR_UNKNOWN, "spirv_to_nir failed");
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker    if (pipeline_flags & VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR)
188*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_view_index_to_device_index);
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker    *nir_out = nir;
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
193*61046927SAndroid Build Coastguard Worker }
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker void
vk_pipeline_hash_shader_stage(VkPipelineCreateFlags2KHR pipeline_flags,const VkPipelineShaderStageCreateInfo * info,const struct vk_pipeline_robustness_state * rstate,unsigned char * stage_sha1)196*61046927SAndroid Build Coastguard Worker vk_pipeline_hash_shader_stage(VkPipelineCreateFlags2KHR pipeline_flags,
197*61046927SAndroid Build Coastguard Worker                               const VkPipelineShaderStageCreateInfo *info,
198*61046927SAndroid Build Coastguard Worker                               const struct vk_pipeline_robustness_state *rstate,
199*61046927SAndroid Build Coastguard Worker                               unsigned char *stage_sha1)
200*61046927SAndroid Build Coastguard Worker {
201*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_shader_module, module, info->module);
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    const nir_shader *builtin_nir = get_builtin_nir(info);
204*61046927SAndroid Build Coastguard Worker    if (builtin_nir != NULL) {
205*61046927SAndroid Build Coastguard Worker       /* Internal NIR module: serialize and hash the NIR shader.
206*61046927SAndroid Build Coastguard Worker        * We don't need to hash other info fields since they should match the
207*61046927SAndroid Build Coastguard Worker        * NIR data.
208*61046927SAndroid Build Coastguard Worker        */
209*61046927SAndroid Build Coastguard Worker       struct blob blob;
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker       blob_init(&blob);
212*61046927SAndroid Build Coastguard Worker       nir_serialize(&blob, builtin_nir, false);
213*61046927SAndroid Build Coastguard Worker       assert(!blob.out_of_memory);
214*61046927SAndroid Build Coastguard Worker       _mesa_sha1_compute(blob.data, blob.size, stage_sha1);
215*61046927SAndroid Build Coastguard Worker       blob_finish(&blob);
216*61046927SAndroid Build Coastguard Worker       return;
217*61046927SAndroid Build Coastguard Worker    }
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    const VkShaderModuleCreateInfo *minfo =
220*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(info->pNext, SHADER_MODULE_CREATE_INFO);
221*61046927SAndroid Build Coastguard Worker    const VkPipelineShaderStageModuleIdentifierCreateInfoEXT *iinfo =
222*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(info->pNext, PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT);
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker    struct mesa_sha1 ctx;
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker    _mesa_sha1_init(&ctx);
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    /* We only care about one of the pipeline flags */
229*61046927SAndroid Build Coastguard Worker    pipeline_flags &= VK_PIPELINE_CREATE_2_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR;
230*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&ctx, &pipeline_flags, sizeof(pipeline_flags));
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&ctx, &info->flags, sizeof(info->flags));
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker    assert(util_bitcount(info->stage) == 1);
235*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&ctx, &info->stage, sizeof(info->stage));
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker    if (module) {
238*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, module->hash, sizeof(module->hash));
239*61046927SAndroid Build Coastguard Worker    } else if (minfo) {
240*61046927SAndroid Build Coastguard Worker       blake3_hash spirv_hash;
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker       _mesa_blake3_compute(minfo->pCode, minfo->codeSize, spirv_hash);
243*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, spirv_hash, sizeof(spirv_hash));
244*61046927SAndroid Build Coastguard Worker    } else {
245*61046927SAndroid Build Coastguard Worker       /* It is legal to pass in arbitrary identifiers as long as they don't exceed
246*61046927SAndroid Build Coastguard Worker        * the limit. Shaders with bogus identifiers are more or less guaranteed to fail. */
247*61046927SAndroid Build Coastguard Worker       assert(iinfo);
248*61046927SAndroid Build Coastguard Worker       assert(iinfo->identifierSize <= VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT);
249*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, iinfo->pIdentifier, iinfo->identifierSize);
250*61046927SAndroid Build Coastguard Worker    }
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker    if (rstate) {
253*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, &rstate->storage_buffers, sizeof(rstate->storage_buffers));
254*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, &rstate->uniform_buffers, sizeof(rstate->uniform_buffers));
255*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, &rstate->vertex_inputs, sizeof(rstate->vertex_inputs));
256*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, &rstate->images, sizeof(rstate->images));
257*61046927SAndroid Build Coastguard Worker    }
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&ctx, info->pName, strlen(info->pName));
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker    if (info->pSpecializationInfo) {
262*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, info->pSpecializationInfo->pMapEntries,
263*61046927SAndroid Build Coastguard Worker                         info->pSpecializationInfo->mapEntryCount *
264*61046927SAndroid Build Coastguard Worker                         sizeof(*info->pSpecializationInfo->pMapEntries));
265*61046927SAndroid Build Coastguard Worker       _mesa_sha1_update(&ctx, info->pSpecializationInfo->pData,
266*61046927SAndroid Build Coastguard Worker                         info->pSpecializationInfo->dataSize);
267*61046927SAndroid Build Coastguard Worker    }
268*61046927SAndroid Build Coastguard Worker 
269*61046927SAndroid Build Coastguard Worker    uint32_t req_subgroup_size = get_required_subgroup_size(info);
270*61046927SAndroid Build Coastguard Worker    _mesa_sha1_update(&ctx, &req_subgroup_size, sizeof(req_subgroup_size));
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    _mesa_sha1_final(&ctx, stage_sha1);
273*61046927SAndroid Build Coastguard Worker }
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker static VkPipelineRobustnessBufferBehaviorEXT
vk_device_default_robust_buffer_behavior(const struct vk_device * device)276*61046927SAndroid Build Coastguard Worker vk_device_default_robust_buffer_behavior(const struct vk_device *device)
277*61046927SAndroid Build Coastguard Worker {
278*61046927SAndroid Build Coastguard Worker    if (device->enabled_features.robustBufferAccess2) {
279*61046927SAndroid Build Coastguard Worker       return VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT;
280*61046927SAndroid Build Coastguard Worker    } else if (device->enabled_features.robustBufferAccess) {
281*61046927SAndroid Build Coastguard Worker       return VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT;
282*61046927SAndroid Build Coastguard Worker    } else {
283*61046927SAndroid Build Coastguard Worker       return VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT;
284*61046927SAndroid Build Coastguard Worker    }
285*61046927SAndroid Build Coastguard Worker }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker static VkPipelineRobustnessImageBehaviorEXT
vk_device_default_robust_image_behavior(const struct vk_device * device)288*61046927SAndroid Build Coastguard Worker vk_device_default_robust_image_behavior(const struct vk_device *device)
289*61046927SAndroid Build Coastguard Worker {
290*61046927SAndroid Build Coastguard Worker    if (device->enabled_features.robustImageAccess2) {
291*61046927SAndroid Build Coastguard Worker       return VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT;
292*61046927SAndroid Build Coastguard Worker    } else if (device->enabled_features.robustImageAccess) {
293*61046927SAndroid Build Coastguard Worker       return VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_EXT;
294*61046927SAndroid Build Coastguard Worker    } else {
295*61046927SAndroid Build Coastguard Worker       return VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT;
296*61046927SAndroid Build Coastguard Worker    }
297*61046927SAndroid Build Coastguard Worker }
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker void
vk_pipeline_robustness_state_fill(const struct vk_device * device,struct vk_pipeline_robustness_state * rs,const void * pipeline_pNext,const void * shader_stage_pNext)300*61046927SAndroid Build Coastguard Worker vk_pipeline_robustness_state_fill(const struct vk_device *device,
301*61046927SAndroid Build Coastguard Worker                                   struct vk_pipeline_robustness_state *rs,
302*61046927SAndroid Build Coastguard Worker                                   const void *pipeline_pNext,
303*61046927SAndroid Build Coastguard Worker                                   const void *shader_stage_pNext)
304*61046927SAndroid Build Coastguard Worker {
305*61046927SAndroid Build Coastguard Worker    rs->uniform_buffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT;
306*61046927SAndroid Build Coastguard Worker    rs->storage_buffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT;
307*61046927SAndroid Build Coastguard Worker    rs->vertex_inputs = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT;
308*61046927SAndroid Build Coastguard Worker    rs->images = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT;
309*61046927SAndroid Build Coastguard Worker    rs->null_uniform_buffer_descriptor = device->enabled_features.nullDescriptor;
310*61046927SAndroid Build Coastguard Worker    rs->null_storage_buffer_descriptor = device->enabled_features.nullDescriptor;
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker    const VkPipelineRobustnessCreateInfoEXT *shader_info =
313*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(shader_stage_pNext,
314*61046927SAndroid Build Coastguard Worker                            PIPELINE_ROBUSTNESS_CREATE_INFO_EXT);
315*61046927SAndroid Build Coastguard Worker    if (shader_info) {
316*61046927SAndroid Build Coastguard Worker       rs->storage_buffers = shader_info->storageBuffers;
317*61046927SAndroid Build Coastguard Worker       rs->uniform_buffers = shader_info->uniformBuffers;
318*61046927SAndroid Build Coastguard Worker       rs->vertex_inputs = shader_info->vertexInputs;
319*61046927SAndroid Build Coastguard Worker       rs->images = shader_info->images;
320*61046927SAndroid Build Coastguard Worker    } else {
321*61046927SAndroid Build Coastguard Worker       const VkPipelineRobustnessCreateInfoEXT *pipeline_info =
322*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(pipeline_pNext,
323*61046927SAndroid Build Coastguard Worker                               PIPELINE_ROBUSTNESS_CREATE_INFO_EXT);
324*61046927SAndroid Build Coastguard Worker       if (pipeline_info) {
325*61046927SAndroid Build Coastguard Worker          rs->storage_buffers = pipeline_info->storageBuffers;
326*61046927SAndroid Build Coastguard Worker          rs->uniform_buffers = pipeline_info->uniformBuffers;
327*61046927SAndroid Build Coastguard Worker          rs->vertex_inputs = pipeline_info->vertexInputs;
328*61046927SAndroid Build Coastguard Worker          rs->images = pipeline_info->images;
329*61046927SAndroid Build Coastguard Worker       }
330*61046927SAndroid Build Coastguard Worker    }
331*61046927SAndroid Build Coastguard Worker 
332*61046927SAndroid Build Coastguard Worker    if (rs->storage_buffers ==
333*61046927SAndroid Build Coastguard Worker        VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT)
334*61046927SAndroid Build Coastguard Worker       rs->storage_buffers = vk_device_default_robust_buffer_behavior(device);
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker    if (rs->uniform_buffers ==
337*61046927SAndroid Build Coastguard Worker        VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT)
338*61046927SAndroid Build Coastguard Worker       rs->uniform_buffers = vk_device_default_robust_buffer_behavior(device);
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker    if (rs->vertex_inputs ==
341*61046927SAndroid Build Coastguard Worker        VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT)
342*61046927SAndroid Build Coastguard Worker       rs->vertex_inputs = vk_device_default_robust_buffer_behavior(device);
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker    if (rs->images == VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT)
345*61046927SAndroid Build Coastguard Worker       rs->images = vk_device_default_robust_image_behavior(device);
346*61046927SAndroid Build Coastguard Worker }
347*61046927SAndroid Build Coastguard Worker 
348*61046927SAndroid Build Coastguard Worker void *
vk_pipeline_zalloc(struct vk_device * device,const struct vk_pipeline_ops * ops,VkPipelineBindPoint bind_point,VkPipelineCreateFlags2KHR flags,const VkAllocationCallbacks * alloc,size_t size)349*61046927SAndroid Build Coastguard Worker vk_pipeline_zalloc(struct vk_device *device,
350*61046927SAndroid Build Coastguard Worker                    const struct vk_pipeline_ops *ops,
351*61046927SAndroid Build Coastguard Worker                    VkPipelineBindPoint bind_point,
352*61046927SAndroid Build Coastguard Worker                    VkPipelineCreateFlags2KHR flags,
353*61046927SAndroid Build Coastguard Worker                    const VkAllocationCallbacks *alloc,
354*61046927SAndroid Build Coastguard Worker                    size_t size)
355*61046927SAndroid Build Coastguard Worker {
356*61046927SAndroid Build Coastguard Worker    struct vk_pipeline *pipeline;
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker    pipeline = vk_object_zalloc(device, alloc, size, VK_OBJECT_TYPE_PIPELINE);
359*61046927SAndroid Build Coastguard Worker    if (pipeline == NULL)
360*61046927SAndroid Build Coastguard Worker       return NULL;
361*61046927SAndroid Build Coastguard Worker 
362*61046927SAndroid Build Coastguard Worker    pipeline->ops = ops;
363*61046927SAndroid Build Coastguard Worker    pipeline->bind_point = bind_point;
364*61046927SAndroid Build Coastguard Worker    pipeline->flags = flags;
365*61046927SAndroid Build Coastguard Worker 
366*61046927SAndroid Build Coastguard Worker    return pipeline;
367*61046927SAndroid Build Coastguard Worker }
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker void
vk_pipeline_free(struct vk_device * device,const VkAllocationCallbacks * alloc,struct vk_pipeline * pipeline)370*61046927SAndroid Build Coastguard Worker vk_pipeline_free(struct vk_device *device,
371*61046927SAndroid Build Coastguard Worker                  const VkAllocationCallbacks *alloc,
372*61046927SAndroid Build Coastguard Worker                  struct vk_pipeline *pipeline)
373*61046927SAndroid Build Coastguard Worker {
374*61046927SAndroid Build Coastguard Worker    vk_object_free(device, alloc, &pipeline->base);
375*61046927SAndroid Build Coastguard Worker }
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyPipeline(VkDevice _device,VkPipeline _pipeline,const VkAllocationCallbacks * pAllocator)378*61046927SAndroid Build Coastguard Worker vk_common_DestroyPipeline(VkDevice _device,
379*61046927SAndroid Build Coastguard Worker                           VkPipeline _pipeline,
380*61046927SAndroid Build Coastguard Worker                           const VkAllocationCallbacks *pAllocator)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
383*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline, pipeline, _pipeline);
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker    if (pipeline == NULL)
386*61046927SAndroid Build Coastguard Worker       return;
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker    pipeline->ops->destroy(device, pipeline, pAllocator);
389*61046927SAndroid Build Coastguard Worker }
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_GetPipelineExecutablePropertiesKHR(VkDevice _device,const VkPipelineInfoKHR * pPipelineInfo,uint32_t * pExecutableCount,VkPipelineExecutablePropertiesKHR * pProperties)392*61046927SAndroid Build Coastguard Worker vk_common_GetPipelineExecutablePropertiesKHR(
393*61046927SAndroid Build Coastguard Worker    VkDevice _device,
394*61046927SAndroid Build Coastguard Worker    const VkPipelineInfoKHR *pPipelineInfo,
395*61046927SAndroid Build Coastguard Worker    uint32_t *pExecutableCount,
396*61046927SAndroid Build Coastguard Worker    VkPipelineExecutablePropertiesKHR *pProperties)
397*61046927SAndroid Build Coastguard Worker {
398*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
399*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline, pipeline, pPipelineInfo->pipeline);
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker    return pipeline->ops->get_executable_properties(device, pipeline,
402*61046927SAndroid Build Coastguard Worker                                                    pExecutableCount,
403*61046927SAndroid Build Coastguard Worker                                                    pProperties);
404*61046927SAndroid Build Coastguard Worker }
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_GetPipelineExecutableStatisticsKHR(VkDevice _device,const VkPipelineExecutableInfoKHR * pExecutableInfo,uint32_t * pStatisticCount,VkPipelineExecutableStatisticKHR * pStatistics)407*61046927SAndroid Build Coastguard Worker vk_common_GetPipelineExecutableStatisticsKHR(
408*61046927SAndroid Build Coastguard Worker     VkDevice _device,
409*61046927SAndroid Build Coastguard Worker     const VkPipelineExecutableInfoKHR *pExecutableInfo,
410*61046927SAndroid Build Coastguard Worker     uint32_t *pStatisticCount,
411*61046927SAndroid Build Coastguard Worker     VkPipelineExecutableStatisticKHR *pStatistics)
412*61046927SAndroid Build Coastguard Worker {
413*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
414*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline, pipeline, pExecutableInfo->pipeline);
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker    return pipeline->ops->get_executable_statistics(device, pipeline,
417*61046927SAndroid Build Coastguard Worker                                                    pExecutableInfo->executableIndex,
418*61046927SAndroid Build Coastguard Worker                                                    pStatisticCount, pStatistics);
419*61046927SAndroid Build Coastguard Worker }
420*61046927SAndroid Build Coastguard Worker 
421*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_GetPipelineExecutableInternalRepresentationsKHR(VkDevice _device,const VkPipelineExecutableInfoKHR * pExecutableInfo,uint32_t * pInternalRepresentationCount,VkPipelineExecutableInternalRepresentationKHR * pInternalRepresentations)422*61046927SAndroid Build Coastguard Worker vk_common_GetPipelineExecutableInternalRepresentationsKHR(
423*61046927SAndroid Build Coastguard Worker     VkDevice _device,
424*61046927SAndroid Build Coastguard Worker     const VkPipelineExecutableInfoKHR *pExecutableInfo,
425*61046927SAndroid Build Coastguard Worker     uint32_t *pInternalRepresentationCount,
426*61046927SAndroid Build Coastguard Worker     VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations)
427*61046927SAndroid Build Coastguard Worker {
428*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
429*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline, pipeline, pExecutableInfo->pipeline);
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    return pipeline->ops->get_internal_representations(device, pipeline,
432*61046927SAndroid Build Coastguard Worker                                                       pExecutableInfo->executableIndex,
433*61046927SAndroid Build Coastguard Worker                                                       pInternalRepresentationCount,
434*61046927SAndroid Build Coastguard Worker                                                       pInternalRepresentations);
435*61046927SAndroid Build Coastguard Worker }
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
vk_common_CmdBindPipeline(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,VkPipeline _pipeline)438*61046927SAndroid Build Coastguard Worker vk_common_CmdBindPipeline(VkCommandBuffer commandBuffer,
439*61046927SAndroid Build Coastguard Worker                           VkPipelineBindPoint pipelineBindPoint,
440*61046927SAndroid Build Coastguard Worker                           VkPipeline _pipeline)
441*61046927SAndroid Build Coastguard Worker {
442*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
443*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline, pipeline, _pipeline);
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker    assert(pipeline->bind_point == pipelineBindPoint);
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker    pipeline->ops->cmd_bind(cmd_buffer, pipeline);
448*61046927SAndroid Build Coastguard Worker }
449*61046927SAndroid Build Coastguard Worker 
450*61046927SAndroid Build Coastguard Worker static const struct vk_pipeline_cache_object_ops pipeline_shader_cache_ops;
451*61046927SAndroid Build Coastguard Worker 
452*61046927SAndroid Build Coastguard Worker static struct vk_shader *
vk_shader_from_cache_obj(struct vk_pipeline_cache_object * object)453*61046927SAndroid Build Coastguard Worker vk_shader_from_cache_obj(struct vk_pipeline_cache_object *object)
454*61046927SAndroid Build Coastguard Worker {
455*61046927SAndroid Build Coastguard Worker    assert(object->ops == &pipeline_shader_cache_ops);
456*61046927SAndroid Build Coastguard Worker    return container_of(object, struct vk_shader, pipeline.cache_obj);
457*61046927SAndroid Build Coastguard Worker }
458*61046927SAndroid Build Coastguard Worker 
459*61046927SAndroid Build Coastguard Worker static bool
vk_pipeline_shader_serialize(struct vk_pipeline_cache_object * object,struct blob * blob)460*61046927SAndroid Build Coastguard Worker vk_pipeline_shader_serialize(struct vk_pipeline_cache_object *object,
461*61046927SAndroid Build Coastguard Worker                              struct blob *blob)
462*61046927SAndroid Build Coastguard Worker {
463*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader = vk_shader_from_cache_obj(object);
464*61046927SAndroid Build Coastguard Worker    struct vk_device *device = shader->base.device;
465*61046927SAndroid Build Coastguard Worker 
466*61046927SAndroid Build Coastguard Worker    return shader->ops->serialize(device, shader, blob);
467*61046927SAndroid Build Coastguard Worker }
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker static void
vk_shader_init_cache_obj(struct vk_device * device,struct vk_shader * shader,const void * key_data,size_t key_size)470*61046927SAndroid Build Coastguard Worker vk_shader_init_cache_obj(struct vk_device *device, struct vk_shader *shader,
471*61046927SAndroid Build Coastguard Worker                          const void *key_data, size_t key_size)
472*61046927SAndroid Build Coastguard Worker {
473*61046927SAndroid Build Coastguard Worker    assert(key_size == sizeof(shader->pipeline.cache_key));
474*61046927SAndroid Build Coastguard Worker    memcpy(&shader->pipeline.cache_key, key_data,
475*61046927SAndroid Build Coastguard Worker           sizeof(shader->pipeline.cache_key));
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_init(device, &shader->pipeline.cache_obj,
478*61046927SAndroid Build Coastguard Worker                                  &pipeline_shader_cache_ops,
479*61046927SAndroid Build Coastguard Worker                                  &shader->pipeline.cache_key,
480*61046927SAndroid Build Coastguard Worker                                  sizeof(shader->pipeline.cache_key));
481*61046927SAndroid Build Coastguard Worker }
482*61046927SAndroid Build Coastguard Worker 
483*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_cache_object *
vk_pipeline_shader_deserialize(struct vk_pipeline_cache * cache,const void * key_data,size_t key_size,struct blob_reader * blob)484*61046927SAndroid Build Coastguard Worker vk_pipeline_shader_deserialize(struct vk_pipeline_cache *cache,
485*61046927SAndroid Build Coastguard Worker                                const void *key_data, size_t key_size,
486*61046927SAndroid Build Coastguard Worker                                struct blob_reader *blob)
487*61046927SAndroid Build Coastguard Worker {
488*61046927SAndroid Build Coastguard Worker    struct vk_device *device = cache->base.device;
489*61046927SAndroid Build Coastguard Worker    const struct vk_device_shader_ops *ops = device->shader_ops;
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker    /* TODO: Do we really want to always use the latest version? */
492*61046927SAndroid Build Coastguard Worker    const uint32_t version = device->physical->properties.shaderBinaryVersion;
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader;
495*61046927SAndroid Build Coastguard Worker    VkResult result = ops->deserialize(device, blob, version,
496*61046927SAndroid Build Coastguard Worker                                       &device->alloc, &shader);
497*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
498*61046927SAndroid Build Coastguard Worker       assert(result == VK_ERROR_OUT_OF_HOST_MEMORY);
499*61046927SAndroid Build Coastguard Worker       return NULL;
500*61046927SAndroid Build Coastguard Worker    }
501*61046927SAndroid Build Coastguard Worker 
502*61046927SAndroid Build Coastguard Worker    vk_shader_init_cache_obj(device, shader, key_data, key_size);
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker    return &shader->pipeline.cache_obj;
505*61046927SAndroid Build Coastguard Worker }
506*61046927SAndroid Build Coastguard Worker 
507*61046927SAndroid Build Coastguard Worker static void
vk_pipeline_shader_destroy(struct vk_device * device,struct vk_pipeline_cache_object * object)508*61046927SAndroid Build Coastguard Worker vk_pipeline_shader_destroy(struct vk_device *device,
509*61046927SAndroid Build Coastguard Worker                            struct vk_pipeline_cache_object *object)
510*61046927SAndroid Build Coastguard Worker {
511*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader = vk_shader_from_cache_obj(object);
512*61046927SAndroid Build Coastguard Worker    assert(shader->base.device == device);
513*61046927SAndroid Build Coastguard Worker 
514*61046927SAndroid Build Coastguard Worker    vk_shader_destroy(device, shader, &device->alloc);
515*61046927SAndroid Build Coastguard Worker }
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker static const struct vk_pipeline_cache_object_ops pipeline_shader_cache_ops = {
518*61046927SAndroid Build Coastguard Worker    .serialize = vk_pipeline_shader_serialize,
519*61046927SAndroid Build Coastguard Worker    .deserialize = vk_pipeline_shader_deserialize,
520*61046927SAndroid Build Coastguard Worker    .destroy = vk_pipeline_shader_destroy,
521*61046927SAndroid Build Coastguard Worker };
522*61046927SAndroid Build Coastguard Worker 
523*61046927SAndroid Build Coastguard Worker static struct vk_shader *
vk_shader_ref(struct vk_shader * shader)524*61046927SAndroid Build Coastguard Worker vk_shader_ref(struct vk_shader *shader)
525*61046927SAndroid Build Coastguard Worker {
526*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_ref(&shader->pipeline.cache_obj);
527*61046927SAndroid Build Coastguard Worker    return shader;
528*61046927SAndroid Build Coastguard Worker }
529*61046927SAndroid Build Coastguard Worker 
530*61046927SAndroid Build Coastguard Worker static void
vk_shader_unref(struct vk_device * device,struct vk_shader * shader)531*61046927SAndroid Build Coastguard Worker vk_shader_unref(struct vk_device *device, struct vk_shader *shader)
532*61046927SAndroid Build Coastguard Worker {
533*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_unref(device, &shader->pipeline.cache_obj);
534*61046927SAndroid Build Coastguard Worker }
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker PRAGMA_DIAGNOSTIC_PUSH
537*61046927SAndroid Build Coastguard Worker PRAGMA_DIAGNOSTIC_ERROR(-Wpadded)
538*61046927SAndroid Build Coastguard Worker struct vk_pipeline_tess_info {
539*61046927SAndroid Build Coastguard Worker    unsigned tcs_vertices_out : 8;
540*61046927SAndroid Build Coastguard Worker    unsigned primitive_mode : 2; /* tess_primitive_mode */
541*61046927SAndroid Build Coastguard Worker    unsigned spacing : 2; /* gl_tess_spacing */
542*61046927SAndroid Build Coastguard Worker    unsigned ccw : 1;
543*61046927SAndroid Build Coastguard Worker    unsigned point_mode : 1;
544*61046927SAndroid Build Coastguard Worker    unsigned _pad : 18;
545*61046927SAndroid Build Coastguard Worker };
546*61046927SAndroid Build Coastguard Worker PRAGMA_DIAGNOSTIC_POP
547*61046927SAndroid Build Coastguard Worker static_assert(sizeof(struct vk_pipeline_tess_info) == 4,
548*61046927SAndroid Build Coastguard Worker               "This struct has no holes");
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker static void
vk_pipeline_gather_nir_tess_info(const nir_shader * nir,struct vk_pipeline_tess_info * info)551*61046927SAndroid Build Coastguard Worker vk_pipeline_gather_nir_tess_info(const nir_shader *nir,
552*61046927SAndroid Build Coastguard Worker                                  struct vk_pipeline_tess_info *info)
553*61046927SAndroid Build Coastguard Worker {
554*61046927SAndroid Build Coastguard Worker    info->tcs_vertices_out  = nir->info.tess.tcs_vertices_out;
555*61046927SAndroid Build Coastguard Worker    info->primitive_mode    = nir->info.tess._primitive_mode;
556*61046927SAndroid Build Coastguard Worker    info->spacing           = nir->info.tess.spacing;
557*61046927SAndroid Build Coastguard Worker    info->ccw               = nir->info.tess.ccw;
558*61046927SAndroid Build Coastguard Worker    info->point_mode        = nir->info.tess.point_mode;
559*61046927SAndroid Build Coastguard Worker }
560*61046927SAndroid Build Coastguard Worker 
561*61046927SAndroid Build Coastguard Worker static void
vk_pipeline_replace_nir_tess_info(nir_shader * nir,const struct vk_pipeline_tess_info * info)562*61046927SAndroid Build Coastguard Worker vk_pipeline_replace_nir_tess_info(nir_shader *nir,
563*61046927SAndroid Build Coastguard Worker                                   const struct vk_pipeline_tess_info *info)
564*61046927SAndroid Build Coastguard Worker {
565*61046927SAndroid Build Coastguard Worker    nir->info.tess.tcs_vertices_out  = info->tcs_vertices_out;
566*61046927SAndroid Build Coastguard Worker    nir->info.tess._primitive_mode   = info->primitive_mode;
567*61046927SAndroid Build Coastguard Worker    nir->info.tess.spacing           = info->spacing;
568*61046927SAndroid Build Coastguard Worker    nir->info.tess.ccw               = info->ccw;
569*61046927SAndroid Build Coastguard Worker    nir->info.tess.point_mode        = info->point_mode;
570*61046927SAndroid Build Coastguard Worker }
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker static void
vk_pipeline_tess_info_merge(struct vk_pipeline_tess_info * dst,const struct vk_pipeline_tess_info * src)573*61046927SAndroid Build Coastguard Worker vk_pipeline_tess_info_merge(struct vk_pipeline_tess_info *dst,
574*61046927SAndroid Build Coastguard Worker                             const struct vk_pipeline_tess_info *src)
575*61046927SAndroid Build Coastguard Worker {
576*61046927SAndroid Build Coastguard Worker    /* The Vulkan 1.0.38 spec, section 21.1 Tessellator says:
577*61046927SAndroid Build Coastguard Worker     *
578*61046927SAndroid Build Coastguard Worker     *    "PointMode. Controls generation of points rather than triangles
579*61046927SAndroid Build Coastguard Worker     *     or lines. This functionality defaults to disabled, and is
580*61046927SAndroid Build Coastguard Worker     *     enabled if either shader stage includes the execution mode.
581*61046927SAndroid Build Coastguard Worker     *
582*61046927SAndroid Build Coastguard Worker     * and about Triangles, Quads, IsoLines, VertexOrderCw, VertexOrderCcw,
583*61046927SAndroid Build Coastguard Worker     * PointMode, SpacingEqual, SpacingFractionalEven, SpacingFractionalOdd,
584*61046927SAndroid Build Coastguard Worker     * and OutputVertices, it says:
585*61046927SAndroid Build Coastguard Worker     *
586*61046927SAndroid Build Coastguard Worker     *    "One mode must be set in at least one of the tessellation
587*61046927SAndroid Build Coastguard Worker     *     shader stages."
588*61046927SAndroid Build Coastguard Worker     *
589*61046927SAndroid Build Coastguard Worker     * So, the fields can be set in either the TCS or TES, but they must
590*61046927SAndroid Build Coastguard Worker     * agree if set in both.
591*61046927SAndroid Build Coastguard Worker     */
592*61046927SAndroid Build Coastguard Worker    assert(dst->tcs_vertices_out == 0 ||
593*61046927SAndroid Build Coastguard Worker           src->tcs_vertices_out == 0 ||
594*61046927SAndroid Build Coastguard Worker           dst->tcs_vertices_out == src->tcs_vertices_out);
595*61046927SAndroid Build Coastguard Worker    dst->tcs_vertices_out |= src->tcs_vertices_out;
596*61046927SAndroid Build Coastguard Worker 
597*61046927SAndroid Build Coastguard Worker    static_assert(TESS_SPACING_UNSPECIFIED == 0, "");
598*61046927SAndroid Build Coastguard Worker    assert(dst->spacing == TESS_SPACING_UNSPECIFIED ||
599*61046927SAndroid Build Coastguard Worker           src->spacing == TESS_SPACING_UNSPECIFIED ||
600*61046927SAndroid Build Coastguard Worker           dst->spacing == src->spacing);
601*61046927SAndroid Build Coastguard Worker    dst->spacing |= src->spacing;
602*61046927SAndroid Build Coastguard Worker 
603*61046927SAndroid Build Coastguard Worker    static_assert(TESS_PRIMITIVE_UNSPECIFIED == 0, "");
604*61046927SAndroid Build Coastguard Worker    assert(dst->primitive_mode == TESS_PRIMITIVE_UNSPECIFIED ||
605*61046927SAndroid Build Coastguard Worker           src->primitive_mode == TESS_PRIMITIVE_UNSPECIFIED ||
606*61046927SAndroid Build Coastguard Worker           dst->primitive_mode == src->primitive_mode);
607*61046927SAndroid Build Coastguard Worker    dst->primitive_mode |= src->primitive_mode;
608*61046927SAndroid Build Coastguard Worker    dst->ccw |= src->ccw;
609*61046927SAndroid Build Coastguard Worker    dst->point_mode |= src->point_mode;
610*61046927SAndroid Build Coastguard Worker }
611*61046927SAndroid Build Coastguard Worker 
612*61046927SAndroid Build Coastguard Worker struct vk_pipeline_precomp_shader {
613*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object cache_obj;
614*61046927SAndroid Build Coastguard Worker 
615*61046927SAndroid Build Coastguard Worker    /* Key for this cache_obj in the pipeline cache.
616*61046927SAndroid Build Coastguard Worker     *
617*61046927SAndroid Build Coastguard Worker     * This is always the output of vk_pipeline_hash_shader_stage() so it must
618*61046927SAndroid Build Coastguard Worker     * be a SHA1 hash.
619*61046927SAndroid Build Coastguard Worker     */
620*61046927SAndroid Build Coastguard Worker    uint8_t cache_key[SHA1_DIGEST_LENGTH];
621*61046927SAndroid Build Coastguard Worker 
622*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage;
623*61046927SAndroid Build Coastguard Worker 
624*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_robustness_state rs;
625*61046927SAndroid Build Coastguard Worker 
626*61046927SAndroid Build Coastguard Worker    /* Tessellation info if the shader is a tessellation shader */
627*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_tess_info tess;
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker    /* Hash of the vk_pipeline_precomp_shader
630*61046927SAndroid Build Coastguard Worker     *
631*61046927SAndroid Build Coastguard Worker     * This is the hash of the final compiled NIR together with tess info and
632*61046927SAndroid Build Coastguard Worker     * robustness state.  It's used as a key for final binary lookups.  By
633*61046927SAndroid Build Coastguard Worker     * having this as a separate key, we can de-duplicate cases where you have
634*61046927SAndroid Build Coastguard Worker     * different SPIR-V or specialization constants but end up compiling the
635*61046927SAndroid Build Coastguard Worker     * same NIR shader in the end anyway.
636*61046927SAndroid Build Coastguard Worker     */
637*61046927SAndroid Build Coastguard Worker    blake3_hash blake3;
638*61046927SAndroid Build Coastguard Worker 
639*61046927SAndroid Build Coastguard Worker    struct blob nir_blob;
640*61046927SAndroid Build Coastguard Worker };
641*61046927SAndroid Build Coastguard Worker 
642*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_precomp_shader *
vk_pipeline_precomp_shader_ref(struct vk_pipeline_precomp_shader * shader)643*61046927SAndroid Build Coastguard Worker vk_pipeline_precomp_shader_ref(struct vk_pipeline_precomp_shader *shader)
644*61046927SAndroid Build Coastguard Worker {
645*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_ref(&shader->cache_obj);
646*61046927SAndroid Build Coastguard Worker    return shader;
647*61046927SAndroid Build Coastguard Worker }
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker static void
vk_pipeline_precomp_shader_unref(struct vk_device * device,struct vk_pipeline_precomp_shader * shader)650*61046927SAndroid Build Coastguard Worker vk_pipeline_precomp_shader_unref(struct vk_device *device,
651*61046927SAndroid Build Coastguard Worker                                  struct vk_pipeline_precomp_shader *shader)
652*61046927SAndroid Build Coastguard Worker {
653*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_unref(device, &shader->cache_obj);
654*61046927SAndroid Build Coastguard Worker }
655*61046927SAndroid Build Coastguard Worker 
656*61046927SAndroid Build Coastguard Worker static const struct vk_pipeline_cache_object_ops pipeline_precomp_shader_cache_ops;
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_precomp_shader *
vk_pipeline_precomp_shader_from_cache_obj(struct vk_pipeline_cache_object * obj)659*61046927SAndroid Build Coastguard Worker vk_pipeline_precomp_shader_from_cache_obj(struct vk_pipeline_cache_object *obj)
660*61046927SAndroid Build Coastguard Worker {
661*61046927SAndroid Build Coastguard Worker    assert(obj->ops == & pipeline_precomp_shader_cache_ops);
662*61046927SAndroid Build Coastguard Worker    return container_of(obj, struct vk_pipeline_precomp_shader, cache_obj);
663*61046927SAndroid Build Coastguard Worker }
664*61046927SAndroid Build Coastguard Worker 
665*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_precomp_shader *
vk_pipeline_precomp_shader_create(struct vk_device * device,const void * key_data,size_t key_size,const struct vk_pipeline_robustness_state * rs,nir_shader * nir)666*61046927SAndroid Build Coastguard Worker vk_pipeline_precomp_shader_create(struct vk_device *device,
667*61046927SAndroid Build Coastguard Worker                                   const void *key_data, size_t key_size,
668*61046927SAndroid Build Coastguard Worker                                   const struct vk_pipeline_robustness_state *rs,
669*61046927SAndroid Build Coastguard Worker                                   nir_shader *nir)
670*61046927SAndroid Build Coastguard Worker {
671*61046927SAndroid Build Coastguard Worker    struct blob blob;
672*61046927SAndroid Build Coastguard Worker    blob_init(&blob);
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker    nir_serialize(&blob, nir, false);
675*61046927SAndroid Build Coastguard Worker 
676*61046927SAndroid Build Coastguard Worker    if (blob.out_of_memory)
677*61046927SAndroid Build Coastguard Worker       goto fail_blob;
678*61046927SAndroid Build Coastguard Worker 
679*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_precomp_shader *shader =
680*61046927SAndroid Build Coastguard Worker       vk_zalloc(&device->alloc, sizeof(*shader), 8,
681*61046927SAndroid Build Coastguard Worker                 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
682*61046927SAndroid Build Coastguard Worker    if (shader == NULL)
683*61046927SAndroid Build Coastguard Worker       goto fail_blob;
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker    assert(sizeof(shader->cache_key) == key_size);
686*61046927SAndroid Build Coastguard Worker    memcpy(shader->cache_key, key_data, sizeof(shader->cache_key));
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_init(device, &shader->cache_obj,
689*61046927SAndroid Build Coastguard Worker                                  &pipeline_precomp_shader_cache_ops,
690*61046927SAndroid Build Coastguard Worker                                  shader->cache_key,
691*61046927SAndroid Build Coastguard Worker                                  sizeof(shader->cache_key));
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker    shader->stage = nir->info.stage;
694*61046927SAndroid Build Coastguard Worker    shader->rs = *rs;
695*61046927SAndroid Build Coastguard Worker 
696*61046927SAndroid Build Coastguard Worker    vk_pipeline_gather_nir_tess_info(nir, &shader->tess);
697*61046927SAndroid Build Coastguard Worker 
698*61046927SAndroid Build Coastguard Worker    struct mesa_blake3 blake3_ctx;
699*61046927SAndroid Build Coastguard Worker    _mesa_blake3_init(&blake3_ctx);
700*61046927SAndroid Build Coastguard Worker    _mesa_blake3_update(&blake3_ctx, rs, sizeof(*rs));
701*61046927SAndroid Build Coastguard Worker    _mesa_blake3_update(&blake3_ctx, blob.data, blob.size);
702*61046927SAndroid Build Coastguard Worker    _mesa_blake3_final(&blake3_ctx, shader->blake3);
703*61046927SAndroid Build Coastguard Worker 
704*61046927SAndroid Build Coastguard Worker    shader->nir_blob = blob;
705*61046927SAndroid Build Coastguard Worker 
706*61046927SAndroid Build Coastguard Worker    return shader;
707*61046927SAndroid Build Coastguard Worker 
708*61046927SAndroid Build Coastguard Worker fail_blob:
709*61046927SAndroid Build Coastguard Worker    blob_finish(&blob);
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker    return NULL;
712*61046927SAndroid Build Coastguard Worker }
713*61046927SAndroid Build Coastguard Worker 
714*61046927SAndroid Build Coastguard Worker static bool
vk_pipeline_precomp_shader_serialize(struct vk_pipeline_cache_object * obj,struct blob * blob)715*61046927SAndroid Build Coastguard Worker vk_pipeline_precomp_shader_serialize(struct vk_pipeline_cache_object *obj,
716*61046927SAndroid Build Coastguard Worker                                      struct blob *blob)
717*61046927SAndroid Build Coastguard Worker {
718*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_precomp_shader *shader =
719*61046927SAndroid Build Coastguard Worker       vk_pipeline_precomp_shader_from_cache_obj(obj);
720*61046927SAndroid Build Coastguard Worker 
721*61046927SAndroid Build Coastguard Worker    blob_write_uint32(blob, shader->stage);
722*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, &shader->rs, sizeof(shader->rs));
723*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, &shader->tess, sizeof(shader->tess));
724*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, shader->blake3, sizeof(shader->blake3));
725*61046927SAndroid Build Coastguard Worker    blob_write_uint64(blob, shader->nir_blob.size);
726*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, shader->nir_blob.data, shader->nir_blob.size);
727*61046927SAndroid Build Coastguard Worker 
728*61046927SAndroid Build Coastguard Worker    return !blob->out_of_memory;
729*61046927SAndroid Build Coastguard Worker }
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_cache_object *
vk_pipeline_precomp_shader_deserialize(struct vk_pipeline_cache * cache,const void * key_data,size_t key_size,struct blob_reader * blob)732*61046927SAndroid Build Coastguard Worker vk_pipeline_precomp_shader_deserialize(struct vk_pipeline_cache *cache,
733*61046927SAndroid Build Coastguard Worker                                        const void *key_data, size_t key_size,
734*61046927SAndroid Build Coastguard Worker                                        struct blob_reader *blob)
735*61046927SAndroid Build Coastguard Worker {
736*61046927SAndroid Build Coastguard Worker    struct vk_device *device = cache->base.device;
737*61046927SAndroid Build Coastguard Worker 
738*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_precomp_shader *shader =
739*61046927SAndroid Build Coastguard Worker       vk_zalloc(&device->alloc, sizeof(*shader), 8,
740*61046927SAndroid Build Coastguard Worker                 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
741*61046927SAndroid Build Coastguard Worker    if (shader == NULL)
742*61046927SAndroid Build Coastguard Worker       return NULL;
743*61046927SAndroid Build Coastguard Worker 
744*61046927SAndroid Build Coastguard Worker    assert(sizeof(shader->cache_key) == key_size);
745*61046927SAndroid Build Coastguard Worker    memcpy(shader->cache_key, key_data, sizeof(shader->cache_key));
746*61046927SAndroid Build Coastguard Worker 
747*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_init(device, &shader->cache_obj,
748*61046927SAndroid Build Coastguard Worker                                  &pipeline_precomp_shader_cache_ops,
749*61046927SAndroid Build Coastguard Worker                                  shader->cache_key,
750*61046927SAndroid Build Coastguard Worker                                  sizeof(shader->cache_key));
751*61046927SAndroid Build Coastguard Worker 
752*61046927SAndroid Build Coastguard Worker    shader->stage = blob_read_uint32(blob);
753*61046927SAndroid Build Coastguard Worker    blob_copy_bytes(blob, &shader->rs, sizeof(shader->rs));
754*61046927SAndroid Build Coastguard Worker    blob_copy_bytes(blob, &shader->tess, sizeof(shader->tess));
755*61046927SAndroid Build Coastguard Worker    blob_copy_bytes(blob, shader->blake3, sizeof(shader->blake3));
756*61046927SAndroid Build Coastguard Worker 
757*61046927SAndroid Build Coastguard Worker    uint64_t nir_size = blob_read_uint64(blob);
758*61046927SAndroid Build Coastguard Worker    if (blob->overrun || nir_size > SIZE_MAX)
759*61046927SAndroid Build Coastguard Worker       goto fail_shader;
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker    const void *nir_data = blob_read_bytes(blob, nir_size);
762*61046927SAndroid Build Coastguard Worker    if (blob->overrun)
763*61046927SAndroid Build Coastguard Worker       goto fail_shader;
764*61046927SAndroid Build Coastguard Worker 
765*61046927SAndroid Build Coastguard Worker    blob_init(&shader->nir_blob);
766*61046927SAndroid Build Coastguard Worker    blob_write_bytes(&shader->nir_blob, nir_data, nir_size);
767*61046927SAndroid Build Coastguard Worker    if (shader->nir_blob.out_of_memory)
768*61046927SAndroid Build Coastguard Worker       goto fail_nir_blob;
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker    return &shader->cache_obj;
771*61046927SAndroid Build Coastguard Worker 
772*61046927SAndroid Build Coastguard Worker fail_nir_blob:
773*61046927SAndroid Build Coastguard Worker    blob_finish(&shader->nir_blob);
774*61046927SAndroid Build Coastguard Worker fail_shader:
775*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_finish(&shader->cache_obj);
776*61046927SAndroid Build Coastguard Worker    vk_free(&device->alloc, shader);
777*61046927SAndroid Build Coastguard Worker 
778*61046927SAndroid Build Coastguard Worker    return NULL;
779*61046927SAndroid Build Coastguard Worker }
780*61046927SAndroid Build Coastguard Worker 
781*61046927SAndroid Build Coastguard Worker static void
vk_pipeline_precomp_shader_destroy(struct vk_device * device,struct vk_pipeline_cache_object * obj)782*61046927SAndroid Build Coastguard Worker vk_pipeline_precomp_shader_destroy(struct vk_device *device,
783*61046927SAndroid Build Coastguard Worker                                    struct vk_pipeline_cache_object *obj)
784*61046927SAndroid Build Coastguard Worker {
785*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_precomp_shader *shader =
786*61046927SAndroid Build Coastguard Worker       vk_pipeline_precomp_shader_from_cache_obj(obj);
787*61046927SAndroid Build Coastguard Worker 
788*61046927SAndroid Build Coastguard Worker    blob_finish(&shader->nir_blob);
789*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_finish(&shader->cache_obj);
790*61046927SAndroid Build Coastguard Worker    vk_free(&device->alloc, shader);
791*61046927SAndroid Build Coastguard Worker }
792*61046927SAndroid Build Coastguard Worker 
793*61046927SAndroid Build Coastguard Worker static nir_shader *
vk_pipeline_precomp_shader_get_nir(const struct vk_pipeline_precomp_shader * shader,const struct nir_shader_compiler_options * nir_options)794*61046927SAndroid Build Coastguard Worker vk_pipeline_precomp_shader_get_nir(const struct vk_pipeline_precomp_shader *shader,
795*61046927SAndroid Build Coastguard Worker                                    const struct nir_shader_compiler_options *nir_options)
796*61046927SAndroid Build Coastguard Worker {
797*61046927SAndroid Build Coastguard Worker    struct blob_reader blob;
798*61046927SAndroid Build Coastguard Worker    blob_reader_init(&blob, shader->nir_blob.data, shader->nir_blob.size);
799*61046927SAndroid Build Coastguard Worker 
800*61046927SAndroid Build Coastguard Worker    nir_shader *nir = nir_deserialize(NULL, nir_options, &blob);
801*61046927SAndroid Build Coastguard Worker    if (blob.overrun) {
802*61046927SAndroid Build Coastguard Worker       ralloc_free(nir);
803*61046927SAndroid Build Coastguard Worker       return NULL;
804*61046927SAndroid Build Coastguard Worker    }
805*61046927SAndroid Build Coastguard Worker 
806*61046927SAndroid Build Coastguard Worker    return nir;
807*61046927SAndroid Build Coastguard Worker }
808*61046927SAndroid Build Coastguard Worker 
809*61046927SAndroid Build Coastguard Worker static const struct vk_pipeline_cache_object_ops pipeline_precomp_shader_cache_ops = {
810*61046927SAndroid Build Coastguard Worker    .serialize = vk_pipeline_precomp_shader_serialize,
811*61046927SAndroid Build Coastguard Worker    .deserialize = vk_pipeline_precomp_shader_deserialize,
812*61046927SAndroid Build Coastguard Worker    .destroy = vk_pipeline_precomp_shader_destroy,
813*61046927SAndroid Build Coastguard Worker };
814*61046927SAndroid Build Coastguard Worker 
815*61046927SAndroid Build Coastguard Worker static VkResult
vk_pipeline_precompile_shader(struct vk_device * device,struct vk_pipeline_cache * cache,VkPipelineCreateFlags2KHR pipeline_flags,const void * pipeline_info_pNext,const VkPipelineShaderStageCreateInfo * info,struct vk_pipeline_precomp_shader ** ps_out)816*61046927SAndroid Build Coastguard Worker vk_pipeline_precompile_shader(struct vk_device *device,
817*61046927SAndroid Build Coastguard Worker                               struct vk_pipeline_cache *cache,
818*61046927SAndroid Build Coastguard Worker                               VkPipelineCreateFlags2KHR pipeline_flags,
819*61046927SAndroid Build Coastguard Worker                               const void *pipeline_info_pNext,
820*61046927SAndroid Build Coastguard Worker                               const VkPipelineShaderStageCreateInfo *info,
821*61046927SAndroid Build Coastguard Worker                               struct vk_pipeline_precomp_shader **ps_out)
822*61046927SAndroid Build Coastguard Worker {
823*61046927SAndroid Build Coastguard Worker    const struct vk_device_shader_ops *ops = device->shader_ops;
824*61046927SAndroid Build Coastguard Worker    VkResult result;
825*61046927SAndroid Build Coastguard Worker 
826*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_robustness_state rs;
827*61046927SAndroid Build Coastguard Worker    vk_pipeline_robustness_state_fill(device, &rs,
828*61046927SAndroid Build Coastguard Worker                                      pipeline_info_pNext,
829*61046927SAndroid Build Coastguard Worker                                      info->pNext);
830*61046927SAndroid Build Coastguard Worker 
831*61046927SAndroid Build Coastguard Worker    uint8_t stage_sha1[SHA1_DIGEST_LENGTH];
832*61046927SAndroid Build Coastguard Worker    vk_pipeline_hash_shader_stage(pipeline_flags, info, &rs, stage_sha1);
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker    if (cache != NULL) {
835*61046927SAndroid Build Coastguard Worker       struct vk_pipeline_cache_object *cache_obj =
836*61046927SAndroid Build Coastguard Worker          vk_pipeline_cache_lookup_object(cache, stage_sha1, sizeof(stage_sha1),
837*61046927SAndroid Build Coastguard Worker                                          &pipeline_precomp_shader_cache_ops,
838*61046927SAndroid Build Coastguard Worker                                          NULL /* cache_hit */);
839*61046927SAndroid Build Coastguard Worker       if (cache_obj != NULL) {
840*61046927SAndroid Build Coastguard Worker          *ps_out = vk_pipeline_precomp_shader_from_cache_obj(cache_obj);
841*61046927SAndroid Build Coastguard Worker          return VK_SUCCESS;
842*61046927SAndroid Build Coastguard Worker       }
843*61046927SAndroid Build Coastguard Worker    }
844*61046927SAndroid Build Coastguard Worker 
845*61046927SAndroid Build Coastguard Worker    if (pipeline_flags &
846*61046927SAndroid Build Coastguard Worker        VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR)
847*61046927SAndroid Build Coastguard Worker       return VK_PIPELINE_COMPILE_REQUIRED;
848*61046927SAndroid Build Coastguard Worker 
849*61046927SAndroid Build Coastguard Worker    const gl_shader_stage stage = vk_to_mesa_shader_stage(info->stage);
850*61046927SAndroid Build Coastguard Worker    const struct nir_shader_compiler_options *nir_options =
851*61046927SAndroid Build Coastguard Worker       ops->get_nir_options(device->physical, stage, &rs);
852*61046927SAndroid Build Coastguard Worker    const struct spirv_to_nir_options spirv_options =
853*61046927SAndroid Build Coastguard Worker       ops->get_spirv_options(device->physical, stage, &rs);
854*61046927SAndroid Build Coastguard Worker 
855*61046927SAndroid Build Coastguard Worker    nir_shader *nir;
856*61046927SAndroid Build Coastguard Worker    result = vk_pipeline_shader_stage_to_nir(device, pipeline_flags, info,
857*61046927SAndroid Build Coastguard Worker                                             &spirv_options, nir_options,
858*61046927SAndroid Build Coastguard Worker                                             NULL, &nir);
859*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
860*61046927SAndroid Build Coastguard Worker       return result;
861*61046927SAndroid Build Coastguard Worker 
862*61046927SAndroid Build Coastguard Worker    if (ops->preprocess_nir != NULL)
863*61046927SAndroid Build Coastguard Worker       ops->preprocess_nir(device->physical, nir);
864*61046927SAndroid Build Coastguard Worker 
865*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_precomp_shader *shader =
866*61046927SAndroid Build Coastguard Worker       vk_pipeline_precomp_shader_create(device, stage_sha1,
867*61046927SAndroid Build Coastguard Worker                                         sizeof(stage_sha1),
868*61046927SAndroid Build Coastguard Worker                                         &rs, nir);
869*61046927SAndroid Build Coastguard Worker    ralloc_free(nir);
870*61046927SAndroid Build Coastguard Worker    if (shader == NULL)
871*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
872*61046927SAndroid Build Coastguard Worker 
873*61046927SAndroid Build Coastguard Worker    if (cache != NULL) {
874*61046927SAndroid Build Coastguard Worker       struct vk_pipeline_cache_object *cache_obj = &shader->cache_obj;
875*61046927SAndroid Build Coastguard Worker       cache_obj = vk_pipeline_cache_add_object(cache, cache_obj);
876*61046927SAndroid Build Coastguard Worker       shader = vk_pipeline_precomp_shader_from_cache_obj(cache_obj);
877*61046927SAndroid Build Coastguard Worker    }
878*61046927SAndroid Build Coastguard Worker 
879*61046927SAndroid Build Coastguard Worker    *ps_out = shader;
880*61046927SAndroid Build Coastguard Worker 
881*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
882*61046927SAndroid Build Coastguard Worker }
883*61046927SAndroid Build Coastguard Worker 
884*61046927SAndroid Build Coastguard Worker struct vk_pipeline_stage {
885*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage;
886*61046927SAndroid Build Coastguard Worker 
887*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_precomp_shader *precomp;
888*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader;
889*61046927SAndroid Build Coastguard Worker };
890*61046927SAndroid Build Coastguard Worker 
891*61046927SAndroid Build Coastguard Worker static int
cmp_vk_pipeline_stages(const void * _a,const void * _b)892*61046927SAndroid Build Coastguard Worker cmp_vk_pipeline_stages(const void *_a, const void *_b)
893*61046927SAndroid Build Coastguard Worker {
894*61046927SAndroid Build Coastguard Worker    const struct vk_pipeline_stage *a = _a, *b = _b;
895*61046927SAndroid Build Coastguard Worker    return vk_shader_cmp_graphics_stages(a->stage, b->stage);
896*61046927SAndroid Build Coastguard Worker }
897*61046927SAndroid Build Coastguard Worker 
898*61046927SAndroid Build Coastguard Worker static bool
vk_pipeline_stage_is_null(const struct vk_pipeline_stage * stage)899*61046927SAndroid Build Coastguard Worker vk_pipeline_stage_is_null(const struct vk_pipeline_stage *stage)
900*61046927SAndroid Build Coastguard Worker {
901*61046927SAndroid Build Coastguard Worker    return stage->precomp == NULL && stage->shader == NULL;
902*61046927SAndroid Build Coastguard Worker }
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker static void
vk_pipeline_stage_finish(struct vk_device * device,struct vk_pipeline_stage * stage)905*61046927SAndroid Build Coastguard Worker vk_pipeline_stage_finish(struct vk_device *device,
906*61046927SAndroid Build Coastguard Worker                          struct vk_pipeline_stage *stage)
907*61046927SAndroid Build Coastguard Worker {
908*61046927SAndroid Build Coastguard Worker    if (stage->precomp != NULL)
909*61046927SAndroid Build Coastguard Worker       vk_pipeline_precomp_shader_unref(device, stage->precomp);
910*61046927SAndroid Build Coastguard Worker 
911*61046927SAndroid Build Coastguard Worker    if (stage->shader)
912*61046927SAndroid Build Coastguard Worker       vk_shader_unref(device, stage->shader);
913*61046927SAndroid Build Coastguard Worker }
914*61046927SAndroid Build Coastguard Worker 
915*61046927SAndroid Build Coastguard Worker static struct vk_pipeline_stage
vk_pipeline_stage_clone(const struct vk_pipeline_stage * in)916*61046927SAndroid Build Coastguard Worker vk_pipeline_stage_clone(const struct vk_pipeline_stage *in)
917*61046927SAndroid Build Coastguard Worker {
918*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_stage out = {
919*61046927SAndroid Build Coastguard Worker       .stage = in->stage,
920*61046927SAndroid Build Coastguard Worker    };
921*61046927SAndroid Build Coastguard Worker 
922*61046927SAndroid Build Coastguard Worker    if (in->precomp)
923*61046927SAndroid Build Coastguard Worker       out.precomp = vk_pipeline_precomp_shader_ref(in->precomp);
924*61046927SAndroid Build Coastguard Worker 
925*61046927SAndroid Build Coastguard Worker    if (in->shader)
926*61046927SAndroid Build Coastguard Worker       out.shader = vk_shader_ref(in->shader);
927*61046927SAndroid Build Coastguard Worker 
928*61046927SAndroid Build Coastguard Worker    return out;
929*61046927SAndroid Build Coastguard Worker }
930*61046927SAndroid Build Coastguard Worker 
931*61046927SAndroid Build Coastguard Worker struct vk_graphics_pipeline {
932*61046927SAndroid Build Coastguard Worker    struct vk_pipeline base;
933*61046927SAndroid Build Coastguard Worker 
934*61046927SAndroid Build Coastguard Worker    union {
935*61046927SAndroid Build Coastguard Worker       struct {
936*61046927SAndroid Build Coastguard Worker          struct vk_graphics_pipeline_all_state all_state;
937*61046927SAndroid Build Coastguard Worker          struct vk_graphics_pipeline_state state;
938*61046927SAndroid Build Coastguard Worker       } lib;
939*61046927SAndroid Build Coastguard Worker 
940*61046927SAndroid Build Coastguard Worker       struct {
941*61046927SAndroid Build Coastguard Worker          struct vk_vertex_input_state _dynamic_vi;
942*61046927SAndroid Build Coastguard Worker          struct vk_sample_locations_state _dynamic_sl;
943*61046927SAndroid Build Coastguard Worker          struct vk_dynamic_graphics_state dynamic;
944*61046927SAndroid Build Coastguard Worker       } linked;
945*61046927SAndroid Build Coastguard Worker    };
946*61046927SAndroid Build Coastguard Worker 
947*61046927SAndroid Build Coastguard Worker    uint32_t set_layout_count;
948*61046927SAndroid Build Coastguard Worker    struct vk_descriptor_set_layout *set_layouts[MESA_VK_MAX_DESCRIPTOR_SETS];
949*61046927SAndroid Build Coastguard Worker 
950*61046927SAndroid Build Coastguard Worker    uint32_t stage_count;
951*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_stage stages[MESA_VK_MAX_GRAPHICS_PIPELINE_STAGES];
952*61046927SAndroid Build Coastguard Worker };
953*61046927SAndroid Build Coastguard Worker 
954*61046927SAndroid Build Coastguard Worker static void
vk_graphics_pipeline_destroy(struct vk_device * device,struct vk_pipeline * pipeline,const VkAllocationCallbacks * pAllocator)955*61046927SAndroid Build Coastguard Worker vk_graphics_pipeline_destroy(struct vk_device *device,
956*61046927SAndroid Build Coastguard Worker                              struct vk_pipeline *pipeline,
957*61046927SAndroid Build Coastguard Worker                              const VkAllocationCallbacks *pAllocator)
958*61046927SAndroid Build Coastguard Worker {
959*61046927SAndroid Build Coastguard Worker    struct vk_graphics_pipeline *gfx_pipeline =
960*61046927SAndroid Build Coastguard Worker       container_of(pipeline, struct vk_graphics_pipeline, base);
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < gfx_pipeline->stage_count; i++)
963*61046927SAndroid Build Coastguard Worker       vk_pipeline_stage_finish(device, &gfx_pipeline->stages[i]);
964*61046927SAndroid Build Coastguard Worker 
965*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < gfx_pipeline->set_layout_count; i++) {
966*61046927SAndroid Build Coastguard Worker       if (gfx_pipeline->set_layouts[i] != NULL)
967*61046927SAndroid Build Coastguard Worker          vk_descriptor_set_layout_unref(device, gfx_pipeline->set_layouts[i]);
968*61046927SAndroid Build Coastguard Worker    }
969*61046927SAndroid Build Coastguard Worker 
970*61046927SAndroid Build Coastguard Worker    vk_pipeline_free(device, pAllocator, pipeline);
971*61046927SAndroid Build Coastguard Worker }
972*61046927SAndroid Build Coastguard Worker 
973*61046927SAndroid Build Coastguard Worker static bool
vk_device_supports_stage(struct vk_device * device,gl_shader_stage stage)974*61046927SAndroid Build Coastguard Worker vk_device_supports_stage(struct vk_device *device,
975*61046927SAndroid Build Coastguard Worker                          gl_shader_stage stage)
976*61046927SAndroid Build Coastguard Worker {
977*61046927SAndroid Build Coastguard Worker    const struct vk_features *features = &device->physical->supported_features;
978*61046927SAndroid Build Coastguard Worker 
979*61046927SAndroid Build Coastguard Worker    switch (stage) {
980*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_VERTEX:
981*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_FRAGMENT:
982*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_COMPUTE:
983*61046927SAndroid Build Coastguard Worker       return true;
984*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_CTRL:
985*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_EVAL:
986*61046927SAndroid Build Coastguard Worker       return features->tessellationShader;
987*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_GEOMETRY:
988*61046927SAndroid Build Coastguard Worker       return features->geometryShader;
989*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TASK:
990*61046927SAndroid Build Coastguard Worker       return features->taskShader;
991*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_MESH:
992*61046927SAndroid Build Coastguard Worker       return features->meshShader;
993*61046927SAndroid Build Coastguard Worker    default:
994*61046927SAndroid Build Coastguard Worker       return false;
995*61046927SAndroid Build Coastguard Worker    }
996*61046927SAndroid Build Coastguard Worker }
997*61046927SAndroid Build Coastguard Worker 
998*61046927SAndroid Build Coastguard Worker static const gl_shader_stage all_gfx_stages[] = {
999*61046927SAndroid Build Coastguard Worker    MESA_SHADER_VERTEX,
1000*61046927SAndroid Build Coastguard Worker    MESA_SHADER_TESS_CTRL,
1001*61046927SAndroid Build Coastguard Worker    MESA_SHADER_TESS_EVAL,
1002*61046927SAndroid Build Coastguard Worker    MESA_SHADER_GEOMETRY,
1003*61046927SAndroid Build Coastguard Worker    MESA_SHADER_TASK,
1004*61046927SAndroid Build Coastguard Worker    MESA_SHADER_MESH,
1005*61046927SAndroid Build Coastguard Worker    MESA_SHADER_FRAGMENT,
1006*61046927SAndroid Build Coastguard Worker };
1007*61046927SAndroid Build Coastguard Worker 
1008*61046927SAndroid Build Coastguard Worker static void
vk_graphics_pipeline_cmd_bind(struct vk_command_buffer * cmd_buffer,struct vk_pipeline * pipeline)1009*61046927SAndroid Build Coastguard Worker vk_graphics_pipeline_cmd_bind(struct vk_command_buffer *cmd_buffer,
1010*61046927SAndroid Build Coastguard Worker                               struct vk_pipeline *pipeline)
1011*61046927SAndroid Build Coastguard Worker {
1012*61046927SAndroid Build Coastguard Worker    struct vk_device *device = cmd_buffer->base.device;
1013*61046927SAndroid Build Coastguard Worker    const struct vk_device_shader_ops *ops = device->shader_ops;
1014*61046927SAndroid Build Coastguard Worker 
1015*61046927SAndroid Build Coastguard Worker    struct vk_graphics_pipeline *gfx_pipeline = NULL;
1016*61046927SAndroid Build Coastguard Worker    struct vk_shader *stage_shader[PIPE_SHADER_MESH_TYPES] = { NULL, };
1017*61046927SAndroid Build Coastguard Worker    if (pipeline != NULL) {
1018*61046927SAndroid Build Coastguard Worker       assert(pipeline->bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);
1019*61046927SAndroid Build Coastguard Worker       assert(!(pipeline->flags & VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR));
1020*61046927SAndroid Build Coastguard Worker       gfx_pipeline = container_of(pipeline, struct vk_graphics_pipeline, base);
1021*61046927SAndroid Build Coastguard Worker 
1022*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < gfx_pipeline->stage_count; i++) {
1023*61046927SAndroid Build Coastguard Worker          struct vk_shader *shader = gfx_pipeline->stages[i].shader;
1024*61046927SAndroid Build Coastguard Worker          stage_shader[shader->stage] = shader;
1025*61046927SAndroid Build Coastguard Worker       }
1026*61046927SAndroid Build Coastguard Worker    }
1027*61046927SAndroid Build Coastguard Worker 
1028*61046927SAndroid Build Coastguard Worker    uint32_t stage_count = 0;
1029*61046927SAndroid Build Coastguard Worker    gl_shader_stage stages[ARRAY_SIZE(all_gfx_stages)];
1030*61046927SAndroid Build Coastguard Worker    struct vk_shader *shaders[ARRAY_SIZE(all_gfx_stages)];
1031*61046927SAndroid Build Coastguard Worker 
1032*61046927SAndroid Build Coastguard Worker    VkShaderStageFlags vk_stages = 0;
1033*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < ARRAY_SIZE(all_gfx_stages); i++) {
1034*61046927SAndroid Build Coastguard Worker       gl_shader_stage stage = all_gfx_stages[i];
1035*61046927SAndroid Build Coastguard Worker       if (!vk_device_supports_stage(device, stage)) {
1036*61046927SAndroid Build Coastguard Worker          assert(stage_shader[stage] == NULL);
1037*61046927SAndroid Build Coastguard Worker          continue;
1038*61046927SAndroid Build Coastguard Worker       }
1039*61046927SAndroid Build Coastguard Worker 
1040*61046927SAndroid Build Coastguard Worker       vk_stages |= mesa_to_vk_shader_stage(stage);
1041*61046927SAndroid Build Coastguard Worker 
1042*61046927SAndroid Build Coastguard Worker       stages[stage_count] = stage;
1043*61046927SAndroid Build Coastguard Worker       shaders[stage_count] = stage_shader[stage];
1044*61046927SAndroid Build Coastguard Worker       stage_count++;
1045*61046927SAndroid Build Coastguard Worker    }
1046*61046927SAndroid Build Coastguard Worker    ops->cmd_bind_shaders(cmd_buffer, stage_count, stages, shaders);
1047*61046927SAndroid Build Coastguard Worker 
1048*61046927SAndroid Build Coastguard Worker    if (gfx_pipeline != NULL) {
1049*61046927SAndroid Build Coastguard Worker       cmd_buffer->pipeline_shader_stages |= vk_stages;
1050*61046927SAndroid Build Coastguard Worker       ops->cmd_set_dynamic_graphics_state(cmd_buffer,
1051*61046927SAndroid Build Coastguard Worker                                           &gfx_pipeline->linked.dynamic);
1052*61046927SAndroid Build Coastguard Worker    } else {
1053*61046927SAndroid Build Coastguard Worker       cmd_buffer->pipeline_shader_stages &= ~vk_stages;
1054*61046927SAndroid Build Coastguard Worker    }
1055*61046927SAndroid Build Coastguard Worker }
1056*61046927SAndroid Build Coastguard Worker 
1057*61046927SAndroid Build Coastguard Worker static VkShaderCreateFlagsEXT
vk_pipeline_to_shader_flags(VkPipelineCreateFlags2KHR pipeline_flags,gl_shader_stage stage)1058*61046927SAndroid Build Coastguard Worker vk_pipeline_to_shader_flags(VkPipelineCreateFlags2KHR pipeline_flags,
1059*61046927SAndroid Build Coastguard Worker                             gl_shader_stage stage)
1060*61046927SAndroid Build Coastguard Worker {
1061*61046927SAndroid Build Coastguard Worker    VkShaderCreateFlagsEXT shader_flags = 0;
1062*61046927SAndroid Build Coastguard Worker 
1063*61046927SAndroid Build Coastguard Worker    if (pipeline_flags & VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR)
1064*61046927SAndroid Build Coastguard Worker       shader_flags |= VK_SHADER_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_MESA;
1065*61046927SAndroid Build Coastguard Worker 
1066*61046927SAndroid Build Coastguard Worker    if (stage == MESA_SHADER_FRAGMENT) {
1067*61046927SAndroid Build Coastguard Worker       if (pipeline_flags & VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR)
1068*61046927SAndroid Build Coastguard Worker          shader_flags |= VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT;
1069*61046927SAndroid Build Coastguard Worker 
1070*61046927SAndroid Build Coastguard Worker       if (pipeline_flags & VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT)
1071*61046927SAndroid Build Coastguard Worker          shader_flags |= VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT;
1072*61046927SAndroid Build Coastguard Worker    }
1073*61046927SAndroid Build Coastguard Worker 
1074*61046927SAndroid Build Coastguard Worker    if (stage == MESA_SHADER_COMPUTE) {
1075*61046927SAndroid Build Coastguard Worker       if (pipeline_flags & VK_PIPELINE_CREATE_2_DISPATCH_BASE_BIT_KHR)
1076*61046927SAndroid Build Coastguard Worker          shader_flags |= VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT;
1077*61046927SAndroid Build Coastguard Worker    }
1078*61046927SAndroid Build Coastguard Worker 
1079*61046927SAndroid Build Coastguard Worker    return shader_flags;
1080*61046927SAndroid Build Coastguard Worker }
1081*61046927SAndroid Build Coastguard Worker 
1082*61046927SAndroid Build Coastguard Worker static VkResult
vk_graphics_pipeline_compile_shaders(struct vk_device * device,struct vk_pipeline_cache * cache,struct vk_graphics_pipeline * pipeline,struct vk_pipeline_layout * pipeline_layout,const struct vk_graphics_pipeline_state * state,uint32_t stage_count,struct vk_pipeline_stage * stages,VkPipelineCreationFeedback * stage_feedbacks)1083*61046927SAndroid Build Coastguard Worker vk_graphics_pipeline_compile_shaders(struct vk_device *device,
1084*61046927SAndroid Build Coastguard Worker                                      struct vk_pipeline_cache *cache,
1085*61046927SAndroid Build Coastguard Worker                                      struct vk_graphics_pipeline *pipeline,
1086*61046927SAndroid Build Coastguard Worker                                      struct vk_pipeline_layout *pipeline_layout,
1087*61046927SAndroid Build Coastguard Worker                                      const struct vk_graphics_pipeline_state *state,
1088*61046927SAndroid Build Coastguard Worker                                      uint32_t stage_count,
1089*61046927SAndroid Build Coastguard Worker                                      struct vk_pipeline_stage *stages,
1090*61046927SAndroid Build Coastguard Worker                                      VkPipelineCreationFeedback *stage_feedbacks)
1091*61046927SAndroid Build Coastguard Worker {
1092*61046927SAndroid Build Coastguard Worker    const struct vk_device_shader_ops *ops = device->shader_ops;
1093*61046927SAndroid Build Coastguard Worker    VkResult result;
1094*61046927SAndroid Build Coastguard Worker 
1095*61046927SAndroid Build Coastguard Worker    if (stage_count == 0)
1096*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1097*61046927SAndroid Build Coastguard Worker 
1098*61046927SAndroid Build Coastguard Worker    /* If we're linking, throw away any previously compiled shaders as they
1099*61046927SAndroid Build Coastguard Worker     * likely haven't been properly linked.  We keep the precompiled shaders
1100*61046927SAndroid Build Coastguard Worker     * and we still look it up in the cache so it may still be fast.
1101*61046927SAndroid Build Coastguard Worker     */
1102*61046927SAndroid Build Coastguard Worker    if (pipeline->base.flags & VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT) {
1103*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < stage_count; i++) {
1104*61046927SAndroid Build Coastguard Worker          if (stages[i].shader != NULL) {
1105*61046927SAndroid Build Coastguard Worker             vk_shader_unref(device, stages[i].shader);
1106*61046927SAndroid Build Coastguard Worker             stages[i].shader = NULL;
1107*61046927SAndroid Build Coastguard Worker          }
1108*61046927SAndroid Build Coastguard Worker       }
1109*61046927SAndroid Build Coastguard Worker    }
1110*61046927SAndroid Build Coastguard Worker 
1111*61046927SAndroid Build Coastguard Worker    bool have_all_shaders = true;
1112*61046927SAndroid Build Coastguard Worker    VkShaderStageFlags all_stages = 0;
1113*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_precomp_shader *tcs_precomp = NULL, *tes_precomp = NULL;
1114*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < stage_count; i++) {
1115*61046927SAndroid Build Coastguard Worker       all_stages |= mesa_to_vk_shader_stage(stages[i].stage);
1116*61046927SAndroid Build Coastguard Worker 
1117*61046927SAndroid Build Coastguard Worker       if (stages[i].shader == NULL)
1118*61046927SAndroid Build Coastguard Worker          have_all_shaders = false;
1119*61046927SAndroid Build Coastguard Worker 
1120*61046927SAndroid Build Coastguard Worker       if (stages[i].stage == MESA_SHADER_TESS_CTRL)
1121*61046927SAndroid Build Coastguard Worker          tcs_precomp = stages[i].precomp;
1122*61046927SAndroid Build Coastguard Worker 
1123*61046927SAndroid Build Coastguard Worker       if (stages[i].stage == MESA_SHADER_TESS_EVAL)
1124*61046927SAndroid Build Coastguard Worker          tes_precomp = stages[i].precomp;
1125*61046927SAndroid Build Coastguard Worker    }
1126*61046927SAndroid Build Coastguard Worker 
1127*61046927SAndroid Build Coastguard Worker    /* If we already have a shader for each stage, there's nothing to do. */
1128*61046927SAndroid Build Coastguard Worker    if (have_all_shaders)
1129*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1130*61046927SAndroid Build Coastguard Worker 
1131*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_tess_info tess_info = { ._pad = 0 };
1132*61046927SAndroid Build Coastguard Worker    if (tcs_precomp != NULL && tes_precomp != NULL) {
1133*61046927SAndroid Build Coastguard Worker       tess_info = tcs_precomp->tess;
1134*61046927SAndroid Build Coastguard Worker       vk_pipeline_tess_info_merge(&tess_info, &tes_precomp->tess);
1135*61046927SAndroid Build Coastguard Worker    }
1136*61046927SAndroid Build Coastguard Worker 
1137*61046927SAndroid Build Coastguard Worker    struct mesa_blake3 blake3_ctx;
1138*61046927SAndroid Build Coastguard Worker    _mesa_blake3_init(&blake3_ctx);
1139*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pipeline->set_layout_count; i++) {
1140*61046927SAndroid Build Coastguard Worker       if (pipeline->set_layouts[i] != NULL) {
1141*61046927SAndroid Build Coastguard Worker          _mesa_blake3_update(&blake3_ctx, pipeline->set_layouts[i]->blake3,
1142*61046927SAndroid Build Coastguard Worker                            sizeof(pipeline->set_layouts[i]->blake3));
1143*61046927SAndroid Build Coastguard Worker       }
1144*61046927SAndroid Build Coastguard Worker    }
1145*61046927SAndroid Build Coastguard Worker    if (pipeline_layout != NULL) {
1146*61046927SAndroid Build Coastguard Worker       _mesa_blake3_update(&blake3_ctx, &pipeline_layout->push_ranges,
1147*61046927SAndroid Build Coastguard Worker                         sizeof(pipeline_layout->push_ranges[0]) *
1148*61046927SAndroid Build Coastguard Worker                            pipeline_layout->push_range_count);
1149*61046927SAndroid Build Coastguard Worker    }
1150*61046927SAndroid Build Coastguard Worker    blake3_hash layout_blake3;
1151*61046927SAndroid Build Coastguard Worker    _mesa_blake3_final(&blake3_ctx, layout_blake3);
1152*61046927SAndroid Build Coastguard Worker 
1153*61046927SAndroid Build Coastguard Worker    /* Partition the shaders */
1154*61046927SAndroid Build Coastguard Worker    uint32_t part_count;
1155*61046927SAndroid Build Coastguard Worker    uint32_t partition[MESA_VK_MAX_GRAPHICS_PIPELINE_STAGES + 1] = { 0 };
1156*61046927SAndroid Build Coastguard Worker    if (pipeline->base.flags & VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT) {
1157*61046927SAndroid Build Coastguard Worker       partition[1] = stage_count;
1158*61046927SAndroid Build Coastguard Worker       part_count = 1;
1159*61046927SAndroid Build Coastguard Worker    } else if (ops->link_geom_stages) {
1160*61046927SAndroid Build Coastguard Worker       if (stages[0].stage == MESA_SHADER_FRAGMENT) {
1161*61046927SAndroid Build Coastguard Worker          assert(stage_count == 1);
1162*61046927SAndroid Build Coastguard Worker          partition[1] = stage_count;
1163*61046927SAndroid Build Coastguard Worker          part_count = 1;
1164*61046927SAndroid Build Coastguard Worker       } else if (stages[stage_count - 1].stage == MESA_SHADER_FRAGMENT) {
1165*61046927SAndroid Build Coastguard Worker          /* In this case we have both */
1166*61046927SAndroid Build Coastguard Worker          assert(stage_count > 1);
1167*61046927SAndroid Build Coastguard Worker          partition[1] = stage_count - 1;
1168*61046927SAndroid Build Coastguard Worker          partition[2] = stage_count;
1169*61046927SAndroid Build Coastguard Worker          part_count = 2;
1170*61046927SAndroid Build Coastguard Worker       } else {
1171*61046927SAndroid Build Coastguard Worker          /* In this case we only have geometry */
1172*61046927SAndroid Build Coastguard Worker          partition[1] = stage_count;
1173*61046927SAndroid Build Coastguard Worker          part_count = 1;
1174*61046927SAndroid Build Coastguard Worker       }
1175*61046927SAndroid Build Coastguard Worker    } else {
1176*61046927SAndroid Build Coastguard Worker       /* Otherwise, we're don't want to link anything */
1177*61046927SAndroid Build Coastguard Worker       part_count = stage_count;
1178*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < stage_count; i++)
1179*61046927SAndroid Build Coastguard Worker          partition[i + 1] = i + 1;
1180*61046927SAndroid Build Coastguard Worker    }
1181*61046927SAndroid Build Coastguard Worker 
1182*61046927SAndroid Build Coastguard Worker    for (uint32_t p = 0; p < part_count; p++) {
1183*61046927SAndroid Build Coastguard Worker       const int64_t part_start = os_time_get_nano();
1184*61046927SAndroid Build Coastguard Worker 
1185*61046927SAndroid Build Coastguard Worker       /* Don't try to re-compile any fast-link shaders */
1186*61046927SAndroid Build Coastguard Worker       if (!(pipeline->base.flags &
1187*61046927SAndroid Build Coastguard Worker             VK_PIPELINE_CREATE_2_LINK_TIME_OPTIMIZATION_BIT_EXT)) {
1188*61046927SAndroid Build Coastguard Worker          assert(partition[p + 1] == partition[p] + 1);
1189*61046927SAndroid Build Coastguard Worker          if (stages[partition[p]].shader != NULL)
1190*61046927SAndroid Build Coastguard Worker             continue;
1191*61046927SAndroid Build Coastguard Worker       }
1192*61046927SAndroid Build Coastguard Worker 
1193*61046927SAndroid Build Coastguard Worker       struct vk_shader_pipeline_cache_key shader_key = { 0 };
1194*61046927SAndroid Build Coastguard Worker 
1195*61046927SAndroid Build Coastguard Worker       _mesa_blake3_init(&blake3_ctx);
1196*61046927SAndroid Build Coastguard Worker 
1197*61046927SAndroid Build Coastguard Worker       VkShaderStageFlags part_stages = 0;
1198*61046927SAndroid Build Coastguard Worker       for (uint32_t i = partition[p]; i < partition[p + 1]; i++) {
1199*61046927SAndroid Build Coastguard Worker          const struct vk_pipeline_stage *stage = &stages[i];
1200*61046927SAndroid Build Coastguard Worker 
1201*61046927SAndroid Build Coastguard Worker          part_stages |= mesa_to_vk_shader_stage(stage->stage);
1202*61046927SAndroid Build Coastguard Worker          _mesa_blake3_update(&blake3_ctx, stage->precomp->blake3,
1203*61046927SAndroid Build Coastguard Worker                              sizeof(stage->precomp->blake3));
1204*61046927SAndroid Build Coastguard Worker 
1205*61046927SAndroid Build Coastguard Worker          VkShaderCreateFlagsEXT shader_flags =
1206*61046927SAndroid Build Coastguard Worker             vk_pipeline_to_shader_flags(pipeline->base.flags, stage->stage);
1207*61046927SAndroid Build Coastguard Worker          _mesa_blake3_update(&blake3_ctx, &shader_flags, sizeof(shader_flags));
1208*61046927SAndroid Build Coastguard Worker       }
1209*61046927SAndroid Build Coastguard Worker 
1210*61046927SAndroid Build Coastguard Worker       blake3_hash state_blake3;
1211*61046927SAndroid Build Coastguard Worker       ops->hash_graphics_state(device->physical, state,
1212*61046927SAndroid Build Coastguard Worker                                part_stages, state_blake3);
1213*61046927SAndroid Build Coastguard Worker 
1214*61046927SAndroid Build Coastguard Worker       _mesa_blake3_update(&blake3_ctx, state_blake3, sizeof(state_blake3));
1215*61046927SAndroid Build Coastguard Worker       _mesa_blake3_update(&blake3_ctx, layout_blake3, sizeof(layout_blake3));
1216*61046927SAndroid Build Coastguard Worker 
1217*61046927SAndroid Build Coastguard Worker       if (part_stages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
1218*61046927SAndroid Build Coastguard Worker                          VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
1219*61046927SAndroid Build Coastguard Worker          _mesa_blake3_update(&blake3_ctx, &tess_info, sizeof(tess_info));
1220*61046927SAndroid Build Coastguard Worker 
1221*61046927SAndroid Build Coastguard Worker       /* The set of geometry stages used together is used to generate the
1222*61046927SAndroid Build Coastguard Worker        * nextStage mask as well as VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT.
1223*61046927SAndroid Build Coastguard Worker        */
1224*61046927SAndroid Build Coastguard Worker       const VkShaderStageFlags geom_stages =
1225*61046927SAndroid Build Coastguard Worker          all_stages & ~VK_SHADER_STAGE_FRAGMENT_BIT;
1226*61046927SAndroid Build Coastguard Worker       _mesa_blake3_update(&blake3_ctx, &geom_stages, sizeof(geom_stages));
1227*61046927SAndroid Build Coastguard Worker 
1228*61046927SAndroid Build Coastguard Worker       _mesa_blake3_final(&blake3_ctx, shader_key.blake3);
1229*61046927SAndroid Build Coastguard Worker 
1230*61046927SAndroid Build Coastguard Worker       if (cache != NULL) {
1231*61046927SAndroid Build Coastguard Worker          /* From the Vulkan 1.3.278 spec:
1232*61046927SAndroid Build Coastguard Worker           *
1233*61046927SAndroid Build Coastguard Worker           *    "VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT
1234*61046927SAndroid Build Coastguard Worker           *    indicates that a readily usable pipeline or pipeline stage was
1235*61046927SAndroid Build Coastguard Worker           *    found in the pipelineCache specified by the application in the
1236*61046927SAndroid Build Coastguard Worker           *    pipeline creation command.
1237*61046927SAndroid Build Coastguard Worker           *
1238*61046927SAndroid Build Coastguard Worker           *    [...]
1239*61046927SAndroid Build Coastguard Worker           *
1240*61046927SAndroid Build Coastguard Worker           *    Note
1241*61046927SAndroid Build Coastguard Worker           *
1242*61046927SAndroid Build Coastguard Worker           *    Implementations are encouraged to provide a meaningful signal
1243*61046927SAndroid Build Coastguard Worker           *    to applications using this bit. The intention is to communicate
1244*61046927SAndroid Build Coastguard Worker           *    to the application that the pipeline or pipeline stage was
1245*61046927SAndroid Build Coastguard Worker           *    created “as fast as it gets” using the pipeline cache provided
1246*61046927SAndroid Build Coastguard Worker           *    by the application. If an implementation uses an internal
1247*61046927SAndroid Build Coastguard Worker           *    cache, it is discouraged from setting this bit as the feedback
1248*61046927SAndroid Build Coastguard Worker           *    would be unactionable."
1249*61046927SAndroid Build Coastguard Worker           *
1250*61046927SAndroid Build Coastguard Worker           * The cache_hit value returned by vk_pipeline_cache_lookup_object()
1251*61046927SAndroid Build Coastguard Worker           * is only set to true when the shader is found in the provided
1252*61046927SAndroid Build Coastguard Worker           * pipeline cache.  It is left false if we fail to find it in the
1253*61046927SAndroid Build Coastguard Worker           * memory cache but find it in the disk cache even though that's
1254*61046927SAndroid Build Coastguard Worker           * still a cache hit from the perspective of the compile pipeline.
1255*61046927SAndroid Build Coastguard Worker           */
1256*61046927SAndroid Build Coastguard Worker          bool all_shaders_found = true;
1257*61046927SAndroid Build Coastguard Worker          bool all_cache_hits = true;
1258*61046927SAndroid Build Coastguard Worker          for (uint32_t i = partition[p]; i < partition[p + 1]; i++) {
1259*61046927SAndroid Build Coastguard Worker             struct vk_pipeline_stage *stage = &stages[i];
1260*61046927SAndroid Build Coastguard Worker 
1261*61046927SAndroid Build Coastguard Worker             shader_key.stage = stage->stage;
1262*61046927SAndroid Build Coastguard Worker 
1263*61046927SAndroid Build Coastguard Worker             if (stage->shader) {
1264*61046927SAndroid Build Coastguard Worker                /* If we have a shader from some library pipeline and the key
1265*61046927SAndroid Build Coastguard Worker                 * matches, just use that.
1266*61046927SAndroid Build Coastguard Worker                 */
1267*61046927SAndroid Build Coastguard Worker                if (memcmp(&stage->shader->pipeline.cache_key,
1268*61046927SAndroid Build Coastguard Worker                           &shader_key, sizeof(shader_key)) == 0)
1269*61046927SAndroid Build Coastguard Worker                   continue;
1270*61046927SAndroid Build Coastguard Worker 
1271*61046927SAndroid Build Coastguard Worker                /* Otherwise, throw it away */
1272*61046927SAndroid Build Coastguard Worker                vk_shader_unref(device, stage->shader);
1273*61046927SAndroid Build Coastguard Worker                stage->shader = NULL;
1274*61046927SAndroid Build Coastguard Worker             }
1275*61046927SAndroid Build Coastguard Worker 
1276*61046927SAndroid Build Coastguard Worker             bool cache_hit = false;
1277*61046927SAndroid Build Coastguard Worker             struct vk_pipeline_cache_object *cache_obj =
1278*61046927SAndroid Build Coastguard Worker                vk_pipeline_cache_lookup_object(cache, &shader_key,
1279*61046927SAndroid Build Coastguard Worker                                                sizeof(shader_key),
1280*61046927SAndroid Build Coastguard Worker                                                &pipeline_shader_cache_ops,
1281*61046927SAndroid Build Coastguard Worker                                                &cache_hit);
1282*61046927SAndroid Build Coastguard Worker             if (cache_obj != NULL) {
1283*61046927SAndroid Build Coastguard Worker                assert(stage->shader == NULL);
1284*61046927SAndroid Build Coastguard Worker                stage->shader = vk_shader_from_cache_obj(cache_obj);
1285*61046927SAndroid Build Coastguard Worker             } else {
1286*61046927SAndroid Build Coastguard Worker                all_shaders_found = false;
1287*61046927SAndroid Build Coastguard Worker             }
1288*61046927SAndroid Build Coastguard Worker 
1289*61046927SAndroid Build Coastguard Worker             if (cache_obj == NULL && !cache_hit)
1290*61046927SAndroid Build Coastguard Worker                all_cache_hits = false;
1291*61046927SAndroid Build Coastguard Worker          }
1292*61046927SAndroid Build Coastguard Worker 
1293*61046927SAndroid Build Coastguard Worker          if (all_cache_hits && cache != device->mem_cache) {
1294*61046927SAndroid Build Coastguard Worker             /* The pipeline cache only really helps if we hit for everything
1295*61046927SAndroid Build Coastguard Worker              * in the partition.  Otherwise, we have to go re-compile it all
1296*61046927SAndroid Build Coastguard Worker              * anyway.
1297*61046927SAndroid Build Coastguard Worker              */
1298*61046927SAndroid Build Coastguard Worker             for (uint32_t i = partition[p]; i < partition[p + 1]; i++) {
1299*61046927SAndroid Build Coastguard Worker                struct vk_pipeline_stage *stage = &stages[i];
1300*61046927SAndroid Build Coastguard Worker 
1301*61046927SAndroid Build Coastguard Worker                stage_feedbacks[stage->stage].flags |=
1302*61046927SAndroid Build Coastguard Worker                   VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT;
1303*61046927SAndroid Build Coastguard Worker             }
1304*61046927SAndroid Build Coastguard Worker          }
1305*61046927SAndroid Build Coastguard Worker 
1306*61046927SAndroid Build Coastguard Worker          if (all_shaders_found) {
1307*61046927SAndroid Build Coastguard Worker             /* Update duration to take cache lookups into account */
1308*61046927SAndroid Build Coastguard Worker             const int64_t part_end = os_time_get_nano();
1309*61046927SAndroid Build Coastguard Worker             for (uint32_t i = partition[p]; i < partition[p + 1]; i++) {
1310*61046927SAndroid Build Coastguard Worker                struct vk_pipeline_stage *stage = &stages[i];
1311*61046927SAndroid Build Coastguard Worker                stage_feedbacks[stage->stage].duration += part_end - part_start;
1312*61046927SAndroid Build Coastguard Worker             }
1313*61046927SAndroid Build Coastguard Worker             continue;
1314*61046927SAndroid Build Coastguard Worker          }
1315*61046927SAndroid Build Coastguard Worker       }
1316*61046927SAndroid Build Coastguard Worker 
1317*61046927SAndroid Build Coastguard Worker       if (pipeline->base.flags &
1318*61046927SAndroid Build Coastguard Worker           VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR)
1319*61046927SAndroid Build Coastguard Worker          return VK_PIPELINE_COMPILE_REQUIRED;
1320*61046927SAndroid Build Coastguard Worker 
1321*61046927SAndroid Build Coastguard Worker       struct vk_shader_compile_info infos[MESA_VK_MAX_GRAPHICS_PIPELINE_STAGES];
1322*61046927SAndroid Build Coastguard Worker       for (uint32_t i = partition[p]; i < partition[p + 1]; i++) {
1323*61046927SAndroid Build Coastguard Worker          struct vk_pipeline_stage *stage = &stages[i];
1324*61046927SAndroid Build Coastguard Worker 
1325*61046927SAndroid Build Coastguard Worker          VkShaderCreateFlagsEXT shader_flags =
1326*61046927SAndroid Build Coastguard Worker             vk_pipeline_to_shader_flags(pipeline->base.flags, stage->stage);
1327*61046927SAndroid Build Coastguard Worker 
1328*61046927SAndroid Build Coastguard Worker          if (partition[p + 1] - partition[p] > 1)
1329*61046927SAndroid Build Coastguard Worker             shader_flags |= VK_SHADER_CREATE_LINK_STAGE_BIT_EXT;
1330*61046927SAndroid Build Coastguard Worker 
1331*61046927SAndroid Build Coastguard Worker          if ((part_stages & VK_SHADER_STAGE_MESH_BIT_EXT) &&
1332*61046927SAndroid Build Coastguard Worker              !(geom_stages & VK_SHADER_STAGE_TASK_BIT_EXT))
1333*61046927SAndroid Build Coastguard Worker             shader_flags = VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT;
1334*61046927SAndroid Build Coastguard Worker 
1335*61046927SAndroid Build Coastguard Worker          VkShaderStageFlags next_stage;
1336*61046927SAndroid Build Coastguard Worker          if (stage->stage == MESA_SHADER_FRAGMENT) {
1337*61046927SAndroid Build Coastguard Worker             next_stage = 0;
1338*61046927SAndroid Build Coastguard Worker          } else if (i + 1 < stage_count) {
1339*61046927SAndroid Build Coastguard Worker             /* We hash geom_stages above so this is safe */
1340*61046927SAndroid Build Coastguard Worker             next_stage = mesa_to_vk_shader_stage(stages[i + 1].stage);
1341*61046927SAndroid Build Coastguard Worker          } else {
1342*61046927SAndroid Build Coastguard Worker             /* We're the last geometry stage */
1343*61046927SAndroid Build Coastguard Worker             next_stage = VK_SHADER_STAGE_FRAGMENT_BIT;
1344*61046927SAndroid Build Coastguard Worker          }
1345*61046927SAndroid Build Coastguard Worker 
1346*61046927SAndroid Build Coastguard Worker          const struct nir_shader_compiler_options *nir_options =
1347*61046927SAndroid Build Coastguard Worker             ops->get_nir_options(device->physical, stage->stage,
1348*61046927SAndroid Build Coastguard Worker                                  &stage->precomp->rs);
1349*61046927SAndroid Build Coastguard Worker 
1350*61046927SAndroid Build Coastguard Worker          nir_shader *nir =
1351*61046927SAndroid Build Coastguard Worker             vk_pipeline_precomp_shader_get_nir(stage->precomp, nir_options);
1352*61046927SAndroid Build Coastguard Worker          if (nir == NULL) {
1353*61046927SAndroid Build Coastguard Worker             for (uint32_t j = partition[p]; j < i; j++)
1354*61046927SAndroid Build Coastguard Worker                ralloc_free(infos[i].nir);
1355*61046927SAndroid Build Coastguard Worker 
1356*61046927SAndroid Build Coastguard Worker             return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1357*61046927SAndroid Build Coastguard Worker          }
1358*61046927SAndroid Build Coastguard Worker 
1359*61046927SAndroid Build Coastguard Worker          if (stage->stage == MESA_SHADER_TESS_CTRL ||
1360*61046927SAndroid Build Coastguard Worker              stage->stage == MESA_SHADER_TESS_EVAL)
1361*61046927SAndroid Build Coastguard Worker             vk_pipeline_replace_nir_tess_info(nir, &tess_info);
1362*61046927SAndroid Build Coastguard Worker 
1363*61046927SAndroid Build Coastguard Worker          const VkPushConstantRange *push_range = NULL;
1364*61046927SAndroid Build Coastguard Worker          if (pipeline_layout != NULL) {
1365*61046927SAndroid Build Coastguard Worker             for (uint32_t r = 0; r < pipeline_layout->push_range_count; r++) {
1366*61046927SAndroid Build Coastguard Worker                if (pipeline_layout->push_ranges[r].stageFlags &
1367*61046927SAndroid Build Coastguard Worker                    mesa_to_vk_shader_stage(stage->stage)) {
1368*61046927SAndroid Build Coastguard Worker                   assert(push_range == NULL);
1369*61046927SAndroid Build Coastguard Worker                   push_range = &pipeline_layout->push_ranges[r];
1370*61046927SAndroid Build Coastguard Worker                }
1371*61046927SAndroid Build Coastguard Worker             }
1372*61046927SAndroid Build Coastguard Worker          }
1373*61046927SAndroid Build Coastguard Worker 
1374*61046927SAndroid Build Coastguard Worker          infos[i] = (struct vk_shader_compile_info) {
1375*61046927SAndroid Build Coastguard Worker             .stage = stage->stage,
1376*61046927SAndroid Build Coastguard Worker             .flags = shader_flags,
1377*61046927SAndroid Build Coastguard Worker             .next_stage_mask = next_stage,
1378*61046927SAndroid Build Coastguard Worker             .nir = nir,
1379*61046927SAndroid Build Coastguard Worker             .robustness = &stage->precomp->rs,
1380*61046927SAndroid Build Coastguard Worker             .set_layout_count = pipeline->set_layout_count,
1381*61046927SAndroid Build Coastguard Worker             .set_layouts = pipeline->set_layouts,
1382*61046927SAndroid Build Coastguard Worker             .push_constant_range_count = push_range != NULL,
1383*61046927SAndroid Build Coastguard Worker             .push_constant_ranges = push_range != NULL ? push_range : NULL,
1384*61046927SAndroid Build Coastguard Worker          };
1385*61046927SAndroid Build Coastguard Worker       }
1386*61046927SAndroid Build Coastguard Worker 
1387*61046927SAndroid Build Coastguard Worker       /* vk_shader_ops::compile() consumes the NIR regardless of whether or
1388*61046927SAndroid Build Coastguard Worker        * not it succeeds and only generates shaders on success. Once this
1389*61046927SAndroid Build Coastguard Worker        * returns, we own the shaders but not the NIR in infos.
1390*61046927SAndroid Build Coastguard Worker        */
1391*61046927SAndroid Build Coastguard Worker       struct vk_shader *shaders[MESA_VK_MAX_GRAPHICS_PIPELINE_STAGES];
1392*61046927SAndroid Build Coastguard Worker       result = ops->compile(device, partition[p + 1] - partition[p],
1393*61046927SAndroid Build Coastguard Worker                             &infos[partition[p]],
1394*61046927SAndroid Build Coastguard Worker                             state,
1395*61046927SAndroid Build Coastguard Worker                             &device->alloc,
1396*61046927SAndroid Build Coastguard Worker                             &shaders[partition[p]]);
1397*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1398*61046927SAndroid Build Coastguard Worker          return result;
1399*61046927SAndroid Build Coastguard Worker 
1400*61046927SAndroid Build Coastguard Worker       const int64_t part_end = os_time_get_nano();
1401*61046927SAndroid Build Coastguard Worker       for (uint32_t i = partition[p]; i < partition[p + 1]; i++) {
1402*61046927SAndroid Build Coastguard Worker          struct vk_pipeline_stage *stage = &stages[i];
1403*61046927SAndroid Build Coastguard Worker 
1404*61046927SAndroid Build Coastguard Worker          shader_key.stage = stage->stage;
1405*61046927SAndroid Build Coastguard Worker          vk_shader_init_cache_obj(device, shaders[i], &shader_key,
1406*61046927SAndroid Build Coastguard Worker                                   sizeof(shader_key));
1407*61046927SAndroid Build Coastguard Worker 
1408*61046927SAndroid Build Coastguard Worker          if (stage->shader == NULL) {
1409*61046927SAndroid Build Coastguard Worker             struct vk_pipeline_cache_object *cache_obj =
1410*61046927SAndroid Build Coastguard Worker                &shaders[i]->pipeline.cache_obj;
1411*61046927SAndroid Build Coastguard Worker             if (cache != NULL)
1412*61046927SAndroid Build Coastguard Worker                cache_obj = vk_pipeline_cache_add_object(cache, cache_obj);
1413*61046927SAndroid Build Coastguard Worker 
1414*61046927SAndroid Build Coastguard Worker             stage->shader = vk_shader_from_cache_obj(cache_obj);
1415*61046927SAndroid Build Coastguard Worker          } else {
1416*61046927SAndroid Build Coastguard Worker             /* This can fail to happen if only some of the shaders were found
1417*61046927SAndroid Build Coastguard Worker              * in the pipeline cache.  In this case, we just throw away the
1418*61046927SAndroid Build Coastguard Worker              * shader as vk_pipeline_cache_add_object() would throw it away
1419*61046927SAndroid Build Coastguard Worker              * for us anyway.
1420*61046927SAndroid Build Coastguard Worker              */
1421*61046927SAndroid Build Coastguard Worker             assert(memcmp(&stage->shader->pipeline.cache_key,
1422*61046927SAndroid Build Coastguard Worker                           &shaders[i]->pipeline.cache_key,
1423*61046927SAndroid Build Coastguard Worker                           sizeof(shaders[i]->pipeline.cache_key)) == 0);
1424*61046927SAndroid Build Coastguard Worker 
1425*61046927SAndroid Build Coastguard Worker             vk_shader_unref(device, shaders[i]);
1426*61046927SAndroid Build Coastguard Worker          }
1427*61046927SAndroid Build Coastguard Worker 
1428*61046927SAndroid Build Coastguard Worker          stage_feedbacks[stage->stage].duration += part_end - part_start;
1429*61046927SAndroid Build Coastguard Worker       }
1430*61046927SAndroid Build Coastguard Worker    }
1431*61046927SAndroid Build Coastguard Worker 
1432*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1433*61046927SAndroid Build Coastguard Worker }
1434*61046927SAndroid Build Coastguard Worker 
1435*61046927SAndroid Build Coastguard Worker static VkResult
vk_graphics_pipeline_get_executable_properties(struct vk_device * device,struct vk_pipeline * pipeline,uint32_t * executable_count,VkPipelineExecutablePropertiesKHR * properties)1436*61046927SAndroid Build Coastguard Worker vk_graphics_pipeline_get_executable_properties(
1437*61046927SAndroid Build Coastguard Worker    struct vk_device *device,
1438*61046927SAndroid Build Coastguard Worker    struct vk_pipeline *pipeline,
1439*61046927SAndroid Build Coastguard Worker    uint32_t *executable_count,
1440*61046927SAndroid Build Coastguard Worker    VkPipelineExecutablePropertiesKHR *properties)
1441*61046927SAndroid Build Coastguard Worker {
1442*61046927SAndroid Build Coastguard Worker    struct vk_graphics_pipeline *gfx_pipeline =
1443*61046927SAndroid Build Coastguard Worker       container_of(pipeline, struct vk_graphics_pipeline, base);
1444*61046927SAndroid Build Coastguard Worker    VkResult result;
1445*61046927SAndroid Build Coastguard Worker 
1446*61046927SAndroid Build Coastguard Worker    if (properties == NULL) {
1447*61046927SAndroid Build Coastguard Worker       *executable_count = 0;
1448*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < gfx_pipeline->stage_count; i++) {
1449*61046927SAndroid Build Coastguard Worker          struct vk_shader *shader = gfx_pipeline->stages[i].shader;
1450*61046927SAndroid Build Coastguard Worker 
1451*61046927SAndroid Build Coastguard Worker          uint32_t shader_exec_count = 0;
1452*61046927SAndroid Build Coastguard Worker          result = shader->ops->get_executable_properties(device, shader,
1453*61046927SAndroid Build Coastguard Worker                                                          &shader_exec_count,
1454*61046927SAndroid Build Coastguard Worker                                                          NULL);
1455*61046927SAndroid Build Coastguard Worker          assert(result == VK_SUCCESS);
1456*61046927SAndroid Build Coastguard Worker          *executable_count += shader_exec_count;
1457*61046927SAndroid Build Coastguard Worker       }
1458*61046927SAndroid Build Coastguard Worker    } else {
1459*61046927SAndroid Build Coastguard Worker       uint32_t arr_len = *executable_count;
1460*61046927SAndroid Build Coastguard Worker       *executable_count = 0;
1461*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < gfx_pipeline->stage_count; i++) {
1462*61046927SAndroid Build Coastguard Worker          struct vk_shader *shader = gfx_pipeline->stages[i].shader;
1463*61046927SAndroid Build Coastguard Worker 
1464*61046927SAndroid Build Coastguard Worker          uint32_t shader_exec_count = arr_len - *executable_count;
1465*61046927SAndroid Build Coastguard Worker          result = shader->ops->get_executable_properties(device, shader,
1466*61046927SAndroid Build Coastguard Worker                                                          &shader_exec_count,
1467*61046927SAndroid Build Coastguard Worker                                                          &properties[*executable_count]);
1468*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
1469*61046927SAndroid Build Coastguard Worker             return result;
1470*61046927SAndroid Build Coastguard Worker 
1471*61046927SAndroid Build Coastguard Worker          *executable_count += shader_exec_count;
1472*61046927SAndroid Build Coastguard Worker       }
1473*61046927SAndroid Build Coastguard Worker    }
1474*61046927SAndroid Build Coastguard Worker 
1475*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1476*61046927SAndroid Build Coastguard Worker }
1477*61046927SAndroid Build Coastguard Worker 
1478*61046927SAndroid Build Coastguard Worker static inline struct vk_shader *
vk_graphics_pipeline_executable_shader(struct vk_device * device,struct vk_graphics_pipeline * gfx_pipeline,uint32_t * executable_index)1479*61046927SAndroid Build Coastguard Worker vk_graphics_pipeline_executable_shader(struct vk_device *device,
1480*61046927SAndroid Build Coastguard Worker                                        struct vk_graphics_pipeline *gfx_pipeline,
1481*61046927SAndroid Build Coastguard Worker                                        uint32_t *executable_index)
1482*61046927SAndroid Build Coastguard Worker {
1483*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < gfx_pipeline->stage_count; i++) {
1484*61046927SAndroid Build Coastguard Worker       struct vk_shader *shader = gfx_pipeline->stages[i].shader;
1485*61046927SAndroid Build Coastguard Worker 
1486*61046927SAndroid Build Coastguard Worker       uint32_t shader_exec_count = 0;
1487*61046927SAndroid Build Coastguard Worker       shader->ops->get_executable_properties(device, shader,
1488*61046927SAndroid Build Coastguard Worker                                              &shader_exec_count, NULL);
1489*61046927SAndroid Build Coastguard Worker 
1490*61046927SAndroid Build Coastguard Worker       if (*executable_index < shader_exec_count)
1491*61046927SAndroid Build Coastguard Worker          return shader;
1492*61046927SAndroid Build Coastguard Worker       else
1493*61046927SAndroid Build Coastguard Worker          *executable_index -= shader_exec_count;
1494*61046927SAndroid Build Coastguard Worker    }
1495*61046927SAndroid Build Coastguard Worker 
1496*61046927SAndroid Build Coastguard Worker    return NULL;
1497*61046927SAndroid Build Coastguard Worker }
1498*61046927SAndroid Build Coastguard Worker 
1499*61046927SAndroid Build Coastguard Worker static VkResult
vk_graphics_pipeline_get_executable_statistics(struct vk_device * device,struct vk_pipeline * pipeline,uint32_t executable_index,uint32_t * statistic_count,VkPipelineExecutableStatisticKHR * statistics)1500*61046927SAndroid Build Coastguard Worker vk_graphics_pipeline_get_executable_statistics(
1501*61046927SAndroid Build Coastguard Worker    struct vk_device *device,
1502*61046927SAndroid Build Coastguard Worker    struct vk_pipeline *pipeline,
1503*61046927SAndroid Build Coastguard Worker    uint32_t executable_index,
1504*61046927SAndroid Build Coastguard Worker    uint32_t *statistic_count,
1505*61046927SAndroid Build Coastguard Worker    VkPipelineExecutableStatisticKHR *statistics)
1506*61046927SAndroid Build Coastguard Worker {
1507*61046927SAndroid Build Coastguard Worker    struct vk_graphics_pipeline *gfx_pipeline =
1508*61046927SAndroid Build Coastguard Worker       container_of(pipeline, struct vk_graphics_pipeline, base);
1509*61046927SAndroid Build Coastguard Worker 
1510*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader =
1511*61046927SAndroid Build Coastguard Worker       vk_graphics_pipeline_executable_shader(device, gfx_pipeline,
1512*61046927SAndroid Build Coastguard Worker                                              &executable_index);
1513*61046927SAndroid Build Coastguard Worker    if (shader == NULL) {
1514*61046927SAndroid Build Coastguard Worker       *statistic_count = 0;
1515*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1516*61046927SAndroid Build Coastguard Worker    }
1517*61046927SAndroid Build Coastguard Worker 
1518*61046927SAndroid Build Coastguard Worker    return shader->ops->get_executable_statistics(device, shader,
1519*61046927SAndroid Build Coastguard Worker                                                  executable_index,
1520*61046927SAndroid Build Coastguard Worker                                                  statistic_count,
1521*61046927SAndroid Build Coastguard Worker                                                  statistics);
1522*61046927SAndroid Build Coastguard Worker }
1523*61046927SAndroid Build Coastguard Worker 
1524*61046927SAndroid Build Coastguard Worker static VkResult
vk_graphics_pipeline_get_internal_representations(struct vk_device * device,struct vk_pipeline * pipeline,uint32_t executable_index,uint32_t * internal_representation_count,VkPipelineExecutableInternalRepresentationKHR * internal_representations)1525*61046927SAndroid Build Coastguard Worker vk_graphics_pipeline_get_internal_representations(
1526*61046927SAndroid Build Coastguard Worker    struct vk_device *device,
1527*61046927SAndroid Build Coastguard Worker    struct vk_pipeline *pipeline,
1528*61046927SAndroid Build Coastguard Worker    uint32_t executable_index,
1529*61046927SAndroid Build Coastguard Worker    uint32_t *internal_representation_count,
1530*61046927SAndroid Build Coastguard Worker    VkPipelineExecutableInternalRepresentationKHR* internal_representations)
1531*61046927SAndroid Build Coastguard Worker {
1532*61046927SAndroid Build Coastguard Worker    struct vk_graphics_pipeline *gfx_pipeline =
1533*61046927SAndroid Build Coastguard Worker       container_of(pipeline, struct vk_graphics_pipeline, base);
1534*61046927SAndroid Build Coastguard Worker 
1535*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader =
1536*61046927SAndroid Build Coastguard Worker       vk_graphics_pipeline_executable_shader(device, gfx_pipeline,
1537*61046927SAndroid Build Coastguard Worker                                              &executable_index);
1538*61046927SAndroid Build Coastguard Worker    if (shader == NULL) {
1539*61046927SAndroid Build Coastguard Worker       *internal_representation_count = 0;
1540*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1541*61046927SAndroid Build Coastguard Worker    }
1542*61046927SAndroid Build Coastguard Worker 
1543*61046927SAndroid Build Coastguard Worker    return shader->ops->get_executable_internal_representations(
1544*61046927SAndroid Build Coastguard Worker       device, shader, executable_index,
1545*61046927SAndroid Build Coastguard Worker       internal_representation_count, internal_representations);
1546*61046927SAndroid Build Coastguard Worker }
1547*61046927SAndroid Build Coastguard Worker 
1548*61046927SAndroid Build Coastguard Worker static const struct vk_pipeline_ops vk_graphics_pipeline_ops = {
1549*61046927SAndroid Build Coastguard Worker    .destroy = vk_graphics_pipeline_destroy,
1550*61046927SAndroid Build Coastguard Worker    .get_executable_statistics = vk_graphics_pipeline_get_executable_statistics,
1551*61046927SAndroid Build Coastguard Worker    .get_executable_properties = vk_graphics_pipeline_get_executable_properties,
1552*61046927SAndroid Build Coastguard Worker    .get_internal_representations = vk_graphics_pipeline_get_internal_representations,
1553*61046927SAndroid Build Coastguard Worker    .cmd_bind = vk_graphics_pipeline_cmd_bind,
1554*61046927SAndroid Build Coastguard Worker };
1555*61046927SAndroid Build Coastguard Worker 
1556*61046927SAndroid Build Coastguard Worker static VkResult
vk_create_graphics_pipeline(struct vk_device * device,struct vk_pipeline_cache * cache,const VkGraphicsPipelineCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipeline)1557*61046927SAndroid Build Coastguard Worker vk_create_graphics_pipeline(struct vk_device *device,
1558*61046927SAndroid Build Coastguard Worker                             struct vk_pipeline_cache *cache,
1559*61046927SAndroid Build Coastguard Worker                             const VkGraphicsPipelineCreateInfo *pCreateInfo,
1560*61046927SAndroid Build Coastguard Worker                             const VkAllocationCallbacks *pAllocator,
1561*61046927SAndroid Build Coastguard Worker                             VkPipeline *pPipeline)
1562*61046927SAndroid Build Coastguard Worker {
1563*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline_layout, pipeline_layout, pCreateInfo->layout);
1564*61046927SAndroid Build Coastguard Worker    const int64_t pipeline_start = os_time_get_nano();
1565*61046927SAndroid Build Coastguard Worker    VkResult result;
1566*61046927SAndroid Build Coastguard Worker 
1567*61046927SAndroid Build Coastguard Worker    const VkPipelineCreateFlags2KHR pipeline_flags =
1568*61046927SAndroid Build Coastguard Worker       vk_graphics_pipeline_create_flags(pCreateInfo);
1569*61046927SAndroid Build Coastguard Worker 
1570*61046927SAndroid Build Coastguard Worker    const VkPipelineCreationFeedbackCreateInfo *feedback_info =
1571*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext,
1572*61046927SAndroid Build Coastguard Worker                            PIPELINE_CREATION_FEEDBACK_CREATE_INFO);
1573*61046927SAndroid Build Coastguard Worker 
1574*61046927SAndroid Build Coastguard Worker    const VkPipelineLibraryCreateInfoKHR *libs_info =
1575*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext,
1576*61046927SAndroid Build Coastguard Worker                            PIPELINE_LIBRARY_CREATE_INFO_KHR);
1577*61046927SAndroid Build Coastguard Worker 
1578*61046927SAndroid Build Coastguard Worker    struct vk_graphics_pipeline *pipeline =
1579*61046927SAndroid Build Coastguard Worker       vk_pipeline_zalloc(device, &vk_graphics_pipeline_ops,
1580*61046927SAndroid Build Coastguard Worker                          VK_PIPELINE_BIND_POINT_GRAPHICS,
1581*61046927SAndroid Build Coastguard Worker                          pipeline_flags, pAllocator, sizeof(*pipeline));
1582*61046927SAndroid Build Coastguard Worker    if (pipeline == NULL)
1583*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1584*61046927SAndroid Build Coastguard Worker 
1585*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_stage stages[PIPE_SHADER_MESH_TYPES];
1586*61046927SAndroid Build Coastguard Worker    memset(stages, 0, sizeof(stages));
1587*61046927SAndroid Build Coastguard Worker 
1588*61046927SAndroid Build Coastguard Worker    VkPipelineCreationFeedback stage_feedbacks[PIPE_SHADER_MESH_TYPES];
1589*61046927SAndroid Build Coastguard Worker    memset(stage_feedbacks, 0, sizeof(stage_feedbacks));
1590*61046927SAndroid Build Coastguard Worker 
1591*61046927SAndroid Build Coastguard Worker    struct vk_graphics_pipeline_state state_tmp, *state;
1592*61046927SAndroid Build Coastguard Worker    struct vk_graphics_pipeline_all_state all_state_tmp, *all_state;
1593*61046927SAndroid Build Coastguard Worker    if (pipeline->base.flags & VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR) {
1594*61046927SAndroid Build Coastguard Worker       /* For pipeline libraries, the state is stored in the pipeline */
1595*61046927SAndroid Build Coastguard Worker       state = &pipeline->lib.state;
1596*61046927SAndroid Build Coastguard Worker       all_state = &pipeline->lib.all_state;
1597*61046927SAndroid Build Coastguard Worker    } else {
1598*61046927SAndroid Build Coastguard Worker       /* For linked pipelines, we throw the state away at the end of pipeline
1599*61046927SAndroid Build Coastguard Worker        * creation and only keep the dynamic state.
1600*61046927SAndroid Build Coastguard Worker        */
1601*61046927SAndroid Build Coastguard Worker       memset(&state_tmp, 0, sizeof(state_tmp));
1602*61046927SAndroid Build Coastguard Worker       state = &state_tmp;
1603*61046927SAndroid Build Coastguard Worker       all_state = &all_state_tmp;
1604*61046927SAndroid Build Coastguard Worker    }
1605*61046927SAndroid Build Coastguard Worker 
1606*61046927SAndroid Build Coastguard Worker    /* If we have libraries, import them first. */
1607*61046927SAndroid Build Coastguard Worker    if (libs_info) {
1608*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < libs_info->libraryCount; i++) {
1609*61046927SAndroid Build Coastguard Worker          VK_FROM_HANDLE(vk_pipeline, lib_pipeline, libs_info->pLibraries[i]);
1610*61046927SAndroid Build Coastguard Worker          assert(lib_pipeline->bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);
1611*61046927SAndroid Build Coastguard Worker          assert(lib_pipeline->flags & VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR);
1612*61046927SAndroid Build Coastguard Worker          struct vk_graphics_pipeline *lib_gfx_pipeline =
1613*61046927SAndroid Build Coastguard Worker             container_of(lib_pipeline, struct vk_graphics_pipeline, base);
1614*61046927SAndroid Build Coastguard Worker 
1615*61046927SAndroid Build Coastguard Worker          vk_graphics_pipeline_state_merge(state, &lib_gfx_pipeline->lib.state);
1616*61046927SAndroid Build Coastguard Worker 
1617*61046927SAndroid Build Coastguard Worker          pipeline->set_layout_count = MAX2(pipeline->set_layout_count,
1618*61046927SAndroid Build Coastguard Worker                                            lib_gfx_pipeline->set_layout_count);
1619*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < lib_gfx_pipeline->set_layout_count; i++) {
1620*61046927SAndroid Build Coastguard Worker             if (lib_gfx_pipeline->set_layouts[i] == NULL)
1621*61046927SAndroid Build Coastguard Worker                continue;
1622*61046927SAndroid Build Coastguard Worker 
1623*61046927SAndroid Build Coastguard Worker             if (pipeline->set_layouts[i] == NULL) {
1624*61046927SAndroid Build Coastguard Worker                pipeline->set_layouts[i] =
1625*61046927SAndroid Build Coastguard Worker                   vk_descriptor_set_layout_ref(lib_gfx_pipeline->set_layouts[i]);
1626*61046927SAndroid Build Coastguard Worker             }
1627*61046927SAndroid Build Coastguard Worker          }
1628*61046927SAndroid Build Coastguard Worker 
1629*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < lib_gfx_pipeline->stage_count; i++) {
1630*61046927SAndroid Build Coastguard Worker             const struct vk_pipeline_stage *lib_stage =
1631*61046927SAndroid Build Coastguard Worker                &lib_gfx_pipeline->stages[i];
1632*61046927SAndroid Build Coastguard Worker 
1633*61046927SAndroid Build Coastguard Worker             /* We shouldn't have duplicated stages in the imported pipeline
1634*61046927SAndroid Build Coastguard Worker              * but it's cheap enough to protect against it so we may as well.
1635*61046927SAndroid Build Coastguard Worker              */
1636*61046927SAndroid Build Coastguard Worker             assert(lib_stage->stage < ARRAY_SIZE(stages));
1637*61046927SAndroid Build Coastguard Worker             assert(vk_pipeline_stage_is_null(&stages[lib_stage->stage]));
1638*61046927SAndroid Build Coastguard Worker             if (!vk_pipeline_stage_is_null(&stages[lib_stage->stage]))
1639*61046927SAndroid Build Coastguard Worker                continue;
1640*61046927SAndroid Build Coastguard Worker 
1641*61046927SAndroid Build Coastguard Worker             stages[lib_stage->stage] = vk_pipeline_stage_clone(lib_stage);
1642*61046927SAndroid Build Coastguard Worker          }
1643*61046927SAndroid Build Coastguard Worker       }
1644*61046927SAndroid Build Coastguard Worker    }
1645*61046927SAndroid Build Coastguard Worker 
1646*61046927SAndroid Build Coastguard Worker    result = vk_graphics_pipeline_state_fill(device, state,
1647*61046927SAndroid Build Coastguard Worker                                             pCreateInfo,
1648*61046927SAndroid Build Coastguard Worker                                             NULL /* driver_rp */,
1649*61046927SAndroid Build Coastguard Worker                                             0 /* driver_rp_flags */,
1650*61046927SAndroid Build Coastguard Worker                                             all_state,
1651*61046927SAndroid Build Coastguard Worker                                             NULL, 0, NULL);
1652*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
1653*61046927SAndroid Build Coastguard Worker       goto fail_stages;
1654*61046927SAndroid Build Coastguard Worker 
1655*61046927SAndroid Build Coastguard Worker    if (!(pipeline->base.flags & VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR)) {
1656*61046927SAndroid Build Coastguard Worker       pipeline->linked.dynamic.vi = &pipeline->linked._dynamic_vi;
1657*61046927SAndroid Build Coastguard Worker       pipeline->linked.dynamic.ms.sample_locations =
1658*61046927SAndroid Build Coastguard Worker          &pipeline->linked._dynamic_sl;
1659*61046927SAndroid Build Coastguard Worker       vk_dynamic_graphics_state_fill(&pipeline->linked.dynamic, &state_tmp);
1660*61046927SAndroid Build Coastguard Worker    }
1661*61046927SAndroid Build Coastguard Worker 
1662*61046927SAndroid Build Coastguard Worker    if (pipeline_layout != NULL) {
1663*61046927SAndroid Build Coastguard Worker       pipeline->set_layout_count = MAX2(pipeline->set_layout_count,
1664*61046927SAndroid Build Coastguard Worker                                         pipeline_layout->set_count);
1665*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < pipeline_layout->set_count; i++) {
1666*61046927SAndroid Build Coastguard Worker          if (pipeline_layout->set_layouts[i] == NULL)
1667*61046927SAndroid Build Coastguard Worker             continue;
1668*61046927SAndroid Build Coastguard Worker 
1669*61046927SAndroid Build Coastguard Worker          if (pipeline->set_layouts[i] == NULL) {
1670*61046927SAndroid Build Coastguard Worker             pipeline->set_layouts[i] =
1671*61046927SAndroid Build Coastguard Worker                vk_descriptor_set_layout_ref(pipeline_layout->set_layouts[i]);
1672*61046927SAndroid Build Coastguard Worker          }
1673*61046927SAndroid Build Coastguard Worker       }
1674*61046927SAndroid Build Coastguard Worker    }
1675*61046927SAndroid Build Coastguard Worker 
1676*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
1677*61046927SAndroid Build Coastguard Worker       const VkPipelineShaderStageCreateInfo *stage_info =
1678*61046927SAndroid Build Coastguard Worker          &pCreateInfo->pStages[i];
1679*61046927SAndroid Build Coastguard Worker 
1680*61046927SAndroid Build Coastguard Worker       const int64_t stage_start = os_time_get_nano();
1681*61046927SAndroid Build Coastguard Worker 
1682*61046927SAndroid Build Coastguard Worker       assert(util_bitcount(stage_info->stage) == 1);
1683*61046927SAndroid Build Coastguard Worker       if (!(state->shader_stages & stage_info->stage))
1684*61046927SAndroid Build Coastguard Worker          continue;
1685*61046927SAndroid Build Coastguard Worker 
1686*61046927SAndroid Build Coastguard Worker       gl_shader_stage stage = vk_to_mesa_shader_stage(stage_info->stage);
1687*61046927SAndroid Build Coastguard Worker       assert(vk_device_supports_stage(device, stage));
1688*61046927SAndroid Build Coastguard Worker 
1689*61046927SAndroid Build Coastguard Worker       stage_feedbacks[stage].flags |=
1690*61046927SAndroid Build Coastguard Worker          VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT;
1691*61046927SAndroid Build Coastguard Worker 
1692*61046927SAndroid Build Coastguard Worker       if (!vk_pipeline_stage_is_null(&stages[stage]))
1693*61046927SAndroid Build Coastguard Worker          continue;
1694*61046927SAndroid Build Coastguard Worker 
1695*61046927SAndroid Build Coastguard Worker       struct vk_pipeline_precomp_shader *precomp;
1696*61046927SAndroid Build Coastguard Worker       result = vk_pipeline_precompile_shader(device, cache, pipeline_flags,
1697*61046927SAndroid Build Coastguard Worker                                              pCreateInfo->pNext,
1698*61046927SAndroid Build Coastguard Worker                                              stage_info,
1699*61046927SAndroid Build Coastguard Worker                                              &precomp);
1700*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1701*61046927SAndroid Build Coastguard Worker          goto fail_stages;
1702*61046927SAndroid Build Coastguard Worker 
1703*61046927SAndroid Build Coastguard Worker       stages[stage] = (struct vk_pipeline_stage) {
1704*61046927SAndroid Build Coastguard Worker          .stage = stage,
1705*61046927SAndroid Build Coastguard Worker          .precomp = precomp,
1706*61046927SAndroid Build Coastguard Worker       };
1707*61046927SAndroid Build Coastguard Worker 
1708*61046927SAndroid Build Coastguard Worker       const int64_t stage_end = os_time_get_nano();
1709*61046927SAndroid Build Coastguard Worker       stage_feedbacks[stage].duration += stage_end - stage_start;
1710*61046927SAndroid Build Coastguard Worker    }
1711*61046927SAndroid Build Coastguard Worker 
1712*61046927SAndroid Build Coastguard Worker    /* Compact the array of stages */
1713*61046927SAndroid Build Coastguard Worker    uint32_t stage_count = 0;
1714*61046927SAndroid Build Coastguard Worker    for (uint32_t s = 0; s < ARRAY_SIZE(stages); s++) {
1715*61046927SAndroid Build Coastguard Worker       assert(s >= stage_count);
1716*61046927SAndroid Build Coastguard Worker       if (!vk_pipeline_stage_is_null(&stages[s]))
1717*61046927SAndroid Build Coastguard Worker          stages[stage_count++] = stages[s];
1718*61046927SAndroid Build Coastguard Worker    }
1719*61046927SAndroid Build Coastguard Worker    for (uint32_t s = stage_count; s < ARRAY_SIZE(stages); s++)
1720*61046927SAndroid Build Coastguard Worker       memset(&stages[s], 0, sizeof(stages[s]));
1721*61046927SAndroid Build Coastguard Worker 
1722*61046927SAndroid Build Coastguard Worker    /* Sort so we always give the driver shaders in order.
1723*61046927SAndroid Build Coastguard Worker     *
1724*61046927SAndroid Build Coastguard Worker     * This makes everything easier for everyone.  This also helps stabilize
1725*61046927SAndroid Build Coastguard Worker     * shader keys so that we get a cache hit even if the client gives us
1726*61046927SAndroid Build Coastguard Worker     * the stages in a different order.
1727*61046927SAndroid Build Coastguard Worker     */
1728*61046927SAndroid Build Coastguard Worker    qsort(stages, stage_count, sizeof(*stages), cmp_vk_pipeline_stages);
1729*61046927SAndroid Build Coastguard Worker 
1730*61046927SAndroid Build Coastguard Worker    result = vk_graphics_pipeline_compile_shaders(device, cache, pipeline,
1731*61046927SAndroid Build Coastguard Worker                                                  pipeline_layout, state,
1732*61046927SAndroid Build Coastguard Worker                                                  stage_count, stages,
1733*61046927SAndroid Build Coastguard Worker                                                  stage_feedbacks);
1734*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
1735*61046927SAndroid Build Coastguard Worker       goto fail_stages;
1736*61046927SAndroid Build Coastguard Worker 
1737*61046927SAndroid Build Coastguard Worker    /* Throw away precompiled shaders unless the client explicitly asks us to
1738*61046927SAndroid Build Coastguard Worker     * keep them.
1739*61046927SAndroid Build Coastguard Worker     */
1740*61046927SAndroid Build Coastguard Worker    if (!(pipeline_flags &
1741*61046927SAndroid Build Coastguard Worker          VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT)) {
1742*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < stage_count; i++) {
1743*61046927SAndroid Build Coastguard Worker          if (stages[i].precomp != NULL) {
1744*61046927SAndroid Build Coastguard Worker             vk_pipeline_precomp_shader_unref(device, stages[i].precomp);
1745*61046927SAndroid Build Coastguard Worker             stages[i].precomp = NULL;
1746*61046927SAndroid Build Coastguard Worker          }
1747*61046927SAndroid Build Coastguard Worker       }
1748*61046927SAndroid Build Coastguard Worker    }
1749*61046927SAndroid Build Coastguard Worker 
1750*61046927SAndroid Build Coastguard Worker    pipeline->stage_count = stage_count;
1751*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < stage_count; i++)
1752*61046927SAndroid Build Coastguard Worker       pipeline->stages[i] = stages[i];
1753*61046927SAndroid Build Coastguard Worker 
1754*61046927SAndroid Build Coastguard Worker    const int64_t pipeline_end = os_time_get_nano();
1755*61046927SAndroid Build Coastguard Worker    if (feedback_info != NULL) {
1756*61046927SAndroid Build Coastguard Worker       VkPipelineCreationFeedback pipeline_feedback = {
1757*61046927SAndroid Build Coastguard Worker          .flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT,
1758*61046927SAndroid Build Coastguard Worker          .duration = pipeline_end - pipeline_start,
1759*61046927SAndroid Build Coastguard Worker       };
1760*61046927SAndroid Build Coastguard Worker 
1761*61046927SAndroid Build Coastguard Worker       /* From the Vulkan 1.3.275 spec:
1762*61046927SAndroid Build Coastguard Worker        *
1763*61046927SAndroid Build Coastguard Worker        *    "An implementation should set the
1764*61046927SAndroid Build Coastguard Worker        *    VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT
1765*61046927SAndroid Build Coastguard Worker        *    bit if it was able to avoid the large majority of pipeline or
1766*61046927SAndroid Build Coastguard Worker        *    pipeline stage creation work by using the pipelineCache parameter"
1767*61046927SAndroid Build Coastguard Worker        *
1768*61046927SAndroid Build Coastguard Worker        * We really shouldn't set this bit unless all the shaders hit the
1769*61046927SAndroid Build Coastguard Worker        * cache.
1770*61046927SAndroid Build Coastguard Worker        */
1771*61046927SAndroid Build Coastguard Worker       uint32_t cache_hit_count = 0;
1772*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < stage_count; i++) {
1773*61046927SAndroid Build Coastguard Worker          const gl_shader_stage stage = stages[i].stage;
1774*61046927SAndroid Build Coastguard Worker          if (stage_feedbacks[stage].flags &
1775*61046927SAndroid Build Coastguard Worker              VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT)
1776*61046927SAndroid Build Coastguard Worker             cache_hit_count++;
1777*61046927SAndroid Build Coastguard Worker       }
1778*61046927SAndroid Build Coastguard Worker       if (cache_hit_count > 0 && cache_hit_count == stage_count) {
1779*61046927SAndroid Build Coastguard Worker          pipeline_feedback.flags |=
1780*61046927SAndroid Build Coastguard Worker             VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT;
1781*61046927SAndroid Build Coastguard Worker       }
1782*61046927SAndroid Build Coastguard Worker 
1783*61046927SAndroid Build Coastguard Worker       *feedback_info->pPipelineCreationFeedback = pipeline_feedback;
1784*61046927SAndroid Build Coastguard Worker 
1785*61046927SAndroid Build Coastguard Worker       /* VUID-VkGraphicsPipelineCreateInfo-pipelineStageCreationFeedbackCount-06594 */
1786*61046927SAndroid Build Coastguard Worker       assert(feedback_info->pipelineStageCreationFeedbackCount == 0 ||
1787*61046927SAndroid Build Coastguard Worker              feedback_info->pipelineStageCreationFeedbackCount ==
1788*61046927SAndroid Build Coastguard Worker              pCreateInfo->stageCount);
1789*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0;
1790*61046927SAndroid Build Coastguard Worker            i < feedback_info->pipelineStageCreationFeedbackCount; i++) {
1791*61046927SAndroid Build Coastguard Worker          const gl_shader_stage stage =
1792*61046927SAndroid Build Coastguard Worker             vk_to_mesa_shader_stage(pCreateInfo->pStages[i].stage);
1793*61046927SAndroid Build Coastguard Worker 
1794*61046927SAndroid Build Coastguard Worker          feedback_info->pPipelineStageCreationFeedbacks[i] =
1795*61046927SAndroid Build Coastguard Worker             stage_feedbacks[stage];
1796*61046927SAndroid Build Coastguard Worker       }
1797*61046927SAndroid Build Coastguard Worker    }
1798*61046927SAndroid Build Coastguard Worker 
1799*61046927SAndroid Build Coastguard Worker    *pPipeline = vk_pipeline_to_handle(&pipeline->base);
1800*61046927SAndroid Build Coastguard Worker 
1801*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1802*61046927SAndroid Build Coastguard Worker 
1803*61046927SAndroid Build Coastguard Worker fail_stages:
1804*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < ARRAY_SIZE(stages); i++)
1805*61046927SAndroid Build Coastguard Worker       vk_pipeline_stage_finish(device, &stages[i]);
1806*61046927SAndroid Build Coastguard Worker 
1807*61046927SAndroid Build Coastguard Worker    vk_graphics_pipeline_destroy(device, &pipeline->base, pAllocator);
1808*61046927SAndroid Build Coastguard Worker 
1809*61046927SAndroid Build Coastguard Worker    return result;
1810*61046927SAndroid Build Coastguard Worker }
1811*61046927SAndroid Build Coastguard Worker 
1812*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateGraphicsPipelines(VkDevice _device,VkPipelineCache pipelineCache,uint32_t createInfoCount,const VkGraphicsPipelineCreateInfo * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)1813*61046927SAndroid Build Coastguard Worker vk_common_CreateGraphicsPipelines(VkDevice _device,
1814*61046927SAndroid Build Coastguard Worker                                   VkPipelineCache pipelineCache,
1815*61046927SAndroid Build Coastguard Worker                                   uint32_t createInfoCount,
1816*61046927SAndroid Build Coastguard Worker                                   const VkGraphicsPipelineCreateInfo *pCreateInfos,
1817*61046927SAndroid Build Coastguard Worker                                   const VkAllocationCallbacks *pAllocator,
1818*61046927SAndroid Build Coastguard Worker                                   VkPipeline *pPipelines)
1819*61046927SAndroid Build Coastguard Worker {
1820*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
1821*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline_cache, cache, pipelineCache);
1822*61046927SAndroid Build Coastguard Worker    VkResult first_error_or_success = VK_SUCCESS;
1823*61046927SAndroid Build Coastguard Worker 
1824*61046927SAndroid Build Coastguard Worker    /* Use implicit pipeline cache if there's no cache set */
1825*61046927SAndroid Build Coastguard Worker    if (!cache && device->mem_cache)
1826*61046927SAndroid Build Coastguard Worker       cache = device->mem_cache;
1827*61046927SAndroid Build Coastguard Worker 
1828*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.3.274 spec:
1829*61046927SAndroid Build Coastguard Worker     *
1830*61046927SAndroid Build Coastguard Worker     *    "When attempting to create many pipelines in a single command, it is
1831*61046927SAndroid Build Coastguard Worker     *    possible that creation may fail for a subset of them. In this case,
1832*61046927SAndroid Build Coastguard Worker     *    the corresponding elements of pPipelines will be set to
1833*61046927SAndroid Build Coastguard Worker     *    VK_NULL_HANDLE.
1834*61046927SAndroid Build Coastguard Worker     */
1835*61046927SAndroid Build Coastguard Worker    memset(pPipelines, 0, createInfoCount * sizeof(*pPipelines));
1836*61046927SAndroid Build Coastguard Worker 
1837*61046927SAndroid Build Coastguard Worker    unsigned i = 0;
1838*61046927SAndroid Build Coastguard Worker    for (; i < createInfoCount; i++) {
1839*61046927SAndroid Build Coastguard Worker       VkResult result = vk_create_graphics_pipeline(device, cache,
1840*61046927SAndroid Build Coastguard Worker                                                     &pCreateInfos[i],
1841*61046927SAndroid Build Coastguard Worker                                                     pAllocator,
1842*61046927SAndroid Build Coastguard Worker                                                     &pPipelines[i]);
1843*61046927SAndroid Build Coastguard Worker       if (result == VK_SUCCESS)
1844*61046927SAndroid Build Coastguard Worker          continue;
1845*61046927SAndroid Build Coastguard Worker 
1846*61046927SAndroid Build Coastguard Worker       if (first_error_or_success == VK_SUCCESS)
1847*61046927SAndroid Build Coastguard Worker          first_error_or_success = result;
1848*61046927SAndroid Build Coastguard Worker 
1849*61046927SAndroid Build Coastguard Worker       /* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED as it
1850*61046927SAndroid Build Coastguard Worker        * is not obvious what error should be report upon 2 different failures.
1851*61046927SAndroid Build Coastguard Worker        */
1852*61046927SAndroid Build Coastguard Worker       if (result != VK_PIPELINE_COMPILE_REQUIRED)
1853*61046927SAndroid Build Coastguard Worker          return result;
1854*61046927SAndroid Build Coastguard Worker 
1855*61046927SAndroid Build Coastguard Worker       const VkPipelineCreateFlags2KHR flags =
1856*61046927SAndroid Build Coastguard Worker          vk_graphics_pipeline_create_flags(&pCreateInfos[i]);
1857*61046927SAndroid Build Coastguard Worker       if (flags & VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR)
1858*61046927SAndroid Build Coastguard Worker          return result;
1859*61046927SAndroid Build Coastguard Worker    }
1860*61046927SAndroid Build Coastguard Worker 
1861*61046927SAndroid Build Coastguard Worker    return first_error_or_success;
1862*61046927SAndroid Build Coastguard Worker }
1863*61046927SAndroid Build Coastguard Worker 
1864*61046927SAndroid Build Coastguard Worker struct vk_compute_pipeline {
1865*61046927SAndroid Build Coastguard Worker    struct vk_pipeline base;
1866*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader;
1867*61046927SAndroid Build Coastguard Worker };
1868*61046927SAndroid Build Coastguard Worker 
1869*61046927SAndroid Build Coastguard Worker static void
vk_compute_pipeline_destroy(struct vk_device * device,struct vk_pipeline * pipeline,const VkAllocationCallbacks * pAllocator)1870*61046927SAndroid Build Coastguard Worker vk_compute_pipeline_destroy(struct vk_device *device,
1871*61046927SAndroid Build Coastguard Worker                             struct vk_pipeline *pipeline,
1872*61046927SAndroid Build Coastguard Worker                             const VkAllocationCallbacks *pAllocator)
1873*61046927SAndroid Build Coastguard Worker {
1874*61046927SAndroid Build Coastguard Worker    struct vk_compute_pipeline *comp_pipeline =
1875*61046927SAndroid Build Coastguard Worker       container_of(pipeline, struct vk_compute_pipeline, base);
1876*61046927SAndroid Build Coastguard Worker 
1877*61046927SAndroid Build Coastguard Worker    vk_shader_unref(device, comp_pipeline->shader);
1878*61046927SAndroid Build Coastguard Worker    vk_pipeline_free(device, pAllocator, pipeline);
1879*61046927SAndroid Build Coastguard Worker }
1880*61046927SAndroid Build Coastguard Worker 
1881*61046927SAndroid Build Coastguard Worker static void
vk_compute_pipeline_cmd_bind(struct vk_command_buffer * cmd_buffer,struct vk_pipeline * pipeline)1882*61046927SAndroid Build Coastguard Worker vk_compute_pipeline_cmd_bind(struct vk_command_buffer *cmd_buffer,
1883*61046927SAndroid Build Coastguard Worker                              struct vk_pipeline *pipeline)
1884*61046927SAndroid Build Coastguard Worker {
1885*61046927SAndroid Build Coastguard Worker    struct vk_device *device = cmd_buffer->base.device;
1886*61046927SAndroid Build Coastguard Worker    const struct vk_device_shader_ops *ops = device->shader_ops;
1887*61046927SAndroid Build Coastguard Worker 
1888*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader = NULL;
1889*61046927SAndroid Build Coastguard Worker    if (pipeline != NULL) {
1890*61046927SAndroid Build Coastguard Worker       assert(pipeline->bind_point == VK_PIPELINE_BIND_POINT_COMPUTE);
1891*61046927SAndroid Build Coastguard Worker       struct vk_compute_pipeline *comp_pipeline =
1892*61046927SAndroid Build Coastguard Worker          container_of(pipeline, struct vk_compute_pipeline, base);
1893*61046927SAndroid Build Coastguard Worker 
1894*61046927SAndroid Build Coastguard Worker       shader = comp_pipeline->shader;
1895*61046927SAndroid Build Coastguard Worker 
1896*61046927SAndroid Build Coastguard Worker       cmd_buffer->pipeline_shader_stages |= VK_SHADER_STAGE_COMPUTE_BIT;
1897*61046927SAndroid Build Coastguard Worker    } else {
1898*61046927SAndroid Build Coastguard Worker       cmd_buffer->pipeline_shader_stages &= ~VK_SHADER_STAGE_COMPUTE_BIT;
1899*61046927SAndroid Build Coastguard Worker    }
1900*61046927SAndroid Build Coastguard Worker 
1901*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage = MESA_SHADER_COMPUTE;
1902*61046927SAndroid Build Coastguard Worker    ops->cmd_bind_shaders(cmd_buffer, 1, &stage, &shader);
1903*61046927SAndroid Build Coastguard Worker }
1904*61046927SAndroid Build Coastguard Worker 
1905*61046927SAndroid Build Coastguard Worker static VkResult
vk_pipeline_compile_compute_stage(struct vk_device * device,struct vk_pipeline_cache * cache,struct vk_compute_pipeline * pipeline,struct vk_pipeline_layout * pipeline_layout,struct vk_pipeline_stage * stage,bool * cache_hit)1906*61046927SAndroid Build Coastguard Worker vk_pipeline_compile_compute_stage(struct vk_device *device,
1907*61046927SAndroid Build Coastguard Worker                                   struct vk_pipeline_cache *cache,
1908*61046927SAndroid Build Coastguard Worker                                   struct vk_compute_pipeline *pipeline,
1909*61046927SAndroid Build Coastguard Worker                                   struct vk_pipeline_layout *pipeline_layout,
1910*61046927SAndroid Build Coastguard Worker                                   struct vk_pipeline_stage *stage,
1911*61046927SAndroid Build Coastguard Worker                                   bool *cache_hit)
1912*61046927SAndroid Build Coastguard Worker {
1913*61046927SAndroid Build Coastguard Worker    const struct vk_device_shader_ops *ops = device->shader_ops;
1914*61046927SAndroid Build Coastguard Worker    VkResult result;
1915*61046927SAndroid Build Coastguard Worker 
1916*61046927SAndroid Build Coastguard Worker    const VkPushConstantRange *push_range = NULL;
1917*61046927SAndroid Build Coastguard Worker    if (pipeline_layout != NULL) {
1918*61046927SAndroid Build Coastguard Worker       for (uint32_t r = 0; r < pipeline_layout->push_range_count; r++) {
1919*61046927SAndroid Build Coastguard Worker          if (pipeline_layout->push_ranges[r].stageFlags &
1920*61046927SAndroid Build Coastguard Worker              VK_SHADER_STAGE_COMPUTE_BIT) {
1921*61046927SAndroid Build Coastguard Worker             assert(push_range == NULL);
1922*61046927SAndroid Build Coastguard Worker             push_range = &pipeline_layout->push_ranges[r];
1923*61046927SAndroid Build Coastguard Worker          }
1924*61046927SAndroid Build Coastguard Worker       }
1925*61046927SAndroid Build Coastguard Worker    }
1926*61046927SAndroid Build Coastguard Worker 
1927*61046927SAndroid Build Coastguard Worker    VkShaderCreateFlagsEXT shader_flags =
1928*61046927SAndroid Build Coastguard Worker       vk_pipeline_to_shader_flags(pipeline->base.flags, MESA_SHADER_COMPUTE);
1929*61046927SAndroid Build Coastguard Worker 
1930*61046927SAndroid Build Coastguard Worker    struct mesa_blake3 blake3_ctx;
1931*61046927SAndroid Build Coastguard Worker    _mesa_blake3_init(&blake3_ctx);
1932*61046927SAndroid Build Coastguard Worker 
1933*61046927SAndroid Build Coastguard Worker    _mesa_blake3_update(&blake3_ctx, stage->precomp->blake3,
1934*61046927SAndroid Build Coastguard Worker                      sizeof(stage->precomp->blake3));
1935*61046927SAndroid Build Coastguard Worker 
1936*61046927SAndroid Build Coastguard Worker    _mesa_blake3_update(&blake3_ctx, &shader_flags, sizeof(shader_flags));
1937*61046927SAndroid Build Coastguard Worker 
1938*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pipeline_layout->set_count; i++) {
1939*61046927SAndroid Build Coastguard Worker       if (pipeline_layout->set_layouts[i] != NULL) {
1940*61046927SAndroid Build Coastguard Worker          _mesa_blake3_update(&blake3_ctx,
1941*61046927SAndroid Build Coastguard Worker                              pipeline_layout->set_layouts[i]->blake3,
1942*61046927SAndroid Build Coastguard Worker                              sizeof(pipeline_layout->set_layouts[i]->blake3));
1943*61046927SAndroid Build Coastguard Worker       }
1944*61046927SAndroid Build Coastguard Worker    }
1945*61046927SAndroid Build Coastguard Worker    if (push_range != NULL)
1946*61046927SAndroid Build Coastguard Worker       _mesa_blake3_update(&blake3_ctx, push_range, sizeof(*push_range));
1947*61046927SAndroid Build Coastguard Worker 
1948*61046927SAndroid Build Coastguard Worker    struct vk_shader_pipeline_cache_key shader_key = {
1949*61046927SAndroid Build Coastguard Worker       .stage = MESA_SHADER_COMPUTE,
1950*61046927SAndroid Build Coastguard Worker    };
1951*61046927SAndroid Build Coastguard Worker    _mesa_blake3_final(&blake3_ctx, shader_key.blake3);
1952*61046927SAndroid Build Coastguard Worker 
1953*61046927SAndroid Build Coastguard Worker    if (cache != NULL) {
1954*61046927SAndroid Build Coastguard Worker       struct vk_pipeline_cache_object *cache_obj =
1955*61046927SAndroid Build Coastguard Worker          vk_pipeline_cache_lookup_object(cache, &shader_key,
1956*61046927SAndroid Build Coastguard Worker                                          sizeof(shader_key),
1957*61046927SAndroid Build Coastguard Worker                                          &pipeline_shader_cache_ops,
1958*61046927SAndroid Build Coastguard Worker                                          cache_hit);
1959*61046927SAndroid Build Coastguard Worker       if (cache_obj != NULL) {
1960*61046927SAndroid Build Coastguard Worker          stage->shader = vk_shader_from_cache_obj(cache_obj);
1961*61046927SAndroid Build Coastguard Worker          return VK_SUCCESS;
1962*61046927SAndroid Build Coastguard Worker       }
1963*61046927SAndroid Build Coastguard Worker    }
1964*61046927SAndroid Build Coastguard Worker 
1965*61046927SAndroid Build Coastguard Worker    if (pipeline->base.flags &
1966*61046927SAndroid Build Coastguard Worker        VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_KHR)
1967*61046927SAndroid Build Coastguard Worker       return VK_PIPELINE_COMPILE_REQUIRED;
1968*61046927SAndroid Build Coastguard Worker 
1969*61046927SAndroid Build Coastguard Worker    const struct nir_shader_compiler_options *nir_options =
1970*61046927SAndroid Build Coastguard Worker       ops->get_nir_options(device->physical, stage->stage,
1971*61046927SAndroid Build Coastguard Worker                            &stage->precomp->rs);
1972*61046927SAndroid Build Coastguard Worker 
1973*61046927SAndroid Build Coastguard Worker    nir_shader *nir = vk_pipeline_precomp_shader_get_nir(stage->precomp,
1974*61046927SAndroid Build Coastguard Worker                                                         nir_options);
1975*61046927SAndroid Build Coastguard Worker    if (nir == NULL)
1976*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1977*61046927SAndroid Build Coastguard Worker 
1978*61046927SAndroid Build Coastguard Worker    /* vk_device_shader_ops::compile() consumes the NIR regardless of whether
1979*61046927SAndroid Build Coastguard Worker     * or not it succeeds and only generates shaders on success. Once compile()
1980*61046927SAndroid Build Coastguard Worker     * returns, we own the shaders but not the NIR in infos.
1981*61046927SAndroid Build Coastguard Worker     */
1982*61046927SAndroid Build Coastguard Worker    struct vk_shader_compile_info compile_info = {
1983*61046927SAndroid Build Coastguard Worker       .stage = stage->stage,
1984*61046927SAndroid Build Coastguard Worker       .flags = shader_flags,
1985*61046927SAndroid Build Coastguard Worker       .next_stage_mask = 0,
1986*61046927SAndroid Build Coastguard Worker       .nir = nir,
1987*61046927SAndroid Build Coastguard Worker       .robustness = &stage->precomp->rs,
1988*61046927SAndroid Build Coastguard Worker       .set_layout_count = pipeline_layout->set_count,
1989*61046927SAndroid Build Coastguard Worker       .set_layouts = pipeline_layout->set_layouts,
1990*61046927SAndroid Build Coastguard Worker       .push_constant_range_count = push_range != NULL,
1991*61046927SAndroid Build Coastguard Worker       .push_constant_ranges = push_range != NULL ? push_range : NULL,
1992*61046927SAndroid Build Coastguard Worker    };
1993*61046927SAndroid Build Coastguard Worker 
1994*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader;
1995*61046927SAndroid Build Coastguard Worker    result = ops->compile(device, 1, &compile_info, NULL,
1996*61046927SAndroid Build Coastguard Worker                          &device->alloc, &shader);
1997*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
1998*61046927SAndroid Build Coastguard Worker       return result;
1999*61046927SAndroid Build Coastguard Worker 
2000*61046927SAndroid Build Coastguard Worker    vk_shader_init_cache_obj(device, shader, &shader_key, sizeof(shader_key));
2001*61046927SAndroid Build Coastguard Worker 
2002*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_cache_object *cache_obj = &shader->pipeline.cache_obj;
2003*61046927SAndroid Build Coastguard Worker    if (cache != NULL)
2004*61046927SAndroid Build Coastguard Worker       cache_obj = vk_pipeline_cache_add_object(cache, cache_obj);
2005*61046927SAndroid Build Coastguard Worker 
2006*61046927SAndroid Build Coastguard Worker    stage->shader = vk_shader_from_cache_obj(cache_obj);
2007*61046927SAndroid Build Coastguard Worker 
2008*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
2009*61046927SAndroid Build Coastguard Worker }
2010*61046927SAndroid Build Coastguard Worker 
2011*61046927SAndroid Build Coastguard Worker static VkResult
vk_compute_pipeline_get_executable_properties(struct vk_device * device,struct vk_pipeline * pipeline,uint32_t * executable_count,VkPipelineExecutablePropertiesKHR * properties)2012*61046927SAndroid Build Coastguard Worker vk_compute_pipeline_get_executable_properties(
2013*61046927SAndroid Build Coastguard Worker    struct vk_device *device,
2014*61046927SAndroid Build Coastguard Worker    struct vk_pipeline *pipeline,
2015*61046927SAndroid Build Coastguard Worker    uint32_t *executable_count,
2016*61046927SAndroid Build Coastguard Worker    VkPipelineExecutablePropertiesKHR *properties)
2017*61046927SAndroid Build Coastguard Worker {
2018*61046927SAndroid Build Coastguard Worker    struct vk_compute_pipeline *comp_pipeline =
2019*61046927SAndroid Build Coastguard Worker       container_of(pipeline, struct vk_compute_pipeline, base);
2020*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader = comp_pipeline->shader;
2021*61046927SAndroid Build Coastguard Worker 
2022*61046927SAndroid Build Coastguard Worker    return shader->ops->get_executable_properties(device, shader,
2023*61046927SAndroid Build Coastguard Worker                                                  executable_count,
2024*61046927SAndroid Build Coastguard Worker                                                  properties);
2025*61046927SAndroid Build Coastguard Worker }
2026*61046927SAndroid Build Coastguard Worker 
2027*61046927SAndroid Build Coastguard Worker static VkResult
vk_compute_pipeline_get_executable_statistics(struct vk_device * device,struct vk_pipeline * pipeline,uint32_t executable_index,uint32_t * statistic_count,VkPipelineExecutableStatisticKHR * statistics)2028*61046927SAndroid Build Coastguard Worker vk_compute_pipeline_get_executable_statistics(
2029*61046927SAndroid Build Coastguard Worker    struct vk_device *device,
2030*61046927SAndroid Build Coastguard Worker    struct vk_pipeline *pipeline,
2031*61046927SAndroid Build Coastguard Worker    uint32_t executable_index,
2032*61046927SAndroid Build Coastguard Worker    uint32_t *statistic_count,
2033*61046927SAndroid Build Coastguard Worker    VkPipelineExecutableStatisticKHR *statistics)
2034*61046927SAndroid Build Coastguard Worker {
2035*61046927SAndroid Build Coastguard Worker    struct vk_compute_pipeline *comp_pipeline =
2036*61046927SAndroid Build Coastguard Worker       container_of(pipeline, struct vk_compute_pipeline, base);
2037*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader = comp_pipeline->shader;
2038*61046927SAndroid Build Coastguard Worker 
2039*61046927SAndroid Build Coastguard Worker    return shader->ops->get_executable_statistics(device, shader,
2040*61046927SAndroid Build Coastguard Worker                                                  executable_index,
2041*61046927SAndroid Build Coastguard Worker                                                  statistic_count,
2042*61046927SAndroid Build Coastguard Worker                                                  statistics);
2043*61046927SAndroid Build Coastguard Worker }
2044*61046927SAndroid Build Coastguard Worker 
2045*61046927SAndroid Build Coastguard Worker static VkResult
vk_compute_pipeline_get_internal_representations(struct vk_device * device,struct vk_pipeline * pipeline,uint32_t executable_index,uint32_t * internal_representation_count,VkPipelineExecutableInternalRepresentationKHR * internal_representations)2046*61046927SAndroid Build Coastguard Worker vk_compute_pipeline_get_internal_representations(
2047*61046927SAndroid Build Coastguard Worker    struct vk_device *device,
2048*61046927SAndroid Build Coastguard Worker    struct vk_pipeline *pipeline,
2049*61046927SAndroid Build Coastguard Worker    uint32_t executable_index,
2050*61046927SAndroid Build Coastguard Worker    uint32_t *internal_representation_count,
2051*61046927SAndroid Build Coastguard Worker    VkPipelineExecutableInternalRepresentationKHR* internal_representations)
2052*61046927SAndroid Build Coastguard Worker {
2053*61046927SAndroid Build Coastguard Worker    struct vk_compute_pipeline *comp_pipeline =
2054*61046927SAndroid Build Coastguard Worker       container_of(pipeline, struct vk_compute_pipeline, base);
2055*61046927SAndroid Build Coastguard Worker    struct vk_shader *shader = comp_pipeline->shader;
2056*61046927SAndroid Build Coastguard Worker 
2057*61046927SAndroid Build Coastguard Worker    return shader->ops->get_executable_internal_representations(
2058*61046927SAndroid Build Coastguard Worker       device, shader, executable_index,
2059*61046927SAndroid Build Coastguard Worker       internal_representation_count, internal_representations);
2060*61046927SAndroid Build Coastguard Worker }
2061*61046927SAndroid Build Coastguard Worker 
2062*61046927SAndroid Build Coastguard Worker static const struct vk_pipeline_ops vk_compute_pipeline_ops = {
2063*61046927SAndroid Build Coastguard Worker    .destroy = vk_compute_pipeline_destroy,
2064*61046927SAndroid Build Coastguard Worker    .get_executable_statistics = vk_compute_pipeline_get_executable_statistics,
2065*61046927SAndroid Build Coastguard Worker    .get_executable_properties = vk_compute_pipeline_get_executable_properties,
2066*61046927SAndroid Build Coastguard Worker    .get_internal_representations = vk_compute_pipeline_get_internal_representations,
2067*61046927SAndroid Build Coastguard Worker    .cmd_bind = vk_compute_pipeline_cmd_bind,
2068*61046927SAndroid Build Coastguard Worker };
2069*61046927SAndroid Build Coastguard Worker 
2070*61046927SAndroid Build Coastguard Worker static VkResult
vk_create_compute_pipeline(struct vk_device * device,struct vk_pipeline_cache * cache,const VkComputePipelineCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipeline)2071*61046927SAndroid Build Coastguard Worker vk_create_compute_pipeline(struct vk_device *device,
2072*61046927SAndroid Build Coastguard Worker                            struct vk_pipeline_cache *cache,
2073*61046927SAndroid Build Coastguard Worker                            const VkComputePipelineCreateInfo *pCreateInfo,
2074*61046927SAndroid Build Coastguard Worker                            const VkAllocationCallbacks *pAllocator,
2075*61046927SAndroid Build Coastguard Worker                            VkPipeline *pPipeline)
2076*61046927SAndroid Build Coastguard Worker {
2077*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline_layout, pipeline_layout, pCreateInfo->layout);
2078*61046927SAndroid Build Coastguard Worker    int64_t pipeline_start = os_time_get_nano();
2079*61046927SAndroid Build Coastguard Worker    VkResult result;
2080*61046927SAndroid Build Coastguard Worker 
2081*61046927SAndroid Build Coastguard Worker    const VkPipelineCreateFlags2KHR pipeline_flags =
2082*61046927SAndroid Build Coastguard Worker       vk_compute_pipeline_create_flags(pCreateInfo);
2083*61046927SAndroid Build Coastguard Worker 
2084*61046927SAndroid Build Coastguard Worker    const VkPipelineCreationFeedbackCreateInfo *feedback_info =
2085*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext,
2086*61046927SAndroid Build Coastguard Worker                            PIPELINE_CREATION_FEEDBACK_CREATE_INFO);
2087*61046927SAndroid Build Coastguard Worker 
2088*61046927SAndroid Build Coastguard Worker    struct vk_compute_pipeline *pipeline =
2089*61046927SAndroid Build Coastguard Worker       vk_pipeline_zalloc(device, &vk_compute_pipeline_ops,
2090*61046927SAndroid Build Coastguard Worker                          VK_PIPELINE_BIND_POINT_COMPUTE,
2091*61046927SAndroid Build Coastguard Worker                          pipeline_flags, pAllocator, sizeof(*pipeline));
2092*61046927SAndroid Build Coastguard Worker    if (pipeline == NULL)
2093*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2094*61046927SAndroid Build Coastguard Worker 
2095*61046927SAndroid Build Coastguard Worker    struct vk_pipeline_stage stage = {
2096*61046927SAndroid Build Coastguard Worker       .stage = MESA_SHADER_COMPUTE,
2097*61046927SAndroid Build Coastguard Worker    };
2098*61046927SAndroid Build Coastguard Worker    result = vk_pipeline_precompile_shader(device, cache, pipeline_flags,
2099*61046927SAndroid Build Coastguard Worker                                           pCreateInfo->pNext,
2100*61046927SAndroid Build Coastguard Worker                                           &pCreateInfo->stage,
2101*61046927SAndroid Build Coastguard Worker                                           &stage.precomp);
2102*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
2103*61046927SAndroid Build Coastguard Worker       goto fail_pipeline;
2104*61046927SAndroid Build Coastguard Worker 
2105*61046927SAndroid Build Coastguard Worker    bool cache_hit;
2106*61046927SAndroid Build Coastguard Worker    result = vk_pipeline_compile_compute_stage(device, cache, pipeline,
2107*61046927SAndroid Build Coastguard Worker                                               pipeline_layout, &stage,
2108*61046927SAndroid Build Coastguard Worker                                               &cache_hit);
2109*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
2110*61046927SAndroid Build Coastguard Worker       goto fail_stage;
2111*61046927SAndroid Build Coastguard Worker 
2112*61046927SAndroid Build Coastguard Worker    if (stage.precomp != NULL)
2113*61046927SAndroid Build Coastguard Worker       vk_pipeline_precomp_shader_unref(device, stage.precomp);
2114*61046927SAndroid Build Coastguard Worker    pipeline->shader = stage.shader;
2115*61046927SAndroid Build Coastguard Worker 
2116*61046927SAndroid Build Coastguard Worker    const int64_t pipeline_end = os_time_get_nano();
2117*61046927SAndroid Build Coastguard Worker    if (feedback_info != NULL) {
2118*61046927SAndroid Build Coastguard Worker       VkPipelineCreationFeedback pipeline_feedback = {
2119*61046927SAndroid Build Coastguard Worker          .flags = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT,
2120*61046927SAndroid Build Coastguard Worker          .duration = pipeline_end - pipeline_start,
2121*61046927SAndroid Build Coastguard Worker       };
2122*61046927SAndroid Build Coastguard Worker       if (cache_hit && cache != device->mem_cache) {
2123*61046927SAndroid Build Coastguard Worker          pipeline_feedback.flags |=
2124*61046927SAndroid Build Coastguard Worker             VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT;
2125*61046927SAndroid Build Coastguard Worker       }
2126*61046927SAndroid Build Coastguard Worker 
2127*61046927SAndroid Build Coastguard Worker       *feedback_info->pPipelineCreationFeedback = pipeline_feedback;
2128*61046927SAndroid Build Coastguard Worker       if (feedback_info->pipelineStageCreationFeedbackCount > 0) {
2129*61046927SAndroid Build Coastguard Worker          feedback_info->pPipelineStageCreationFeedbacks[0] =
2130*61046927SAndroid Build Coastguard Worker             pipeline_feedback;
2131*61046927SAndroid Build Coastguard Worker       }
2132*61046927SAndroid Build Coastguard Worker    }
2133*61046927SAndroid Build Coastguard Worker 
2134*61046927SAndroid Build Coastguard Worker    *pPipeline = vk_pipeline_to_handle(&pipeline->base);
2135*61046927SAndroid Build Coastguard Worker 
2136*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
2137*61046927SAndroid Build Coastguard Worker 
2138*61046927SAndroid Build Coastguard Worker fail_stage:
2139*61046927SAndroid Build Coastguard Worker    vk_pipeline_stage_finish(device, &stage);
2140*61046927SAndroid Build Coastguard Worker fail_pipeline:
2141*61046927SAndroid Build Coastguard Worker    vk_pipeline_free(device, pAllocator, &pipeline->base);
2142*61046927SAndroid Build Coastguard Worker 
2143*61046927SAndroid Build Coastguard Worker    return result;
2144*61046927SAndroid Build Coastguard Worker }
2145*61046927SAndroid Build Coastguard Worker 
2146*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateComputePipelines(VkDevice _device,VkPipelineCache pipelineCache,uint32_t createInfoCount,const VkComputePipelineCreateInfo * pCreateInfos,const VkAllocationCallbacks * pAllocator,VkPipeline * pPipelines)2147*61046927SAndroid Build Coastguard Worker vk_common_CreateComputePipelines(VkDevice _device,
2148*61046927SAndroid Build Coastguard Worker                                  VkPipelineCache pipelineCache,
2149*61046927SAndroid Build Coastguard Worker                                  uint32_t createInfoCount,
2150*61046927SAndroid Build Coastguard Worker                                  const VkComputePipelineCreateInfo *pCreateInfos,
2151*61046927SAndroid Build Coastguard Worker                                  const VkAllocationCallbacks *pAllocator,
2152*61046927SAndroid Build Coastguard Worker                                  VkPipeline *pPipelines)
2153*61046927SAndroid Build Coastguard Worker {
2154*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
2155*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_pipeline_cache, cache, pipelineCache);
2156*61046927SAndroid Build Coastguard Worker    VkResult first_error_or_success = VK_SUCCESS;
2157*61046927SAndroid Build Coastguard Worker 
2158*61046927SAndroid Build Coastguard Worker    /* Use implicit pipeline cache if there's no cache set */
2159*61046927SAndroid Build Coastguard Worker    if (!cache && device->mem_cache)
2160*61046927SAndroid Build Coastguard Worker       cache = device->mem_cache;
2161*61046927SAndroid Build Coastguard Worker 
2162*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.3.274 spec:
2163*61046927SAndroid Build Coastguard Worker     *
2164*61046927SAndroid Build Coastguard Worker     *    "When attempting to create many pipelines in a single command, it is
2165*61046927SAndroid Build Coastguard Worker     *    possible that creation may fail for a subset of them. In this case,
2166*61046927SAndroid Build Coastguard Worker     *    the corresponding elements of pPipelines will be set to
2167*61046927SAndroid Build Coastguard Worker     *    VK_NULL_HANDLE.
2168*61046927SAndroid Build Coastguard Worker     */
2169*61046927SAndroid Build Coastguard Worker    memset(pPipelines, 0, createInfoCount * sizeof(*pPipelines));
2170*61046927SAndroid Build Coastguard Worker 
2171*61046927SAndroid Build Coastguard Worker    unsigned i = 0;
2172*61046927SAndroid Build Coastguard Worker    for (; i < createInfoCount; i++) {
2173*61046927SAndroid Build Coastguard Worker       VkResult result = vk_create_compute_pipeline(device, cache,
2174*61046927SAndroid Build Coastguard Worker                                                    &pCreateInfos[i],
2175*61046927SAndroid Build Coastguard Worker                                                    pAllocator,
2176*61046927SAndroid Build Coastguard Worker                                                    &pPipelines[i]);
2177*61046927SAndroid Build Coastguard Worker       if (result == VK_SUCCESS)
2178*61046927SAndroid Build Coastguard Worker          continue;
2179*61046927SAndroid Build Coastguard Worker 
2180*61046927SAndroid Build Coastguard Worker       if (first_error_or_success == VK_SUCCESS)
2181*61046927SAndroid Build Coastguard Worker          first_error_or_success = result;
2182*61046927SAndroid Build Coastguard Worker 
2183*61046927SAndroid Build Coastguard Worker       /* Bail out on the first error != VK_PIPELINE_COMPILE_REQUIRED as it
2184*61046927SAndroid Build Coastguard Worker        * is not obvious what error should be report upon 2 different failures.
2185*61046927SAndroid Build Coastguard Worker        */
2186*61046927SAndroid Build Coastguard Worker       if (result != VK_PIPELINE_COMPILE_REQUIRED)
2187*61046927SAndroid Build Coastguard Worker          return result;
2188*61046927SAndroid Build Coastguard Worker 
2189*61046927SAndroid Build Coastguard Worker       const VkPipelineCreateFlags2KHR flags =
2190*61046927SAndroid Build Coastguard Worker          vk_compute_pipeline_create_flags(&pCreateInfos[i]);
2191*61046927SAndroid Build Coastguard Worker       if (flags & VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT_KHR)
2192*61046927SAndroid Build Coastguard Worker          return result;
2193*61046927SAndroid Build Coastguard Worker    }
2194*61046927SAndroid Build Coastguard Worker 
2195*61046927SAndroid Build Coastguard Worker    return first_error_or_success;
2196*61046927SAndroid Build Coastguard Worker }
2197*61046927SAndroid Build Coastguard Worker 
2198*61046927SAndroid Build Coastguard Worker void
vk_cmd_unbind_pipelines_for_stages(struct vk_command_buffer * cmd_buffer,VkShaderStageFlags stages)2199*61046927SAndroid Build Coastguard Worker vk_cmd_unbind_pipelines_for_stages(struct vk_command_buffer *cmd_buffer,
2200*61046927SAndroid Build Coastguard Worker                                    VkShaderStageFlags stages)
2201*61046927SAndroid Build Coastguard Worker {
2202*61046927SAndroid Build Coastguard Worker    stages &= cmd_buffer->pipeline_shader_stages;
2203*61046927SAndroid Build Coastguard Worker 
2204*61046927SAndroid Build Coastguard Worker    if (stages & ~VK_SHADER_STAGE_COMPUTE_BIT)
2205*61046927SAndroid Build Coastguard Worker       vk_graphics_pipeline_cmd_bind(cmd_buffer, NULL);
2206*61046927SAndroid Build Coastguard Worker 
2207*61046927SAndroid Build Coastguard Worker    if (stages & VK_SHADER_STAGE_COMPUTE_BIT)
2208*61046927SAndroid Build Coastguard Worker       vk_compute_pipeline_cmd_bind(cmd_buffer, NULL);
2209*61046927SAndroid Build Coastguard Worker }
2210