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