diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index a5275c41243..427fea125f4 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -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); diff --git a/src/gallium/drivers/v3d/v3d_job.c b/src/gallium/drivers/v3d/v3d_job.c index d608684a5a3..744ed0fbfa6 100644 --- a/src/gallium/drivers/v3d/v3d_job.c +++ b/src/gallium/drivers/v3d/v3d_job.c @@ -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; diff --git a/src/gallium/drivers/v3d/v3dx_rcl.c b/src/gallium/drivers/v3d/v3dx_rcl.c index 7cebd3d0fc0..31d7d2b4cd4 100644 --- a/src/gallium/drivers/v3d/v3dx_rcl.c +++ b/src/gallium/drivers/v3d/v3dx_rcl.c @@ -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; }