[Mesa-dev] [PATCHv3 14/16] i965: refactor do_gs_prog

Chia-I Wu olvaffe at gmail.com
Tue Aug 19 23:40:35 PDT 2014


Split do_gs_prog into

  brw_gs_init_compile
  brw_gs_do_compile
  brw_gs_upload_compile
  brw_gs_clear_complile

Signed-off-by: Chia-I Wu <olv at lunarg.com>
Acked-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/mesa/drivers/dri/i965/brw_vec4_gs.c | 161 ++++++++++++++++++++------------
 1 file changed, 102 insertions(+), 59 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_vec4_gs.c b/src/mesa/drivers/dri/i965/brw_vec4_gs.c
index 5b2ed51..04407b8 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_gs.c
+++ b/src/mesa/drivers/dri/i965/brw_vec4_gs.c
@@ -33,22 +33,29 @@
 #include "brw_state.h"
 
 
-static bool
-do_gs_prog(struct brw_context *brw,
-           struct gl_shader_program *prog,
-           struct brw_geometry_program *gp,
-           struct brw_gs_prog_key *key)
+static void
+brw_gs_init_compile(struct brw_context *brw,
+                    struct gl_shader_program *prog,
+                    struct brw_geometry_program *gp,
+                    const struct brw_gs_prog_key *key,
+                    struct brw_gs_compile *c)
 {
-   struct brw_stage_state *stage_state = &brw->gs.base;
-   struct brw_gs_compile c;
-   memset(&c, 0, sizeof(c));
-   c.key = *key;
-   c.gp = gp;
+   memset(c, 0, sizeof(*c));
 
-   c.prog_data.include_primitive_id =
-      (gp->program.Base.InputsRead & VARYING_BIT_PRIMITIVE_ID) != 0;
+   c->key = *key;
+   c->gp = gp;
+   c->base.shader_prog = prog;
+   c->base.mem_ctx = ralloc_context(NULL);
+}
 
-   c.prog_data.invocations = gp->program.Invocations;
+static bool
+brw_gs_do_compile(struct brw_context *brw,
+                  struct brw_gs_compile *c)
+{
+   c->prog_data.include_primitive_id =
+      (c->gp->program.Base.InputsRead & VARYING_BIT_PRIMITIVE_ID) != 0;
+
+   c->prog_data.invocations = c->gp->program.Invocations;
 
    /* Allocate the references to the uniforms that will end up in the
     * prog_data associated with the compiled program, and which will be freed
@@ -58,34 +65,37 @@ do_gs_prog(struct brw_context *brw,
     * padding around uniform values below vec4 size, so the worst case is that
     * every uniform is a float which gets padded to the size of a vec4.
     */
-   struct gl_shader *gs = prog->_LinkedShaders[MESA_SHADER_GEOMETRY];
+   struct gl_shader *gs =
+      c->base.shader_prog->_LinkedShaders[MESA_SHADER_GEOMETRY];
    int param_count = gs->num_uniform_components * 4;
 
    /* We also upload clip plane data as uniforms */
    param_count += MAX_CLIP_PLANES * 4;
 
-   c.prog_data.base.base.param =
+   c->prog_data.base.base.param =
       rzalloc_array(NULL, const gl_constant_value *, param_count);
-   c.prog_data.base.base.pull_param =
+   c->prog_data.base.base.pull_param =
       rzalloc_array(NULL, const gl_constant_value *, param_count);
    /* Setting nr_params here NOT to the size of the param and pull_param
     * arrays, but to the number of uniform components vec4_visitor
     * needs. vec4_visitor::setup_uniforms() will set it back to a proper value.
     */
-   c.prog_data.base.base.nr_params = ALIGN(param_count, 4) / 4 + gs->num_samplers;
+   c->prog_data.base.base.nr_params =
+      ALIGN(param_count, 4) / 4 + gs->num_samplers;
 
-   if (gp->program.OutputType == GL_POINTS) {
+   if (c->gp->program.OutputType == GL_POINTS) {
       /* When the output type is points, the geometry shader may output data
        * to multiple streams, and EndPrimitive() has no effect.  So we
        * configure the hardware to interpret the control data as stream ID.
        */
-      c.prog_data.control_data_format = GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_SID;
+      c->prog_data.control_data_format =
+         GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_SID;
 
       /* We only have to emit control bits if we are using streams */
-      if (prog->Geom.UsesStreams)
-         c.control_data_bits_per_vertex = 2;
+      if (c->base.shader_prog->Geom.UsesStreams)
+         c->control_data_bits_per_vertex = 2;
       else
-         c.control_data_bits_per_vertex = 0;
+         c->control_data_bits_per_vertex = 0;
    } else {
       /* When the output type is triangle_strip or line_strip, EndPrimitive()
        * may be used to terminate the current strip and start a new one
@@ -93,32 +103,34 @@ do_gs_prog(struct brw_context *brw,
        * streams is not supported.  So we configure the hardware to interpret
        * the control data as EndPrimitive information (a.k.a. "cut bits").
        */
-      c.prog_data.control_data_format = GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_CUT;
+      c->prog_data.control_data_format =
+         GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_CUT;
 
       /* We only need to output control data if the shader actually calls
        * EndPrimitive().
        */
-      c.control_data_bits_per_vertex = gp->program.UsesEndPrimitive ? 1 : 0;
+      c->control_data_bits_per_vertex =
+         c->gp->program.UsesEndPrimitive ? 1 : 0;
    }
-   c.control_data_header_size_bits =
-      gp->program.VerticesOut * c.control_data_bits_per_vertex;
+   c->control_data_header_size_bits =
+      c->gp->program.VerticesOut * c->control_data_bits_per_vertex;
 
    /* 1 HWORD = 32 bytes = 256 bits */
-   c.prog_data.control_data_header_size_hwords =
-      ALIGN(c.control_data_header_size_bits, 256) / 256;
+   c->prog_data.control_data_header_size_hwords =
+      ALIGN(c->control_data_header_size_bits, 256) / 256;
 
-   GLbitfield64 outputs_written = gp->program.Base.OutputsWritten;
+   GLbitfield64 outputs_written = c->gp->program.Base.OutputsWritten;
 
    /* In order for legacy clipping to work, we need to populate the clip
     * distance varying slots whenever clipping is enabled, even if the vertex
     * shader doesn't write to gl_ClipDistance.
     */
-   if (c.key.base.userclip_active) {
+   if (c->key.base.userclip_active) {
       outputs_written |= BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0);
       outputs_written |= BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1);
    }
 
-   brw_compute_vue_map(brw, &c.prog_data.base.vue_map, outputs_written);
+   brw_compute_vue_map(brw, &c->prog_data.base.vue_map, outputs_written);
 
    /* Compute the output vertex size.
     *
@@ -168,9 +180,10 @@ do_gs_prog(struct brw_context *brw,
     * per interpolation type, so this is plenty.
     *
     */
-   unsigned output_vertex_size_bytes = c.prog_data.base.vue_map.num_slots * 16;
+   unsigned output_vertex_size_bytes =
+           c->prog_data.base.vue_map.num_slots * 16;
    assert(output_vertex_size_bytes <= GEN7_MAX_GS_OUTPUT_VERTEX_SIZE_BYTES);
-   c.prog_data.output_vertex_size_hwords =
+   c->prog_data.output_vertex_size_hwords =
       ALIGN(output_vertex_size_bytes, 32) / 32;
 
    /* Compute URB entry size.  The maximum allowed URB entry size is 32k.
@@ -200,9 +213,9 @@ do_gs_prog(struct brw_context *brw,
     * number of output vertices.  So we'll just calculate the amount of space
     * we need, and if it's too large, fail to compile.
     */
-   unsigned output_size_bytes =
-      c.prog_data.output_vertex_size_hwords * 32 * gp->program.VerticesOut;
-   output_size_bytes += 32 * c.prog_data.control_data_header_size_hwords;
+   unsigned output_size_bytes = c->prog_data.output_vertex_size_hwords * 32 *
+                                c->gp->program.VerticesOut;
+   output_size_bytes += 32 * c->prog_data.control_data_header_size_hwords;
 
    /* Broadwell stores "Vertex Count" as a full 8 DWord (32 byte) URB output,
     * which comes before the control header.
@@ -215,46 +228,76 @@ do_gs_prog(struct brw_context *brw,
       return false;
 
    /* URB entry sizes are stored as a multiple of 64 bytes. */
-   c.prog_data.base.urb_entry_size = ALIGN(output_size_bytes, 64) / 64;
+   c->prog_data.base.urb_entry_size = ALIGN(output_size_bytes, 64) / 64;
 
-   c.prog_data.output_topology =
-      get_hw_prim_for_gl_prim(gp->program.OutputType);
+   c->prog_data.output_topology =
+      get_hw_prim_for_gl_prim(c->gp->program.OutputType);
 
-   brw_compute_vue_map(brw, &c.input_vue_map, c.key.input_varyings);
+   brw_compute_vue_map(brw, &c->input_vue_map, c->key.input_varyings);
 
    /* GS inputs are read from the VUE 256 bits (2 vec4's) at a time, so we
     * need to program a URB read length of ceiling(num_slots / 2).
     */
-   c.prog_data.base.urb_read_length = (c.input_vue_map.num_slots + 1) / 2;
-
-   void *mem_ctx = ralloc_context(NULL);
-   unsigned program_size;
-   const unsigned *program =
-      brw_gs_emit(brw, prog, &c, mem_ctx, &program_size);
-   if (program == NULL) {
-      ralloc_free(mem_ctx);
+   c->prog_data.base.urb_read_length = (c->input_vue_map.num_slots + 1) / 2;
+
+   c->base.program = brw_gs_emit(brw, c->base.shader_prog, c,
+         c->base.mem_ctx, &c->base.program_size);
+   if (c->base.program == NULL)
       return false;
+
+   if (c->base.last_scratch) {
+      c->prog_data.base.total_scratch
+         = brw_get_scratch_size(c->base.last_scratch*REG_SIZE);
    }
 
+   return true;
+}
+
+static void
+brw_gs_upload_compile(struct brw_context *brw,
+                      const struct brw_gs_compile *c)
+{
    /* Scratch space is used for register spilling */
-   if (c.base.last_scratch) {
+   if (c->prog_data.base.total_scratch) {
       perf_debug("Geometry shader triggered register spilling.  "
                  "Try reducing the number of live vec4 values to "
                  "improve performance.\n");
 
-      c.prog_data.base.total_scratch
-         = brw_get_scratch_size(c.base.last_scratch*REG_SIZE);
-
-      brw_get_scratch_bo(brw, &stage_state->scratch_bo,
-			 c.prog_data.base.total_scratch * brw->max_gs_threads);
+      brw_get_scratch_bo(brw, &brw->gs.base.scratch_bo,
+            c->prog_data.base.total_scratch * brw->max_gs_threads);
    }
 
    brw_upload_cache(&brw->cache, BRW_GS_PROG,
-                    &c.key, sizeof(c.key),
-                    program, program_size,
-                    &c.prog_data, sizeof(c.prog_data),
-                    &stage_state->prog_offset, &brw->gs.prog_data);
-   ralloc_free(mem_ctx);
+                    &c->key, sizeof(c->key),
+                    c->base.program, c->base.program_size,
+                    &c->prog_data, sizeof(c->prog_data),
+                    &brw->gs.base.prog_offset, &brw->gs.prog_data);
+}
+
+static void
+brw_gs_clear_compile(struct brw_context *brw,
+                     struct brw_gs_compile *c)
+{
+   ralloc_free(c->base.mem_ctx);
+}
+
+static bool
+do_gs_prog(struct brw_context *brw,
+           struct gl_shader_program *prog,
+           struct brw_geometry_program *gp,
+           struct brw_gs_prog_key *key)
+{
+   struct brw_gs_compile c;
+
+   brw_gs_init_compile(brw, prog, gp, key, &c);
+
+   if (!brw_gs_do_compile(brw, &c)) {
+      brw_gs_clear_compile(brw, &c);
+      return false;
+   }
+
+   brw_gs_upload_compile(brw, &c);
+   brw_gs_clear_compile(brw, &c);
 
    return true;
 }
-- 
2.0.0.rc2



More information about the mesa-dev mailing list