diff options
Diffstat (limited to 'src/panfrost/vulkan/panvk_vX_meta_clear.c')
-rw-r--r-- | src/panfrost/vulkan/panvk_vX_meta_clear.c | 527 |
1 files changed, 527 insertions, 0 deletions
diff --git a/src/panfrost/vulkan/panvk_vX_meta_clear.c b/src/panfrost/vulkan/panvk_vX_meta_clear.c new file mode 100644 index 00000000000..b12a2797c34 --- /dev/null +++ b/src/panfrost/vulkan/panvk_vX_meta_clear.c @@ -0,0 +1,527 @@ +/* + * Copyright © 2021 Collabora Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "nir/nir_builder.h" +#include "pan_blitter.h" +#include "pan_encoder.h" +#include "pan_props.h" +#include "pan_shader.h" + +#include "panvk_cmd_buffer.h" +#include "panvk_device.h" +#include "panvk_entrypoints.h" +#include "panvk_image.h" +#include "panvk_meta.h" +#include "panvk_physical_device.h" + +#include "vk_format.h" +#include "vk_render_pass.h" + +static mali_ptr +panvk_meta_clear_color_attachment_shader(struct panvk_device *dev, + enum glsl_base_type base_type, + struct pan_shader_info *shader_info) +{ + struct panvk_physical_device *phys_dev = + to_panvk_physical_device(dev->vk.physical); + struct pan_pool *bin_pool = &dev->meta.bin_pool.base; + + nir_builder b = nir_builder_init_simple_shader( + MESA_SHADER_FRAGMENT, GENX(pan_shader_get_compiler_options)(), + "panvk_meta_clear_attachment(base_type=%d)", base_type); + + 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; + + nir_def *clear_values = + nir_load_push_constant(&b, 4, 32, nir_imm_int(&b, 0), .range = ~0); + nir_store_var(&b, out, clear_values, 0xff); + + struct panfrost_compile_inputs inputs = { + .gpu_id = phys_dev->kmod.props.gpu_prod_id, + .is_blit = true, + .no_ubo_to_push = true, + }; + + struct util_dynarray binary; + + util_dynarray_init(&binary, NULL); + pan_shader_preprocess(b.shader, inputs.gpu_id); + GENX(pan_shader_compile)(b.shader, &inputs, &binary, shader_info); + + shader_info->push.count = 4; + + mali_ptr shader = + pan_pool_upload_aligned(bin_pool, binary.data, binary.size, 128); + + util_dynarray_fini(&binary); + ralloc_free(b.shader); + + return shader; +} + +static mali_ptr +panvk_meta_clear_color_attachment_emit_rsd(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_ARRAY(rt + 1, BLEND)); + + pan_pack(rsd_ptr.cpu, RENDERER_STATE, cfg) { + pan_shader_prepare_rsd(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.properties.allow_forward_pixel_to_be_killed = true; + cfg.properties.allow_forward_pixel_to_kill = true; + cfg.properties.zs_update_operation = MALI_PIXEL_KILL_WEAK_EARLY; + cfg.properties.pixel_kill_operation = MALI_PIXEL_KILL_WEAK_EARLY; + } + + void *bd = rsd_ptr.cpu + pan_size(RENDERER_STATE); + + pan_pack(bd, BLEND, cfg) { + cfg.round_to_fb_precision = true; + cfg.load_destination = false; + cfg.equation.rgb.a = MALI_BLEND_OPERAND_A_SRC; + cfg.equation.rgb.b = MALI_BLEND_OPERAND_B_SRC; + cfg.equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO; + cfg.equation.alpha.a = MALI_BLEND_OPERAND_A_SRC; + cfg.equation.alpha.b = MALI_BLEND_OPERAND_B_SRC; + cfg.equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO; + cfg.internal.mode = MALI_BLEND_MODE_OPAQUE; + cfg.equation.color_mask = 0xf; + cfg.internal.fixed_function.num_comps = 4; + cfg.internal.fixed_function.rt = rt; + cfg.internal.fixed_function.conversion.memory_format = + GENX(panfrost_dithered_format_from_pipe_format)(format, false); + cfg.internal.fixed_function.conversion.register_format = + shader_info->bifrost.blend[0].format; + } + + return rsd_ptr.gpu; +} + +static mali_ptr +panvk_meta_clear_zs_attachment_emit_rsd(struct pan_pool *desc_pool, + VkImageAspectFlags mask, + VkClearDepthStencilValue value) +{ + struct panfrost_ptr rsd_ptr = pan_pool_alloc_desc(desc_pool, RENDERER_STATE); + + pan_pack(rsd_ptr.cpu, RENDERER_STATE, cfg) { + cfg.properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION; + cfg.multisample_misc.sample_mask = UINT16_MAX; + + if (mask & VK_IMAGE_ASPECT_DEPTH_BIT) { + cfg.multisample_misc.depth_write_mask = true; + cfg.multisample_misc.depth_function = MALI_FUNC_NOT_EQUAL; + + if (value.depth != 0.0) { + cfg.stencil_mask_misc.front_facing_depth_bias = true; + cfg.stencil_mask_misc.back_facing_depth_bias = true; + cfg.depth_units = INFINITY; + cfg.depth_bias_clamp = value.depth; + } + } + + if (mask & VK_IMAGE_ASPECT_STENCIL_BIT) { + cfg.stencil_mask_misc.stencil_enable = true; + cfg.stencil_mask_misc.stencil_mask_front = 0xFF; + cfg.stencil_mask_misc.stencil_mask_back = 0xFF; + + cfg.stencil_front.compare_function = (mask & VK_IMAGE_ASPECT_DEPTH_BIT) + ? MALI_FUNC_ALWAYS + : MALI_FUNC_NOT_EQUAL; + + cfg.stencil_front.stencil_fail = MALI_STENCIL_OP_KEEP; + cfg.stencil_front.depth_fail = MALI_STENCIL_OP_REPLACE; + cfg.stencil_front.depth_pass = MALI_STENCIL_OP_REPLACE; + cfg.stencil_front.reference_value = value.stencil; + cfg.stencil_front.mask = 0xFF; + cfg.stencil_back = cfg.stencil_front; + } + + cfg.properties.allow_forward_pixel_to_be_killed = true; + cfg.properties.zs_update_operation = MALI_PIXEL_KILL_WEAK_EARLY; + cfg.properties.pixel_kill_operation = MALI_PIXEL_KILL_WEAK_EARLY; + } + + return rsd_ptr.gpu; +} + +static void +panvk_meta_clear_attachment_emit_dcd(struct pan_pool *pool, mali_ptr coords, + mali_ptr push_constants, mali_ptr vpd, + mali_ptr tsd, mali_ptr rsd, void *out) +{ + pan_pack(out, DRAW, cfg) { + cfg.thread_storage = tsd; + cfg.state = rsd; + cfg.push_uniforms = push_constants; + cfg.position = coords; + cfg.viewport = vpd; + } +} + +static struct panfrost_ptr +panvk_meta_clear_attachment_emit_tiler_job(struct pan_pool *desc_pool, + struct pan_jc *jc, mali_ptr coords, + 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, TILER_JOB); + + panvk_meta_clear_attachment_emit_dcd( + desc_pool, coords, push_constants, vpd, tsd, rsd, + pan_section_ptr(job.cpu, TILER_JOB, DRAW)); + + pan_section_pack(job.cpu, 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, TILER_JOB, PRIMITIVE_SIZE, cfg) { + cfg.constant = 1.0f; + } + + void *invoc = pan_section_ptr(job.cpu, TILER_JOB, INVOCATION); + panfrost_pack_work_groups_compute(invoc, 1, 4, 1, 1, 1, 1, true, false); + + pan_section_pack(job.cpu, TILER_JOB, PADDING, cfg) + ; + pan_section_pack(job.cpu, TILER_JOB, TILER, cfg) { + cfg.address = tiler; + } + + pan_jc_add_job(desc_pool, jc, 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, unsigned rt, + VkImageAspectFlags mask, + const VkClearValue *clear_value, + const VkClearRect *clear_rect) +{ + struct panvk_device *dev = to_panvk_device(cmdbuf->vk.base.device); + struct panvk_meta *meta = &dev->meta; + struct panvk_batch *batch = cmdbuf->state.batch; + enum pipe_format pfmt = cmdbuf->state.fb.info.rts[rt].view->format; + 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); + + panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf); + panvk_per_arch(cmd_alloc_tls_desc)(cmdbuf, true); + panvk_per_arch(cmd_prepare_tiler_context)(cmdbuf); + + mali_ptr vpd = panvk_per_arch(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(pfmt); + + mali_ptr tiler = batch->tiler.ctx_desc.gpu; + mali_ptr tsd = batch->tls.gpu; + + mali_ptr pushconsts = 0, rsd = 0; + + if (mask & VK_IMAGE_ASPECT_COLOR_BIT) { + mali_ptr shader = meta->clear_attachment.color[base_type].shader; + struct pan_shader_info *shader_info = + &meta->clear_attachment.color[base_type].shader_info; + + pushconsts = pan_pool_upload_aligned(&cmdbuf->desc_pool.base, clear_value, + sizeof(*clear_value), 16); + + rsd = panvk_meta_clear_color_attachment_emit_rsd( + &cmdbuf->desc_pool.base, pfmt, rt, shader_info, shader); + } else { + rsd = panvk_meta_clear_zs_attachment_emit_rsd( + &cmdbuf->desc_pool.base, mask, clear_value->depthStencil); + } + + struct panfrost_ptr job; + + job = panvk_meta_clear_attachment_emit_tiler_job( + &cmdbuf->desc_pool.base, &batch->jc, coordinates, pushconsts, vpd, rsd, + tsd, tiler); + + util_dynarray_append(&batch->jobs, void *, job.cpu); +} + +static void +panvk_meta_clear_color_img(struct panvk_cmd_buffer *cmdbuf, + struct panvk_image *img, + const VkClearColorValue *color, + const VkImageSubresourceRange *range) +{ + struct panvk_device *dev = to_panvk_device(cmdbuf->vk.base.device); + struct panvk_physical_device *phys_dev = + to_panvk_physical_device(dev->vk.physical); + struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; + struct pan_image_view view = { + .format = img->pimage.layout.format, + .dim = MALI_TEXTURE_DIMENSION_2D, + .planes[0] = &img->pimage, + .nr_samples = img->pimage.layout.nr_samples, + .swizzle = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, + PIPE_SWIZZLE_W}, + }; + + cmdbuf->state.fb.crc_valid[0] = false; + *fbinfo = (struct pan_fb_info){ + .tile_buf_budget = panfrost_query_optimal_tib_size(phys_dev->model), + .nr_samples = img->pimage.layout.nr_samples, + .rt_count = 1, + .rts[0].view = &view, + .rts[0].clear = true, + .rts[0].crc_valid = &cmdbuf->state.fb.crc_valid[0], + }; + + uint32_t clearval[4]; + pan_pack_color(panfrost_blendable_formats_v7, clearval, + (union pipe_color_union *)color, img->pimage.layout.format, + false); + memcpy(fbinfo->rts[0].clear_value, clearval, + sizeof(fbinfo->rts[0].clear_value)); + + unsigned level_count = vk_image_subresource_level_count(&img->vk, range); + unsigned layer_count = vk_image_subresource_layer_count(&img->vk, range); + + for (unsigned level = range->baseMipLevel; + level < range->baseMipLevel + level_count; level++) { + view.first_level = view.last_level = level; + fbinfo->width = u_minify(img->pimage.layout.width, level); + fbinfo->height = u_minify(img->pimage.layout.height, level); + fbinfo->extent.maxx = fbinfo->width - 1; + fbinfo->extent.maxy = fbinfo->height - 1; + + for (unsigned layer = range->baseArrayLayer; + layer < range->baseArrayLayer + layer_count; layer++) { + view.first_layer = view.last_layer = layer; + panvk_per_arch(cmd_open_batch)(cmdbuf); + panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf); + panvk_per_arch(cmd_close_batch)(cmdbuf); + } + } +} + +VKAPI_ATTR void VKAPI_CALL +panvk_per_arch(CmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, + VkImageLayout imageLayout, + const VkClearColorValue *pColor, + uint32_t rangeCount, + const VkImageSubresourceRange *pRanges) +{ + VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); + VK_FROM_HANDLE(panvk_image, img, image); + + panvk_per_arch(cmd_close_batch)(cmdbuf); + + for (unsigned i = 0; i < rangeCount; i++) + panvk_meta_clear_color_img(cmdbuf, img, pColor, &pRanges[i]); +} + +static void +panvk_meta_clear_zs_img(struct panvk_cmd_buffer *cmdbuf, + struct panvk_image *img, + const VkClearDepthStencilValue *value, + const VkImageSubresourceRange *range) +{ + struct panvk_device *dev = to_panvk_device(cmdbuf->vk.base.device); + struct panvk_physical_device *phys_dev = + to_panvk_physical_device(dev->vk.physical); + struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; + struct pan_image_view view = { + .format = img->pimage.layout.format, + .dim = MALI_TEXTURE_DIMENSION_2D, + .planes[0] = &img->pimage, + .nr_samples = img->pimage.layout.nr_samples, + .swizzle = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, + PIPE_SWIZZLE_W}, + }; + + cmdbuf->state.fb.crc_valid[0] = false; + *fbinfo = (struct pan_fb_info){ + .tile_buf_budget = panfrost_query_optimal_tib_size(phys_dev->model), + .nr_samples = img->pimage.layout.nr_samples, + .rt_count = 1, + .zs.clear_value.depth = value->depth, + .zs.clear_value.stencil = value->stencil, + .zs.clear.z = range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT, + .zs.clear.s = range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT}; + + const struct util_format_description *fdesc = + util_format_description(view.format); + + if (util_format_has_depth(fdesc)) { + fbinfo->zs.view.zs = &view; + if (util_format_has_stencil(fdesc)) { + fbinfo->zs.preload.z = !fbinfo->zs.clear.z; + fbinfo->zs.preload.s = !fbinfo->zs.clear.s; + } + } else { + fbinfo->zs.view.s = &view; + } + + unsigned level_count = vk_image_subresource_level_count(&img->vk, range); + unsigned layer_count = vk_image_subresource_layer_count(&img->vk, range); + + for (unsigned level = range->baseMipLevel; + level < range->baseMipLevel + level_count; level++) { + view.first_level = view.last_level = level; + fbinfo->width = u_minify(img->pimage.layout.width, level); + fbinfo->height = u_minify(img->pimage.layout.height, level); + fbinfo->extent.maxx = fbinfo->width - 1; + fbinfo->extent.maxy = fbinfo->height - 1; + + for (unsigned layer = range->baseArrayLayer; + layer < range->baseArrayLayer + layer_count; layer++) { + view.first_layer = view.last_layer = layer; + panvk_per_arch(cmd_open_batch)(cmdbuf); + panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf); + panvk_per_arch(cmd_close_batch)(cmdbuf); + } + } + + memset(fbinfo, 0, sizeof(*fbinfo)); +} + +VKAPI_ATTR void VKAPI_CALL +panvk_per_arch(CmdClearDepthStencilImage)( + VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, + const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount, + const VkImageSubresourceRange *pRanges) +{ + VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); + VK_FROM_HANDLE(panvk_image, img, image); + + panvk_per_arch(cmd_close_batch)(cmdbuf); + + for (unsigned i = 0; i < rangeCount; i++) + panvk_meta_clear_zs_img(cmdbuf, img, pDepthStencil, &pRanges[i]); +} + +VKAPI_ATTR void VKAPI_CALL +panvk_per_arch(CmdClearAttachments)(VkCommandBuffer commandBuffer, + uint32_t attachmentCount, + const VkClearAttachment *pAttachments, + uint32_t rectCount, + const VkClearRect *pRects) +{ + VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); + const struct vk_subpass *subpass = + &cmdbuf->vk.render_pass->subpasses[cmdbuf->vk.subpass_idx]; + + for (unsigned i = 0; i < attachmentCount; i++) { + for (unsigned j = 0; j < rectCount; j++) { + + uint32_t attachment = VK_ATTACHMENT_UNUSED, rt = 0; + if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { + rt = pAttachments[i].colorAttachment; + attachment = subpass->color_attachments[rt].attachment; + } else if (subpass->depth_stencil_attachment) { + attachment = subpass->depth_stencil_attachment->attachment; + } + + if (attachment == VK_ATTACHMENT_UNUSED) + continue; + + panvk_meta_clear_attachment(cmdbuf, rt, pAttachments[i].aspectMask, + &pAttachments[i].clearValue, &pRects[j]); + } + } +} + +static void +panvk_meta_clear_attachment_init(struct panvk_device *dev) +{ + dev->meta.clear_attachment.color[GLSL_TYPE_UINT].shader = + panvk_meta_clear_color_attachment_shader( + dev, GLSL_TYPE_UINT, + &dev->meta.clear_attachment.color[GLSL_TYPE_UINT].shader_info); + + dev->meta.clear_attachment.color[GLSL_TYPE_INT].shader = + panvk_meta_clear_color_attachment_shader( + dev, GLSL_TYPE_INT, + &dev->meta.clear_attachment.color[GLSL_TYPE_INT].shader_info); + + dev->meta.clear_attachment.color[GLSL_TYPE_FLOAT].shader = + panvk_meta_clear_color_attachment_shader( + dev, GLSL_TYPE_FLOAT, + &dev->meta.clear_attachment.color[GLSL_TYPE_FLOAT].shader_info); +} + +void +panvk_per_arch(meta_clear_init)(struct panvk_device *dev) +{ + panvk_meta_clear_attachment_init(dev); +} |