[Mesa-dev] [RFC PATCH 10/13] nir/xfb: WIP: handle xfb buffer/offset rule for block arrays

Alejandro PiƱeiro apinheiro at igalia.com
Sat Dec 8 11:48:18 UTC 2018


>From GLSL 4.60 spec, Section 4.4.2. Output Layout Qualifiers,
subsection Transform Feedback Layout Qualifiers:

   "When a block is declared as an array, all members of block
    array-element 0 are captured, as previously described, by the
    declared or inherited xfb_buffer. Generally, an array of size N of
    blocks is captured by N consecutive buffers, with all members of
    block array-element E captured by buffer B, where B equals the
    declared or inherited xfb_buffer plus E"

And although not explicitly mentioned, one conclusion for this
paragraph would be that the xfb offset remain the same for the same
member of each array-element.

WIP: xfb arrays of blocks tests still not working properly due
     location overlapping.
---
 src/compiler/nir/nir_gather_xfb_info.c | 57 ++++++++++++++++++++------
 1 file changed, 45 insertions(+), 12 deletions(-)

diff --git a/src/compiler/nir/nir_gather_xfb_info.c b/src/compiler/nir/nir_gather_xfb_info.c
index 6611691b686..c46af311b20 100644
--- a/src/compiler/nir/nir_gather_xfb_info.c
+++ b/src/compiler/nir/nir_gather_xfb_info.c
@@ -30,28 +30,30 @@ add_var_xfb_outputs(nir_xfb_info *xfb,
                     nir_variable *var,
                     unsigned *location,
                     unsigned *offset,
+                    unsigned buffer,
                     const struct glsl_type *type)
 {
    if (glsl_type_is_array(type) || glsl_type_is_matrix(type)) {
       unsigned length = glsl_get_length(type);
       const struct glsl_type *child_type = glsl_get_array_element(type);
+
       for (unsigned i = 0; i < length; i++)
-         add_var_xfb_outputs(xfb, var, location, offset, child_type);
+         add_var_xfb_outputs(xfb, var, location, offset, buffer, child_type);
    } else if (glsl_type_is_struct(type)) {
       unsigned length = glsl_get_length(type);
       for (unsigned i = 0; i < length; i++) {
          const struct glsl_type *child_type = glsl_get_struct_field(type, i);
-         add_var_xfb_outputs(xfb, var, location, offset, child_type);
+         add_var_xfb_outputs(xfb, var, location, offset, buffer, child_type);
       }
    } else {
-      assert(var->data.xfb_buffer < NIR_MAX_XFB_BUFFERS);
-      if (xfb->buffers_written & (1 << var->data.xfb_buffer)) {
-         assert(xfb->strides[var->data.xfb_buffer] == var->data.xfb_stride);
-         assert(xfb->buffer_to_stream[var->data.xfb_buffer] == var->data.stream);
+      assert(buffer < NIR_MAX_XFB_BUFFERS);
+      if (xfb->buffers_written & (1 << buffer)) {
+         assert(xfb->strides[buffer] == var->data.xfb_stride);
+         assert(xfb->buffer_to_stream[buffer] == var->data.stream);
       } else {
-         xfb->buffers_written |= (1 << var->data.xfb_buffer);
-         xfb->strides[var->data.xfb_buffer] = var->data.xfb_stride;
-         xfb->buffer_to_stream[var->data.xfb_buffer] = var->data.stream;
+         xfb->buffers_written |= (1 << buffer);
+         xfb->strides[buffer] = var->data.xfb_stride;
+         xfb->buffer_to_stream[buffer] = var->data.stream;
       }
 
       assert(var->data.stream < NIR_MAX_XFB_STREAMS);
@@ -76,7 +78,7 @@ add_var_xfb_outputs(nir_xfb_info *xfb,
       for (unsigned s = 0; s < attrib_slots; s++) {
          nir_xfb_output_info *output = &xfb->outputs[xfb->output_count++];
 
-         output->buffer = var->data.xfb_buffer;
+         output->buffer = buffer;
          output->offset = *offset;
          output->location = *location;
          output->component_mask = (comp_mask >> (s * 4)) & 0xf;
@@ -154,9 +156,40 @@ nir_gather_xfb_info(const nir_shader *shader, void *mem_ctx)
       if (var->data.explicit_xfb_buffer &&
           var->data.explicit_offset) {
 
+         unsigned buffer = var->data.xfb_buffer;
          unsigned location = var->data.location;
-         unsigned offset = var->data.offset;
-         add_var_xfb_outputs(xfb, var, &location, &offset, var->type);
+
+         /* The last check is needed to distinguish a block array from a block
+          * that contains an array. That becomes messy due all the
+          * nir_split_per_members passes, as at this point we are not going to
+          * receive the original block array type, but splitted
+          */
+         bool block_array = glsl_type_is_array(var->type) &&
+            var->interface_type != NULL &&
+            glsl_get_array_element(var->type) == var->interface_type;
+
+         /*
+          * From GLSL 4.60 spec, Section 4.4.2. Output Layout Qualifiers,
+          * subsection Transform Feedback Layout Qualifiers:
+          *
+          * "When a block is declared as an array, all members of block
+          *  array-element 0 are captured, as previously described, by the
+          *  declared or inherited xfb_buffer. Generally, an array of size N
+          *  of blocks is captured by N consecutive buffers, with all members
+          *  of block array-element E captured by buffer B, where B equals the
+          *  declared or inherited xfb_buffer plus E"
+          *
+          * We handle it here, externally to add_var_xfb_outputs, in order to
+          * not make it overly complicated.
+          */
+         unsigned num_iterations = block_array ? glsl_get_length(var->type) : 1;
+         const struct glsl_type *top_level_type = block_array ? var->interface_type : var->type;
+
+         for (unsigned i = 0; i < num_iterations; i++, buffer++) {
+            unsigned offset = var->data.offset;
+
+            add_var_xfb_outputs(xfb, var, &location, &offset, buffer, top_level_type);
+         }
       }
    }
    assert(xfb->output_count == num_outputs);
-- 
2.19.1



More information about the mesa-dev mailing list