2 * © Copyright 2018 Alyssa Rosenzweig
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:
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
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
29 #include "pan_context.h"
31 #include "panfrost-quirks.h"
33 #include "compiler/nir/nir.h"
34 #include "nir/tgsi_to_nir.h"
35 #include "midgard/midgard_compile.h"
36 #include "bifrost/bifrost_compile.h"
37 #include "util/u_dynarray.h"
39 #include "tgsi/tgsi_dump.h"
42 pan_format_from_nir_base(nir_alu_type base
)
46 return MALI_FORMAT_SINT
;
49 return MALI_FORMAT_UINT
;
51 return MALI_CHANNEL_FLOAT
;
53 unreachable("Invalid base");
58 pan_format_from_nir_size(nir_alu_type base
, unsigned size
)
60 if (base
== nir_type_float
) {
62 case 16: return MALI_FORMAT_SINT
;
63 case 32: return MALI_FORMAT_UNORM
;
65 unreachable("Invalid float size for format");
70 case 8: return MALI_CHANNEL_8
;
71 case 16: return MALI_CHANNEL_16
;
72 case 32: return MALI_CHANNEL_32
;
74 unreachable("Invalid int size for format");
79 static enum mali_format
80 pan_format_from_glsl(const struct glsl_type
*type
)
82 enum glsl_base_type glsl_base
= glsl_get_base_type(glsl_without_array(type
));
83 nir_alu_type t
= nir_get_nir_type_for_glsl_base_type(glsl_base
);
85 unsigned base
= nir_alu_type_get_base_type(t
);
86 unsigned size
= nir_alu_type_get_type_size(t
);
88 return pan_format_from_nir_base(base
) |
89 pan_format_from_nir_size(base
, size
) |
93 static enum bifrost_shader_type
94 bifrost_blend_type_from_nir(nir_alu_type nir_type
)
97 case 0: /* Render target not in use */
99 case nir_type_float16
:
100 return BIFROST_BLEND_F16
;
101 case nir_type_float32
:
102 return BIFROST_BLEND_F32
;
104 return BIFROST_BLEND_I32
;
105 case nir_type_uint32
:
106 return BIFROST_BLEND_U32
;
108 return BIFROST_BLEND_I16
;
109 case nir_type_uint16
:
110 return BIFROST_BLEND_U16
;
112 DBG("Unsupported blend shader type for NIR alu type %d", nir_type
);
119 panfrost_shader_compile(struct panfrost_context
*ctx
,
120 enum pipe_shader_ir ir_type
,
122 gl_shader_stage stage
,
123 struct panfrost_shader_state
*state
,
124 uint64_t *outputs_written
)
126 struct panfrost_device
*dev
= pan_device(ctx
->base
.screen
);
131 if (ir_type
== PIPE_SHADER_IR_NIR
) {
132 s
= nir_shader_clone(NULL
, ir
);
134 assert (ir_type
== PIPE_SHADER_IR_TGSI
);
135 s
= tgsi_to_nir(ir
, ctx
->base
.screen
, false);
138 s
->info
.stage
= stage
;
140 /* Call out to Midgard compiler given the above NIR */
142 panfrost_program program
= {
143 .alpha_ref
= state
->alpha_state
.ref_value
146 if (dev
->quirks
& IS_BIFROST
) {
147 bifrost_compile_shader_nir(s
, &program
, dev
->gpu_id
);
149 midgard_compile_shader_nir(s
, &program
, false, 0, dev
->gpu_id
,
150 pan_debug
& PAN_DBG_PRECOMPILE
);
153 /* Prepare the compiled binary for upload */
154 int size
= program
.compiled
.size
;
155 dst
= program
.compiled
.data
;
157 /* Upload the shader. The lookahead tag is ORed on as a tagged pointer.
158 * I bet someone just thought that would be a cute pun. At least,
159 * that's how I'd do it. */
162 state
->bo
= pan_bo_create(dev
, size
, PAN_BO_EXECUTE
);
163 memcpy(state
->bo
->cpu
, dst
, size
);
166 if (!(dev
->quirks
& IS_BIFROST
)) {
167 /* If size = 0, no shader. Use dummy tag to avoid
168 * INSTR_INVALID_ENC */
169 state
->first_tag
= size
? program
.first_tag
: 1;
172 util_dynarray_fini(&program
.compiled
);
174 state
->sysval_count
= program
.sysval_count
;
175 memcpy(state
->sysval
, program
.sysvals
, sizeof(state
->sysval
[0]) * state
->sysval_count
);
177 bool vertex_id
= s
->info
.system_values_read
& (1 << SYSTEM_VALUE_VERTEX_ID
);
178 bool instance_id
= s
->info
.system_values_read
& (1 << SYSTEM_VALUE_INSTANCE_ID
);
181 case MESA_SHADER_VERTEX
:
182 state
->attribute_count
= util_bitcount64(s
->info
.inputs_read
);
183 state
->varying_count
= util_bitcount64(s
->info
.outputs_written
);
186 state
->attribute_count
= MAX2(state
->attribute_count
, PAN_VERTEX_ID
+ 1);
189 state
->attribute_count
= MAX2(state
->attribute_count
, PAN_INSTANCE_ID
+ 1);
192 case MESA_SHADER_FRAGMENT
:
193 state
->attribute_count
= 0;
194 state
->varying_count
= util_bitcount64(s
->info
.inputs_read
);
195 if (s
->info
.outputs_written
& BITFIELD64_BIT(FRAG_RESULT_DEPTH
))
196 state
->writes_depth
= true;
197 if (s
->info
.outputs_written
& BITFIELD64_BIT(FRAG_RESULT_STENCIL
))
198 state
->writes_stencil
= true;
200 case MESA_SHADER_COMPUTE
:
202 state
->attribute_count
= 0;
203 state
->varying_count
= 0;
204 state
->shared_size
= s
->info
.cs
.shared_size
;
207 unreachable("Unknown shader state");
210 state
->can_discard
= s
->info
.fs
.uses_discard
;
211 state
->writes_point_size
= program
.writes_point_size
;
212 state
->reads_point_coord
= false;
213 state
->helper_invocations
= s
->info
.fs
.needs_helper_invocations
;
214 state
->stack_size
= program
.tls_size
;
217 *outputs_written
= s
->info
.outputs_written
;
219 /* Separate as primary uniform count is truncated. Sysvals are prefix
221 state
->uniform_count
= s
->num_uniforms
+ program
.sysval_count
;
222 state
->uniform_cutoff
= program
.uniform_cutoff
;
223 state
->work_reg_count
= program
.work_register_count
;
225 if (dev
->quirks
& IS_BIFROST
)
226 for (unsigned i
= 0; i
< BIFROST_MAX_RENDER_TARGET_COUNT
; i
++)
227 state
->blend_types
[i
] = bifrost_blend_type_from_nir(program
.blend_types
[i
]);
229 unsigned default_vec1_swizzle
;
230 unsigned default_vec2_swizzle
;
231 unsigned default_vec4_swizzle
;
233 if (dev
->quirks
& HAS_SWIZZLES
) {
234 default_vec1_swizzle
= panfrost_get_default_swizzle(1);
235 default_vec2_swizzle
= panfrost_get_default_swizzle(2);
236 default_vec4_swizzle
= panfrost_get_default_swizzle(4);
238 default_vec1_swizzle
= panfrost_bifrost_swizzle(1);
239 default_vec2_swizzle
= panfrost_bifrost_swizzle(2);
240 default_vec4_swizzle
= panfrost_bifrost_swizzle(4);
243 /* Record the varying mapping for the command stream's bookkeeping */
245 unsigned p_varyings
[32];
246 enum mali_format p_varying_type
[32];
248 struct exec_list
*l_varyings
=
249 stage
== MESA_SHADER_VERTEX
? &s
->outputs
: &s
->inputs
;
251 nir_foreach_variable(var
, l_varyings
) {
252 unsigned loc
= var
->data
.driver_location
;
253 unsigned sz
= glsl_count_attribute_slots(var
->type
, FALSE
);
255 for (int c
= 0; c
< sz
; ++c
) {
256 p_varyings
[loc
+ c
] = var
->data
.location
+ c
;
257 p_varying_type
[loc
+ c
] = pan_format_from_glsl(var
->type
);
261 /* Iterate the varyings and emit the corresponding descriptor */
262 for (unsigned i
= 0; i
< state
->varying_count
; ++i
) {
263 unsigned location
= p_varyings
[i
];
265 /* Default to a vec4 varying */
266 struct mali_attr_meta v
= {
267 .format
= p_varying_type
[i
],
268 .swizzle
= default_vec4_swizzle
,
269 .unknown1
= dev
->quirks
& IS_BIFROST
? 0x0 : 0x2,
272 /* Check for special cases, otherwise assume general varying */
274 if (location
== VARYING_SLOT_POS
) {
275 if (stage
== MESA_SHADER_FRAGMENT
)
276 state
->reads_frag_coord
= true;
278 v
.format
= MALI_VARYING_POS
;
279 } else if (location
== VARYING_SLOT_PSIZ
) {
280 v
.format
= MALI_R16F
;
281 v
.swizzle
= default_vec1_swizzle
;
283 state
->writes_point_size
= true;
284 } else if (location
== VARYING_SLOT_PNTC
) {
285 v
.format
= MALI_RG16F
;
286 v
.swizzle
= default_vec2_swizzle
;
288 state
->reads_point_coord
= true;
289 } else if (location
== VARYING_SLOT_FACE
) {
290 v
.format
= MALI_R32I
;
291 v
.swizzle
= default_vec1_swizzle
;
293 state
->reads_face
= true;
296 state
->varyings
[i
] = v
;
297 state
->varyings_loc
[i
] = location
;