delete [] bits;
}
-
-void
-ir_array_refcount_entry::mark_array_elements_referenced(const array_deref_range *dr,
- unsigned count)
-{
- if (count != array_depth)
- return;
-
- mark_array_elements_referenced(dr, count, 1, 0);
-}
-
-void
-ir_array_refcount_entry::mark_array_elements_referenced(const array_deref_range *dr,
- unsigned count,
- unsigned scale,
- unsigned linearized_index)
-{
- /* Walk through the list of array dereferences in least- to
- * most-significant order. Along the way, accumulate the current
- * linearized offset and the scale factor for each array-of-.
- */
- for (unsigned i = 0; i < count; i++) {
- if (dr[i].index < dr[i].size) {
- linearized_index += dr[i].index * scale;
- scale *= dr[i].size;
- } else {
- /* For each element in the current array, update the count and
- * offset, then recurse to process the remaining arrays.
- *
- * There is some inefficency here if the last element in the
- * array_deref_range list specifies the entire array. In that case,
- * the loop will make recursive calls with count == 0. In the call,
- * all that will happen is the bit will be set.
- */
- for (unsigned j = 0; j < dr[i].size; j++) {
- mark_array_elements_referenced(&dr[i + 1],
- count - (i + 1),
- scale * dr[i].size,
- linearized_index + (j * scale));
- }
-
- return;
- }
- }
-
- BITSET_SET(bits, linearized_index);
-}
-
ir_array_refcount_entry *
ir_array_refcount_visitor::get_variable_entry(ir_variable *var)
{
if (entry == NULL)
return visit_stop;
- entry->mark_array_elements_referenced(derefs, num_derefs);
+ link_util_mark_array_elements_referenced(derefs, num_derefs,
+ entry->array_depth,
+ entry->bits);
return visit_continue;
}
#include "ir.h"
#include "ir_visitor.h"
+#include "linker_util.h"
#include "compiler/glsl_types.h"
#include "util/bitset.h"
-/**
- * Describes an access of an array element or an access of the whole array
- */
-struct array_deref_range {
- /**
- * Index that was accessed.
- *
- * All valid array indices are less than the size of the array. If index
- * is equal to the size of the array, this means the entire array has been
- * accessed (e.g., due to use of a non-constant index).
- */
- unsigned index;
-
- /** Size of the array. Used for offset calculations. */
- unsigned size;
-};
-
class ir_array_refcount_entry
{
public:
/** Has the variable been referenced? */
bool is_referenced;
- /**
- * Mark a set of array elements as accessed.
- *
- * If every \c array_deref_range is for a single index, only a single
- * element will be marked. If any \c array_deref_range is for an entire
- * array-of-, then multiple elements will be marked.
- *
- * Items in the \c array_deref_range list appear in least- to
- * most-significant order. This is the \b opposite order the indices
- * appear in the GLSL shader text. An array access like
- *
- * x = y[1][i][3];
- *
- * would appear as
- *
- * { { 3, n }, { m, m }, { 1, p } }
- *
- * where n, m, and p are the sizes of the arrays-of-arrays.
- *
- * The set of marked array elements can later be queried by
- * \c ::is_linearized_index_referenced.
- *
- * \param dr List of array_deref_range elements to be processed.
- * \param count Number of array_deref_range elements to be processed.
- */
- void mark_array_elements_referenced(const array_deref_range *dr,
- unsigned count);
+ /** Count of nested arrays in the type. */
+ unsigned array_depth;
+
+ /** Set of bit-flags to note which array elements have been accessed. */
+ BITSET_WORD *bits;
/** Has a linearized array index been referenced? */
bool is_linearized_index_referenced(unsigned linearized_index) const
}
private:
- /** Set of bit-flags to note which array elements have been accessed. */
- BITSET_WORD *bits;
/**
* Total number of bits referenced by \c bits.
*/
unsigned num_bits;
- /** Count of nested arrays in the type. */
- unsigned array_depth;
-
- /**
- * Recursive part of the public mark_array_elements_referenced method.
- *
- * The recursion occurs when an entire array-of- is accessed. See the
- * implementation for more details.
- *
- * \param dr List of array_deref_range elements to be
- * processed.
- * \param count Number of array_deref_range elements to be
- * processed.
- * \param scale Current offset scale.
- * \param linearized_index Current accumulated linearized array index.
- */
- void mark_array_elements_referenced(const array_deref_range *dr,
- unsigned count,
- unsigned scale,
- unsigned linearized_index);
-
friend class array_refcount_test;
};
}
}
}
+
+/**
+ * Recursive part of the public mark_array_elements_referenced function.
+ *
+ * The recursion occurs when an entire array-of- is accessed. See the
+ * implementation for more details.
+ *
+ * \param dr List of array_deref_range elements to be
+ * processed.
+ * \param count Number of array_deref_range elements to be
+ * processed.
+ * \param scale Current offset scale.
+ * \param linearized_index Current accumulated linearized array index.
+ */
+void
+_mark_array_elements_referenced(const struct array_deref_range *dr,
+ unsigned count, unsigned scale,
+ unsigned linearized_index,
+ BITSET_WORD *bits)
+{
+ /* Walk through the list of array dereferences in least- to
+ * most-significant order. Along the way, accumulate the current
+ * linearized offset and the scale factor for each array-of-.
+ */
+ for (unsigned i = 0; i < count; i++) {
+ if (dr[i].index < dr[i].size) {
+ linearized_index += dr[i].index * scale;
+ scale *= dr[i].size;
+ } else {
+ /* For each element in the current array, update the count and
+ * offset, then recurse to process the remaining arrays.
+ *
+ * There is some inefficency here if the last eBITSET_WORD *bitslement in the
+ * array_deref_range list specifies the entire array. In that case,
+ * the loop will make recursive calls with count == 0. In the call,
+ * all that will happen is the bit will be set.
+ */
+ for (unsigned j = 0; j < dr[i].size; j++) {
+ _mark_array_elements_referenced(&dr[i + 1],
+ count - (i + 1),
+ scale * dr[i].size,
+ linearized_index + (j * scale),
+ bits);
+ }
+
+ return;
+ }
+ }
+
+ BITSET_SET(bits, linearized_index);
+}
+
+/**
+ * Mark a set of array elements as accessed.
+ *
+ * If every \c array_deref_range is for a single index, only a single
+ * element will be marked. If any \c array_deref_range is for an entire
+ * array-of-, then multiple elements will be marked.
+ *
+ * Items in the \c array_deref_range list appear in least- to
+ * most-significant order. This is the \b opposite order the indices
+ * appear in the GLSL shader text. An array access like
+ *
+ * x = y[1][i][3];
+ *
+ * would appear as
+ *
+ * { { 3, n }, { m, m }, { 1, p } }
+ *
+ * where n, m, and p are the sizes of the arrays-of-arrays.
+ *
+ * The set of marked array elements can later be queried by
+ * \c ::is_linearized_index_referenced.
+ *
+ * \param dr List of array_deref_range elements to be processed.
+ * \param count Number of array_deref_range elements to be processed.
+ */
+void
+link_util_mark_array_elements_referenced(const struct array_deref_range *dr,
+ unsigned count, unsigned array_depth,
+ BITSET_WORD *bits)
+{
+ if (count != array_depth)
+ return;
+
+ _mark_array_elements_referenced(dr, count, 1, 0, bits);
+}
#ifndef GLSL_LINKER_UTIL_H
#define GLSL_LINKER_UTIL_H
+#include "util/bitset.h"
+
struct gl_context;
struct gl_shader_program;
struct gl_uniform_storage;
unsigned slots;
};
+/**
+ * Describes an access of an array element or an access of the whole array
+ */
+struct array_deref_range {
+ /**
+ * Index that was accessed.
+ *
+ * All valid array indices are less than the size of the array. If index
+ * is equal to the size of the array, this means the entire array has been
+ * accessed (e.g., due to use of a non-constant index).
+ */
+ unsigned index;
+
+ /** Size of the array. Used for offset calculations. */
+ unsigned size;
+};
+
void
linker_error(struct gl_shader_program *prog, const char *fmt, ...);
void
link_util_calculate_subroutine_compat(struct gl_shader_program *prog);
+void
+link_util_mark_array_elements_referenced(const struct array_deref_range *dr,
+ unsigned count, unsigned array_depth,
+ BITSET_WORD *bits);
+
#ifdef __cplusplus
}
#endif
};
const unsigned accessed_element = 0 + (1 * 5) + (2 * 4 * 5);
- entry.mark_array_elements_referenced(dr, 3);
+ link_util_mark_array_elements_referenced(dr, 3, entry.array_depth,
+ entry.bits);
for (unsigned i = 0; i < total_elements; i++)
EXPECT_EQ(i == accessed_element, entry.is_linearized_index_referenced(i));
{ 0, 5 }, { 1, 4 }, { 3, 3 }
};
- entry.mark_array_elements_referenced(dr, 3);
+ link_util_mark_array_elements_referenced(dr, 3, entry.array_depth,
+ entry.bits);
for (unsigned i = 0; i < 3; i++) {
for (unsigned j = 0; j < 4; j++) {
{ 0, 5 }, { 4, 4 }, { 1, 3 }
};
- entry.mark_array_elements_referenced(dr, 3);
+ link_util_mark_array_elements_referenced(dr, 3, entry.array_depth,
+ entry.bits);
for (unsigned i = 0; i < 3; i++) {
for (unsigned j = 0; j < 4; j++) {
{ 5, 5 }, { 2, 4 }, { 1, 3 }
};
- entry.mark_array_elements_referenced(dr, 3);
+ link_util_mark_array_elements_referenced(dr, 3, entry.array_depth,
+ entry.bits);
for (unsigned i = 0; i < 3; i++) {
for (unsigned j = 0; j < 4; j++) {
{ 5, 5 }, { 3, 4 }, { 3, 3 }
};
- entry.mark_array_elements_referenced(dr, 3);
+ link_util_mark_array_elements_referenced(dr, 3, entry.array_depth,
+ entry.bits);
for (unsigned i = 0; i < 3; i++) {
for (unsigned j = 0; j < 4; j++) {