diff options
author | Kenneth Graunke <[email protected]> | 2019-06-04 23:18:45 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2019-06-05 16:58:07 -0700 |
commit | f06c86358c2b3840d7b74514a90f83ed6fdd1991 (patch) | |
tree | e28c80313f89c1bc803f230ea38d537b69c34dac /src/intel/blorp/blorp_blit.c | |
parent | 1aea4cd0d91e755ad4b1bcfaee84f41110ccb5af (diff) |
intel/blorp: Handle SINT/UINT clamping on blits.
This patch makes blorp_blit handle SINT<->UINT blit value clamping.
After reading the source's integer data (which is expanded to 32-bit),
we either IMAX with 0 (for SINT -> UINT, to clamp negative numbers) or
UMIN with (1 << 31) - 1 (for UINT -> SINT, to clamp positive numbers
outside of the representable range).
Such blits are not allowed by the OpenGL or Vulkan APIs directly:
The Vulkan 1.1 spec for vkCmdBlitImage says:
"Integer formats can only be converted to other integer formats with
the same signedness."
The GL 4.5 spec for glBlitFramebuffer says:
"An INVALID_OPERATION error is generated if format conversions are
not supported, which occurs under any of the following conditions:
[...]
* The read buffer contains unsigned integer values and any draw
buffer does not contain unsigned integer values.
* The read buffer contains signed integer values and any draw buffer
does not contain signed integer values."
However, they are useful for other operations, such as texture upload
and download, which typically are implemented via blorp_blit(). i965
has code to fall back in this case (which the next commit will delete),
and Gallium expects blit() to handle this case for texture upload.
Fixes the following tests on iris:
- GTF-GL46.gtf32.GL3Tests.packed_pixels.packed_pixels
- GTF-GL46.gtf32.GL3Tests.packed_pixels.packed_pixels_pbo
- GTF-GL46.gtf32.GL3Tests.packed_pixels.packed_pixels_pixelstore
Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/intel/blorp/blorp_blit.c')
-rw-r--r-- | src/intel/blorp/blorp_blit.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c index 9e964d02f36..c0b2b5e6533 100644 --- a/src/intel/blorp/blorp_blit.c +++ b/src/intel/blorp/blorp_blit.c @@ -1426,6 +1426,29 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx, color = bit_cast_color(&b, color, key); } else if (key->dst_format) { color = convert_color(&b, color, key); + } else if (key->uint32_to_sint) { + /* Normally the hardware will take care of converting values from/to + * the source and destination formats. But a few cases need help. + * + * The Skylake PRM, volume 07, page 658 has a programming note: + * + * "When using SINT or UINT rendertarget surface formats, Blending + * must be DISABLED. The Pre-Blend Color Clamp Enable and Color + * Clamp Range fields are ignored, and an implied clamp to the + * rendertarget surface format is performed." + * + * For UINT to SINT blits, our sample operation gives us a uint32_t, + * but our render target write expects a signed int32_t number. If we + * simply passed the value along, the hardware would interpret a value + * with bit 31 set as a negative value, clamping it to the largest + * negative number the destination format could represent. But the + * actual source value is a positive number, so we want to clamp it + * to INT_MAX. To fix this, we explicitly take min(color, INT_MAX). + */ + color = nir_umin(&b, color, nir_imm_int(&b, INT32_MAX)); + } else if (key->sint32_to_uint) { + /* Similar to above, but clamping negative numbers to zero. */ + color = nir_imax(&b, color, nir_imm_int(&b, 0)); } if (key->dst_rgb) { @@ -2300,9 +2323,18 @@ blorp_blit(struct blorp_batch *batch, params.src.view.swizzle = src_swizzle; params.dst.view.swizzle = dst_swizzle; + const struct isl_format_layout *src_fmtl = + isl_format_get_layout(params.src.view.format); + struct brw_blorp_blit_prog_key wm_prog_key = { .shader_type = BLORP_SHADER_TYPE_BLIT, .filter = filter, + .sint32_to_uint = src_fmtl->channels.r.bits == 32 && + isl_format_has_sint_channel(params.src.view.format) && + isl_format_has_uint_channel(params.dst.view.format), + .uint32_to_sint = src_fmtl->channels.r.bits == 32 && + isl_format_has_uint_channel(params.src.view.format) && + isl_format_has_sint_channel(params.dst.view.format), }; /* Scaling factors used for bilinear filtering in multisample scaled |