gallium: Implement 2D constant buffers for fragment shader in softpipe.
authorMichal Krol <michal@vmware.com>
Tue, 19 Jan 2010 12:20:15 +0000 (13:20 +0100)
committerMichal Krol <michal@vmware.com>
Thu, 28 Jan 2010 13:07:29 +0000 (14:07 +0100)
src/gallium/auxiliary/draw/draw_gs.c
src/gallium/auxiliary/draw/draw_vs_exec.c
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/tgsi/tgsi_exec.h
src/gallium/drivers/softpipe/sp_context.c
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/softpipe/sp_draw_arrays.c
src/gallium/drivers/softpipe/sp_fs_sse.c
src/gallium/drivers/softpipe/sp_quad_fs.c
src/gallium/drivers/softpipe/sp_state_fs.c

index daf8d071f123d43fb0955abe1a0c134a6c4fc4a9..c3cc365a8d9c98a6e69fe6a86697582a3a42aae2 100644 (file)
@@ -302,7 +302,7 @@ void draw_geometry_shader_run(struct draw_geometry_shader *shader,
    unsigned num_primitives = count/num_vertices;
    unsigned inputs_from_vs = 0;
 
-   machine->Consts = constants;
+   machine->Consts[0] = constants;
 
    for (i = 0; i < shader->info.num_inputs; ++i) {
       if (shader->info.input_semantic_name[i] != TGSI_SEMANTIC_PRIMID)
index 41cc802613126f9dc81f68d5c571b41ccfcafaaa..3f7a5ca14b4bef51bf7bf4b9eba878269ded2063 100644 (file)
@@ -95,7 +95,7 @@ vs_exec_run_linear( struct draw_vertex_shader *shader,
    unsigned int i, j;
    unsigned slot;
 
-   machine->Consts = constants;
+   machine->Consts[0] = constants;
 
    for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
       unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
index 83646b73c1ee3d12735611a1463e89f5ebfaa031..74e7e637cc6913339165454bea2222fd82bbd597 100644 (file)
@@ -953,107 +953,90 @@ micro_sub(
 }
 
 static void
-fetch_src_file_channel(
-   const struct tgsi_exec_machine *mach,
-   const uint file,
-   const uint swizzle,
-   const union tgsi_exec_channel *index,
-   union tgsi_exec_channel *chan )
-{
-   switch( swizzle ) {
-   case TGSI_SWIZZLE_X:
-   case TGSI_SWIZZLE_Y:
-   case TGSI_SWIZZLE_Z:
-   case TGSI_SWIZZLE_W:
-      switch( file ) {
-      case TGSI_FILE_CONSTANT:
-         assert(mach->Consts);
-         if (index->i[0] < 0)
-            chan->f[0] = 0.0f;
-         else
-            chan->f[0] = mach->Consts[index->i[0]][swizzle];
-         if (index->i[1] < 0)
-            chan->f[1] = 0.0f;
-         else
-            chan->f[1] = mach->Consts[index->i[1]][swizzle];
-         if (index->i[2] < 0)
-            chan->f[2] = 0.0f;
-         else
-            chan->f[2] = mach->Consts[index->i[2]][swizzle];
-         if (index->i[3] < 0)
-            chan->f[3] = 0.0f;
-         else
-            chan->f[3] = mach->Consts[index->i[3]][swizzle];
-         break;
+fetch_src_file_channel(const struct tgsi_exec_machine *mach,
+                       const uint file,
+                       const uint swizzle,
+                       const union tgsi_exec_channel *index,
+                       const union tgsi_exec_channel *index2D,
+                       union tgsi_exec_channel *chan)
+{
+   uint i;
 
-      case TGSI_FILE_INPUT:
-      case TGSI_FILE_SYSTEM_VALUE:
-         chan->u[0] = mach->Inputs[index->i[0]].xyzw[swizzle].u[0];
-         chan->u[1] = mach->Inputs[index->i[1]].xyzw[swizzle].u[1];
-         chan->u[2] = mach->Inputs[index->i[2]].xyzw[swizzle].u[2];
-         chan->u[3] = mach->Inputs[index->i[3]].xyzw[swizzle].u[3];
-         break;
+   switch (file) {
+   case TGSI_FILE_CONSTANT:
+      for (i = 0; i < QUAD_SIZE; i++) {
+         assert(index2D->i[i] >= 0 && index2D->i[i] < PIPE_MAX_CONSTANT);
+         assert(mach->Consts[index2D->i[i]]);
 
-      case TGSI_FILE_TEMPORARY:
-         assert(index->i[0] < TGSI_EXEC_NUM_TEMPS);
-         chan->u[0] = mach->Temps[index->i[0]].xyzw[swizzle].u[0];
-         chan->u[1] = mach->Temps[index->i[1]].xyzw[swizzle].u[1];
-         chan->u[2] = mach->Temps[index->i[2]].xyzw[swizzle].u[2];
-         chan->u[3] = mach->Temps[index->i[3]].xyzw[swizzle].u[3];
-         break;
+         if (index->i[i] < 0) {
+            chan->u[i] = 0;
+         } else {
+            const uint *p = (const uint *)mach->Consts[index2D->i[i]];
 
-      case TGSI_FILE_IMMEDIATE:
-         assert( index->i[0] < (int) mach->ImmLimit );
-         chan->f[0] = mach->Imms[index->i[0]][swizzle];
-         assert( index->i[1] < (int) mach->ImmLimit );
-         chan->f[1] = mach->Imms[index->i[1]][swizzle];
-         assert( index->i[2] < (int) mach->ImmLimit );
-         chan->f[2] = mach->Imms[index->i[2]][swizzle];
-         assert( index->i[3] < (int) mach->ImmLimit );
-         chan->f[3] = mach->Imms[index->i[3]][swizzle];
-         break;
+            chan->u[i] = p[index->i[i] * 4 + swizzle];
+         }
+      }
+      break;
 
-      case TGSI_FILE_ADDRESS:
-         chan->u[0] = mach->Addrs[index->i[0]].xyzw[swizzle].u[0];
-         chan->u[1] = mach->Addrs[index->i[1]].xyzw[swizzle].u[1];
-         chan->u[2] = mach->Addrs[index->i[2]].xyzw[swizzle].u[2];
-         chan->u[3] = mach->Addrs[index->i[3]].xyzw[swizzle].u[3];
-         break;
+   case TGSI_FILE_INPUT:
+   case TGSI_FILE_SYSTEM_VALUE:
+      for (i = 0; i < QUAD_SIZE; i++) {
+         /* XXX: 2D indexing */
+         chan->u[i] = mach->Inputs[index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i]].xyzw[swizzle].u[i];
+      }
+      break;
 
-      case TGSI_FILE_PREDICATE:
-         assert(index->i[0] < TGSI_EXEC_NUM_PREDS);
-         assert(index->i[1] < TGSI_EXEC_NUM_PREDS);
-         assert(index->i[2] < TGSI_EXEC_NUM_PREDS);
-         assert(index->i[3] < TGSI_EXEC_NUM_PREDS);
-         chan->u[0] = mach->Predicates[0].xyzw[swizzle].u[0];
-         chan->u[1] = mach->Predicates[0].xyzw[swizzle].u[1];
-         chan->u[2] = mach->Predicates[0].xyzw[swizzle].u[2];
-         chan->u[3] = mach->Predicates[0].xyzw[swizzle].u[3];
-         break;
+   case TGSI_FILE_TEMPORARY:
+      for (i = 0; i < QUAD_SIZE; i++) {
+         assert(index->i[i] < TGSI_EXEC_NUM_TEMPS);
+         assert(index2D->i[i] == 0);
 
-      case TGSI_FILE_OUTPUT:
-         /* vertex/fragment output vars can be read too */
-         chan->u[0] = mach->Outputs[index->i[0]].xyzw[swizzle].u[0];
-         chan->u[1] = mach->Outputs[index->i[1]].xyzw[swizzle].u[1];
-         chan->u[2] = mach->Outputs[index->i[2]].xyzw[swizzle].u[2];
-         chan->u[3] = mach->Outputs[index->i[3]].xyzw[swizzle].u[3];
-         break;
+         chan->u[i] = mach->Temps[index->i[i]].xyzw[swizzle].u[i];
+      }
+      break;
 
-      default:
-         assert( 0 );
-         chan->u[0] = 0;
-         chan->u[1] = 0;
-         chan->u[2] = 0;
-         chan->u[3] = 0;
+   case TGSI_FILE_IMMEDIATE:
+      for (i = 0; i < QUAD_SIZE; i++) {
+         assert(index->i[i] >= 0 && index->i[i] < (int)mach->ImmLimit);
+         assert(index2D->i[i] == 0);
+
+         chan->f[i] = mach->Imms[index->i[i]][swizzle];
+      }
+      break;
+
+   case TGSI_FILE_ADDRESS:
+      for (i = 0; i < QUAD_SIZE; i++) {
+         assert(index->i[i] >= 0);
+         assert(index2D->i[i] == 0);
+
+         chan->u[i] = mach->Addrs[index->i[i]].xyzw[swizzle].u[i];
+      }
+      break;
+
+   case TGSI_FILE_PREDICATE:
+      for (i = 0; i < QUAD_SIZE; i++) {
+         assert(index->i[i] >= 0 && index->i[i] < TGSI_EXEC_NUM_PREDS);
+         assert(index2D->i[i] == 0);
+
+         chan->u[i] = mach->Predicates[0].xyzw[swizzle].u[i];
+      }
+      break;
+
+   case TGSI_FILE_OUTPUT:
+      /* vertex/fragment output vars can be read too */
+      for (i = 0; i < QUAD_SIZE; i++) {
+         assert(index->i[i] >= 0);
+         assert(index2D->i[i] == 0);
+
+         chan->u[i] = mach->Outputs[index->i[i]].xyzw[swizzle].u[i];
       }
       break;
 
    default:
-      assert( 0 );
-      chan->u[0] = 0;
-      chan->u[1] = 0;
-      chan->u[2] = 0;
-      chan->u[3] = 0;
+      assert(0);
+      for (i = 0; i < QUAD_SIZE; i++) {
+         chan->u[i] = 0;
+      }
    }
 }
 
@@ -1065,6 +1048,7 @@ fetch_source(const struct tgsi_exec_machine *mach,
              enum tgsi_exec_datatype src_datatype)
 {
    union tgsi_exec_channel index;
+   union tgsi_exec_channel index2D;
    uint swizzle;
 
    /* We start with a direct index into a register file.
@@ -1103,12 +1087,12 @@ fetch_source(const struct tgsi_exec_machine *mach,
 
       /* get current value of address register[swizzle] */
       swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, CHAN_X );
-      fetch_src_file_channel(
-         mach,
-         reg->Indirect.File,
-         swizzle,
-         &index2,
-         &indir_index );
+      fetch_src_file_channel(mach,
+                             reg->Indirect.File,
+                             swizzle,
+                             &index2,
+                             &ZeroVec,
+                             &indir_index);
 
       /* add value of address register to the offset */
       index.i[0] += indir_index.i[0];
@@ -1129,35 +1113,15 @@ fetch_source(const struct tgsi_exec_machine *mach,
     * subscript to a register file. Effectively it means that
     * the register file is actually a 2D array of registers.
     *
-    *    file[3][1] == file[3*sizeof(file[1])+1],
+    *    file[3][1],
     *    where:
     *       [3] = Dimension.Index
     */
    if (reg->Register.Dimension) {
-      int array_size;
-      union tgsi_exec_channel dim_index;
-
-      /* The size of the first-order array depends on the register file type.
-       * We need to multiply the index to the first array to get an effective,
-       * "flat" index that points to the beginning of the second-order array.
-       */
-      switch (reg->Register.File) {
-      case TGSI_FILE_INPUT:
-      case TGSI_FILE_SYSTEM_VALUE:
-         array_size = TGSI_EXEC_MAX_INPUT_ATTRIBS;
-         break;
-      case TGSI_FILE_CONSTANT:
-         array_size = TGSI_EXEC_MAX_CONST_BUFFER;
-         break;
-      default:
-         assert( 0 );
-         array_size = 0;
-      }
-
-      dim_index.i[0] =
-      dim_index.i[1] =
-      dim_index.i[2] =
-      dim_index.i[3] = reg->Dimension.Index;
+      index2D.i[0] =
+      index2D.i[1] =
+      index2D.i[2] =
+      index2D.i[3] = reg->Dimension.Index;
 
       /* Again, the second subscript index can be addressed indirectly
        * identically to the first one.
@@ -1182,45 +1146,46 @@ fetch_source(const struct tgsi_exec_machine *mach,
          index2.i[3] = reg->DimIndirect.Index;
 
          swizzle = tgsi_util_get_src_register_swizzle( &reg->DimIndirect, CHAN_X );
-         fetch_src_file_channel(
-            mach,
-            reg->DimIndirect.File,
-            swizzle,
-            &index2,
-            &indir_index );
-
-         dim_index.i[0] += indir_index.i[0];
-         dim_index.i[1] += indir_index.i[1];
-         dim_index.i[2] += indir_index.i[2];
-         dim_index.i[3] += indir_index.i[3];
+         fetch_src_file_channel(mach,
+                                reg->DimIndirect.File,
+                                swizzle,
+                                &index2,
+                                &ZeroVec,
+                                &indir_index);
+
+         index2D.i[0] += indir_index.i[0];
+         index2D.i[1] += indir_index.i[1];
+         index2D.i[2] += indir_index.i[2];
+         index2D.i[3] += indir_index.i[3];
 
          /* for disabled execution channels, zero-out the index to
           * avoid using a potential garbage value.
           */
          for (i = 0; i < QUAD_SIZE; i++) {
-            if ((execmask & (1 << i)) == 0)
-               dim_index.i[i] = 0;
+            if ((execmask & (1 << i)) == 0) {
+               index2D.i[i] = 0;
+            }
          }
       }
 
-      index.i[0] += dim_index.i[0] * array_size;
-      index.i[1] += dim_index.i[1] * array_size;
-      index.i[2] += dim_index.i[2] * array_size;
-      index.i[3] += dim_index.i[3] * array_size;
-
       /* If by any chance there was a need for a 3D array of register
        * files, we would have to check whether Dimension is followed
        * by a dimension register and continue the saga.
        */
+   } else {
+      index2D.i[0] =
+      index2D.i[1] =
+      index2D.i[2] =
+      index2D.i[3] = 0;
    }
 
    swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index );
-   fetch_src_file_channel(
-      mach,
-      reg->Register.File,
-      swizzle,
-      &index,
-      chan );
+   fetch_src_file_channel(mach,
+                          reg->Register.File,
+                          swizzle,
+                          &index,
+                          &index2D,
+                          chan);
 
    if (reg->Register.Absolute) {
       if (src_datatype == TGSI_EXEC_DATA_FLOAT) {
@@ -1283,12 +1248,12 @@ store_dest(struct tgsi_exec_machine *mach,
       swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, CHAN_X );
 
       /* fetch values from the address/indirection register */
-      fetch_src_file_channel(
-         mach,
-         reg->Indirect.File,
-         swizzle,
-         &index,
-         &indir_index );
+      fetch_src_file_channel(mach,
+                             reg->Indirect.File,
+                             swizzle,
+                             &index,
+                             &ZeroVec,
+                             &indir_index);
 
       /* save indirection offset */
       offset = indir_index.i[0];
index 59e3b445cc3cbd9cf9dc5cce1b789ee79121f423..1f3e85fb62f4df603e658a6c6498ca0b6ce68c22 100644 (file)
@@ -260,7 +260,7 @@ struct tgsi_exec_machine
    struct tgsi_sampler           **Samplers;
 
    unsigned                      ImmLimit;
-   const float                   (*Consts)[4];
+   const void *Consts[PIPE_MAX_CONSTANT];
    const struct tgsi_token       *Tokens;   /**< Declarations, instructions */
    unsigned                      Processor; /**< TGSI_PROCESSOR_x */
 
index 73e075f0d88671e2f1fcbbc2104e9b5849023725..a3a7825aa1882f9fd89eeb3b70de596d4bc77136 100644 (file)
@@ -111,9 +111,13 @@ softpipe_destroy( struct pipe_context *pipe )
       pipe_texture_reference(&softpipe->vertex_textures[i], NULL);
    }
 
-   for (i = 0; i < Elements(softpipe->constants); i++) {
-      if (softpipe->constants[i]) {
-         pipe_buffer_reference(&softpipe->constants[i], NULL);
+   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
+      uint j;
+
+      for (j = 0; j < PIPE_MAX_CONSTANT; j++) {
+         if (softpipe->constants[i][j]) {
+            pipe_buffer_reference(&softpipe->constants[i][j], NULL);
+         }
       }
    }
 
index da673c57adab134a2cad7db500b7ca92b8bcfc9d..f19b3cd5be289ba2e4f4b07b803b4ee74b88ee55 100644 (file)
@@ -63,7 +63,7 @@ struct softpipe_context {
    /** Other rendering state */
    struct pipe_blend_color blend_color;
    struct pipe_clip_state clip;
-   struct pipe_buffer *constants[PIPE_SHADER_TYPES];
+   struct pipe_buffer *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT];
    struct pipe_framebuffer_state framebuffer;
    struct pipe_poly_stipple poly_stipple;
    struct pipe_scissor_state scissor;
@@ -92,7 +92,7 @@ struct softpipe_context {
    ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
 
    /** Mapped constant buffers */
-   void *mapped_constants[PIPE_SHADER_TYPES];
+   void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT];
 
    /** Vertex format */
    struct vertex_info vertex_info;
index 03b58d2fb7245c41d64a782cf7fdd1e61ed71876..cbb9631fa5356867ff3941d5c2706efa26bb40a9 100644 (file)
@@ -52,26 +52,32 @@ softpipe_map_constant_buffers(struct softpipe_context *sp)
    uint i, vssize, gssize;
 
    for (i = 0; i < PIPE_SHADER_TYPES; i++) {
-      if (sp->constants[i] && sp->constants[i]->size)
-         sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i],
-                                                  PIPE_BUFFER_USAGE_CPU_READ);
+      uint j;
+
+      for (j = 0; j < PIPE_MAX_CONSTANT; j++) {
+         if (sp->constants[i][j] && sp->constants[i][j]->size) {
+            sp->mapped_constants[i][j] = ws->buffer_map(ws,
+                                                        sp->constants[i][j],
+                                                        PIPE_BUFFER_USAGE_CPU_READ);
+         }
+      }
    }
 
-   if (sp->constants[PIPE_SHADER_VERTEX])
-      vssize = sp->constants[PIPE_SHADER_VERTEX]->size;
+   if (sp->constants[PIPE_SHADER_VERTEX][0])
+      vssize = sp->constants[PIPE_SHADER_VERTEX][0]->size;
    else
       vssize = 0;
 
-   if (sp->constants[PIPE_SHADER_GEOMETRY])
-      gssize = sp->constants[PIPE_SHADER_GEOMETRY]->size;
+   if (sp->constants[PIPE_SHADER_GEOMETRY][0])
+      gssize = sp->constants[PIPE_SHADER_GEOMETRY][0]->size;
    else
       gssize = 0;
 
    draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX,
-                                   sp->mapped_constants[PIPE_SHADER_VERTEX],
+                                   sp->mapped_constants[PIPE_SHADER_VERTEX][0],
                                    vssize);
    draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY,
-                                   sp->mapped_constants[PIPE_SHADER_GEOMETRY],
+                                   sp->mapped_constants[PIPE_SHADER_GEOMETRY][0],
                                    gssize);
 }
 
@@ -91,9 +97,14 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp)
    draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY, NULL, 0);
 
    for (i = 0; i < PIPE_SHADER_TYPES; i++) {
-      if (sp->constants[i] && sp->constants[i]->size)
-         ws->buffer_unmap(ws, sp->constants[i]);
-      sp->mapped_constants[i] = NULL;
+      uint j;
+
+      for (j = 0; j < PIPE_MAX_CONSTANT; j++) {
+         if (sp->constants[i][j] && sp->constants[i][j]->size) {
+            ws->buffer_unmap(ws, sp->constants[i][j]);
+         }
+         sp->mapped_constants[i][j] = NULL;
+      }
    }
 }
 
index f912950658523fab2b875f0730f00e5ede327fbe..acee213670606864fdf399a8bdf094a97151422b 100644 (file)
@@ -135,7 +135,7 @@ fs_sse_run( const struct sp_fragment_shader *base,
    tgsi_set_exec_mask(machine, 1, 1, 1, 1);
 
    shader->func( machine,
-                machine->Consts,
+                 (const float (*)[4])machine->Consts[0],
                  (const float (*)[4])shader->immediates,
                 machine->InterpCoefs
                 /*, &machine->QuadPos*/
index e799df136edd9a1de96ef88b9dcfa6f709bd05db..9c497073c23fa4258daded10a8092c48a4b2bfa1 100644 (file)
@@ -107,10 +107,11 @@ shade_quads(struct quad_stage *qs,
    struct quad_shade_stage *qss = quad_shade_stage( qs );
    struct softpipe_context *softpipe = qs->softpipe;
    struct tgsi_exec_machine *machine = qss->machine;
-
    unsigned i, pass = 0;
-   
-   machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
+
+   for (i = 0; i < PIPE_MAX_CONSTANT; i++) {
+      machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i];
+   }
    machine->InterpCoefs = quads[0]->coef;
 
    for (i = 0; i < nr; i++) {
index b7ed4441b4363ab0c5f665b36f354f5f267dfe8c..50ed51661aed2ca48f2eb5ed34ed6daf267d54bf 100644 (file)
@@ -164,12 +164,12 @@ softpipe_set_constant_buffer(struct pipe_context *pipe,
    struct softpipe_context *softpipe = softpipe_context(pipe);
 
    assert(shader < PIPE_SHADER_TYPES);
-   assert(index == 0);
+   assert(index < PIPE_MAX_CONSTANT);
 
    draw_flush(softpipe->draw);
 
    /* note: reference counting */
-   pipe_buffer_reference(&softpipe->constants[shader], buf);
+   pipe_buffer_reference(&softpipe->constants[shader][index], buf);
 
    softpipe->dirty |= SP_NEW_CONSTANTS;
 }