Path: blob/21.2-virgl/src/broadcom/vulkan/v3dvx_meta_copy.c
4560 views
/*1* Copyright © 2021 Raspberry Pi2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "v3dv_private.h"24#include "v3dv_meta_copy.h"25#include "broadcom/common/v3d_macros.h"26#include "broadcom/cle/v3dx_pack.h"27#include "broadcom/compiler/v3d_compiler.h"2829#include "vk_format_info.h"3031struct rcl_clear_info {32const union v3dv_clear_value *clear_value;33struct v3dv_image *image;34VkImageAspectFlags aspects;35uint32_t layer;36uint32_t level;37};3839static struct v3dv_cl *40emit_rcl_prologue(struct v3dv_job *job,41struct framebuffer_data *fb,42const struct rcl_clear_info *clear_info)43{44const struct v3dv_frame_tiling *tiling = &job->frame_tiling;4546struct v3dv_cl *rcl = &job->rcl;47v3dv_cl_ensure_space_with_branch(rcl, 200 +48tiling->layers * 256 *49cl_packet_length(SUPERTILE_COORDINATES));50if (job->cmd_buffer->state.oom)51return NULL;5253cl_emit(rcl, TILE_RENDERING_MODE_CFG_COMMON, config) {54config.early_z_disable = true;55config.image_width_pixels = tiling->width;56config.image_height_pixels = tiling->height;57config.number_of_render_targets = 1;58config.multisample_mode_4x = tiling->msaa;59config.maximum_bpp_of_all_render_targets = tiling->internal_bpp;60config.internal_depth_type = fb->internal_depth_type;61}6263if (clear_info && (clear_info->aspects & VK_IMAGE_ASPECT_COLOR_BIT)) {64uint32_t clear_pad = 0;65if (clear_info->image) {66const struct v3dv_image *image = clear_info->image;67const struct v3d_resource_slice *slice =68&image->slices[clear_info->level];69if (slice->tiling == V3D_TILING_UIF_NO_XOR ||70slice->tiling == V3D_TILING_UIF_XOR) {71int uif_block_height = v3d_utile_height(image->cpp) * 2;7273uint32_t implicit_padded_height =74align(tiling->height, uif_block_height) / uif_block_height;7576if (slice->padded_height_of_output_image_in_uif_blocks -77implicit_padded_height >= 15) {78clear_pad = slice->padded_height_of_output_image_in_uif_blocks;79}80}81}8283const uint32_t *color = &clear_info->clear_value->color[0];84cl_emit(rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART1, clear) {85clear.clear_color_low_32_bits = color[0];86clear.clear_color_next_24_bits = color[1] & 0x00ffffff;87clear.render_target_number = 0;88};8990if (tiling->internal_bpp >= V3D_INTERNAL_BPP_64) {91cl_emit(rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART2, clear) {92clear.clear_color_mid_low_32_bits =93((color[1] >> 24) | (color[2] << 8));94clear.clear_color_mid_high_24_bits =95((color[2] >> 24) | ((color[3] & 0xffff) << 8));96clear.render_target_number = 0;97};98}99100if (tiling->internal_bpp >= V3D_INTERNAL_BPP_128 || clear_pad) {101cl_emit(rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART3, clear) {102clear.uif_padded_height_in_uif_blocks = clear_pad;103clear.clear_color_high_16_bits = color[3] >> 16;104clear.render_target_number = 0;105};106}107}108109cl_emit(rcl, TILE_RENDERING_MODE_CFG_COLOR, rt) {110rt.render_target_0_internal_bpp = tiling->internal_bpp;111rt.render_target_0_internal_type = fb->internal_type;112rt.render_target_0_clamp = V3D_RENDER_TARGET_CLAMP_NONE;113}114115cl_emit(rcl, TILE_RENDERING_MODE_CFG_ZS_CLEAR_VALUES, clear) {116clear.z_clear_value = clear_info ? clear_info->clear_value->z : 1.0f;117clear.stencil_clear_value = clear_info ? clear_info->clear_value->s : 0;118};119120cl_emit(rcl, TILE_LIST_INITIAL_BLOCK_SIZE, init) {121init.use_auto_chained_tile_lists = true;122init.size_of_first_block_in_chained_tile_lists =123TILE_ALLOCATION_BLOCK_SIZE_64B;124}125126return rcl;127}128129static void130emit_frame_setup(struct v3dv_job *job,131uint32_t layer,132const union v3dv_clear_value *clear_value)133{134v3dv_return_if_oom(NULL, job);135136const struct v3dv_frame_tiling *tiling = &job->frame_tiling;137138struct v3dv_cl *rcl = &job->rcl;139140const uint32_t tile_alloc_offset =14164 * layer * tiling->draw_tiles_x * tiling->draw_tiles_y;142cl_emit(rcl, MULTICORE_RENDERING_TILE_LIST_SET_BASE, list) {143list.address = v3dv_cl_address(job->tile_alloc, tile_alloc_offset);144}145146cl_emit(rcl, MULTICORE_RENDERING_SUPERTILE_CFG, config) {147config.number_of_bin_tile_lists = 1;148config.total_frame_width_in_tiles = tiling->draw_tiles_x;149config.total_frame_height_in_tiles = tiling->draw_tiles_y;150151config.supertile_width_in_tiles = tiling->supertile_width;152config.supertile_height_in_tiles = tiling->supertile_height;153154config.total_frame_width_in_supertiles =155tiling->frame_width_in_supertiles;156config.total_frame_height_in_supertiles =157tiling->frame_height_in_supertiles;158}159160/* Implement GFXH-1742 workaround. Also, if we are clearing we have to do161* it here.162*/163for (int i = 0; i < 2; i++) {164cl_emit(rcl, TILE_COORDINATES, coords);165cl_emit(rcl, END_OF_LOADS, end);166cl_emit(rcl, STORE_TILE_BUFFER_GENERAL, store) {167store.buffer_to_store = NONE;168}169if (clear_value && i == 0) {170cl_emit(rcl, CLEAR_TILE_BUFFERS, clear) {171clear.clear_z_stencil_buffer = true;172clear.clear_all_render_targets = true;173}174}175cl_emit(rcl, END_OF_TILE_MARKER, end);176}177178cl_emit(rcl, FLUSH_VCD_CACHE, flush);179}180181static void182emit_supertile_coordinates(struct v3dv_job *job,183struct framebuffer_data *framebuffer)184{185v3dv_return_if_oom(NULL, job);186187struct v3dv_cl *rcl = &job->rcl;188189const uint32_t min_y = framebuffer->min_y_supertile;190const uint32_t max_y = framebuffer->max_y_supertile;191const uint32_t min_x = framebuffer->min_x_supertile;192const uint32_t max_x = framebuffer->max_x_supertile;193194for (int y = min_y; y <= max_y; y++) {195for (int x = min_x; x <= max_x; x++) {196cl_emit(rcl, SUPERTILE_COORDINATES, coords) {197coords.column_number_in_supertiles = x;198coords.row_number_in_supertiles = y;199}200}201}202}203204static void205emit_linear_load(struct v3dv_cl *cl,206uint32_t buffer,207struct v3dv_bo *bo,208uint32_t offset,209uint32_t stride,210uint32_t format)211{212cl_emit(cl, LOAD_TILE_BUFFER_GENERAL, load) {213load.buffer_to_load = buffer;214load.address = v3dv_cl_address(bo, offset);215load.input_image_format = format;216load.memory_format = V3D_TILING_RASTER;217load.height_in_ub_or_stride = stride;218load.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0;219}220}221222static void223emit_linear_store(struct v3dv_cl *cl,224uint32_t buffer,225struct v3dv_bo *bo,226uint32_t offset,227uint32_t stride,228bool msaa,229uint32_t format)230{231cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) {232store.buffer_to_store = RENDER_TARGET_0;233store.address = v3dv_cl_address(bo, offset);234store.clear_buffer_being_stored = false;235store.output_image_format = format;236store.memory_format = V3D_TILING_RASTER;237store.height_in_ub_or_stride = stride;238store.decimate_mode = msaa ? V3D_DECIMATE_MODE_ALL_SAMPLES :239V3D_DECIMATE_MODE_SAMPLE_0;240}241}242243/* This chooses a tile buffer format that is appropriate for the copy operation.244* Typically, this is the image render target type, however, if we are copying245* depth/stencil to/from a buffer the hardware can't do raster loads/stores, so246* we need to load and store to/from a tile color buffer using a compatible247* color format.248*/249static uint32_t250choose_tlb_format(struct framebuffer_data *framebuffer,251VkImageAspectFlags aspect,252bool for_store,253bool is_copy_to_buffer,254bool is_copy_from_buffer)255{256if (is_copy_to_buffer || is_copy_from_buffer) {257switch (framebuffer->vk_format) {258case VK_FORMAT_D16_UNORM:259return V3D_OUTPUT_IMAGE_FORMAT_R16UI;260case VK_FORMAT_D32_SFLOAT:261return V3D_OUTPUT_IMAGE_FORMAT_R32F;262case VK_FORMAT_X8_D24_UNORM_PACK32:263return V3D_OUTPUT_IMAGE_FORMAT_RGBA8UI;264case VK_FORMAT_D24_UNORM_S8_UINT:265/* When storing the stencil aspect of a combined depth/stencil image266* to a buffer, the Vulkan spec states that the output buffer must267* have packed stencil values, so we choose an R8UI format for our268* store outputs. For the load input we still want RGBA8UI since the269* source image contains 4 channels (including the 3 channels270* containing the 24-bit depth value).271*272* When loading the stencil aspect of a combined depth/stencil image273* from a buffer, we read packed 8-bit stencil values from the buffer274* that we need to put into the LSB of the 32-bit format (the R275* channel), so we use R8UI. For the store, if we used R8UI then we276* would write 8-bit stencil values consecutively over depth channels,277* so we need to use RGBA8UI. This will write each stencil value in278* its correct position, but will overwrite depth values (channels G279* B,A) with undefined values. To fix this, we will have to restore280* the depth aspect from the Z tile buffer, which we should pre-load281* from the image before the store).282*/283if (aspect & VK_IMAGE_ASPECT_DEPTH_BIT) {284return V3D_OUTPUT_IMAGE_FORMAT_RGBA8UI;285} else {286assert(aspect & VK_IMAGE_ASPECT_STENCIL_BIT);287if (is_copy_to_buffer) {288return for_store ? V3D_OUTPUT_IMAGE_FORMAT_R8UI :289V3D_OUTPUT_IMAGE_FORMAT_RGBA8UI;290} else {291assert(is_copy_from_buffer);292return for_store ? V3D_OUTPUT_IMAGE_FORMAT_RGBA8UI :293V3D_OUTPUT_IMAGE_FORMAT_R8UI;294}295}296default: /* Color formats */297return framebuffer->format->rt_type;298break;299}300} else {301return framebuffer->format->rt_type;302}303}304305static inline bool306format_needs_rb_swap(struct v3dv_device *device,307VkFormat format)308{309const uint8_t *swizzle = v3dv_get_format_swizzle(device, format);310return swizzle[0] == PIPE_SWIZZLE_Z;311}312313static void314emit_image_load(struct v3dv_device *device,315struct v3dv_cl *cl,316struct framebuffer_data *framebuffer,317struct v3dv_image *image,318VkImageAspectFlags aspect,319uint32_t layer,320uint32_t mip_level,321bool is_copy_to_buffer,322bool is_copy_from_buffer)323{324uint32_t layer_offset = v3dv_layer_offset(image, mip_level, layer);325326/* For image to/from buffer copies we always load to and store from RT0,327* even for depth/stencil aspects, because the hardware can't do raster328* stores or loads from/to the depth/stencil tile buffers.329*/330bool load_to_color_tlb = is_copy_to_buffer || is_copy_from_buffer ||331aspect == VK_IMAGE_ASPECT_COLOR_BIT;332333const struct v3d_resource_slice *slice = &image->slices[mip_level];334cl_emit(cl, LOAD_TILE_BUFFER_GENERAL, load) {335load.buffer_to_load = load_to_color_tlb ?336RENDER_TARGET_0 : v3dX(zs_buffer_from_aspect_bits)(aspect);337338load.address = v3dv_cl_address(image->mem->bo, layer_offset);339340load.input_image_format = choose_tlb_format(framebuffer, aspect, false,341is_copy_to_buffer,342is_copy_from_buffer);343load.memory_format = slice->tiling;344345/* When copying depth/stencil images to a buffer, for D24 formats Vulkan346* expects the depth value in the LSB bits of each 32-bit pixel.347* Unfortunately, the hardware seems to put the S8/X8 bits there and the348* depth bits on the MSB. To work around that we can reverse the channel349* order and then swap the R/B channels to get what we want.350*351* NOTE: reversing and swapping only gets us the behavior we want if the352* operations happen in that exact order, which seems to be the case when353* done on the tile buffer load operations. On the store, it seems the354* order is not the same. The order on the store is probably reversed so355* that reversing and swapping on both the load and the store preserves356* the original order of the channels in memory.357*358* Notice that we only need to do this when copying to a buffer, where359* depth and stencil aspects are copied as separate regions and360* the spec expects them to be tightly packed.361*/362bool needs_rb_swap = false;363bool needs_chan_reverse = false;364if (is_copy_to_buffer &&365(framebuffer->vk_format == VK_FORMAT_X8_D24_UNORM_PACK32 ||366(framebuffer->vk_format == VK_FORMAT_D24_UNORM_S8_UINT &&367(aspect & VK_IMAGE_ASPECT_DEPTH_BIT)))) {368needs_rb_swap = true;369needs_chan_reverse = true;370} else if (!is_copy_from_buffer && !is_copy_to_buffer &&371(aspect & VK_IMAGE_ASPECT_COLOR_BIT)) {372/* This is not a raw data copy (i.e. we are clearing the image),373* so we need to make sure we respect the format swizzle.374*/375needs_rb_swap = format_needs_rb_swap(device, framebuffer->vk_format);376}377378load.r_b_swap = needs_rb_swap;379load.channel_reverse = needs_chan_reverse;380381if (slice->tiling == V3D_TILING_UIF_NO_XOR ||382slice->tiling == V3D_TILING_UIF_XOR) {383load.height_in_ub_or_stride =384slice->padded_height_of_output_image_in_uif_blocks;385} else if (slice->tiling == V3D_TILING_RASTER) {386load.height_in_ub_or_stride = slice->stride;387}388389if (image->samples > VK_SAMPLE_COUNT_1_BIT)390load.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES;391else392load.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0;393}394}395396static void397emit_image_store(struct v3dv_device *device,398struct v3dv_cl *cl,399struct framebuffer_data *framebuffer,400struct v3dv_image *image,401VkImageAspectFlags aspect,402uint32_t layer,403uint32_t mip_level,404bool is_copy_to_buffer,405bool is_copy_from_buffer,406bool is_multisample_resolve)407{408uint32_t layer_offset = v3dv_layer_offset(image, mip_level, layer);409410bool store_from_color_tlb = is_copy_to_buffer || is_copy_from_buffer ||411aspect == VK_IMAGE_ASPECT_COLOR_BIT;412413const struct v3d_resource_slice *slice = &image->slices[mip_level];414cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) {415store.buffer_to_store = store_from_color_tlb ?416RENDER_TARGET_0 : v3dX(zs_buffer_from_aspect_bits)(aspect);417418store.address = v3dv_cl_address(image->mem->bo, layer_offset);419store.clear_buffer_being_stored = false;420421/* See rationale in emit_image_load() */422bool needs_rb_swap = false;423bool needs_chan_reverse = false;424if (is_copy_from_buffer &&425(framebuffer->vk_format == VK_FORMAT_X8_D24_UNORM_PACK32 ||426(framebuffer->vk_format == VK_FORMAT_D24_UNORM_S8_UINT &&427(aspect & VK_IMAGE_ASPECT_DEPTH_BIT)))) {428needs_rb_swap = true;429needs_chan_reverse = true;430} else if (!is_copy_from_buffer && !is_copy_to_buffer &&431(aspect & VK_IMAGE_ASPECT_COLOR_BIT)) {432needs_rb_swap = format_needs_rb_swap(device, framebuffer->vk_format);433}434435store.r_b_swap = needs_rb_swap;436store.channel_reverse = needs_chan_reverse;437438store.output_image_format = choose_tlb_format(framebuffer, aspect, true,439is_copy_to_buffer,440is_copy_from_buffer);441store.memory_format = slice->tiling;442if (slice->tiling == V3D_TILING_UIF_NO_XOR ||443slice->tiling == V3D_TILING_UIF_XOR) {444store.height_in_ub_or_stride =445slice->padded_height_of_output_image_in_uif_blocks;446} else if (slice->tiling == V3D_TILING_RASTER) {447store.height_in_ub_or_stride = slice->stride;448}449450if (image->samples > VK_SAMPLE_COUNT_1_BIT)451store.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES;452else if (is_multisample_resolve)453store.decimate_mode = V3D_DECIMATE_MODE_4X;454else455store.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0;456}457}458459static void460emit_copy_layer_to_buffer_per_tile_list(struct v3dv_job *job,461struct framebuffer_data *framebuffer,462struct v3dv_buffer *buffer,463struct v3dv_image *image,464uint32_t layer_offset,465const VkBufferImageCopy2KHR *region)466{467struct v3dv_cl *cl = &job->indirect;468v3dv_cl_ensure_space(cl, 200, 1);469v3dv_return_if_oom(NULL, job);470471struct v3dv_cl_reloc tile_list_start = v3dv_cl_get_address(cl);472473cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);474475/* Load image to TLB */476assert((image->type != VK_IMAGE_TYPE_3D &&477layer_offset < region->imageSubresource.layerCount) ||478layer_offset < image->extent.depth);479480const uint32_t image_layer = image->type != VK_IMAGE_TYPE_3D ?481region->imageSubresource.baseArrayLayer + layer_offset :482region->imageOffset.z + layer_offset;483484emit_image_load(job->device, cl, framebuffer, image,485region->imageSubresource.aspectMask,486image_layer,487region->imageSubresource.mipLevel,488true, false);489490cl_emit(cl, END_OF_LOADS, end);491492cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch);493494/* Store TLB to buffer */495uint32_t width, height;496if (region->bufferRowLength == 0)497width = region->imageExtent.width;498else499width = region->bufferRowLength;500501if (region->bufferImageHeight == 0)502height = region->imageExtent.height;503else504height = region->bufferImageHeight;505506/* Handle copy from compressed format */507width = DIV_ROUND_UP(width, vk_format_get_blockwidth(image->vk_format));508height = DIV_ROUND_UP(height, vk_format_get_blockheight(image->vk_format));509510/* If we are storing stencil from a combined depth/stencil format the511* Vulkan spec states that the output buffer must have packed stencil512* values, where each stencil value is 1 byte.513*/514uint32_t cpp =515region->imageSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT ?5161 : image->cpp;517uint32_t buffer_stride = width * cpp;518uint32_t buffer_offset = buffer->mem_offset + region->bufferOffset +519height * buffer_stride * layer_offset;520521uint32_t format = choose_tlb_format(framebuffer,522region->imageSubresource.aspectMask,523true, true, false);524bool msaa = image->samples > VK_SAMPLE_COUNT_1_BIT;525526emit_linear_store(cl, RENDER_TARGET_0, buffer->mem->bo,527buffer_offset, buffer_stride, msaa, format);528529cl_emit(cl, END_OF_TILE_MARKER, end);530531cl_emit(cl, RETURN_FROM_SUB_LIST, ret);532533cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) {534branch.start = tile_list_start;535branch.end = v3dv_cl_get_address(cl);536}537}538539static void540emit_copy_layer_to_buffer(struct v3dv_job *job,541struct v3dv_buffer *buffer,542struct v3dv_image *image,543struct framebuffer_data *framebuffer,544uint32_t layer,545const VkBufferImageCopy2KHR *region)546{547emit_frame_setup(job, layer, NULL);548emit_copy_layer_to_buffer_per_tile_list(job, framebuffer, buffer,549image, layer, region);550emit_supertile_coordinates(job, framebuffer);551}552553void554v3dX(job_emit_copy_image_to_buffer_rcl)(struct v3dv_job *job,555struct v3dv_buffer *buffer,556struct v3dv_image *image,557struct framebuffer_data *framebuffer,558const VkBufferImageCopy2KHR *region)559{560struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL);561v3dv_return_if_oom(NULL, job);562563for (int layer = 0; layer < job->frame_tiling.layers; layer++)564emit_copy_layer_to_buffer(job, buffer, image, framebuffer, layer, region);565cl_emit(rcl, END_OF_RENDERING, end);566}567568static void569emit_resolve_image_layer_per_tile_list(struct v3dv_job *job,570struct framebuffer_data *framebuffer,571struct v3dv_image *dst,572struct v3dv_image *src,573uint32_t layer_offset,574const VkImageResolve2KHR *region)575{576struct v3dv_cl *cl = &job->indirect;577v3dv_cl_ensure_space(cl, 200, 1);578v3dv_return_if_oom(NULL, job);579580struct v3dv_cl_reloc tile_list_start = v3dv_cl_get_address(cl);581582cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);583584assert((src->type != VK_IMAGE_TYPE_3D &&585layer_offset < region->srcSubresource.layerCount) ||586layer_offset < src->extent.depth);587588const uint32_t src_layer = src->type != VK_IMAGE_TYPE_3D ?589region->srcSubresource.baseArrayLayer + layer_offset :590region->srcOffset.z + layer_offset;591592emit_image_load(job->device, cl, framebuffer, src,593region->srcSubresource.aspectMask,594src_layer,595region->srcSubresource.mipLevel,596false, false);597598cl_emit(cl, END_OF_LOADS, end);599600cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch);601602assert((dst->type != VK_IMAGE_TYPE_3D &&603layer_offset < region->dstSubresource.layerCount) ||604layer_offset < dst->extent.depth);605606const uint32_t dst_layer = dst->type != VK_IMAGE_TYPE_3D ?607region->dstSubresource.baseArrayLayer + layer_offset :608region->dstOffset.z + layer_offset;609610emit_image_store(job->device, cl, framebuffer, dst,611region->dstSubresource.aspectMask,612dst_layer,613region->dstSubresource.mipLevel,614false, false, true);615616cl_emit(cl, END_OF_TILE_MARKER, end);617618cl_emit(cl, RETURN_FROM_SUB_LIST, ret);619620cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) {621branch.start = tile_list_start;622branch.end = v3dv_cl_get_address(cl);623}624}625626static void627emit_resolve_image_layer(struct v3dv_job *job,628struct v3dv_image *dst,629struct v3dv_image *src,630struct framebuffer_data *framebuffer,631uint32_t layer,632const VkImageResolve2KHR *region)633{634emit_frame_setup(job, layer, NULL);635emit_resolve_image_layer_per_tile_list(job, framebuffer,636dst, src, layer, region);637emit_supertile_coordinates(job, framebuffer);638}639640void641v3dX(job_emit_resolve_image_rcl)(struct v3dv_job *job,642struct v3dv_image *dst,643struct v3dv_image *src,644struct framebuffer_data *framebuffer,645const VkImageResolve2KHR *region)646{647struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL);648v3dv_return_if_oom(NULL, job);649650for (int layer = 0; layer < job->frame_tiling.layers; layer++)651emit_resolve_image_layer(job, dst, src, framebuffer, layer, region);652cl_emit(rcl, END_OF_RENDERING, end);653}654655static void656emit_copy_buffer_per_tile_list(struct v3dv_job *job,657struct v3dv_bo *dst,658struct v3dv_bo *src,659uint32_t dst_offset,660uint32_t src_offset,661uint32_t stride,662uint32_t format)663{664struct v3dv_cl *cl = &job->indirect;665v3dv_cl_ensure_space(cl, 200, 1);666v3dv_return_if_oom(NULL, job);667668struct v3dv_cl_reloc tile_list_start = v3dv_cl_get_address(cl);669670cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);671672emit_linear_load(cl, RENDER_TARGET_0, src, src_offset, stride, format);673674cl_emit(cl, END_OF_LOADS, end);675676cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch);677678emit_linear_store(cl, RENDER_TARGET_0,679dst, dst_offset, stride, false, format);680681cl_emit(cl, END_OF_TILE_MARKER, end);682683cl_emit(cl, RETURN_FROM_SUB_LIST, ret);684685cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) {686branch.start = tile_list_start;687branch.end = v3dv_cl_get_address(cl);688}689}690691void692v3dX(job_emit_copy_buffer)(struct v3dv_job *job,693struct v3dv_bo *dst,694struct v3dv_bo *src,695uint32_t dst_offset,696uint32_t src_offset,697struct framebuffer_data *framebuffer,698uint32_t format,699uint32_t item_size)700{701const uint32_t stride = job->frame_tiling.width * item_size;702emit_copy_buffer_per_tile_list(job, dst, src,703dst_offset, src_offset,704stride, format);705emit_supertile_coordinates(job, framebuffer);706}707708void709v3dX(job_emit_copy_buffer_rcl)(struct v3dv_job *job,710struct v3dv_bo *dst,711struct v3dv_bo *src,712uint32_t dst_offset,713uint32_t src_offset,714struct framebuffer_data *framebuffer,715uint32_t format,716uint32_t item_size)717{718struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL);719v3dv_return_if_oom(NULL, job);720721emit_frame_setup(job, 0, NULL);722723v3dX(job_emit_copy_buffer)(job, dst, src, dst_offset, src_offset,724framebuffer, format, item_size);725726cl_emit(rcl, END_OF_RENDERING, end);727}728729static void730emit_copy_image_layer_per_tile_list(struct v3dv_job *job,731struct framebuffer_data *framebuffer,732struct v3dv_image *dst,733struct v3dv_image *src,734uint32_t layer_offset,735const VkImageCopy2KHR *region)736{737struct v3dv_cl *cl = &job->indirect;738v3dv_cl_ensure_space(cl, 200, 1);739v3dv_return_if_oom(NULL, job);740741struct v3dv_cl_reloc tile_list_start = v3dv_cl_get_address(cl);742743cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);744745assert((src->type != VK_IMAGE_TYPE_3D &&746layer_offset < region->srcSubresource.layerCount) ||747layer_offset < src->extent.depth);748749const uint32_t src_layer = src->type != VK_IMAGE_TYPE_3D ?750region->srcSubresource.baseArrayLayer + layer_offset :751region->srcOffset.z + layer_offset;752753emit_image_load(job->device, cl, framebuffer, src,754region->srcSubresource.aspectMask,755src_layer,756region->srcSubresource.mipLevel,757false, false);758759cl_emit(cl, END_OF_LOADS, end);760761cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch);762763assert((dst->type != VK_IMAGE_TYPE_3D &&764layer_offset < region->dstSubresource.layerCount) ||765layer_offset < dst->extent.depth);766767const uint32_t dst_layer = dst->type != VK_IMAGE_TYPE_3D ?768region->dstSubresource.baseArrayLayer + layer_offset :769region->dstOffset.z + layer_offset;770771emit_image_store(job->device, cl, framebuffer, dst,772region->dstSubresource.aspectMask,773dst_layer,774region->dstSubresource.mipLevel,775false, false, false);776777cl_emit(cl, END_OF_TILE_MARKER, end);778779cl_emit(cl, RETURN_FROM_SUB_LIST, ret);780781cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) {782branch.start = tile_list_start;783branch.end = v3dv_cl_get_address(cl);784}785}786787static void788emit_copy_image_layer(struct v3dv_job *job,789struct v3dv_image *dst,790struct v3dv_image *src,791struct framebuffer_data *framebuffer,792uint32_t layer,793const VkImageCopy2KHR *region)794{795emit_frame_setup(job, layer, NULL);796emit_copy_image_layer_per_tile_list(job, framebuffer, dst, src, layer, region);797emit_supertile_coordinates(job, framebuffer);798}799800void801v3dX(job_emit_copy_image_rcl)(struct v3dv_job *job,802struct v3dv_image *dst,803struct v3dv_image *src,804struct framebuffer_data *framebuffer,805const VkImageCopy2KHR *region)806{807struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL);808v3dv_return_if_oom(NULL, job);809810for (int layer = 0; layer < job->frame_tiling.layers; layer++)811emit_copy_image_layer(job, dst, src, framebuffer, layer, region);812cl_emit(rcl, END_OF_RENDERING, end);813}814815void816v3dX(cmd_buffer_emit_tfu_job)(struct v3dv_cmd_buffer *cmd_buffer,817struct v3dv_image *dst,818uint32_t dst_mip_level,819uint32_t dst_layer,820struct v3dv_image *src,821uint32_t src_mip_level,822uint32_t src_layer,823uint32_t width,824uint32_t height,825const struct v3dv_format *format)826{827const struct v3d_resource_slice *src_slice = &src->slices[src_mip_level];828const struct v3d_resource_slice *dst_slice = &dst->slices[dst_mip_level];829830assert(dst->mem && dst->mem->bo);831const struct v3dv_bo *dst_bo = dst->mem->bo;832833assert(src->mem && src->mem->bo);834const struct v3dv_bo *src_bo = src->mem->bo;835836struct drm_v3d_submit_tfu tfu = {837.ios = (height << 16) | width,838.bo_handles = {839dst_bo->handle,840src_bo->handle != dst_bo->handle ? src_bo->handle : 0841},842};843844const uint32_t src_offset =845src_bo->offset + v3dv_layer_offset(src, src_mip_level, src_layer);846tfu.iia |= src_offset;847848uint32_t icfg;849if (src_slice->tiling == V3D_TILING_RASTER) {850icfg = V3D_TFU_ICFG_FORMAT_RASTER;851} else {852icfg = V3D_TFU_ICFG_FORMAT_LINEARTILE +853(src_slice->tiling - V3D_TILING_LINEARTILE);854}855tfu.icfg |= icfg << V3D_TFU_ICFG_FORMAT_SHIFT;856857const uint32_t dst_offset =858dst_bo->offset + v3dv_layer_offset(dst, dst_mip_level, dst_layer);859tfu.ioa |= dst_offset;860861tfu.ioa |= (V3D_TFU_IOA_FORMAT_LINEARTILE +862(dst_slice->tiling - V3D_TILING_LINEARTILE)) <<863V3D_TFU_IOA_FORMAT_SHIFT;864tfu.icfg |= format->tex_type << V3D_TFU_ICFG_TTYPE_SHIFT;865866switch (src_slice->tiling) {867case V3D_TILING_UIF_NO_XOR:868case V3D_TILING_UIF_XOR:869tfu.iis |= src_slice->padded_height / (2 * v3d_utile_height(src->cpp));870break;871case V3D_TILING_RASTER:872tfu.iis |= src_slice->stride / src->cpp;873break;874default:875break;876}877878/* If we're writing level 0 (!IOA_DIMTW), then we need to supply the879* OPAD field for the destination (how many extra UIF blocks beyond880* those necessary to cover the height).881*/882if (dst_slice->tiling == V3D_TILING_UIF_NO_XOR ||883dst_slice->tiling == V3D_TILING_UIF_XOR) {884uint32_t uif_block_h = 2 * v3d_utile_height(dst->cpp);885uint32_t implicit_padded_height = align(height, uif_block_h);886uint32_t icfg =887(dst_slice->padded_height - implicit_padded_height) / uif_block_h;888tfu.icfg |= icfg << V3D_TFU_ICFG_OPAD_SHIFT;889}890891v3dv_cmd_buffer_add_tfu_job(cmd_buffer, &tfu);892}893894static void895emit_clear_image_per_tile_list(struct v3dv_job *job,896struct framebuffer_data *framebuffer,897struct v3dv_image *image,898VkImageAspectFlags aspects,899uint32_t layer,900uint32_t level)901{902struct v3dv_cl *cl = &job->indirect;903v3dv_cl_ensure_space(cl, 200, 1);904v3dv_return_if_oom(NULL, job);905906struct v3dv_cl_reloc tile_list_start = v3dv_cl_get_address(cl);907908cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);909910cl_emit(cl, END_OF_LOADS, end);911912cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch);913914emit_image_store(job->device, cl, framebuffer, image, aspects,915layer, level, false, false, false);916917cl_emit(cl, END_OF_TILE_MARKER, end);918919cl_emit(cl, RETURN_FROM_SUB_LIST, ret);920921cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) {922branch.start = tile_list_start;923branch.end = v3dv_cl_get_address(cl);924}925}926927static void928emit_clear_image(struct v3dv_job *job,929struct v3dv_image *image,930struct framebuffer_data *framebuffer,931VkImageAspectFlags aspects,932uint32_t layer,933uint32_t level)934{935emit_clear_image_per_tile_list(job, framebuffer, image, aspects, layer, level);936emit_supertile_coordinates(job, framebuffer);937}938939void940v3dX(job_emit_clear_image_rcl)(struct v3dv_job *job,941struct v3dv_image *image,942struct framebuffer_data *framebuffer,943const union v3dv_clear_value *clear_value,944VkImageAspectFlags aspects,945uint32_t layer,946uint32_t level)947{948const struct rcl_clear_info clear_info = {949.clear_value = clear_value,950.image = image,951.aspects = aspects,952.layer = layer,953.level = level,954};955956struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, &clear_info);957v3dv_return_if_oom(NULL, job);958959emit_frame_setup(job, 0, clear_value);960emit_clear_image(job, image, framebuffer, aspects, layer, level);961cl_emit(rcl, END_OF_RENDERING, end);962}963964static void965emit_fill_buffer_per_tile_list(struct v3dv_job *job,966struct v3dv_bo *bo,967uint32_t offset,968uint32_t stride)969{970struct v3dv_cl *cl = &job->indirect;971v3dv_cl_ensure_space(cl, 200, 1);972v3dv_return_if_oom(NULL, job);973974struct v3dv_cl_reloc tile_list_start = v3dv_cl_get_address(cl);975976cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);977978cl_emit(cl, END_OF_LOADS, end);979980cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch);981982emit_linear_store(cl, RENDER_TARGET_0, bo, offset, stride, false,983V3D_OUTPUT_IMAGE_FORMAT_RGBA8UI);984985cl_emit(cl, END_OF_TILE_MARKER, end);986987cl_emit(cl, RETURN_FROM_SUB_LIST, ret);988989cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) {990branch.start = tile_list_start;991branch.end = v3dv_cl_get_address(cl);992}993}994995static void996emit_fill_buffer(struct v3dv_job *job,997struct v3dv_bo *bo,998uint32_t offset,999struct framebuffer_data *framebuffer)1000{1001const uint32_t stride = job->frame_tiling.width * 4;1002emit_fill_buffer_per_tile_list(job, bo, offset, stride);1003emit_supertile_coordinates(job, framebuffer);1004}10051006void1007v3dX(job_emit_fill_buffer_rcl)(struct v3dv_job *job,1008struct v3dv_bo *bo,1009uint32_t offset,1010struct framebuffer_data *framebuffer,1011uint32_t data)1012{1013const union v3dv_clear_value clear_value = {1014.color = { data, 0, 0, 0 },1015};10161017const struct rcl_clear_info clear_info = {1018.clear_value = &clear_value,1019.image = NULL,1020.aspects = VK_IMAGE_ASPECT_COLOR_BIT,1021.layer = 0,1022.level = 0,1023};10241025struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, &clear_info);1026v3dv_return_if_oom(NULL, job);10271028emit_frame_setup(job, 0, &clear_value);1029emit_fill_buffer(job, bo, offset, framebuffer);1030cl_emit(rcl, END_OF_RENDERING, end);1031}103210331034static void1035emit_copy_buffer_to_layer_per_tile_list(struct v3dv_job *job,1036struct framebuffer_data *framebuffer,1037struct v3dv_image *image,1038struct v3dv_buffer *buffer,1039uint32_t layer,1040const VkBufferImageCopy2KHR *region)1041{1042struct v3dv_cl *cl = &job->indirect;1043v3dv_cl_ensure_space(cl, 200, 1);1044v3dv_return_if_oom(NULL, job);10451046struct v3dv_cl_reloc tile_list_start = v3dv_cl_get_address(cl);10471048cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);10491050const VkImageSubresourceLayers *imgrsc = ®ion->imageSubresource;1051assert((image->type != VK_IMAGE_TYPE_3D && layer < imgrsc->layerCount) ||1052layer < image->extent.depth);10531054/* Load TLB from buffer */1055uint32_t width, height;1056if (region->bufferRowLength == 0)1057width = region->imageExtent.width;1058else1059width = region->bufferRowLength;10601061if (region->bufferImageHeight == 0)1062height = region->imageExtent.height;1063else1064height = region->bufferImageHeight;10651066/* Handle copy to compressed format using a compatible format */1067width = DIV_ROUND_UP(width, vk_format_get_blockwidth(image->vk_format));1068height = DIV_ROUND_UP(height, vk_format_get_blockheight(image->vk_format));10691070uint32_t cpp = imgrsc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT ?10711 : image->cpp;1072uint32_t buffer_stride = width * cpp;1073uint32_t buffer_offset =1074buffer->mem_offset + region->bufferOffset + height * buffer_stride * layer;10751076uint32_t format = choose_tlb_format(framebuffer, imgrsc->aspectMask,1077false, false, true);10781079emit_linear_load(cl, RENDER_TARGET_0, buffer->mem->bo,1080buffer_offset, buffer_stride, format);10811082/* Because we can't do raster loads/stores of Z/S formats we need to1083* use a color tile buffer with a compatible RGBA color format instead.1084* However, when we are uploading a single aspect to a combined1085* depth/stencil image we have the problem that our tile buffer stores don't1086* allow us to mask out the other aspect, so we always write all four RGBA1087* channels to the image and we end up overwriting that other aspect with1088* undefined values. To work around that, we first load the aspect we are1089* not copying from the image memory into a proper Z/S tile buffer. Then we1090* do our store from the color buffer for the aspect we are copying, and1091* after that, we do another store from the Z/S tile buffer to restore the1092* other aspect to its original value.1093*/1094if (framebuffer->vk_format == VK_FORMAT_D24_UNORM_S8_UINT) {1095if (imgrsc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {1096emit_image_load(job->device, cl, framebuffer, image,1097VK_IMAGE_ASPECT_STENCIL_BIT,1098imgrsc->baseArrayLayer + layer, imgrsc->mipLevel,1099false, false);1100} else {1101assert(imgrsc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT);1102emit_image_load(job->device, cl, framebuffer, image,1103VK_IMAGE_ASPECT_DEPTH_BIT,1104imgrsc->baseArrayLayer + layer, imgrsc->mipLevel,1105false, false);1106}1107}11081109cl_emit(cl, END_OF_LOADS, end);11101111cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch);11121113/* Store TLB to image */1114emit_image_store(job->device, cl, framebuffer, image, imgrsc->aspectMask,1115imgrsc->baseArrayLayer + layer, imgrsc->mipLevel,1116false, true, false);11171118if (framebuffer->vk_format == VK_FORMAT_D24_UNORM_S8_UINT) {1119if (imgrsc->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {1120emit_image_store(job->device, cl, framebuffer, image,1121VK_IMAGE_ASPECT_STENCIL_BIT,1122imgrsc->baseArrayLayer + layer, imgrsc->mipLevel,1123false, false, false);1124} else {1125assert(imgrsc->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT);1126emit_image_store(job->device, cl, framebuffer, image,1127VK_IMAGE_ASPECT_DEPTH_BIT,1128imgrsc->baseArrayLayer + layer, imgrsc->mipLevel,1129false, false, false);1130}1131}11321133cl_emit(cl, END_OF_TILE_MARKER, end);11341135cl_emit(cl, RETURN_FROM_SUB_LIST, ret);11361137cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) {1138branch.start = tile_list_start;1139branch.end = v3dv_cl_get_address(cl);1140}1141}11421143static void1144emit_copy_buffer_to_layer(struct v3dv_job *job,1145struct v3dv_image *image,1146struct v3dv_buffer *buffer,1147struct framebuffer_data *framebuffer,1148uint32_t layer,1149const VkBufferImageCopy2KHR *region)1150{1151emit_frame_setup(job, layer, NULL);1152emit_copy_buffer_to_layer_per_tile_list(job, framebuffer, image, buffer,1153layer, region);1154emit_supertile_coordinates(job, framebuffer);1155}11561157void1158v3dX(job_emit_copy_buffer_to_image_rcl)(struct v3dv_job *job,1159struct v3dv_image *image,1160struct v3dv_buffer *buffer,1161struct framebuffer_data *framebuffer,1162const VkBufferImageCopy2KHR *region)1163{1164struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL);1165v3dv_return_if_oom(NULL, job);11661167for (int layer = 0; layer < job->frame_tiling.layers; layer++)1168emit_copy_buffer_to_layer(job, image, buffer, framebuffer, layer, region);1169cl_emit(rcl, END_OF_RENDERING, end);1170}11711172/* Figure out a TLB size configuration for a number of pixels to process.1173* Beware that we can't "render" more than 4096x4096 pixels in a single job,1174* if the pixel count is larger than this, the caller might need to split1175* the job and call this function multiple times.1176*/1177static void1178framebuffer_size_for_pixel_count(uint32_t num_pixels,1179uint32_t *width,1180uint32_t *height)1181{1182assert(num_pixels > 0);11831184const uint32_t max_dim_pixels = 4096;1185const uint32_t max_pixels = max_dim_pixels * max_dim_pixels;11861187uint32_t w, h;1188if (num_pixels > max_pixels) {1189w = max_dim_pixels;1190h = max_dim_pixels;1191} else {1192w = num_pixels;1193h = 1;1194while (w > max_dim_pixels || ((w % 2) == 0 && w > 2 * h)) {1195w >>= 1;1196h <<= 1;1197}1198}1199assert(w <= max_dim_pixels && h <= max_dim_pixels);1200assert(w * h <= num_pixels);1201assert(w > 0 && h > 0);12021203*width = w;1204*height = h;1205}12061207struct v3dv_job *1208v3dX(cmd_buffer_copy_buffer)(struct v3dv_cmd_buffer *cmd_buffer,1209struct v3dv_bo *dst,1210uint32_t dst_offset,1211struct v3dv_bo *src,1212uint32_t src_offset,1213const VkBufferCopy2KHR *region)1214{1215const uint32_t internal_bpp = V3D_INTERNAL_BPP_32;1216const uint32_t internal_type = V3D_INTERNAL_TYPE_8UI;12171218/* Select appropriate pixel format for the copy operation based on the1219* size to copy and the alignment of the source and destination offsets.1220*/1221src_offset += region->srcOffset;1222dst_offset += region->dstOffset;1223uint32_t item_size = 4;1224while (item_size > 1 &&1225(src_offset % item_size != 0 || dst_offset % item_size != 0)) {1226item_size /= 2;1227}12281229while (item_size > 1 && region->size % item_size != 0)1230item_size /= 2;12311232assert(region->size % item_size == 0);1233uint32_t num_items = region->size / item_size;1234assert(num_items > 0);12351236uint32_t format;1237VkFormat vk_format;1238switch (item_size) {1239case 4:1240format = V3D_OUTPUT_IMAGE_FORMAT_RGBA8UI;1241vk_format = VK_FORMAT_R8G8B8A8_UINT;1242break;1243case 2:1244format = V3D_OUTPUT_IMAGE_FORMAT_RG8UI;1245vk_format = VK_FORMAT_R8G8_UINT;1246break;1247default:1248format = V3D_OUTPUT_IMAGE_FORMAT_R8UI;1249vk_format = VK_FORMAT_R8_UINT;1250break;1251}12521253struct v3dv_job *job = NULL;1254while (num_items > 0) {1255job = v3dv_cmd_buffer_start_job(cmd_buffer, -1, V3DV_JOB_TYPE_GPU_CL);1256if (!job)1257return NULL;12581259uint32_t width, height;1260framebuffer_size_for_pixel_count(num_items, &width, &height);12611262v3dv_job_start_frame(job, width, height, 1, 1, internal_bpp, false);12631264struct framebuffer_data framebuffer;1265v3dX(setup_framebuffer_data)(&framebuffer, vk_format, internal_type,1266&job->frame_tiling);12671268v3dX(job_emit_binning_flush)(job);12691270v3dX(job_emit_copy_buffer_rcl)(job, dst, src, dst_offset, src_offset,1271&framebuffer, format, item_size);12721273v3dv_cmd_buffer_finish_job(cmd_buffer);12741275const uint32_t items_copied = width * height;1276const uint32_t bytes_copied = items_copied * item_size;1277num_items -= items_copied;1278src_offset += bytes_copied;1279dst_offset += bytes_copied;1280}12811282return job;1283}12841285void1286v3dX(cmd_buffer_fill_buffer)(struct v3dv_cmd_buffer *cmd_buffer,1287struct v3dv_bo *bo,1288uint32_t offset,1289uint32_t size,1290uint32_t data)1291{1292assert(size > 0 && size % 4 == 0);1293assert(offset + size <= bo->size);12941295const uint32_t internal_bpp = V3D_INTERNAL_BPP_32;1296const uint32_t internal_type = V3D_INTERNAL_TYPE_8UI;1297uint32_t num_items = size / 4;12981299while (num_items > 0) {1300struct v3dv_job *job =1301v3dv_cmd_buffer_start_job(cmd_buffer, -1, V3DV_JOB_TYPE_GPU_CL);1302if (!job)1303return;13041305uint32_t width, height;1306framebuffer_size_for_pixel_count(num_items, &width, &height);13071308v3dv_job_start_frame(job, width, height, 1, 1, internal_bpp, false);13091310struct framebuffer_data framebuffer;1311v3dX(setup_framebuffer_data)(&framebuffer, VK_FORMAT_R8G8B8A8_UINT,1312internal_type, &job->frame_tiling);13131314v3dX(job_emit_binning_flush)(job);13151316v3dX(job_emit_fill_buffer_rcl)(job, bo, offset, &framebuffer, data);13171318v3dv_cmd_buffer_finish_job(cmd_buffer);13191320const uint32_t items_copied = width * height;1321const uint32_t bytes_copied = items_copied * 4;1322num_items -= items_copied;1323offset += bytes_copied;1324}1325}13261327void1328v3dX(setup_framebuffer_data)(struct framebuffer_data *fb,1329VkFormat vk_format,1330uint32_t internal_type,1331const struct v3dv_frame_tiling *tiling)1332{1333fb->internal_type = internal_type;13341335/* Supertile coverage always starts at 0,0 */1336uint32_t supertile_w_in_pixels =1337tiling->tile_width * tiling->supertile_width;1338uint32_t supertile_h_in_pixels =1339tiling->tile_height * tiling->supertile_height;13401341fb->min_x_supertile = 0;1342fb->min_y_supertile = 0;1343fb->max_x_supertile = (tiling->width - 1) / supertile_w_in_pixels;1344fb->max_y_supertile = (tiling->height - 1) / supertile_h_in_pixels;13451346fb->vk_format = vk_format;1347fb->format = v3dX(get_format)(vk_format);13481349fb->internal_depth_type = V3D_INTERNAL_TYPE_DEPTH_32F;1350if (vk_format_is_depth_or_stencil(vk_format))1351fb->internal_depth_type = v3dX(get_internal_depth_type)(vk_format);1352}135313541355