From 6afd0954e12eb75a4ce19580907b1fc4145369b9 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Tue, 31 Mar 2020 13:49:30 +1100 Subject: [PATCH] glsl: pull mark_array_elements_referenced() out into common helper MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We will reuse this helper in the NIR linker in the following patches. Reviewed-by: Alejandro Piñeiro Part-of: --- src/compiler/glsl/ir_array_refcount.cpp | 52 +---------- src/compiler/glsl/ir_array_refcount.h | 73 ++-------------- src/compiler/glsl/linker_util.cpp | 87 +++++++++++++++++++ src/compiler/glsl/linker_util.h | 24 +++++ .../glsl/tests/array_refcount_test.cpp | 15 ++-- 5 files changed, 130 insertions(+), 121 deletions(-) diff --git a/src/compiler/glsl/ir_array_refcount.cpp b/src/compiler/glsl/ir_array_refcount.cpp index c2295c96ca9..0c18c7e0ecf 100644 --- a/src/compiler/glsl/ir_array_refcount.cpp +++ b/src/compiler/glsl/ir_array_refcount.cpp @@ -75,54 +75,6 @@ ir_array_refcount_entry::~ir_array_refcount_entry() 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) { @@ -224,7 +176,9 @@ ir_array_refcount_visitor::visit_enter(ir_dereference_array *ir) 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; } diff --git a/src/compiler/glsl/ir_array_refcount.h b/src/compiler/glsl/ir_array_refcount.h index ef3fbaa368d..4a9d9017a02 100644 --- a/src/compiler/glsl/ir_array_refcount.h +++ b/src/compiler/glsl/ir_array_refcount.h @@ -32,26 +32,10 @@ #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: @@ -63,33 +47,11 @@ 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 @@ -101,8 +63,6 @@ public: } private: - /** Set of bit-flags to note which array elements have been accessed. */ - BITSET_WORD *bits; /** * Total number of bits referenced by \c bits. @@ -111,27 +71,6 @@ private: */ 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; }; diff --git a/src/compiler/glsl/linker_util.cpp b/src/compiler/glsl/linker_util.cpp index 80c9f2872f9..a790de3ca39 100644 --- a/src/compiler/glsl/linker_util.cpp +++ b/src/compiler/glsl/linker_util.cpp @@ -287,3 +287,90 @@ link_util_calculate_subroutine_compat(struct gl_shader_program *prog) } } } + +/** + * 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); +} diff --git a/src/compiler/glsl/linker_util.h b/src/compiler/glsl/linker_util.h index 53e0ca315a5..16f5ca9e401 100644 --- a/src/compiler/glsl/linker_util.h +++ b/src/compiler/glsl/linker_util.h @@ -24,6 +24,8 @@ #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; @@ -45,6 +47,23 @@ struct empty_uniform_block { 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, ...); @@ -81,6 +100,11 @@ link_util_check_uniform_resources(struct gl_context *ctx, 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 diff --git a/src/compiler/glsl/tests/array_refcount_test.cpp b/src/compiler/glsl/tests/array_refcount_test.cpp index 3d2778d46a5..7a69f56c435 100644 --- a/src/compiler/glsl/tests/array_refcount_test.cpp +++ b/src/compiler/glsl/tests/array_refcount_test.cpp @@ -283,7 +283,8 @@ TEST_F(array_refcount_test, mark_array_elements_referenced_simple) }; 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)); @@ -302,7 +303,8 @@ TEST_F(array_refcount_test, mark_array_elements_referenced_whole_first_array) { 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++) { @@ -330,7 +332,8 @@ TEST_F(array_refcount_test, mark_array_elements_referenced_whole_second_array) { 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++) { @@ -358,7 +361,8 @@ TEST_F(array_refcount_test, mark_array_elements_referenced_whole_third_array) { 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++) { @@ -386,7 +390,8 @@ TEST_F(array_refcount_test, mark_array_elements_referenced_whole_first_and_third { 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++) { -- 2.30.2