summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <robclark@freedesktop.org>2016-04-19 08:28:22 -0400
committerRob Clark <robclark@freedesktop.org>2016-04-19 17:13:50 -0400
commiteddfc977096c63dc9699b63b05ad0e1212680fb1 (patch)
tree43504361d69dbfaf60f14b403e47ea1aec57857e
parenteb00a0fc581c4040bc2e4640da4ff9f40c951ae8 (diff)
downloadmesa-eddfc977096c63dc9699b63b05ad0e1212680fb1.tar.gz
mesa-eddfc977096c63dc9699b63b05ad0e1212680fb1.tar.xz
nir/lower-tex: add srgb->linear lowering
Signed-off-by: Rob Clark <robclark@freedesktop.org> Reviewed-by: Eric Anholt <eric@anholt.net> Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
-rw-r--r--src/compiler/nir/nir.h7
-rw-r--r--src/compiler/nir/nir_lower_tex.c46
2 files changed, 53 insertions, 0 deletions
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index bbbc208..3b82cfa 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2301,6 +2301,13 @@ typedef struct nir_lower_tex_options {
* while 4 and 5 represent 0 and 1 respectively.
*/
uint8_t swizzles[32][4];
+
+ /**
+ * Bitmap of textures that need srgb to linear conversion. If
+ * (lower_srgb & (1 << texture_index)) then the rgb (xyz) components
+ * of the texture are lowered to linear.
+ */
+ unsigned lower_srgb;
} 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 7740e58..4cc1822 100644
--- a/src/compiler/nir/nir_lower_tex.c
+++ b/src/compiler/nir/nir_lower_tex.c
@@ -275,6 +275,45 @@ swizzle_result(nir_builder *b, nir_tex_instr *tex, const uint8_t swizzle[4])
swizzled->parent_instr);
}
+static void
+linearize_srgb_result(nir_builder *b, nir_tex_instr *tex)
+{
+ assert(tex->dest.is_ssa);
+ assert(nir_tex_instr_dest_size(tex) == 4);
+ assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
+
+ b->cursor = nir_after_instr(&tex->instr);
+
+ static const unsigned swiz[4] = {0, 1, 2, 0};
+ nir_ssa_def *comp = nir_swizzle(b, &tex->dest.ssa, swiz, 3, true);
+
+ /* Formula is:
+ * (comp <= 0.04045) ?
+ * (comp / 12.92) :
+ * pow((comp + 0.055) / 1.055, 2.4)
+ */
+ nir_ssa_def *low = nir_fmul(b, comp, nir_imm_float(b, 1.0 / 12.92));
+ nir_ssa_def *high = nir_fpow(b,
+ nir_fmul(b,
+ nir_fadd(b,
+ comp,
+ nir_imm_float(b, 0.055)),
+ nir_imm_float(b, 1.0 / 1.055)),
+ nir_imm_float(b, 2.4));
+ nir_ssa_def *cond = nir_fge(b, nir_imm_float(b, 0.04045), comp);
+ nir_ssa_def *rgb = nir_bcsel(b, cond, low, high);
+
+ /* alpha is untouched: */
+ nir_ssa_def *result = nir_vec4(b,
+ nir_channel(b, rgb, 0),
+ nir_channel(b, rgb, 1),
+ nir_channel(b, rgb, 2),
+ nir_channel(b, &tex->dest.ssa, 3));
+
+ nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, nir_src_for_ssa(result),
+ result->parent_instr);
+}
+
static bool
nir_lower_tex_block(nir_block *block, void *void_state)
{
@@ -323,6 +362,13 @@ nir_lower_tex_block(nir_block *block, void *void_state)
swizzle_result(b, tex, options->swizzles[tex->texture_index]);
state->progress = true;
}
+
+ /* should be after swizzle so we know which channels are rgb: */
+ if (((1 << tex->texture_index) & options->lower_srgb) &&
+ !nir_tex_instr_is_query(tex) && !tex->is_shadow) {
+ linearize_srgb_result(b, tex);
+ state->progress = true;
+ }
}
return true;