From d9156efc5292b4ac7cea9d12e68882fc7b5da5fd Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 20 Jul 2016 20:32:31 -0700 Subject: [PATCH] nir/lower_tex: Add support for lowering coordinate offsets On i965, we can't support coordinate offsets for texelFetch or rectangle textures. Previously, we were doing this with a GLSL pass but we need to do it in NIR if we want those workarounds for SPIR-V. Signed-off-by: Jason Ekstrand Reviewed-by: Kenneth Graunke Cc: "12.0" --- src/compiler/nir/nir.h | 10 ++++++ src/compiler/nir/nir_lower_tex.c | 54 ++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 5a69e7858d4..f23d0b256a8 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -2408,6 +2408,16 @@ typedef struct nir_lower_tex_options { */ unsigned lower_txp; + /** + * If true, lower away nir_tex_src_offset for all texelfetch instructions. + */ + bool lower_txf_offset; + + /** + * If true, lower away nir_tex_src_offset for all rect textures. + */ + bool lower_rect_offset; + /** * If true, lower rect textures to 2D, using txs to fetch the * texture dimensions and dividing the texture coords by the diff --git a/src/compiler/nir/nir_lower_tex.c b/src/compiler/nir/nir_lower_tex.c index e70a9aa7693..93637a33844 100644 --- a/src/compiler/nir/nir_lower_tex.c +++ b/src/compiler/nir/nir_lower_tex.c @@ -128,6 +128,54 @@ project_src(nir_builder *b, nir_tex_instr *tex) tex_instr_remove_src(tex, proj_index); } +static bool +lower_offset(nir_builder *b, nir_tex_instr *tex) +{ + int offset_index = tex_instr_find_src(tex, nir_tex_src_offset); + if (offset_index < 0) + return false; + + int coord_index = tex_instr_find_src(tex, nir_tex_src_coord); + assert(coord_index >= 0); + + assert(tex->src[offset_index].src.is_ssa); + assert(tex->src[coord_index].src.is_ssa); + nir_ssa_def *offset = tex->src[offset_index].src.ssa; + nir_ssa_def *coord = tex->src[coord_index].src.ssa; + + b->cursor = nir_before_instr(&tex->instr); + + nir_ssa_def *offset_coord; + if (nir_tex_instr_src_type(tex, coord_index) == nir_type_float) { + assert(tex->sampler_dim == GLSL_SAMPLER_DIM_RECT); + offset_coord = nir_fadd(b, coord, nir_i2f(b, offset)); + } else { + offset_coord = nir_iadd(b, coord, offset); + } + + if (tex->is_array) { + /* The offset is not applied to the array index */ + if (tex->coord_components == 2) { + offset_coord = nir_vec2(b, nir_channel(b, offset_coord, 0), + nir_channel(b, coord, 1)); + } else if (tex->coord_components == 3) { + offset_coord = nir_vec3(b, nir_channel(b, offset_coord, 0), + nir_channel(b, offset_coord, 1), + nir_channel(b, coord, 2)); + } else { + unreachable("Invalid number of components"); + } + } + + nir_instr_rewrite_src(&tex->instr, &tex->src[coord_index].src, + nir_src_for_ssa(offset_coord)); + + tex_instr_remove_src(tex, offset_index); + + return true; +} + + static nir_ssa_def * get_texture_size(nir_builder *b, nir_tex_instr *tex) { @@ -458,6 +506,12 @@ nir_lower_tex_block(nir_block *block, nir_builder *b, progress = true; } + if ((tex->op == nir_texop_txf && options->lower_txf_offset) || + (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT && + options->lower_rect_offset)) { + progress = lower_offset(b, tex) || progress; + } + if ((tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) && options->lower_rect) { lower_rect(b, tex); progress = true; -- 2.30.2