glsl: handle varyings that are not written to but have an xfb_offset
authorTimothy Arceri <timothy.arceri@collabora.com>
Sun, 13 Mar 2016 23:32:17 +0000 (10:32 +1100)
committerTimothy Arceri <timothy.arceri@collabora.com>
Thu, 31 Mar 2016 01:52:29 +0000 (12:52 +1100)
Reviewed-by: Dave Airlie <airlied@redhat.com>
src/compiler/glsl/link_varyings.cpp
src/compiler/glsl/link_varyings.h

index c5c392d6140b82f6302a8778d93aebf85aa080a5..ce6ff0863f03ca5c74ed1aecf1ad3dbfeaa8dec7 100644 (file)
@@ -738,14 +738,26 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
    unsigned num_components = this->num_components();
    while (num_components > 0) {
       unsigned output_size = MIN2(num_components, 4 - location_frac);
-      assert(info->NumOutputs < max_outputs);
-      info->Outputs[info->NumOutputs].ComponentOffset = location_frac;
-      info->Outputs[info->NumOutputs].OutputRegister = location;
-      info->Outputs[info->NumOutputs].NumComponents = output_size;
-      info->Outputs[info->NumOutputs].StreamId = stream_id;
-      info->Outputs[info->NumOutputs].OutputBuffer = buffer;
-      info->Outputs[info->NumOutputs].DstOffset = xfb_offset;
-      ++info->NumOutputs;
+      assert((info->NumOutputs == 0 && max_outputs == 0) ||
+             info->NumOutputs < max_outputs);
+
+      /* From the ARB_enhanced_layouts spec:
+       *
+       *    "If such a block member or variable is not written during a shader
+       *    invocation, the buffer contents at the assigned offset will be
+       *    undefined.  Even if there are no static writes to a variable or
+       *    member that is assigned a transform feedback offset, the space is
+       *    still allocated in the buffer and still affects the stride."
+       */
+      if (this->is_varying_written()) {
+         info->Outputs[info->NumOutputs].ComponentOffset = location_frac;
+         info->Outputs[info->NumOutputs].OutputRegister = location;
+         info->Outputs[info->NumOutputs].NumComponents = output_size;
+         info->Outputs[info->NumOutputs].StreamId = stream_id;
+         info->Outputs[info->NumOutputs].OutputBuffer = buffer;
+         info->Outputs[info->NumOutputs].DstOffset = xfb_offset;
+         ++info->NumOutputs;
+      }
       info->Buffers[buffer].Stream = this->stream_id;
       xfb_offset += output_size;
 
@@ -936,8 +948,10 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
                     num_tfeedback_decls);
 
    unsigned num_outputs = 0;
-   for (unsigned i = 0; i < num_tfeedback_decls; ++i)
-      num_outputs += tfeedback_decls[i].get_num_outputs();
+   for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+      if (tfeedback_decls[i].is_varying_written())
+         num_outputs += tfeedback_decls[i].get_num_outputs();
+   }
 
    prog->LinkedTransformFeedback.Outputs =
       rzalloc_array(prog,
index 7919a8d5cd548a2b1e61df13ff21115bf90cae82..9ea79f04fa8d07b444e6e0c478aef0a4713e9a19 100644 (file)
@@ -108,6 +108,14 @@ public:
       return this->next_buffer_separator;
    }
 
+   bool is_varying_written() const
+   {
+      if (this->next_buffer_separator || this->skip_components)
+         return false;
+
+      return this->matched_candidate->toplevel_var->data.assigned;
+   }
+
    bool is_varying() const
    {
       return !this->next_buffer_separator && !this->skip_components;