xref: /aosp_15_r20/external/mesa3d/src/asahi/vulkan/hk_shader.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2024 Valve Corporation
3*61046927SAndroid Build Coastguard Worker  * Copyright 2024 Alyssa Rosenzweig
4*61046927SAndroid Build Coastguard Worker  * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
6*61046927SAndroid Build Coastguard Worker  */
7*61046927SAndroid Build Coastguard Worker #include "hk_shader.h"
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #include "agx_helpers.h"
10*61046927SAndroid Build Coastguard Worker #include "agx_nir_lower_gs.h"
11*61046927SAndroid Build Coastguard Worker #include "glsl_types.h"
12*61046927SAndroid Build Coastguard Worker #include "nir.h"
13*61046927SAndroid Build Coastguard Worker #include "nir_builder.h"
14*61046927SAndroid Build Coastguard Worker 
15*61046927SAndroid Build Coastguard Worker #include "agx_bo.h"
16*61046927SAndroid Build Coastguard Worker #include "hk_cmd_buffer.h"
17*61046927SAndroid Build Coastguard Worker #include "hk_descriptor_set_layout.h"
18*61046927SAndroid Build Coastguard Worker #include "hk_device.h"
19*61046927SAndroid Build Coastguard Worker #include "hk_physical_device.h"
20*61046927SAndroid Build Coastguard Worker #include "hk_sampler.h"
21*61046927SAndroid Build Coastguard Worker #include "hk_shader.h"
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker #include "nir_builder_opcodes.h"
24*61046927SAndroid Build Coastguard Worker #include "nir_builtin_builder.h"
25*61046927SAndroid Build Coastguard Worker #include "nir_intrinsics.h"
26*61046927SAndroid Build Coastguard Worker #include "nir_intrinsics_indices.h"
27*61046927SAndroid Build Coastguard Worker #include "nir_xfb_info.h"
28*61046927SAndroid Build Coastguard Worker #include "shader_enums.h"
29*61046927SAndroid Build Coastguard Worker #include "vk_nir_convert_ycbcr.h"
30*61046927SAndroid Build Coastguard Worker #include "vk_pipeline.h"
31*61046927SAndroid Build Coastguard Worker #include "vk_pipeline_layout.h"
32*61046927SAndroid Build Coastguard Worker #include "vk_shader_module.h"
33*61046927SAndroid Build Coastguard Worker #include "vk_ycbcr_conversion.h"
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker #include "asahi/compiler/agx_compile.h"
36*61046927SAndroid Build Coastguard Worker #include "asahi/lib/agx_linker.h"
37*61046927SAndroid Build Coastguard Worker #include "asahi/lib/agx_nir_passes.h"
38*61046927SAndroid Build Coastguard Worker #include "asahi/lib/agx_tilebuffer.h"
39*61046927SAndroid Build Coastguard Worker #include "asahi/lib/agx_uvs.h"
40*61046927SAndroid Build Coastguard Worker #include "compiler/spirv/nir_spirv.h"
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker #include "util/blob.h"
43*61046927SAndroid Build Coastguard Worker #include "util/hash_table.h"
44*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
45*61046927SAndroid Build Coastguard Worker #include "util/mesa-sha1.h"
46*61046927SAndroid Build Coastguard Worker #include "util/simple_mtx.h"
47*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
48*61046927SAndroid Build Coastguard Worker #include "vulkan/vulkan_core.h"
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker struct hk_fs_key {
51*61046927SAndroid Build Coastguard Worker    bool zs_self_dep;
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker    /** True if sample shading is forced on via an API knob such as
54*61046927SAndroid Build Coastguard Worker     * VkPipelineMultisampleStateCreateInfo::minSampleShading
55*61046927SAndroid Build Coastguard Worker     */
56*61046927SAndroid Build Coastguard Worker    bool force_sample_shading;
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker    uint8_t pad[2];
59*61046927SAndroid Build Coastguard Worker };
60*61046927SAndroid Build Coastguard Worker static_assert(sizeof(struct hk_fs_key) == 4, "packed");
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker static void
shared_var_info(const struct glsl_type * type,unsigned * size,unsigned * align)63*61046927SAndroid Build Coastguard Worker shared_var_info(const struct glsl_type *type, unsigned *size, unsigned *align)
64*61046927SAndroid Build Coastguard Worker {
65*61046927SAndroid Build Coastguard Worker    assert(glsl_type_is_vector_or_scalar(type));
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker    uint32_t comp_size =
68*61046927SAndroid Build Coastguard Worker       glsl_type_is_boolean(type) ? 4 : glsl_get_bit_size(type) / 8;
69*61046927SAndroid Build Coastguard Worker    unsigned length = glsl_get_vector_elements(type);
70*61046927SAndroid Build Coastguard Worker    *size = comp_size * length, *align = comp_size;
71*61046927SAndroid Build Coastguard Worker }
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker uint64_t
hk_physical_device_compiler_flags(const struct hk_physical_device * pdev)74*61046927SAndroid Build Coastguard Worker hk_physical_device_compiler_flags(const struct hk_physical_device *pdev)
75*61046927SAndroid Build Coastguard Worker {
76*61046927SAndroid Build Coastguard Worker    /* TODO compiler flags */
77*61046927SAndroid Build Coastguard Worker    return 0;
78*61046927SAndroid Build Coastguard Worker }
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker const nir_shader_compiler_options *
hk_get_nir_options(struct vk_physical_device * vk_pdev,gl_shader_stage stage,UNUSED const struct vk_pipeline_robustness_state * rs)81*61046927SAndroid Build Coastguard Worker hk_get_nir_options(struct vk_physical_device *vk_pdev, gl_shader_stage stage,
82*61046927SAndroid Build Coastguard Worker                    UNUSED const struct vk_pipeline_robustness_state *rs)
83*61046927SAndroid Build Coastguard Worker {
84*61046927SAndroid Build Coastguard Worker    return &agx_nir_options;
85*61046927SAndroid Build Coastguard Worker }
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker static struct spirv_to_nir_options
hk_get_spirv_options(struct vk_physical_device * vk_pdev,UNUSED gl_shader_stage stage,const struct vk_pipeline_robustness_state * rs)88*61046927SAndroid Build Coastguard Worker hk_get_spirv_options(struct vk_physical_device *vk_pdev,
89*61046927SAndroid Build Coastguard Worker                      UNUSED gl_shader_stage stage,
90*61046927SAndroid Build Coastguard Worker                      const struct vk_pipeline_robustness_state *rs)
91*61046927SAndroid Build Coastguard Worker {
92*61046927SAndroid Build Coastguard Worker    return (struct spirv_to_nir_options){
93*61046927SAndroid Build Coastguard Worker       .ssbo_addr_format = hk_buffer_addr_format(rs->storage_buffers),
94*61046927SAndroid Build Coastguard Worker       .phys_ssbo_addr_format = nir_address_format_64bit_global,
95*61046927SAndroid Build Coastguard Worker       .ubo_addr_format = hk_buffer_addr_format(rs->uniform_buffers),
96*61046927SAndroid Build Coastguard Worker       .shared_addr_format = nir_address_format_32bit_offset,
97*61046927SAndroid Build Coastguard Worker       .min_ssbo_alignment = HK_MIN_SSBO_ALIGNMENT,
98*61046927SAndroid Build Coastguard Worker       .min_ubo_alignment = HK_MIN_UBO_ALIGNMENT,
99*61046927SAndroid Build Coastguard Worker    };
100*61046927SAndroid Build Coastguard Worker }
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker static bool
lower_halt_to_return(nir_builder * b,nir_instr * instr,UNUSED void * _data)103*61046927SAndroid Build Coastguard Worker lower_halt_to_return(nir_builder *b, nir_instr *instr, UNUSED void *_data)
104*61046927SAndroid Build Coastguard Worker {
105*61046927SAndroid Build Coastguard Worker    if (instr->type != nir_instr_type_jump)
106*61046927SAndroid Build Coastguard Worker       return false;
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker    nir_jump_instr *jump = nir_instr_as_jump(instr);
109*61046927SAndroid Build Coastguard Worker    if (jump->type != nir_jump_halt)
110*61046927SAndroid Build Coastguard Worker       return false;
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker    assert(b->impl == nir_shader_get_entrypoint(b->shader));
113*61046927SAndroid Build Coastguard Worker    jump->type = nir_jump_return;
114*61046927SAndroid Build Coastguard Worker    return true;
115*61046927SAndroid Build Coastguard Worker }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker void
hk_preprocess_nir_internal(struct vk_physical_device * vk_pdev,nir_shader * nir)118*61046927SAndroid Build Coastguard Worker hk_preprocess_nir_internal(struct vk_physical_device *vk_pdev, nir_shader *nir)
119*61046927SAndroid Build Coastguard Worker {
120*61046927SAndroid Build Coastguard Worker    /* Must lower before io to temps */
121*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_FRAGMENT) {
122*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_terminate_to_demote);
123*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_shader_instructions_pass, lower_halt_to_return,
124*61046927SAndroid Build Coastguard Worker                nir_metadata_all, NULL);
125*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_returns);
126*61046927SAndroid Build Coastguard Worker    }
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    /* Unroll loops before lowering indirects via nir_lower_io_to_temporaries */
129*61046927SAndroid Build Coastguard Worker    UNUSED bool progress = false;
130*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_global_vars_to_local);
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker    do {
133*61046927SAndroid Build Coastguard Worker       progress = false;
134*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
135*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_copy_prop);
136*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_dce);
137*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_constant_folding);
138*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_loop);
139*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_loop_unroll);
140*61046927SAndroid Build Coastguard Worker    } while (progress);
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_FRAGMENT) {
143*61046927SAndroid Build Coastguard Worker       struct nir_lower_sysvals_to_varyings_options sysvals_opts = {
144*61046927SAndroid Build Coastguard Worker          .point_coord = true,
145*61046927SAndroid Build Coastguard Worker       };
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker       nir_lower_sysvals_to_varyings(nir, &sysvals_opts);
148*61046927SAndroid Build Coastguard Worker    }
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_system_values);
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker    /* Gather info before preprocess_nir but after some general lowering, so
153*61046927SAndroid Build Coastguard Worker     * inputs_read and system_values_read are accurately set.
154*61046927SAndroid Build Coastguard Worker     */
155*61046927SAndroid Build Coastguard Worker    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir),
158*61046927SAndroid Build Coastguard Worker               true, false);
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_global_vars_to_local);
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_split_var_copies);
163*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_split_struct_vars, nir_var_function_temp);
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    /* Optimize but allow copies because we haven't lowered them yet */
166*61046927SAndroid Build Coastguard Worker    agx_preprocess_nir(nir, NULL);
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_load_const_to_scalar);
169*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_var_copies);
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker static void
hk_preprocess_nir(struct vk_physical_device * vk_pdev,nir_shader * nir)173*61046927SAndroid Build Coastguard Worker hk_preprocess_nir(struct vk_physical_device *vk_pdev, nir_shader *nir)
174*61046927SAndroid Build Coastguard Worker {
175*61046927SAndroid Build Coastguard Worker    hk_preprocess_nir_internal(vk_pdev, nir);
176*61046927SAndroid Build Coastguard Worker    nir_lower_compute_system_values_options csv_options = {
177*61046927SAndroid Build Coastguard Worker       .has_base_workgroup_id = true,
178*61046927SAndroid Build Coastguard Worker    };
179*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_compute_system_values, &csv_options);
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker static void
hk_populate_fs_key(struct hk_fs_key * key,const struct vk_graphics_pipeline_state * state)183*61046927SAndroid Build Coastguard Worker hk_populate_fs_key(struct hk_fs_key *key,
184*61046927SAndroid Build Coastguard Worker                    const struct vk_graphics_pipeline_state *state)
185*61046927SAndroid Build Coastguard Worker {
186*61046927SAndroid Build Coastguard Worker    memset(key, 0, sizeof(*key));
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker    if (state == NULL)
189*61046927SAndroid Build Coastguard Worker       return;
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker    if (state->pipeline_flags &
192*61046927SAndroid Build Coastguard Worker        VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT)
193*61046927SAndroid Build Coastguard Worker       key->zs_self_dep = true;
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker    /* We force per-sample interpolation whenever sampleShadingEnable is set
196*61046927SAndroid Build Coastguard Worker     * regardless of minSampleShading or rasterizationSamples.
197*61046927SAndroid Build Coastguard Worker     *
198*61046927SAndroid Build Coastguard Worker     * When sampleShadingEnable is set, few guarantees are made about the
199*61046927SAndroid Build Coastguard Worker     * location of interpolation of the inputs.  The only real guarantees are
200*61046927SAndroid Build Coastguard Worker     * that the inputs are interpolated within the pixel and that you get at
201*61046927SAndroid Build Coastguard Worker     * least `rasterizationSamples * minSampleShading` unique positions.
202*61046927SAndroid Build Coastguard Worker     * Importantly, it does not require that when `rasterizationSamples *
203*61046927SAndroid Build Coastguard Worker     * minSampleShading <= 1.0` that those positions are at the fragment
204*61046927SAndroid Build Coastguard Worker     * center.  Therefore, it's valid to just always do per-sample all the time.
205*61046927SAndroid Build Coastguard Worker     *
206*61046927SAndroid Build Coastguard Worker     * The one caveat here is that we have to be careful about gl_SampleMaskIn.
207*61046927SAndroid Build Coastguard Worker     * When `hk_fs_key::force_sample_shading = true` we also turn any reads of
208*61046927SAndroid Build Coastguard Worker     * gl_SampleMaskIn into `1 << gl_SampleID` because the hardware sample mask
209*61046927SAndroid Build Coastguard Worker     * is actually per-fragment, not per-pass.  We handle this by smashing
210*61046927SAndroid Build Coastguard Worker     * minSampleShading to 1.0 whenever gl_SampleMaskIn is read.
211*61046927SAndroid Build Coastguard Worker     */
212*61046927SAndroid Build Coastguard Worker    const struct vk_multisample_state *ms = state->ms;
213*61046927SAndroid Build Coastguard Worker    if (ms != NULL && ms->sample_shading_enable)
214*61046927SAndroid Build Coastguard Worker       key->force_sample_shading = true;
215*61046927SAndroid Build Coastguard Worker }
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker static void
hk_hash_graphics_state(struct vk_physical_device * device,const struct vk_graphics_pipeline_state * state,VkShaderStageFlags stages,blake3_hash blake3_out)218*61046927SAndroid Build Coastguard Worker hk_hash_graphics_state(struct vk_physical_device *device,
219*61046927SAndroid Build Coastguard Worker                        const struct vk_graphics_pipeline_state *state,
220*61046927SAndroid Build Coastguard Worker                        VkShaderStageFlags stages, blake3_hash blake3_out)
221*61046927SAndroid Build Coastguard Worker {
222*61046927SAndroid Build Coastguard Worker    struct mesa_blake3 blake3_ctx;
223*61046927SAndroid Build Coastguard Worker    _mesa_blake3_init(&blake3_ctx);
224*61046927SAndroid Build Coastguard Worker    if (stages & VK_SHADER_STAGE_FRAGMENT_BIT) {
225*61046927SAndroid Build Coastguard Worker       struct hk_fs_key key;
226*61046927SAndroid Build Coastguard Worker       hk_populate_fs_key(&key, state);
227*61046927SAndroid Build Coastguard Worker       _mesa_blake3_update(&blake3_ctx, &key, sizeof(key));
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker       const bool is_multiview = state->rp->view_mask != 0;
230*61046927SAndroid Build Coastguard Worker       _mesa_blake3_update(&blake3_ctx, &is_multiview, sizeof(is_multiview));
231*61046927SAndroid Build Coastguard Worker    }
232*61046927SAndroid Build Coastguard Worker    _mesa_blake3_final(&blake3_ctx, blake3_out);
233*61046927SAndroid Build Coastguard Worker }
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker static bool
lower_load_global_constant_offset_instr(nir_builder * b,nir_intrinsic_instr * intrin,void * data)236*61046927SAndroid Build Coastguard Worker lower_load_global_constant_offset_instr(nir_builder *b,
237*61046927SAndroid Build Coastguard Worker                                         nir_intrinsic_instr *intrin, void *data)
238*61046927SAndroid Build Coastguard Worker {
239*61046927SAndroid Build Coastguard Worker    if (intrin->intrinsic != nir_intrinsic_load_global_constant_offset &&
240*61046927SAndroid Build Coastguard Worker        intrin->intrinsic != nir_intrinsic_load_global_constant_bounded)
241*61046927SAndroid Build Coastguard Worker       return false;
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker    b->cursor = nir_before_instr(&intrin->instr);
244*61046927SAndroid Build Coastguard Worker    bool *has_soft_fault = data;
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker    nir_def *base_addr = intrin->src[0].ssa;
247*61046927SAndroid Build Coastguard Worker    nir_def *offset = intrin->src[1].ssa;
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    nir_def *zero = NULL;
250*61046927SAndroid Build Coastguard Worker    nir_def *in_bounds = NULL;
251*61046927SAndroid Build Coastguard Worker    if (intrin->intrinsic == nir_intrinsic_load_global_constant_bounded) {
252*61046927SAndroid Build Coastguard Worker       nir_def *bound = intrin->src[2].ssa;
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker       unsigned bit_size = intrin->def.bit_size;
255*61046927SAndroid Build Coastguard Worker       assert(bit_size >= 8 && bit_size % 8 == 0);
256*61046927SAndroid Build Coastguard Worker       unsigned byte_size = bit_size / 8;
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker       zero = nir_imm_zero(b, intrin->num_components, bit_size);
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker       unsigned load_size = byte_size * intrin->num_components;
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker       nir_def *sat_offset =
263*61046927SAndroid Build Coastguard Worker          nir_umin(b, offset, nir_imm_int(b, UINT32_MAX - (load_size - 1)));
264*61046927SAndroid Build Coastguard Worker       in_bounds = nir_ilt(b, nir_iadd_imm(b, sat_offset, load_size - 1), bound);
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker       /* If we do not have soft fault, we branch to bounds check. This is slow,
267*61046927SAndroid Build Coastguard Worker        * fortunately we always have soft fault for release drivers.
268*61046927SAndroid Build Coastguard Worker        *
269*61046927SAndroid Build Coastguard Worker        * With soft fault, we speculatively load and smash to zero at the end.
270*61046927SAndroid Build Coastguard Worker        */
271*61046927SAndroid Build Coastguard Worker       if (!(*has_soft_fault))
272*61046927SAndroid Build Coastguard Worker          nir_push_if(b, in_bounds);
273*61046927SAndroid Build Coastguard Worker    }
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    nir_def *val = nir_build_load_global_constant(
276*61046927SAndroid Build Coastguard Worker       b, intrin->def.num_components, intrin->def.bit_size,
277*61046927SAndroid Build Coastguard Worker       nir_iadd(b, base_addr, nir_u2u64(b, offset)),
278*61046927SAndroid Build Coastguard Worker       .align_mul = nir_intrinsic_align_mul(intrin),
279*61046927SAndroid Build Coastguard Worker       .align_offset = nir_intrinsic_align_offset(intrin),
280*61046927SAndroid Build Coastguard Worker       .access = nir_intrinsic_access(intrin));
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker    if (intrin->intrinsic == nir_intrinsic_load_global_constant_bounded) {
283*61046927SAndroid Build Coastguard Worker       if (*has_soft_fault) {
284*61046927SAndroid Build Coastguard Worker          val = nir_bcsel(b, in_bounds, val, zero);
285*61046927SAndroid Build Coastguard Worker       } else {
286*61046927SAndroid Build Coastguard Worker          nir_pop_if(b, NULL);
287*61046927SAndroid Build Coastguard Worker          val = nir_if_phi(b, val, zero);
288*61046927SAndroid Build Coastguard Worker       }
289*61046927SAndroid Build Coastguard Worker    }
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    nir_def_replace(&intrin->def, val);
292*61046927SAndroid Build Coastguard Worker    return true;
293*61046927SAndroid Build Coastguard Worker }
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker struct lower_ycbcr_state {
296*61046927SAndroid Build Coastguard Worker    uint32_t set_layout_count;
297*61046927SAndroid Build Coastguard Worker    struct vk_descriptor_set_layout *const *set_layouts;
298*61046927SAndroid Build Coastguard Worker };
299*61046927SAndroid Build Coastguard Worker 
300*61046927SAndroid Build Coastguard Worker static const struct vk_ycbcr_conversion_state *
lookup_ycbcr_conversion(const void * _state,uint32_t set,uint32_t binding,uint32_t array_index)301*61046927SAndroid Build Coastguard Worker lookup_ycbcr_conversion(const void *_state, uint32_t set, uint32_t binding,
302*61046927SAndroid Build Coastguard Worker                         uint32_t array_index)
303*61046927SAndroid Build Coastguard Worker {
304*61046927SAndroid Build Coastguard Worker    const struct lower_ycbcr_state *state = _state;
305*61046927SAndroid Build Coastguard Worker    assert(set < state->set_layout_count);
306*61046927SAndroid Build Coastguard Worker    assert(state->set_layouts[set] != NULL);
307*61046927SAndroid Build Coastguard Worker    const struct hk_descriptor_set_layout *set_layout =
308*61046927SAndroid Build Coastguard Worker       vk_to_hk_descriptor_set_layout(state->set_layouts[set]);
309*61046927SAndroid Build Coastguard Worker    assert(binding < set_layout->binding_count);
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker    const struct hk_descriptor_set_binding_layout *bind_layout =
312*61046927SAndroid Build Coastguard Worker       &set_layout->binding[binding];
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker    if (bind_layout->immutable_samplers == NULL)
315*61046927SAndroid Build Coastguard Worker       return NULL;
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker    array_index = MIN2(array_index, bind_layout->array_size - 1);
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker    const struct hk_sampler *sampler =
320*61046927SAndroid Build Coastguard Worker       bind_layout->immutable_samplers[array_index];
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker    return sampler && sampler->vk.ycbcr_conversion
323*61046927SAndroid Build Coastguard Worker              ? &sampler->vk.ycbcr_conversion->state
324*61046927SAndroid Build Coastguard Worker              : NULL;
325*61046927SAndroid Build Coastguard Worker }
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker static inline bool
nir_has_image_var(nir_shader * nir)328*61046927SAndroid Build Coastguard Worker nir_has_image_var(nir_shader *nir)
329*61046927SAndroid Build Coastguard Worker {
330*61046927SAndroid Build Coastguard Worker    nir_foreach_image_variable(_, nir)
331*61046927SAndroid Build Coastguard Worker       return true;
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker    return false;
334*61046927SAndroid Build Coastguard Worker }
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker static int
glsl_type_size(const struct glsl_type * type,bool bindless)337*61046927SAndroid Build Coastguard Worker glsl_type_size(const struct glsl_type *type, bool bindless)
338*61046927SAndroid Build Coastguard Worker {
339*61046927SAndroid Build Coastguard Worker    return glsl_count_attribute_slots(type, false);
340*61046927SAndroid Build Coastguard Worker }
341*61046927SAndroid Build Coastguard Worker 
342*61046927SAndroid Build Coastguard Worker /*
343*61046927SAndroid Build Coastguard Worker  * This is the world's worst multiview implementation. We simply duplicate each
344*61046927SAndroid Build Coastguard Worker  * draw on the CPU side, changing a uniform in between, and then plumb the view
345*61046927SAndroid Build Coastguard Worker  * index into the layer ID here. Whatever, it works.
346*61046927SAndroid Build Coastguard Worker  *
347*61046927SAndroid Build Coastguard Worker  * The "proper" implementation on AGX would use vertex amplification, but a
348*61046927SAndroid Build Coastguard Worker  * MacBook is not a VR headset.
349*61046927SAndroid Build Coastguard Worker  */
350*61046927SAndroid Build Coastguard Worker static void
hk_lower_multiview(nir_shader * nir)351*61046927SAndroid Build Coastguard Worker hk_lower_multiview(nir_shader *nir)
352*61046927SAndroid Build Coastguard Worker {
353*61046927SAndroid Build Coastguard Worker    /* If there's an existing layer ID write, ignore it. This avoids validation
354*61046927SAndroid Build Coastguard Worker     * splat with vk_meta.
355*61046927SAndroid Build Coastguard Worker     */
356*61046927SAndroid Build Coastguard Worker    nir_variable *existing = nir_find_variable_with_location(
357*61046927SAndroid Build Coastguard Worker       nir, nir_var_shader_out, VARYING_SLOT_LAYER);
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker    if (existing) {
360*61046927SAndroid Build Coastguard Worker       existing->data.mode = nir_var_shader_temp;
361*61046927SAndroid Build Coastguard Worker       existing->data.location = 0;
362*61046927SAndroid Build Coastguard Worker       nir_fixup_deref_modes(nir);
363*61046927SAndroid Build Coastguard Worker    }
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker    /* Now write the view index as the layer */
366*61046927SAndroid Build Coastguard Worker    nir_builder b =
367*61046927SAndroid Build Coastguard Worker       nir_builder_at(nir_after_impl(nir_shader_get_entrypoint(nir)));
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    nir_variable *layer =
370*61046927SAndroid Build Coastguard Worker       nir_variable_create(nir, nir_var_shader_out, glsl_uint_type(), NULL);
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker    layer->data.location = VARYING_SLOT_LAYER;
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    nir_store_var(&b, layer, nir_load_view_index(&b), nir_component_mask(1));
375*61046927SAndroid Build Coastguard Worker    b.shader->info.outputs_written |= VARYING_BIT_LAYER;
376*61046927SAndroid Build Coastguard Worker }
377*61046927SAndroid Build Coastguard Worker 
378*61046927SAndroid Build Coastguard Worker /*
379*61046927SAndroid Build Coastguard Worker  * KHR_maintenance5 requires that points rasterize with a default point size of
380*61046927SAndroid Build Coastguard Worker  * 1.0, while our hardware requires an explicit point size write for this.
381*61046927SAndroid Build Coastguard Worker  * Since topology may be dynamic, we insert an unconditional write if necessary.
382*61046927SAndroid Build Coastguard Worker  */
383*61046927SAndroid Build Coastguard Worker static bool
hk_nir_insert_psiz_write(nir_shader * nir)384*61046927SAndroid Build Coastguard Worker hk_nir_insert_psiz_write(nir_shader *nir)
385*61046927SAndroid Build Coastguard Worker {
386*61046927SAndroid Build Coastguard Worker    nir_function_impl *impl = nir_shader_get_entrypoint(nir);
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker    if (nir->info.outputs_written & VARYING_BIT_PSIZ) {
389*61046927SAndroid Build Coastguard Worker       nir_metadata_preserve(impl, nir_metadata_all);
390*61046927SAndroid Build Coastguard Worker       return false;
391*61046927SAndroid Build Coastguard Worker    }
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker    nir_builder b = nir_builder_at(nir_after_impl(impl));
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker    nir_store_output(&b, nir_imm_float(&b, 1.0), nir_imm_int(&b, 0),
396*61046927SAndroid Build Coastguard Worker                     .write_mask = nir_component_mask(1),
397*61046927SAndroid Build Coastguard Worker                     .io_semantics.location = VARYING_SLOT_PSIZ,
398*61046927SAndroid Build Coastguard Worker                     .io_semantics.num_slots = 1, .src_type = nir_type_float32);
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker    nir->info.outputs_written |= VARYING_BIT_PSIZ;
401*61046927SAndroid Build Coastguard Worker    nir_metadata_preserve(b.impl, nir_metadata_control_flow);
402*61046927SAndroid Build Coastguard Worker    return true;
403*61046927SAndroid Build Coastguard Worker }
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker static nir_def *
query_custom_border(nir_builder * b,nir_tex_instr * tex)406*61046927SAndroid Build Coastguard Worker query_custom_border(nir_builder *b, nir_tex_instr *tex)
407*61046927SAndroid Build Coastguard Worker {
408*61046927SAndroid Build Coastguard Worker    return nir_build_texture_query(b, tex, nir_texop_custom_border_color_agx, 4,
409*61046927SAndroid Build Coastguard Worker                                   tex->dest_type, false, false);
410*61046927SAndroid Build Coastguard Worker }
411*61046927SAndroid Build Coastguard Worker 
412*61046927SAndroid Build Coastguard Worker static nir_def *
has_custom_border(nir_builder * b,nir_tex_instr * tex)413*61046927SAndroid Build Coastguard Worker has_custom_border(nir_builder *b, nir_tex_instr *tex)
414*61046927SAndroid Build Coastguard Worker {
415*61046927SAndroid Build Coastguard Worker    return nir_build_texture_query(b, tex, nir_texop_has_custom_border_color_agx,
416*61046927SAndroid Build Coastguard Worker                                   1, nir_type_bool1, false, false);
417*61046927SAndroid Build Coastguard Worker }
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker static bool
lower(nir_builder * b,nir_instr * instr,UNUSED void * _data)420*61046927SAndroid Build Coastguard Worker lower(nir_builder *b, nir_instr *instr, UNUSED void *_data)
421*61046927SAndroid Build Coastguard Worker {
422*61046927SAndroid Build Coastguard Worker    if (instr->type != nir_instr_type_tex)
423*61046927SAndroid Build Coastguard Worker       return false;
424*61046927SAndroid Build Coastguard Worker 
425*61046927SAndroid Build Coastguard Worker    nir_tex_instr *tex = nir_instr_as_tex(instr);
426*61046927SAndroid Build Coastguard Worker    if (!nir_tex_instr_need_sampler(tex) || nir_tex_instr_is_query(tex))
427*61046927SAndroid Build Coastguard Worker       return false;
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker    /* XXX: this is a really weird edge case, is this even well-defined? */
430*61046927SAndroid Build Coastguard Worker    if (tex->is_shadow)
431*61046927SAndroid Build Coastguard Worker       return false;
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker    b->cursor = nir_after_instr(&tex->instr);
434*61046927SAndroid Build Coastguard Worker    nir_def *has_custom = has_custom_border(b, tex);
435*61046927SAndroid Build Coastguard Worker 
436*61046927SAndroid Build Coastguard Worker    nir_instr *orig = nir_instr_clone(b->shader, &tex->instr);
437*61046927SAndroid Build Coastguard Worker    nir_builder_instr_insert(b, orig);
438*61046927SAndroid Build Coastguard Worker    nir_def *clamp_to_1 = &nir_instr_as_tex(orig)->def;
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker    nir_push_if(b, has_custom);
441*61046927SAndroid Build Coastguard Worker    nir_def *replaced = NULL;
442*61046927SAndroid Build Coastguard Worker    {
443*61046927SAndroid Build Coastguard Worker       /* Sample again, this time with clamp-to-0 instead of clamp-to-1 */
444*61046927SAndroid Build Coastguard Worker       nir_instr *clone_instr = nir_instr_clone(b->shader, &tex->instr);
445*61046927SAndroid Build Coastguard Worker       nir_builder_instr_insert(b, clone_instr);
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker       nir_tex_instr *tex_0 = nir_instr_as_tex(clone_instr);
448*61046927SAndroid Build Coastguard Worker       nir_def *clamp_to_0 = &tex_0->def;
449*61046927SAndroid Build Coastguard Worker 
450*61046927SAndroid Build Coastguard Worker       tex_0->backend_flags |= AGX_TEXTURE_FLAG_CLAMP_TO_0;
451*61046927SAndroid Build Coastguard Worker 
452*61046927SAndroid Build Coastguard Worker       /* Grab the border colour */
453*61046927SAndroid Build Coastguard Worker       nir_def *border = query_custom_border(b, tex_0);
454*61046927SAndroid Build Coastguard Worker 
455*61046927SAndroid Build Coastguard Worker       if (tex->op == nir_texop_tg4) {
456*61046927SAndroid Build Coastguard Worker          border = nir_replicate(b, nir_channel(b, border, tex->component), 4);
457*61046927SAndroid Build Coastguard Worker       }
458*61046927SAndroid Build Coastguard Worker 
459*61046927SAndroid Build Coastguard Worker       /* Combine together with the border */
460*61046927SAndroid Build Coastguard Worker       if (nir_alu_type_get_base_type(tex->dest_type) == nir_type_float &&
461*61046927SAndroid Build Coastguard Worker           tex->op != nir_texop_tg4) {
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker          /* For floats, lerp together:
464*61046927SAndroid Build Coastguard Worker           *
465*61046927SAndroid Build Coastguard Worker           * For border texels:  (1 * border) + (0 * border      ) = border
466*61046927SAndroid Build Coastguard Worker           * For regular texels: (x * border) + (x * (1 - border)) = x.
467*61046927SAndroid Build Coastguard Worker           *
468*61046927SAndroid Build Coastguard Worker           * Linear filtering is linear (duh), so lerping is compatible.
469*61046927SAndroid Build Coastguard Worker           */
470*61046927SAndroid Build Coastguard Worker          replaced = nir_flrp(b, clamp_to_0, clamp_to_1, border);
471*61046927SAndroid Build Coastguard Worker       } else {
472*61046927SAndroid Build Coastguard Worker          /* For integers, just select componentwise since there is no linear
473*61046927SAndroid Build Coastguard Worker           * filtering. Gathers also use this path since they are unfiltered in
474*61046927SAndroid Build Coastguard Worker           * each component.
475*61046927SAndroid Build Coastguard Worker           */
476*61046927SAndroid Build Coastguard Worker          replaced = nir_bcsel(b, nir_ieq(b, clamp_to_0, clamp_to_1), clamp_to_0,
477*61046927SAndroid Build Coastguard Worker                               border);
478*61046927SAndroid Build Coastguard Worker       }
479*61046927SAndroid Build Coastguard Worker    }
480*61046927SAndroid Build Coastguard Worker    nir_pop_if(b, NULL);
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker    /* Put it together with a phi */
483*61046927SAndroid Build Coastguard Worker    nir_def *phi = nir_if_phi(b, replaced, clamp_to_1);
484*61046927SAndroid Build Coastguard Worker    nir_def_replace(&tex->def, phi);
485*61046927SAndroid Build Coastguard Worker    return true;
486*61046927SAndroid Build Coastguard Worker }
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker static bool
agx_nir_lower_custom_border(nir_shader * nir)489*61046927SAndroid Build Coastguard Worker agx_nir_lower_custom_border(nir_shader *nir)
490*61046927SAndroid Build Coastguard Worker {
491*61046927SAndroid Build Coastguard Worker    return nir_shader_instructions_pass(nir, lower, nir_metadata_none, NULL);
492*61046927SAndroid Build Coastguard Worker }
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker /*
495*61046927SAndroid Build Coastguard Worker  * In Vulkan, the VIEWPORT should read 0 in the fragment shader if it is not
496*61046927SAndroid Build Coastguard Worker  * written by the vertex shader, but in our implementation, the varying would
497*61046927SAndroid Build Coastguard Worker  * otherwise be undefined. This small pass predicates VIEWPORT reads based on
498*61046927SAndroid Build Coastguard Worker  * whether the hardware vertex shader writes the VIEWPORT (nonzero UVS index).
499*61046927SAndroid Build Coastguard Worker  */
500*61046927SAndroid Build Coastguard Worker static bool
lower_viewport_fs(nir_builder * b,nir_intrinsic_instr * intr,UNUSED void * data)501*61046927SAndroid Build Coastguard Worker lower_viewport_fs(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *data)
502*61046927SAndroid Build Coastguard Worker {
503*61046927SAndroid Build Coastguard Worker    if (intr->intrinsic != nir_intrinsic_load_input)
504*61046927SAndroid Build Coastguard Worker       return false;
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker    nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
507*61046927SAndroid Build Coastguard Worker    if (sem.location != VARYING_SLOT_VIEWPORT)
508*61046927SAndroid Build Coastguard Worker       return false;
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker    b->cursor = nir_after_instr(&intr->instr);
511*61046927SAndroid Build Coastguard Worker    nir_def *orig = &intr->def;
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker    nir_def *uvs = nir_load_uvs_index_agx(b, .io_semantics = sem);
514*61046927SAndroid Build Coastguard Worker    nir_def *def = nir_bcsel(b, nir_ine_imm(b, uvs, 0), orig, nir_imm_int(b, 0));
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker    nir_def_rewrite_uses_after(orig, def, def->parent_instr);
517*61046927SAndroid Build Coastguard Worker    return true;
518*61046927SAndroid Build Coastguard Worker }
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker static bool
lower_subpass_dim(nir_builder * b,nir_instr * instr,UNUSED void * _data)521*61046927SAndroid Build Coastguard Worker lower_subpass_dim(nir_builder *b, nir_instr *instr, UNUSED void *_data)
522*61046927SAndroid Build Coastguard Worker {
523*61046927SAndroid Build Coastguard Worker    if (instr->type != nir_instr_type_tex)
524*61046927SAndroid Build Coastguard Worker       return false;
525*61046927SAndroid Build Coastguard Worker 
526*61046927SAndroid Build Coastguard Worker    nir_tex_instr *tex = nir_instr_as_tex(instr);
527*61046927SAndroid Build Coastguard Worker    if (tex->sampler_dim == GLSL_SAMPLER_DIM_SUBPASS)
528*61046927SAndroid Build Coastguard Worker       tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
529*61046927SAndroid Build Coastguard Worker    else if (tex->sampler_dim == GLSL_SAMPLER_DIM_SUBPASS_MS)
530*61046927SAndroid Build Coastguard Worker       tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
531*61046927SAndroid Build Coastguard Worker    else
532*61046927SAndroid Build Coastguard Worker       return false;
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker    return true;
535*61046927SAndroid Build Coastguard Worker }
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker void
hk_lower_nir(struct hk_device * dev,nir_shader * nir,const struct vk_pipeline_robustness_state * rs,bool is_multiview,uint32_t set_layout_count,struct vk_descriptor_set_layout * const * set_layouts)538*61046927SAndroid Build Coastguard Worker hk_lower_nir(struct hk_device *dev, nir_shader *nir,
539*61046927SAndroid Build Coastguard Worker              const struct vk_pipeline_robustness_state *rs, bool is_multiview,
540*61046927SAndroid Build Coastguard Worker              uint32_t set_layout_count,
541*61046927SAndroid Build Coastguard Worker              struct vk_descriptor_set_layout *const *set_layouts)
542*61046927SAndroid Build Coastguard Worker {
543*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_FRAGMENT) {
544*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_input_attachments,
545*61046927SAndroid Build Coastguard Worker                &(nir_input_attachment_options){
546*61046927SAndroid Build Coastguard Worker                   .use_fragcoord_sysval = true,
547*61046927SAndroid Build Coastguard Worker                   .use_layer_id_sysval = true,
548*61046927SAndroid Build Coastguard Worker                   .use_view_id_for_layer = is_multiview,
549*61046927SAndroid Build Coastguard Worker                });
550*61046927SAndroid Build Coastguard Worker 
551*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_shader_instructions_pass, lower_subpass_dim,
552*61046927SAndroid Build Coastguard Worker                nir_metadata_all, NULL);
553*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_wpos_center);
554*61046927SAndroid Build Coastguard Worker    }
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker    /* XXX: should be last geometry stage, how do I get to that? */
557*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_VERTEX) {
558*61046927SAndroid Build Coastguard Worker       if (is_multiview)
559*61046927SAndroid Build Coastguard Worker          hk_lower_multiview(nir);
560*61046927SAndroid Build Coastguard Worker    }
561*61046927SAndroid Build Coastguard Worker 
562*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_TESS_EVAL) {
563*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_patch_vertices,
564*61046927SAndroid Build Coastguard Worker                nir->info.tess.tcs_vertices_out, NULL);
565*61046927SAndroid Build Coastguard Worker    }
566*61046927SAndroid Build Coastguard Worker 
567*61046927SAndroid Build Coastguard Worker    const struct lower_ycbcr_state ycbcr_state = {
568*61046927SAndroid Build Coastguard Worker       .set_layout_count = set_layout_count,
569*61046927SAndroid Build Coastguard Worker       .set_layouts = set_layouts,
570*61046927SAndroid Build Coastguard Worker    };
571*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_vk_lower_ycbcr_tex, lookup_ycbcr_conversion,
572*61046927SAndroid Build Coastguard Worker             &ycbcr_state);
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker    /* Lower push constants before lower_descriptors */
575*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_push_const,
576*61046927SAndroid Build Coastguard Worker             nir_address_format_32bit_offset);
577*61046927SAndroid Build Coastguard Worker 
578*61046927SAndroid Build Coastguard Worker    // NIR_PASS(_, nir, nir_opt_large_constants, NULL, 32);
579*61046927SAndroid Build Coastguard Worker 
580*61046927SAndroid Build Coastguard Worker    /* Images accessed through the texture or PBE hardware are robust, so we
581*61046927SAndroid Build Coastguard Worker     * don't set lower_image. (There are some sticky details around txf but
582*61046927SAndroid Build Coastguard Worker     * they're handled by agx_nir_lower_texture). However, image atomics are
583*61046927SAndroid Build Coastguard Worker     * software so require robustness lowering.
584*61046927SAndroid Build Coastguard Worker     */
585*61046927SAndroid Build Coastguard Worker    nir_lower_robust_access_options robustness = {
586*61046927SAndroid Build Coastguard Worker       .lower_image_atomic = true,
587*61046927SAndroid Build Coastguard Worker    };
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_robust_access, &robustness);
590*61046927SAndroid Build Coastguard Worker 
591*61046927SAndroid Build Coastguard Worker    /* We must do early lowering before hk_nir_lower_descriptors, since this will
592*61046927SAndroid Build Coastguard Worker     * create lod_bias_agx instructions.
593*61046927SAndroid Build Coastguard Worker     */
594*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, agx_nir_lower_texture_early, true /* support_lod_bias */);
595*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, agx_nir_lower_custom_border);
596*61046927SAndroid Build Coastguard Worker 
597*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, hk_nir_lower_descriptors, rs, set_layout_count,
598*61046927SAndroid Build Coastguard Worker             set_layouts);
599*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_global,
600*61046927SAndroid Build Coastguard Worker             nir_address_format_64bit_global);
601*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_ssbo,
602*61046927SAndroid Build Coastguard Worker             hk_buffer_addr_format(rs->storage_buffers));
603*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_ubo,
604*61046927SAndroid Build Coastguard Worker             hk_buffer_addr_format(rs->uniform_buffers));
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker    bool soft_fault = agx_has_soft_fault(&dev->dev);
607*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_shader_intrinsics_pass,
608*61046927SAndroid Build Coastguard Worker             lower_load_global_constant_offset_instr, nir_metadata_none,
609*61046927SAndroid Build Coastguard Worker             &soft_fault);
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker    if (!nir->info.shared_memory_explicit_layout) {
612*61046927SAndroid Build Coastguard Worker       /* There may be garbage in shared_size, but it's the job of
613*61046927SAndroid Build Coastguard Worker        * nir_lower_vars_to_explicit_types to allocate it. We have to reset to
614*61046927SAndroid Build Coastguard Worker        * avoid overallocation.
615*61046927SAndroid Build Coastguard Worker        */
616*61046927SAndroid Build Coastguard Worker       nir->info.shared_size = 0;
617*61046927SAndroid Build Coastguard Worker 
618*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_vars_to_explicit_types, nir_var_mem_shared,
619*61046927SAndroid Build Coastguard Worker                shared_var_info);
620*61046927SAndroid Build Coastguard Worker    }
621*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_shared,
622*61046927SAndroid Build Coastguard Worker             nir_address_format_32bit_offset);
623*61046927SAndroid Build Coastguard Worker 
624*61046927SAndroid Build Coastguard Worker    if (nir->info.zero_initialize_shared_memory && nir->info.shared_size > 0) {
625*61046927SAndroid Build Coastguard Worker       /* Align everything up to 16B so we can write whole vec4s. */
626*61046927SAndroid Build Coastguard Worker       nir->info.shared_size = align(nir->info.shared_size, 16);
627*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_zero_initialize_shared_memory, nir->info.shared_size,
628*61046927SAndroid Build Coastguard Worker                16);
629*61046927SAndroid Build Coastguard Worker 
630*61046927SAndroid Build Coastguard Worker       /* We need to call lower_compute_system_values again because
631*61046927SAndroid Build Coastguard Worker        * nir_zero_initialize_shared_memory generates load_invocation_id which
632*61046927SAndroid Build Coastguard Worker        * has to be lowered to load_invocation_index.
633*61046927SAndroid Build Coastguard Worker        */
634*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_compute_system_values, NULL);
635*61046927SAndroid Build Coastguard Worker    }
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker    /* TODO: we can do indirect VS output */
638*61046927SAndroid Build Coastguard Worker    nir_variable_mode lower_indirect_modes = 0;
639*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_FRAGMENT)
640*61046927SAndroid Build Coastguard Worker       lower_indirect_modes |= nir_var_shader_out;
641*61046927SAndroid Build Coastguard Worker    else if (nir->info.stage == MESA_SHADER_VERTEX)
642*61046927SAndroid Build Coastguard Worker       lower_indirect_modes |= nir_var_shader_in | nir_var_shader_out;
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_indirect_derefs, lower_indirect_modes,
645*61046927SAndroid Build Coastguard Worker             UINT32_MAX);
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out,
648*61046927SAndroid Build Coastguard Worker             glsl_type_size, nir_lower_io_lower_64bit_to_32);
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_FRAGMENT) {
651*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_shader_intrinsics_pass, lower_viewport_fs,
652*61046927SAndroid Build Coastguard Worker                nir_metadata_control_flow, NULL);
653*61046927SAndroid Build Coastguard Worker    }
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, agx_nir_lower_texture);
656*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, agx_nir_lower_multisampled_image_store);
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker    agx_preprocess_nir(nir, dev->dev.libagx);
659*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_opt_conditional_discard);
660*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_opt_if,
661*61046927SAndroid Build Coastguard Worker             nir_opt_if_optimize_phi_true_false | nir_opt_if_avoid_64bit_phis);
662*61046927SAndroid Build Coastguard Worker }
663*61046927SAndroid Build Coastguard Worker 
664*61046927SAndroid Build Coastguard Worker static void
hk_upload_shader(struct hk_device * dev,struct hk_shader * shader)665*61046927SAndroid Build Coastguard Worker hk_upload_shader(struct hk_device *dev, struct hk_shader *shader)
666*61046927SAndroid Build Coastguard Worker {
667*61046927SAndroid Build Coastguard Worker    if (shader->b.info.has_preamble) {
668*61046927SAndroid Build Coastguard Worker       unsigned offs = shader->b.info.preamble_offset;
669*61046927SAndroid Build Coastguard Worker       assert(offs < shader->b.binary_size);
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker       size_t size = shader->b.binary_size - offs;
672*61046927SAndroid Build Coastguard Worker       assert(size > 0);
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker       shader->bo = agx_bo_create(&dev->dev, size, 0,
675*61046927SAndroid Build Coastguard Worker                                  AGX_BO_EXEC | AGX_BO_LOW_VA, "Preamble");
676*61046927SAndroid Build Coastguard Worker       memcpy(shader->bo->map, shader->b.binary + offs, size);
677*61046927SAndroid Build Coastguard Worker       shader->preamble_addr = shader->bo->va->addr;
678*61046927SAndroid Build Coastguard Worker    }
679*61046927SAndroid Build Coastguard Worker 
680*61046927SAndroid Build Coastguard Worker    if (!shader->linked.ht) {
681*61046927SAndroid Build Coastguard Worker       /* If we only have a single variant, link now. */
682*61046927SAndroid Build Coastguard Worker       shader->only_linked = hk_fast_link(dev, false, shader, NULL, NULL, 0);
683*61046927SAndroid Build Coastguard Worker    }
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker    if (shader->info.stage == MESA_SHADER_FRAGMENT) {
686*61046927SAndroid Build Coastguard Worker       agx_pack(&shader->frag_face, FRAGMENT_FACE_2, cfg) {
687*61046927SAndroid Build Coastguard Worker          cfg.conservative_depth =
688*61046927SAndroid Build Coastguard Worker             agx_translate_depth_layout(shader->b.info.depth_layout);
689*61046927SAndroid Build Coastguard Worker       }
690*61046927SAndroid Build Coastguard Worker    }
691*61046927SAndroid Build Coastguard Worker 
692*61046927SAndroid Build Coastguard Worker    agx_pack(&shader->counts, COUNTS, cfg) {
693*61046927SAndroid Build Coastguard Worker       cfg.uniform_register_count = shader->b.info.push_count;
694*61046927SAndroid Build Coastguard Worker       cfg.preshader_register_count = shader->b.info.nr_preamble_gprs;
695*61046927SAndroid Build Coastguard Worker       cfg.sampler_state_register_count = agx_translate_sampler_state_count(
696*61046927SAndroid Build Coastguard Worker          shader->b.info.uses_txf ? 1 : 0, false);
697*61046927SAndroid Build Coastguard Worker    }
698*61046927SAndroid Build Coastguard Worker }
699*61046927SAndroid Build Coastguard Worker 
700*61046927SAndroid Build Coastguard Worker DERIVE_HASH_TABLE(hk_fast_link_key_vs);
701*61046927SAndroid Build Coastguard Worker DERIVE_HASH_TABLE(hk_fast_link_key_fs);
702*61046927SAndroid Build Coastguard Worker 
703*61046927SAndroid Build Coastguard Worker static VkResult
hk_init_link_ht(struct hk_shader * shader,gl_shader_stage sw_stage)704*61046927SAndroid Build Coastguard Worker hk_init_link_ht(struct hk_shader *shader, gl_shader_stage sw_stage)
705*61046927SAndroid Build Coastguard Worker {
706*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&shader->linked.lock, mtx_plain);
707*61046927SAndroid Build Coastguard Worker 
708*61046927SAndroid Build Coastguard Worker    bool multiple_variants =
709*61046927SAndroid Build Coastguard Worker       sw_stage == MESA_SHADER_VERTEX || sw_stage == MESA_SHADER_FRAGMENT;
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker    if (!multiple_variants)
712*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
713*61046927SAndroid Build Coastguard Worker 
714*61046927SAndroid Build Coastguard Worker    if (sw_stage == MESA_SHADER_VERTEX)
715*61046927SAndroid Build Coastguard Worker       shader->linked.ht = hk_fast_link_key_vs_table_create(NULL);
716*61046927SAndroid Build Coastguard Worker    else
717*61046927SAndroid Build Coastguard Worker       shader->linked.ht = hk_fast_link_key_fs_table_create(NULL);
718*61046927SAndroid Build Coastguard Worker 
719*61046927SAndroid Build Coastguard Worker    return (shader->linked.ht == NULL) ? VK_ERROR_OUT_OF_HOST_MEMORY
720*61046927SAndroid Build Coastguard Worker                                       : VK_SUCCESS;
721*61046927SAndroid Build Coastguard Worker }
722*61046927SAndroid Build Coastguard Worker 
723*61046927SAndroid Build Coastguard Worker static VkResult
hk_compile_nir(struct hk_device * dev,const VkAllocationCallbacks * pAllocator,nir_shader * nir,VkShaderCreateFlagsEXT shader_flags,const struct vk_pipeline_robustness_state * rs,const struct hk_fs_key * fs_key,struct hk_shader * shader,gl_shader_stage sw_stage,bool hw,nir_xfb_info * xfb_info)724*61046927SAndroid Build Coastguard Worker hk_compile_nir(struct hk_device *dev, const VkAllocationCallbacks *pAllocator,
725*61046927SAndroid Build Coastguard Worker                nir_shader *nir, VkShaderCreateFlagsEXT shader_flags,
726*61046927SAndroid Build Coastguard Worker                const struct vk_pipeline_robustness_state *rs,
727*61046927SAndroid Build Coastguard Worker                const struct hk_fs_key *fs_key, struct hk_shader *shader,
728*61046927SAndroid Build Coastguard Worker                gl_shader_stage sw_stage, bool hw, nir_xfb_info *xfb_info)
729*61046927SAndroid Build Coastguard Worker {
730*61046927SAndroid Build Coastguard Worker    unsigned vs_uniform_base = 0;
731*61046927SAndroid Build Coastguard Worker 
732*61046927SAndroid Build Coastguard Worker    /* For now, only shader objects are supported */
733*61046927SAndroid Build Coastguard Worker    if (sw_stage == MESA_SHADER_VERTEX) {
734*61046927SAndroid Build Coastguard Worker       vs_uniform_base =
735*61046927SAndroid Build Coastguard Worker          6 * DIV_ROUND_UP(
736*61046927SAndroid Build Coastguard Worker                 BITSET_LAST_BIT(shader->info.vs.attrib_components_read), 4);
737*61046927SAndroid Build Coastguard Worker    } else if (sw_stage == MESA_SHADER_FRAGMENT) {
738*61046927SAndroid Build Coastguard Worker       shader->info.fs.interp = agx_gather_interp_info(nir);
739*61046927SAndroid Build Coastguard Worker       shader->info.fs.writes_memory = nir->info.writes_memory;
740*61046927SAndroid Build Coastguard Worker 
741*61046927SAndroid Build Coastguard Worker       /* Discards must be lowering before lowering MSAA to handle discards */
742*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, agx_nir_lower_discard_zs_emit);
743*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, agx_nir_lower_fs_output_to_epilog,
744*61046927SAndroid Build Coastguard Worker                &shader->info.fs.epilog_key);
745*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, agx_nir_lower_sample_mask);
746*61046927SAndroid Build Coastguard Worker 
747*61046927SAndroid Build Coastguard Worker       if (nir->info.fs.uses_sample_shading) {
748*61046927SAndroid Build Coastguard Worker          /* Ensure the sample ID is preserved in register */
749*61046927SAndroid Build Coastguard Worker          nir_builder b =
750*61046927SAndroid Build Coastguard Worker             nir_builder_at(nir_after_impl(nir_shader_get_entrypoint(nir)));
751*61046927SAndroid Build Coastguard Worker          nir_export_agx(&b, nir_load_exported_agx(&b, 1, 16, .base = 1),
752*61046927SAndroid Build Coastguard Worker                         .base = 1);
753*61046927SAndroid Build Coastguard Worker 
754*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, agx_nir_lower_to_per_sample);
755*61046927SAndroid Build Coastguard Worker       }
756*61046927SAndroid Build Coastguard Worker 
757*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, agx_nir_lower_fs_active_samples_to_register);
758*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, agx_nir_lower_interpolation);
759*61046927SAndroid Build Coastguard Worker    } else if (sw_stage == MESA_SHADER_TESS_EVAL) {
760*61046927SAndroid Build Coastguard Worker       shader->info.ts.ccw = nir->info.tess.ccw;
761*61046927SAndroid Build Coastguard Worker       shader->info.ts.point_mode = nir->info.tess.point_mode;
762*61046927SAndroid Build Coastguard Worker       shader->info.ts.spacing = nir->info.tess.spacing;
763*61046927SAndroid Build Coastguard Worker       shader->info.ts.mode = nir->info.tess._primitive_mode;
764*61046927SAndroid Build Coastguard Worker 
765*61046927SAndroid Build Coastguard Worker       if (nir->info.tess.point_mode) {
766*61046927SAndroid Build Coastguard Worker          shader->info.ts.out_prim = MESA_PRIM_POINTS;
767*61046927SAndroid Build Coastguard Worker       } else if (nir->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES) {
768*61046927SAndroid Build Coastguard Worker          shader->info.ts.out_prim = MESA_PRIM_LINES;
769*61046927SAndroid Build Coastguard Worker       } else {
770*61046927SAndroid Build Coastguard Worker          shader->info.ts.out_prim = MESA_PRIM_TRIANGLES;
771*61046927SAndroid Build Coastguard Worker       }
772*61046927SAndroid Build Coastguard Worker 
773*61046927SAndroid Build Coastguard Worker       /* This destroys info so it needs to happen after the gather */
774*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, agx_nir_lower_tes, dev->dev.libagx, hw);
775*61046927SAndroid Build Coastguard Worker    } else if (sw_stage == MESA_SHADER_TESS_CTRL) {
776*61046927SAndroid Build Coastguard Worker       shader->info.tcs.output_patch_size = nir->info.tess.tcs_vertices_out;
777*61046927SAndroid Build Coastguard Worker       shader->info.tcs.per_vertex_outputs = agx_tcs_per_vertex_outputs(nir);
778*61046927SAndroid Build Coastguard Worker       shader->info.tcs.nr_patch_outputs =
779*61046927SAndroid Build Coastguard Worker          util_last_bit(nir->info.patch_outputs_written);
780*61046927SAndroid Build Coastguard Worker       shader->info.tcs.output_stride = agx_tcs_output_stride(nir);
781*61046927SAndroid Build Coastguard Worker    }
782*61046927SAndroid Build Coastguard Worker 
783*61046927SAndroid Build Coastguard Worker    uint64_t outputs = nir->info.outputs_written;
784*61046927SAndroid Build Coastguard Worker    if (!hw &&
785*61046927SAndroid Build Coastguard Worker        (sw_stage == MESA_SHADER_VERTEX || sw_stage == MESA_SHADER_TESS_EVAL)) {
786*61046927SAndroid Build Coastguard Worker       nir->info.stage = MESA_SHADER_COMPUTE;
787*61046927SAndroid Build Coastguard Worker       memset(&nir->info.cs, 0, sizeof(nir->info.cs));
788*61046927SAndroid Build Coastguard Worker       nir->xfb_info = NULL;
789*61046927SAndroid Build Coastguard Worker    }
790*61046927SAndroid Build Coastguard Worker 
791*61046927SAndroid Build Coastguard Worker    /* XXX: rename */
792*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, hk_lower_uvs_index, vs_uniform_base);
793*61046927SAndroid Build Coastguard Worker 
794*61046927SAndroid Build Coastguard Worker #if 0
795*61046927SAndroid Build Coastguard Worker    /* TODO */
796*61046927SAndroid Build Coastguard Worker    nir_variable_mode robust2_modes = 0;
797*61046927SAndroid Build Coastguard Worker    if (rs->uniform_buffers == VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT)
798*61046927SAndroid Build Coastguard Worker       robust2_modes |= nir_var_mem_ubo;
799*61046927SAndroid Build Coastguard Worker    if (rs->storage_buffers == VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT)
800*61046927SAndroid Build Coastguard Worker       robust2_modes |= nir_var_mem_ssbo;
801*61046927SAndroid Build Coastguard Worker #endif
802*61046927SAndroid Build Coastguard Worker 
803*61046927SAndroid Build Coastguard Worker    struct agx_shader_key backend_key = {
804*61046927SAndroid Build Coastguard Worker       .dev = agx_gather_device_key(&dev->dev),
805*61046927SAndroid Build Coastguard Worker       .reserved_preamble = 128 /* TODO */,
806*61046927SAndroid Build Coastguard Worker       .libagx = dev->dev.libagx,
807*61046927SAndroid Build Coastguard Worker       .no_stop = nir->info.stage == MESA_SHADER_FRAGMENT,
808*61046927SAndroid Build Coastguard Worker       .has_scratch = true,
809*61046927SAndroid Build Coastguard Worker    };
810*61046927SAndroid Build Coastguard Worker 
811*61046927SAndroid Build Coastguard Worker    /* For now, sample shading is always dynamic. Indicate that. */
812*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_FRAGMENT &&
813*61046927SAndroid Build Coastguard Worker        nir->info.fs.uses_sample_shading)
814*61046927SAndroid Build Coastguard Worker       backend_key.fs.inside_sample_loop = true;
815*61046927SAndroid Build Coastguard Worker 
816*61046927SAndroid Build Coastguard Worker    agx_compile_shader_nir(nir, &backend_key, NULL, &shader->b);
817*61046927SAndroid Build Coastguard Worker 
818*61046927SAndroid Build Coastguard Worker    shader->code_ptr = shader->b.binary;
819*61046927SAndroid Build Coastguard Worker    shader->code_size = shader->b.binary_size;
820*61046927SAndroid Build Coastguard Worker 
821*61046927SAndroid Build Coastguard Worker    shader->info.stage = sw_stage;
822*61046927SAndroid Build Coastguard Worker    shader->info.clip_distance_array_size = nir->info.clip_distance_array_size;
823*61046927SAndroid Build Coastguard Worker    shader->info.cull_distance_array_size = nir->info.cull_distance_array_size;
824*61046927SAndroid Build Coastguard Worker    shader->b.info.outputs = outputs;
825*61046927SAndroid Build Coastguard Worker 
826*61046927SAndroid Build Coastguard Worker    if (sw_stage == MESA_SHADER_COMPUTE) {
827*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < 3; ++i)
828*61046927SAndroid Build Coastguard Worker          shader->info.cs.local_size[i] = nir->info.workgroup_size[i];
829*61046927SAndroid Build Coastguard Worker    }
830*61046927SAndroid Build Coastguard Worker 
831*61046927SAndroid Build Coastguard Worker    if (xfb_info) {
832*61046927SAndroid Build Coastguard Worker       assert(xfb_info->output_count < ARRAY_SIZE(shader->info.xfb_outputs));
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker       memcpy(&shader->info.xfb_info, xfb_info,
835*61046927SAndroid Build Coastguard Worker              nir_xfb_info_size(xfb_info->output_count));
836*61046927SAndroid Build Coastguard Worker 
837*61046927SAndroid Build Coastguard Worker       typed_memcpy(shader->info.xfb_stride, nir->info.xfb_stride, 4);
838*61046927SAndroid Build Coastguard Worker    }
839*61046927SAndroid Build Coastguard Worker 
840*61046927SAndroid Build Coastguard Worker    if (nir->constant_data_size > 0) {
841*61046927SAndroid Build Coastguard Worker       uint32_t data_size = align(nir->constant_data_size, HK_MIN_UBO_ALIGNMENT);
842*61046927SAndroid Build Coastguard Worker 
843*61046927SAndroid Build Coastguard Worker       void *data = malloc(data_size);
844*61046927SAndroid Build Coastguard Worker       if (data == NULL) {
845*61046927SAndroid Build Coastguard Worker          ralloc_free(nir);
846*61046927SAndroid Build Coastguard Worker          return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
847*61046927SAndroid Build Coastguard Worker       }
848*61046927SAndroid Build Coastguard Worker 
849*61046927SAndroid Build Coastguard Worker       memcpy(data, nir->constant_data, nir->constant_data_size);
850*61046927SAndroid Build Coastguard Worker 
851*61046927SAndroid Build Coastguard Worker       assert(nir->constant_data_size <= data_size);
852*61046927SAndroid Build Coastguard Worker       memset(data + nir->constant_data_size, 0,
853*61046927SAndroid Build Coastguard Worker              data_size - nir->constant_data_size);
854*61046927SAndroid Build Coastguard Worker 
855*61046927SAndroid Build Coastguard Worker       shader->data_ptr = data;
856*61046927SAndroid Build Coastguard Worker       shader->data_size = data_size;
857*61046927SAndroid Build Coastguard Worker    }
858*61046927SAndroid Build Coastguard Worker 
859*61046927SAndroid Build Coastguard Worker    ralloc_free(nir);
860*61046927SAndroid Build Coastguard Worker 
861*61046927SAndroid Build Coastguard Worker    VkResult result = hk_init_link_ht(shader, sw_stage);
862*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
863*61046927SAndroid Build Coastguard Worker       return vk_error(dev, result);
864*61046927SAndroid Build Coastguard Worker 
865*61046927SAndroid Build Coastguard Worker    hk_upload_shader(dev, shader);
866*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
867*61046927SAndroid Build Coastguard Worker }
868*61046927SAndroid Build Coastguard Worker 
869*61046927SAndroid Build Coastguard Worker static const struct vk_shader_ops hk_shader_ops;
870*61046927SAndroid Build Coastguard Worker 
871*61046927SAndroid Build Coastguard Worker static void
hk_destroy_linked_shader(struct hk_device * dev,struct hk_linked_shader * linked)872*61046927SAndroid Build Coastguard Worker hk_destroy_linked_shader(struct hk_device *dev, struct hk_linked_shader *linked)
873*61046927SAndroid Build Coastguard Worker {
874*61046927SAndroid Build Coastguard Worker    agx_bo_unreference(&dev->dev, linked->b.bo);
875*61046927SAndroid Build Coastguard Worker    ralloc_free(linked);
876*61046927SAndroid Build Coastguard Worker }
877*61046927SAndroid Build Coastguard Worker 
878*61046927SAndroid Build Coastguard Worker static void
hk_shader_destroy(struct hk_device * dev,struct hk_shader * s)879*61046927SAndroid Build Coastguard Worker hk_shader_destroy(struct hk_device *dev, struct hk_shader *s)
880*61046927SAndroid Build Coastguard Worker {
881*61046927SAndroid Build Coastguard Worker    free((void *)s->code_ptr);
882*61046927SAndroid Build Coastguard Worker    free((void *)s->data_ptr);
883*61046927SAndroid Build Coastguard Worker    agx_bo_unreference(&dev->dev, s->bo);
884*61046927SAndroid Build Coastguard Worker 
885*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&s->linked.lock);
886*61046927SAndroid Build Coastguard Worker 
887*61046927SAndroid Build Coastguard Worker    if (s->only_linked)
888*61046927SAndroid Build Coastguard Worker       hk_destroy_linked_shader(dev, s->only_linked);
889*61046927SAndroid Build Coastguard Worker 
890*61046927SAndroid Build Coastguard Worker    if (s->linked.ht) {
891*61046927SAndroid Build Coastguard Worker       hash_table_foreach(s->linked.ht, entry) {
892*61046927SAndroid Build Coastguard Worker          hk_destroy_linked_shader(dev, entry->data);
893*61046927SAndroid Build Coastguard Worker       }
894*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_destroy(s->linked.ht, NULL);
895*61046927SAndroid Build Coastguard Worker    }
896*61046927SAndroid Build Coastguard Worker }
897*61046927SAndroid Build Coastguard Worker 
898*61046927SAndroid Build Coastguard Worker void
hk_api_shader_destroy(struct vk_device * vk_dev,struct vk_shader * vk_shader,const VkAllocationCallbacks * pAllocator)899*61046927SAndroid Build Coastguard Worker hk_api_shader_destroy(struct vk_device *vk_dev, struct vk_shader *vk_shader,
900*61046927SAndroid Build Coastguard Worker                       const VkAllocationCallbacks *pAllocator)
901*61046927SAndroid Build Coastguard Worker {
902*61046927SAndroid Build Coastguard Worker    struct hk_device *dev = container_of(vk_dev, struct hk_device, vk);
903*61046927SAndroid Build Coastguard Worker    struct hk_api_shader *obj =
904*61046927SAndroid Build Coastguard Worker       container_of(vk_shader, struct hk_api_shader, vk);
905*61046927SAndroid Build Coastguard Worker 
906*61046927SAndroid Build Coastguard Worker    hk_foreach_variant(obj, shader) {
907*61046927SAndroid Build Coastguard Worker       hk_shader_destroy(dev, shader);
908*61046927SAndroid Build Coastguard Worker    }
909*61046927SAndroid Build Coastguard Worker 
910*61046927SAndroid Build Coastguard Worker    vk_shader_free(&dev->vk, pAllocator, &obj->vk);
911*61046927SAndroid Build Coastguard Worker }
912*61046927SAndroid Build Coastguard Worker 
913*61046927SAndroid Build Coastguard Worker static void
hk_lower_hw_vs(nir_shader * nir,struct hk_shader * shader)914*61046927SAndroid Build Coastguard Worker hk_lower_hw_vs(nir_shader *nir, struct hk_shader *shader)
915*61046927SAndroid Build Coastguard Worker {
916*61046927SAndroid Build Coastguard Worker    /* Point size must be clamped, excessively large points don't render
917*61046927SAndroid Build Coastguard Worker     * properly on G13.
918*61046927SAndroid Build Coastguard Worker     *
919*61046927SAndroid Build Coastguard Worker     * Must be synced with pointSizeRange.
920*61046927SAndroid Build Coastguard Worker     */
921*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_point_size, 1.0f, 511.95f);
922*61046927SAndroid Build Coastguard Worker 
923*61046927SAndroid Build Coastguard Worker    /* TODO: Optimize out for monolithic? */
924*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, hk_nir_insert_psiz_write);
925*61046927SAndroid Build Coastguard Worker 
926*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_io_to_scalar, nir_var_shader_out, NULL, NULL);
927*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, agx_nir_lower_cull_distance_vs);
928*61046927SAndroid Build Coastguard Worker 
929*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, agx_nir_lower_uvs, &shader->info.uvs);
930*61046927SAndroid Build Coastguard Worker 
931*61046927SAndroid Build Coastguard Worker    shader->info.vs.cull_distance_array_size =
932*61046927SAndroid Build Coastguard Worker       nir->info.cull_distance_array_size;
933*61046927SAndroid Build Coastguard Worker }
934*61046927SAndroid Build Coastguard Worker 
935*61046927SAndroid Build Coastguard Worker VkResult
hk_compile_shader(struct hk_device * dev,struct vk_shader_compile_info * info,const struct vk_graphics_pipeline_state * state,const VkAllocationCallbacks * pAllocator,struct hk_api_shader ** shader_out)936*61046927SAndroid Build Coastguard Worker hk_compile_shader(struct hk_device *dev, struct vk_shader_compile_info *info,
937*61046927SAndroid Build Coastguard Worker                   const struct vk_graphics_pipeline_state *state,
938*61046927SAndroid Build Coastguard Worker                   const VkAllocationCallbacks *pAllocator,
939*61046927SAndroid Build Coastguard Worker                   struct hk_api_shader **shader_out)
940*61046927SAndroid Build Coastguard Worker {
941*61046927SAndroid Build Coastguard Worker    VkResult result;
942*61046927SAndroid Build Coastguard Worker 
943*61046927SAndroid Build Coastguard Worker    /* We consume the NIR, regardless of success or failure */
944*61046927SAndroid Build Coastguard Worker    nir_shader *nir = info->nir;
945*61046927SAndroid Build Coastguard Worker 
946*61046927SAndroid Build Coastguard Worker    size_t size = sizeof(struct hk_api_shader) +
947*61046927SAndroid Build Coastguard Worker                  sizeof(struct hk_shader) * hk_num_variants(info->stage);
948*61046927SAndroid Build Coastguard Worker    struct hk_api_shader *obj =
949*61046927SAndroid Build Coastguard Worker       vk_shader_zalloc(&dev->vk, &hk_shader_ops, info->stage, pAllocator, size);
950*61046927SAndroid Build Coastguard Worker 
951*61046927SAndroid Build Coastguard Worker    if (obj == NULL) {
952*61046927SAndroid Build Coastguard Worker       ralloc_free(nir);
953*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
954*61046927SAndroid Build Coastguard Worker    }
955*61046927SAndroid Build Coastguard Worker 
956*61046927SAndroid Build Coastguard Worker    /* TODO: Multiview with ESO */
957*61046927SAndroid Build Coastguard Worker    const bool is_multiview = state && state->rp->view_mask != 0;
958*61046927SAndroid Build Coastguard Worker 
959*61046927SAndroid Build Coastguard Worker    hk_lower_nir(dev, nir, info->robustness, is_multiview,
960*61046927SAndroid Build Coastguard Worker                 info->set_layout_count, info->set_layouts);
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker    gl_shader_stage sw_stage = nir->info.stage;
963*61046927SAndroid Build Coastguard Worker 
964*61046927SAndroid Build Coastguard Worker    struct hk_fs_key fs_key_tmp, *fs_key = NULL;
965*61046927SAndroid Build Coastguard Worker    if (sw_stage == MESA_SHADER_FRAGMENT) {
966*61046927SAndroid Build Coastguard Worker       hk_populate_fs_key(&fs_key_tmp, state);
967*61046927SAndroid Build Coastguard Worker       fs_key = &fs_key_tmp;
968*61046927SAndroid Build Coastguard Worker 
969*61046927SAndroid Build Coastguard Worker       nir->info.fs.uses_sample_shading |= fs_key->force_sample_shading;
970*61046927SAndroid Build Coastguard Worker 
971*61046927SAndroid Build Coastguard Worker       /* Force late-Z for Z/S self-deps. TODO: There's probably a less silly way
972*61046927SAndroid Build Coastguard Worker        * to do this.
973*61046927SAndroid Build Coastguard Worker        */
974*61046927SAndroid Build Coastguard Worker       if (fs_key->zs_self_dep) {
975*61046927SAndroid Build Coastguard Worker          nir_builder b =
976*61046927SAndroid Build Coastguard Worker             nir_builder_at(nir_before_impl(nir_shader_get_entrypoint(nir)));
977*61046927SAndroid Build Coastguard Worker          nir_discard_if(&b, nir_imm_false(&b));
978*61046927SAndroid Build Coastguard Worker          nir->info.fs.uses_discard = true;
979*61046927SAndroid Build Coastguard Worker       }
980*61046927SAndroid Build Coastguard Worker 
981*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, agx_nir_lower_sample_intrinsics, false);
982*61046927SAndroid Build Coastguard Worker    } else if (sw_stage == MESA_SHADER_TESS_CTRL) {
983*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, agx_nir_lower_tcs, dev->dev.libagx);
984*61046927SAndroid Build Coastguard Worker    }
985*61046927SAndroid Build Coastguard Worker 
986*61046927SAndroid Build Coastguard Worker    /* Compile all variants up front */
987*61046927SAndroid Build Coastguard Worker    if (sw_stage == MESA_SHADER_GEOMETRY) {
988*61046927SAndroid Build Coastguard Worker       for (unsigned rast_disc = 0; rast_disc < 2; ++rast_disc) {
989*61046927SAndroid Build Coastguard Worker          struct hk_shader *count_variant = hk_count_gs_variant(obj, rast_disc);
990*61046927SAndroid Build Coastguard Worker          nir_shader *clone = nir_shader_clone(NULL, nir);
991*61046927SAndroid Build Coastguard Worker 
992*61046927SAndroid Build Coastguard Worker          enum mesa_prim out_prim = MESA_PRIM_MAX;
993*61046927SAndroid Build Coastguard Worker          nir_shader *count = NULL, *rast = NULL, *pre_gs = NULL;
994*61046927SAndroid Build Coastguard Worker 
995*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, clone, agx_nir_lower_gs, dev->dev.libagx, rast_disc,
996*61046927SAndroid Build Coastguard Worker                   &count, &rast, &pre_gs, &out_prim,
997*61046927SAndroid Build Coastguard Worker                   &count_variant->info.gs.count_words);
998*61046927SAndroid Build Coastguard Worker 
999*61046927SAndroid Build Coastguard Worker          if (!rast_disc) {
1000*61046927SAndroid Build Coastguard Worker             struct hk_shader *shader = &obj->variants[HK_GS_VARIANT_RAST];
1001*61046927SAndroid Build Coastguard Worker 
1002*61046927SAndroid Build Coastguard Worker             hk_lower_hw_vs(rast, shader);
1003*61046927SAndroid Build Coastguard Worker             shader->info.gs.out_prim = out_prim;
1004*61046927SAndroid Build Coastguard Worker          }
1005*61046927SAndroid Build Coastguard Worker 
1006*61046927SAndroid Build Coastguard Worker          struct {
1007*61046927SAndroid Build Coastguard Worker             nir_shader *in;
1008*61046927SAndroid Build Coastguard Worker             struct hk_shader *out;
1009*61046927SAndroid Build Coastguard Worker          } variants[] = {
1010*61046927SAndroid Build Coastguard Worker             {clone, hk_main_gs_variant(obj, rast_disc)},
1011*61046927SAndroid Build Coastguard Worker             {pre_gs, hk_pre_gs_variant(obj, rast_disc)},
1012*61046927SAndroid Build Coastguard Worker             {count, count_variant},
1013*61046927SAndroid Build Coastguard Worker             {rast_disc ? NULL : rast, &obj->variants[HK_GS_VARIANT_RAST]},
1014*61046927SAndroid Build Coastguard Worker          };
1015*61046927SAndroid Build Coastguard Worker 
1016*61046927SAndroid Build Coastguard Worker          for (unsigned v = 0; v < ARRAY_SIZE(variants); ++v) {
1017*61046927SAndroid Build Coastguard Worker             if (variants[v].in) {
1018*61046927SAndroid Build Coastguard Worker                result = hk_compile_nir(dev, pAllocator, variants[v].in,
1019*61046927SAndroid Build Coastguard Worker                                        info->flags, info->robustness, NULL,
1020*61046927SAndroid Build Coastguard Worker                                        variants[v].out, sw_stage, true, NULL);
1021*61046927SAndroid Build Coastguard Worker                if (result != VK_SUCCESS) {
1022*61046927SAndroid Build Coastguard Worker                   hk_api_shader_destroy(&dev->vk, &obj->vk, pAllocator);
1023*61046927SAndroid Build Coastguard Worker                   ralloc_free(nir);
1024*61046927SAndroid Build Coastguard Worker                   return result;
1025*61046927SAndroid Build Coastguard Worker                }
1026*61046927SAndroid Build Coastguard Worker             }
1027*61046927SAndroid Build Coastguard Worker          }
1028*61046927SAndroid Build Coastguard Worker       }
1029*61046927SAndroid Build Coastguard Worker    } else if (sw_stage == MESA_SHADER_VERTEX ||
1030*61046927SAndroid Build Coastguard Worker               sw_stage == MESA_SHADER_TESS_EVAL) {
1031*61046927SAndroid Build Coastguard Worker 
1032*61046927SAndroid Build Coastguard Worker       if (sw_stage == MESA_SHADER_VERTEX) {
1033*61046927SAndroid Build Coastguard Worker          assert(
1034*61046927SAndroid Build Coastguard Worker             !(nir->info.inputs_read & BITFIELD64_MASK(VERT_ATTRIB_GENERIC0)) &&
1035*61046927SAndroid Build Coastguard Worker             "Fixed-function attributes not used in Vulkan");
1036*61046927SAndroid Build Coastguard Worker 
1037*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_recompute_io_bases, nir_var_shader_in);
1038*61046927SAndroid Build Coastguard Worker       }
1039*61046927SAndroid Build Coastguard Worker 
1040*61046927SAndroid Build Coastguard Worker       /* the shader_out portion of this is load-bearing even for tess eval */
1041*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_io_add_const_offset_to_base,
1042*61046927SAndroid Build Coastguard Worker                nir_var_shader_in | nir_var_shader_out);
1043*61046927SAndroid Build Coastguard Worker 
1044*61046927SAndroid Build Coastguard Worker       for (enum hk_vs_variant v = 0; v < HK_VS_VARIANTS; ++v) {
1045*61046927SAndroid Build Coastguard Worker          struct hk_shader *shader = &obj->variants[v];
1046*61046927SAndroid Build Coastguard Worker          bool hw = v == HK_VS_VARIANT_HW;
1047*61046927SAndroid Build Coastguard Worker 
1048*61046927SAndroid Build Coastguard Worker          /* TODO: Optimize single variant when we know nextStage */
1049*61046927SAndroid Build Coastguard Worker          nir_shader *clone = nir_shader_clone(NULL, nir);
1050*61046927SAndroid Build Coastguard Worker 
1051*61046927SAndroid Build Coastguard Worker          if (sw_stage == MESA_SHADER_VERTEX) {
1052*61046927SAndroid Build Coastguard Worker             NIR_PASS(_, clone, agx_nir_lower_vs_input_to_prolog,
1053*61046927SAndroid Build Coastguard Worker                      shader->info.vs.attrib_components_read);
1054*61046927SAndroid Build Coastguard Worker 
1055*61046927SAndroid Build Coastguard Worker             shader->info.vs.attribs_read =
1056*61046927SAndroid Build Coastguard Worker                nir->info.inputs_read >> VERT_ATTRIB_GENERIC0;
1057*61046927SAndroid Build Coastguard Worker          }
1058*61046927SAndroid Build Coastguard Worker 
1059*61046927SAndroid Build Coastguard Worker          if (hw) {
1060*61046927SAndroid Build Coastguard Worker             hk_lower_hw_vs(clone, shader);
1061*61046927SAndroid Build Coastguard Worker          } else {
1062*61046927SAndroid Build Coastguard Worker             NIR_PASS(_, clone, agx_nir_lower_vs_before_gs, dev->dev.libagx);
1063*61046927SAndroid Build Coastguard Worker          }
1064*61046927SAndroid Build Coastguard Worker 
1065*61046927SAndroid Build Coastguard Worker          result = hk_compile_nir(dev, pAllocator, clone, info->flags,
1066*61046927SAndroid Build Coastguard Worker                                  info->robustness, fs_key, shader, sw_stage, hw,
1067*61046927SAndroid Build Coastguard Worker                                  nir->xfb_info);
1068*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS) {
1069*61046927SAndroid Build Coastguard Worker             hk_api_shader_destroy(&dev->vk, &obj->vk, pAllocator);
1070*61046927SAndroid Build Coastguard Worker             ralloc_free(nir);
1071*61046927SAndroid Build Coastguard Worker             return result;
1072*61046927SAndroid Build Coastguard Worker          }
1073*61046927SAndroid Build Coastguard Worker       }
1074*61046927SAndroid Build Coastguard Worker    } else {
1075*61046927SAndroid Build Coastguard Worker       struct hk_shader *shader = hk_only_variant(obj);
1076*61046927SAndroid Build Coastguard Worker 
1077*61046927SAndroid Build Coastguard Worker       /* hk_compile_nir takes ownership of nir */
1078*61046927SAndroid Build Coastguard Worker       result =
1079*61046927SAndroid Build Coastguard Worker          hk_compile_nir(dev, pAllocator, nir, info->flags, info->robustness,
1080*61046927SAndroid Build Coastguard Worker                         fs_key, shader, sw_stage, true, NULL);
1081*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
1082*61046927SAndroid Build Coastguard Worker          hk_api_shader_destroy(&dev->vk, &obj->vk, pAllocator);
1083*61046927SAndroid Build Coastguard Worker          return result;
1084*61046927SAndroid Build Coastguard Worker       }
1085*61046927SAndroid Build Coastguard Worker    }
1086*61046927SAndroid Build Coastguard Worker 
1087*61046927SAndroid Build Coastguard Worker    *shader_out = obj;
1088*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1089*61046927SAndroid Build Coastguard Worker }
1090*61046927SAndroid Build Coastguard Worker 
1091*61046927SAndroid Build Coastguard Worker static VkResult
hk_compile_shaders(struct vk_device * vk_dev,uint32_t shader_count,struct vk_shader_compile_info * infos,const struct vk_graphics_pipeline_state * state,const VkAllocationCallbacks * pAllocator,struct vk_shader ** shaders_out)1092*61046927SAndroid Build Coastguard Worker hk_compile_shaders(struct vk_device *vk_dev, uint32_t shader_count,
1093*61046927SAndroid Build Coastguard Worker                    struct vk_shader_compile_info *infos,
1094*61046927SAndroid Build Coastguard Worker                    const struct vk_graphics_pipeline_state *state,
1095*61046927SAndroid Build Coastguard Worker                    const VkAllocationCallbacks *pAllocator,
1096*61046927SAndroid Build Coastguard Worker                    struct vk_shader **shaders_out)
1097*61046927SAndroid Build Coastguard Worker {
1098*61046927SAndroid Build Coastguard Worker    struct hk_device *dev = container_of(vk_dev, struct hk_device, vk);
1099*61046927SAndroid Build Coastguard Worker 
1100*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < shader_count; i++) {
1101*61046927SAndroid Build Coastguard Worker       VkResult result =
1102*61046927SAndroid Build Coastguard Worker          hk_compile_shader(dev, &infos[i], state, pAllocator,
1103*61046927SAndroid Build Coastguard Worker                            (struct hk_api_shader **)&shaders_out[i]);
1104*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
1105*61046927SAndroid Build Coastguard Worker          /* Clean up all the shaders before this point */
1106*61046927SAndroid Build Coastguard Worker          for (uint32_t j = 0; j < i; j++)
1107*61046927SAndroid Build Coastguard Worker             hk_api_shader_destroy(&dev->vk, shaders_out[j], pAllocator);
1108*61046927SAndroid Build Coastguard Worker 
1109*61046927SAndroid Build Coastguard Worker          /* Clean up all the NIR after this point */
1110*61046927SAndroid Build Coastguard Worker          for (uint32_t j = i + 1; j < shader_count; j++)
1111*61046927SAndroid Build Coastguard Worker             ralloc_free(infos[j].nir);
1112*61046927SAndroid Build Coastguard Worker 
1113*61046927SAndroid Build Coastguard Worker          /* Memset the output array */
1114*61046927SAndroid Build Coastguard Worker          memset(shaders_out, 0, shader_count * sizeof(*shaders_out));
1115*61046927SAndroid Build Coastguard Worker 
1116*61046927SAndroid Build Coastguard Worker          return result;
1117*61046927SAndroid Build Coastguard Worker       }
1118*61046927SAndroid Build Coastguard Worker    }
1119*61046927SAndroid Build Coastguard Worker 
1120*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1121*61046927SAndroid Build Coastguard Worker }
1122*61046927SAndroid Build Coastguard Worker 
1123*61046927SAndroid Build Coastguard Worker static VkResult
hk_deserialize_shader(struct hk_device * dev,struct blob_reader * blob,struct hk_shader * shader)1124*61046927SAndroid Build Coastguard Worker hk_deserialize_shader(struct hk_device *dev, struct blob_reader *blob,
1125*61046927SAndroid Build Coastguard Worker                       struct hk_shader *shader)
1126*61046927SAndroid Build Coastguard Worker {
1127*61046927SAndroid Build Coastguard Worker    struct hk_shader_info info;
1128*61046927SAndroid Build Coastguard Worker    blob_copy_bytes(blob, &info, sizeof(info));
1129*61046927SAndroid Build Coastguard Worker 
1130*61046927SAndroid Build Coastguard Worker    struct agx_shader_info b_info;
1131*61046927SAndroid Build Coastguard Worker    blob_copy_bytes(blob, &b_info, sizeof(b_info));
1132*61046927SAndroid Build Coastguard Worker 
1133*61046927SAndroid Build Coastguard Worker    const uint32_t code_size = blob_read_uint32(blob);
1134*61046927SAndroid Build Coastguard Worker    const uint32_t data_size = blob_read_uint32(blob);
1135*61046927SAndroid Build Coastguard Worker    if (blob->overrun)
1136*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
1137*61046927SAndroid Build Coastguard Worker 
1138*61046927SAndroid Build Coastguard Worker    VkResult result = hk_init_link_ht(shader, info.stage);
1139*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
1140*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
1141*61046927SAndroid Build Coastguard Worker 
1142*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&shader->linked.lock, mtx_plain);
1143*61046927SAndroid Build Coastguard Worker 
1144*61046927SAndroid Build Coastguard Worker    shader->b.info = b_info;
1145*61046927SAndroid Build Coastguard Worker    shader->info = info;
1146*61046927SAndroid Build Coastguard Worker    shader->code_size = code_size;
1147*61046927SAndroid Build Coastguard Worker    shader->data_size = data_size;
1148*61046927SAndroid Build Coastguard Worker    shader->b.binary_size = code_size;
1149*61046927SAndroid Build Coastguard Worker 
1150*61046927SAndroid Build Coastguard Worker    shader->code_ptr = malloc(code_size);
1151*61046927SAndroid Build Coastguard Worker    if (shader->code_ptr == NULL)
1152*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
1153*61046927SAndroid Build Coastguard Worker 
1154*61046927SAndroid Build Coastguard Worker    shader->data_ptr = malloc(data_size);
1155*61046927SAndroid Build Coastguard Worker    if (shader->data_ptr == NULL)
1156*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
1157*61046927SAndroid Build Coastguard Worker 
1158*61046927SAndroid Build Coastguard Worker    blob_copy_bytes(blob, (void *)shader->code_ptr, shader->code_size);
1159*61046927SAndroid Build Coastguard Worker    blob_copy_bytes(blob, (void *)shader->data_ptr, shader->data_size);
1160*61046927SAndroid Build Coastguard Worker    if (blob->overrun)
1161*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
1162*61046927SAndroid Build Coastguard Worker 
1163*61046927SAndroid Build Coastguard Worker    shader->b.binary = (void *)shader->code_ptr;
1164*61046927SAndroid Build Coastguard Worker    hk_upload_shader(dev, shader);
1165*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1166*61046927SAndroid Build Coastguard Worker }
1167*61046927SAndroid Build Coastguard Worker 
1168*61046927SAndroid Build Coastguard Worker static VkResult
hk_deserialize_api_shader(struct vk_device * vk_dev,struct blob_reader * blob,uint32_t binary_version,const VkAllocationCallbacks * pAllocator,struct vk_shader ** shader_out)1169*61046927SAndroid Build Coastguard Worker hk_deserialize_api_shader(struct vk_device *vk_dev, struct blob_reader *blob,
1170*61046927SAndroid Build Coastguard Worker                           uint32_t binary_version,
1171*61046927SAndroid Build Coastguard Worker                           const VkAllocationCallbacks *pAllocator,
1172*61046927SAndroid Build Coastguard Worker                           struct vk_shader **shader_out)
1173*61046927SAndroid Build Coastguard Worker {
1174*61046927SAndroid Build Coastguard Worker    struct hk_device *dev = container_of(vk_dev, struct hk_device, vk);
1175*61046927SAndroid Build Coastguard Worker 
1176*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage = blob_read_uint8(blob);
1177*61046927SAndroid Build Coastguard Worker    if (blob->overrun)
1178*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
1179*61046927SAndroid Build Coastguard Worker 
1180*61046927SAndroid Build Coastguard Worker    size_t size = sizeof(struct hk_api_shader) +
1181*61046927SAndroid Build Coastguard Worker                  sizeof(struct hk_shader) * hk_num_variants(stage);
1182*61046927SAndroid Build Coastguard Worker 
1183*61046927SAndroid Build Coastguard Worker    struct hk_api_shader *obj =
1184*61046927SAndroid Build Coastguard Worker       vk_shader_zalloc(&dev->vk, &hk_shader_ops, stage, pAllocator, size);
1185*61046927SAndroid Build Coastguard Worker 
1186*61046927SAndroid Build Coastguard Worker    if (obj == NULL)
1187*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
1188*61046927SAndroid Build Coastguard Worker 
1189*61046927SAndroid Build Coastguard Worker    hk_foreach_variant(obj, shader) {
1190*61046927SAndroid Build Coastguard Worker       VkResult result = hk_deserialize_shader(dev, blob, shader);
1191*61046927SAndroid Build Coastguard Worker 
1192*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
1193*61046927SAndroid Build Coastguard Worker          hk_api_shader_destroy(&dev->vk, &obj->vk, pAllocator);
1194*61046927SAndroid Build Coastguard Worker          return result;
1195*61046927SAndroid Build Coastguard Worker       }
1196*61046927SAndroid Build Coastguard Worker    }
1197*61046927SAndroid Build Coastguard Worker 
1198*61046927SAndroid Build Coastguard Worker    *shader_out = &obj->vk;
1199*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1200*61046927SAndroid Build Coastguard Worker }
1201*61046927SAndroid Build Coastguard Worker 
1202*61046927SAndroid Build Coastguard Worker static void
hk_shader_serialize(struct vk_device * vk_dev,const struct hk_shader * shader,struct blob * blob)1203*61046927SAndroid Build Coastguard Worker hk_shader_serialize(struct vk_device *vk_dev, const struct hk_shader *shader,
1204*61046927SAndroid Build Coastguard Worker                     struct blob *blob)
1205*61046927SAndroid Build Coastguard Worker {
1206*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, &shader->info, sizeof(shader->info));
1207*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, &shader->b.info, sizeof(shader->b.info));
1208*61046927SAndroid Build Coastguard Worker 
1209*61046927SAndroid Build Coastguard Worker    blob_write_uint32(blob, shader->code_size);
1210*61046927SAndroid Build Coastguard Worker    blob_write_uint32(blob, shader->data_size);
1211*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, shader->code_ptr, shader->code_size);
1212*61046927SAndroid Build Coastguard Worker    blob_write_bytes(blob, shader->data_ptr, shader->data_size);
1213*61046927SAndroid Build Coastguard Worker }
1214*61046927SAndroid Build Coastguard Worker 
1215*61046927SAndroid Build Coastguard Worker static bool
hk_api_shader_serialize(struct vk_device * vk_dev,const struct vk_shader * vk_shader,struct blob * blob)1216*61046927SAndroid Build Coastguard Worker hk_api_shader_serialize(struct vk_device *vk_dev,
1217*61046927SAndroid Build Coastguard Worker                         const struct vk_shader *vk_shader, struct blob *blob)
1218*61046927SAndroid Build Coastguard Worker {
1219*61046927SAndroid Build Coastguard Worker    struct hk_api_shader *obj =
1220*61046927SAndroid Build Coastguard Worker       container_of(vk_shader, struct hk_api_shader, vk);
1221*61046927SAndroid Build Coastguard Worker 
1222*61046927SAndroid Build Coastguard Worker    blob_write_uint8(blob, vk_shader->stage);
1223*61046927SAndroid Build Coastguard Worker 
1224*61046927SAndroid Build Coastguard Worker    hk_foreach_variant(obj, shader) {
1225*61046927SAndroid Build Coastguard Worker       hk_shader_serialize(vk_dev, shader, blob);
1226*61046927SAndroid Build Coastguard Worker    }
1227*61046927SAndroid Build Coastguard Worker 
1228*61046927SAndroid Build Coastguard Worker    return !blob->out_of_memory;
1229*61046927SAndroid Build Coastguard Worker }
1230*61046927SAndroid Build Coastguard Worker 
1231*61046927SAndroid Build Coastguard Worker #define WRITE_STR(field, ...)                                                  \
1232*61046927SAndroid Build Coastguard Worker    ({                                                                          \
1233*61046927SAndroid Build Coastguard Worker       memset(field, 0, sizeof(field));                                         \
1234*61046927SAndroid Build Coastguard Worker       UNUSED int i = snprintf(field, sizeof(field), __VA_ARGS__);              \
1235*61046927SAndroid Build Coastguard Worker       assert(i > 0 && i < sizeof(field));                                      \
1236*61046927SAndroid Build Coastguard Worker    })
1237*61046927SAndroid Build Coastguard Worker 
1238*61046927SAndroid Build Coastguard Worker static VkResult
hk_shader_get_executable_properties(UNUSED struct vk_device * device,const struct vk_shader * vk_shader,uint32_t * executable_count,VkPipelineExecutablePropertiesKHR * properties)1239*61046927SAndroid Build Coastguard Worker hk_shader_get_executable_properties(
1240*61046927SAndroid Build Coastguard Worker    UNUSED struct vk_device *device, const struct vk_shader *vk_shader,
1241*61046927SAndroid Build Coastguard Worker    uint32_t *executable_count, VkPipelineExecutablePropertiesKHR *properties)
1242*61046927SAndroid Build Coastguard Worker {
1243*61046927SAndroid Build Coastguard Worker    struct hk_api_shader *obj =
1244*61046927SAndroid Build Coastguard Worker       container_of(vk_shader, struct hk_api_shader, vk);
1245*61046927SAndroid Build Coastguard Worker 
1246*61046927SAndroid Build Coastguard Worker    VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutablePropertiesKHR, out, properties,
1247*61046927SAndroid Build Coastguard Worker                           executable_count);
1248*61046927SAndroid Build Coastguard Worker 
1249*61046927SAndroid Build Coastguard Worker    vk_outarray_append_typed(VkPipelineExecutablePropertiesKHR, &out, props)
1250*61046927SAndroid Build Coastguard Worker    {
1251*61046927SAndroid Build Coastguard Worker       props->stages = mesa_to_vk_shader_stage(obj->vk.stage);
1252*61046927SAndroid Build Coastguard Worker       props->subgroupSize = 32;
1253*61046927SAndroid Build Coastguard Worker       WRITE_STR(props->name, "%s", _mesa_shader_stage_to_string(obj->vk.stage));
1254*61046927SAndroid Build Coastguard Worker       WRITE_STR(props->description, "%s shader",
1255*61046927SAndroid Build Coastguard Worker                 _mesa_shader_stage_to_string(obj->vk.stage));
1256*61046927SAndroid Build Coastguard Worker    }
1257*61046927SAndroid Build Coastguard Worker 
1258*61046927SAndroid Build Coastguard Worker    return vk_outarray_status(&out);
1259*61046927SAndroid Build Coastguard Worker }
1260*61046927SAndroid Build Coastguard Worker 
1261*61046927SAndroid Build Coastguard Worker static VkResult
hk_shader_get_executable_statistics(UNUSED struct vk_device * device,const struct vk_shader * vk_shader,uint32_t executable_index,uint32_t * statistic_count,VkPipelineExecutableStatisticKHR * statistics)1262*61046927SAndroid Build Coastguard Worker hk_shader_get_executable_statistics(
1263*61046927SAndroid Build Coastguard Worker    UNUSED struct vk_device *device, const struct vk_shader *vk_shader,
1264*61046927SAndroid Build Coastguard Worker    uint32_t executable_index, uint32_t *statistic_count,
1265*61046927SAndroid Build Coastguard Worker    VkPipelineExecutableStatisticKHR *statistics)
1266*61046927SAndroid Build Coastguard Worker {
1267*61046927SAndroid Build Coastguard Worker    struct hk_api_shader *obj =
1268*61046927SAndroid Build Coastguard Worker       container_of(vk_shader, struct hk_api_shader, vk);
1269*61046927SAndroid Build Coastguard Worker 
1270*61046927SAndroid Build Coastguard Worker    VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableStatisticKHR, out, statistics,
1271*61046927SAndroid Build Coastguard Worker                           statistic_count);
1272*61046927SAndroid Build Coastguard Worker 
1273*61046927SAndroid Build Coastguard Worker    assert(executable_index == 0);
1274*61046927SAndroid Build Coastguard Worker 
1275*61046927SAndroid Build Coastguard Worker    /* TODO: find a sane way to report multiple variants and have that play nice
1276*61046927SAndroid Build Coastguard Worker     * with zink.
1277*61046927SAndroid Build Coastguard Worker     */
1278*61046927SAndroid Build Coastguard Worker    struct hk_shader *shader = hk_any_variant(obj);
1279*61046927SAndroid Build Coastguard Worker 
1280*61046927SAndroid Build Coastguard Worker    vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat)
1281*61046927SAndroid Build Coastguard Worker    {
1282*61046927SAndroid Build Coastguard Worker       WRITE_STR(stat->name, "Code Size");
1283*61046927SAndroid Build Coastguard Worker       WRITE_STR(stat->description,
1284*61046927SAndroid Build Coastguard Worker                 "Size of the compiled shader binary, in bytes");
1285*61046927SAndroid Build Coastguard Worker       stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
1286*61046927SAndroid Build Coastguard Worker       stat->value.u64 = shader->code_size;
1287*61046927SAndroid Build Coastguard Worker    }
1288*61046927SAndroid Build Coastguard Worker 
1289*61046927SAndroid Build Coastguard Worker    vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat)
1290*61046927SAndroid Build Coastguard Worker    {
1291*61046927SAndroid Build Coastguard Worker       WRITE_STR(stat->name, "Number of GPRs");
1292*61046927SAndroid Build Coastguard Worker       WRITE_STR(stat->description, "Number of GPRs used by this pipeline");
1293*61046927SAndroid Build Coastguard Worker       stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
1294*61046927SAndroid Build Coastguard Worker       stat->value.u64 = shader->b.info.nr_gprs;
1295*61046927SAndroid Build Coastguard Worker    }
1296*61046927SAndroid Build Coastguard Worker 
1297*61046927SAndroid Build Coastguard Worker    return vk_outarray_status(&out);
1298*61046927SAndroid Build Coastguard Worker }
1299*61046927SAndroid Build Coastguard Worker 
1300*61046927SAndroid Build Coastguard Worker static bool
write_ir_text(VkPipelineExecutableInternalRepresentationKHR * ir,const char * data)1301*61046927SAndroid Build Coastguard Worker write_ir_text(VkPipelineExecutableInternalRepresentationKHR *ir,
1302*61046927SAndroid Build Coastguard Worker               const char *data)
1303*61046927SAndroid Build Coastguard Worker {
1304*61046927SAndroid Build Coastguard Worker    ir->isText = VK_TRUE;
1305*61046927SAndroid Build Coastguard Worker 
1306*61046927SAndroid Build Coastguard Worker    size_t data_len = strlen(data) + 1;
1307*61046927SAndroid Build Coastguard Worker 
1308*61046927SAndroid Build Coastguard Worker    if (ir->pData == NULL) {
1309*61046927SAndroid Build Coastguard Worker       ir->dataSize = data_len;
1310*61046927SAndroid Build Coastguard Worker       return true;
1311*61046927SAndroid Build Coastguard Worker    }
1312*61046927SAndroid Build Coastguard Worker 
1313*61046927SAndroid Build Coastguard Worker    strncpy(ir->pData, data, ir->dataSize);
1314*61046927SAndroid Build Coastguard Worker    if (ir->dataSize < data_len)
1315*61046927SAndroid Build Coastguard Worker       return false;
1316*61046927SAndroid Build Coastguard Worker 
1317*61046927SAndroid Build Coastguard Worker    ir->dataSize = data_len;
1318*61046927SAndroid Build Coastguard Worker    return true;
1319*61046927SAndroid Build Coastguard Worker }
1320*61046927SAndroid Build Coastguard Worker 
1321*61046927SAndroid Build Coastguard Worker static VkResult
hk_shader_get_executable_internal_representations(UNUSED struct vk_device * device,const struct vk_shader * vk_shader,uint32_t executable_index,uint32_t * internal_representation_count,VkPipelineExecutableInternalRepresentationKHR * internal_representations)1322*61046927SAndroid Build Coastguard Worker hk_shader_get_executable_internal_representations(
1323*61046927SAndroid Build Coastguard Worker    UNUSED struct vk_device *device, const struct vk_shader *vk_shader,
1324*61046927SAndroid Build Coastguard Worker    uint32_t executable_index, uint32_t *internal_representation_count,
1325*61046927SAndroid Build Coastguard Worker    VkPipelineExecutableInternalRepresentationKHR *internal_representations)
1326*61046927SAndroid Build Coastguard Worker {
1327*61046927SAndroid Build Coastguard Worker    VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableInternalRepresentationKHR, out,
1328*61046927SAndroid Build Coastguard Worker                           internal_representations,
1329*61046927SAndroid Build Coastguard Worker                           internal_representation_count);
1330*61046927SAndroid Build Coastguard Worker    bool incomplete_text = false;
1331*61046927SAndroid Build Coastguard Worker 
1332*61046927SAndroid Build Coastguard Worker    assert(executable_index == 0);
1333*61046927SAndroid Build Coastguard Worker 
1334*61046927SAndroid Build Coastguard Worker    /* TODO */
1335*61046927SAndroid Build Coastguard Worker #if 0
1336*61046927SAndroid Build Coastguard Worker    vk_outarray_append_typed(VkPipelineExecutableInternalRepresentationKHR, &out, ir) {
1337*61046927SAndroid Build Coastguard Worker       WRITE_STR(ir->name, "AGX assembly");
1338*61046927SAndroid Build Coastguard Worker       WRITE_STR(ir->description, "AGX assembly");
1339*61046927SAndroid Build Coastguard Worker       if (!write_ir_text(ir, TODO))
1340*61046927SAndroid Build Coastguard Worker          incomplete_text = true;
1341*61046927SAndroid Build Coastguard Worker    }
1342*61046927SAndroid Build Coastguard Worker #endif
1343*61046927SAndroid Build Coastguard Worker 
1344*61046927SAndroid Build Coastguard Worker    return incomplete_text ? VK_INCOMPLETE : vk_outarray_status(&out);
1345*61046927SAndroid Build Coastguard Worker }
1346*61046927SAndroid Build Coastguard Worker 
1347*61046927SAndroid Build Coastguard Worker static const struct vk_shader_ops hk_shader_ops = {
1348*61046927SAndroid Build Coastguard Worker    .destroy = hk_api_shader_destroy,
1349*61046927SAndroid Build Coastguard Worker    .serialize = hk_api_shader_serialize,
1350*61046927SAndroid Build Coastguard Worker    .get_executable_properties = hk_shader_get_executable_properties,
1351*61046927SAndroid Build Coastguard Worker    .get_executable_statistics = hk_shader_get_executable_statistics,
1352*61046927SAndroid Build Coastguard Worker    .get_executable_internal_representations =
1353*61046927SAndroid Build Coastguard Worker       hk_shader_get_executable_internal_representations,
1354*61046927SAndroid Build Coastguard Worker };
1355*61046927SAndroid Build Coastguard Worker 
1356*61046927SAndroid Build Coastguard Worker const struct vk_device_shader_ops hk_device_shader_ops = {
1357*61046927SAndroid Build Coastguard Worker    .get_nir_options = hk_get_nir_options,
1358*61046927SAndroid Build Coastguard Worker    .get_spirv_options = hk_get_spirv_options,
1359*61046927SAndroid Build Coastguard Worker    .preprocess_nir = hk_preprocess_nir,
1360*61046927SAndroid Build Coastguard Worker    .hash_graphics_state = hk_hash_graphics_state,
1361*61046927SAndroid Build Coastguard Worker    .compile = hk_compile_shaders,
1362*61046927SAndroid Build Coastguard Worker    .deserialize = hk_deserialize_api_shader,
1363*61046927SAndroid Build Coastguard Worker    .cmd_set_dynamic_graphics_state = vk_cmd_set_dynamic_graphics_state,
1364*61046927SAndroid Build Coastguard Worker    .cmd_bind_shaders = hk_cmd_bind_shaders,
1365*61046927SAndroid Build Coastguard Worker };
1366*61046927SAndroid Build Coastguard Worker 
1367*61046927SAndroid Build Coastguard Worker struct hk_linked_shader *
hk_fast_link(struct hk_device * dev,bool fragment,struct hk_shader * main,struct agx_shader_part * prolog,struct agx_shader_part * epilog,unsigned nr_samples_shaded)1368*61046927SAndroid Build Coastguard Worker hk_fast_link(struct hk_device *dev, bool fragment, struct hk_shader *main,
1369*61046927SAndroid Build Coastguard Worker              struct agx_shader_part *prolog, struct agx_shader_part *epilog,
1370*61046927SAndroid Build Coastguard Worker              unsigned nr_samples_shaded)
1371*61046927SAndroid Build Coastguard Worker {
1372*61046927SAndroid Build Coastguard Worker    struct hk_linked_shader *s = rzalloc(NULL, struct hk_linked_shader);
1373*61046927SAndroid Build Coastguard Worker    agx_fast_link(&s->b, &dev->dev, fragment, &main->b, prolog, epilog,
1374*61046927SAndroid Build Coastguard Worker                  nr_samples_shaded);
1375*61046927SAndroid Build Coastguard Worker 
1376*61046927SAndroid Build Coastguard Worker    if (fragment) {
1377*61046927SAndroid Build Coastguard Worker       agx_pack(&s->fs_counts, FRAGMENT_SHADER_WORD_0, cfg) {
1378*61046927SAndroid Build Coastguard Worker          cfg.cf_binding_count = s->b.cf.nr_bindings;
1379*61046927SAndroid Build Coastguard Worker          cfg.uniform_register_count = main->b.info.push_count;
1380*61046927SAndroid Build Coastguard Worker          cfg.preshader_register_count = main->b.info.nr_preamble_gprs;
1381*61046927SAndroid Build Coastguard Worker          cfg.sampler_state_register_count =
1382*61046927SAndroid Build Coastguard Worker             agx_translate_sampler_state_count(s->b.uses_txf ? 1 : 0, false);
1383*61046927SAndroid Build Coastguard Worker       }
1384*61046927SAndroid Build Coastguard Worker    }
1385*61046927SAndroid Build Coastguard Worker 
1386*61046927SAndroid Build Coastguard Worker    /* Now that we've linked, bake the USC words to bind this program */
1387*61046927SAndroid Build Coastguard Worker    struct agx_usc_builder b = agx_usc_builder(s->usc.data, sizeof(s->usc.data));
1388*61046927SAndroid Build Coastguard Worker 
1389*61046927SAndroid Build Coastguard Worker    if (main && main->b.info.immediate_size_16) {
1390*61046927SAndroid Build Coastguard Worker       unreachable("todo");
1391*61046927SAndroid Build Coastguard Worker #if 0
1392*61046927SAndroid Build Coastguard Worker       /* XXX: do ahead of time */
1393*61046927SAndroid Build Coastguard Worker       uint64_t ptr = agx_pool_upload_aligned(
1394*61046927SAndroid Build Coastguard Worker          &cmd->pool, s->b.info.immediates, s->b.info.immediate_size_16 * 2, 64);
1395*61046927SAndroid Build Coastguard Worker 
1396*61046927SAndroid Build Coastguard Worker       for (unsigned range = 0; range < constant_push_ranges; ++range) {
1397*61046927SAndroid Build Coastguard Worker          unsigned offset = 64 * range;
1398*61046927SAndroid Build Coastguard Worker          assert(offset < s->b.info.immediate_size_16);
1399*61046927SAndroid Build Coastguard Worker 
1400*61046927SAndroid Build Coastguard Worker          agx_usc_uniform(&b, s->b.info.immediate_base_uniform + offset,
1401*61046927SAndroid Build Coastguard Worker                          MIN2(64, s->b.info.immediate_size_16 - offset),
1402*61046927SAndroid Build Coastguard Worker                          ptr + (offset * 2));
1403*61046927SAndroid Build Coastguard Worker       }
1404*61046927SAndroid Build Coastguard Worker #endif
1405*61046927SAndroid Build Coastguard Worker    }
1406*61046927SAndroid Build Coastguard Worker 
1407*61046927SAndroid Build Coastguard Worker    agx_usc_push_packed(&b, UNIFORM, dev->rodata.image_heap);
1408*61046927SAndroid Build Coastguard Worker 
1409*61046927SAndroid Build Coastguard Worker    if (s->b.uses_txf)
1410*61046927SAndroid Build Coastguard Worker       agx_usc_push_packed(&b, SAMPLER, dev->rodata.txf_sampler);
1411*61046927SAndroid Build Coastguard Worker 
1412*61046927SAndroid Build Coastguard Worker    agx_usc_shared_non_fragment(&b, &main->b.info, 0);
1413*61046927SAndroid Build Coastguard Worker    agx_usc_push_packed(&b, SHADER, s->b.shader);
1414*61046927SAndroid Build Coastguard Worker    agx_usc_push_packed(&b, REGISTERS, s->b.regs);
1415*61046927SAndroid Build Coastguard Worker 
1416*61046927SAndroid Build Coastguard Worker    if (fragment)
1417*61046927SAndroid Build Coastguard Worker       agx_usc_push_packed(&b, FRAGMENT_PROPERTIES, s->b.fragment_props);
1418*61046927SAndroid Build Coastguard Worker 
1419*61046927SAndroid Build Coastguard Worker    if (main && main->b.info.has_preamble) {
1420*61046927SAndroid Build Coastguard Worker       agx_usc_pack(&b, PRESHADER, cfg) {
1421*61046927SAndroid Build Coastguard Worker          cfg.code = agx_usc_addr(&dev->dev, main->preamble_addr);
1422*61046927SAndroid Build Coastguard Worker       }
1423*61046927SAndroid Build Coastguard Worker    } else {
1424*61046927SAndroid Build Coastguard Worker       agx_usc_pack(&b, NO_PRESHADER, cfg)
1425*61046927SAndroid Build Coastguard Worker          ;
1426*61046927SAndroid Build Coastguard Worker    }
1427*61046927SAndroid Build Coastguard Worker 
1428*61046927SAndroid Build Coastguard Worker    s->usc.size = b.head - s->usc.data;
1429*61046927SAndroid Build Coastguard Worker    return s;
1430*61046927SAndroid Build Coastguard Worker }
1431