#include "util/format_rgb9e5.h"
/* header-only include needed for _mesa_unorm_to_float and friends. */
#include "mesa/main/format_utils.h"
+#include "util/u_math.h"
#define FILE_DEBUG_FLAG DEBUG_BLORP
v->frag_coord = nir_variable_create(b->shader, nir_var_shader_in,
glsl_vec4_type(), "gl_FragCoord");
v->frag_coord->data.location = VARYING_SLOT_POS;
- v->frag_coord->data.origin_upper_left = true;
v->color_out = nir_variable_create(b->shader, nir_var_shader_out,
glsl_vec4_type(), "gl_FragColor");
#ifdef HAVE___BUILTIN_CTZ
return __builtin_ctz(~value);
#else
- return _mesa_bitcount(value & ~(value + 1));
+ return util_bitcount(value & ~(value + 1));
#endif
}
static nir_ssa_def *
-blorp_nir_manual_blend_average(nir_builder *b, struct brw_blorp_blit_vars *v,
- nir_ssa_def *pos, unsigned tex_samples,
- enum isl_aux_usage tex_aux_usage,
- nir_alu_type dst_type)
+blorp_nir_combine_samples(nir_builder *b, struct brw_blorp_blit_vars *v,
+ nir_ssa_def *pos, unsigned tex_samples,
+ enum isl_aux_usage tex_aux_usage,
+ nir_alu_type dst_type,
+ enum blorp_filter filter)
{
/* If non-null, this is the outer-most if statement */
nir_if *outer_if = NULL;
if (tex_aux_usage == ISL_AUX_USAGE_MCS)
mcs = blorp_blit_txf_ms_mcs(b, v, pos);
+ nir_op combine_op;
+ switch (filter) {
+ case BLORP_FILTER_AVERAGE:
+ assert(dst_type == nir_type_float);
+ combine_op = nir_op_fadd;
+ break;
+
+ case BLORP_FILTER_MIN_SAMPLE:
+ switch (dst_type) {
+ case nir_type_int: combine_op = nir_op_imin; break;
+ case nir_type_uint: combine_op = nir_op_umin; break;
+ case nir_type_float: combine_op = nir_op_fmin; break;
+ default: unreachable("Invalid dst_type");
+ }
+ break;
+
+ case BLORP_FILTER_MAX_SAMPLE:
+ switch (dst_type) {
+ case nir_type_int: combine_op = nir_op_imax; break;
+ case nir_type_uint: combine_op = nir_op_umax; break;
+ case nir_type_float: combine_op = nir_op_fmax; break;
+ default: unreachable("Invalid dst_type");
+ }
+ break;
+
+ default:
+ unreachable("Invalid filter");
+ }
+
/* We add together samples using a binary tree structure, e.g. for 4x MSAA:
*
* result = ((sample[0] + sample[1]) + (sample[2] + sample[3])) / 4
nir_ssa_def *texture_data[5];
unsigned stack_depth = 0;
for (unsigned i = 0; i < tex_samples; ++i) {
- assert(stack_depth == _mesa_bitcount(i)); /* Loop invariant */
+ assert(stack_depth == util_bitcount(i)); /* Loop invariant */
/* Push sample i onto the stack */
assert(stack_depth < ARRAY_SIZE(texture_data));
assert(stack_depth >= 2);
--stack_depth;
- assert(dst_type == nir_type_float);
texture_data[stack_depth - 1] =
- nir_fadd(b, texture_data[stack_depth - 1],
- texture_data[stack_depth]);
+ nir_build_alu(b, combine_op,
+ texture_data[stack_depth - 1],
+ texture_data[stack_depth],
+ NULL, NULL);
}
}
/* We should have just 1 sample on the stack now. */
assert(stack_depth == 1);
- texture_data[0] = nir_fmul(b, texture_data[0],
- nir_imm_float(b, 1.0 / tex_samples));
+ if (filter == BLORP_FILTER_AVERAGE) {
+ assert(dst_type == nir_type_float);
+ texture_data[0] = nir_fmul(b, texture_data[0],
+ nir_imm_float(b, 1.0 / tex_samples));
+ }
nir_store_var(b, color, texture_data[0], 0xf);
return nir_load_var(b, color);
}
-static inline nir_ssa_def *
-nir_imm_vec2(nir_builder *build, float x, float y)
-{
- nir_const_value v;
-
- memset(&v, 0, sizeof(v));
- v.f32[0] = x;
- v.f32[1] = y;
-
- return nir_build_imm(build, 4, 32, v);
-}
-
static nir_ssa_def *
blorp_nir_manual_blend_bilinear(nir_builder *b, nir_ssa_def *pos,
unsigned tex_samples,
isl_format_get_num_channels(key->src_format);
color = nir_channels(b, color, (1 << src_channels) - 1);
- color = nir_format_bitcast_uint_vec_unmasked(b, color, src_bpc, dst_bpc);
+ color = nir_format_bitcast_uvec_unmasked(b, color, src_bpc, dst_bpc);
}
/* Blorp likes to assume that colors are vec4s */
nir_ssa_def *value;
if (key->dst_format == ISL_FORMAT_R24_UNORM_X8_TYPELESS) {
- /* The destination image is bound as R32_UNORM but the data needs to be
+ /* The destination image is bound as R32_UINT but the data needs to be
* in R24_UNORM_X8_TYPELESS. The bottom 24 are the actual data and the
* top 8 need to be zero. We can accomplish this by simply multiplying
* by a factor to scale things down.
*/
- float factor = (float)((1 << 24) - 1) / (float)UINT32_MAX;
- value = nir_fmul(b, nir_fsat(b, nir_channel(b, color, 0)),
- nir_imm_float(b, factor));
+ unsigned factor = (1 << 24) - 1;
+ value = nir_fsat(b, nir_channel(b, color, 0));
+ value = nir_f2i32(b, nir_fmul(b, value, nir_imm_float(b, factor)));
} else if (key->dst_format == ISL_FORMAT_L8_UNORM_SRGB) {
value = nir_format_linear_to_srgb(b, nir_channel(b, color, 0));
} else if (key->dst_format == ISL_FORMAT_R8G8B8_UNORM_SRGB) {
(key->dst_samples <= 1));
nir_builder b;
- nir_builder_init_simple_shader(&b, mem_ctx, MESA_SHADER_FRAGMENT, NULL);
+ blorp_nir_init_shader(&b, mem_ctx, MESA_SHADER_FRAGMENT, NULL);
struct brw_blorp_blit_vars v;
brw_blorp_blit_vars_init(&b, &v, key);
break;
case BLORP_FILTER_AVERAGE:
+ case BLORP_FILTER_MIN_SAMPLE:
+ case BLORP_FILTER_MAX_SAMPLE:
assert(!key->src_tiled_w);
assert(key->tex_samples == key->src_samples);
assert(key->tex_layout == key->src_layout);
* to multiply our X and Y coordinates each by 2 and then add 1.
*/
assert(key->src_coords_normalized);
+ assert(key->filter == BLORP_FILTER_AVERAGE);
src_pos = nir_fadd(&b,
nir_i2f32(&b, src_pos),
nir_imm_float(&b, 0.5f));
color = blorp_nir_tex(&b, &v, key, src_pos);
} else {
/* Gen7+ hardware doesn't automaticaly blend. */
- color = blorp_nir_manual_blend_average(&b, &v, src_pos, key->src_samples,
- key->tex_aux_usage,
- key->texture_data_type);
+ color = blorp_nir_combine_samples(&b, &v, src_pos, key->src_samples,
+ key->tex_aux_usage,
+ key->texture_data_type,
+ key->filter);
}
break;
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) {
}
static bool
-brw_blorp_get_blit_kernel(struct blorp_context *blorp,
+brw_blorp_get_blit_kernel(struct blorp_batch *batch,
struct blorp_params *params,
const struct brw_blorp_blit_prog_key *prog_key)
{
- if (blorp->lookup_shader(blorp, prog_key, sizeof(*prog_key),
+ struct blorp_context *blorp = batch->blorp;
+
+ if (blorp->lookup_shader(batch, prog_key, sizeof(*prog_key),
¶ms->wm_prog_kernel, ¶ms->wm_prog_data))
return true;
&prog_data);
bool result =
- blorp->upload_shader(blorp, prog_key, sizeof(*prog_key),
+ blorp->upload_shader(batch, prog_key, sizeof(*prog_key),
program, prog_data.base.program_size,
&prog_data.base, sizeof(prog_data),
¶ms->wm_prog_kernel, ¶ms->wm_prog_data);
{
bool ok UNUSED;
+ /* It would be insane to try and do this on a compressed surface */
+ assert(info->aux_usage == ISL_AUX_USAGE_NONE);
+
/* Just bail if we have nothing to do. */
if (info->surf.dim == ISL_SURF_DIM_2D &&
info->view.base_level == 0 && info->view.base_array_layer == 0 &&
isl_format_rgbx_to_rgba(params->dst.view.format);
} else if (params->dst.view.format == ISL_FORMAT_R24_UNORM_X8_TYPELESS) {
wm_prog_key->dst_format = params->dst.view.format;
- params->dst.view.format = ISL_FORMAT_R32_UNORM;
+ params->dst.view.format = ISL_FORMAT_R32_UINT;
} else if (params->dst.view.format == ISL_FORMAT_A4B4G4R4_UNORM) {
params->dst.view.swizzle =
isl_swizzle_compose(params->dst.view.swizzle,
/* For some texture types, we need to pass the layer through the sampler. */
params->wm_inputs.src_z = params->src.z_offset;
- if (!brw_blorp_get_blit_kernel(batch->blorp, params, wm_prog_key))
+ if (!brw_blorp_get_blit_kernel(batch, params, wm_prog_key))
return 0;
- if (!blorp_ensure_sf_program(batch->blorp, params))
+ if (!blorp_ensure_sf_program(batch, params))
return 0;
unsigned result = 0;
x_offset_sa = (uint32_t)*x0 * px_size_sa.w + info->tile_x_sa;
y_offset_sa = (uint32_t)*y0 * px_size_sa.h + info->tile_y_sa;
isl_tiling_get_intratile_offset_sa(info->surf.tiling,
- info->surf.format, info->surf.row_pitch,
+ info->surf.format, info->surf.row_pitch_B,
x_offset_sa, y_offset_sa,
&byte_offset,
&info->tile_x_sa, &info->tile_y_sa);
}
}
+ /* ISL_FORMAT_R24_UNORM_X8_TYPELESS it isn't supported as a render target,
+ * which requires shader math to render to it. Blitting Z24X8 to Z24X8
+ * is fairly common though, so we'd like to avoid it. Since we don't need
+ * to blend depth values, we can simply pick a renderable format with the
+ * right number of bits-per-pixel, like 8-bit BGRA.
+ */
+ if (dst_surf->surf->format == ISL_FORMAT_R24_UNORM_X8_TYPELESS &&
+ src_surf->surf->format == ISL_FORMAT_R24_UNORM_X8_TYPELESS) {
+ src_format = dst_format = ISL_FORMAT_B8G8R8A8_UNORM;
+ }
+
brw_blorp_surface_info_init(batch->blorp, ¶ms.src, src_surf, src_level,
src_layer, src_format, false);
brw_blorp_surface_info_init(batch->blorp, ¶ms.dst, dst_surf, dst_level,
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
*y /= fmtl->bh;
}
- info->surf.logical_level0_px.width =
- DIV_ROUND_UP(info->surf.logical_level0_px.width, fmtl->bw);
- info->surf.logical_level0_px.height =
- DIV_ROUND_UP(info->surf.logical_level0_px.height, fmtl->bh);
-
- assert(info->surf.phys_level0_sa.width % fmtl->bw == 0);
- assert(info->surf.phys_level0_sa.height % fmtl->bh == 0);
- info->surf.phys_level0_sa.width /= fmtl->bw;
- info->surf.phys_level0_sa.height /= fmtl->bh;
+ info->surf.logical_level0_px = isl_surf_get_logical_level0_el(&info->surf);
+ info->surf.phys_level0_sa = isl_surf_get_phys_level0_el(&info->surf);
assert(info->tile_x_sa % fmtl->bw == 0);
assert(info->tile_y_sa % fmtl->bh == 0);
.levels = 1,
.array_len = 1,
.samples = 1,
- .row_pitch = width * block_size,
+ .row_pitch_B = width * block_size,
.usage = ISL_SURF_USAGE_TEXTURE_BIT |
ISL_SURF_USAGE_RENDER_TARGET_BIT,
.tiling_flags = ISL_TILING_LINEAR_BIT);