X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_meta_fast_clear.c;h=76988bfda7bdff230da0c50c86aaec7bb44f5310;hb=e54b2e902aba22f697c0ba8622cd0a905f1edfff;hp=fbde3f04204b6e91e27cad88513ffc16cd558e15;hpb=8a0c85b25853decb4a110b6d36d79c4f095d437b;p=mesa.git 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 fbde3f04204..76988bfda7b 100644 --- a/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c +++ b/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c @@ -26,6 +26,7 @@ #include "main/context.h" #include "main/objectlabel.h" #include "main/shaderapi.h" +#include "main/shaderobj.h" #include "main/arrayobj.h" #include "main/bufferobj.h" #include "main/buffers.h" @@ -36,11 +37,15 @@ #include "main/varray.h" #include "main/uniforms.h" #include "main/fbobject.h" +#include "main/framebuffer.h" +#include "main/renderbuffer.h" #include "main/texobj.h" #include "main/api_validate.h" #include "main/state.h" +#include "util/format_srgb.h" + #include "vbo/vbo_context.h" #include "drivers/common/meta.h" @@ -48,15 +53,18 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_draw.h" +#include "brw_state.h" #include "intel_fbo.h" #include "intel_batchbuffer.h" #include "brw_blorp.h" +#include "brw_meta_util.h" struct brw_fast_clear_state { + struct gl_buffer_object *buf_obj; + struct gl_vertex_array_object *array_obj; + struct gl_shader_program *shader_prog; GLuint vao; - GLuint vbo; - GLuint shader_prog; GLint color_location; }; @@ -64,11 +72,11 @@ static bool brw_fast_clear_init(struct brw_context *brw) { struct brw_fast_clear_state *clear; + struct gl_context *ctx = &brw->ctx; if (brw->fast_clear_state) { clear = brw->fast_clear_state; _mesa_BindVertexArray(clear->vao); - _mesa_BindBuffer(GL_ARRAY_BUFFER, clear->vbo); return true; } @@ -79,10 +87,21 @@ brw_fast_clear_init(struct brw_context *brw) memset(clear, 0, sizeof *clear); _mesa_GenVertexArrays(1, &clear->vao); _mesa_BindVertexArray(clear->vao); - _mesa_GenBuffers(1, &clear->vbo); - _mesa_BindBuffer(GL_ARRAY_BUFFER, clear->vbo); - _mesa_VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0); - _mesa_EnableVertexAttribArray(0); + + clear->buf_obj = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF); + if (clear->buf_obj == NULL) + return false; + + clear->array_obj = _mesa_lookup_vao(ctx, clear->vao); + assert(clear->array_obj != NULL); + + _mesa_update_array_format(ctx, clear->array_obj, VERT_ATTRIB_GENERIC(0), + 2, GL_FLOAT, GL_RGBA, GL_FALSE, GL_FALSE, GL_FALSE, + 0, true); + _mesa_bind_vertex_buffer(ctx, clear->array_obj, VERT_ATTRIB_GENERIC(0), + clear->buf_obj, 0, sizeof(float) * 2); + _mesa_enable_vertex_array_attrib(ctx, clear->array_obj, + VERT_ATTRIB_GENERIC(0)); return true; } @@ -93,7 +112,8 @@ brw_bind_rep_write_shader(struct brw_context *brw, float *color) const char *vs_source = "#extension GL_AMD_vertex_shader_layer : enable\n" "#extension GL_ARB_draw_instanced : enable\n" - "attribute vec4 position;\n" + "#extension GL_ARB_explicit_attrib_location : enable\n" + "layout(location = 0) in vec4 position;\n" "uniform int layer;\n" "void main()\n" "{\n" @@ -109,32 +129,23 @@ brw_bind_rep_write_shader(struct brw_context *brw, float *color) " gl_FragColor = color;\n" "}\n"; - GLuint vs, fs; struct brw_fast_clear_state *clear = brw->fast_clear_state; struct gl_context *ctx = &brw->ctx; if (clear->shader_prog) { - _mesa_UseProgram(clear->shader_prog); + _mesa_meta_use_program(ctx, clear->shader_prog); _mesa_Uniform4fv(clear->color_location, 1, color); return; } - vs = _mesa_meta_compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); - fs = _mesa_meta_compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); - - clear->shader_prog = _mesa_CreateProgram(); - _mesa_AttachShader(clear->shader_prog, fs); - _mesa_DeleteShader(fs); - _mesa_AttachShader(clear->shader_prog, vs); - _mesa_DeleteShader(vs); - _mesa_BindAttribLocation(clear->shader_prog, 0, "position"); - _mesa_ObjectLabel(GL_PROGRAM, clear->shader_prog, -1, "meta repclear"); - _mesa_LinkProgram(clear->shader_prog); + _mesa_meta_compile_and_link_program(ctx, vs_source, fs_source, + "meta repclear", + &clear->shader_prog); clear->color_location = - _mesa_GetUniformLocation(clear->shader_prog, "color"); + _mesa_program_resource_location(clear->shader_prog, GL_UNIFORM, "color"); - _mesa_UseProgram(clear->shader_prog); + _mesa_meta_use_program(ctx, clear->shader_prog); _mesa_Uniform4fv(clear->color_location, 1, color); } @@ -150,8 +161,8 @@ brw_meta_fast_clear_free(struct brw_context *brw) _mesa_make_current(&brw->ctx, NULL, NULL); _mesa_DeleteVertexArrays(1, &clear->vao); - _mesa_DeleteBuffers(1, &clear->vbo); - _mesa_DeleteProgram(clear->shader_prog); + _mesa_reference_buffer_object(&brw->ctx, &clear->buf_obj, NULL); + _mesa_reference_shader_program(&brw->ctx, &clear->shader_prog, NULL); free(clear); if (old_context) @@ -161,12 +172,14 @@ brw_meta_fast_clear_free(struct brw_context *brw) } struct rect { - int x0, y0, x1, y1; + unsigned x0, y0, x1, y1; }; static void -brw_draw_rectlist(struct gl_context *ctx, struct rect *rect, int num_instances) +brw_draw_rectlist(struct brw_context *brw, struct rect *rect, int num_instances) { + struct gl_context *ctx = &brw->ctx; + struct brw_fast_clear_state *clear = brw->fast_clear_state; int start = 0, count = 3; struct _mesa_prim prim; float verts[6]; @@ -179,8 +192,8 @@ brw_draw_rectlist(struct gl_context *ctx, struct rect *rect, int num_instances) verts[5] = rect->y0; /* upload new vertex data */ - _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, - GL_DYNAMIC_DRAW_ARB); + _mesa_buffer_data(ctx, clear->buf_obj, GL_NONE, sizeof(verts), verts, + GL_DYNAMIC_DRAW, __func__); if (ctx->NewState) _mesa_update_state(ctx); @@ -203,14 +216,19 @@ brw_draw_rectlist(struct gl_context *ctx, struct rect *rect, int num_instances) NULL, 0, NULL); } -static void -get_fast_clear_rect(struct gl_framebuffer *fb, - struct intel_renderbuffer *irb, struct rect *rect) +void +brw_get_fast_clear_rect(const struct brw_context *brw, + const struct gl_framebuffer *fb, + const struct intel_mipmap_tree* mt, + unsigned *x0, unsigned *y0, + unsigned *x1, unsigned *y1) { unsigned int x_align, y_align; unsigned int x_scaledown, y_scaledown; - if (irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE) { + /* Only single sampled surfaces need to (and actually can) be resolved. */ + if (mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE || + intel_miptree_is_lossless_compressed(brw, mt)) { /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render * Target(s)", beneath the "Fast Color Clear" bullet (p327): * @@ -226,9 +244,16 @@ get_fast_clear_rect(struct gl_framebuffer *fb, * alignment size returned by intel_get_non_msrt_mcs_alignment(), but * with X alignment multiplied by 16 and Y alignment multiplied by 32. */ - intel_get_non_msrt_mcs_alignment(irb->mt, &x_align, &y_align); + intel_get_non_msrt_mcs_alignment(mt, &x_align, &y_align); x_align *= 16; - y_align *= 32; + + /* SKL+ line alignment requirement for Y-tiled are half those of the prior + * generations. + */ + if (brw->gen >= 9) + y_align *= 16; + else + y_align *= 32; /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render * Target(s)", beneath the "Fast Color Clear" bullet (p327): @@ -265,8 +290,10 @@ get_fast_clear_rect(struct gl_framebuffer *fb, * terms of (width,height) of the RT. * * MSAA Width of Clear Rect Height of Clear Rect + * 2X Ceil(1/8*width) Ceil(1/2*height) * 4X Ceil(1/8*width) Ceil(1/2*height) * 8X Ceil(1/2*width) Ceil(1/2*height) + * 16X width Ceil(1/2*height) * * The text "with upper left co-ordinate to coincide with actual * rectangle being cleared" is a little confusing--it seems to imply @@ -281,7 +308,7 @@ get_fast_clear_rect(struct gl_framebuffer *fb, * vertically and either 4 or 16 horizontally, and the scaledown * factor is 2 vertically and either 2 or 8 horizontally. */ - switch (irb->mt->num_samples) { + switch (mt->num_samples) { case 2: case 4: x_scaledown = 8; @@ -289,6 +316,9 @@ get_fast_clear_rect(struct gl_framebuffer *fb, case 8: x_scaledown = 2; break; + case 16: + x_scaledown = 1; + break; default: unreachable("Unexpected sample count for fast clear"); } @@ -297,34 +327,35 @@ get_fast_clear_rect(struct gl_framebuffer *fb, y_align = y_scaledown * 2; } - rect->x0 = fb->_Xmin; - rect->x1 = fb->_Xmax; + *x0 = fb->_Xmin; + *x1 = fb->_Xmax; if (fb->Name != 0) { - rect->y0 = fb->_Ymin; - rect->y1 = fb->_Ymax; + *y0 = fb->_Ymin; + *y1 = fb->_Ymax; } else { - rect->y0 = fb->Height - fb->_Ymax; - rect->y1 = fb->Height - fb->_Ymin; + *y0 = fb->Height - fb->_Ymax; + *y1 = fb->Height - fb->_Ymin; } - rect->x0 = ROUND_DOWN_TO(rect->x0, x_align) / x_scaledown; - rect->y0 = ROUND_DOWN_TO(rect->y0, y_align) / y_scaledown; - rect->x1 = ALIGN(rect->x1, x_align) / x_scaledown; - rect->y1 = ALIGN(rect->y1, y_align) / y_scaledown; + *x0 = ROUND_DOWN_TO(*x0, x_align) / x_scaledown; + *y0 = ROUND_DOWN_TO(*y0, y_align) / y_scaledown; + *x1 = ALIGN(*x1, x_align) / x_scaledown; + *y1 = ALIGN(*y1, y_align) / y_scaledown; } -static void -get_buffer_rect(struct brw_context *brw, struct gl_framebuffer *fb, - struct intel_renderbuffer *irb, struct rect *rect) +void +brw_meta_get_buffer_rect(const struct gl_framebuffer *fb, + unsigned *x0, unsigned *y0, + unsigned *x1, unsigned *y1) { - rect->x0 = fb->_Xmin; - rect->x1 = fb->_Xmax; + *x0 = fb->_Xmin; + *x1 = fb->_Xmax; if (fb->Name != 0) { - rect->y0 = fb->_Ymin; - rect->y1 = fb->_Ymax; + *y0 = fb->_Ymin; + *y1 = fb->_Ymax; } else { - rect->y0 = fb->Height - fb->_Ymax; - rect->y1 = fb->Height - fb->_Ymin; + *y0 = fb->Height - fb->_Ymax; + *y1 = fb->Height - fb->_Ymin; } } @@ -334,11 +365,38 @@ get_buffer_rect(struct brw_context *brw, struct gl_framebuffer *fb, * Fast color clear can only clear to color values of 1.0 or 0.0. At the * moment we only support floating point, unorm, and snorm buffers. */ -static bool -is_color_fast_clear_compatible(struct brw_context *brw, - mesa_format format, - const union gl_color_union *color) +bool +brw_is_color_fast_clear_compatible(struct brw_context *brw, + const struct intel_mipmap_tree *mt, + const union gl_color_union *color) { + const struct gl_context *ctx = &brw->ctx; + + /* If we're mapping the render format to a different format than the + * format we use for texturing then it is a bit questionable whether it + * should be possible to use a fast clear. Although we only actually + * render using a renderable format, without the override workaround it + * wouldn't be possible to have a non-renderable surface in a fast clear + * state so the hardware probably legitimately doesn't need to support + * this case. At least on Gen9 this really does seem to cause problems. + */ + if (brw->gen >= 9 && + brw_format_for_mesa_format(mt->format) != + brw->render_target_format[mt->format]) + return false; + + /* Gen9 doesn't support fast clear on single-sampled SRGB buffers. When + * GL_FRAMEBUFFER_SRGB is enabled any color renderbuffers will be + * resolved in intel_update_state. In that case it's pointless to do a + * fast clear because it's very likely to be immediately resolved. + */ + if (brw->gen >= 9 && + mt->num_samples <= 1 && + ctx->Color.sRGBEnabled && + _mesa_get_srgb_format_linear(mt->format) != mt->format) + return false; + + const mesa_format format = _mesa_get_render_format(ctx, mt->format); if (_mesa_is_format_integer_color(format)) { if (brw->gen >= 8) { perf_debug("Integer fast clear not enabled for (%s)", @@ -348,8 +406,12 @@ is_color_fast_clear_compatible(struct brw_context *brw, } for (int i = 0; i < 4; i++) { - if (color->f[i] != 0.0f && color->f[i] != 1.0f && - _mesa_format_has_color_component(format, i)) { + if (!_mesa_format_has_color_component(format, i)) { + continue; + } + + if (brw->gen < 9 && + color->f[i] != 0.0f && color->f[i] != 1.0f) { return false; } } @@ -358,18 +420,64 @@ is_color_fast_clear_compatible(struct brw_context *brw, /** * Convert the given color to a bitfield suitable for ORing into DWORD 7 of - * SURFACE_STATE. + * SURFACE_STATE (DWORD 12-15 on SKL+). */ -static uint32_t -compute_fast_clear_color_bits(const union gl_color_union *color) +void +brw_meta_set_fast_clear_color(struct brw_context *brw, + struct intel_mipmap_tree *mt, + const union gl_color_union *color) { - uint32_t bits = 0; - for (int i = 0; i < 4; i++) { - /* Testing for non-0 works for integer and float colors */ - if (color->f[i] != 0.0f) - bits |= 1 << (GEN7_SURFACE_CLEAR_COLOR_SHIFT + (3 - i)); + union gl_color_union override_color = *color; + + /* The sampler doesn't look at the format of the surface when the fast + * clear color is used so we need to implement luminance, intensity and + * missing components manually. + */ + switch (_mesa_get_format_base_format(mt->format)) { + case GL_INTENSITY: + override_color.ui[3] = override_color.ui[0]; + /* flow through */ + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + override_color.ui[1] = override_color.ui[0]; + override_color.ui[2] = override_color.ui[0]; + break; + default: + for (int i = 0; i < 3; i++) { + if (!_mesa_format_has_color_component(mt->format, i)) + override_color.ui[i] = 0; + } + break; + } + + if (!_mesa_format_has_color_component(mt->format, 3)) { + if (_mesa_is_format_integer_color(mt->format)) + override_color.ui[3] = 1; + else + override_color.f[3] = 1.0f; + } + + /* Handle linear→SRGB conversion */ + if (brw->ctx.Color.sRGBEnabled && + _mesa_get_srgb_format_linear(mt->format) != mt->format) { + for (int i = 0; i < 3; i++) { + override_color.f[i] = + util_format_linear_to_srgb_float(override_color.f[i]); + } + } + + if (brw->gen >= 9) { + mt->gen9_fast_clear_color = override_color; + } else { + mt->fast_clear_color_value = 0; + for (int i = 0; i < 4; i++) { + /* Testing for non-0 works for integer and float colors */ + if (override_color.f[i] != 0.0f) { + mt->fast_clear_color_value |= + 1 << (GEN7_SURFACE_CLEAR_COLOR_SHIFT + (3 - i)); + } + } } - return bits; } static const uint32_t fast_clear_color[4] = { ~0, ~0, ~0, ~0 }; @@ -409,12 +517,75 @@ 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) +{ + struct gl_context *ctx = &brw->ctx; + const bool srgb_enabled = ctx->Color.sRGBEnabled; + + assert(brw->gen >= 9); + + /* Make sure the GL_FRAMEBUFFER_SRGB is disabled during fast clear so that + * the surface state will always be uploaded with a linear buffer. SRGB + * buffers are not supported on Gen9 because they are not marked as + * losslessly compressible. This shouldn't matter for the fast clear + * because the color is not written to the framebuffer yet so the hardware + * doesn't need to do any SRGB conversion. + */ + if (srgb_enabled) + _mesa_set_framebuffer_srgb(ctx, GL_FALSE); + + 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(brw, &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); + + if (srgb_enabled) + _mesa_set_framebuffer_srgb(ctx, GL_TRUE); +} + bool brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb, GLbitfield buffers, bool partial_clear) { struct gl_context *ctx = &brw->ctx; - mesa_format format; enum { FAST_CLEAR, REP_CLEAR, PLAIN_CLEAR } clear_type; GLbitfield plain_clear_buffers, meta_save, rep_clear_buffers, fast_clear_buffers; struct rect fast_clear_rect, clear_rect; @@ -451,11 +622,6 @@ brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb, if (irb->mt->fast_clear_state == INTEL_FAST_CLEAR_STATE_NO_MCS) clear_type = REP_CLEAR; - if (brw->gen >= 9 && clear_type == FAST_CLEAR) { - perf_debug("fast MCS clears are disabled on gen9"); - clear_type = REP_CLEAR; - } - /* We can't do scissored fast clears because of the restrictions on the * fast clear rectangle size. */ @@ -465,8 +631,8 @@ brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb, /* Fast clear is only supported for colors where all components are * either 0 or 1. */ - format = _mesa_get_render_format(ctx, irb->mt->format); - if (!is_color_fast_clear_compatible(brw, format, &ctx->Color.ClearColor)) + if (!brw_is_color_fast_clear_compatible(brw, irb->mt, + &ctx->Color.ClearColor)) clear_type = REP_CLEAR; /* From the SNB PRM (Vol4_Part1): @@ -487,6 +653,7 @@ brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb, GLubyte *color_mask = ctx->Color.ColorMask[buf]; for (int i = 0; i < 4; i++) { if (_mesa_format_has_color_component(irb->mt->format, i) && + !(i == 3 && irb->Base.Base._BaseFormat == GL_RGB) && !color_mask[i]) { perf_debug("Falling back to plain clear on %dx%d buffer because of color mask\n", irb->mt->logical_width0, irb->mt->logical_height0); @@ -504,8 +671,7 @@ brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb, switch (clear_type) { case FAST_CLEAR: - irb->mt->fast_clear_color_value = - compute_fast_clear_color_bits(&ctx->Color.ClearColor); + brw_meta_set_fast_clear_color(brw, irb->mt, &ctx->Color.ClearColor); irb->need_downsample = true; /* If the buffer is already in INTEL_FAST_CLEAR_STATE_CLEAR, the @@ -521,21 +687,29 @@ brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb, irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED; irb->need_downsample = true; fast_clear_buffers |= 1 << index; - get_fast_clear_rect(fb, irb, &fast_clear_rect); + brw_get_fast_clear_rect(brw, fb, irb->mt, + &fast_clear_rect.x0, &fast_clear_rect.y0, + &fast_clear_rect.x1, &fast_clear_rect.y1); break; case REP_CLEAR: rep_clear_buffers |= 1 << index; - get_buffer_rect(brw, fb, irb, &clear_rect); + brw_meta_get_buffer_rect(fb, + &clear_rect.x0, &clear_rect.y0, + &clear_rect.x1, &clear_rect.y1); break; case PLAIN_CLEAR: plain_clear_buffers |= 1 << index; - get_buffer_rect(brw, fb, irb, &clear_rect); + brw_meta_get_buffer_rect(fb, + &clear_rect.x0, &clear_rect.y0, + &clear_rect.x1, &clear_rect.y1); continue; } } + assert((fast_clear_buffers & rep_clear_buffers) == 0); + if (!(fast_clear_buffers | rep_clear_buffers)) { if (plain_clear_buffers) /* If we only have plain clears, skip the meta save/restore. */ @@ -583,30 +757,33 @@ 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); + brw_draw_rectlist(brw, &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) { _mesa_meta_drawbuffers_from_bitfield(rep_clear_buffers); brw_bind_rep_write_shader(brw, ctx->Color.ClearColor.f); - 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; + brw_draw_rectlist(brw, &clear_rect, layers); } bail_to_meta: @@ -640,9 +817,11 @@ brw_meta_fast_clear(struct brw_context *brw, struct gl_framebuffer *fb, return true; } -static void -get_resolve_rect(struct brw_context *brw, - struct intel_mipmap_tree *mt, struct rect *rect) +void +brw_get_resolve_rect(const struct brw_context *brw, + const struct intel_mipmap_tree *mt, + unsigned *x0, unsigned *y0, + unsigned *x1, unsigned *y1) { unsigned x_align, y_align; unsigned x_scaledown, y_scaledown; @@ -654,8 +833,9 @@ get_resolve_rect(struct brw_context *brw, * * The scaledown factors in the table that follows are related to the * alignment size returned by intel_get_non_msrt_mcs_alignment() by a - * multiplier. For IVB and HSW, we divide by two, for BDW we multiply - * by 8 and 16 and 8 and 8 for SKL. + * multiplier. For IVB and HSW, we divide by two, for BDW we multiply + * by 8 and 16. Similar to the fast clear, SKL eases the BDW vertical scaling + * by a factor of 2. */ intel_get_non_msrt_mcs_alignment(mt, &x_align, &y_align); @@ -669,9 +849,9 @@ get_resolve_rect(struct brw_context *brw, x_scaledown = x_align / 2; y_scaledown = y_align / 2; } - rect->x0 = rect->y0 = 0; - rect->x1 = ALIGN(mt->logical_width0, x_scaledown) / x_scaledown; - rect->y1 = ALIGN(mt->logical_height0, y_scaledown) / y_scaledown; + *x0 = *y0 = 0; + *x1 = ALIGN(mt->logical_width0, x_scaledown) / x_scaledown; + *y1 = ALIGN(mt->logical_height0, y_scaledown) / y_scaledown; } void @@ -679,20 +859,25 @@ brw_meta_resolve_color(struct brw_context *brw, struct intel_mipmap_tree *mt) { struct gl_context *ctx = &brw->ctx; - GLuint fbo, rbo; + struct gl_framebuffer *drawFb; + struct gl_renderbuffer *rb; struct rect rect; brw_emit_mi_flush(brw); + drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); + if (drawFb == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "in %s", __func__); + return; + } + _mesa_meta_begin(ctx, MESA_META_ALL); - _mesa_GenFramebuffers(1, &fbo); - rbo = brw_get_rb_for_slice(brw, mt, 0, 0, false); + rb = brw_get_rb_for_slice(brw, mt, 0, 0, false); - _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); - _mesa_FramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, rbo); + _mesa_bind_framebuffers(ctx, drawFb, ctx->ReadBuffer); + _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0, + rb); _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0); brw_fast_clear_init(brw); @@ -701,18 +886,25 @@ brw_meta_resolve_color(struct brw_context *brw, brw_bind_rep_write_shader(brw, (float *) fast_clear_color); - set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE); + /* 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. + */ + if (intel_miptree_is_lossless_compressed(brw, mt)) + set_fast_clear_op(brw, GEN9_PS_RENDER_TARGET_RESOLVE_FULL); + else + set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE); mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED; - get_resolve_rect(brw, mt, &rect); + brw_get_resolve_rect(brw, mt, &rect.x0, &rect.y0, &rect.x1, &rect.y1); - brw_draw_rectlist(ctx, &rect, 1); + brw_draw_rectlist(brw, &rect, 1); set_fast_clear_op(brw, 0); use_rectlist(brw, false); - _mesa_DeleteRenderbuffers(1, &rbo); - _mesa_DeleteFramebuffers(1, &fbo); + _mesa_reference_renderbuffer(&rb, NULL); + _mesa_reference_framebuffer(&drawFb, NULL); _mesa_meta_end(ctx);