v3dv: more frame tiling refactors

This puts all the information required to setup frame tiling into
v3dv_frame_tiling so we no longer need a framebuffer to start a
frame. This makes the code simpler, since frame tiling calculations
happen automatically when we start a new frame and simplifies
the implementation of copy and clear operations that used to
requiere that we setup a fake framebuffer with no actual attachments,
which was a bit of a kludge.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
Iago Toral Quiroga 2020-03-03 11:57:59 +01:00 committed by Marge Bot
parent 2a3fa914d4
commit 313809487c
5 changed files with 234 additions and 284 deletions

View File

@ -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

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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,