diff options
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/nir/nir.h | 7 | ||||
-rw-r--r-- | src/compiler/nir/nir_lower_tex.c | 46 |
2 files changed, 53 insertions, 0 deletions
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; |