From 9fbe2a20078242594db788e5abec41651cbc6991 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 19 Jun 2018 22:05:57 -0700 Subject: [PATCH] intel/blorp: Add a blorp_filter enum for use in blorp_blit At the moment, this is entirely internal but we'll expose it to clients of the BLORP API in the next commit. Reviewed-by: Chad Versace --- src/intel/blorp/blorp.h | 8 ++ src/intel/blorp/blorp_blit.c | 212 +++++++++++++++++++---------------- src/intel/blorp/blorp_priv.h | 12 +- 3 files changed, 123 insertions(+), 109 deletions(-) diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h index 0a10ff91576..6e2f888d17f 100644 --- a/src/intel/blorp/blorp.h +++ b/src/intel/blorp/blorp.h @@ -119,6 +119,14 @@ struct blorp_surf uint32_t tile_x_sa, tile_y_sa; }; +enum blorp_filter { + BLORP_FILTER_NONE, + BLORP_FILTER_NEAREST, + BLORP_FILTER_BILINEAR, + BLORP_FILTER_SAMPLE_0, + BLORP_FILTER_AVERAGE, +}; + void blorp_blit(struct blorp_batch *batch, const struct blorp_surf *src_surf, diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c index f719aac1b86..cdabf441e52 100644 --- a/src/intel/blorp/blorp_blit.c +++ b/src/intel/blorp/blorp_blit.c @@ -70,9 +70,6 @@ static void brw_blorp_blit_vars_init(nir_builder *b, struct brw_blorp_blit_vars *v, const struct brw_blorp_blit_prog_key *key) { - /* Blended and scaled blits never use pixel discard. */ - assert(!key->use_kill || !(key->blend && key->blit_scaled)); - #define LOAD_INPUT(name, type)\ v->v_##name = BLORP_CREATE_NIR_INPUT(b->shader, name, type); @@ -1164,18 +1161,6 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx, assert(key->persample_msaa_dispatch); } - if (key->blend) { - /* We are blending, which means we won't have an opportunity to - * translate the tiling and sample count for the texture surface. So - * the surface state for the texture must be configured with the correct - * tiling and sample count. - */ - assert(!key->src_tiled_w); - assert(key->tex_samples == key->src_samples); - assert(key->tex_layout == key->src_layout); - assert(key->tex_samples > 0); - } - if (key->persample_msaa_dispatch) { /* It only makes sense to do persample dispatch if the render target is * configured as multisampled. @@ -1251,10 +1236,8 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx, * If we need to kill pixels that are outside the destination rectangle, * now is the time to do it. */ - if (key->use_kill) { - assert(!(key->blend && key->blit_scaled)); + if (key->use_kill) blorp_nir_discard_if_outside_rect(&b, dst_pos, &v); - } src_pos = blorp_blit_apply_transform(&b, nir_i2f32(&b, dst_pos), &v); if (dst_pos->num_components == 3) { @@ -1277,7 +1260,82 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx, * that we want to texture from. Exception: if we are blending, then S is * irrelevant, because we are going to fetch all samples. */ - if (key->blend && !key->blit_scaled) { + switch (key->filter) { + case BLORP_FILTER_NONE: + case BLORP_FILTER_NEAREST: + case BLORP_FILTER_SAMPLE_0: + /* We're going to use texelFetch, so we need integers */ + if (src_pos->num_components == 2) { + src_pos = nir_f2i32(&b, src_pos); + } else { + assert(src_pos->num_components == 3); + src_pos = nir_vec3(&b, nir_channel(&b, nir_f2i32(&b, src_pos), 0), + nir_channel(&b, nir_f2i32(&b, src_pos), 1), + nir_channel(&b, src_pos, 2)); + } + + /* We aren't blending, which means we just want to fetch a single + * sample from the source surface. The address that we want to fetch + * from is related to the X, Y and S values according to the formula: + * + * (X, Y, S) = decode_msaa(src_samples, detile(src_tiling, offset)). + * + * If the actual tiling and sample count of the source surface are + * not the same as the configuration of the texture, then we need to + * adjust the coordinates to compensate for the difference. + */ + if (tex_tiled_w != key->src_tiled_w || + key->tex_samples != key->src_samples || + key->tex_layout != key->src_layout) { + src_pos = blorp_nir_encode_msaa(&b, src_pos, key->src_samples, + key->src_layout); + /* Now (X, Y, S) = detile(src_tiling, offset) */ + if (tex_tiled_w != key->src_tiled_w) + src_pos = blorp_nir_retile_w_to_y(&b, src_pos); + /* Now (X, Y, S) = detile(tex_tiling, offset) */ + src_pos = blorp_nir_decode_msaa(&b, src_pos, key->tex_samples, + key->tex_layout); + } + + if (key->need_src_offset) + src_pos = nir_iadd(&b, src_pos, nir_load_var(&b, v.v_src_offset)); + + /* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)). + * + * In other words: X, Y, and S now contain values which, when passed to + * the texturing unit, will cause data to be read from the correct + * memory location. So we can fetch the texel now. + */ + if (key->src_samples == 1) { + color = blorp_nir_txf(&b, &v, src_pos, key->texture_data_type); + } else { + nir_ssa_def *mcs = NULL; + if (key->tex_aux_usage == ISL_AUX_USAGE_MCS) + mcs = blorp_blit_txf_ms_mcs(&b, &v, src_pos); + + color = blorp_nir_txf_ms(&b, &v, src_pos, mcs, key->texture_data_type); + } + break; + + case BLORP_FILTER_BILINEAR: + assert(!key->src_tiled_w); + assert(key->tex_samples == key->src_samples); + assert(key->tex_layout == key->src_layout); + + if (key->src_samples == 1) { + color = blorp_nir_tex(&b, &v, key, src_pos); + } else { + assert(!key->use_kill); + color = blorp_nir_manual_blend_bilinear(&b, src_pos, key->src_samples, + key, &v); + } + break; + + case BLORP_FILTER_AVERAGE: + assert(!key->src_tiled_w); + assert(key->tex_samples == key->src_samples); + assert(key->tex_layout == key->src_layout); + /* Resolves (effecively) use texelFetch, so we need integers and we * don't care about the sample index if we got one. */ @@ -1302,65 +1360,10 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx, key->tex_aux_usage, key->texture_data_type); } - } else if (key->blend && key->blit_scaled) { - assert(!key->use_kill); - color = blorp_nir_manual_blend_bilinear(&b, src_pos, key->src_samples, key, &v); - } else { - if (key->bilinear_filter) { - color = blorp_nir_tex(&b, &v, key, src_pos); - } else { - /* We're going to use texelFetch, so we need integers */ - if (src_pos->num_components == 2) { - src_pos = nir_f2i32(&b, src_pos); - } else { - assert(src_pos->num_components == 3); - src_pos = nir_vec3(&b, nir_channel(&b, nir_f2i32(&b, src_pos), 0), - nir_channel(&b, nir_f2i32(&b, src_pos), 1), - nir_channel(&b, src_pos, 2)); - } + break; - /* We aren't blending, which means we just want to fetch a single - * sample from the source surface. The address that we want to fetch - * from is related to the X, Y and S values according to the formula: - * - * (X, Y, S) = decode_msaa(src_samples, detile(src_tiling, offset)). - * - * If the actual tiling and sample count of the source surface are - * not the same as the configuration of the texture, then we need to - * adjust the coordinates to compensate for the difference. - */ - if (tex_tiled_w != key->src_tiled_w || - key->tex_samples != key->src_samples || - key->tex_layout != key->src_layout) { - src_pos = blorp_nir_encode_msaa(&b, src_pos, key->src_samples, - key->src_layout); - /* Now (X, Y, S) = detile(src_tiling, offset) */ - if (tex_tiled_w != key->src_tiled_w) - src_pos = blorp_nir_retile_w_to_y(&b, src_pos); - /* Now (X, Y, S) = detile(tex_tiling, offset) */ - src_pos = blorp_nir_decode_msaa(&b, src_pos, key->tex_samples, - key->tex_layout); - } - - if (key->need_src_offset) - src_pos = nir_iadd(&b, src_pos, nir_load_var(&b, v.v_src_offset)); - - /* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)). - * - * In other words: X, Y, and S now contain values which, when passed to - * the texturing unit, will cause data to be read from the correct - * memory location. So we can fetch the texel now. - */ - if (key->src_samples == 1) { - color = blorp_nir_txf(&b, &v, src_pos, key->texture_data_type); - } else { - nir_ssa_def *mcs = NULL; - if (key->tex_aux_usage == ISL_AUX_USAGE_MCS) - mcs = blorp_blit_txf_ms_mcs(&b, &v, src_pos); - - color = blorp_nir_txf_ms(&b, &v, src_pos, mcs, key->texture_data_type); - } - } + default: + unreachable("Invalid blorp filter"); } if (!isl_swizzle_is_identity(key->src_swizzle)) { @@ -1929,8 +1932,8 @@ try_blorp_blit(struct blorp_batch *batch, params->num_samples = params->dst.surf.samples; - if ((wm_prog_key->bilinear_filter || - (wm_prog_key->blend && !wm_prog_key->blit_scaled)) && + if ((wm_prog_key->filter == BLORP_FILTER_AVERAGE || + wm_prog_key->filter == BLORP_FILTER_BILINEAR) && batch->blorp->isl_dev->info->gen <= 6) { /* Gen4-5 don't support non-normalized texture coordinates */ wm_prog_key->src_coords_normalized = true; @@ -2241,7 +2244,7 @@ blorp_blit(struct blorp_batch *batch, }; /* Scaled blitting or not. */ - wm_prog_key.blit_scaled = + const bool blit_scaled = ((dst_x1 - dst_x0) == (src_x1 - src_x0) && (dst_y1 - dst_y0) == (src_y1 - src_y0)) ? false : true; @@ -2254,25 +2257,37 @@ blorp_blit(struct blorp_batch *batch, wm_prog_key.x_scale = 2.0f; wm_prog_key.y_scale = params.src.surf.samples / wm_prog_key.x_scale; - if (filter == GL_LINEAR && - params.src.surf.samples <= 1 && params.dst.surf.samples <= 1) { - wm_prog_key.bilinear_filter = true; - } + const bool bilinear_filter = filter == GL_LINEAR && + params.src.surf.samples <= 1 && + params.dst.surf.samples <= 1; - if ((params.src.surf.usage & ISL_SURF_USAGE_DEPTH_BIT) == 0 && - (params.src.surf.usage & ISL_SURF_USAGE_STENCIL_BIT) == 0 && - !isl_format_has_int_channel(params.src.surf.format) && - params.src.surf.samples > 1 && params.dst.surf.samples <= 1) { - /* We are downsampling a non-integer color buffer, so blend. - * - * Regarding integer color buffers, the OpenGL ES 3.2 spec says: - * - * "If the source formats are integer types or stencil values, a - * single sample's value is selected for each pixel." - * - * This implies we should not blend in that case. - */ - wm_prog_key.blend = true; + /* If we are downsampling a non-integer color buffer, blend. + * + * Regarding integer color buffers, the OpenGL ES 3.2 spec says: + * + * "If the source formats are integer types or stencil values, a + * single sample's value is selected for each pixel." + * + * This implies we should not blend in that case. + */ + const bool blend = + (params.src.surf.usage & ISL_SURF_USAGE_DEPTH_BIT) == 0 && + (params.src.surf.usage & ISL_SURF_USAGE_STENCIL_BIT) == 0 && + !isl_format_has_int_channel(params.src.surf.format) && + params.src.surf.samples > 1 && + params.dst.surf.samples <= 1; + + if (blend && !blit_scaled) { + wm_prog_key.filter = BLORP_FILTER_AVERAGE; + } else if (blend && blit_scaled) { + wm_prog_key.filter = BLORP_FILTER_BILINEAR; + } else if (bilinear_filter) { + wm_prog_key.filter = BLORP_FILTER_BILINEAR; + } else { + if (params.src.surf.samples > 1) + wm_prog_key.filter = BLORP_FILTER_SAMPLE_0; + else + wm_prog_key.filter = BLORP_FILTER_NEAREST; } params.wm_inputs.rect_grid.x1 = @@ -2510,6 +2525,7 @@ blorp_copy(struct blorp_batch *batch, struct brw_blorp_blit_prog_key wm_prog_key = { .shader_type = BLORP_SHADER_TYPE_BLIT, + .filter = BLORP_FILTER_NONE, .need_src_offset = src_surf->tile_x_sa || src_surf->tile_y_sa, .need_dst_offset = dst_surf->tile_x_sa || dst_surf->tile_y_sa, }; diff --git a/src/intel/blorp/blorp_priv.h b/src/intel/blorp/blorp_priv.h index 40f8c09bbad..a6aa2aa4151 100644 --- a/src/intel/blorp/blorp_priv.h +++ b/src/intel/blorp/blorp_priv.h @@ -307,11 +307,7 @@ struct brw_blorp_blit_prog_key */ bool dst_rgb; - /* True if all source samples should be blended together to produce each - * destination pixel. If true, src_tiled_w must be false, tex_samples must - * equal src_samples, and tex_samples must be nonzero. - */ - bool blend; + enum blorp_filter filter; /* True if the rectangle being sent through the rendering pipeline might be * larger than the destination rectangle, so the WM program should kill any @@ -325,9 +321,6 @@ struct brw_blorp_blit_prog_key */ bool persample_msaa_dispatch; - /* True for scaled blitting. */ - bool blit_scaled; - /* True if this blit operation may involve intratile offsets on the source. * In this case, we need to add the offset before texturing. */ @@ -343,9 +336,6 @@ struct brw_blorp_blit_prog_key */ float x_scale; float y_scale; - - /* True for blits with filter = GL_LINEAR. */ - bool bilinear_filter; }; /** -- 2.30.2