xref: /aosp_15_r20/external/mesa3d/src/panfrost/lib/pan_shader.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (C) 2021 Collabora, Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  */
24 
25 #ifndef __PAN_SHADER_H__
26 #define __PAN_SHADER_H__
27 
28 #include "compiler/nir/nir.h"
29 #include "panfrost/compiler/bifrost/disassemble.h"
30 #include "panfrost/compiler/valhall/disassemble.h"
31 #include "panfrost/midgard/disassemble.h"
32 #include "panfrost/util/pan_ir.h"
33 #include "panfrost/util/pan_lower_framebuffer.h"
34 #include "panfrost/lib/pan_props.h"
35 #include "genxml/gen_macros.h"
36 
37 void bifrost_preprocess_nir(nir_shader *nir, unsigned gpu_id);
38 void midgard_preprocess_nir(nir_shader *nir, unsigned gpu_id);
39 
40 static inline void
pan_shader_preprocess(nir_shader * nir,unsigned gpu_id)41 pan_shader_preprocess(nir_shader *nir, unsigned gpu_id)
42 {
43    if (pan_arch(gpu_id) >= 6)
44       bifrost_preprocess_nir(nir, gpu_id);
45    else
46       midgard_preprocess_nir(nir, gpu_id);
47 }
48 
49 static inline void
pan_shader_disassemble(FILE * fp,const void * code,size_t size,unsigned gpu_id,bool verbose)50 pan_shader_disassemble(FILE *fp, const void *code, size_t size, unsigned gpu_id,
51                        bool verbose)
52 {
53    if (pan_arch(gpu_id) >= 9)
54       disassemble_valhall(fp, (const uint64_t *)code, size, verbose);
55    else if (pan_arch(gpu_id) >= 6)
56       disassemble_bifrost(fp, code, size, verbose);
57    else
58       disassemble_midgard(fp, code, size, gpu_id, verbose);
59 }
60 
61 uint8_t pan_raw_format_mask_midgard(enum pipe_format *formats);
62 
63 #ifdef PAN_ARCH
64 const nir_shader_compiler_options *GENX(pan_shader_get_compiler_options)(void);
65 
66 void GENX(pan_shader_compile)(nir_shader *nir,
67                               struct panfrost_compile_inputs *inputs,
68                               struct util_dynarray *binary,
69                               struct pan_shader_info *info);
70 
71 #if PAN_ARCH >= 6 && PAN_ARCH <= 7
72 enum mali_register_file_format
73    GENX(pan_fixup_blend_type)(nir_alu_type T_size, enum pipe_format format);
74 #endif
75 
76 #if PAN_ARCH >= 9
77 static inline enum mali_shader_stage
pan_shader_stage(const struct pan_shader_info * info)78 pan_shader_stage(const struct pan_shader_info *info)
79 {
80    switch (info->stage) {
81    case MESA_SHADER_VERTEX:
82       return MALI_SHADER_STAGE_VERTEX;
83    case MESA_SHADER_FRAGMENT:
84       return MALI_SHADER_STAGE_FRAGMENT;
85    default:
86       return MALI_SHADER_STAGE_COMPUTE;
87    }
88 }
89 #endif
90 
91 #if PAN_ARCH >= 7
92 static inline enum mali_shader_register_allocation
pan_register_allocation(unsigned work_reg_count)93 pan_register_allocation(unsigned work_reg_count)
94 {
95    return (work_reg_count <= 32)
96              ? MALI_SHADER_REGISTER_ALLOCATION_32_PER_THREAD
97              : MALI_SHADER_REGISTER_ALLOCATION_64_PER_THREAD;
98 }
99 #endif
100 
101 static inline enum mali_depth_source
pan_depth_source(const struct pan_shader_info * info)102 pan_depth_source(const struct pan_shader_info *info)
103 {
104    return info->fs.writes_depth ? MALI_DEPTH_SOURCE_SHADER
105                                 : MALI_DEPTH_SOURCE_FIXED_FUNCTION;
106 }
107 
108 #if PAN_ARCH <= 7
109 #if PAN_ARCH <= 5
110 static inline void
pan_shader_prepare_midgard_rsd(const struct pan_shader_info * info,struct MALI_RENDERER_STATE * rsd)111 pan_shader_prepare_midgard_rsd(const struct pan_shader_info *info,
112                                struct MALI_RENDERER_STATE *rsd)
113 {
114    assert((info->push.count & 3) == 0);
115 
116    rsd->properties.uniform_count = info->push.count / 4;
117    rsd->properties.shader_has_side_effects = info->writes_global;
118    rsd->properties.fp_mode = MALI_FP_MODE_GL_INF_NAN_ALLOWED;
119 
120    /* For fragment shaders, work register count, early-z, reads at draw-time */
121 
122    if (info->stage != MESA_SHADER_FRAGMENT) {
123       rsd->properties.work_register_count = info->work_reg_count;
124    } else {
125       rsd->properties.shader_reads_tilebuffer = info->fs.outputs_read;
126 
127       /* However, forcing early-z in the shader overrides draw-time */
128       rsd->properties.force_early_z = info->fs.early_fragment_tests;
129    }
130 }
131 
132 #else
133 
134 #define pan_preloads(reg) (preload & BITFIELD64_BIT(reg))
135 
136 static void
pan_make_preload(gl_shader_stage stage,uint64_t preload,struct MALI_PRELOAD * out)137 pan_make_preload(gl_shader_stage stage, uint64_t preload,
138                  struct MALI_PRELOAD *out)
139 {
140    switch (stage) {
141    case MESA_SHADER_VERTEX:
142       out->vertex.position_result_address_lo = pan_preloads(58);
143       out->vertex.position_result_address_hi = pan_preloads(59);
144       out->vertex.vertex_id = pan_preloads(61);
145       out->vertex.instance_id = pan_preloads(62);
146       break;
147 
148    case MESA_SHADER_FRAGMENT:
149       out->fragment.primitive_id = pan_preloads(57);
150       out->fragment.primitive_flags = pan_preloads(58);
151       out->fragment.fragment_position = pan_preloads(59);
152       out->fragment.sample_mask_id = pan_preloads(61);
153       out->fragment.coverage = true;
154       break;
155 
156    default:
157       out->compute.local_invocation_xy = pan_preloads(55);
158       out->compute.local_invocation_z = pan_preloads(56);
159       out->compute.work_group_x = pan_preloads(57);
160       out->compute.work_group_y = pan_preloads(58);
161       out->compute.work_group_z = pan_preloads(59);
162       out->compute.global_invocation_x = pan_preloads(60);
163       out->compute.global_invocation_y = pan_preloads(61);
164       out->compute.global_invocation_z = pan_preloads(62);
165       break;
166    }
167 }
168 
169 #if PAN_ARCH == 7
170 static inline void
pan_pack_message_preload(struct MALI_MESSAGE_PRELOAD * cfg,const struct bifrost_message_preload * msg)171 pan_pack_message_preload(struct MALI_MESSAGE_PRELOAD *cfg,
172                          const struct bifrost_message_preload *msg)
173 {
174    enum mali_message_preload_register_format regfmt =
175       msg->fp16 ? MALI_MESSAGE_PRELOAD_REGISTER_FORMAT_F16
176                 : MALI_MESSAGE_PRELOAD_REGISTER_FORMAT_F32;
177 
178    if (msg->enabled && msg->texture) {
179       cfg->type = MALI_MESSAGE_TYPE_VAR_TEX;
180       cfg->var_tex.varying_index = msg->varying_index;
181       cfg->var_tex.texture_index = msg->texture_index;
182       cfg->var_tex.register_format = regfmt;
183       cfg->var_tex.skip = msg->skip;
184       cfg->var_tex.zero_lod = msg->zero_lod;
185    } else if (msg->enabled) {
186       cfg->type = MALI_MESSAGE_TYPE_LD_VAR;
187       cfg->ld_var.varying_index = msg->varying_index;
188       cfg->ld_var.register_format = regfmt;
189       cfg->ld_var.num_components = msg->num_components;
190    } else {
191       cfg->type = MALI_MESSAGE_TYPE_DISABLED;
192    }
193 }
194 #endif
195 
196 static inline void
pan_shader_prepare_bifrost_rsd(const struct pan_shader_info * info,struct MALI_RENDERER_STATE * rsd)197 pan_shader_prepare_bifrost_rsd(const struct pan_shader_info *info,
198                                struct MALI_RENDERER_STATE *rsd)
199 {
200    unsigned fau_count = DIV_ROUND_UP(info->push.count, 2);
201    rsd->preload.uniform_count = fau_count;
202 
203 #if PAN_ARCH >= 7
204    rsd->properties.shader_register_allocation =
205       pan_register_allocation(info->work_reg_count);
206 #endif
207 
208    pan_make_preload(info->stage, info->preload, &rsd->preload);
209 
210    if (info->stage == MESA_SHADER_FRAGMENT) {
211       rsd->properties.shader_modifies_coverage =
212          info->fs.writes_coverage || info->fs.can_discard;
213 
214       rsd->properties.allow_forward_pixel_to_be_killed = !info->writes_global;
215 
216 #if PAN_ARCH >= 7
217       rsd->properties.shader_wait_dependency_6 = info->bifrost.wait_6;
218       rsd->properties.shader_wait_dependency_7 = info->bifrost.wait_7;
219 
220       pan_pack_message_preload(&rsd->message_preload_1,
221                                &info->bifrost.messages[0]);
222       pan_pack_message_preload(&rsd->message_preload_2,
223                                &info->bifrost.messages[1]);
224 #endif
225    } else if (info->stage == MESA_SHADER_VERTEX && info->vs.secondary_enable) {
226       rsd->secondary_preload.uniform_count = fau_count;
227 
228       pan_make_preload(info->stage, info->vs.secondary_preload,
229                        &rsd->secondary_preload);
230 
231       rsd->secondary_shader = rsd->shader.shader + info->vs.secondary_offset;
232 
233 #if PAN_ARCH >= 7
234       rsd->properties.secondary_shader_register_allocation =
235          pan_register_allocation(info->vs.secondary_work_reg_count);
236 #endif
237    }
238 }
239 
240 #endif
241 
242 static inline void
pan_shader_prepare_rsd(const struct pan_shader_info * shader_info,mali_ptr shader_ptr,struct MALI_RENDERER_STATE * rsd)243 pan_shader_prepare_rsd(const struct pan_shader_info *shader_info,
244                        mali_ptr shader_ptr, struct MALI_RENDERER_STATE *rsd)
245 {
246 #if PAN_ARCH <= 5
247    shader_ptr |= shader_info->midgard.first_tag;
248 #endif
249 
250    rsd->shader.shader = shader_ptr;
251    rsd->shader.attribute_count = shader_info->attribute_count;
252    rsd->shader.varying_count =
253       shader_info->varyings.input_count + shader_info->varyings.output_count;
254    rsd->shader.texture_count = shader_info->texture_count;
255    rsd->shader.sampler_count = shader_info->sampler_count;
256    rsd->properties.shader_contains_barrier = shader_info->contains_barrier;
257    rsd->properties.uniform_buffer_count = shader_info->ubo_count;
258 
259    if (shader_info->stage == MESA_SHADER_FRAGMENT) {
260       rsd->properties.stencil_from_shader = shader_info->fs.writes_stencil;
261       rsd->properties.depth_source = pan_depth_source(shader_info);
262 
263       /* This also needs to be set if the API forces per-sample
264        * shading, but that'll just got ORed in */
265       rsd->multisample_misc.evaluate_per_sample =
266          shader_info->fs.sample_shading;
267    }
268 
269 #if PAN_ARCH >= 6
270    pan_shader_prepare_bifrost_rsd(shader_info, rsd);
271 #else
272    pan_shader_prepare_midgard_rsd(shader_info, rsd);
273 #endif
274 }
275 #endif /* PAN_ARCH */
276 #endif
277 
278 #endif
279