zink: Blit using one triangle for nearest filtering

Fixes dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_out_of_bounds_.* on RADV.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28892>
This commit is contained in:
Konstantin Seurer 2024-04-23 13:31:08 +02:00 committed by Marge Bot
parent 3233d19f87
commit a3aadac5fe
5 changed files with 49 additions and 0 deletions

View file

@ -442,6 +442,8 @@ zink_blit(struct pipe_context *pctx,
zink_resource_object_init_mutable(ctx, dst);
zink_blit_barriers(ctx, use_src, dst, whole);
ctx->blitting = true;
ctx->blit_scissor = info->scissor_enable;
ctx->blit_nearest = info->filter == PIPE_TEX_FILTER_NEAREST;
if (stencil_blit) {
struct pipe_surface *dst_view, dst_templ;
@ -636,3 +638,36 @@ zink_blit_region_covers(struct u_rect region, struct u_rect covers)
return intersect.x0 == c.x0 && intersect.y0 == c.y0 &&
intersect.x1 == c.x1 && intersect.y1 == c.y1;
}
void
zink_draw_rectangle(struct blitter_context *blitter, void *vertex_elements_cso,
blitter_get_vs_func get_vs, int x1, int y1, int x2, int y2,
float depth, unsigned num_instances, enum blitter_attrib_type type,
const union blitter_attrib *attrib)
{
struct zink_context *ctx = zink_context(blitter->pipe);
union blitter_attrib new_attrib = *attrib;
/* Avoid inconsistencies in rounding between both triangles which can show with
* nearest filtering by expanding the rect so only one triangle is effectively drawn.
*/
if (ctx->blit_scissor && ctx->blit_nearest) {
int64_t new_x1 = (int64_t)x1 * 2 - x2;
int64_t new_y2 = (int64_t)y2 * 2 - y1;
if (new_x1 < INT32_MAX && new_x1 > INT32_MIN &&
new_y2 < INT32_MAX && new_y2 > INT32_MIN) {
x1 = new_x1;
y2 = new_y2;
if (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY ||
type == UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW) {
new_attrib.texcoord.x1 += new_attrib.texcoord.x1 - new_attrib.texcoord.x2;
new_attrib.texcoord.y2 += new_attrib.texcoord.y2 - new_attrib.texcoord.y1;
}
}
}
util_blitter_draw_rectangle(blitter, vertex_elements_cso, get_vs, x1, y1, x2, y2,
depth, num_instances, type, &new_attrib);
}

View file

@ -5212,6 +5212,8 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
ctx->blitter = util_blitter_create(&ctx->base);
if (!ctx->blitter)
goto fail;
if (screen->driver_workarounds.inconsistent_interpolation)
ctx->blitter->draw_rectangle = zink_draw_rectangle;
}
zink_set_last_vertex_key(ctx)->last_vertex_stage = true;

View file

@ -232,6 +232,12 @@ zink_blit_region_fills(struct u_rect region, unsigned width, unsigned height);
bool
zink_blit_region_covers(struct u_rect region, struct u_rect covers);
void
zink_draw_rectangle(struct blitter_context *blitter, void *vertex_elements_cso,
blitter_get_vs_func get_vs, int x1, int y1, int x2, int y2,
float depth, unsigned num_instances, enum blitter_attrib_type type,
const union blitter_attrib *attrib);
static inline struct u_rect
zink_rect_from_box(const struct pipe_box *box)
{

View file

@ -3052,6 +3052,8 @@ init_driver_workarounds(struct zink_screen *screen)
case VK_DRIVER_ID_AMD_PROPRIETARY:
/* this has bad perf on AMD */
screen->info.have_KHR_push_descriptor = false;
/* Interpolation is not consistent between two triangles of a rectangle. */
screen->driver_workarounds.inconsistent_interpolation = true;
break;
default:
break;

View file

@ -46,6 +46,7 @@
#include "util/set.h"
#include "util/simple_mtx.h"
#include "util/slab.h"
#include "util/u_blitter.h"
#include "util/u_dynarray.h"
#include "util/u_idalloc.h"
#include "util/u_live_shader_cache.h"
@ -1542,6 +1543,7 @@ struct zink_screen {
bool needs_zs_shader_swizzle;
bool can_do_invalid_linear_modifier;
bool io_opt;
bool inconsistent_interpolation;
unsigned z16_unscaled_bias;
unsigned z24_unscaled_bias;
} driver_workarounds;
@ -2009,6 +2011,8 @@ struct zink_context {
bool is_device_lost;
bool primitive_restart;
bool blitting : 1;
bool blit_scissor : 1;
bool blit_nearest : 1;
bool unordered_blitting : 1;
bool vertex_state_changed : 1;
bool blend_state_changed : 1;