glsl: pull mark_array_elements_referenced() out into common helper
We will reuse this helper in the NIR linker in the following patches. Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4623>
This commit is contained in:

committed by
Marge Bot

parent
5d992b539e
commit
6afd0954e1
@@ -75,54 +75,6 @@ ir_array_refcount_entry::~ir_array_refcount_entry()
|
|||||||
delete [] bits;
|
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_entry *
|
||||||
ir_array_refcount_visitor::get_variable_entry(ir_variable *var)
|
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)
|
if (entry == NULL)
|
||||||
return visit_stop;
|
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;
|
return visit_continue;
|
||||||
}
|
}
|
||||||
|
@@ -32,26 +32,10 @@
|
|||||||
|
|
||||||
#include "ir.h"
|
#include "ir.h"
|
||||||
#include "ir_visitor.h"
|
#include "ir_visitor.h"
|
||||||
|
#include "linker_util.h"
|
||||||
#include "compiler/glsl_types.h"
|
#include "compiler/glsl_types.h"
|
||||||
#include "util/bitset.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
|
class ir_array_refcount_entry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -63,33 +47,11 @@ public:
|
|||||||
/** Has the variable been referenced? */
|
/** Has the variable been referenced? */
|
||||||
bool is_referenced;
|
bool is_referenced;
|
||||||
|
|
||||||
/**
|
/** Count of nested arrays in the type. */
|
||||||
* Mark a set of array elements as accessed.
|
unsigned array_depth;
|
||||||
*
|
|
||||||
* If every \c array_deref_range is for a single index, only a single
|
/** Set of bit-flags to note which array elements have been accessed. */
|
||||||
* element will be marked. If any \c array_deref_range is for an entire
|
BITSET_WORD *bits;
|
||||||
* 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);
|
|
||||||
|
|
||||||
/** Has a linearized array index been referenced? */
|
/** Has a linearized array index been referenced? */
|
||||||
bool is_linearized_index_referenced(unsigned linearized_index) const
|
bool is_linearized_index_referenced(unsigned linearized_index) const
|
||||||
@@ -101,8 +63,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Set of bit-flags to note which array elements have been accessed. */
|
|
||||||
BITSET_WORD *bits;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Total number of bits referenced by \c bits.
|
* Total number of bits referenced by \c bits.
|
||||||
@@ -111,27 +71,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
unsigned num_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;
|
friend class array_refcount_test;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
@@ -24,6 +24,8 @@
|
|||||||
#ifndef GLSL_LINKER_UTIL_H
|
#ifndef GLSL_LINKER_UTIL_H
|
||||||
#define GLSL_LINKER_UTIL_H
|
#define GLSL_LINKER_UTIL_H
|
||||||
|
|
||||||
|
#include "util/bitset.h"
|
||||||
|
|
||||||
struct gl_context;
|
struct gl_context;
|
||||||
struct gl_shader_program;
|
struct gl_shader_program;
|
||||||
struct gl_uniform_storage;
|
struct gl_uniform_storage;
|
||||||
@@ -45,6 +47,23 @@ struct empty_uniform_block {
|
|||||||
unsigned slots;
|
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
|
void
|
||||||
linker_error(struct gl_shader_program *prog, const char *fmt, ...);
|
linker_error(struct gl_shader_program *prog, const char *fmt, ...);
|
||||||
|
|
||||||
@@ -81,6 +100,11 @@ link_util_check_uniform_resources(struct gl_context *ctx,
|
|||||||
void
|
void
|
||||||
link_util_calculate_subroutine_compat(struct gl_shader_program *prog);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -283,7 +283,8 @@ TEST_F(array_refcount_test, mark_array_elements_referenced_simple)
|
|||||||
};
|
};
|
||||||
const unsigned accessed_element = 0 + (1 * 5) + (2 * 4 * 5);
|
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++)
|
for (unsigned i = 0; i < total_elements; i++)
|
||||||
EXPECT_EQ(i == accessed_element, entry.is_linearized_index_referenced(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 }
|
{ 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 i = 0; i < 3; i++) {
|
||||||
for (unsigned j = 0; j < 4; j++) {
|
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 }
|
{ 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 i = 0; i < 3; i++) {
|
||||||
for (unsigned j = 0; j < 4; j++) {
|
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 }
|
{ 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 i = 0; i < 3; i++) {
|
||||||
for (unsigned j = 0; j < 4; j++) {
|
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 }
|
{ 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 i = 0; i < 3; i++) {
|
||||||
for (unsigned j = 0; j < 4; j++) {
|
for (unsigned j = 0; j < 4; j++) {
|
||||||
|
Reference in New Issue
Block a user