[Mesa-dev] [PATCH 17/37] i965/gen6/gs: Implement geometry shaders for outputs other than points.

2014-08-14 Thread Iago Toral Quiroga
---
 src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp | 72 ---
 src/mesa/drivers/dri/i965/gen6_gs_visitor.h   |  2 +
 2 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp 
b/src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp
index b78c55e..5123bd7 100644
--- a/src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp
@@ -79,6 +79,21 @@ gen6_gs_visitor::emit_prolog()
 * and URB_WRITE messages.
 */
this->temp = src_reg(this, glsl_type::uint_type);
+
+   /* This will be used to know when we are processing the first vertex of
+* a primitive. We will set this to URB_WRITE_PRIM_START only when we know
+* that we are processing the first vertex in the primitive and to zero
+* otherwise. This way we can use its value directly in the URB write
+* headers.
+*/
+   this->first_vertex = src_reg(this, glsl_type::uint_type);
+   emit(MOV(dst_reg(this->first_vertex), URB_WRITE_PRIM_START));
+
+   /* The FF_SYNC message requires to know the number of primitives generated,
+* so keep a counter for this.
+*/
+   this->prim_count = src_reg(this, glsl_type::uint_type);
+   emit(MOV(dst_reg(this->prim_count), 0u));
 }
 
 void
@@ -109,18 +124,26 @@ gen6_gs_visitor::visit(ir_emit_vertex *)
   this->vertex_output_offset, 1u));
   }
 
-  /* Now buffer flags for this vertex (we only support point output
-   * for now).
-   */
+  /* Now buffer flags for this vertex */
   dst_reg dst(this->vertex_output);
   dst.reladdr = ralloc(mem_ctx, src_reg);
   memcpy(dst.reladdr, &this->vertex_output_offset, sizeof(src_reg));
-  /* If we are outputting points, then every vertex has PrimStart and
-   * PrimEnd set.
-   */
   if (c->gp->program.OutputType == GL_POINTS) {
+ /* If we are outputting points, then every vertex has PrimStart and
+  * PrimEnd set.
+  */
  emit(MOV(dst, (_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT) |
   URB_WRITE_PRIM_START | URB_WRITE_PRIM_END));
+ emit(ADD(dst_reg(this->prim_count), this->prim_count, 1u));
+  } else {
+ /* Otherwise, we can only set the PrimStart flag, which we have stored
+  * in the first_vertex register. We will have to wait until we execute
+  * EndPrimitive() or we end the thread to set the PrimEnd flag on a
+  * vertex.
+  */
+ emit(OR(dst, this->first_vertex,
+ (c->prog_data.output_topology << URB_WRITE_PRIM_TYPE_SHIFT)));
+ emit(MOV(dst_reg(this->first_vertex), 0u));
   }
   emit(ADD(dst_reg(this->vertex_output_offset),
this->vertex_output_offset, 1u));
@@ -140,6 +163,41 @@ gen6_gs_visitor::visit(ir_end_primitive *)
 */
if (c->gp->program.OutputType == GL_POINTS)
   return;
+
+   /* Otheriwse we know that the last vertex we have processed was the last
+* vertex in the primitive and we need to set its PrimEnd flag, so do this
+* unless we haven't emitted that vertex at all.
+*
+* Notice that we have already incremented vertex_count when we processed
+* the last emit_vertex, so we need to take that into account in the
+* comparison below (hence the num_output_vertices + 1 in the comparison
+* below).
+*/
+   unsigned num_output_vertices = c->gp->program.VerticesOut;
+   emit(CMP(dst_null_d(), this->vertex_count, src_reg(num_output_vertices + 1),
+BRW_CONDITIONAL_L));
+   emit(IF(BRW_PREDICATE_NORMAL));
+   {
+  /* vertex_output_offset is already pointing at the first entry of the
+   * next vertex. So subtract 1 to modify the flags for the previous
+   * vertex.
+   */
+  src_reg offset(this, glsl_type::uint_type);
+  emit(ADD(dst_reg(offset), this->vertex_output_offset, brw_imm_d(-1)));
+
+  src_reg dst(this->vertex_output);
+  dst.reladdr = ralloc(mem_ctx, src_reg);
+  memcpy(dst.reladdr, &offset, sizeof(src_reg));
+
+  emit(OR(dst_reg(dst), dst, URB_WRITE_PRIM_END));
+  emit(ADD(dst_reg(this->prim_count), this->prim_count, 1u));
+
+  /* Set the first vertex flag to indicate that the next vertex will start
+   * a primitive.
+   */
+  emit(MOV(dst_reg(this->first_vertex), URB_WRITE_PRIM_START));
+   }
+   emit(BRW_OPCODE_ENDIF);
 }
 
 void
@@ -234,7 +292,7 @@ gen6_gs_visitor::emit_thread_end()
/* Issue the FF_SYNC message and obtain the initial VUE handle. */
this->current_annotation = "gen6 thread end: ff_sync";
emit(GS_OPCODE_FF_SYNC,
-dst_reg(MRF, base_mrf), this->temp, this->vertex_count);
+dst_reg(MRF, base_mrf), this->temp, this->prim_count);
 
/* Loop over all buffered vertices and emit URB write messages */
this->current_annotation = "gen6 thread end: urb writes init";
diff --git a/src/mesa/drivers/dri/i965/gen6_gs_visitor.h 
b/src/mesa/drivers/dri/i965/gen6_gs_visito

Re: [Mesa-dev] [PATCH 17/37] i965/gen6/gs: Implement geometry shaders for outputs other than points.

2014-09-16 Thread Jordan Justen
On Thu, Aug 14, 2014 at 4:11 AM, Iago Toral Quiroga  wrote:
> ---
>  src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp | 72 
> ---
>  src/mesa/drivers/dri/i965/gen6_gs_visitor.h   |  2 +
>  2 files changed, 67 insertions(+), 7 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp 
> b/src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp
> index b78c55e..5123bd7 100644
> --- a/src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp
> +++ b/src/mesa/drivers/dri/i965/gen6_gs_visitor.cpp
> @@ -79,6 +79,21 @@ gen6_gs_visitor::emit_prolog()
>  * and URB_WRITE messages.
>  */
> this->temp = src_reg(this, glsl_type::uint_type);
> +
> +   /* This will be used to know when we are processing the first vertex of
> +* a primitive. We will set this to URB_WRITE_PRIM_START only when we know
> +* that we are processing the first vertex in the primitive and to zero
> +* otherwise. This way we can use its value directly in the URB write
> +* headers.
> +*/
> +   this->first_vertex = src_reg(this, glsl_type::uint_type);
> +   emit(MOV(dst_reg(this->first_vertex), URB_WRITE_PRIM_START));
> +
> +   /* The FF_SYNC message requires to know the number of primitives 
> generated,
> +* so keep a counter for this.
> +*/
> +   this->prim_count = src_reg(this, glsl_type::uint_type);
> +   emit(MOV(dst_reg(this->prim_count), 0u));
>  }
>
>  void
> @@ -109,18 +124,26 @@ gen6_gs_visitor::visit(ir_emit_vertex *)
>this->vertex_output_offset, 1u));
>}
>
> -  /* Now buffer flags for this vertex (we only support point output
> -   * for now).
> -   */
> +  /* Now buffer flags for this vertex */
>dst_reg dst(this->vertex_output);
>dst.reladdr = ralloc(mem_ctx, src_reg);
>memcpy(dst.reladdr, &this->vertex_output_offset, sizeof(src_reg));
> -  /* If we are outputting points, then every vertex has PrimStart and
> -   * PrimEnd set.
> -   */
>if (c->gp->program.OutputType == GL_POINTS) {
> + /* If we are outputting points, then every vertex has PrimStart and
> +  * PrimEnd set.
> +  */
>   emit(MOV(dst, (_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT) |
>URB_WRITE_PRIM_START | URB_WRITE_PRIM_END));
> + emit(ADD(dst_reg(this->prim_count), this->prim_count, 1u));
> +  } else {
> + /* Otherwise, we can only set the PrimStart flag, which we have 
> stored
> +  * in the first_vertex register. We will have to wait until we 
> execute
> +  * EndPrimitive() or we end the thread to set the PrimEnd flag on a
> +  * vertex.
> +  */
> + emit(OR(dst, this->first_vertex,
> + (c->prog_data.output_topology << 
> URB_WRITE_PRIM_TYPE_SHIFT)));
> + emit(MOV(dst_reg(this->first_vertex), 0u));
>}
>emit(ADD(dst_reg(this->vertex_output_offset),
> this->vertex_output_offset, 1u));
> @@ -140,6 +163,41 @@ gen6_gs_visitor::visit(ir_end_primitive *)
>  */
> if (c->gp->program.OutputType == GL_POINTS)
>return;
> +
> +   /* Otheriwse we know that the last vertex we have processed was the last

Typo.

16 & 17
Reviewed-by: Jordan Justen 

> +* vertex in the primitive and we need to set its PrimEnd flag, so do this
> +* unless we haven't emitted that vertex at all.
> +*
> +* Notice that we have already incremented vertex_count when we processed
> +* the last emit_vertex, so we need to take that into account in the
> +* comparison below (hence the num_output_vertices + 1 in the comparison
> +* below).
> +*/
> +   unsigned num_output_vertices = c->gp->program.VerticesOut;
> +   emit(CMP(dst_null_d(), this->vertex_count, src_reg(num_output_vertices + 
> 1),
> +BRW_CONDITIONAL_L));
> +   emit(IF(BRW_PREDICATE_NORMAL));
> +   {
> +  /* vertex_output_offset is already pointing at the first entry of the
> +   * next vertex. So subtract 1 to modify the flags for the previous
> +   * vertex.
> +   */
> +  src_reg offset(this, glsl_type::uint_type);
> +  emit(ADD(dst_reg(offset), this->vertex_output_offset, brw_imm_d(-1)));
> +
> +  src_reg dst(this->vertex_output);
> +  dst.reladdr = ralloc(mem_ctx, src_reg);
> +  memcpy(dst.reladdr, &offset, sizeof(src_reg));
> +
> +  emit(OR(dst_reg(dst), dst, URB_WRITE_PRIM_END));
> +  emit(ADD(dst_reg(this->prim_count), this->prim_count, 1u));
> +
> +  /* Set the first vertex flag to indicate that the next vertex will 
> start
> +   * a primitive.
> +   */
> +  emit(MOV(dst_reg(this->first_vertex), URB_WRITE_PRIM_START));
> +   }
> +   emit(BRW_OPCODE_ENDIF);
>  }
>
>  void
> @@ -234,7 +292,7 @@ gen6_gs_visitor::emit_thread_end()
> /* Issue the FF_SYNC message and obtain the initial VUE handle. */
> this->current_annotation = "gen6 thread end: ff_sync";
> emit(GS_OPCODE_FF_SYNC,
> -dst_reg(MRF, base