From eddfc977096c63dc9699b63b05ad0e1212680fb1 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 19 Apr 2016 08:28:22 -0400 Subject: [PATCH] nir/lower-tex: add srgb->linear lowering Signed-off-by: Rob Clark Reviewed-by: Eric Anholt Reviewed-by: Jason Ekstrand --- src/compiler/nir/nir.h | 7 +++++ src/compiler/nir/nir_lower_tex.c | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index bbbc2089db3..3b82cfac1b5 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 7740e588790..4cc18228d1d 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; -- 2.30.2