instr->texture_index = 0;
instr->texture_array_size = 0;
instr->texture = NULL;
+ instr->sampler_index = 0;
+ instr->sampler = NULL;
return instr;
}
return false;
}
+ if (instr->sampler != NULL) {
+ if (!visit_deref_src(instr->sampler, cb, state))
+ return false;
+ }
+
return true;
}
nir_tex_src_ddx,
nir_tex_src_ddy,
nir_tex_src_texture_offset, /* < dynamically uniform indirect offset */
+ nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */
nir_num_tex_src_types
} nir_tex_src_type;
/** The size of the texture array or 0 if it's not an array */
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;
static inline unsigned
ntex->is_new_style_shadow = tex->is_new_style_shadow;
memcpy(ntex->const_offset, tex->const_offset, sizeof(ntex->const_offset));
ntex->component = tex->component;
+
ntex->texture_index = tex->texture_index;
- ntex->texture_array_size = tex->texture_array_size;
if (tex->texture)
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;
}
hash = HASH(hash, component);
hash = HASH(hash, instr->texture_index);
hash = HASH(hash, instr->texture_array_size);
+ hash = HASH(hash, instr->sampler_index);
- assert(!instr->texture);
+ assert(!instr->texture && !instr->sampler);
return hash;
}
sizeof(tex1->const_offset)) != 0 ||
tex1->component != tex2->component ||
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;
}
- /* Don't support un-lowered texture derefs currently. */
- assert(!tex1->texture && !tex2->texture);
+ /* Don't support un-lowered sampler derefs currently. */
+ assert(!tex1->texture && !tex1->sampler &&
+ !tex2->texture && !tex2->sampler);
return true;
}
case nir_instr_type_tex: {
nir_tex_instr *tex = nir_instr_as_tex(instr);
- /* Don't support un-lowered texture derefs currently. */
- if (tex->texture)
+ /* Don't support un-lowered sampler derefs currently. */
+ if (tex->texture || tex->sampler)
return false;
return true;
if (instr->texture == NULL)
return;
+ /* In GLSL, we only fill out the texture field. The sampler is inferred */
+ assert(instr->sampler == NULL);
+
instr->texture_index = 0;
unsigned location = instr->texture->var->data.location;
unsigned array_elements = 1;
if (indirect) {
/* First, we have to resize the array of texture sources */
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++) {
new_srcs[i].src_type = instr->src[i].src_type;
&instr->src[instr->num_srcs - 1].src,
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_index +=
shader_program->UniformStorage[location].opaque[stage].index;
+ instr->sampler_index = instr->texture_index;
+
instr->texture = NULL;
}
/* mask of src coords to saturate (clamp): */
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 */
- if ((1 << tex->texture_index) & state->options->saturate_t)
+ if ((1 << tex->sampler_index) & state->options->saturate_t)
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 */
/* If we are clamping any coords, we must lower projector first
static bool
constant_fold_tex_instr(nir_tex_instr *instr)
{
+ bool progress = false;
+
if (instr->texture)
- return constant_fold_deref(&instr->instr, instr->texture);
- else
- return false;
+ progress |= constant_fold_deref(&instr->instr, instr->texture);
+
+ if (instr->sampler)
+ progress |= constant_fold_deref(&instr->instr, instr->sampler);
+
+ return progress;
}
static bool
case nir_tex_src_texture_offset:
fprintf(fp, "(texture_offset)");
break;
+ case nir_tex_src_sampler_offset:
+ fprintf(fp, "(sampler_offset)");
+ break;
default:
unreachable("Invalid texture source type");
if (instr->texture) {
print_deref(instr->texture, state);
+ fprintf(fp, " (texture)");
+ if (instr->sampler) {
+ print_deref(instr->sampler, state);
+ fprintf(fp, " (sampler)");
+ }
} 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
nir_variable *var = instr->texture->var;
_mesa_set_add(live, var);
}
+
+ if (instr->sampler != NULL) {
+ nir_variable *var = instr->sampler->var;
+ _mesa_set_add(live, var);
+ }
}
static bool
if (instr->texture != NULL)
validate_deref_var(instr, instr->texture, state);
+ if (instr->sampler != NULL)
+ validate_deref_var(instr, instr->sampler, state);
+
validate_dest(&instr->dest, state);
}
assert(tgsi_inst->Src[samp].Register.File == TGSI_FILE_SAMPLER);
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
* src, we would use that here instead. But for the "legacy"
break;
}
+ case nir_tex_src_sampler_offset:
+ break; /* Ignored for now */
+
default:
unreachable("unknown texture source");
}
break;
}
+ case nir_tex_src_sampler_offset:
+ break; /* Ignored for now */
+
case nir_tex_src_projector:
unreachable("Should be lowered by do_lower_texture_projection");
instr->dest_type = nir_type_float;
instr->is_shadow = prog_inst->TexShadow;
instr->texture_index = prog_inst->TexSrcUnit;
+ instr->sampler_index = prog_inst->TexSrcUnit;
switch (prog_inst->TexSrcTarget) {
case TEXTURE_1D_INDEX: