diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index 9084803adf1..6a1a0b5f113 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -2378,7 +2378,8 @@ nir_visitor::visit(ir_texture *ir) num_srcs++; if (ir->shadow_comparator != NULL) num_srcs++; - if (ir->offset != NULL) + /* offsets are constants we store inside nir_tex_intrs.offsets */ + if (ir->offset != NULL && !ir->offset->type->is_array()) num_srcs++; /* Add one for the texture deref */ @@ -2439,13 +2440,25 @@ nir_visitor::visit(ir_texture *ir) } if (ir->offset != NULL) { - /* we don't support multiple offsets yet */ - assert(ir->offset->type->is_vector() || ir->offset->type->is_scalar()); + if (ir->offset->type->is_array()) { + for (int i = 0; i < ir->offset->type->array_size(); i++) { + const ir_constant *c = + ir->offset->as_constant()->get_array_element(i); - instr->src[src_number].src = - nir_src_for_ssa(evaluate_rvalue(ir->offset)); - instr->src[src_number].src_type = nir_tex_src_offset; - src_number++; + for (unsigned j = 0; j < 2; ++j) { + int val = c->get_int_component(j); + assert(val <= 31 && val >= -32); + instr->tg4_offsets[i][j] = val; + } + } + } else { + assert(ir->offset->type->is_vector() || ir->offset->type->is_scalar()); + + instr->src[src_number].src = + nir_src_for_ssa(evaluate_rvalue(ir->offset)); + instr->src[src_number].src_type = nir_tex_src_offset; + src_number++; + } } switch (ir->op) { diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 4a7c757db3a..0daafc4936d 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -531,6 +531,14 @@ nir_call_instr_create(nir_shader *shader, nir_function *callee) return instr; } +static int8_t default_tg4_offsets[4][2] = +{ + { 0, 1 }, + { 1, 1 }, + { 1, 0 }, + { 0, 0 }, +}; + nir_tex_instr * nir_tex_instr_create(nir_shader *shader, unsigned num_srcs) { @@ -547,6 +555,7 @@ nir_tex_instr_create(nir_shader *shader, unsigned num_srcs) instr->texture_index = 0; instr->texture_array_size = 0; instr->sampler_index = 0; + memcpy(instr->tg4_offsets, default_tg4_offsets, sizeof(instr->tg4_offsets)); return instr; } @@ -589,6 +598,15 @@ nir_tex_instr_remove_src(nir_tex_instr *tex, unsigned src_idx) tex->num_srcs--; } +bool +nir_tex_instr_has_explicit_tg4_offsets(nir_tex_instr *tex) +{ + if (tex->op != nir_texop_tg4) + return false; + return memcmp(tex->tg4_offsets, default_tg4_offsets, + sizeof(tex->tg4_offsets)) != 0; +} + nir_phi_instr * nir_phi_instr_create(nir_shader *shader) { diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index f9c2adb83e5..2c1caf2687a 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1482,6 +1482,9 @@ typedef struct { /* gather component selector */ unsigned component : 2; + /* gather offsets */ + int8_t tg4_offsets[4][2]; + /** The texture index * * If this texture instruction has a nir_tex_src_texture_offset source, @@ -1699,6 +1702,8 @@ void nir_tex_instr_add_src(nir_tex_instr *tex, void nir_tex_instr_remove_src(nir_tex_instr *tex, unsigned src_idx); +bool nir_tex_instr_has_explicit_tg4_offsets(nir_tex_instr *tex); + typedef struct { nir_instr instr; diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c index fa24f8b6028..9594eb8044d 100644 --- a/src/compiler/nir/nir_clone.c +++ b/src/compiler/nir/nir_clone.c @@ -394,6 +394,7 @@ clone_tex(clone_state *state, const nir_tex_instr *tex) ntex->is_shadow = tex->is_shadow; ntex->is_new_style_shadow = tex->is_new_style_shadow; ntex->component = tex->component; + memcpy(ntex->tg4_offsets, tex->tg4_offsets, sizeof(tex->tg4_offsets)); ntex->texture_index = tex->texture_index; ntex->texture_array_size = tex->texture_array_size; diff --git a/src/compiler/nir/nir_instr_set.c b/src/compiler/nir/nir_instr_set.c index 8f4e971b89a..d106e9ebcae 100644 --- a/src/compiler/nir/nir_instr_set.c +++ b/src/compiler/nir/nir_instr_set.c @@ -200,6 +200,9 @@ hash_tex(uint32_t hash, const nir_tex_instr *instr) hash = HASH(hash, instr->is_new_style_shadow); unsigned component = instr->component; hash = HASH(hash, component); + for (unsigned i = 0; i < 4; ++i) + for (unsigned j = 0; j < 2; ++j) + hash = HASH(hash, instr->tg4_offsets[i][j]); hash = HASH(hash, instr->texture_index); hash = HASH(hash, instr->texture_array_size); hash = HASH(hash, instr->sampler_index); @@ -403,6 +406,10 @@ nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2) return false; } + if (memcmp(tex1->tg4_offsets, tex2->tg4_offsets, + sizeof(tex1->tg4_offsets))) + return false; + return true; } case nir_instr_type_load_const: { diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index 6b270394f9d..8e714e6666b 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -984,6 +984,14 @@ print_tex_instr(nir_tex_instr *instr, print_state *state) fprintf(fp, "%u (gather_component), ", instr->component); } + if (nir_tex_instr_has_explicit_tg4_offsets(instr)) { + fprintf(fp, "{ (%i, %i)", instr->tg4_offsets[0][0], instr->tg4_offsets[0][1]); + for (unsigned i = 1; i < 4; ++i) + fprintf(fp, ", (%i, %i)", instr->tg4_offsets[i][0], + instr->tg4_offsets[i][1]); + fprintf(fp, " } (offsets), "); + } + if (!has_texture_deref) { fprintf(fp, "%u (texture), ", instr->texture_index); } diff --git a/src/compiler/nir/nir_serialize.c b/src/compiler/nir/nir_serialize.c index 840a1572786..fd8708fbb43 100644 --- a/src/compiler/nir/nir_serialize.c +++ b/src/compiler/nir/nir_serialize.c @@ -617,6 +617,7 @@ write_tex(write_ctx *ctx, const nir_tex_instr *tex) blob_write_uint32(ctx->blob, tex->texture_index); blob_write_uint32(ctx->blob, tex->texture_array_size); blob_write_uint32(ctx->blob, tex->sampler_index); + blob_write_bytes(ctx->blob, tex->tg4_offsets, sizeof(tex->tg4_offsets)); STATIC_ASSERT(sizeof(union packed_tex_data) == sizeof(uint32_t)); union packed_tex_data packed = { @@ -647,6 +648,7 @@ read_tex(read_ctx *ctx) tex->texture_index = blob_read_uint32(ctx->blob); tex->texture_array_size = blob_read_uint32(ctx->blob); tex->sampler_index = blob_read_uint32(ctx->blob); + blob_copy_bytes(ctx->blob, tex->tg4_offsets, sizeof(tex->tg4_offsets)); union packed_tex_data packed; packed.u32 = blob_read_uint32(ctx->blob); diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 3a3c232d370..ef2e2b62783 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -598,6 +598,11 @@ validate_tex_instr(nir_tex_instr *instr, validate_state *state) 0, nir_tex_instr_src_size(instr, i)); } + if (nir_tex_instr_has_explicit_tg4_offsets(instr)) { + validate_assert(state, instr->op == nir_texop_tg4); + validate_assert(state, !src_type_seen[nir_tex_src_offset]); + } + validate_dest(&instr->dest, state, 0, nir_tex_instr_dest_size(instr)); }