nir: Separate texture from sampler in nir_tex_instr

This commit adds the capability to NIR to support separate textures and
samplers.  As it currently stands, glsl_to_nir only sets the texture deref
and leaves the sampler deref alone as it did before and nir_lower_samplers
assumes this.  Backends can still assume that they are combined and only
look at only at the texture index.  Or, if they wish, they can assume that
they are separate because nir_lower_samplers, tgsi_to_nir, and prog_to_nir
all set both texture and sampler index whenever a sampler is required (the
two indices are the same in this case).

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Jason Ekstrand
2015-11-02 17:58:29 -08:00
parent ee85014b90
commit 5ec456375e
14 changed files with 102 additions and 18 deletions

View File

@@ -489,6 +489,8 @@ nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
instr->texture_index = 0; instr->texture_index = 0;
instr->texture_array_size = 0; instr->texture_array_size = 0;
instr->texture = NULL; instr->texture = NULL;
instr->sampler_index = 0;
instr->sampler = NULL;
return instr; return instr;
} }
@@ -1012,6 +1014,11 @@ visit_tex_src(nir_tex_instr *instr, nir_foreach_src_cb cb, void *state)
return false; return false;
} }
if (instr->sampler != NULL) {
if (!visit_deref_src(instr->sampler, cb, state))
return false;
}
return true; return true;
} }

View File

@@ -966,6 +966,7 @@ typedef enum {
nir_tex_src_ddx, nir_tex_src_ddx,
nir_tex_src_ddy, nir_tex_src_ddy,
nir_tex_src_texture_offset, /* < dynamically uniform indirect offset */ nir_tex_src_texture_offset, /* < dynamically uniform indirect offset */
nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */
nir_num_tex_src_types nir_num_tex_src_types
} nir_tex_src_type; } nir_tex_src_type;
@@ -1025,7 +1026,35 @@ typedef struct {
/** The size of the texture array or 0 if it's not an array */ /** The size of the texture array or 0 if it's not an array */
unsigned texture_array_size; unsigned texture_array_size;
nir_deref_var *texture; /* if this is NULL, use texture_index instead */ /** The texture deref
*
* If this is null, use texture_index instead.
*/
nir_deref_var *texture;
/** The sampler index
*
* The following operations do not require a sampler and, as such, this
* field should be ignored:
* - nir_texop_txf
* - nir_texop_txf_ms
* - nir_texop_txs
* - nir_texop_lod
* - nir_texop_tg4
* - nir_texop_query_levels
* - nir_texop_texture_samples
* - nir_texop_samples_identical
*
* If this texture instruction has a nir_tex_src_sampler_offset source,
* then the sampler index is given by sampler_index + sampler_offset.
*/
unsigned sampler_index;
/** The sampler deref
*
* If this is null, use sampler_index instead.
*/
nir_deref_var *sampler;
} nir_tex_instr; } nir_tex_instr;
static inline unsigned static inline unsigned

View File

@@ -357,10 +357,15 @@ clone_tex(clone_state *state, const nir_tex_instr *tex)
ntex->is_new_style_shadow = tex->is_new_style_shadow; ntex->is_new_style_shadow = tex->is_new_style_shadow;
memcpy(ntex->const_offset, tex->const_offset, sizeof(ntex->const_offset)); memcpy(ntex->const_offset, tex->const_offset, sizeof(ntex->const_offset));
ntex->component = tex->component; ntex->component = tex->component;
ntex->texture_index = tex->texture_index; ntex->texture_index = tex->texture_index;
ntex->texture_array_size = tex->texture_array_size;
if (tex->texture) if (tex->texture)
ntex->texture = clone_deref_var(state, tex->texture, &ntex->instr); ntex->texture = clone_deref_var(state, tex->texture, &ntex->instr);
ntex->texture_array_size = tex->texture_array_size;
ntex->sampler_index = tex->sampler_index;
if (tex->sampler)
ntex->sampler = clone_deref_var(state, tex->sampler, &ntex->instr);
return ntex; return ntex;
} }

View File

@@ -157,8 +157,9 @@ hash_tex(uint32_t hash, const nir_tex_instr *instr)
hash = HASH(hash, component); hash = HASH(hash, component);
hash = HASH(hash, instr->texture_index); hash = HASH(hash, instr->texture_index);
hash = HASH(hash, instr->texture_array_size); hash = HASH(hash, instr->texture_array_size);
hash = HASH(hash, instr->sampler_index);
assert(!instr->texture); assert(!instr->texture && !instr->sampler);
return hash; return hash;
} }
@@ -306,12 +307,14 @@ nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2)
sizeof(tex1->const_offset)) != 0 || sizeof(tex1->const_offset)) != 0 ||
tex1->component != tex2->component || tex1->component != tex2->component ||
tex1->texture_index != tex2->texture_index || tex1->texture_index != tex2->texture_index ||
tex1->texture_array_size != tex2->texture_array_size) { tex1->texture_array_size != tex2->texture_array_size ||
tex1->sampler_index != tex2->sampler_index) {
return false; return false;
} }
/* Don't support un-lowered texture derefs currently. */ /* Don't support un-lowered sampler derefs currently. */
assert(!tex1->texture && !tex2->texture); assert(!tex1->texture && !tex1->sampler &&
!tex2->texture && !tex2->sampler);
return true; return true;
} }
@@ -421,8 +424,8 @@ instr_can_rewrite(nir_instr *instr)
case nir_instr_type_tex: { case nir_instr_type_tex: {
nir_tex_instr *tex = nir_instr_as_tex(instr); nir_tex_instr *tex = nir_instr_as_tex(instr);
/* Don't support un-lowered texture derefs currently. */ /* Don't support un-lowered sampler derefs currently. */
if (tex->texture) if (tex->texture || tex->sampler)
return false; return false;
return true; return true;

View File

@@ -94,6 +94,9 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
if (instr->texture == NULL) if (instr->texture == NULL)
return; return;
/* In GLSL, we only fill out the texture field. The sampler is inferred */
assert(instr->sampler == NULL);
instr->texture_index = 0; instr->texture_index = 0;
unsigned location = instr->texture->var->data.location; unsigned location = instr->texture->var->data.location;
unsigned array_elements = 1; unsigned array_elements = 1;
@@ -106,7 +109,7 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
if (indirect) { if (indirect) {
/* First, we have to resize the array of texture sources */ /* First, we have to resize the array of texture sources */
nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src, nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,
instr->num_srcs + 1); instr->num_srcs + 2);
for (unsigned i = 0; i < instr->num_srcs; i++) { for (unsigned i = 0; i < instr->num_srcs; i++) {
new_srcs[i].src_type = instr->src[i].src_type; new_srcs[i].src_type = instr->src[i].src_type;
@@ -126,6 +129,12 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
&instr->src[instr->num_srcs - 1].src, &instr->src[instr->num_srcs - 1].src,
nir_src_for_ssa(indirect)); nir_src_for_ssa(indirect));
instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
instr->num_srcs++;
nir_instr_rewrite_src(&instr->instr,
&instr->src[instr->num_srcs - 1].src,
nir_src_for_ssa(indirect));
instr->texture_array_size = array_elements; instr->texture_array_size = array_elements;
} }
@@ -138,6 +147,8 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
instr->texture_index += instr->texture_index +=
shader_program->UniformStorage[location].opaque[stage].index; shader_program->UniformStorage[location].opaque[stage].index;
instr->sampler_index = instr->texture_index;
instr->texture = NULL; instr->texture = NULL;
} }

View File

@@ -291,11 +291,11 @@ nir_lower_tex_block(nir_block *block, void *void_state)
/* mask of src coords to saturate (clamp): */ /* mask of src coords to saturate (clamp): */
unsigned sat_mask = 0; unsigned sat_mask = 0;
if ((1 << tex->texture_index) & state->options->saturate_r) if ((1 << tex->sampler_index) & state->options->saturate_r)
sat_mask |= (1 << 2); /* .z */ sat_mask |= (1 << 2); /* .z */
if ((1 << tex->texture_index) & state->options->saturate_t) if ((1 << tex->sampler_index) & state->options->saturate_t)
sat_mask |= (1 << 1); /* .y */ sat_mask |= (1 << 1); /* .y */
if ((1 << tex->texture_index) & state->options->saturate_s) if ((1 << tex->sampler_index) & state->options->saturate_s)
sat_mask |= (1 << 0); /* .x */ sat_mask |= (1 << 0); /* .x */
/* If we are clamping any coords, we must lower projector first /* If we are clamping any coords, we must lower projector first

View File

@@ -136,10 +136,15 @@ constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
static bool static bool
constant_fold_tex_instr(nir_tex_instr *instr) constant_fold_tex_instr(nir_tex_instr *instr)
{ {
bool progress = false;
if (instr->texture) if (instr->texture)
return constant_fold_deref(&instr->instr, instr->texture); progress |= constant_fold_deref(&instr->instr, instr->texture);
else
return false; if (instr->sampler)
progress |= constant_fold_deref(&instr->instr, instr->sampler);
return progress;
} }
static bool static bool

View File

@@ -625,6 +625,9 @@ print_tex_instr(nir_tex_instr *instr, print_state *state)
case nir_tex_src_texture_offset: case nir_tex_src_texture_offset:
fprintf(fp, "(texture_offset)"); fprintf(fp, "(texture_offset)");
break; break;
case nir_tex_src_sampler_offset:
fprintf(fp, "(sampler_offset)");
break;
default: default:
unreachable("Invalid texture source type"); unreachable("Invalid texture source type");
@@ -654,11 +657,16 @@ print_tex_instr(nir_tex_instr *instr, print_state *state)
if (instr->texture) { if (instr->texture) {
print_deref(instr->texture, state); print_deref(instr->texture, state);
fprintf(fp, " (texture)");
if (instr->sampler) {
print_deref(instr->sampler, state);
fprintf(fp, " (sampler)");
}
} else { } else {
fprintf(fp, "%u", instr->texture_index); assert(instr->sampler == NULL);
fprintf(fp, "%u (texture) %u (sampler)",
instr->texture_index, instr->sampler_index);
} }
fprintf(fp, " (texture)");
} }
static void static void

View File

@@ -58,6 +58,11 @@ add_var_use_tex(nir_tex_instr *instr, struct set *live)
nir_variable *var = instr->texture->var; nir_variable *var = instr->texture->var;
_mesa_set_add(live, var); _mesa_set_add(live, var);
} }
if (instr->sampler != NULL) {
nir_variable *var = instr->sampler->var;
_mesa_set_add(live, var);
}
} }
static bool static bool

View File

@@ -448,6 +448,9 @@ validate_tex_instr(nir_tex_instr *instr, validate_state *state)
if (instr->texture != NULL) if (instr->texture != NULL)
validate_deref_var(instr, instr->texture, state); validate_deref_var(instr, instr->texture, state);
if (instr->sampler != NULL)
validate_deref_var(instr, instr->sampler, state);
validate_dest(&instr->dest, state); validate_dest(&instr->dest, state);
} }

View File

@@ -1310,6 +1310,7 @@ ttn_tex(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)
assert(tgsi_inst->Src[samp].Register.File == TGSI_FILE_SAMPLER); assert(tgsi_inst->Src[samp].Register.File == TGSI_FILE_SAMPLER);
instr->texture_index = tgsi_inst->Src[samp].Register.Index; instr->texture_index = tgsi_inst->Src[samp].Register.Index;
instr->sampler_index = tgsi_inst->Src[samp].Register.Index;
/* TODO if we supported any opc's which take an explicit SVIEW /* TODO if we supported any opc's which take an explicit SVIEW
* src, we would use that here instead. But for the "legacy" * src, we would use that here instead. But for the "legacy"

View File

@@ -3024,6 +3024,9 @@ fs_visitor::nir_emit_texture(const fs_builder &bld, nir_tex_instr *instr)
break; break;
} }
case nir_tex_src_sampler_offset:
break; /* Ignored for now */
default: default:
unreachable("unknown texture source"); unreachable("unknown texture source");
} }

View File

@@ -1738,6 +1738,9 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
break; break;
} }
case nir_tex_src_sampler_offset:
break; /* Ignored for now */
case nir_tex_src_projector: case nir_tex_src_projector:
unreachable("Should be lowered by do_lower_texture_projection"); unreachable("Should be lowered by do_lower_texture_projection");

View File

@@ -610,6 +610,7 @@ ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src,
instr->dest_type = nir_type_float; instr->dest_type = nir_type_float;
instr->is_shadow = prog_inst->TexShadow; instr->is_shadow = prog_inst->TexShadow;
instr->texture_index = prog_inst->TexSrcUnit; instr->texture_index = prog_inst->TexSrcUnit;
instr->sampler_index = prog_inst->TexSrcUnit;
switch (prog_inst->TexSrcTarget) { switch (prog_inst->TexSrcTarget) {
case TEXTURE_1D_INDEX: case TEXTURE_1D_INDEX: