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