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:
parent
2a3fa914d4
commit
313809487c
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue