src/gallium/auxiliary/tgsi/tgsi_ureg.c | 2 ++
src/gallium/include/pipe/p_state.h | 13 +++++++
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 57 +++++++++++++++++++++++++-----
src/mesa/state_tracker/st_program.c | 4 +++
src/mesa/state_tracker/st_program.h | 1 +
5 files changed, 69 insertions(+), 8 deletions(-)
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index 3c2a923..61db431 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -1658,6 +1658,8 @@ void *ureg_create_shader( struct ureg_program *ureg,
else
memset(&state.stream_output, 0, sizeof(state.stream_output));
+ memset(&state.array_info, 0, sizeof(state.array_info));
+
if (ureg->processor == TGSI_PROCESSOR_VERTEX)
return pipe->create_vs_state( pipe, &state );
else
diff --git a/src/gallium/include/pipe/p_state.h
b/src/gallium/include/pipe/p_state.h
index ab49cab..4490f2e 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -65,6 +65,8 @@ extern "C" {
#define PIPE_MAX_TEXTURE_LEVELS 16
#define PIPE_MAX_SO_BUFFERS 4
+#define PIPE_MAX_INDIRECT_ARRAYS 16
+
struct pipe_reference
{
@@ -205,11 +207,22 @@ struct pipe_stream_output_info
} output[PIPE_MAX_SHADER_OUTPUTS];
};
+struct pipe_shader_indirect_array {
+ unsigned index:16;
+ unsigned size:16;
+};
+
+struct pipe_shader_array_info
+{
+ struct pipe_shader_indirect_array arrays[PIPE_MAX_INDIRECT_ARRAYS];
+ unsigned num_arrays;
+};
struct pipe_shader_state
{
const struct tgsi_token *tokens;
struct pipe_stream_output_info stream_output;
+ struct pipe_shader_array_info array_info;
};
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 1d96e90..4ded1be 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -110,6 +110,7 @@ public:
this->index2D = 0;
this->type = type ? type->base_type : GLSL_TYPE_ERROR;
this->reladdr = NULL;
+ this->size = 0;
}
st_src_reg(gl_register_file file, int index, int type)
@@ -121,6 +122,7 @@ public:
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
this->reladdr = NULL;
+ this->size = 0;
}
st_src_reg(gl_register_file file, int index, int type, int index2D)
@@ -132,6 +134,7 @@ public:
this->swizzle = SWIZZLE_XYZW;
this->negate = 0;
this->reladdr = NULL;
+ this->size = 0;
}
st_src_reg()
@@ -143,6 +146,7 @@ public:
this->swizzle = 0;
this->negate = 0;
this->reladdr = NULL;
+ this->size = 0;
}
explicit st_src_reg(st_dst_reg reg);
@@ -155,6 +159,7 @@ public:
int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
/** Register index should be offset by the integer in this reg. */
st_src_reg *reladdr;
+ int size;
};
class st_dst_reg {
@@ -244,8 +249,9 @@ public:
class variable_storage : public exec_node {
public:
- variable_storage(ir_variable *var, gl_register_file file, int index)
- : file(file), index(index), var(var)
+ variable_storage(ir_variable *var, gl_register_file file, int index,
+ int size = 0)
+ : file(file), index(index), var(var), size(size)
{
/* empty */
}
@@ -253,6 +259,7 @@ public:
gl_register_file file;
int index;
ir_variable *var; /* variable that maps to this, if any */
+ int size;
};
class immediate_storage : public exec_node {
@@ -312,6 +319,7 @@ public:
struct gl_program *prog;
struct gl_shader_program *shader_program;
struct gl_shader_compiler_options *options;
+ struct pipe_shader_array_info array_info;
int next_temp;
@@ -445,6 +453,8 @@ public:
void emit_block_mov(ir_assignment *ir, const struct glsl_type *type,
st_dst_reg *l, st_src_reg *r);
+ void add_array_info(const st_src_reg *src);
+
void *mem_ctx;
};
@@ -1004,7 +1014,8 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type)
src.file = PROGRAM_TEMPORARY;
src.index = next_temp;
src.reladdr = NULL;
- next_temp += type_size(type);
+ src.size = type_size(type);
+ next_temp += src.size;
if (type->is_array() || type->is_record()) {
src.swizzle = SWIZZLE_NOOP;
@@ -1075,9 +1086,10 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
assert((int) ir->num_state_slots == type_size(ir->type));
storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
- this->next_temp);
+ this->next_temp,
+ type_size(ir->type));
this->variables.push_tail(storage);
- this->next_temp += type_size(ir->type);
+ this->next_temp += storage->size;
dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index,
native_integers ? ir->type->base_type : GLSL_TYPE_FLOAT));
@@ -2029,10 +2041,10 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)
case ir_var_auto:
case ir_var_temporary:
entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY,
- this->next_temp);
+ this->next_temp,
+ type_size(var->type));
this->variables.push_tail(entry);
-
- next_temp += type_size(var->type);
+ next_temp += entry->size;
break;
}
@@ -2043,6 +2055,8 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)
}
this->result = st_src_reg(entry->file, entry->index, var->type);
+ this->result.size = entry->size;
+
if (!native_integers)
this->result.type = GLSL_TYPE_FLOAT;
}
@@ -2062,12 +2076,16 @@ glsl_to_tgsi_visitor::visit(ir_dereference_array *ir)
if (index) {
src.index += index->value.i[0] * element_size;
} else {
+
/* Variable index array dereference. It eats the "vec4" of the
* base of the array and an index that offsets the TGSI register
* index.
*/
ir->array_index->accept(this);
+ if (src.size > 1 && src.file == PROGRAM_TEMPORARY)
+ add_array_info(&src);
+
st_src_reg index_reg;
if (element_size == 1) {
@@ -2969,6 +2987,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
prog = NULL;
shader_program = NULL;
options = NULL;
+ array_info.num_arrays = 0;
}
glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor()
@@ -3771,6 +3790,23 @@ glsl_to_tgsi_visitor::renumber_registers(void)
this->next_temp = new_index;
}
+void
+glsl_to_tgsi_visitor::add_array_info(const st_src_reg *src)
+{
+ unsigned i;
+
+ if (array_info.num_arrays == PIPE_MAX_INDIRECT_ARRAYS)
+ return;
+
+ for (i = 0; i < array_info.num_arrays; ++i) {
+ if (array_info.arrays[i].index == (unsigned)src->index)
+ return;
+ }
+ array_info.arrays[i].index = src->index;
+ array_info.arrays[i].size = src->size;
+ ++array_info.num_arrays;
+}
+
/**
* Returns a fragment program which implements the current pixel transfer ops.
* Based on get_pixel_transfer_program in st_atom_pixeltransfer.c.
@@ -4798,6 +4834,11 @@ st_translate_program(
}
if (program->indirect_addr_temps) {
+ struct pipe_shader_array_info *ai =
+ &((struct st_fragment_program*) proginfo)->array_info;
+
+ memcpy(ai, &program->array_info, sizeof(struct pipe_shader_array_info));
+
/* If temps are accessed with indirect addressing, declare temporaries
* in sequential order. Else, we declare them on demand elsewhere.
* (Note: the number of temporaries is equal to program->next_temp)
diff --git a/src/mesa/state_tracker/st_program.c
b/src/mesa/state_tracker/st_program.c
index a9111b5..1370c76 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -739,6 +739,10 @@ st_translate_fragment_program(struct st_context *st,
fs_output_semantic_index, FALSE,
key->clamp_color);
+ if (stfp->glsl_to_tgsi)
+ memcpy(&variant->tgsi.array_info, &stfp->array_info,
+ sizeof(struct pipe_shader_array_info));
+
variant->tgsi.tokens = ureg_get_tokens( ureg, NULL );
ureg_destroy( ureg );
diff --git a/src/mesa/state_tracker/st_program.h
b/src/mesa/state_tracker/st_program.h
index 23a262c..d6b2b0f 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -90,6 +90,7 @@ struct st_fragment_program
{
struct gl_fragment_program Base;
struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+ struct pipe_shader_array_info array_info;
struct st_fp_variant *variants;
};