nir/lower_tex: Add lowering for some min_lod cases

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Jason Ekstrand
2018-10-11 14:14:29 -05:00
parent 4a691cfa7e
commit 4ef8f46fd1
2 changed files with 116 additions and 0 deletions

View File

@@ -3013,6 +3013,24 @@ typedef struct nir_lower_tex_options {
* Implies lower_txd_cube_map and lower_txd_shadow. * Implies lower_txd_cube_map and lower_txd_shadow.
*/ */
bool lower_txd; 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; } nir_lower_tex_options;
bool nir_lower_tex(nir_shader *shader, bool nir_lower_tex(nir_shader *shader,

View File

@@ -150,6 +150,54 @@ get_texture_size(nir_builder *b, nir_tex_instr *tex)
return nir_i2f32(b, &txs->dest.ssa); 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 static bool
lower_offset(nir_builder *b, nir_tex_instr *tex) 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; 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 * static nir_ssa_def *
sample_plane(nir_builder *b, nir_tex_instr *tex, int plane) 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_ddx));
nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddy)); 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)); nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod));
tex->op = nir_texop_txl; tex->op = nir_texop_txl;
} }
@@ -803,9 +888,22 @@ nir_lower_tex_block(nir_block *block, nir_builder *b,
progress = true; 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 && if (tex->op == nir_texop_txd &&
(options->lower_txd || (options->lower_txd ||
(options->lower_txd_shadow && tex->is_shadow) || (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 && (options->lower_txd_cube_map &&
tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE))) { tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE))) {
lower_gradient(b, tex); lower_gradient(b, tex);