summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
authorBen Widawsky <[email protected]>2015-10-13 20:50:22 -0700
committerBen Widawsky <[email protected]>2015-11-20 11:45:32 -0800
commitc4edc048c6f6877461a9d9dc07142640f380f340 (patch)
tree304ddcaca92153f0d627176f56da35e7746aee8b /src/mesa
parent6fa1130cd21926cdd4ae86aa12ee3f5c0bb5ba33 (diff)
i965/meta/gen9: Individually fast clear color attachments
The impetus for this patch comes from a seemingly benign statement within the spec (quoted within the patch). It is very important for clearing multiple color buffer attachments and can be observed in the following piglit tests: spec/arb_framebuffer_object/fbo-drawbuffers-none glclear spec/ext_framebuffer_multisample/blit-multiple-render-targets 0 v2: Doing the framebuffer binding only once (Chad) Directly use the renderbuffers from the mt (Chad) v3: Patch from Neil whose feedback I originally missed. Signed-off-by: Ben Widawsky <[email protected]> Reviewed-by: Chad Versace <[email protected]> Reviewed-by: Neil Roberts <[email protected]>
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/drivers/dri/i965/brw_meta_fast_clear.c78
1 files changed, 65 insertions, 13 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c b/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c
index 938e028f58d..7bf68194b71 100644
--- a/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c
+++ b/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c
@@ -427,6 +427,55 @@ use_rectlist(struct brw_context *brw, bool enable)
brw->ctx.NewDriverState |= BRW_NEW_FRAGMENT_PROGRAM;
}
+/**
+ * Individually fast clear each color buffer attachment. On previous gens this
+ * isn't required. The motivation for this comes from one line (which seems to
+ * be specific to SKL+). The list item is in section titled _MCS Buffer for
+ * Render Target(s)_
+ *
+ * "Since only one RT is bound with a clear pass, only one RT can be cleared
+ * at a time. To clear multiple RTs, multiple clear passes are required."
+ *
+ * The code follows the same idea as the resolve code which creates a fake FBO
+ * to avoid interfering with too much of the GL state.
+ */
+static void
+fast_clear_attachments(struct brw_context *brw,
+ struct gl_framebuffer *fb,
+ uint32_t fast_clear_buffers,
+ struct rect fast_clear_rect)
+{
+ assert(brw->gen >= 9);
+ struct gl_context *ctx = &brw->ctx;
+
+ brw_bind_rep_write_shader(brw, (float *) fast_clear_color);
+
+ /* SKL+ also has a resolve mode for compressed render targets and thus more
+ * bits to let us select the type of resolve. For fast clear resolves, it
+ * turns out we can use the same value as pre-SKL though.
+ */
+ set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE);
+
+ while (fast_clear_buffers) {
+ int index = ffs(fast_clear_buffers) - 1;
+
+ fast_clear_buffers &= ~(1 << index);
+
+ _mesa_meta_drawbuffers_from_bitfield(1 << index);
+
+ brw_draw_rectlist(ctx, &fast_clear_rect, MAX2(1, fb->MaxNumLayers));
+
+ /* Now set the mcs we cleared to INTEL_FAST_CLEAR_STATE_CLEAR so we'll
+ * resolve them eventually.
+ */
+ struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[0];
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+ irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
+ }
+
+ set_fast_clear_op(brw, 0);
+}
+
bool
brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb,
GLbitfield buffers, bool partial_clear)
@@ -609,12 +658,27 @@ brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb,
use_rectlist(brw, true);
layers = MAX2(1, fb->MaxNumLayers);
- if (fast_clear_buffers) {
+
+ if (brw->gen >= 9 && fast_clear_buffers) {
+ fast_clear_attachments(brw, fb, fast_clear_buffers, fast_clear_rect);
+ } else if (fast_clear_buffers) {
_mesa_meta_drawbuffers_from_bitfield(fast_clear_buffers);
brw_bind_rep_write_shader(brw, (float *) fast_clear_color);
set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE);
brw_draw_rectlist(ctx, &fast_clear_rect, layers);
set_fast_clear_op(brw, 0);
+
+ /* Now set the mcs we cleared to INTEL_FAST_CLEAR_STATE_CLEAR so we'll
+ * resolve them eventually.
+ */
+ for (unsigned buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
+ struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+ int index = fb->_ColorDrawBufferIndexes[buf];
+
+ if ((1 << index) & fast_clear_buffers)
+ irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
+ }
}
if (rep_clear_buffers) {
@@ -623,18 +687,6 @@ brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb,
brw_draw_rectlist(ctx, &clear_rect, layers);
}
- /* Now set the mts we cleared to INTEL_FAST_CLEAR_STATE_CLEAR so we'll
- * resolve them eventually.
- */
- for (unsigned buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
- struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
- struct intel_renderbuffer *irb = intel_renderbuffer(rb);
- int index = fb->_ColorDrawBufferIndexes[buf];
-
- if ((1 << index) & fast_clear_buffers)
- irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
- }
-
bail_to_meta:
/* Dirty _NEW_BUFFERS so we reemit SURFACE_STATE which sets the fast clear
* color before resolve and sets irb->mt->fast_clear_state to UNRESOLVED if