v3d: implement tile buffer blits

This implements blit operation using the TLB.

It uses a source color buffer (bbuf) which will be blitted to color
buffer 0.

It also takes in account the number of samples for the input and output
so it can perform multisample resolve.

v1:
 - Fix comment (Iago)
 - Removed needless brackets (Iago)
 - Ensure msaa is correctly set (Iago)
 - Get rid of job->resolve (Iago)
 - Add rbuf as part of job's key (Iago)
 - Rename rbuf/rsurf by bbuf/bsurf (Iago)
 - Revert needless change (Iago)

v2:
 - Remove spurious change (Iago)
 - Add assert for safety reasons (Iago)
 - Add brackets in condition (Iago)
 - Fix commit message and title (Iago)
 - Do tile blit only for version >=4.0 (Iago)

v3:
 - Add assertion (Iago)
 - Fix comment (Iago)
 - Change commit title (Iago)

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Signed-off-by: Juan A. Suarez Romero <jasuarez@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7816>
This commit is contained in:
Juan A. Suarez Romero
2020-11-27 14:23:43 +01:00
committed by Marge Bot
parent 9eb2517a88
commit 487dd96c4f
3 changed files with 58 additions and 9 deletions
+9 -2
View File
@@ -280,6 +280,7 @@ struct v3d_ssbo_stateobj {
struct v3d_job_key {
struct pipe_surface *cbufs[4];
struct pipe_surface *zsbuf;
struct pipe_surface *bbuf;
};
enum v3d_ez_state {
@@ -336,10 +337,15 @@ struct v3d_job {
/* Size of the submit.bo_handles array. */
uint32_t bo_handles_size;
/** @{ Surfaces to submit rendering for. */
/** @{
* Surfaces to submit rendering for.
* For blit operations, bbuf is the source surface, and cbufs[0] is
* the destination surface.
*/
uint32_t nr_cbufs;
struct pipe_surface *cbufs[4];
struct pipe_surface *zsbuf;
struct pipe_surface *bbuf;
/** @} */
/** @{
* Bounding box of the scissor across all queued drawing.
@@ -648,7 +654,8 @@ void v3d_job_free(struct v3d_context *v3d, struct v3d_job *job);
struct v3d_job *v3d_get_job(struct v3d_context *v3d,
uint32_t nr_cbufs,
struct pipe_surface **cbufs,
struct pipe_surface *zsbuf);
struct pipe_surface *zsbuf,
struct pipe_surface *bbuf);
struct v3d_job *v3d_get_job_for_fbo(struct v3d_context *v3d);
void v3d_job_set_tile_buffer_size(struct v3d_job *job);
void v3d_job_add_bo(struct v3d_job *job, struct v3d_bo *bo);
+18 -2
View File
@@ -72,6 +72,8 @@ v3d_job_free(struct v3d_context *v3d, struct v3d_job *job)
job->zsbuf->texture);
pipe_surface_reference(&job->zsbuf, NULL);
}
if (job->bbuf)
pipe_surface_reference(&job->bbuf, NULL);
if (v3d->job == job)
v3d->job = NULL;
@@ -300,6 +302,13 @@ v3d_job_set_tile_buffer_size(struct v3d_job *job)
max_bpp = MAX2(max_bpp, surf->internal_bpp);
}
}
if (job->bbuf) {
struct v3d_surface *bsurf = v3d_surface(job->bbuf);
assert(job->bbuf->texture->nr_samples <= 1 || job->msaa);
max_bpp = MAX2(max_bpp, bsurf->internal_bpp);
}
job->internal_bpp = max_bpp;
STATIC_ASSERT(RENDER_TARGET_MAXIMUM_32BPP == 0);
tile_size_index += max_bpp;
@@ -321,7 +330,8 @@ struct v3d_job *
v3d_get_job(struct v3d_context *v3d,
uint32_t nr_cbufs,
struct pipe_surface **cbufs,
struct pipe_surface *zsbuf)
struct pipe_surface *zsbuf,
struct pipe_surface *bbuf)
{
/* Return the existing job for this FBO if we have one */
struct v3d_job_key local_key = {
@@ -332,6 +342,7 @@ v3d_get_job(struct v3d_context *v3d,
cbufs[3],
},
.zsbuf = zsbuf,
.bbuf = bbuf,
};
struct hash_entry *entry = _mesa_hash_table_search(v3d->jobs,
&local_key);
@@ -363,6 +374,11 @@ v3d_get_job(struct v3d_context *v3d,
if (zsbuf->texture->nr_samples > 1)
job->msaa = true;
}
if (bbuf) {
pipe_surface_reference(&job->bbuf, bbuf);
if (bbuf->texture->nr_samples > 1)
job->msaa = true;
}
for (int i = 0; i < job->nr_cbufs; i++) {
if (cbufs[i])
@@ -399,7 +415,7 @@ v3d_get_job_for_fbo(struct v3d_context *v3d)
uint32_t nr_cbufs = v3d->framebuffer.nr_cbufs;
struct pipe_surface **cbufs = v3d->framebuffer.cbufs;
struct pipe_surface *zsbuf = v3d->framebuffer.zsbuf;
struct v3d_job *job = v3d_get_job(v3d, nr_cbufs, cbufs, zsbuf);
struct v3d_job *job = v3d_get_job(v3d, nr_cbufs, cbufs, zsbuf, NULL);
if (v3d->framebuffer.samples >= 1)
job->msaa = true;
+31 -5
View File
@@ -114,7 +114,8 @@ static void
store_general(struct v3d_job *job,
struct v3d_cl *cl, struct pipe_surface *psurf,
int layer, int buffer, int pipe_bit,
uint32_t *stores_pending, bool general_color_clear)
uint32_t *stores_pending, bool general_color_clear,
bool is_blit)
{
struct v3d_surface *surf = v3d_surface(psurf);
bool separate_stencil = surf->separate_stencil && buffer == STENCIL;
@@ -158,8 +159,11 @@ store_general(struct v3d_job *job,
store.height_in_ub_or_stride = slice->stride;
}
assert(!is_blit || job->bbuf);
if (psurf->texture->nr_samples > 1)
store.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES;
else if (is_blit && job->bbuf->texture->nr_samples > 1)
store.decimate_mode = V3D_DECIMATE_MODE_4X;
else
store.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0;
@@ -213,6 +217,14 @@ static void
v3d_rcl_emit_loads(struct v3d_job *job, struct v3d_cl *cl, int layer)
{
uint32_t loads_pending = job->load;
uint32_t blit_pending = job->bbuf ? PIPE_CLEAR_COLOR0 : 0;
assert(!job->bbuf || V3D_VERSION >= 40);
/* When blitting, no color buffer is loaded; instead the blit source
* buffer is loaded.
*/
assert(!job->bbuf || job->load == 0);
for (int i = 0; i < job->nr_cbufs; i++) {
uint32_t bit = PIPE_CLEAR_COLOR0 << i;
@@ -229,6 +241,12 @@ v3d_rcl_emit_loads(struct v3d_job *job, struct v3d_cl *cl, int layer)
bit, &loads_pending);
}
if (blit_pending) {
load_general(cl, job->bbuf, RENDER_TARGET_0, layer,
PIPE_CLEAR_COLOR0, &blit_pending);
assert(blit_pending == 0);
}
if ((loads_pending & PIPE_CLEAR_DEPTHSTENCIL) &&
(V3D_VERSION >= 40 ||
(job->zsbuf && job->zsbuf->texture->nr_samples > 1))) {
@@ -313,6 +331,7 @@ v3d_rcl_emit_stores(struct v3d_job *job, struct v3d_cl *cl, int layer)
* perspective. Non-MSAA surfaces will use
* STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED.
*/
assert(!job->bbuf || job->nr_cbufs == 1);
for (int i = 0; i < job->nr_cbufs; i++) {
uint32_t bit = PIPE_CLEAR_COLOR0 << i;
if (!(job->store & bit))
@@ -325,7 +344,7 @@ v3d_rcl_emit_stores(struct v3d_job *job, struct v3d_cl *cl, int layer)
}
store_general(job, cl, psurf, layer, RENDER_TARGET_0 + i, bit,
&stores_pending, general_color_clear);
&stores_pending, general_color_clear, job->bbuf);
}
if (job->store & PIPE_CLEAR_DEPTHSTENCIL && job->zsbuf &&
@@ -336,20 +355,23 @@ v3d_rcl_emit_stores(struct v3d_job *job, struct v3d_cl *cl, int layer)
store_general(job, cl, job->zsbuf, layer,
Z, PIPE_CLEAR_DEPTH,
&stores_pending,
general_color_clear);
general_color_clear,
false);
}
if (job->store & PIPE_CLEAR_STENCIL) {
store_general(job, cl, job->zsbuf, layer,
STENCIL, PIPE_CLEAR_STENCIL,
&stores_pending,
general_color_clear);
general_color_clear,
false);
}
} else {
store_general(job, cl, job->zsbuf, layer,
zs_buffer_from_pipe_bits(job->store),
job->store & PIPE_CLEAR_DEPTHSTENCIL,
&stores_pending, general_color_clear);
&stores_pending, general_color_clear,
false);
}
}
@@ -473,6 +495,10 @@ v3d_setup_render_target(struct v3d_job *job, int cbuf,
struct v3d_surface *surf = v3d_surface(job->cbufs[cbuf]);
*rt_bpp = surf->internal_bpp;
if (job->bbuf) {
struct v3d_surface *bsurf = v3d_surface(job->bbuf);
*rt_bpp = MAX2(*rt_bpp, bsurf->internal_bpp);
}
*rt_type = surf->internal_type;
*rt_clamp = V3D_RENDER_TARGET_CLAMP_NONE;
}