v3d: take TLB blit framebuffer dimensions from smallest surface dimensions
authorIago Toral Quiroga <itoral@igalia.com>
Tue, 18 May 2021 07:50:17 +0000 (09:50 +0200)
committerMarge Bot <eric+marge@anholt.net>
Thu, 20 May 2021 05:45:33 +0000 (05:45 +0000)
Typically, we program the framebuffer dimensions using the destination
surface, however, if we blit a rect from a surface that is smaller than
the destination, the simulator will complain that the TLB load stride
is not large enough to match the destination framebuffer. We can work
around this by programming the smallest size of both surfaces, which
should be okay because the tlb blit path requires that the blit
coordinates are the same for both src and dst.

Fixes assert crashes with the simulator for MSAA tests in:
./bin/gl-1.0-logicop

Reviewed-by: Juan A. Suarez <jasuarez@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10863>

src/gallium/drivers/v3d/v3d_blit.c

index 70c55d3..7b19b39 100644 (file)
@@ -521,11 +521,17 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info)
         job->draw_min_y = info->dst.box.y;
         job->draw_max_x = info->dst.box.x + info->dst.box.width;
         job->draw_max_y = info->dst.box.y + info->dst.box.height;
-        job->draw_width = dst_surf->width;
-        job->draw_height = dst_surf->height;
-        job->draw_tiles_x = DIV_ROUND_UP(dst_surf->width,
+        /* The simulator complains if we do a TLB load from a source with a
+         * stride that is smaller than the destination's, so we program the
+         * 'frame region' to match the smallest dimensions of the two surfaces.
+         * This should be fine because we only get here if the src and dst boxes
+         * match, so we know the blit involves the same tiles on both surfaces.
+         */
+        job->draw_width = MIN2(dst_surf->width, src_surf->width);
+        job->draw_height = MIN2(dst_surf->height, src_surf->height);
+        job->draw_tiles_x = DIV_ROUND_UP(job->draw_width,
                                          job->tile_width);
-        job->draw_tiles_y = DIV_ROUND_UP(dst_surf->height,
+        job->draw_tiles_y = DIV_ROUND_UP(job->draw_height,
                                          job->tile_height);
 
         job->needs_flush = true;