diff --git a/src/gallium/drivers/radeonsi/si_compute_blit.c b/src/gallium/drivers/radeonsi/si_compute_blit.c index aeb86af7331..10e78015d7d 100644 --- a/src/gallium/drivers/radeonsi/si_compute_blit.c +++ b/src/gallium/drivers/radeonsi/si_compute_blit.c @@ -1052,6 +1052,31 @@ static unsigned si_format_get_last_blit_component(enum pipe_format format, bool return num; } +static bool si_should_blit_clamp_xy(const struct pipe_blit_info *info) +{ + int src_width = u_minify(info->src.resource->width0, info->src.level); + int src_height = u_minify(info->src.resource->height0, info->src.level); + struct pipe_box box = info->src.box; + + /* Eliminate negative width/height/depth. */ + if (box.width < 0) { + box.x += box.width; + box.width *= -1; + } + if (box.height < 0) { + box.y += box.height; + box.height *= -1; + } + + bool in_bounds = box.x >= 0 && box.x < src_width && + box.y >= 0 && box.y < src_height && + box.x + box.width > 0 && box.x + box.width <= src_width && + box.y + box.height > 0 && box.y + box.height <= src_height; + + /* Return if the box is not in bounds. */ + return !in_bounds; +} + bool si_compute_blit(struct si_context *sctx, const struct pipe_blit_info *info) { /* Compute blits require D16 right now (see the ISA). @@ -1118,6 +1143,7 @@ bool si_compute_blit(struct si_context *sctx, const struct pipe_blit_info *info) util_format_is_pure_integer(info->src.format); unsigned num_samples = MAX2(info->src.resource->nr_samples, info->dst.resource->nr_samples); options.log2_samples = options.sample0_only ? 0 : util_logbase2(num_samples); + options.xy_clamp_to_edge = si_should_blit_clamp_xy(info); options.flip_x = info->src.box.width < 0; options.flip_y = info->src.box.height < 0; options.sint_to_uint = util_format_is_pure_sint(info->src.format) && diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index c8fc1ba6bae..6358d6ddbf2 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -1573,6 +1573,7 @@ union si_compute_blit_shader_key { uint8_t log2_samples:4; bool sample0_only:1; /* src is MSAA, dst is not MSAA, log2_samples is ignored */ /* Source coordinate modifiers. */ + bool xy_clamp_to_edge:1; bool flip_x:1; bool flip_y:1; /* Output modifiers. */ diff --git a/src/gallium/drivers/radeonsi/si_shaderlib_nir.c b/src/gallium/drivers/radeonsi/si_shaderlib_nir.c index 1d074aedb5c..2fd97cf1d05 100644 --- a/src/gallium/drivers/radeonsi/si_shaderlib_nir.c +++ b/src/gallium/drivers/radeonsi/si_shaderlib_nir.c @@ -492,16 +492,18 @@ void *si_create_blit_cs(struct si_context *sctx, const union si_compute_blit_sha coord_src = nir_iadd(&b, coord_src, src_xyz); /* Clamp to edge for src, only X and Y because Z can't be out of bounds. */ - unsigned src_clamp_channels = options->src_is_1d ? 0x1 : 0x3; - nir_ssa_def *dim = nir_image_deref_size(&b, 4, 32, deref_ssa(&b, img_src), zero); - dim = nir_channels(&b, dim, src_clamp_channels); + if (options->xy_clamp_to_edge) { + unsigned src_clamp_channels = options->src_is_1d ? 0x1 : 0x3; + nir_ssa_def *dim = nir_image_deref_size(&b, 4, 32, deref_ssa(&b, img_src), zero); + dim = nir_channels(&b, dim, src_clamp_channels); - nir_ssa_def *coord_src_clamped = nir_channels(&b, coord_src, src_clamp_channels); - coord_src_clamped = nir_imax(&b, coord_src_clamped, nir_imm_int(&b, 0)); - coord_src_clamped = nir_imin(&b, coord_src_clamped, nir_iadd_imm(&b, dim, -1)); + nir_ssa_def *coord_src_clamped = nir_channels(&b, coord_src, src_clamp_channels); + coord_src_clamped = nir_imax(&b, coord_src_clamped, nir_imm_int(&b, 0)); + coord_src_clamped = nir_imin(&b, coord_src_clamped, nir_iadd_imm(&b, dim, -1)); - for (unsigned i = 0; i < util_bitcount(src_clamp_channels); i++) - coord_src = nir_vector_insert_imm(&b, coord_src, nir_channel(&b, coord_src_clamped, i), i); + for (unsigned i = 0; i < util_bitcount(src_clamp_channels); i++) + coord_src = nir_vector_insert_imm(&b, coord_src, nir_channel(&b, coord_src_clamped, i), i); + } /* Swizzle coordinates for 1D_ARRAY. */ static unsigned swizzle_xz[] = {0, 2, 0, 0};