draw: rework handling of non-existing outputs in emit code
authorRoland Scheidegger <sroland@vmware.com>
Thu, 7 Jan 2016 00:52:39 +0000 (01:52 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Thu, 7 Jan 2016 00:52:39 +0000 (01:52 +0100)
Previously the code would just redirect requests for attributes which
don't exist to use output 0. Rework this to output all zeros instead which
seems more useful - in particular some extensions like
ARB_fragment_layer_viewport require 0 in the fs even if it wasn't output by
previous stages. That way, drivers don't have to special case this depending
if the vs/gs outputs some attribute or not.

Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com>
src/gallium/auxiliary/draw/draw_pipe_vbuf.c
src/gallium/auxiliary/draw/draw_pt_emit.c
src/gallium/auxiliary/draw/draw_vertex.h

index f36706cee0147ad09e3afbc1bce67866659f9454..6df7149b5313187a5d7ce4b57bc1825758b8e7a1 100644 (file)
@@ -74,9 +74,10 @@ struct vbuf_stage {
    unsigned max_indices;
    unsigned nr_indices;
 
-   /* Cache point size somewhere it's address won't change:
+   /* Cache point size somewhere its address won't change:
     */
    float point_size;
+   float zero4[4];
 
    struct translate_cache *cache;
 };
@@ -205,6 +206,7 @@ vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
    struct translate_key hw_key;
    unsigned dst_offset;
    unsigned i;
+   const struct vertex_info *vinfo;
 
    vbuf->render->set_primitive(vbuf->render, prim);
 
@@ -215,27 +217,33 @@ vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
     * state change.
     */
    vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
-   vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
+   vinfo = vbuf->vinfo;
+   vbuf->vertex_size = vinfo->size * sizeof(float);
 
    /* Translate from pipeline vertices to hw vertices.
     */
    dst_offset = 0;
 
-   for (i = 0; i < vbuf->vinfo->num_attribs; i++) {
+   for (i = 0; i < vinfo->num_attribs; i++) {
       unsigned emit_sz = 0;
       unsigned src_buffer = 0;
       enum pipe_format output_format;
-      unsigned src_offset = (vbuf->vinfo->attrib[i].src_index * 4 * sizeof(float) );
+      unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );
 
-      output_format = draw_translate_vinfo_format(vbuf->vinfo->attrib[i].emit);
-      emit_sz = draw_translate_vinfo_size(vbuf->vinfo->attrib[i].emit);
+      output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
+      emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);
 
       /* doesn't handle EMIT_OMIT */
       assert(emit_sz != 0);
 
-      if (vbuf->vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
-        src_buffer = 1;
-        src_offset = 0;
+      if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
+         src_buffer = 1;
+         src_offset = 0;
+      }
+      else if (vinfo->attrib[i].src_index == DRAW_ATTR_NONEXIST) {
+         /* elements which don't exist will get assigned zeros */
+         src_buffer = 2;
+         src_offset = 0;
       }
 
       hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
@@ -249,7 +257,7 @@ vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
       dst_offset += emit_sz;
    }
 
-   hw_key.nr_elements = vbuf->vinfo->num_attribs;
+   hw_key.nr_elements = vinfo->num_attribs;
    hw_key.output_stride = vbuf->vertex_size;
 
    /* Don't bother with caching at this stage:
@@ -261,6 +269,7 @@ vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
       vbuf->translate = translate_cache_find(vbuf->cache, &hw_key);
 
       vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0, ~0);
+      vbuf->translate->set_buffer(vbuf->translate, 2, &vbuf->zero4[0], 0, ~0);
    }
 
    vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;
@@ -428,7 +437,7 @@ struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
    struct vbuf_stage *vbuf = CALLOC_STRUCT(vbuf_stage);
    if (!vbuf)
       goto fail;
-   
+
    vbuf->stage.draw = draw;
    vbuf->stage.name = "vbuf";
    vbuf->stage.point = vbuf_first_point;
@@ -437,29 +446,30 @@ struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
    vbuf->stage.flush = vbuf_flush;
    vbuf->stage.reset_stipple_counter = vbuf_reset_stipple_counter;
    vbuf->stage.destroy = vbuf_destroy;
-   
+
    vbuf->render = render;
    vbuf->max_indices = MIN2(render->max_indices, UNDEFINED_VERTEX_ID-1);
 
-   vbuf->indices = (ushort *) align_malloc( vbuf->max_indices * 
-                                           sizeof(vbuf->indices[0]), 
-                                           16 );
+   vbuf->indices = (ushort *) align_malloc(vbuf->max_indices *
+                    sizeof(vbuf->indices[0]),
+                    16);
    if (!vbuf->indices)
       goto fail;
 
    vbuf->cache = translate_cache_create();
-   if (!vbuf->cache) 
+   if (!vbuf->cache)
       goto fail;
-      
-   
+
    vbuf->vertices = NULL;
    vbuf->vertex_ptr = vbuf->vertices;
-   
+
+   vbuf->zero4[0] = vbuf->zero4[1] = vbuf->zero4[2] = vbuf->zero4[3] = 0.0f;
+
    return &vbuf->stage;
 
- fail:
+fail:
    if (vbuf)
       vbuf_destroy(&vbuf->stage);
-   
+
    return NULL;
 }
index 0b9fab5721cc554819ff53b24f699ad3311da460..6fb630b5498397a73eb604247163cf958ea15e8c 100644 (file)
@@ -44,6 +44,9 @@ struct pt_emit {
    unsigned prim;
 
    const struct vertex_info *vinfo;
+
+   float zero4[4];
+
 };
 
 
@@ -92,6 +95,11 @@ draw_pt_emit_prepare(struct pt_emit *emit,
          src_buffer = 1;
          src_offset = 0;
       }
+      else if (vinfo->attrib[i].src_index == DRAW_ATTR_NONEXIST) {
+         /* elements which don't exist will get assigned zeros */
+         src_buffer = 2;
+         src_offset = 0;
+      }
 
       hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
       hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
@@ -111,6 +119,8 @@ draw_pt_emit_prepare(struct pt_emit *emit,
        translate_key_compare(&emit->translate->key, &hw_key) != 0) {
       translate_key_sanitize(&hw_key);
       emit->translate = translate_cache_find(emit->cache, &hw_key);
+
+      emit->translate->set_buffer(emit->translate, 2, &emit->zero4[0], 0, ~0);
    }
 
    if (!vinfo->size)
@@ -287,6 +297,8 @@ draw_pt_emit_create(struct draw_context *draw)
       return NULL;
    }
 
+   emit->zero4[0] = emit->zero4[1] = emit->zero4[2] = emit->zero4[3] = 0.0f;
+
    return emit;
 }
 
index ee11d2f9276196cad8591810ee7e4d2db152ccfa..ae207e2b0b39c08147c1c06ae87be40d8e8be12a 100644 (file)
@@ -44,6 +44,7 @@
 #include "util/u_debug.h"
 #include "util/u_memory.h"
 
+#define DRAW_ATTR_NONEXIST 255
 
 /**
  * Vertex attribute emit modes
@@ -130,9 +131,9 @@ draw_emit_vertex_attr(struct vertex_info *vinfo,
    const uint n = vinfo->num_attribs;
 
    /* If the src_index is negative, meaning it hasn't been found
-    * lets just redirect it to the first output slot */
+    * we'll assign it all zeros later - set to DRAW_ATTR_NONEXIST */
    if (src_index < 0) {
-      src_index = 0;
+      src_index = DRAW_ATTR_NONEXIST;
    }
 
    assert(n < Elements(vinfo->attrib));