[Mesa-dev] [PATCH 5/8] tgsi: add support for image operations to tgsi_exec.

Brian Paul brianp at vmware.com
Tue Mar 22 15:37:46 UTC 2016


On 03/21/2016 04:02 PM, Dave Airlie wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> This adds support for load/store/atomic operations on images
> along with image tracking support.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>   src/gallium/auxiliary/draw/draw_gs.c      |   2 +-
>   src/gallium/auxiliary/draw/draw_vs_exec.c |   2 +-
>   src/gallium/auxiliary/tgsi/tgsi_exec.c    | 229 +++++++++++++++++++++++++++++-
>   src/gallium/auxiliary/tgsi/tgsi_exec.h    |  40 +++++-
>   src/gallium/drivers/softpipe/sp_fs_exec.c |   4 +-
>   5 files changed, 271 insertions(+), 6 deletions(-)
>
> diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
> index 6b33341..c4ced9f 100644
> --- a/src/gallium/auxiliary/draw/draw_gs.c
> +++ b/src/gallium/auxiliary/draw/draw_gs.c
> @@ -687,7 +687,7 @@ void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
>      if (!use_llvm && shader && shader->machine->Tokens != shader->state.tokens) {
>         tgsi_exec_machine_bind_shader(shader->machine,
>                                       shader->state.tokens,
> -                                    draw->gs.tgsi.sampler);
> +                                    draw->gs.tgsi.sampler, NULL);
>      }
>   }
>
> diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
> index abd64f5..8c759d4 100644
> --- a/src/gallium/auxiliary/draw/draw_vs_exec.c
> +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
> @@ -70,7 +70,7 @@ vs_exec_prepare( struct draw_vertex_shader *shader,
>      if (evs->machine->Tokens != shader->state.tokens) {
>         tgsi_exec_machine_bind_shader(evs->machine,
>                                       shader->state.tokens,
> -                                    draw->vs.tgsi.sampler);
> +                                    draw->vs.tgsi.sampler, NULL);
>      }
>   }
>
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
> index fa1c916..fe82a95 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
> +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
> @@ -853,7 +853,8 @@ void
>   tgsi_exec_machine_bind_shader(
>      struct tgsi_exec_machine *mach,
>      const struct tgsi_token *tokens,
> -   struct tgsi_sampler *sampler)
> +   struct tgsi_sampler *sampler,
> +   struct tgsi_image *image)
>   {
>      uint k;
>      struct tgsi_parse_context parse;
> @@ -871,6 +872,7 @@ tgsi_exec_machine_bind_shader(
>
>      mach->Tokens = tokens;
>      mach->Sampler = sampler;
> +   mach->Image = image;
>
>      if (!tokens) {
>         /* unbind and free all */
> @@ -3706,6 +3708,206 @@ exec_dfracexp(struct tgsi_exec_machine *mach,
>      }
>   }
>
> +static int
> +get_image_coord_dim(int tgsi_tex, int *sample)
> +{
> +   int dim;
> +   switch (tgsi_tex) {
> +   case TGSI_TEXTURE_BUFFER:
> +   case TGSI_TEXTURE_1D:
> +      dim = 1;
> +      break;
> +   case TGSI_TEXTURE_2D:
> +   case TGSI_TEXTURE_RECT:
> +   case TGSI_TEXTURE_1D_ARRAY:
> +   case TGSI_TEXTURE_2D_MSAA:
> +      dim = 2;
> +      break;
> +   case TGSI_TEXTURE_3D:
> +   case TGSI_TEXTURE_CUBE:
> +   case TGSI_TEXTURE_2D_ARRAY:
> +   case TGSI_TEXTURE_2D_ARRAY_MSAA:
> +   case TGSI_TEXTURE_CUBE_ARRAY:
> +      dim = 3;
> +      break;
> +   default:
> +      assert(!"unknown texture target");
> +      dim = 0;
> +      break;
> +   }
> +
> +   if (sample) {
> +      switch (tgsi_tex) {
> +      case TGSI_TEXTURE_2D_MSAA:
> +         *sample = 3;
> +         break;
> +      case TGSI_TEXTURE_2D_ARRAY_MSAA:
> +         *sample = 4;
> +         break;
> +      default:
> +         *sample = 0;
> +         break;
> +      }
> +   }
> +   return dim;
> +}

That function seems to do two independent things.  Can this be two 
functions?



> +
> +static void
> +exec_load(struct tgsi_exec_machine *mach,
> +          const struct tgsi_full_instruction *inst)
> +{
> +   union tgsi_exec_channel r[4], sample_r;
> +   uint unit;
> +   int sample;
> +   int i, j;
> +   int dim;
> +   uint chan;
> +   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
> +   struct tgsi_image_params params;
> +   int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
> +
> +   unit = fetch_sampler_unit(mach, inst, 0);
> +   dim = get_image_coord_dim(inst->Memory.Texture, &sample);
> +   assert(dim <= 3);
> +
> +   params.execmask = mach->ExecMask & mach->NonHelperMask & ~kilmask;
> +   params.unit = unit;
> +   params.tgsi_tex_instr = inst->Memory.Texture;
> +   params.format = inst->Memory.Format;
> +
> +   for (i = 0; i < dim; i++) {
> +      IFETCH(&r[i], 1, TGSI_CHAN_X + i);
> +   }
> +
> +   if (sample)
> +      IFETCH(&sample_r, 1, TGSI_CHAN_X + sample);
> +
> +   mach->Image->load(mach->Image, &params,
> +                     r[0].i, r[1].i, r[2].i, sample_r.i,
> +                     rgba);
> +   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> +      r[0].f[j] = rgba[0][j];
> +      r[1].f[j] = rgba[1][j];
> +      r[2].f[j] = rgba[2][j];
> +      r[3].f[j] = rgba[3][j];
> +   }
> +   for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
> +      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
> +         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
> +      }
> +   }
> +}
> +
> +static void
> +exec_store(struct tgsi_exec_machine *mach,
> +           const struct tgsi_full_instruction *inst)
> +{
> +   union tgsi_exec_channel r[3], sample_r;
> +   union tgsi_exec_channel value[4];
> +   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
> +   struct tgsi_image_params params;
> +   int dim;
> +   int sample;
> +   int i, j;
> +   uint unit;
> +   int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
> +   unit = inst->Dst[0].Register.Index;
> +   dim = get_image_coord_dim(inst->Memory.Texture, &sample);
> +   assert(dim <= 3);
> +
> +   params.execmask = mach->ExecMask & mach->NonHelperMask & ~kilmask;
> +   params.unit = unit;
> +   params.tgsi_tex_instr = inst->Memory.Texture;
> +   params.format = inst->Memory.Format;
> +
> +   for (i = 0; i < dim; i++) {
> +      IFETCH(&r[i], 0, TGSI_CHAN_X + i);
> +   }
> +
> +   for (i = 0; i < 4; i++) {
> +      FETCH(&value[i], 1, TGSI_CHAN_X + i);
> +   }
> +   if (sample)
> +      IFETCH(&sample_r, 0, TGSI_CHAN_X + sample);
> +
> +   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> +      rgba[0][j] = value[0].f[j];
> +      rgba[1][j] = value[1].f[j];
> +      rgba[2][j] = value[2].f[j];
> +      rgba[3][j] = value[3].f[j];
> +   }
> +
> +   mach->Image->store(mach->Image, &params,
> +                      r[0].i, r[1].i, r[2].i, sample_r.i,
> +                      rgba);
> +}
> +
> +static void
> +exec_atomop(struct tgsi_exec_machine *mach,
> +            const struct tgsi_full_instruction *inst)
> +{
> +   union tgsi_exec_channel r[3], sample_r;
> +   union tgsi_exec_channel value[4], value2[4];
> +   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
> +   float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
> +   struct tgsi_image_params params;
> +   int dim;
> +   int sample;
> +   int i, j;
> +   uint unit, chan;
> +   int kilmask = mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
> +   unit = fetch_sampler_unit(mach, inst, 0);
> +   dim = get_image_coord_dim(inst->Memory.Texture, &sample);
> +   assert(dim <= 3);
> +
> +   params.execmask = mach->ExecMask & mach->NonHelperMask & ~kilmask;
> +   params.unit = unit;
> +   params.tgsi_tex_instr = inst->Memory.Texture;
> +   params.format = inst->Memory.Format;
> +
> +   for (i = 0; i < dim; i++) {
> +      IFETCH(&r[i], 1, TGSI_CHAN_X + i);
> +   }
> +
> +   for (i = 0; i < 4; i++) {
> +      FETCH(&value[i], 2, TGSI_CHAN_X + i);
> +      if (inst->Instruction.Opcode == TGSI_OPCODE_ATOMCAS)
> +         FETCH(&value2[i], 3, TGSI_CHAN_X + i);
> +   }
> +   if (sample)
> +      IFETCH(&sample_r, 1, TGSI_CHAN_X + sample);
> +
> +   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> +      rgba[0][j] = value[0].f[j];
> +      rgba[1][j] = value[1].f[j];
> +      rgba[2][j] = value[2].f[j];
> +      rgba[3][j] = value[3].f[j];
> +   }
> +   if (inst->Instruction.Opcode == TGSI_OPCODE_ATOMCAS) {
> +      for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> +         rgba2[0][j] = value2[0].f[j];
> +         rgba2[1][j] = value2[1].f[j];
> +         rgba2[2][j] = value2[2].f[j];
> +         rgba2[3][j] = value2[3].f[j];
> +      }
> +   }
> +
> +   mach->Image->op(mach->Image, &params, inst->Instruction.Opcode,
> +                   r[0].i, r[1].i, r[2].i, sample_r.i,
> +                   rgba, rgba2);
> +
> +   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> +      r[0].f[j] = rgba[0][j];
> +      r[1].f[j] = rgba[1][j];
> +      r[2].f[j] = rgba[2][j];
> +      r[3].f[j] = rgba[3][j];
> +   }
> +   for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
> +      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
> +         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
> +      }
> +   }
> +}
>
>   static void
>   micro_i2f(union tgsi_exec_channel *dst,
> @@ -5172,6 +5374,31 @@ exec_instruction(
>      case TGSI_OPCODE_D2U:
>         exec_d2u(mach, inst);
>         break;
> +
> +   case TGSI_OPCODE_LOAD:
> +      exec_load(mach, inst);
> +      break;
> +
> +   case TGSI_OPCODE_STORE:
> +      exec_store(mach, inst);
> +      break;
> +
> +   case TGSI_OPCODE_ATOMUADD:
> +   case TGSI_OPCODE_ATOMXCHG:
> +   case TGSI_OPCODE_ATOMCAS:
> +   case TGSI_OPCODE_ATOMAND:
> +   case TGSI_OPCODE_ATOMOR:
> +   case TGSI_OPCODE_ATOMXOR:
> +   case TGSI_OPCODE_ATOMUMIN:
> +   case TGSI_OPCODE_ATOMUMAX:
> +   case TGSI_OPCODE_ATOMIMIN:
> +   case TGSI_OPCODE_ATOMIMAX:
> +      exec_atomop(mach, inst);
> +      break;
> +
> +   case TGSI_OPCODE_BARRIER:
> +   case TGSI_OPCODE_MEMBAR:
> +      break;
>      default:
>         assert( 0 );
>      }
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
> index 05ae388..9ff8a72 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
> +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
> @@ -98,6 +98,42 @@ enum tgsi_sampler_control
>      TGSI_SAMPLER_GATHER,
>   };
>
> +struct tgsi_image_params {
> +   unsigned unit;
> +   unsigned tgsi_tex_instr;
> +   enum pipe_format format;
> +   unsigned execmask;
> +};
> +
> +struct tgsi_image {
> +   /* image interfaces */
> +   void (*load)(struct tgsi_image *image,
> +                struct tgsi_image_params *params,
> +                const int s[TGSI_QUAD_SIZE],
> +                const int t[TGSI_QUAD_SIZE],
> +                const int r[TGSI_QUAD_SIZE],
> +                const int sample[TGSI_QUAD_SIZE],
> +                float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
> +
> +   void (*store)(struct tgsi_image *image,
> +                 struct tgsi_image_params *params,
> +                 const int s[TGSI_QUAD_SIZE],
> +                 const int t[TGSI_QUAD_SIZE],
> +                 const int r[TGSI_QUAD_SIZE],
> +                 const int sample[TGSI_QUAD_SIZE],
> +                 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
> +
> +   void (*op)(struct tgsi_image *image,
> +              struct tgsi_image_params *params,
> +              unsigned opcode,
> +              const int s[TGSI_QUAD_SIZE],
> +              const int t[TGSI_QUAD_SIZE],
> +              const int r[TGSI_QUAD_SIZE],
> +              const int sample[TGSI_QUAD_SIZE],
> +              float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
> +              float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
> +};
> +
>   /**
>    * Information for sampling textures, which must be implemented
>    * by code outside the TGSI executor.
> @@ -298,6 +334,7 @@ struct tgsi_exec_machine
>
>      struct tgsi_sampler           *Sampler;
>
> +   struct tgsi_image             *Image;
>      unsigned                      ImmLimit;
>
>      const void *Consts[PIPE_MAX_CONSTANT_BUFFERS];
> @@ -386,7 +423,8 @@ void
>   tgsi_exec_machine_bind_shader(
>      struct tgsi_exec_machine *mach,
>      const struct tgsi_token *tokens,
> -   struct tgsi_sampler *sampler);
> +   struct tgsi_sampler *sampler,
> +   struct tgsi_image *image);
>
>   uint
>   tgsi_exec_machine_run(
> diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c
> index e2d527d..2c5bf7e 100644
> --- a/src/gallium/drivers/softpipe/sp_fs_exec.c
> +++ b/src/gallium/drivers/softpipe/sp_fs_exec.c
> @@ -69,7 +69,7 @@ exec_prepare( const struct sp_fragment_shader_variant *var,
>       */
>      tgsi_exec_machine_bind_shader(machine,
>                                    var->tokens,
> -                                 sampler);
> +                                 sampler, NULL);
>   }
>
>
> @@ -184,7 +184,7 @@ exec_delete(struct sp_fragment_shader_variant *var,
>               struct tgsi_exec_machine *machine)
>   {
>      if (machine->Tokens == var->tokens) {
> -      tgsi_exec_machine_bind_shader(machine, NULL, NULL);
> +      tgsi_exec_machine_bind_shader(machine, NULL, NULL, NULL);
>      }
>
>      FREE( (void *) var->tokens );
>



More information about the mesa-dev mailing list