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/util/pan_ir.h"
30
31 #include "pan_device.h"
32 #include "genxml/gen_macros.h"
33
34 struct panfrost_device;
35
36 #ifdef PAN_ARCH
37 const nir_shader_compiler_options *
38 GENX(pan_shader_get_compiler_options)(void);
39
40 void
41 GENX(pan_shader_compile)(nir_shader *nir,
42 struct panfrost_compile_inputs *inputs,
43 struct util_dynarray *binary,
44 struct pan_shader_info *info);
45
46 #if PAN_ARCH >= 9
47 static inline enum mali_shader_stage
pan_shader_stage(const struct pan_shader_info * info)48 pan_shader_stage(const struct pan_shader_info *info)
49 {
50 switch (info->stage) {
51 case MESA_SHADER_VERTEX:
52 return MALI_SHADER_STAGE_VERTEX;
53 case MESA_SHADER_FRAGMENT:
54 return MALI_SHADER_STAGE_FRAGMENT;
55 default:
56 return MALI_SHADER_STAGE_COMPUTE;
57 }
58 }
59 #endif
60
61 #if PAN_ARCH >= 7
62 static inline enum mali_shader_register_allocation
pan_register_allocation(unsigned work_reg_count)63 pan_register_allocation(unsigned work_reg_count)
64 {
65 return (work_reg_count <= 32) ?
66 MALI_SHADER_REGISTER_ALLOCATION_32_PER_THREAD :
67 MALI_SHADER_REGISTER_ALLOCATION_64_PER_THREAD;
68 }
69 #endif
70
71 static inline enum mali_depth_source
pan_depth_source(const struct pan_shader_info * info)72 pan_depth_source(const struct pan_shader_info *info)
73 {
74 return info->fs.writes_depth ? MALI_DEPTH_SOURCE_SHADER :
75 MALI_DEPTH_SOURCE_FIXED_FUNCTION;
76 }
77
78 #if PAN_ARCH <= 7
79 #if PAN_ARCH <= 5
80 static inline void
pan_shader_prepare_midgard_rsd(const struct pan_shader_info * info,struct MALI_RENDERER_STATE * rsd)81 pan_shader_prepare_midgard_rsd(const struct pan_shader_info *info,
82 struct MALI_RENDERER_STATE *rsd)
83 {
84 assert((info->push.count & 3) == 0);
85
86 rsd->properties.uniform_count = info->push.count / 4;
87 rsd->properties.shader_has_side_effects = info->writes_global;
88 rsd->properties.fp_mode = MALI_FP_MODE_GL_INF_NAN_ALLOWED;
89
90 /* For fragment shaders, work register count, early-z, reads at draw-time */
91
92 if (info->stage != MESA_SHADER_FRAGMENT) {
93 rsd->properties.work_register_count = info->work_reg_count;
94 } else {
95 rsd->properties.shader_reads_tilebuffer =
96 info->fs.outputs_read;
97
98 /* However, forcing early-z in the shader overrides draw-time */
99 rsd->properties.force_early_z =
100 info->fs.early_fragment_tests;
101 }
102 }
103
104 #else
105
106 #define pan_preloads(reg) (preload & BITFIELD64_BIT(reg))
107
108 static void
pan_make_preload(gl_shader_stage stage,uint64_t preload,struct MALI_PRELOAD * out)109 pan_make_preload(gl_shader_stage stage,
110 uint64_t preload,
111 struct MALI_PRELOAD *out)
112 {
113 switch (stage) {
114 case MESA_SHADER_VERTEX:
115 out->vertex.position_result_address_lo = pan_preloads(58);
116 out->vertex.position_result_address_hi = pan_preloads(59);
117 out->vertex.vertex_id = pan_preloads(61);
118 out->vertex.instance_id = pan_preloads(62);
119 break;
120
121 case MESA_SHADER_FRAGMENT:
122 out->fragment.primitive_id = pan_preloads(57);
123 out->fragment.primitive_flags = pan_preloads(58);
124 out->fragment.fragment_position = pan_preloads(59);
125 out->fragment.sample_mask_id = pan_preloads(61);
126 out->fragment.coverage = true;
127 break;
128
129 default:
130 out->compute.local_invocation_xy = pan_preloads(55);
131 out->compute.local_invocation_z = pan_preloads(56);
132 out->compute.work_group_x = pan_preloads(57);
133 out->compute.work_group_y = pan_preloads(58);
134 out->compute.work_group_z = pan_preloads(59);
135 out->compute.global_invocation_x = pan_preloads(60);
136 out->compute.global_invocation_y = pan_preloads(61);
137 out->compute.global_invocation_z = pan_preloads(62);
138 break;
139 }
140 }
141
142 #if PAN_ARCH == 7
143 static inline void
pan_pack_message_preload(struct MALI_MESSAGE_PRELOAD * cfg,const struct bifrost_message_preload * msg)144 pan_pack_message_preload(struct MALI_MESSAGE_PRELOAD *cfg,
145 const struct bifrost_message_preload *msg)
146 {
147 enum mali_message_preload_register_format regfmt = msg->fp16 ?
148 MALI_MESSAGE_PRELOAD_REGISTER_FORMAT_F16 :
149 MALI_MESSAGE_PRELOAD_REGISTER_FORMAT_F32;
150
151 if (msg->enabled && msg->texture) {
152 cfg->type = MALI_MESSAGE_TYPE_VAR_TEX;
153 cfg->var_tex.varying_index = msg->varying_index;
154 cfg->var_tex.texture_index = msg->texture_index;
155 cfg->var_tex.register_format = regfmt;
156 cfg->var_tex.skip = msg->skip;
157 cfg->var_tex.zero_lod = msg->zero_lod;
158 } else if (msg->enabled) {
159 cfg->type = MALI_MESSAGE_TYPE_LD_VAR;
160 cfg->ld_var.varying_index = msg->varying_index;
161 cfg->ld_var.register_format = regfmt;
162 cfg->ld_var.num_components = msg->num_components;
163 } else {
164 cfg->type = MALI_MESSAGE_TYPE_DISABLED;
165 }
166 }
167 #endif
168
169 static inline void
pan_shader_prepare_bifrost_rsd(const struct pan_shader_info * info,struct MALI_RENDERER_STATE * rsd)170 pan_shader_prepare_bifrost_rsd(const struct pan_shader_info *info,
171 struct MALI_RENDERER_STATE *rsd)
172 {
173 unsigned fau_count = DIV_ROUND_UP(info->push.count, 2);
174 rsd->preload.uniform_count = fau_count;
175
176 #if PAN_ARCH >= 7
177 rsd->properties.shader_register_allocation =
178 pan_register_allocation(info->work_reg_count);
179 #endif
180
181 pan_make_preload(info->stage, info->preload, &rsd->preload);
182
183 if (info->stage == MESA_SHADER_FRAGMENT) {
184 rsd->properties.shader_modifies_coverage =
185 info->fs.writes_coverage || info->fs.can_discard;
186
187 rsd->properties.allow_forward_pixel_to_be_killed =
188 !info->writes_global;
189
190 #if PAN_ARCH >= 7
191 rsd->properties.shader_wait_dependency_6 = info->bifrost.wait_6;
192 rsd->properties.shader_wait_dependency_7 = info->bifrost.wait_7;
193
194 pan_pack_message_preload(&rsd->message_preload_1, &info->bifrost.messages[0]);
195 pan_pack_message_preload(&rsd->message_preload_2, &info->bifrost.messages[1]);
196 #endif
197 } else if (info->stage == MESA_SHADER_VERTEX && info->vs.secondary_enable) {
198 rsd->secondary_preload.uniform_count = fau_count;
199
200 pan_make_preload(info->stage, info->vs.secondary_preload,
201 &rsd->secondary_preload);
202
203 rsd->secondary_shader = rsd->shader.shader +
204 info->vs.secondary_offset;
205
206 #if PAN_ARCH >= 7
207 rsd->properties.secondary_shader_register_allocation =
208 pan_register_allocation(info->vs.secondary_work_reg_count);
209 #endif
210 }
211 }
212
213 #endif
214
215 static inline void
pan_shader_prepare_rsd(const struct pan_shader_info * shader_info,mali_ptr shader_ptr,struct MALI_RENDERER_STATE * rsd)216 pan_shader_prepare_rsd(const struct pan_shader_info *shader_info,
217 mali_ptr shader_ptr,
218 struct MALI_RENDERER_STATE *rsd)
219 {
220 #if PAN_ARCH <= 5
221 shader_ptr |= shader_info->midgard.first_tag;
222 #endif
223
224 rsd->shader.shader = shader_ptr;
225 rsd->shader.attribute_count = shader_info->attribute_count;
226 rsd->shader.varying_count = shader_info->varyings.input_count +
227 shader_info->varyings.output_count;
228 rsd->shader.texture_count = shader_info->texture_count;
229 rsd->shader.sampler_count = shader_info->sampler_count;
230 rsd->properties.shader_contains_barrier = shader_info->contains_barrier;
231 rsd->properties.uniform_buffer_count = shader_info->ubo_count;
232
233 if (shader_info->stage == MESA_SHADER_FRAGMENT) {
234 rsd->properties.stencil_from_shader =
235 shader_info->fs.writes_stencil;
236 rsd->properties.depth_source = pan_depth_source(shader_info);
237
238 /* This also needs to be set if the API forces per-sample
239 * shading, but that'll just got ORed in */
240 rsd->multisample_misc.evaluate_per_sample =
241 shader_info->fs.sample_shading;
242 }
243
244 #if PAN_ARCH >= 6
245 pan_shader_prepare_bifrost_rsd(shader_info, rsd);
246 #else
247 pan_shader_prepare_midgard_rsd(shader_info, rsd);
248 #endif
249 }
250 #endif /* PAN_ARCH */
251 #endif
252
253 #endif
254