<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, May 13, 2016 at 10:49 AM, Jason Ekstrand <span dir="ltr"><<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Wed, May 11, 2016 at 7:42 PM, Jason Ekstrand <span dir="ltr"><<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>The current MSAA resolve code has a special-case for if the MCS value is 0.<br>
In this case we can only sample once because we know that all values are in<br>
slice 0. This commit adds a second optimization that detecs the magic MCS<br>
value that indicates the clear color and grabs the color from a push<br>
constant and avoids sampling altogether. On a microbenchmark written by<br>
Neil Roberts that tests resolving surfaces with just clear color, this<br>
improves performance by 60% for 8x, 40% for 4x, and 28% for 2x MSAA on my<br>
SKL gte3 laptop. The benchmark can be found on the ML archive:<br>
<br>
<a href="https://lists.freedesktop.org/archives/mesa-dev/2016-February/108077.html" rel="noreferrer" target="_blank">https://lists.freedesktop.org/archives/mesa-dev/2016-February/108077.html</a><br></span></blockquote></div></div></div></div></div></blockquote><div><br></div><div>More data: It seems to help T-Rex on Haswell by maybe 0.5% and hurts some of the cpu-bound synthetics just a bit. Meh?<br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>
---<br>
src/mesa/drivers/dri/i965/brw_blorp.h | 4 +-<br>
</span> src/mesa/drivers/dri/i965/brw_blorp_blit.cpp | 101 +++++++++++++++++++++++++--<br>
2 files changed, 100 insertions(+), 5 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_blorp.h b/src/mesa/drivers/dri/i965/brw_blorp.h<br>
index 15114d0..9d71ca4 100644<br>
<span>--- a/src/mesa/drivers/dri/i965/brw_blorp.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_blorp.h<br>
@@ -197,7 +197,9 @@ struct brw_blorp_wm_push_constants<br>
uint32_t src_z;<br>
<br>
/* Pad out to an integral number of registers */<br>
- uint32_t pad[5];<br>
+ uint32_t pad;<br>
+<br>
+ union gl_color_union clear_color;<br>
};<br>
<br>
#define BRW_BLORP_NUM_PUSH_CONSTANT_DWORDS \<br>
diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp<br>
</span>index 514a316..45b696d 100644<br>
<div><div>--- a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp<br>
@@ -346,6 +346,7 @@ struct brw_blorp_blit_vars {<br>
nir_variable *offset;<br>
} u_x_transform, u_y_transform;<br>
nir_variable *u_src_z;<br>
+ nir_variable *u_clear_color;<br>
<br>
/* gl_FragCoord */<br>
nir_variable *frag_coord;<br>
@@ -374,6 +375,7 @@ brw_blorp_blit_vars_init(nir_builder *b, struct brw_blorp_blit_vars *v,<br>
LOAD_UNIFORM(y_transform.multiplier, glsl_float_type())<br>
LOAD_UNIFORM(y_transform.offset, glsl_float_type())<br>
LOAD_UNIFORM(src_z, glsl_uint_type())<br>
+ LOAD_UNIFORM(clear_color, glsl_vec4_type())<br>
<br>
#undef DECL_UNIFORM<br>
<br>
@@ -858,7 +860,8 @@ static nir_ssa_def *<br>
blorp_nir_manual_blend_average(nir_builder *b, nir_ssa_def *pos,<br>
unsigned tex_samples,<br>
enum intel_msaa_layout tex_layout,<br>
- enum brw_reg_type dst_type)<br>
+ enum brw_reg_type dst_type,<br>
+ struct brw_blorp_blit_vars *v)<br>
{<br>
/* If non-null, this is the outer-most if statement */<br>
nir_if *outer_if = NULL;<br>
@@ -867,9 +870,53 @@ blorp_nir_manual_blend_average(nir_builder *b, nir_ssa_def *pos,<br>
nir_local_variable_create(b->impl, glsl_vec4_type(), "color");<br>
<br>
nir_ssa_def *mcs = NULL;<br>
- if (tex_layout == INTEL_MSAA_LAYOUT_CMS)<br>
+ if (tex_layout == INTEL_MSAA_LAYOUT_CMS) {<br>
mcs = blorp_nir_txf_ms_mcs(b, pos);<br>
<br>
+ /* The MCS buffer stores a packed value that provides a mapping from<br>
+ * samples to array slices. The magic value of all ones means that all<br>
+ * samples have the clear color. In this case, we can short-circuit the<br>
+ * sampling process and just use the clear color that we pushed into the<br>
+ * shader.<br>
+ */<br>
+ nir_ssa_def *is_clear_color;<br>
+ switch (tex_samples) {<br>
+ case 2:<br>
+ /* Empirical evidence suggests that the value returned from the<br>
+ * sampler is not always 0x3 for clear color so we need to mask it.<br>
+ */<br>
+ is_clear_color =<br>
+ nir_ieq(b, nir_iand(b, nir_channel(b, mcs, 0), nir_imm_int(b, 0x3)),<br>
+ nir_imm_int(b, 0x3));<br>
+ break;<br>
+ case 4:<br>
+ is_clear_color =<br>
+ nir_ieq(b, nir_channel(b, mcs, 0), nir_imm_int(b, 0xff));<br>
+ break;<br>
+ case 8:<br>
+ is_clear_color =<br>
+ nir_ieq(b, nir_channel(b, mcs, 0), nir_imm_int(b, ~0));<br>
+ break;<br>
+ case 16:<br>
+ is_clear_color =<br>
+ nir_ior(b, nir_ieq(b, nir_channel(b, mcs, 0), nir_imm_int(b, ~0)),<br></div></div></blockquote><div><br></div></div></div><div>This needs to be nir_iand. Fixed locally...<br></div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>
+ nir_ieq(b, nir_channel(b, mcs, 1), nir_imm_int(b, ~0)));<br>
+ break;<br>
+ default:<br>
+ unreachable("Invalid sample count");<br>
+ }<br>
+<br>
+ nir_if *if_stmt = nir_if_create(b->shader);<br>
+ if_stmt->condition = nir_src_for_ssa(is_clear_color);<br>
+ nir_cf_node_insert(b->cursor, &if_stmt->cf_node);<br>
+<br>
+ b->cursor = nir_after_cf_list(&if_stmt->then_list);<br>
+ nir_store_var(b, color, nir_load_var(b, v->u_clear_color), 0xf);<br>
+<br>
+ b->cursor = nir_after_cf_list(&if_stmt->else_list);<br>
+ outer_if = if_stmt;<br>
+ }<br>
+<br>
/* We add together samples using a binary tree structure, e.g. for 4x MSAA:<br>
*<br>
* result = ((sample[0] + sample[1]) + (sample[2] + sample[3])) / 4<br>
@@ -937,7 +984,8 @@ blorp_nir_manual_blend_average(nir_builder *b, nir_ssa_def *pos,<br>
nir_store_var(b, color, texture_data[0], 0xf);<br>
<br>
b->cursor = nir_after_cf_list(&if_stmt->else_list);<br>
- outer_if = if_stmt;<br>
+ if (!outer_if)<br>
+ outer_if = if_stmt;<br>
}<br>
<br>
for (int j = 0; j < count_trailing_one_bits(i); j++) {<br>
</div></div>@@ -1341,7 +1389,7 @@ brw_blorp_build_nir_shader(struct brw_context *brw,<br>
<span> /* Gen7+ hardware doesn't automaticaly blend. */<br>
color = blorp_nir_manual_blend_average(&b, src_pos, key->src_samples,<br>
key->src_layout,<br>
- key->texture_data_type);<br>
+ key->texture_data_type, &v);<br>
}<br>
} else if (key->blend && key->blit_scaled) {<br>
color = blorp_nir_manual_blend_bilinear(&b, src_pos, key->src_samples, key, &v);<br>
</span>@@ -1493,6 +1541,48 @@ compute_msaa_layout_for_pipeline(struct brw_context *brw, unsigned num_samples,<br>
}<br>
<br>
<br>
+static union gl_color_union<br>
+brw_blorp_get_clear_color_for_mt(struct brw_context *brw,<br>
+ struct intel_mipmap_tree *mt,<br>
+ unsigned swizzle)<br>
+{<br>
+ union gl_color_union color;<br>
<span>+ if (brw->gen >= 9) {<br>
</span>+ color = mt->gen9_fast_clear_color;<br>
+ } else if (_mesa_is_format_integer(mt->format)) {<br>
+ color.i[0] = (mt->fast_clear_color_value & (1 << 31)) != 0;<br>
+ color.i[1] = (mt->fast_clear_color_value & (1 << 30)) != 0;<br>
+ color.i[2] = (mt->fast_clear_color_value & (1 << 29)) != 0;<br>
+ color.i[3] = (mt->fast_clear_color_value & (1 << 28)) != 0;<br>
+ } else {<br>
+ color.f[0] = (mt->fast_clear_color_value & (1 << 31)) != 0;<br>
+ color.f[1] = (mt->fast_clear_color_value & (1 << 30)) != 0;<br>
+ color.f[2] = (mt->fast_clear_color_value & (1 << 29)) != 0;<br>
+ color.f[3] = (mt->fast_clear_color_value & (1 << 28)) != 0;<br>
+ }<br>
+<br>
+ if (swizzle != SWIZZLE_NOOP) {<br>
+ union gl_color_union orig_color = color;<br>
+ for (unsigned i = 0; i < 4; i++) {<br>
+ unsigned s = GET_SWZ(swizzle, i);<br>
+ if (s <= SWIZZLE_W) {<br>
+ color.i[i] = orig_color.i[s];<br>
+ } else if (s == SWIZZLE_ZERO) {<br>
+ color.i[i] = 0;<br>
+ } else {<br>
+ assert(s == SWIZZLE_ONE);<br>
+ if (_mesa_is_format_integer(mt->format))<br>
+ color.i[i] = 1;<br>
+ else<br>
+ color.f[i] = 1;<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ return color;<br>
+}<br>
+<br>
+<br>
/**<br>
* Note: if the src (or dst) is a 2D multisample array texture on Gen7+ using<br>
* INTEL_MSAA_LAYOUT_UMS or INTEL_MSAA_LAYOUT_CMS, src_layer (dst_layer) is<br>
@@ -1665,6 +1755,9 @@ brw_blorp_blit_miptrees(struct brw_context *brw,<br>
<span> params.src.num_samples <= 1 && params.dst.num_samples <= 1)<br>
wm_prog_key.bilinear_filter = true;<br>
<br>
</span>+ params.wm_push_consts.clear_color =<br>
+ brw_blorp_get_clear_color_for_mt(brw, src_mt, src_swizzle);<br>
<div><div>+<br>
GLenum base_format = _mesa_get_format_base_format(src_mt->format);<br>
if (base_format != GL_DEPTH_COMPONENT && /* TODO: what about depth/stencil? */<br>
base_format != GL_STENCIL_INDEX &&<br>
--<br>
2.5.0.400.gff86faf<br>
<br>
</div></div></blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div>