panfrost: Inherit default values from structs
[mesa.git] / src / panfrost / lib / pan_blit.c
1 /*
2 * Copyright (C) 2020 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 * Authors:
24 * Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
25 */
26
27 #include <math.h>
28 #include <stdio.h>
29 #include "pan_encoder.h"
30 #include "pan_pool.h"
31 #include "pan_scoreboard.h"
32 #include "pan_texture.h"
33 #include "panfrost-quirks.h"
34 #include "../midgard/midgard_compile.h"
35 #include "compiler/nir/nir_builder.h"
36 #include "util/u_math.h"
37
38 /* On Midgard, the native blit infrastructure (via MFBD preloads) is broken or
39 * missing in many cases. We instead use software paths as fallbacks to
40 * implement blits, which are done as TILER jobs. No vertex shader is
41 * necessary since we can supply screen-space coordinates directly.
42 *
43 * This is primarily designed as a fallback for preloads but could be extended
44 * for other clears/blits if needed in the future. */
45
46 static void
47 panfrost_build_blit_shader(panfrost_program *program, unsigned gpu_id, gl_frag_result loc, nir_alu_type T, bool ms)
48 {
49 bool is_colour = loc >= FRAG_RESULT_DATA0;
50
51 nir_shader *shader = nir_shader_create(NULL, MESA_SHADER_FRAGMENT, &midgard_nir_options, NULL);
52 nir_function *fn = nir_function_create(shader, "main");
53 nir_function_impl *impl = nir_function_impl_create(fn);
54
55 nir_variable *c_src = nir_variable_create(shader, nir_var_shader_in, glsl_vector_type(GLSL_TYPE_FLOAT, 2), "coord");
56 nir_variable *c_out = nir_variable_create(shader, nir_var_shader_out, glsl_vector_type(
57 GLSL_TYPE_FLOAT, is_colour ? 4 : 1), "out");
58
59 c_src->data.location = VARYING_SLOT_TEX0;
60 c_out->data.location = loc;
61
62 nir_builder _b;
63 nir_builder *b = &_b;
64 nir_builder_init(b, impl);
65 b->cursor = nir_before_block(nir_start_block(impl));
66
67 nir_ssa_def *coord = nir_load_var(b, c_src);
68
69 nir_tex_instr *tex = nir_tex_instr_create(shader, ms ? 3 : 1);
70
71 tex->dest_type = T;
72
73 if (ms) {
74 tex->src[0].src_type = nir_tex_src_coord;
75 tex->src[0].src = nir_src_for_ssa(nir_f2i32(b, coord));
76 tex->coord_components = 2;
77
78 tex->src[1].src_type = nir_tex_src_ms_index;
79 tex->src[1].src = nir_src_for_ssa(nir_load_sample_id(b));
80
81 tex->src[2].src_type = nir_tex_src_lod;
82 tex->src[2].src = nir_src_for_ssa(nir_imm_int(b, 0));
83 tex->sampler_dim = GLSL_SAMPLER_DIM_MS;
84 tex->op = nir_texop_txf_ms;
85 } else {
86 tex->op = nir_texop_tex;
87
88 tex->src[0].src_type = nir_tex_src_coord;
89 tex->src[0].src = nir_src_for_ssa(coord);
90 tex->coord_components = 2;
91
92 tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
93 }
94
95 nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL);
96 nir_builder_instr_insert(b, &tex->instr);
97
98 if (is_colour)
99 nir_store_var(b, c_out, &tex->dest.ssa, 0xFF);
100 else
101 nir_store_var(b, c_out, nir_channel(b, &tex->dest.ssa, 0), 0xFF);
102
103 midgard_compile_shader_nir(shader, program, false, 0, gpu_id, false, true);
104 ralloc_free(shader);
105 }
106
107 /* Compile and upload all possible blit shaders ahead-of-time to reduce draw
108 * time overhead. There's only ~30 of them at the moment, so this is fine */
109
110 void
111 panfrost_init_blit_shaders(struct panfrost_device *dev)
112 {
113 static const struct {
114 gl_frag_result loc;
115 unsigned types;
116 } shader_descs[] = {
117 { FRAG_RESULT_DEPTH, 1 << PAN_BLIT_FLOAT },
118 { FRAG_RESULT_STENCIL, 1 << PAN_BLIT_UINT },
119 { FRAG_RESULT_DATA0, ~0 },
120 { FRAG_RESULT_DATA1, ~0 },
121 { FRAG_RESULT_DATA2, ~0 },
122 { FRAG_RESULT_DATA3, ~0 },
123 { FRAG_RESULT_DATA4, ~0 },
124 { FRAG_RESULT_DATA5, ~0 },
125 { FRAG_RESULT_DATA6, ~0 },
126 { FRAG_RESULT_DATA7, ~0 }
127 };
128
129 nir_alu_type nir_types[PAN_BLIT_NUM_TYPES] = {
130 nir_type_float,
131 nir_type_uint,
132 nir_type_int
133 };
134
135 /* Total size = # of shaders * bytes per shader. There are
136 * shaders for each RT (so up to DATA7 -- overestimate is
137 * okay) and up to NUM_TYPES variants of each, * 2 for multisampling
138 * variants. These shaders are simple enough that they should be less
139 * than 8 quadwords each (again, overestimate is fine). */
140
141 unsigned offset = 0;
142 unsigned total_size = (FRAG_RESULT_DATA7 * PAN_BLIT_NUM_TYPES)
143 * (8 * 16) * 2;
144
145 dev->blit_shaders.bo = panfrost_bo_create(dev, total_size, PAN_BO_EXECUTE);
146
147 /* Don't bother generating multisampling variants if we don't actually
148 * support multisampling */
149 bool has_ms = !(dev->quirks & MIDGARD_SFBD);
150
151 for (unsigned ms = 0; ms <= has_ms; ++ms) {
152 for (unsigned i = 0; i < ARRAY_SIZE(shader_descs); ++i) {
153 unsigned loc = shader_descs[i].loc;
154
155 for (enum pan_blit_type T = 0; T < PAN_BLIT_NUM_TYPES; ++T) {
156 if (!(shader_descs[i].types & (1 << T)))
157 continue;
158
159 panfrost_program program;
160 panfrost_build_blit_shader(&program, dev->gpu_id, loc,
161 nir_types[T], ms);
162
163 assert(offset + program.compiled.size < total_size);
164 memcpy(dev->blit_shaders.bo->cpu + offset, program.compiled.data, program.compiled.size);
165
166 dev->blit_shaders.loads[loc][T][ms] = (dev->blit_shaders.bo->gpu + offset) | program.first_tag;
167 offset += ALIGN_POT(program.compiled.size, 64);
168 util_dynarray_fini(&program.compiled);
169 }
170 }
171 }
172 }
173
174 /* Add a shader-based load on Midgard (draw-time for GL). Shaders are
175 * precached */
176
177 void
178 panfrost_load_midg(
179 struct pan_pool *pool,
180 struct pan_scoreboard *scoreboard,
181 mali_ptr blend_shader,
182 mali_ptr fbd,
183 mali_ptr coordinates, unsigned vertex_count,
184 struct pan_image *image,
185 unsigned loc)
186 {
187 unsigned width = u_minify(image->width0, image->first_level);
188 unsigned height = u_minify(image->height0, image->first_level);
189
190 struct panfrost_transfer viewport = panfrost_pool_alloc(pool, MALI_VIEWPORT_LENGTH);
191 struct panfrost_transfer sampler = panfrost_pool_alloc(pool, MALI_MIDGARD_SAMPLER_LENGTH);
192 struct panfrost_transfer varying = panfrost_pool_alloc(pool, MALI_ATTRIBUTE_LENGTH);
193 struct panfrost_transfer varying_buffer = panfrost_pool_alloc(pool, MALI_ATTRIBUTE_BUFFER_LENGTH);
194
195 pan_pack(viewport.cpu, VIEWPORT, cfg) {
196 cfg.scissor_maximum_x = width - 1; /* Inclusive */
197 cfg.scissor_maximum_y = height - 1;
198 }
199
200 pan_pack(varying_buffer.cpu, ATTRIBUTE_BUFFER, cfg) {
201 cfg.pointer = coordinates;
202 cfg.stride = 4 * sizeof(float);
203 cfg.size = cfg.stride * vertex_count;
204 }
205
206 pan_pack(varying.cpu, ATTRIBUTE, cfg) {
207 cfg.buffer_index = 0;
208 cfg.format = (MALI_CHANNEL_R << 0) | (MALI_CHANNEL_G << 3) | (MALI_RGBA32F << 12);
209 }
210
211 struct mali_stencil_packed stencil;
212 pan_pack(&stencil, STENCIL, cfg) {
213 cfg.compare_function = MALI_FUNC_ALWAYS;
214 cfg.stencil_fail = MALI_STENCIL_OP_REPLACE;
215 cfg.depth_fail = MALI_STENCIL_OP_REPLACE;
216 cfg.depth_pass = MALI_STENCIL_OP_REPLACE;
217 };
218
219 struct mali_blend_equation_packed eq;
220
221 pan_pack(&eq, BLEND_EQUATION, cfg) {
222 cfg.rgb_mode = 0x122;
223 cfg.alpha_mode = 0x122;
224
225 if (loc < FRAG_RESULT_DATA0)
226 cfg.color_mask = 0x0;
227 }
228
229 union midgard_blend replace = {
230 .equation = eq
231 };
232
233 if (blend_shader)
234 replace.shader = blend_shader;
235
236 /* Determine the sampler type needed. Stencil is always sampled as
237 * UINT. Pure (U)INT is always (U)INT. Everything else is FLOAT. */
238
239 enum pan_blit_type T =
240 (loc == FRAG_RESULT_STENCIL) ? PAN_BLIT_UINT :
241 (util_format_is_pure_uint(image->format)) ? PAN_BLIT_UINT :
242 (util_format_is_pure_sint(image->format)) ? PAN_BLIT_INT :
243 PAN_BLIT_FLOAT;
244
245 bool ms = image->nr_samples > 1;
246
247 struct mali_shader_packed shader;
248
249 pan_pack(&shader, SHADER, cfg) {
250 cfg.shader = pool->dev->blit_shaders.loads[loc][T][ms];
251 cfg.varying_count = 1;
252 cfg.texture_count = 1;
253 cfg.sampler_count = 1;
254
255 assert(cfg.shader);
256 }
257
258 struct mali_shader_meta shader_meta = {
259 .shader = shader,
260 .coverage_mask = ~0,
261 .unknown2_3 = MALI_DEPTH_FUNC(MALI_FUNC_ALWAYS) | 0x10,
262 .unknown2_4 = 0x4e0,
263 .stencil_mask_front = ~0,
264 .stencil_mask_back = ~0,
265 .stencil_front = stencil,
266 .stencil_back = stencil,
267 .blend = {
268 .shader = blend_shader
269 }
270 };
271
272 struct mali_midgard_properties_packed midgard_props;
273
274 pan_pack(&midgard_props, MIDGARD_PROPERTIES, cfg) {
275 cfg.work_register_count = 4;
276 cfg.early_z_enable = (loc >= FRAG_RESULT_DATA0);
277 cfg.stencil_from_shader = (loc == FRAG_RESULT_STENCIL);
278 cfg.depth_source = (loc == FRAG_RESULT_DEPTH) ?
279 MALI_DEPTH_SOURCE_SHADER :
280 MALI_DEPTH_SOURCE_FIXED_FUNCTION;
281 }
282
283 memcpy(&shader_meta.midgard_props, &midgard_props, sizeof(midgard_props));
284
285 if (ms)
286 shader_meta.unknown2_3 |= MALI_HAS_MSAA | MALI_PER_SAMPLE;
287 else
288 shader_meta.unknown2_4 |= MALI_NO_MSAA;
289
290 if (pool->dev->quirks & MIDGARD_SFBD) {
291 shader_meta.unknown2_4 |= (0x10 | MALI_NO_DITHER);
292 shader_meta.blend = replace;
293 }
294
295 if (loc == FRAG_RESULT_DEPTH)
296 shader_meta.unknown2_3 |= MALI_DEPTH_WRITEMASK;
297 else if (loc == FRAG_RESULT_STENCIL)
298 shader_meta.unknown2_4 |= MALI_STENCIL_TEST;
299
300 /* Create the texture descriptor. We partially compute the base address
301 * ourselves to account for layer, such that the texture descriptor
302 * itself is for a 2D texture with array size 1 even for 3D/array
303 * textures, removing the need to separately key the blit shaders for
304 * 2D and 3D variants */
305
306 struct panfrost_transfer texture_t = panfrost_pool_alloc_aligned(
307 pool, MALI_MIDGARD_TEXTURE_LENGTH + sizeof(mali_ptr) * 2 * MAX2(image->nr_samples, 1), 128);
308
309 panfrost_new_texture(texture_t.cpu,
310 image->width0, image->height0,
311 MAX2(image->nr_samples, 1), 1,
312 image->format, MALI_TEXTURE_DIMENSION_2D,
313 image->modifier,
314 image->first_level, image->last_level,
315 0, 0,
316 image->nr_samples,
317 0,
318 (MALI_CHANNEL_R << 0) | (MALI_CHANNEL_G << 3) | (MALI_CHANNEL_B << 6) | (MALI_CHANNEL_A << 9),
319 image->bo->gpu + image->first_layer *
320 panfrost_get_layer_stride(image->slices,
321 image->dim == MALI_TEXTURE_DIMENSION_3D,
322 image->cubemap_stride, image->first_level),
323 image->slices);
324
325 pan_pack(sampler.cpu, MIDGARD_SAMPLER, cfg)
326 cfg.normalized_coordinates = false;
327
328 struct panfrost_transfer shader_meta_t = panfrost_pool_alloc_aligned(
329 pool, sizeof(shader_meta) + 8 * sizeof(struct midgard_blend_rt), 128);
330
331 memcpy(shader_meta_t.cpu, &shader_meta, sizeof(shader_meta));
332
333 for (unsigned i = 0; i < 8; ++i) {
334 void *dest = shader_meta_t.cpu + sizeof(shader_meta) + sizeof(struct midgard_blend_rt) * i;
335
336 if (loc == (FRAG_RESULT_DATA0 + i)) {
337 struct midgard_blend_rt blend_rt = {
338 .blend = replace,
339 };
340
341 unsigned flags = 0;
342 pan_pack(&flags, BLEND_FLAGS, cfg) {
343 cfg.dither_disable = true;
344 cfg.srgb = util_format_is_srgb(image->format);
345 cfg.midgard_blend_shader = blend_shader;
346 }
347 blend_rt.flags.opaque[0] = flags;
348
349 if (blend_shader)
350 blend_rt.blend.shader = blend_shader;
351
352 memcpy(dest, &blend_rt, sizeof(struct midgard_blend_rt));
353 } else {
354 memset(dest, 0x0, sizeof(struct midgard_blend_rt));
355 }
356 }
357
358 struct midgard_payload_vertex_tiler payload = {
359 .prefix = {
360 .draw_mode = MALI_DRAW_MODE_TRIANGLES,
361 .unknown_draw = 0x3000,
362 .index_count = MALI_POSITIVE(vertex_count)
363 },
364 .postfix = {
365 .gl_enables = 0x7,
366 .position_varying = coordinates,
367 .textures = panfrost_pool_upload(pool, &texture_t.gpu, sizeof(texture_t.gpu)),
368 .sampler_descriptor = sampler.gpu,
369 .shader = shader_meta_t.gpu,
370 .varyings = varying_buffer.gpu,
371 .varying_meta = varying.gpu,
372 .viewport = viewport.gpu,
373 .shared_memory = fbd
374 }
375 };
376
377 panfrost_pack_work_groups_compute(&payload.prefix, 1, vertex_count, 1, 1, 1, 1, true);
378 payload.prefix.workgroups_x_shift_3 = 6;
379
380 panfrost_new_job(pool, scoreboard, MALI_JOB_TYPE_TILER, false, 0, &payload, sizeof(payload), true);
381 }