static bool do_single_blorp_clear(struct brw_context *brw, struct gl_framebuffer *fb, struct gl_renderbuffer *rb, unsigned buf, bool partial_clear, bool encode_srgb, unsigned layer) { struct gl_context *ctx = &brw->ctx; struct intel_renderbuffer *irb = intel_renderbuffer(rb); mesa_format format = irb->mt->format; struct brw_blorp_params params; brw_blorp_params_init(¶ms); if (!encode_srgb && _mesa_get_format_color_encoding(format) == GL_SRGB) format = _mesa_get_srgb_format_linear(format); brw_blorp_surface_info_init(brw, ¶ms.dst, irb->mt, irb->mt_level, layer, format, true); /* Override the surface format according to the context's sRGB rules. */ params.dst.brw_surfaceformat = brw->render_target_format[format]; params.x0 = fb->_Xmin; params.x1 = fb->_Xmax; if (rb->Name != 0) { params.y0 = fb->_Ymin; params.y1 = fb->_Ymax; } else { params.y0 = rb->Height - fb->_Ymax; params.y1 = rb->Height - fb->_Ymin; } memcpy(¶ms.wm_inputs, ctx->Color.ClearColor.f, sizeof(float) * 4); bool use_simd16_replicated_data = true; /* From the SNB PRM (Vol4_Part1): * * "Replicated data (Message Type = 111) is only supported when * accessing tiled memory. Using this Message Type to access linear * (untiled) memory is UNDEFINED." */ if (irb->mt->tiling == I915_TILING_NONE) use_simd16_replicated_data = false; /* Constant color writes ignore everyting in blend and color calculator * state. This is not documented. */ if (set_write_disables(irb, ctx->Color.ColorMask[buf], params.color_write_disable)) use_simd16_replicated_data = false; if (irb->mt->fast_clear_state != INTEL_FAST_CLEAR_STATE_NO_MCS && !partial_clear && use_simd16_replicated_data && brw_is_color_fast_clear_compatible(brw, irb->mt, &ctx->Color.ClearColor)) { memset(¶ms.wm_inputs, 0xff, 4*sizeof(float)); params.fast_clear_op = GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE; brw_get_fast_clear_rect(brw, fb, irb->mt, ¶ms.x0, ¶ms.y0, ¶ms.x1, ¶ms.y1); } else { brw_meta_get_buffer_rect(fb, ¶ms.x0, ¶ms.y0, ¶ms.x1, ¶ms.y1); } brw_blorp_params_get_clear_kernel(brw, ¶ms, use_simd16_replicated_data); const bool is_fast_clear = params.fast_clear_op == GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE; if (is_fast_clear) { /* Record the clear color in the miptree so that it will be * programmed in SURFACE_STATE by later rendering and resolve * operations. */ const bool color_updated = brw_meta_set_fast_clear_color( brw, irb->mt, &ctx->Color.ClearColor); /* If the buffer is already in INTEL_FAST_CLEAR_STATE_CLEAR, the clear * is redundant and can be skipped. */ if (!color_updated && irb->mt->fast_clear_state == INTEL_FAST_CLEAR_STATE_CLEAR) return true; /* If the MCS buffer hasn't been allocated yet, we need to allocate * it now. */ if (!irb->mt->mcs_mt) { if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt)) { /* MCS allocation failed--probably this will only happen in * out-of-memory conditions. But in any case, try to recover * by falling back to a non-blorp clear technique. */ return false; } } } const char *clear_type; if (is_fast_clear) clear_type = "fast"; else if (use_simd16_replicated_data) clear_type = "replicated"; else clear_type = "slow"; DBG("%s (%s) to mt %p level %d layer %d\n", __FUNCTION__, clear_type, irb->mt, irb->mt_level, irb->mt_layer); brw_blorp_exec(brw, ¶ms); if (is_fast_clear) { /* Now that the fast clear has occurred, put the buffer in * INTEL_FAST_CLEAR_STATE_CLEAR so that we won't waste time doing * redundant clears. */ irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR; } else if (intel_miptree_is_lossless_compressed(brw, irb->mt)) { /* Compressed buffers can be cleared also using normal rep-clear. In * such case they bahave such as if they were drawn using normal 3D * render pipeline, and we simply mark the mcs as dirty. */ assert(partial_clear); irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_UNRESOLVED; } return true; }
static bool do_single_blorp_clear(struct brw_context *brw, struct gl_framebuffer *fb, struct gl_renderbuffer *rb, unsigned buf, bool partial_clear, bool encode_srgb) { struct gl_context *ctx = &brw->ctx; struct intel_renderbuffer *irb = intel_renderbuffer(rb); mesa_format format = irb->mt->format; uint32_t x0, x1, y0, y1; if (!encode_srgb && _mesa_get_format_color_encoding(format) == GL_SRGB) format = _mesa_get_srgb_format_linear(format); x0 = fb->_Xmin; x1 = fb->_Xmax; if (rb->Name != 0) { y0 = fb->_Ymin; y1 = fb->_Ymax; } else { y0 = rb->Height - fb->_Ymax; y1 = rb->Height - fb->_Ymin; } /* If the clear region is empty, just return. */ if (x0 == x1 || y0 == y1) return true; bool can_fast_clear = !partial_clear; bool color_write_disable[4] = { false, false, false, false }; if (set_write_disables(irb, ctx->Color.ColorMask[buf], color_write_disable)) can_fast_clear = false; if (irb->mt->no_ccs || !brw_is_color_fast_clear_compatible(brw, irb->mt, &ctx->Color.ClearColor)) can_fast_clear = false; const unsigned logical_layer = irb_logical_mt_layer(irb); const enum intel_fast_clear_state fast_clear_state = intel_miptree_get_fast_clear_state(irb->mt, irb->mt_level, logical_layer); /* Surface state can only record one fast clear color value. Therefore * unless different levels/layers agree on the color it can be used to * represent only single level/layer. Here it will be reserved for the * first slice (level 0, layer 0). */ if (irb->layer_count > 1 || irb->mt_level || irb->mt_layer) can_fast_clear = false; if (can_fast_clear) { union gl_color_union override_color = brw_meta_convert_fast_clear_color(brw, irb->mt, &ctx->Color.ClearColor); /* Record the clear color in the miptree so that it will be * programmed in SURFACE_STATE by later rendering and resolve * operations. */ const bool color_updated = brw_meta_set_fast_clear_color( brw, &irb->mt->gen9_fast_clear_color, &override_color); /* If the buffer is already in INTEL_FAST_CLEAR_STATE_CLEAR, the clear * is redundant and can be skipped. */ if (!color_updated && fast_clear_state == INTEL_FAST_CLEAR_STATE_CLEAR) return true; /* If the MCS buffer hasn't been allocated yet, we need to allocate * it now. */ if (!irb->mt->mcs_buf) { assert(!intel_miptree_is_lossless_compressed(brw, irb->mt)); if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt, false)) { /* MCS allocation failed--probably this will only happen in * out-of-memory conditions. But in any case, try to recover * by falling back to a non-blorp clear technique. */ return false; } } } const unsigned num_layers = fb->MaxNumLayers ? irb->layer_count : 1; /* We can't setup the blorp_surf until we've allocated the MCS above */ struct isl_surf isl_tmp[2]; struct blorp_surf surf; unsigned level = irb->mt_level; blorp_surf_for_miptree(brw, &surf, irb->mt, true, (1 << ISL_AUX_USAGE_MCS) | (1 << ISL_AUX_USAGE_CCS_E) | (1 << ISL_AUX_USAGE_CCS_D), &level, logical_layer, num_layers, isl_tmp); if (can_fast_clear) { DBG("%s (fast) to mt %p level %d layers %d+%d\n", __FUNCTION__, irb->mt, irb->mt_level, irb->mt_layer, num_layers); struct blorp_batch batch; blorp_batch_init(&brw->blorp, &batch, brw, 0); blorp_fast_clear(&batch, &surf, (enum isl_format)brw->render_target_format[format], level, logical_layer, num_layers, x0, y0, x1, y1); blorp_batch_finish(&batch); /* Now that the fast clear has occurred, put the buffer in * INTEL_FAST_CLEAR_STATE_CLEAR so that we won't waste time doing * redundant clears. */ intel_miptree_set_fast_clear_state(brw, irb->mt, irb->mt_level, logical_layer, num_layers, INTEL_FAST_CLEAR_STATE_CLEAR); } else { DBG("%s (slow) to mt %p level %d layer %d+%d\n", __FUNCTION__, irb->mt, irb->mt_level, irb->mt_layer, num_layers); union isl_color_value clear_color; memcpy(clear_color.f32, ctx->Color.ClearColor.f, sizeof(float) * 4); struct blorp_batch batch; blorp_batch_init(&brw->blorp, &batch, brw, 0); blorp_clear(&batch, &surf, (enum isl_format)brw->render_target_format[format], ISL_SWIZZLE_IDENTITY, level, irb_logical_mt_layer(irb), num_layers, x0, y0, x1, y1, clear_color, color_write_disable); blorp_batch_finish(&batch); } return true; }