1 /*
2 * Copyright © 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
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "nir/nir_builder.h"
25 #include "pan_blitter.h"
26 #include "pan_encoder.h"
27 #include "pan_shader.h"
28
29 #include "panvk_private.h"
30 #include "panvk_vX_meta.h"
31
32 #include "vk_format.h"
33
34 static mali_ptr
panvk_meta_clear_color_attachment_shader(struct panfrost_device * pdev,struct pan_pool * bin_pool,unsigned rt,enum glsl_base_type base_type,struct pan_shader_info * shader_info)35 panvk_meta_clear_color_attachment_shader(struct panfrost_device *pdev,
36 struct pan_pool *bin_pool,
37 unsigned rt,
38 enum glsl_base_type base_type,
39 struct pan_shader_info *shader_info)
40 {
41 nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
42 GENX(pan_shader_get_compiler_options)(),
43 "panvk_meta_clear_rt%d_attachment(base_type=%d)",
44 rt, base_type);
45
46 b.shader->info.internal = true;
47 b.shader->info.num_ubos = 1;
48
49 const struct glsl_type *out_type = glsl_vector_type(base_type, 4);
50 nir_variable *out =
51 nir_variable_create(b.shader, nir_var_shader_out, out_type, "out");
52 out->data.location = FRAG_RESULT_DATA0 + rt;
53
54 nir_ssa_def *clear_values = nir_load_ubo(&b, 4, 32, nir_imm_int(&b, 0),
55 nir_imm_int(&b, 0),
56 .align_mul = 4,
57 .align_offset = 0,
58 .range_base = 0,
59 .range = ~0);
60 nir_store_var(&b, out, clear_values, 0xff);
61
62 struct panfrost_compile_inputs inputs = {
63 .gpu_id = pdev->gpu_id,
64 .is_blit = true,
65 };
66
67 struct util_dynarray binary;
68
69 util_dynarray_init(&binary, NULL);
70 GENX(pan_shader_compile)(b.shader, &inputs, &binary, shader_info);
71
72 /* Make sure UBO words have been upgraded to push constants */
73 assert(shader_info->ubo_count == 1);
74 assert(shader_info->push.count == 4);
75
76 mali_ptr shader =
77 pan_pool_upload_aligned(bin_pool, binary.data, binary.size,
78 PAN_ARCH >= 6 ? 128 : 64);
79
80 util_dynarray_fini(&binary);
81 ralloc_free(b.shader);
82
83 return shader;
84 }
85
86 static mali_ptr
panvk_meta_clear_zs_attachment_shader(struct panfrost_device * pdev,struct pan_pool * bin_pool,bool clear_z,bool clear_s,enum glsl_base_type base_type,struct pan_shader_info * shader_info)87 panvk_meta_clear_zs_attachment_shader(struct panfrost_device *pdev,
88 struct pan_pool *bin_pool,
89 bool clear_z, bool clear_s,
90 enum glsl_base_type base_type,
91 struct pan_shader_info *shader_info)
92 {
93 nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
94 GENX(pan_shader_get_compiler_options)(),
95 "panvk_meta_clear_%s%s_attachment()",
96 clear_z ? "z" : "", clear_s ? "s" : "");
97
98 b.shader->info.internal = true;
99 b.shader->info.num_ubos = 1;
100
101 unsigned drv_loc = 0;
102 nir_variable *z_out =
103 clear_z ?
104 nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(), "depth") :
105 NULL;
106 nir_variable *s_out =
107 clear_s ?
108 nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(), "stencil") :
109 NULL;
110
111 nir_ssa_def *clear_values = nir_load_ubo(&b, 2, 32, nir_imm_int(&b, 0),
112 nir_imm_int(&b, 0),
113 .align_mul = 4,
114 .align_offset = 0,
115 .range_base = 0,
116 .range = ~0);
117
118 if (z_out) {
119 z_out->data.location = FRAG_RESULT_DEPTH;
120 z_out->data.driver_location = drv_loc++;
121 nir_store_var(&b, z_out, nir_channel(&b, clear_values, 0), 1);
122 }
123
124 if (s_out) {
125 s_out->data.location = FRAG_RESULT_STENCIL;
126 s_out->data.driver_location = drv_loc++;
127 nir_store_var(&b, s_out, nir_channel(&b, clear_values, 1), 1);
128 }
129
130 struct panfrost_compile_inputs inputs = {
131 .gpu_id = pdev->gpu_id,
132 .is_blit = true,
133 };
134
135 struct util_dynarray binary;
136
137 util_dynarray_init(&binary, NULL);
138 GENX(pan_shader_compile)(b.shader, &inputs, &binary, shader_info);
139
140 /* Make sure UBO words have been upgraded to push constants */
141 assert(shader_info->ubo_count == 1);
142 assert(shader_info->push.count == 2);
143
144 mali_ptr shader =
145 pan_pool_upload_aligned(bin_pool, binary.data, binary.size,
146 PAN_ARCH >= 6 ? 128 : 64);
147
148 util_dynarray_fini(&binary);
149 ralloc_free(b.shader);
150
151 return shader;
152 }
153
154 static mali_ptr
panvk_meta_clear_attachments_emit_rsd(struct panfrost_device * pdev,struct pan_pool * desc_pool,enum pipe_format format,unsigned rt,bool z,bool s,struct pan_shader_info * shader_info,mali_ptr shader)155 panvk_meta_clear_attachments_emit_rsd(struct panfrost_device *pdev,
156 struct pan_pool *desc_pool,
157 enum pipe_format format,
158 unsigned rt, bool z, bool s,
159 struct pan_shader_info *shader_info,
160 mali_ptr shader)
161 {
162 struct panfrost_ptr rsd_ptr =
163 pan_pool_alloc_desc_aggregate(desc_pool,
164 PAN_DESC(RENDERER_STATE),
165 PAN_DESC_ARRAY(rt + 1, BLEND));
166 bool zs = z | s;
167
168 pan_pack(rsd_ptr.cpu, RENDERER_STATE, cfg) {
169 pan_shader_prepare_rsd(shader_info, shader, &cfg);
170 cfg.properties.depth_source =
171 z ?
172 MALI_DEPTH_SOURCE_SHADER :
173 MALI_DEPTH_SOURCE_FIXED_FUNCTION;
174 cfg.multisample_misc.depth_write_mask = z;
175 cfg.multisample_misc.sample_mask = UINT16_MAX;
176 cfg.multisample_misc.depth_function = MALI_FUNC_ALWAYS;
177 cfg.stencil_mask_misc.stencil_enable = s;
178 cfg.properties.stencil_from_shader = s;
179 cfg.stencil_mask_misc.stencil_mask_front = 0xFF;
180 cfg.stencil_mask_misc.stencil_mask_back = 0xFF;
181 cfg.stencil_front.compare_function = MALI_FUNC_ALWAYS;
182 cfg.stencil_front.stencil_fail = MALI_STENCIL_OP_REPLACE;
183 cfg.stencil_front.depth_fail = MALI_STENCIL_OP_REPLACE;
184 cfg.stencil_front.depth_pass = MALI_STENCIL_OP_REPLACE;
185 cfg.stencil_front.mask = 0xFF;
186 cfg.stencil_back = cfg.stencil_front;
187
188 #if PAN_ARCH >= 6
189 cfg.properties.allow_forward_pixel_to_be_killed = PAN_ARCH >= 7 || !zs;
190 cfg.properties.allow_forward_pixel_to_kill = !zs;
191 if (zs) {
192 cfg.properties.zs_update_operation =
193 MALI_PIXEL_KILL_FORCE_LATE;
194 cfg.properties.pixel_kill_operation =
195 MALI_PIXEL_KILL_FORCE_LATE;
196 } else {
197 cfg.properties.zs_update_operation =
198 MALI_PIXEL_KILL_STRONG_EARLY;
199 cfg.properties.pixel_kill_operation =
200 MALI_PIXEL_KILL_FORCE_EARLY;
201 }
202 #else
203 cfg.properties.shader_reads_tilebuffer = false;
204 cfg.properties.work_register_count = shader_info->work_reg_count;
205 cfg.properties.force_early_z = !zs;
206 cfg.stencil_mask_misc.alpha_test_compare_function = MALI_FUNC_ALWAYS;
207 #endif
208 }
209
210 void *bd = rsd_ptr.cpu + pan_size(RENDERER_STATE);
211
212 /* Disable all RTs except the one we're interested in. */
213 for (unsigned i = 0; i < rt; i++) {
214 pan_pack(bd, BLEND, cfg) {
215 cfg.enable = false;
216 #if PAN_ARCH >= 6
217 cfg.internal.mode = MALI_BLEND_MODE_OFF;
218 #endif
219 }
220
221 bd += pan_size(BLEND);
222 }
223
224 if (zs) {
225 /* We write the depth/stencil, disable blending on RT0. */
226 pan_pack(bd, BLEND, cfg) {
227 cfg.enable = false;
228 #if PAN_ARCH >= 6
229 cfg.internal.mode = MALI_BLEND_MODE_OFF;
230 #endif
231 }
232 } else {
233 pan_pack(bd, BLEND, cfg) {
234 cfg.round_to_fb_precision = true;
235 cfg.load_destination = false;
236 cfg.equation.rgb.a = MALI_BLEND_OPERAND_A_SRC;
237 cfg.equation.rgb.b = MALI_BLEND_OPERAND_B_SRC;
238 cfg.equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO;
239 cfg.equation.alpha.a = MALI_BLEND_OPERAND_A_SRC;
240 cfg.equation.alpha.b = MALI_BLEND_OPERAND_B_SRC;
241 cfg.equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO;
242 #if PAN_ARCH >= 6
243 cfg.internal.mode = MALI_BLEND_MODE_OPAQUE;
244 cfg.equation.color_mask = 0xf;
245 cfg.internal.fixed_function.num_comps = 4;
246 cfg.internal.fixed_function.conversion.memory_format =
247 panfrost_format_to_bifrost_blend(pdev, format, false);
248 cfg.internal.fixed_function.conversion.register_format =
249 shader_info->bifrost.blend[rt].format;
250 #else
251 cfg.equation.color_mask =
252 (1 << util_format_get_nr_components(format)) - 1;
253 #endif
254 }
255 }
256
257 return rsd_ptr.gpu;
258 }
259
260 static mali_ptr
panvk_meta_clear_attachment_emit_push_constants(struct panfrost_device * pdev,const struct panfrost_ubo_push * pushmap,struct pan_pool * pool,const VkClearValue * clear_value)261 panvk_meta_clear_attachment_emit_push_constants(struct panfrost_device *pdev,
262 const struct panfrost_ubo_push *pushmap,
263 struct pan_pool *pool,
264 const VkClearValue *clear_value)
265 {
266 assert(pushmap->count <= (sizeof(*clear_value) / 4));
267
268 uint32_t *in = (uint32_t *)clear_value;
269 uint32_t pushvals[sizeof(*clear_value) / 4];
270
271 for (unsigned i = 0; i < pushmap->count; i++) {
272 assert(i < ARRAY_SIZE(pushvals));
273 assert(pushmap->words[i].ubo == 0);
274 assert(pushmap->words[i].offset < sizeof(*clear_value));
275 pushvals[i] = in[pushmap->words[i].offset / 4];
276 }
277
278 return pan_pool_upload_aligned(pool, pushvals, sizeof(pushvals), 16);
279 }
280
281 static mali_ptr
panvk_meta_clear_attachment_emit_ubo(struct panfrost_device * pdev,const struct panfrost_ubo_push * pushmap,struct pan_pool * pool,const VkClearValue * clear_value)282 panvk_meta_clear_attachment_emit_ubo(struct panfrost_device *pdev,
283 const struct panfrost_ubo_push *pushmap,
284 struct pan_pool *pool,
285 const VkClearValue *clear_value)
286 {
287 struct panfrost_ptr ubo = pan_pool_alloc_desc(pool, UNIFORM_BUFFER);
288
289 pan_pack(ubo.cpu, UNIFORM_BUFFER, cfg) {
290 cfg.entries = DIV_ROUND_UP(sizeof(*clear_value), 16);
291 cfg.pointer = pan_pool_upload_aligned(pool, clear_value, sizeof(*clear_value), 16);
292 }
293
294 return ubo.gpu;
295 }
296
297 static void
panvk_meta_clear_attachment_emit_dcd(struct pan_pool * pool,mali_ptr coords,mali_ptr ubo,mali_ptr push_constants,mali_ptr vpd,mali_ptr tsd,mali_ptr rsd,void * out)298 panvk_meta_clear_attachment_emit_dcd(struct pan_pool *pool,
299 mali_ptr coords,
300 mali_ptr ubo, mali_ptr push_constants,
301 mali_ptr vpd, mali_ptr tsd, mali_ptr rsd,
302 void *out)
303 {
304 pan_pack(out, DRAW, cfg) {
305 cfg.four_components_per_vertex = true;
306 cfg.draw_descriptor_is_64b = true;
307 cfg.thread_storage = tsd;
308 cfg.state = rsd;
309 cfg.uniform_buffers = ubo;
310 cfg.push_uniforms = push_constants;
311 cfg.position = coords;
312 cfg.viewport = vpd;
313 }
314 }
315
316 static struct panfrost_ptr
panvk_meta_clear_attachment_emit_tiler_job(struct pan_pool * desc_pool,struct pan_scoreboard * scoreboard,mali_ptr coords,mali_ptr ubo,mali_ptr push_constants,mali_ptr vpd,mali_ptr rsd,mali_ptr tsd,mali_ptr tiler)317 panvk_meta_clear_attachment_emit_tiler_job(struct pan_pool *desc_pool,
318 struct pan_scoreboard *scoreboard,
319 mali_ptr coords,
320 mali_ptr ubo, mali_ptr push_constants,
321 mali_ptr vpd, mali_ptr rsd,
322 mali_ptr tsd, mali_ptr tiler)
323 {
324 struct panfrost_ptr job =
325 pan_pool_alloc_desc(desc_pool, TILER_JOB);
326
327 panvk_meta_clear_attachment_emit_dcd(desc_pool,
328 coords,
329 ubo, push_constants,
330 vpd, tsd, rsd,
331 pan_section_ptr(job.cpu, TILER_JOB, DRAW));
332
333 pan_section_pack(job.cpu, TILER_JOB, PRIMITIVE, cfg) {
334 cfg.draw_mode = MALI_DRAW_MODE_TRIANGLE_STRIP;
335 cfg.index_count = 4;
336 cfg.job_task_split = 6;
337 }
338
339 pan_section_pack(job.cpu, TILER_JOB, PRIMITIVE_SIZE, cfg) {
340 cfg.constant = 1.0f;
341 }
342
343 void *invoc = pan_section_ptr(job.cpu,
344 TILER_JOB,
345 INVOCATION);
346 panfrost_pack_work_groups_compute(invoc, 1, 4,
347 1, 1, 1, 1, true, false);
348
349 #if PAN_ARCH >= 6
350 pan_section_pack(job.cpu, TILER_JOB, PADDING, cfg);
351 pan_section_pack(job.cpu, TILER_JOB, TILER, cfg) {
352 cfg.address = tiler;
353 }
354 #endif
355
356 panfrost_add_job(desc_pool, scoreboard, MALI_JOB_TYPE_TILER,
357 false, false, 0, 0, &job, false);
358 return job;
359 }
360
361 static enum glsl_base_type
panvk_meta_get_format_type(enum pipe_format format)362 panvk_meta_get_format_type(enum pipe_format format)
363 {
364 const struct util_format_description *desc = util_format_description(format);
365 int i;
366
367 i = util_format_get_first_non_void_channel(format);
368 assert(i >= 0);
369
370 if (desc->channel[i].normalized)
371 return GLSL_TYPE_FLOAT;
372
373 switch(desc->channel[i].type) {
374
375 case UTIL_FORMAT_TYPE_UNSIGNED:
376 return GLSL_TYPE_UINT;
377
378 case UTIL_FORMAT_TYPE_SIGNED:
379 return GLSL_TYPE_INT;
380
381 case UTIL_FORMAT_TYPE_FLOAT:
382 return GLSL_TYPE_FLOAT;
383
384 default:
385 unreachable("Unhandled format");
386 return GLSL_TYPE_FLOAT;
387 }
388 }
389
390 static void
panvk_meta_clear_attachment(struct panvk_cmd_buffer * cmdbuf,unsigned attachment,unsigned rt,VkImageAspectFlags mask,const VkClearValue * clear_value,const VkClearRect * clear_rect)391 panvk_meta_clear_attachment(struct panvk_cmd_buffer *cmdbuf,
392 unsigned attachment, unsigned rt,
393 VkImageAspectFlags mask,
394 const VkClearValue *clear_value,
395 const VkClearRect *clear_rect)
396 {
397 struct panvk_physical_device *dev = cmdbuf->device->physical_device;
398 struct panfrost_device *pdev = &dev->pdev;
399 struct panvk_meta *meta = &cmdbuf->device->physical_device->meta;
400 struct panvk_batch *batch = cmdbuf->state.batch;
401 const struct panvk_render_pass *pass = cmdbuf->state.pass;
402 const struct panvk_render_pass_attachment *att = &pass->attachments[attachment];
403 unsigned minx = MAX2(clear_rect->rect.offset.x, 0);
404 unsigned miny = MAX2(clear_rect->rect.offset.y, 0);
405 unsigned maxx = MAX2(clear_rect->rect.offset.x + clear_rect->rect.extent.width - 1, 0);
406 unsigned maxy = MAX2(clear_rect->rect.offset.y + clear_rect->rect.extent.height - 1, 0);
407
408 panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf);
409 panvk_per_arch(cmd_alloc_tls_desc)(cmdbuf, true);
410 panvk_per_arch(cmd_prepare_tiler_context)(cmdbuf);
411
412 mali_ptr vpd =
413 panvk_per_arch(meta_emit_viewport)(&cmdbuf->desc_pool.base,
414 minx, miny, maxx, maxy);
415
416 float rect[] = {
417 minx, miny, 0.0, 1.0,
418 maxx + 1, miny, 0.0, 1.0,
419 minx, maxy + 1, 0.0, 1.0,
420 maxx + 1, maxy + 1, 0.0, 1.0,
421 };
422 mali_ptr coordinates = pan_pool_upload_aligned(&cmdbuf->desc_pool.base,
423 rect, sizeof(rect), 64);
424
425 enum glsl_base_type base_type = panvk_meta_get_format_type(att->format);
426 struct pan_shader_info *shader_info;
427 bool clear_z = false, clear_s = false;
428 mali_ptr shader;
429
430 switch (mask) {
431 case VK_IMAGE_ASPECT_COLOR_BIT:
432 shader = meta->clear_attachment.color[rt][base_type].shader;
433 shader_info = &meta->clear_attachment.color[rt][base_type].shader_info;
434 break;
435 case VK_IMAGE_ASPECT_DEPTH_BIT:
436 shader = meta->clear_attachment.z.shader;
437 shader_info = &meta->clear_attachment.z.shader_info;
438 clear_z = true;
439 break;
440 case VK_IMAGE_ASPECT_STENCIL_BIT:
441 shader = meta->clear_attachment.s.shader;
442 shader_info = &meta->clear_attachment.s.shader_info;
443 clear_s = true;
444 break;
445 case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
446 shader = meta->clear_attachment.zs.shader;
447 shader_info = &meta->clear_attachment.zs.shader_info;
448 clear_s = clear_z = true;
449 break;
450 default:
451 unreachable("Invalid aspect mask\n");
452 }
453
454 mali_ptr rsd =
455 panvk_meta_clear_attachments_emit_rsd(pdev,
456 &cmdbuf->desc_pool.base,
457 att->format, rt, clear_z, clear_s,
458 shader_info,
459 shader);
460
461 mali_ptr pushconsts =
462 panvk_meta_clear_attachment_emit_push_constants(pdev, &shader_info->push,
463 &cmdbuf->desc_pool.base,
464 clear_value);
465 mali_ptr ubo =
466 panvk_meta_clear_attachment_emit_ubo(pdev, &shader_info->push,
467 &cmdbuf->desc_pool.base,
468 clear_value);
469
470 mali_ptr tsd = PAN_ARCH >= 6 ? batch->tls.gpu : batch->fb.desc.gpu;
471 mali_ptr tiler = PAN_ARCH >= 6 ? batch->tiler.descs.gpu : 0;
472
473 struct panfrost_ptr job;
474
475 job = panvk_meta_clear_attachment_emit_tiler_job(&cmdbuf->desc_pool.base,
476 &batch->scoreboard,
477 coordinates,
478 ubo, pushconsts,
479 vpd, rsd, tsd, tiler);
480
481 util_dynarray_append(&batch->jobs, void *, job.cpu);
482 }
483
484 static void
panvk_meta_clear_color_img(struct panvk_cmd_buffer * cmdbuf,struct panvk_image * img,const VkClearColorValue * color,const VkImageSubresourceRange * range)485 panvk_meta_clear_color_img(struct panvk_cmd_buffer *cmdbuf,
486 struct panvk_image *img,
487 const VkClearColorValue *color,
488 const VkImageSubresourceRange *range)
489 {
490 struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info;
491 struct pan_image_view view = {
492 .format = img->pimage.layout.format,
493 .dim = MALI_TEXTURE_DIMENSION_2D,
494 .image = &img->pimage,
495 .nr_samples = img->pimage.layout.nr_samples,
496 .swizzle = { PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W },
497 };
498
499 cmdbuf->state.fb.crc_valid[0] = false;
500 *fbinfo = (struct pan_fb_info){
501 .nr_samples = img->pimage.layout.nr_samples,
502 .rt_count = 1,
503 .rts[0].view = &view,
504 .rts[0].clear = true,
505 .rts[0].crc_valid = &cmdbuf->state.fb.crc_valid[0],
506 };
507
508 uint32_t clearval[4];
509 pan_pack_color(clearval, (union pipe_color_union *)color,
510 img->pimage.layout.format, false);
511 memcpy(fbinfo->rts[0].clear_value, clearval, sizeof(fbinfo->rts[0].clear_value));
512
513 for (unsigned level = range->baseMipLevel;
514 level < range->baseMipLevel + range->levelCount; level++) {
515 view.first_level = view.last_level = level;
516 fbinfo->width = u_minify(img->pimage.layout.width, level);
517 fbinfo->height = u_minify(img->pimage.layout.height, level);
518 fbinfo->extent.maxx = fbinfo->width - 1;
519 fbinfo->extent.maxy = fbinfo->height - 1;
520
521 for (unsigned layer = range->baseArrayLayer;
522 layer < range->baseArrayLayer + range->layerCount; layer++) {
523 view.first_layer = view.last_layer = layer;
524 panvk_cmd_open_batch(cmdbuf);
525 panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf);
526 panvk_per_arch(cmd_close_batch)(cmdbuf);
527 }
528 }
529 }
530
531 void
panvk_per_arch(CmdClearColorImage)532 panvk_per_arch(CmdClearColorImage)(VkCommandBuffer commandBuffer,
533 VkImage image,
534 VkImageLayout imageLayout,
535 const VkClearColorValue *pColor,
536 uint32_t rangeCount,
537 const VkImageSubresourceRange *pRanges)
538 {
539 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
540 VK_FROM_HANDLE(panvk_image, img, image);
541
542 panvk_per_arch(cmd_close_batch)(cmdbuf);
543
544 for (unsigned i = 0; i < rangeCount; i++)
545 panvk_meta_clear_color_img(cmdbuf, img, pColor, &pRanges[i]);
546 }
547
548 static void
panvk_meta_clear_zs_img(struct panvk_cmd_buffer * cmdbuf,struct panvk_image * img,const VkClearDepthStencilValue * value,const VkImageSubresourceRange * range)549 panvk_meta_clear_zs_img(struct panvk_cmd_buffer *cmdbuf,
550 struct panvk_image *img,
551 const VkClearDepthStencilValue *value,
552 const VkImageSubresourceRange *range)
553 {
554 struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info;
555 struct pan_image_view view = {
556 .format = img->pimage.layout.format,
557 .dim = MALI_TEXTURE_DIMENSION_2D,
558 .image = &img->pimage,
559 .nr_samples = img->pimage.layout.nr_samples,
560 .swizzle = { PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W },
561 };
562
563 cmdbuf->state.fb.crc_valid[0] = false;
564 *fbinfo = (struct pan_fb_info){
565 .nr_samples = img->pimage.layout.nr_samples,
566 .rt_count = 1,
567 };
568
569 const struct util_format_description *fdesc =
570 util_format_description(view.format);
571
572 if (util_format_has_depth(fdesc)) {
573 fbinfo->zs.view.zs = &view;
574 fbinfo->zs.clear.z = range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT;
575 if (util_format_has_stencil(fdesc)) {
576 fbinfo->zs.clear.s = range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT;
577 fbinfo->zs.preload.z = !fbinfo->zs.clear.z && fbinfo->zs.clear.s;
578 fbinfo->zs.preload.s = !fbinfo->zs.clear.s && fbinfo->zs.clear.z;
579 }
580 } else {
581 fbinfo->zs.view.s = &view;
582 fbinfo->zs.clear.s = range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT;
583 }
584
585 if (fbinfo->zs.clear.z)
586 fbinfo->zs.clear_value.depth = value->depth;
587
588 if (fbinfo->zs.clear.s)
589 fbinfo->zs.clear_value.stencil = value->stencil;
590
591 for (unsigned level = range->baseMipLevel;
592 level < range->baseMipLevel + range->levelCount; level++) {
593 view.first_level = view.last_level = level;
594 fbinfo->width = u_minify(img->pimage.layout.width, level);
595 fbinfo->height = u_minify(img->pimage.layout.height, level);
596 fbinfo->extent.maxx = fbinfo->width - 1;
597 fbinfo->extent.maxy = fbinfo->height - 1;
598
599 for (unsigned layer = range->baseArrayLayer;
600 layer < range->baseArrayLayer + range->layerCount; layer++) {
601 view.first_layer = view.last_layer = layer;
602 panvk_cmd_open_batch(cmdbuf);
603 panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf);
604 panvk_per_arch(cmd_close_batch)(cmdbuf);
605 }
606 }
607 }
608
609 void
panvk_per_arch(CmdClearDepthStencilImage)610 panvk_per_arch(CmdClearDepthStencilImage)(VkCommandBuffer commandBuffer,
611 VkImage image,
612 VkImageLayout imageLayout,
613 const VkClearDepthStencilValue *pDepthStencil,
614 uint32_t rangeCount,
615 const VkImageSubresourceRange *pRanges)
616 {
617 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
618 VK_FROM_HANDLE(panvk_image, img, image);
619
620 panvk_per_arch(cmd_close_batch)(cmdbuf);
621
622 for (unsigned i = 0; i < rangeCount; i++)
623 panvk_meta_clear_zs_img(cmdbuf, img, pDepthStencil, &pRanges[i]);
624 }
625
626 void
panvk_per_arch(CmdClearAttachments)627 panvk_per_arch(CmdClearAttachments)(VkCommandBuffer commandBuffer,
628 uint32_t attachmentCount,
629 const VkClearAttachment *pAttachments,
630 uint32_t rectCount,
631 const VkClearRect *pRects)
632 {
633 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
634 const struct panvk_subpass *subpass = cmdbuf->state.subpass;
635
636 for (unsigned i = 0; i < attachmentCount; i++) {
637 for (unsigned j = 0; j < rectCount; j++) {
638
639 uint32_t attachment, rt = 0;
640 if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
641 rt = pAttachments[i].colorAttachment;
642 attachment = subpass->color_attachments[rt].idx;
643 } else {
644 attachment = subpass->zs_attachment.idx;
645 }
646
647 if (attachment == VK_ATTACHMENT_UNUSED)
648 continue;
649
650 panvk_meta_clear_attachment(cmdbuf, attachment, rt,
651 pAttachments[i].aspectMask,
652 &pAttachments[i].clearValue,
653 &pRects[j]);
654 }
655 }
656 }
657
658 static void
panvk_meta_clear_attachment_init(struct panvk_physical_device * dev)659 panvk_meta_clear_attachment_init(struct panvk_physical_device *dev)
660 {
661 for (unsigned rt = 0; rt < MAX_RTS; rt++) {
662 dev->meta.clear_attachment.color[rt][GLSL_TYPE_UINT].shader =
663 panvk_meta_clear_color_attachment_shader(
664 &dev->pdev,
665 &dev->meta.bin_pool.base,
666 rt,
667 GLSL_TYPE_UINT,
668 &dev->meta.clear_attachment.color[rt][GLSL_TYPE_UINT].shader_info);
669
670 dev->meta.clear_attachment.color[rt][GLSL_TYPE_INT].shader =
671 panvk_meta_clear_color_attachment_shader(
672 &dev->pdev,
673 &dev->meta.bin_pool.base,
674 rt,
675 GLSL_TYPE_INT,
676 &dev->meta.clear_attachment.color[rt][GLSL_TYPE_INT].shader_info);
677
678 dev->meta.clear_attachment.color[rt][GLSL_TYPE_FLOAT].shader =
679 panvk_meta_clear_color_attachment_shader(
680 &dev->pdev,
681 &dev->meta.bin_pool.base,
682 rt,
683 GLSL_TYPE_FLOAT,
684 &dev->meta.clear_attachment.color[rt][GLSL_TYPE_FLOAT].shader_info);
685 }
686
687 dev->meta.clear_attachment.z.shader =
688 panvk_meta_clear_zs_attachment_shader(
689 &dev->pdev,
690 &dev->meta.bin_pool.base,
691 true, false,
692 GLSL_TYPE_FLOAT,
693 &dev->meta.clear_attachment.z.shader_info);
694 dev->meta.clear_attachment.s.shader =
695 panvk_meta_clear_zs_attachment_shader(
696 &dev->pdev,
697 &dev->meta.bin_pool.base,
698 false, true,
699 GLSL_TYPE_FLOAT,
700 &dev->meta.clear_attachment.s.shader_info);
701 dev->meta.clear_attachment.zs.shader =
702 panvk_meta_clear_zs_attachment_shader(
703 &dev->pdev,
704 &dev->meta.bin_pool.base,
705 true, true,
706 GLSL_TYPE_FLOAT,
707 &dev->meta.clear_attachment.zs.shader_info);
708 }
709
710 void
panvk_per_arch(meta_clear_init)711 panvk_per_arch(meta_clear_init)(struct panvk_physical_device *dev)
712 {
713 panvk_meta_clear_attachment_init(dev);
714 }
715