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 <ben@bwidawsk.net> Reviewed-by: Chad Versace <chad.versace@intel.com> Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
parent
6fa1130cd2
commit
c4edc048c6
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue