diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index d6b667fa4e8..28b8a08a3fa 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -293,24 +293,99 @@ cmd_buffer_can_merge_subpass(struct v3dv_cmd_buffer *cmd_buffer) return true; } +/** + * Computes and sets the job frame tiling information required to setup frame + * binning and rendering. + */ +static struct v3dv_frame_tiling * +job_compute_frame_tiling(struct v3dv_job *job, + uint32_t width, + uint32_t height, + uint32_t layers, + uint32_t render_target_count, + uint8_t max_internal_bpp) +{ + static const uint8_t tile_sizes[] = { + 64, 64, + 64, 32, + 32, 32, + 32, 16, + 16, 16, + }; + + assert(job); + struct v3dv_frame_tiling *tiling = &job->frame_tiling; + + tiling->width = width; + tiling->height = height; + tiling->layers = layers; + tiling->render_target_count = render_target_count; + + uint32_t tile_size_index = 0; + + /* FIXME: MSAA */ + + if (render_target_count > 2) + tile_size_index += 2; + else if (render_target_count > 1) + tile_size_index += 1; + + tiling->internal_bpp = max_internal_bpp; + tile_size_index += tiling->internal_bpp; + assert(tile_size_index < ARRAY_SIZE(tile_sizes)); + + tiling->tile_width = tile_sizes[tile_size_index * 2]; + tiling->tile_height = tile_sizes[tile_size_index * 2 + 1]; + + tiling->draw_tiles_x = DIV_ROUND_UP(width, tiling->tile_width); + tiling->draw_tiles_y = DIV_ROUND_UP(height, tiling->tile_height); + + /* Size up our supertiles until we get under the limit */ + const uint32_t max_supertiles = 256; + tiling->supertile_width = 1; + tiling->supertile_height = 1; + for (;;) { + tiling->frame_width_in_supertiles = + DIV_ROUND_UP(tiling->draw_tiles_x, tiling->supertile_width); + tiling->frame_height_in_supertiles = + DIV_ROUND_UP(tiling->draw_tiles_y, tiling->supertile_height); + const uint32_t num_supertiles = tiling->frame_width_in_supertiles * + tiling->frame_height_in_supertiles; + if (num_supertiles < max_supertiles) + break; + + if (tiling->supertile_width < tiling->supertile_height) + tiling->supertile_width++; + else + tiling->supertile_height++; + } + + return tiling; +} + void v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer, - const struct v3dv_framebuffer *framebuffer, - const struct v3dv_frame_tiling *tiling, - int32_t num_render_targets) + uint32_t width, + uint32_t height, + uint32_t layers, + uint32_t render_target_count, + uint8_t max_internal_bpp) { struct v3dv_job *job = cmd_buffer->state.job; assert(job); - /* Copy the frame tiling spec into the job */ - memcpy(&job->frame_tiling, tiling, sizeof(struct v3dv_frame_tiling)); + /* Start by computing frame tiling spec for this job */ + const struct v3dv_frame_tiling *tiling = + job_compute_frame_tiling(job, + width, height, layers, + render_target_count, max_internal_bpp); v3dv_cl_ensure_space_with_branch(&job->bcl, 256); /* The PTB will request the tile alloc initial size per tile at start * of tile binning. */ - uint32_t tile_alloc_size = 64 * framebuffer->layers * + uint32_t tile_alloc_size = 64 * tiling->layers * tiling->draw_tiles_x * tiling->draw_tiles_y; @@ -334,7 +409,7 @@ v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer, v3dv_job_add_bo(job, job->tile_alloc); const uint32_t tsda_per_tile_size = 256; - const uint32_t tile_state_size = framebuffer->layers * + const uint32_t tile_state_size = tiling->layers * tiling->draw_tiles_x * tiling->draw_tiles_y * tsda_per_tile_size; @@ -345,16 +420,13 @@ v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer, * required for layered framebuffers to work. */ cl_emit(&job->bcl, NUMBER_OF_LAYERS, config) { - config.number_of_layers = framebuffer->layers; + config.number_of_layers = layers; } - if (num_render_targets == -1) - num_render_targets = framebuffer->color_attachment_count; - cl_emit(&job->bcl, TILE_BINNING_MODE_CFG, config) { - config.width_in_pixels = framebuffer->width; - config.height_in_pixels = framebuffer->height; - config.number_of_render_targets = MAX2(num_render_targets, 1); + config.width_in_pixels = tiling->width; + config.height_in_pixels = tiling->height; + config.number_of_render_targets = MAX2(tiling->render_target_count, 1); config.multisample_mode_4x = false; /* FIXME */ config.maximum_bpp_of_all_render_targets = tiling->internal_bpp; } @@ -1421,12 +1493,12 @@ subpass_start(struct v3dv_cmd_buffer *cmd_buffer, uint32_t subpass_idx) const uint8_t internal_bpp = v3dv_framebuffer_compute_internal_bpp(framebuffer, subpass); - struct v3dv_frame_tiling frame_tiling; - v3dv_framebuffer_compute_tiling_params(framebuffer, subpass, internal_bpp, - &frame_tiling); - - v3dv_cmd_buffer_start_frame(cmd_buffer, framebuffer, &frame_tiling, - subpass->color_count); + v3dv_cmd_buffer_start_frame(cmd_buffer, + framebuffer->width, + framebuffer->height, + framebuffer->layers, + subpass->color_count, + internal_bpp); } /* If we don't have a scissor or viewport defined let's just use the render diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c index e5417b8ef7e..5cbbb9bfea8 100644 --- a/src/broadcom/vulkan/v3dv_device.c +++ b/src/broadcom/vulkan/v3dv_device.c @@ -1659,6 +1659,11 @@ v3dv_DestroyBuffer(VkDevice _device, vk_free2(&device->alloc, pAllocator, buffer); } +/** + * This computes the maximum bpp used by any of the render targets used by + * a particular subpass. If we don't have a subpass (when we are not inside a + * render pass), then we assume that all framebuffer attachments are used. + */ uint8_t v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer, const struct v3dv_subpass *subpass) @@ -1682,9 +1687,6 @@ v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer return max_bpp; } - /* If we are not in a render pass then we assume that all framebuffer - * attachments are used. - */ assert(framebuffer->attachment_count <= 4); for (uint32_t i = 0; i < framebuffer->attachment_count; i++) { const struct v3dv_image_view *att = framebuffer->attachments[i]; @@ -1697,65 +1699,6 @@ v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer return max_bpp; } -void -v3dv_framebuffer_compute_tiling_params(const struct v3dv_framebuffer *framebuffer, - const struct v3dv_subpass *subpass, - uint8_t internal_bpp, - struct v3dv_frame_tiling *tiling) -{ - static const uint8_t tile_sizes[] = { - 64, 64, - 64, 32, - 32, 32, - 32, 16, - 16, 16, - }; - - uint32_t tile_size_index = 0; - - /* FIXME: MSAA */ - - const uint32_t color_attachment_count = - subpass ? subpass->color_count : framebuffer->color_attachment_count; - - if (color_attachment_count > 2) - tile_size_index += 2; - else if (color_attachment_count > 1) - tile_size_index += 1; - - tiling->internal_bpp = internal_bpp; - tile_size_index += tiling->internal_bpp; - assert(tile_size_index < ARRAY_SIZE(tile_sizes)); - - tiling->tile_width = tile_sizes[tile_size_index * 2]; - tiling->tile_height = tile_sizes[tile_size_index * 2 + 1]; - - tiling->draw_tiles_x = - DIV_ROUND_UP(framebuffer->width, tiling->tile_width); - tiling->draw_tiles_y = - DIV_ROUND_UP(framebuffer->height, tiling->tile_height); - - /* Size up our supertiles until we get under the limit */ - const uint32_t max_supertiles = 256; - tiling->supertile_width = 1; - tiling->supertile_height = 1; - for (;;) { - tiling->frame_width_in_supertiles = - DIV_ROUND_UP(tiling->draw_tiles_x, tiling->supertile_width); - tiling->frame_height_in_supertiles = - DIV_ROUND_UP(tiling->draw_tiles_y, tiling->supertile_height); - const uint32_t num_supertiles = tiling->frame_width_in_supertiles * - tiling->frame_height_in_supertiles; - if (num_supertiles < max_supertiles) - break; - - if (tiling->supertile_width < tiling->supertile_height) - tiling->supertile_width++; - else - tiling->supertile_height++; - } -} - VkResult v3dv_CreateFramebuffer(VkDevice _device, const VkFramebufferCreateInfo *pCreateInfo, diff --git a/src/broadcom/vulkan/v3dv_meta_clear.c b/src/broadcom/vulkan/v3dv_meta_clear.c index 6b13f2e7d9f..9f736c81b53 100644 --- a/src/broadcom/vulkan/v3dv_meta_clear.c +++ b/src/broadcom/vulkan/v3dv_meta_clear.c @@ -262,12 +262,12 @@ emit_tlb_clear_job(struct v3dv_cmd_buffer *cmd_buffer, const uint8_t internal_bpp = v3dv_framebuffer_compute_internal_bpp(framebuffer, subpass); - struct v3dv_frame_tiling frame_tiling; - v3dv_framebuffer_compute_tiling_params(framebuffer, subpass, internal_bpp, - &frame_tiling); - - v3dv_cmd_buffer_start_frame(cmd_buffer, framebuffer, &frame_tiling, - color_attachment_count); + v3dv_cmd_buffer_start_frame(cmd_buffer, + framebuffer->width, + framebuffer->height, + framebuffer->layers, + color_attachment_count, + internal_bpp); struct v3dv_cl *rcl = &job->rcl; v3dv_cl_ensure_space_with_branch(rcl, 200 + @@ -399,13 +399,13 @@ emit_tlb_clear(struct v3dv_cmd_buffer *cmd_buffer, uint32_t base_layer, uint32_t layer_count) { - const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state; - const struct v3dv_framebuffer *framebuffer = state->framebuffer; - struct v3dv_job *job = cmd_buffer->state.job; assert(job); - /* Save a copy of the current subpass tiling spec */ + /* Save a copy of the current subpass tiling spec, since we are about to + * split the job for the clear and we will need to then resume it with the + * same specs. + */ struct v3dv_frame_tiling subpass_tiling; memcpy(&subpass_tiling, &job->frame_tiling, sizeof(subpass_tiling)); @@ -428,10 +428,14 @@ emit_tlb_clear(struct v3dv_cmd_buffer *cmd_buffer, * after the clear. */ job = v3dv_cmd_buffer_start_job(cmd_buffer, false); - uint32_t subpass_color_count = - state->pass->subpasses[state->subpass_idx].color_count; - v3dv_cmd_buffer_start_frame(cmd_buffer, framebuffer, &subpass_tiling, - subpass_color_count); + + v3dv_cmd_buffer_start_frame(cmd_buffer, + subpass_tiling.width, + subpass_tiling.height, + subpass_tiling.layers, + subpass_tiling.render_target_count, + subpass_tiling.internal_bpp); + job->is_subpass_continue = true; } diff --git a/src/broadcom/vulkan/v3dv_meta_copy.c b/src/broadcom/vulkan/v3dv_meta_copy.c index 244ed5354a2..10753adfbfd 100644 --- a/src/broadcom/vulkan/v3dv_meta_copy.c +++ b/src/broadcom/vulkan/v3dv_meta_copy.c @@ -26,71 +26,44 @@ #include "broadcom/cle/v3dx_pack.h" #include "vk_format_info.h" -/* Most "copy" operations in this file are implemented using the tile buffer - * to fill and/or copy buffers and images. To do that, we need to have some - * representation of a framebuffer that describes the layout of the render - * target and the tiling information. That information is typically represented - * in a framebuffer object but for most operations in this file we don't have - * one provided by the user, so instead we need to create one that matches - * the semantics of the copy operation we want to implement. A "real" - * framebuffer description includes references to image views (v3dv_image_view) - * and their underlying images (v3dv_image) for each attachment though, - * but here, we usually work with buffers instead of images, or we have images - * but we don't have image views, so instead of trying to use a real - * framebuffer we use a "fake" one, where we don't include attachment info - * and we simply store the internal type of the single render target we are - * copying to or filling with data. +/** + * Copy operations implemented in this file don't operate on a framebuffer + * object provided by the user, however, since most use the TLB for this, + * we still need to have some representation of the framebuffer. For the most + * part, the job's frame tiling information is enough for this, however we + * still need additional information such us the internal type of our single + * render target, so we use this auxiliary struct to pass that information + * around. */ -struct fake_framebuffer { - struct v3dv_framebuffer fb; - struct v3dv_frame_tiling tiling; +struct framebuffer_data { + /* The internal type of the single render target */ uint32_t internal_type; + + /* Supertile coverage */ uint32_t min_x_supertile; uint32_t min_y_supertile; uint32_t max_x_supertile; uint32_t max_y_supertile; }; -/* Sets framebuffer dimensions and computes tile size parameters based on the - * maximum internal bpp provided. - */ static void -setup_framebuffer_params(struct fake_framebuffer *fb, - uint32_t width, - uint32_t height, - uint32_t layer_count, - uint32_t internal_bpp, - uint32_t internal_type) +setup_framebuffer_data(struct framebuffer_data *fb, + uint32_t internal_type, + const struct v3dv_frame_tiling *tiling) { - fb->fb.width = width; - fb->fb.height = height; - fb->fb.layers = layer_count; - - /* We are only interested in the framebufer description required to compute - * the tiling setup parameters below, so we don't need real attachments, - * only the framebuffer size, the internal bpp and the number of attachments. - */ - fb->fb.attachment_count = 1; - fb->fb.color_attachment_count = 1; - - /* For simplicity, we store the internal type of the single render target - * that functions in this file need in the fake framebuffer objects so - * we don't have to pass it around everywhere. - */ fb->internal_type = internal_type; - fb->tiling.internal_bpp = MAX2(RENDER_TARGET_MAXIMUM_32BPP, internal_bpp); - v3dv_framebuffer_compute_tiling_params(&fb->fb, NULL, - fb->tiling.internal_bpp, &fb->tiling); - + /* Supertile coverage always starts at 0,0 */ uint32_t supertile_w_in_pixels = - fb->tiling.tile_width * fb->tiling.supertile_width; + tiling->tile_width * tiling->supertile_width; uint32_t supertile_h_in_pixels = - fb->tiling.tile_height * fb->tiling.supertile_height; + tiling->tile_height * tiling->supertile_height; + fb->min_x_supertile = 0; fb->min_y_supertile = 0; - fb->max_x_supertile = (fb->fb.width - 1) / supertile_w_in_pixels; - fb->max_y_supertile = (fb->fb.height - 1) / supertile_h_in_pixels; + fb->max_x_supertile = (tiling->width - 1) / supertile_w_in_pixels; + fb->max_y_supertile = (tiling->height - 1) / supertile_h_in_pixels; + } /* This chooses a tile buffer format that is appropriate for the copy operation. @@ -208,23 +181,24 @@ get_internal_type_bpp_for_image_aspects(struct v3dv_image *image, static struct v3dv_cl * emit_rcl_prologue(struct v3dv_job *job, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, const union v3dv_clear_value *clear_value, struct v3dv_image *image, VkImageAspectFlags aspects, uint32_t layer, uint32_t level) { + const struct v3dv_frame_tiling *tiling = &job->frame_tiling; + struct v3dv_cl *rcl = &job->rcl; v3dv_cl_ensure_space_with_branch(rcl, 200 + - framebuffer->fb.layers * 256 * + tiling->layers * 256 * cl_packet_length(SUPERTILE_COORDINATES)); - const struct v3dv_frame_tiling *tiling = &framebuffer->tiling; cl_emit(rcl, TILE_RENDERING_MODE_CFG_COMMON, config) { config.early_z_disable = true; - config.image_width_pixels = framebuffer->fb.width; - config.image_height_pixels = framebuffer->fb.height; + config.image_width_pixels = tiling->width; + config.image_height_pixels = tiling->height; config.number_of_render_targets = 1; config.multisample_mode_4x = false; config.maximum_bpp_of_all_render_targets = tiling->internal_bpp; @@ -240,7 +214,7 @@ emit_rcl_prologue(struct v3dv_job *job, int uif_block_height = v3d_utile_height(image->cpp) * 2; uint32_t implicit_padded_height = - align(framebuffer->fb.height, uif_block_height) / uif_block_height; + align(tiling->height, uif_block_height) / uif_block_height; if (slice->padded_height_of_output_image_in_uif_blocks - implicit_padded_height >= 15) { @@ -297,31 +271,31 @@ emit_rcl_prologue(struct v3dv_job *job, static void emit_frame_setup(struct v3dv_job *job, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, uint32_t layer, const union v3dv_clear_value *clear_value) { + const struct v3dv_frame_tiling *tiling = &job->frame_tiling; struct v3dv_cl *rcl = &job->rcl; const uint32_t tile_alloc_offset = - 64 * layer * framebuffer->tiling.draw_tiles_x * - framebuffer->tiling.draw_tiles_y; + 64 * layer * tiling->draw_tiles_x * tiling->draw_tiles_y; cl_emit(rcl, MULTICORE_RENDERING_TILE_LIST_SET_BASE, list) { list.address = v3dv_cl_address(job->tile_alloc, tile_alloc_offset); } cl_emit(rcl, MULTICORE_RENDERING_SUPERTILE_CFG, config) { config.number_of_bin_tile_lists = 1; - config.total_frame_width_in_tiles = framebuffer->tiling.draw_tiles_x; - config.total_frame_height_in_tiles = framebuffer->tiling.draw_tiles_y; + config.total_frame_width_in_tiles = tiling->draw_tiles_x; + config.total_frame_height_in_tiles = tiling->draw_tiles_y; - config.supertile_width_in_tiles = framebuffer->tiling.supertile_width; - config.supertile_height_in_tiles = framebuffer->tiling.supertile_height; + config.supertile_width_in_tiles = tiling->supertile_width; + config.supertile_height_in_tiles = tiling->supertile_height; config.total_frame_width_in_supertiles = - framebuffer->tiling.frame_width_in_supertiles; + tiling->frame_width_in_supertiles; config.total_frame_height_in_supertiles = - framebuffer->tiling.frame_height_in_supertiles; + tiling->frame_height_in_supertiles; } /* Implement GFXH-1742 workaround. Also, if we are clearing we have to do @@ -347,7 +321,7 @@ emit_frame_setup(struct v3dv_job *job, static void emit_supertile_coordinates(struct v3dv_job *job, - struct fake_framebuffer *framebuffer) + struct framebuffer_data *framebuffer) { struct v3dv_cl *rcl = &job->rcl; @@ -612,7 +586,7 @@ static void emit_copy_layer_to_buffer(struct v3dv_job *job, struct v3dv_buffer *buffer, struct v3dv_image *image, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, uint32_t layer, const VkBufferImageCopy *region) { @@ -625,13 +599,13 @@ static void emit_copy_image_to_buffer_rcl(struct v3dv_job *job, struct v3dv_buffer *buffer, struct v3dv_image *image, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, const VkBufferImageCopy *region) { struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL, NULL, region->imageSubresource.aspectMask, 0, 0); - for (int layer = 0; layer < framebuffer->fb.layers; layer++) + for (int layer = 0; layer < job->frame_tiling.layers; layer++) emit_copy_layer_to_buffer(job, buffer, image, framebuffer, layer, region); cl_emit(rcl, END_OF_RENDERING, end); } @@ -664,31 +638,15 @@ copy_image_to_buffer_tlb(struct v3dv_cmd_buffer *cmd_buffer, uint32_t num_layers = region->imageSubresource.layerCount; assert(num_layers > 0); - struct fake_framebuffer framebuffer; - setup_framebuffer_params(&framebuffer, - region->imageExtent.width, - region->imageExtent.height, - num_layers, internal_bpp, internal_type); - - /* Limit supertile coverage to the requested region */ - uint32_t supertile_w_in_pixels = - framebuffer.tiling.tile_width * framebuffer.tiling.supertile_width; - uint32_t supertile_h_in_pixels = - framebuffer.tiling.tile_height * framebuffer.tiling.supertile_height; - const uint32_t max_render_x = - region->imageOffset.x + region->imageExtent.width - 1; - const uint32_t max_render_y = - region->imageOffset.y + region->imageExtent.height - 1; - - assert(region->imageOffset.x == 0 && region->imageOffset.y == 0); - framebuffer.min_x_supertile = 0; - framebuffer.min_y_supertile = 0; - framebuffer.max_x_supertile = max_render_x / supertile_w_in_pixels; - framebuffer.max_y_supertile = max_render_y / supertile_h_in_pixels; - struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); + v3dv_cmd_buffer_start_frame(cmd_buffer, - &framebuffer.fb, &framebuffer.tiling, 1); + region->imageExtent.width, + region->imageExtent.height, + num_layers, 1, internal_bpp); + + struct framebuffer_data framebuffer; + setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling); v3dv_job_emit_binning_flush(job); emit_copy_image_to_buffer_rcl(job, buffer, image, &framebuffer, region); @@ -768,7 +726,7 @@ static void emit_copy_image_layer(struct v3dv_job *job, struct v3dv_image *dst, struct v3dv_image *src, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, uint32_t layer, const VkImageCopy *region) { @@ -781,13 +739,13 @@ static void emit_copy_image_rcl(struct v3dv_job *job, struct v3dv_image *dst, struct v3dv_image *src, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, const VkImageCopy *region) { struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL, NULL, region->dstSubresource.aspectMask, 0, 0); - for (int layer = 0; layer < framebuffer->fb.layers; layer++) + for (int layer = 0; layer < job->frame_tiling.layers; layer++) emit_copy_image_layer(job, dst, src, framebuffer, layer, region); cl_emit(rcl, END_OF_RENDERING, end); } @@ -822,28 +780,15 @@ copy_image_tlb(struct v3dv_cmd_buffer *cmd_buffer, uint32_t num_layers = region->dstSubresource.layerCount; assert(num_layers > 0); - struct fake_framebuffer framebuffer; - setup_framebuffer_params(&framebuffer, - region->extent.width, region->extent.height, - num_layers, internal_bpp, internal_type); - - /* Limit supertile coverage to the requested region */ - uint32_t supertile_w_in_pixels = - framebuffer.tiling.tile_width * framebuffer.tiling.supertile_width; - uint32_t supertile_h_in_pixels = - framebuffer.tiling.tile_height * framebuffer.tiling.supertile_height; - const uint32_t max_render_x = region->extent.width - 1; - const uint32_t max_render_y = region->extent.height - 1; - - assert(region->dstOffset.x == 0 && region->dstOffset.y == 0); - framebuffer.min_x_supertile = 0; - framebuffer.min_y_supertile = 0; - framebuffer.max_x_supertile = max_render_x / supertile_w_in_pixels; - framebuffer.max_y_supertile = max_render_y / supertile_h_in_pixels; - struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); + v3dv_cmd_buffer_start_frame(cmd_buffer, - &framebuffer.fb, &framebuffer.tiling, 1); + region->extent.width, + region->extent.height, + num_layers, 1, internal_bpp); + + struct framebuffer_data framebuffer; + setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling); v3dv_job_emit_binning_flush(job); emit_copy_image_rcl(job, dst, src, &framebuffer, region); @@ -906,7 +851,7 @@ emit_clear_image_per_tile_list(struct v3dv_job *job, static void emit_clear_image(struct v3dv_job *job, struct v3dv_image *image, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, VkImageAspectFlags aspects, uint32_t layer, uint32_t level) @@ -918,7 +863,7 @@ emit_clear_image(struct v3dv_job *job, static void emit_clear_image_rcl(struct v3dv_job *job, struct v3dv_image *image, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, const union v3dv_clear_value *clear_value, VkImageAspectFlags aspects, uint32_t layer, @@ -970,13 +915,14 @@ clear_image_tlb(struct v3dv_cmd_buffer *cmd_buffer, uint32_t width = u_minify(image->extent.width, level); uint32_t height = u_minify(image->extent.height, level); - struct fake_framebuffer framebuffer; - setup_framebuffer_params(&framebuffer, width, height, 1, - internal_bpp, internal_type); - struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); - v3dv_cmd_buffer_start_frame(cmd_buffer, - &framebuffer.fb, &framebuffer.tiling, 1); + + v3dv_cmd_buffer_start_frame(cmd_buffer, width, height, 1, + 1, internal_bpp); + + struct framebuffer_data framebuffer; + setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling); + v3dv_job_emit_binning_flush(job); /* If this triggers it is an application bug: the spec requires @@ -1073,10 +1019,10 @@ emit_copy_buffer(struct v3dv_job *job, struct v3dv_bo *src, uint32_t dst_offset, uint32_t src_offset, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, uint32_t format) { - const uint32_t stride = framebuffer->fb.width * 4; + const uint32_t stride = job->frame_tiling.width * 4; emit_copy_buffer_per_tile_list(job, dst, src, dst_offset, src_offset, stride, format); @@ -1089,7 +1035,7 @@ emit_copy_buffer_rcl(struct v3dv_job *job, struct v3dv_bo *src, uint32_t dst_offset, uint32_t src_offset, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, uint32_t format) { struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL, NULL, @@ -1105,11 +1051,12 @@ emit_copy_buffer_rcl(struct v3dv_job *job, * the job and call this function multiple times. */ static void -setup_framebuffer_for_pixel_count(struct fake_framebuffer *framebuffer, - uint32_t num_pixels, - uint32_t internal_bpp, - uint32_t internal_type) +framebuffer_size_for_pixel_count(uint32_t num_pixels, + uint32_t *width, + uint32_t *height) { + assert(num_pixels > 0); + const uint32_t max_dim_pixels = 4096; const uint32_t max_pixels = max_dim_pixels * max_dim_pixels; @@ -1127,15 +1074,10 @@ setup_framebuffer_for_pixel_count(struct fake_framebuffer *framebuffer, } assert(w <= max_dim_pixels && h <= max_dim_pixels); assert(w * h <= num_pixels); + assert(w > 0 && h > 0); - /* Skip tiling calculations if the framebuffer setup has not changed */ - if (w != framebuffer->fb.width || - h != framebuffer->fb.height || - internal_bpp != framebuffer->tiling.internal_bpp || - internal_type != framebuffer->internal_type) { - setup_framebuffer_params(framebuffer, w, h, 1, - internal_bpp, internal_type); - } + *width = w; + *height = h; } static struct v3dv_job * @@ -1175,14 +1117,17 @@ copy_buffer(struct v3dv_cmd_buffer *cmd_buffer, struct v3dv_job *job; uint32_t src_offset = region->srcOffset; uint32_t dst_offset = region->dstOffset; - struct fake_framebuffer framebuffer = { .fb.width = 0 }; while (num_items > 0) { - setup_framebuffer_for_pixel_count(&framebuffer, num_items, - internal_bpp, internal_type); - job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); - v3dv_cmd_buffer_start_frame(cmd_buffer, - &framebuffer.fb, &framebuffer.tiling, 1); + + uint32_t width, height; + framebuffer_size_for_pixel_count(num_items, &width, &height); + + v3dv_cmd_buffer_start_frame(cmd_buffer, width, height, 1, + 1, internal_bpp); + + struct framebuffer_data framebuffer; + setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling); v3dv_job_emit_binning_flush(job); @@ -1191,7 +1136,7 @@ copy_buffer(struct v3dv_cmd_buffer *cmd_buffer, v3dv_cmd_buffer_finish_job(cmd_buffer); - const uint32_t items_copied = framebuffer.fb.width * framebuffer.fb.height; + const uint32_t items_copied = width * height; const uint32_t bytes_copied = items_copied * item_size; num_items -= items_copied; src_offset += bytes_copied; @@ -1293,9 +1238,9 @@ static void emit_fill_buffer(struct v3dv_job *job, struct v3dv_bo *bo, uint32_t offset, - struct fake_framebuffer *framebuffer) + struct framebuffer_data *framebuffer) { - const uint32_t stride = framebuffer->fb.width * 4; + const uint32_t stride = job->frame_tiling.width * 4; emit_fill_buffer_per_tile_list(job, bo, offset, stride); emit_supertile_coordinates(job, framebuffer); } @@ -1304,7 +1249,7 @@ static void emit_fill_buffer_rcl(struct v3dv_job *job, struct v3dv_bo *bo, uint32_t offset, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, uint32_t data) { const union v3dv_clear_value clear_value = { @@ -1332,14 +1277,16 @@ fill_buffer(struct v3dv_cmd_buffer *cmd_buffer, const uint32_t internal_type = V3D_INTERNAL_TYPE_8UI; uint32_t num_items = size / 4; - struct fake_framebuffer framebuffer = { .fb.width = 0 }; while (num_items > 0) { - setup_framebuffer_for_pixel_count(&framebuffer, num_items, - internal_bpp, internal_type); - struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); - v3dv_cmd_buffer_start_frame(cmd_buffer, - &framebuffer.fb, &framebuffer.tiling, 1); + + uint32_t width, height; + framebuffer_size_for_pixel_count(num_items, &width, &height); + + v3dv_cmd_buffer_start_frame(cmd_buffer, width, height, 1, 1, internal_bpp); + + struct framebuffer_data framebuffer; + setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling); v3dv_job_emit_binning_flush(job); @@ -1347,7 +1294,7 @@ fill_buffer(struct v3dv_cmd_buffer *cmd_buffer, v3dv_cmd_buffer_finish_job(cmd_buffer); - const uint32_t items_copied = framebuffer.fb.width * framebuffer.fb.height; + const uint32_t items_copied = width * height; const uint32_t bytes_copied = items_copied * 4; num_items -= items_copied; offset += bytes_copied; @@ -1480,7 +1427,7 @@ static void emit_copy_buffer_to_layer(struct v3dv_job *job, struct v3dv_image *image, struct v3dv_buffer *buffer, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, uint32_t layer, const VkBufferImageCopy *region) { @@ -1493,13 +1440,13 @@ static void emit_copy_buffer_to_image_rcl(struct v3dv_job *job, struct v3dv_image *image, struct v3dv_buffer *buffer, - struct fake_framebuffer *framebuffer, + struct framebuffer_data *framebuffer, const VkBufferImageCopy *region) { struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL, NULL, region->imageSubresource.aspectMask, 0, 0); - for (int layer = 0; layer < framebuffer->fb.layers; layer++) + for (int layer = 0; layer < job->frame_tiling.layers; layer++) emit_copy_buffer_to_layer(job, image, buffer, framebuffer, layer, region); cl_emit(rcl, END_OF_RENDERING, end); } @@ -1520,31 +1467,14 @@ copy_buffer_to_image_tlb(struct v3dv_cmd_buffer *cmd_buffer, uint32_t num_layers = region->imageSubresource.layerCount; assert(num_layers > 0); - struct fake_framebuffer framebuffer; - setup_framebuffer_params(&framebuffer, - region->imageExtent.width, - region->imageExtent.height, - num_layers, internal_bpp, internal_type); - - /* Limit supertile coverage to the requested region */ - uint32_t supertile_w_in_pixels = - framebuffer.tiling.tile_width * framebuffer.tiling.supertile_width; - uint32_t supertile_h_in_pixels = - framebuffer.tiling.tile_height * framebuffer.tiling.supertile_height; - const uint32_t max_render_x = - region->imageOffset.x + region->imageExtent.width - 1; - const uint32_t max_render_y = - region->imageOffset.y + region->imageExtent.height - 1; - - assert(region->imageOffset.x == 0 && region->imageOffset.y == 0); - framebuffer.min_x_supertile = 0; - framebuffer.min_y_supertile = 0; - framebuffer.max_x_supertile = max_render_x / supertile_w_in_pixels; - framebuffer.max_y_supertile = max_render_y / supertile_h_in_pixels; - struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1); v3dv_cmd_buffer_start_frame(cmd_buffer, - &framebuffer.fb, &framebuffer.tiling, 1); + region->imageExtent.width, + region->imageExtent.height, + num_layers, 1, internal_bpp); + + struct framebuffer_data framebuffer; + setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling); v3dv_job_emit_binning_flush(job); emit_copy_buffer_to_image_rcl(job, image, buffer, &framebuffer, region); diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index c0f1fe2afa5..be7290e9a87 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -409,7 +409,11 @@ struct v3dv_framebuffer { }; struct v3dv_frame_tiling { + uint32_t width; + uint32_t height; + uint32_t render_target_count; uint32_t internal_bpp; + uint32_t layers; uint32_t tile_width; uint32_t tile_height; uint32_t draw_tiles_x; @@ -422,11 +426,6 @@ struct v3dv_frame_tiling { uint8_t v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer, const struct v3dv_subpass *subpass); -void v3dv_framebuffer_compute_tiling_params(const struct v3dv_framebuffer *framebuffer, - const struct v3dv_subpass *subpass, - uint8_t internal_bpp, - struct v3dv_frame_tiling *tiling); - struct v3dv_cmd_pool { VkAllocationCallbacks alloc; @@ -646,9 +645,11 @@ struct v3dv_job *v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer, int32_t subpass_idx); void v3dv_cmd_buffer_finish_job(struct v3dv_cmd_buffer *cmd_buffer); void v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer, - const struct v3dv_framebuffer *framebuffer, - const struct v3dv_frame_tiling *tiling, - int32_t num_render_targets); + uint32_t width, + uint32_t height, + uint32_t layers, + uint32_t render_target_count, + uint8_t max_internal_bpp); void v3dv_render_pass_setup_render_target(struct v3dv_cmd_buffer *cmd_buffer, int rt,