• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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