[Mesa-dev] [PATCH 1/6] nir: Separate texture from sampler in nir_tex_instr
Jason Ekstrand
jason at jlekstrand.net
Sat Feb 6 05:20:24 UTC 2016
This commit adds the capability to NIR to support separate textures and
samplers. As it currently stands, glsl_to_nir only sets the sampler and
leaves the texture alone as it did before and nir_lower_samplers assumes
this. However, backends can, if they wish, assume that they are separate
because nir_lower_samplers sets both texture and sampler index (they are
the same in this case).
---
src/compiler/nir/nir.c | 8 +++++++-
src/compiler/nir/nir.h | 26 ++++++++++++++++++++++----
src/compiler/nir/nir_clone.c | 7 ++++++-
src/compiler/nir/nir_instr_set.c | 13 ++++++++-----
src/compiler/nir/nir_lower_samplers.c | 15 +++++++++++++--
src/compiler/nir/nir_lower_tex.c | 4 ++--
src/compiler/nir/nir_print.c | 14 +++++++++++---
src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 2 +-
src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 2 +-
src/mesa/program/prog_to_nir.c | 1 +
10 files changed, 72 insertions(+), 20 deletions(-)
diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c
index 21bf678..cd22a5c 100644
--- a/src/compiler/nir/nir.c
+++ b/src/compiler/nir/nir.c
@@ -486,8 +486,10 @@ nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
for (unsigned i = 0; i < num_srcs; i++)
src_init(&instr->src[i].src);
+ instr->texture_index = 0;
+ instr->texture_array_size = 0;
+ instr->texture = NULL;
instr->sampler_index = 0;
- instr->sampler_array_size = 0;
instr->sampler = NULL;
return instr;
@@ -1005,6 +1007,10 @@ visit_tex_src(nir_tex_instr *instr, nir_foreach_src_cb cb, void *state)
if (!visit_src(&instr->src[i].src, cb, state))
return false;
+ if (instr->texture != NULL)
+ if (!visit_deref_src(instr->texture, cb, state))
+ return false;
+
if (instr->sampler != NULL)
if (!visit_deref_src(instr->sampler, cb, state))
return false;
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 4968460..6d660d8 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -923,6 +923,7 @@ typedef enum {
nir_tex_src_ms_index, /* MSAA sample index */
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;
@@ -973,6 +974,22 @@ typedef struct {
/* gather component selector */
unsigned component : 2;
+ /** The texture index
+ *
+ * If this texture instruction has a nir_tex_src_texture_offset source,
+ * then the texture index is given by texture_index + texture_offset.
+ */
+ unsigned texture_index;
+
+ /** The size of the texture array or 0 if it's not an array */
+ unsigned texture_array_size;
+
+ /** The texture deref
+ *
+ * If this is null, use texture_index instead.
+ */
+ nir_deref_var *texture;
+
/** The sampler index
*
* If this texture instruction has a nir_tex_src_sampler_offset source,
@@ -980,10 +997,11 @@ typedef struct {
*/
unsigned sampler_index;
- /** The size of the sampler array or 0 if it's not an array */
- unsigned sampler_array_size;
-
- nir_deref_var *sampler; /* if this is NULL, use sampler_index instead */
+ /** The sampler deref
+ *
+ * If this is null, use sampler_index instead.
+ */
+ nir_deref_var *sampler;
} nir_tex_instr;
static inline unsigned
diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c
index 5eff743..a666d8e 100644
--- a/src/compiler/nir/nir_clone.c
+++ b/src/compiler/nir/nir_clone.c
@@ -357,8 +357,13 @@ clone_tex(clone_state *state, const nir_tex_instr *tex)
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;
+ 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;
- ntex->sampler_array_size = tex->sampler_array_size;
if (tex->sampler)
ntex->sampler = clone_deref_var(state, tex->sampler, &ntex->instr);
diff --git a/src/compiler/nir/nir_instr_set.c b/src/compiler/nir/nir_instr_set.c
index d3f939f..eb02132 100644
--- a/src/compiler/nir/nir_instr_set.c
+++ b/src/compiler/nir/nir_instr_set.c
@@ -155,8 +155,9 @@ hash_tex(uint32_t hash, const nir_tex_instr *instr)
hash = HASH(hash, instr->const_offset);
unsigned component = instr->component;
hash = HASH(hash, component);
+ hash = HASH(hash, instr->texture_index);
+ hash = HASH(hash, instr->texture_array_size);
hash = HASH(hash, instr->sampler_index);
- hash = HASH(hash, instr->sampler_array_size);
assert(!instr->sampler);
@@ -305,13 +306,15 @@ nir_instrs_equal(const nir_instr *instr1, const nir_instr *instr2)
memcmp(tex1->const_offset, tex2->const_offset,
sizeof(tex1->const_offset)) != 0 ||
tex1->component != tex2->component ||
- tex1->sampler_index != tex2->sampler_index ||
- tex1->sampler_array_size != tex2->sampler_array_size) {
+ tex1->texture_index != tex2->texture_index ||
+ tex1->texture_array_size != tex2->texture_array_size ||
+ tex1->sampler_index != tex2->sampler_index) {
return false;
}
/* Don't support un-lowered sampler derefs currently. */
- assert(!tex1->sampler && !tex2->sampler);
+ assert(!tex1->texture && !tex1->sampler &&
+ !tex2->texture && !tex2->sampler);
return true;
}
@@ -422,7 +425,7 @@ instr_can_rewrite(nir_instr *instr)
nir_tex_instr *tex = nir_instr_as_tex(instr);
/* Don't support un-lowered sampler derefs currently. */
- if (tex->sampler)
+ if (tex->texture || tex->sampler)
return false;
return true;
diff --git a/src/compiler/nir/nir_lower_samplers.c b/src/compiler/nir/nir_lower_samplers.c
index 96e8291..2965413 100644
--- a/src/compiler/nir/nir_lower_samplers.c
+++ b/src/compiler/nir/nir_lower_samplers.c
@@ -94,6 +94,9 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
if (instr->sampler == NULL)
return;
+ /* GLSL only has combined textures/samplers */
+ assert(instr->texture == NULL);
+
instr->sampler_index = 0;
unsigned location = instr->sampler->var->data.location;
unsigned array_elements = 1;
@@ -106,7 +109,7 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
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;
@@ -120,13 +123,19 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
/* Now we can go ahead and move the source over to being a
* first-class texture source.
*/
+ instr->src[instr->num_srcs].src_type = nir_tex_src_texture_offset;
+ instr->num_srcs++;
+ nir_instr_rewrite_src(&instr->instr,
+ &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->sampler_array_size = array_elements;
+ instr->texture_array_size = array_elements;
}
if (location > shader_program->NumUniformStorage - 1 ||
@@ -139,6 +148,8 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr
shader_program->UniformStorage[location].opaque[stage].index;
instr->sampler = NULL;
+
+ instr->texture_index = instr->sampler_index;
}
typedef struct {
diff --git a/src/compiler/nir/nir_lower_tex.c b/src/compiler/nir/nir_lower_tex.c
index ae24fb2..d0590ee 100644
--- a/src/compiler/nir/nir_lower_tex.c
+++ b/src/compiler/nir/nir_lower_tex.c
@@ -133,7 +133,7 @@ get_texture_size(nir_builder *b, nir_tex_instr *tex)
txs = nir_tex_instr_create(b->shader, 1);
txs->op = nir_texop_txs;
txs->sampler_dim = GLSL_SAMPLER_DIM_RECT;
- txs->sampler_index = tex->sampler_index;
+ txs->texture_index = tex->texture_index;
txs->dest_type = nir_type_int;
/* only single src, the lod: */
@@ -317,7 +317,7 @@ nir_lower_tex_block(nir_block *block, void *void_state)
state->progress = true;
}
- if (((1 << tex->sampler_index) & state->options->swizzle_result) &&
+ if (((1 << tex->texture_index) & state->options->swizzle_result) &&
!nir_tex_instr_is_query(tex) &&
!(tex->is_shadow && tex->is_new_style_shadow)) {
swizzle_result(b, tex, state->options->swizzles[tex->sampler_index]);
diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c
index 48ecb48..5736944 100644
--- a/src/compiler/nir/nir_print.c
+++ b/src/compiler/nir/nir_print.c
@@ -600,6 +600,9 @@ print_tex_instr(nir_tex_instr *instr, print_state *state)
case nir_tex_src_ddy:
fprintf(fp, "(ddy)");
break;
+ case nir_tex_src_texture_offset:
+ fprintf(fp, "(texture_offset)");
+ break;
case nir_tex_src_sampler_offset:
fprintf(fp, "(sampler_offset)");
break;
@@ -630,13 +633,18 @@ print_tex_instr(nir_tex_instr *instr, print_state *state)
fprintf(fp, "%u (gather_component), ", instr->component);
}
+ if (instr->texture) {
+ assert(instr->sampler);
+ fprintf(fp, " (texture)");
+ }
if (instr->sampler) {
print_deref(instr->sampler, state);
+ fprintf(fp, " (sampler)");
} else {
- fprintf(fp, "%u", instr->sampler_index);
+ assert(instr->texture == NULL);
+ fprintf(fp, "%u (texture) %u (sampler)",
+ instr->texture_index, instr->sampler_index);
}
-
- fprintf(fp, " (sampler)");
}
static void
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index 0efb2fa..66decde 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -3009,7 +3009,7 @@ fs_visitor::nir_emit_texture(const fs_builder &bld, nir_tex_instr *instr)
case nir_tex_src_sampler_offset: {
/* Figure out the highest possible sampler index and mark it as used */
- uint32_t max_used = sampler + instr->sampler_array_size - 1;
+ uint32_t max_used = sampler + instr->texture_array_size - 1;
if (instr->op == nir_texop_tg4 && devinfo->gen < 8) {
max_used += stage_prog_data->binding_table.gather_texture_start;
} else {
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
index d3ac7ab..f3f361c 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
@@ -1720,7 +1720,7 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
* the last element of the array. Mark it here, because the generator
* doesn't have enough information to determine the bound.
*/
- uint32_t array_size = instr->sampler_array_size;
+ uint32_t array_size = instr->texture_array_size;
uint32_t max_used = sampler + array_size - 1;
if (instr->op == nir_texop_tg4) {
max_used += prog_data->base.binding_table.gather_texture_start;
diff --git a/src/mesa/program/prog_to_nir.c b/src/mesa/program/prog_to_nir.c
index ebcc528..f8659f6 100644
--- a/src/mesa/program/prog_to_nir.c
+++ b/src/mesa/program/prog_to_nir.c
@@ -609,6 +609,7 @@ ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src,
instr->op = op;
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) {
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list