From 4ef8f46fd12876146212e119c0e238c92796226a Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Thu, 11 Oct 2018 14:14:29 -0500 Subject: [PATCH] nir/lower_tex: Add lowering for some min_lod cases Reviewed-by: Ian Romanick --- src/compiler/nir/nir.h | 18 ++++++ src/compiler/nir/nir_lower_tex.c | 98 ++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 376211d5e74..5d9c96fe11e 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -3013,6 +3013,24 @@ typedef struct nir_lower_tex_options { * Implies lower_txd_cube_map and lower_txd_shadow. */ bool lower_txd; + + /** + * If true, lower nir_texop_txb that try to use shadow compare and min_lod + * at the same time to a nir_texop_lod, some math, and nir_texop_tex. + */ + bool lower_txb_shadow_clamp; + + /** + * If true, lower nir_texop_txd on shadow samplers when it uses min_lod + * with nir_texop_txl. This includes cube maps. + */ + bool lower_txd_shadow_clamp; + + /** + * If true, lower nir_texop_txd on when it uses both offset and min_lod + * with nir_texop_txl. This includes cube maps. + */ + bool lower_txd_offset_clamp; } nir_lower_tex_options; bool nir_lower_tex(nir_shader *shader, diff --git a/src/compiler/nir/nir_lower_tex.c b/src/compiler/nir/nir_lower_tex.c index cd93c4f1749..6a6b6c41a7b 100644 --- a/src/compiler/nir/nir_lower_tex.c +++ b/src/compiler/nir/nir_lower_tex.c @@ -150,6 +150,54 @@ get_texture_size(nir_builder *b, nir_tex_instr *tex) return nir_i2f32(b, &txs->dest.ssa); } +static nir_ssa_def * +get_texture_lod(nir_builder *b, nir_tex_instr *tex) +{ + b->cursor = nir_before_instr(&tex->instr); + + nir_tex_instr *tql; + + unsigned num_srcs = 0; + for (unsigned i = 0; i < tex->num_srcs; i++) { + if (tex->src[i].src_type == nir_tex_src_coord || + tex->src[i].src_type == nir_tex_src_texture_deref || + tex->src[i].src_type == nir_tex_src_sampler_deref || + tex->src[i].src_type == nir_tex_src_texture_offset || + tex->src[i].src_type == nir_tex_src_sampler_offset) + num_srcs++; + } + + tql = nir_tex_instr_create(b->shader, num_srcs); + tql->op = nir_texop_lod; + tql->coord_components = tex->coord_components; + tql->sampler_dim = tex->sampler_dim; + tql->is_array = tex->is_array; + tql->is_shadow = tex->is_shadow; + tql->is_new_style_shadow = tex->is_new_style_shadow; + tql->texture_index = tex->texture_index; + tql->sampler_index = tex->sampler_index; + tql->dest_type = nir_type_float; + + unsigned idx = 0; + for (unsigned i = 0; i < tex->num_srcs; i++) { + if (tex->src[i].src_type == nir_tex_src_coord || + tex->src[i].src_type == nir_tex_src_texture_deref || + tex->src[i].src_type == nir_tex_src_sampler_deref || + tex->src[i].src_type == nir_tex_src_texture_offset || + tex->src[i].src_type == nir_tex_src_sampler_offset) { + nir_src_copy(&tql->src[idx].src, &tex->src[i].src, tql); + tql->src[idx].src_type = tex->src[i].src_type; + idx++; + } + } + + nir_ssa_dest_init(&tql->instr, &tql->dest, 2, 32, NULL); + nir_builder_instr_insert(b, &tql->instr); + + /* The LOD is the y component of the result */ + return nir_channel(b, &tql->dest.ssa, 1); +} + static bool lower_offset(nir_builder *b, nir_tex_instr *tex) { @@ -227,6 +275,36 @@ lower_rect(nir_builder *b, nir_tex_instr *tex) tex->sampler_dim = GLSL_SAMPLER_DIM_2D; } +static void +lower_implicit_lod(nir_builder *b, nir_tex_instr *tex) +{ + assert(tex->op == nir_texop_tex || tex->op == nir_texop_txb); + assert(nir_tex_instr_src_index(tex, nir_tex_src_lod) < 0); + assert(nir_tex_instr_src_index(tex, nir_tex_src_ddx) < 0); + assert(nir_tex_instr_src_index(tex, nir_tex_src_ddy) < 0); + + b->cursor = nir_before_instr(&tex->instr); + + nir_ssa_def *lod = get_texture_lod(b, tex); + + int bias_idx = nir_tex_instr_src_index(tex, nir_tex_src_bias); + if (bias_idx >= 0) { + /* If we have a bias, add it in */ + lod = nir_fadd(b, lod, nir_ssa_for_src(b, tex->src[bias_idx].src, 1)); + nir_tex_instr_remove_src(tex, bias_idx); + } + + int min_lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod); + if (min_lod_idx >= 0) { + /* If we have a minimum LOD, clamp LOD accordingly */ + lod = nir_fmax(b, lod, nir_ssa_for_src(b, tex->src[min_lod_idx].src, 1)); + nir_tex_instr_remove_src(tex, min_lod_idx); + } + + nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod)); + tex->op = nir_texop_txl; +} + static nir_ssa_def * sample_plane(nir_builder *b, nir_tex_instr *tex, int plane) { @@ -374,6 +452,13 @@ replace_gradient_with_lod(nir_builder *b, nir_ssa_def *lod, nir_tex_instr *tex) nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddx)); nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddy)); + int min_lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod); + if (min_lod_idx >= 0) { + /* If we have a minimum LOD, clamp LOD accordingly */ + lod = nir_fmax(b, lod, nir_ssa_for_src(b, tex->src[min_lod_idx].src, 1)); + nir_tex_instr_remove_src(tex, min_lod_idx); + } + nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod)); tex->op = nir_texop_txl; } @@ -803,9 +888,22 @@ nir_lower_tex_block(nir_block *block, nir_builder *b, progress = true; } + const bool has_min_lod = + nir_tex_instr_src_index(tex, nir_tex_src_min_lod) >= 0; + const bool has_offset = + nir_tex_instr_src_index(tex, nir_tex_src_offset) >= 0; + + if (tex->op == nir_texop_txb && tex->is_shadow && has_min_lod && + options->lower_txb_shadow_clamp) { + lower_implicit_lod(b, tex); + progress = true; + } + if (tex->op == nir_texop_txd && (options->lower_txd || (options->lower_txd_shadow && tex->is_shadow) || + (options->lower_txd_shadow_clamp && tex->is_shadow && has_min_lod) || + (options->lower_txd_offset_clamp && has_offset && has_min_lod) || (options->lower_txd_cube_map && tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE))) { lower_gradient(b, tex); -- 2.30.2