#include "compiler/nir/nir_builder.h"
#include "blorp_priv.h"
-#include "brw_meta_util.h"
+
+/* header-only include needed for _mesa_unorm_to_float and friends. */
+#include "mesa/main/format_utils.h"
#define FILE_DEBUG_FLAG DEBUG_BLORP
+static const bool split_blorp_blit_debug = false;
+
/**
* Enum to specify the order of arguments in a sampler message
*/
const struct brw_blorp_blit_prog_key *key,
struct brw_blorp_blit_vars *v)
{
- nir_ssa_def *coord = nir_f2i(b, nir_load_var(b, v->frag_coord));
+ nir_ssa_def *coord = nir_f2i32(b, nir_load_var(b, v->frag_coord));
/* Account for destination surface intratile offset
*
nir_ssa_def *sample_off = nir_imm_vec2(b, sample_off_x, sample_off_y);
nir_ssa_def *sample_coords = nir_fadd(b, pos_xy, sample_off);
- nir_ssa_def *sample_coords_int = nir_f2i(b, sample_coords);
+ nir_ssa_def *sample_coords_int = nir_f2i32(b, sample_coords);
/* The MCS value we fetch has to match up with the pixel that we're
* sampling from. Since we sample from different pixels in each
nir_ssa_def *sample =
nir_fdot2(b, frac, nir_imm_vec2(b, key->x_scale,
key->x_scale * key->y_scale));
- sample = nir_f2i(b, sample);
+ sample = nir_f2i32(b, sample);
if (tex_samples == 8) {
sample = nir_iand(b, nir_ishr(b, nir_imm_int(b, 0x64210573),
blorp_nir_discard_if_outside_rect(&b, dst_pos, &v);
}
- src_pos = blorp_blit_apply_transform(&b, nir_i2f(&b, dst_pos), &v);
+ src_pos = blorp_blit_apply_transform(&b, nir_i2f32(&b, dst_pos), &v);
if (dst_pos->num_components == 3) {
/* The sample coordinate is an integer that we want left alone but
* blorp_blit_apply_transform() blindly applies the transform to all
/* Resolves (effecively) use texelFetch, so we need integers and we
* don't care about the sample index if we got one.
*/
- src_pos = nir_f2i(&b, nir_channels(&b, src_pos, 0x3));
+ src_pos = nir_f2i32(&b, nir_channels(&b, src_pos, 0x3));
if (devinfo->gen == 6) {
/* Because gen6 only supports 4x interleved MSAA, we can do all the
*/
src_pos = nir_ishl(&b, src_pos, nir_imm_int(&b, 1));
src_pos = nir_iadd(&b, src_pos, nir_imm_int(&b, 1));
- src_pos = nir_i2f(&b, src_pos);
+ src_pos = nir_i2f32(&b, src_pos);
color = blorp_nir_tex(&b, &v, src_pos, key->texture_data_type);
} else {
/* Gen7+ hardware doesn't automaticaly blend. */
} else {
/* We're going to use texelFetch, so we need integers */
if (src_pos->num_components == 2) {
- src_pos = nir_f2i(&b, src_pos);
+ src_pos = nir_f2i32(&b, src_pos);
} else {
assert(src_pos->num_components == 3);
- src_pos = nir_vec3(&b, nir_channel(&b, nir_f2i(&b, src_pos), 0),
- nir_channel(&b, nir_f2i(&b, src_pos), 1),
+ src_pos = nir_vec3(&b, nir_channel(&b, nir_f2i32(&b, src_pos), 0),
+ nir_channel(&b, nir_f2i32(&b, src_pos), 1),
nir_channel(&b, src_pos, 2));
}
struct brw_wm_prog_data prog_data;
nir_shader *nir = brw_blorp_build_nir_shader(blorp, mem_ctx, prog_key);
+ nir->info->name = ralloc_strdup(nir, "BLORP-blit");
+
struct brw_wm_prog_key wm_key;
brw_blorp_init_wm_prog_key(&wm_key);
wm_key.tex.compressed_multisample_layout_mask =
info->tile_y_sa /= 2;
}
+static bool
+can_shrink_surface(const struct brw_blorp_surface_info *surf)
+{
+ /* The current code doesn't support offsets into the aux buffers. This
+ * should be possible, but we need to make sure the offset is page
+ * aligned for both the surface and the aux buffer surface. Generally
+ * this mean using the page aligned offset for the aux buffer.
+ *
+ * Currently the cases where we must split the blit are limited to cases
+ * where we don't have a aux buffer.
+ */
+ if (surf->aux_addr.buffer != NULL)
+ return false;
+
+ /* We can't support splitting the blit for gen <= 7, because the qpitch
+ * size is calculated by the hardware based on the surface height for
+ * gen <= 7. In gen >= 8, the qpitch is controlled by the driver.
+ */
+ if (surf->surf.msaa_layout == ISL_MSAA_LAYOUT_ARRAY)
+ return false;
+
+ return true;
+}
+
static bool
can_shrink_surfaces(const struct blorp_params *params)
{
- return false;
+ return
+ can_shrink_surface(¶ms->src) &&
+ can_shrink_surface(¶ms->dst);
+}
+
+static unsigned
+get_max_surface_size(const struct gen_device_info *devinfo,
+ const struct blorp_params *params)
+{
+ const unsigned max = devinfo->gen >= 7 ? 16384 : 8192;
+ if (split_blorp_blit_debug && can_shrink_surfaces(params))
+ return max >> 4; /* A smaller restriction when debug is enabled */
+ else
+ return max;
}
struct blt_axis {
brw_blorp_get_blit_kernel(batch->blorp, params, wm_prog_key);
unsigned result = 0;
+ unsigned max_surface_size = get_max_surface_size(devinfo, params);
+ if (params->src.surf.logical_level0_px.width > max_surface_size ||
+ params->dst.surf.logical_level0_px.width > max_surface_size)
+ result |= BLIT_WIDTH_SHRINK;
+ if (params->src.surf.logical_level0_px.height > max_surface_size ||
+ params->dst.surf.logical_level0_px.height > max_surface_size)
+ result |= BLIT_HEIGHT_SHRINK;
if (result == 0) {
batch->blorp->exec(batch, params);
split_coords->src1 = orig->src1 + (scale >= 0.0 ? delta1 : delta0);
}
-static const struct isl_extent2d
+static struct isl_extent2d
get_px_size_sa(const struct isl_surf *surf)
{
static const struct isl_extent2d one_to_one = { .w = 1, .h = 1 };
y_scale = -y_scale;
bool x_done, y_done;
- bool shrink = false;
+ bool shrink = split_blorp_blit_debug && can_shrink_surfaces(orig_params);
do {
params = *orig_params;
blit_coords = split_coords;
}
}
+/* Takes an isl_color_value and returns a color value that is the original
+ * color value only bit-casted to a UINT format. This value, together with
+ * the format from get_ccs_compatible_uint_format, will yield the same bit
+ * value as the original color and format.
+ */
+static union isl_color_value
+bitcast_color_value_to_uint(union isl_color_value color,
+ const struct isl_format_layout *fmtl)
+{
+ /* All CCS formats have the same number of bits in each channel */
+ const struct isl_channel_layout *chan = &fmtl->channels.r;
+
+ union isl_color_value bits;
+ switch (chan->type) {
+ case ISL_UINT:
+ case ISL_SINT:
+ /* Hardware will ignore the high bits so there's no need to cast */
+ bits = color;
+ break;
+
+ case ISL_UNORM:
+ for (unsigned i = 0; i < 4; i++)
+ bits.u32[i] = _mesa_float_to_unorm(color.f32[i], chan->bits);
+ break;
+
+ case ISL_SNORM:
+ for (unsigned i = 0; i < 4; i++)
+ bits.i32[i] = _mesa_float_to_snorm(color.f32[i], chan->bits);
+ break;
+
+ case ISL_SFLOAT:
+ switch (chan->bits) {
+ case 16:
+ for (unsigned i = 0; i < 4; i++)
+ bits.u32[i] = _mesa_float_to_half(color.f32[i]);
+ break;
+
+ case 32:
+ bits = color;
+ break;
+
+ default:
+ unreachable("Invalid float format size");
+ }
+ break;
+
+ default:
+ unreachable("Invalid channel type");
+ }
+
+ switch (fmtl->format) {
+ case ISL_FORMAT_B8G8R8A8_UNORM:
+ case ISL_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case ISL_FORMAT_B8G8R8X8_UNORM:
+ case ISL_FORMAT_B8G8R8X8_UNORM_SRGB: {
+ /* If it's a BGRA format, we need to swap blue and red */
+ uint32_t tmp = bits.u32[0];
+ bits.u32[0] = bits.u32[2];
+ bits.u32[2] = tmp;
+ break;
+ }
+
+ default:
+ break; /* Nothing to do */
+ }
+
+ return bits;
+}
+
static void
surf_convert_to_uncompressed(const struct isl_device *isl_dev,
struct brw_blorp_surface_info *info,
params.src.view.format = get_copy_format_for_bpb(isl_dev, src_fmtl->bpb);
}
+ if (params.src.aux_usage == ISL_AUX_USAGE_CCS_E) {
+ assert(isl_formats_are_ccs_e_compatible(batch->blorp->isl_dev->info,
+ src_surf->surf->format,
+ params.src.view.format));
+ params.src.clear_color =
+ bitcast_color_value_to_uint(params.src.clear_color, src_fmtl);
+ }
+
+ if (params.dst.aux_usage == ISL_AUX_USAGE_CCS_E) {
+ assert(isl_formats_are_ccs_e_compatible(batch->blorp->isl_dev->info,
+ dst_surf->surf->format,
+ params.dst.view.format));
+ params.dst.clear_color =
+ bitcast_color_value_to_uint(params.dst.clear_color, dst_fmtl);
+ }
+
wm_prog_key.src_bpc =
isl_format_get_layout(params.src.view.format)->channels.r.bits;
wm_prog_key.dst_bpc =