Module: Mesa Branch: main Commit: 59c2337f2264c7e98600fae049812934e00a66b1 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=59c2337f2264c7e98600fae049812934e00a66b1
Author: Tomeu Vizoso <[email protected]> Date: Fri Jul 9 16:11:50 2021 +0200 panvk: Implement vkCmdClearAttachments For now it only supports one RT and color attachments. Signed-off-by: Tomeu Vizoso <[email protected]> Reviewed-by: Boris Brezillon <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12019> --- src/panfrost/vulkan/panvk_meta.c | 468 +++++++++++++++++++++++++++++++++++- src/panfrost/vulkan/panvk_private.h | 5 + 2 files changed, 472 insertions(+), 1 deletion(-) diff --git a/src/panfrost/vulkan/panvk_meta.c b/src/panfrost/vulkan/panvk_meta.c index 7c123d10b2b..657a3c4324f 100644 --- a/src/panfrost/vulkan/panvk_meta.c +++ b/src/panfrost/vulkan/panvk_meta.c @@ -141,6 +141,449 @@ panvk_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, panvk_stub(); } +static mali_ptr +panvk_meta_emit_viewport(struct pan_pool *pool, + uint16_t minx, uint16_t miny, + uint16_t maxx, uint16_t maxy) +{ + struct panfrost_ptr vp = pan_pool_alloc_desc(pool, VIEWPORT); + + pan_pack(vp.cpu, VIEWPORT, cfg) { + cfg.scissor_minimum_x = minx; + cfg.scissor_minimum_y = miny; + cfg.scissor_maximum_x = maxx; + cfg.scissor_maximum_y = maxy; + } + + return vp.gpu; +} + +static mali_ptr +panvk_meta_clear_attachments_shader(struct panfrost_device *pdev, + struct pan_pool *bin_pool, + unsigned rt, + enum glsl_base_type base_type, + struct pan_shader_info *shader_info) +{ + nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, + pan_shader_get_compiler_options(pdev), + "panvk_meta_clear_attachment(base_type=%d,rt=%d)", + base_type, + rt); + + b.shader->info.internal = true; + b.shader->info.num_ubos = 1; + + const struct glsl_type *out_type = glsl_vector_type(base_type, 4); + nir_variable *out = + nir_variable_create(b.shader, nir_var_shader_out, out_type, "out"); + out->data.location = FRAG_RESULT_DATA0 + rt; + + nir_ssa_def *clear_values = nir_load_ubo(&b, 4, 32, nir_imm_int(&b, 0), + nir_imm_int(&b, 0), + .align_mul = 4, + .align_offset = 0, + .range_base = 0, + .range = ~0); + nir_store_var(&b, out, clear_values, 0xff); + + struct panfrost_compile_inputs inputs = { + .gpu_id = pdev->gpu_id, + .is_blit = true, + }; + + struct util_dynarray binary; + + util_dynarray_init(&binary, NULL); + pan_shader_compile(pdev, b.shader, &inputs, &binary, shader_info); + + /* Make sure UBO words have been upgraded to push constants */ + assert(shader_info->ubo_count == 1); + assert(shader_info->push.count == 4); + + mali_ptr shader = + pan_pool_upload_aligned(bin_pool, binary.data, binary.size, + pan_is_bifrost(pdev) ? 128 : 64); + + util_dynarray_fini(&binary); + ralloc_free(b.shader); + + return shader; +} + +static mali_ptr +panvk_meta_clear_attachments_emit_rsd(struct panfrost_device *pdev, + struct pan_pool *desc_pool, + enum pipe_format format, + unsigned rt, + struct pan_shader_info *shader_info, + mali_ptr shader) +{ + struct panfrost_ptr rsd_ptr = + pan_pool_alloc_desc_aggregate(desc_pool, + PAN_DESC(RENDERER_STATE), + PAN_DESC(BLEND)); + + unsigned fullmask = (1 << util_format_get_nr_components(format)) - 1; + + /* TODO: Support multiple render targets */ + assert(rt == 0); + + pan_pack(rsd_ptr.cpu, RENDERER_STATE, cfg) { + pan_shader_prepare_rsd(pdev, shader_info, shader, &cfg); + cfg.properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION; + cfg.multisample_misc.sample_mask = UINT16_MAX; + cfg.multisample_misc.depth_function = MALI_FUNC_ALWAYS; + cfg.stencil_mask_misc.stencil_mask_front = 0xFF; + cfg.stencil_mask_misc.stencil_mask_back = 0xFF; + cfg.stencil_front.compare_function = MALI_FUNC_ALWAYS; + cfg.stencil_front.stencil_fail = MALI_STENCIL_OP_REPLACE; + cfg.stencil_front.depth_fail = MALI_STENCIL_OP_REPLACE; + cfg.stencil_front.depth_pass = MALI_STENCIL_OP_REPLACE; + cfg.stencil_front.mask = 0xFF; + cfg.stencil_back = cfg.stencil_front; + + if (pan_is_bifrost(pdev)) { + cfg.properties.bifrost.allow_forward_pixel_to_be_killed = true; + cfg.properties.bifrost.allow_forward_pixel_to_kill = true; + cfg.properties.bifrost.zs_update_operation = + MALI_PIXEL_KILL_STRONG_EARLY; + cfg.properties.bifrost.pixel_kill_operation = + MALI_PIXEL_KILL_FORCE_EARLY; + } else { + cfg.properties.midgard.shader_reads_tilebuffer = false; + cfg.properties.midgard.work_register_count = shader_info->work_reg_count; + cfg.properties.midgard.force_early_z = true; + cfg.stencil_mask_misc.alpha_test_compare_function = MALI_FUNC_ALWAYS; + } + } + + pan_pack(rsd_ptr.cpu + MALI_RENDERER_STATE_LENGTH, BLEND, cfg) { + cfg.round_to_fb_precision = true; + cfg.load_destination = false; + if (pan_is_bifrost(pdev)) { + cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OPAQUE; + cfg.bifrost.equation.rgb.a = MALI_BLEND_OPERAND_A_SRC; + cfg.bifrost.equation.rgb.b = MALI_BLEND_OPERAND_B_SRC; + cfg.bifrost.equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO; + cfg.bifrost.equation.alpha.a = MALI_BLEND_OPERAND_A_SRC; + cfg.bifrost.equation.alpha.b = MALI_BLEND_OPERAND_B_SRC; + cfg.bifrost.equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO; + cfg.bifrost.equation.color_mask = 0xf; + cfg.bifrost.internal.fixed_function.num_comps = 4; + cfg.bifrost.internal.fixed_function.conversion.memory_format = + panfrost_format_to_bifrost_blend(pdev, format); + cfg.bifrost.internal.fixed_function.conversion.register_format = + shader_info->bifrost.blend[rt].format; + } else { + cfg.midgard.equation.rgb.a = MALI_BLEND_OPERAND_A_SRC; + cfg.midgard.equation.rgb.b = MALI_BLEND_OPERAND_B_SRC; + cfg.midgard.equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO; + cfg.midgard.equation.alpha.a = MALI_BLEND_OPERAND_A_SRC; + cfg.midgard.equation.alpha.b = MALI_BLEND_OPERAND_B_SRC; + cfg.midgard.equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO; + cfg.midgard.equation.color_mask = fullmask; + } + } + + return rsd_ptr.gpu; +} + +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) +{ + assert(pushmap->count <= (sizeof(*clear_value) / 4)); + + uint32_t *in = (uint32_t *)clear_value; + uint32_t pushvals[sizeof(*clear_value) / 4]; + + for (unsigned i = 0; i < pushmap->count; i++) { + assert(i < ARRAY_SIZE(pushvals)); + assert(pushmap->words[i].ubo == 0); + assert(pushmap->words[i].offset < sizeof(*clear_value)); + pushvals[i] = in[pushmap->words[i].offset / 4]; + } + + return pan_pool_upload_aligned(pool, pushvals, sizeof(pushvals), 16); +} + +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) +{ + struct panfrost_ptr ubo = pan_pool_alloc_desc(pool, UNIFORM_BUFFER); + + pan_pack(ubo.cpu, UNIFORM_BUFFER, cfg) { + cfg.entries = DIV_ROUND_UP(sizeof(*clear_value), 16); + cfg.pointer = pan_pool_upload_aligned(pool, clear_value, sizeof(*clear_value), 16); + } + + return ubo.gpu; +} + +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) +{ + pan_pack(out, DRAW, cfg) { + cfg.four_components_per_vertex = true; + cfg.draw_descriptor_is_64b = true; + cfg.thread_storage = tsd; + cfg.state = rsd; + cfg.uniform_buffers = ubo; + cfg.push_uniforms = push_constants; + cfg.position = coords; + cfg.viewport = vpd; + cfg.texture_descriptor_is_64b = !pan_is_bifrost(pool->dev); + } +} + +static struct panfrost_ptr +panvk_meta_clear_attachment_emit_bifrost_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) +{ + struct panfrost_ptr job = + pan_pool_alloc_desc(desc_pool, BIFROST_TILER_JOB); + + panvk_meta_clear_attachment_emit_dcd(desc_pool, + coords, + ubo, push_constants, + vpd, tsd, rsd, + pan_section_ptr(job.cpu, BIFROST_TILER_JOB, DRAW)); + + pan_section_pack(job.cpu, BIFROST_TILER_JOB, PRIMITIVE, cfg) { + cfg.draw_mode = MALI_DRAW_MODE_TRIANGLE_STRIP; + cfg.index_count = 4; + cfg.job_task_split = 6; + } + + pan_section_pack(job.cpu, BIFROST_TILER_JOB, PRIMITIVE_SIZE, cfg) { + cfg.constant = 1.0f; + } + + void *invoc = pan_section_ptr(job.cpu, + BIFROST_TILER_JOB, + INVOCATION); + panfrost_pack_work_groups_compute(invoc, 1, 4, + 1, 1, 1, 1, true, false); + + pan_section_pack(job.cpu, BIFROST_TILER_JOB, PADDING, cfg); + pan_section_pack(job.cpu, BIFROST_TILER_JOB, TILER, cfg) { + cfg.address = tiler; + } + + panfrost_add_job(desc_pool, scoreboard, MALI_JOB_TYPE_TILER, + false, false, 0, 0, &job, false); + return job; +} + +static struct panfrost_ptr +panvk_meta_clear_attachment_emit_midgard_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) +{ + struct panfrost_ptr job = + pan_pool_alloc_desc(desc_pool, MIDGARD_TILER_JOB); + + panvk_meta_clear_attachment_emit_dcd(desc_pool, + coords, + ubo, push_constants, + vpd, tsd, rsd, + pan_section_ptr(job.cpu, MIDGARD_TILER_JOB, DRAW)); + + pan_section_pack(job.cpu, MIDGARD_TILER_JOB, PRIMITIVE, cfg) { + cfg.draw_mode = MALI_DRAW_MODE_TRIANGLE_STRIP; + cfg.index_count = 4; + cfg.job_task_split = 6; + } + + pan_section_pack(job.cpu, MIDGARD_TILER_JOB, PRIMITIVE_SIZE, cfg) { + cfg.constant = 1.0f; + } + + void *invoc = pan_section_ptr(job.cpu, + MIDGARD_TILER_JOB, + INVOCATION); + panfrost_pack_work_groups_compute(invoc, 1, 4, + 1, 1, 1, 1, true, false); + + panfrost_add_job(desc_pool, scoreboard, MALI_JOB_TYPE_TILER, + false, false, 0, 0, &job, false); + return job; +} + +static enum glsl_base_type +panvk_meta_get_format_type(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + int i; + + i = util_format_get_first_non_void_channel(format); + assert(i >= 0); + + if (desc->channel[i].normalized) + return GLSL_TYPE_FLOAT; + + switch(desc->channel[i].type) { + + case UTIL_FORMAT_TYPE_UNSIGNED: + return GLSL_TYPE_UINT; + + case UTIL_FORMAT_TYPE_SIGNED: + return GLSL_TYPE_INT; + + case UTIL_FORMAT_TYPE_FLOAT: + return GLSL_TYPE_FLOAT; + + default: + unreachable("Unhandled format"); + return GLSL_TYPE_FLOAT; + } +} + +static void +panvk_meta_clear_attachment(struct panvk_cmd_buffer *cmdbuf, + uint32_t attachment, + VkImageAspectFlags mask, + const VkClearValue *clear_value, + const VkClearRect *clear_rect) +{ + struct panvk_physical_device *dev = cmdbuf->device->physical_device; + struct panfrost_device *pdev = &dev->pdev; + struct panvk_meta *meta = &cmdbuf->device->physical_device->meta; + struct panvk_batch *batch = cmdbuf->state.batch; + const struct panvk_render_pass *pass = cmdbuf->state.pass; + const struct panvk_render_pass_attachment *att = &pass->attachments[attachment]; + unsigned minx = MAX2(clear_rect->rect.offset.x, 0); + unsigned miny = MAX2(clear_rect->rect.offset.y, 0); + unsigned maxx = MAX2(clear_rect->rect.offset.x + clear_rect->rect.extent.width - 1, 0); + unsigned maxy = MAX2(clear_rect->rect.offset.y + clear_rect->rect.extent.height - 1, 0); + + /* TODO: Support depth/stencil */ + assert(mask == VK_IMAGE_ASPECT_COLOR_BIT); + + panvk_cmd_alloc_fb_desc(cmdbuf); + panvk_cmd_alloc_tls_desc(cmdbuf); + + if (pan_is_bifrost(pdev)) { + panvk_cmd_get_bifrost_tiler_context(cmdbuf, + batch->fb.info->width, + batch->fb.info->height); + } else { + panvk_cmd_get_midgard_polygon_list(cmdbuf, + batch->fb.info->width, + batch->fb.info->height, + true); + } + + mali_ptr vpd = panvk_meta_emit_viewport(&cmdbuf->desc_pool.base, + minx, miny, maxx, maxy); + + float rect[] = { + minx, miny, 0.0, 1.0, + maxx + 1, miny, 0.0, 1.0, + minx, maxy + 1, 0.0, 1.0, + maxx + 1, maxy + 1, 0.0, 1.0, + }; + mali_ptr coordinates = pan_pool_upload_aligned(&cmdbuf->desc_pool.base, + rect, sizeof(rect), 64); + + enum glsl_base_type base_type = panvk_meta_get_format_type(att->format); + mali_ptr shader = meta->clear_attachment[attachment][base_type].shader; + struct pan_shader_info *shader_info = + &meta->clear_attachment[attachment][base_type].shader_info; + + mali_ptr rsd = + panvk_meta_clear_attachments_emit_rsd(pdev, + &cmdbuf->desc_pool.base, + att->format, + attachment, + shader_info, + shader); + + mali_ptr pushconsts = + panvk_meta_clear_attachment_emit_push_constants(pdev, &shader_info->push, + &cmdbuf->desc_pool.base, + clear_value); + mali_ptr ubo = + panvk_meta_clear_attachment_emit_ubo(pdev, &shader_info->push, + &cmdbuf->desc_pool.base, + clear_value); + + mali_ptr tsd, tiler; + + if (pan_is_bifrost(pdev)) { + tsd = batch->tls.gpu; + tiler = batch->tiler.bifrost_descs.gpu; + } else { + tsd = batch->fb.desc.gpu; + tiler = 0; + } + + struct panfrost_ptr job; + + if (pan_is_bifrost(pdev)) { + job = panvk_meta_clear_attachment_emit_bifrost_tiler_job(&cmdbuf->desc_pool.base, + &batch->scoreboard, + coordinates, + ubo, pushconsts, + vpd, rsd, tsd, tiler); + } else { + job = panvk_meta_clear_attachment_emit_midgard_tiler_job(&cmdbuf->desc_pool.base, + &batch->scoreboard, + coordinates, + ubo, pushconsts, + vpd, rsd, tsd); + } + + util_dynarray_append(&batch->jobs, void *, job.cpu); +} + +static void +panvk_meta_clear_attachment_init(struct panvk_physical_device *dev) +{ + for (unsigned rt = 0; rt < MAX_RTS; rt++) { + dev->meta.clear_attachment[rt][GLSL_TYPE_UINT].shader = + panvk_meta_clear_attachments_shader( + &dev->pdev, + &dev->meta.bin_pool.base, + rt, + GLSL_TYPE_UINT, + &dev->meta.clear_attachment[rt][GLSL_TYPE_UINT].shader_info); + + dev->meta.clear_attachment[rt][GLSL_TYPE_INT].shader = + panvk_meta_clear_attachments_shader( + &dev->pdev, + &dev->meta.bin_pool.base, + rt, + GLSL_TYPE_INT, + &dev->meta.clear_attachment[rt][GLSL_TYPE_INT].shader_info); + + dev->meta.clear_attachment[rt][GLSL_TYPE_FLOAT].shader = + panvk_meta_clear_attachments_shader( + &dev->pdev, + &dev->meta.bin_pool.base, + rt, + GLSL_TYPE_FLOAT, + &dev->meta.clear_attachment[rt][GLSL_TYPE_FLOAT].shader_info); + } +} + void panvk_CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, @@ -148,7 +591,29 @@ panvk_CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t rectCount, const VkClearRect *pRects) { - panvk_stub(); + VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); + const struct panvk_subpass *subpass = cmdbuf->state.subpass; + + for (unsigned i = 0; i < attachmentCount; i++) { + for (unsigned j = 0; j < rectCount; j++) { + + uint32_t attachment; + if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { + unsigned idx = pAttachments[i].colorAttachment; + attachment = subpass->color_attachments[idx].idx; + } else { + attachment = subpass->zs_attachment.idx; + } + + if (attachment == VK_ATTACHMENT_UNUSED) + continue; + + panvk_meta_clear_attachment(cmdbuf, attachment, + pAttachments[i].aspectMask, + &pAttachments[i].clearValue, + &pRects[j]); + } + } } void @@ -166,6 +631,7 @@ panvk_meta_init(struct panvk_physical_device *dev) false); pan_blitter_init(&dev->pdev, &dev->meta.blitter.bin_pool.base, &dev->meta.blitter.desc_pool.base); + panvk_meta_clear_attachment_init(dev); } void diff --git a/src/panfrost/vulkan/panvk_private.h b/src/panfrost/vulkan/panvk_private.h index 08e6a80150f..986648fe9c6 100644 --- a/src/panfrost/vulkan/panvk_private.h +++ b/src/panfrost/vulkan/panvk_private.h @@ -145,6 +145,11 @@ struct panvk_meta { struct panvk_pool bin_pool; struct panvk_pool desc_pool; } blitter; + + struct { + mali_ptr shader; + struct pan_shader_info shader_info; + } clear_attachment[MAX_RTS][3]; /* 3 base types */ }; struct panvk_physical_device { _______________________________________________ mesa-commit mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-commit
