[Mesa-dev] [RFC PATCH 1/2] nv50: Add separate functions for varying bits

Juan A. Suarez Romero jasuarez at igalia.com
Fri Mar 20 09:19:09 UTC 2020


On Thu, 2020-03-19 at 21:20 +0100, Mark Menzynski wrote:
> This separation will be needed for shader disk caching. The reason for it
> is that when loading shaders from cache, data in info structure already gets
> loaded. That means varying bits for info is needed only when compiling
> shaders and not needed when loading from cache. Varying bits for prog are
> needed in both cases.
> 
> Unfortunately, I don't know how most of the code works, I have separated
> this manually, only by looking at the original code. That means that this
> patch is experimental. Together with following commit it works
> (there seem to be no regressions at all in VK-GL-CTS
> [openglcts/data/mustpass/gl/khronos_mustpass/4.6.1.x/gl33-master.txt]
> and all benchmarks behaved normally). Unfortunately, I cannot test in
> Piglit because of technical problems, so there might be still some
> work needed.
> 
> I am mainly asking to help with the function names,
> look for bugs and pointing out useless code. I will be glad for every
> review.
> 
> Signed-off-by: Mark Menzynski <mmenzyns at redhat.com>


Could you submit the patch through GitLab?

Instructions at https://www.mesa3d.org/submittingpatches.html#submit


	J.A.



> ---
>  .../drivers/nouveau/nv50/nv50_program.c       | 344 ++++++++++++++++++
>  1 file changed, 344 insertions(+)
> 
> diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c
> index a3f3054cbaa..bf63b20f613 100644
> --- a/src/gallium/drivers/nouveau/nv50/nv50_program.c
> +++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c
> @@ -139,6 +139,130 @@ nv50_vertprog_assign_slots(struct nv50_ir_prog_info_out *info)
>     return 0;
>  }
>  
> +static int
> +nv50_vertprog_assign_slots_info(struct nv50_ir_prog_info_out *info)
> +{
> +   unsigned i, n, c;
> +
> +   n = 0;
> +   for (i = 0; i < info->numInputs; ++i) {
> +       for (c = 0; c < 4; ++c)
> +         if (info->in[i].mask & (1 << c))
> +            info->in[i].slot[c] = n++;
> +   }
> +
> +   /* VertexID before InstanceID */
> +   if (info->io.vertexId < info->numSysVals)
> +      info->sv[info->io.vertexId].slot[0] = n++;
> +   if (info->io.instanceId < info->numSysVals)
> +      info->sv[info->io.instanceId].slot[0] = n++;
> +
> +   n = 0;
> +   for (i = 0; i < info->numOutputs; ++i) {
> +      for (c = 0; c < 4; ++c)
> +         if (info->out[i].mask & (1 << c))
> +            info->out[i].slot[c] = n++;
> +   }
> +
> +   return 0;
> +}
> +
> +static int
> +nv50_vertprog_assign_slots_prog(struct nv50_ir_prog_info_out *info)
> +{
> +   struct nv50_program *prog = (struct nv50_program *)info->driverPriv;
> +   unsigned i, n, c;
> +
> +   n = 0;
> +   for (i = 0; i < info->numInputs; ++i) {
> +      prog->in[i].id = i;
> +      prog->in[i].sn = info->in[i].sn;
> +      prog->in[i].si = info->in[i].si;
> +      prog->in[i].hw = n;
> +      prog->in[i].mask = info->in[i].mask;
> +
> +      prog->vp.attrs[(4 * i) / 32] |= info->in[i].mask << ((4 * i) % 32);
> +
> +      for (c = 0; c < 4; ++c)
> +         if (info->in[i].mask & (1 << c))
> +            n++;
> +
> +      if (info->in[i].sn == TGSI_SEMANTIC_PRIMID)
> +         prog->vp.attrs[2] |= NV50_3D_VP_GP_BUILTIN_ATTR_EN_PRIMITIVE_ID;
> +   }
> +   prog->in_nr = info->numInputs;
> +
> +   for (i = 0; i < info->numSysVals; ++i) {
> +      switch (info->sv[i].sn) {
> +      case TGSI_SEMANTIC_INSTANCEID:
> +         prog->vp.attrs[2] |= NV50_3D_VP_GP_BUILTIN_ATTR_EN_INSTANCE_ID;
> +         continue;
> +      case TGSI_SEMANTIC_VERTEXID:
> +         prog->vp.attrs[2] |= NV50_3D_VP_GP_BUILTIN_ATTR_EN_VERTEX_ID;
> +         prog->vp.attrs[2] |= NV50_3D_VP_GP_BUILTIN_ATTR_EN_VERTEX_ID_DRAW_ARRAYS_ADD_START;
> +         continue;
> +      default:
> +         break;
> +      }
> +   }
> +
> +   /*
> +    * Corner case: VP has no inputs, but we will still need to submit data to
> +    * draw it. HW will shout at us and won't draw anything if we don't enable
> +    * any input, so let's just pretend it's the first one.
> +    */
> +   if (prog->vp.attrs[0] == 0 &&
> +       prog->vp.attrs[1] == 0 &&
> +       prog->vp.attrs[2] == 0)
> +      prog->vp.attrs[0] |= 0xf;
> +
> +   n = 0;
> +   for (i = 0; i < info->numOutputs; ++i) {
> +      switch (info->out[i].sn) {
> +      case TGSI_SEMANTIC_PSIZE:
> +         prog->vp.psiz = i;
> +         break;
> +      case TGSI_SEMANTIC_CLIPDIST:
> +         prog->vp.clpd[info->out[i].si] = n;
> +         break;
> +      case TGSI_SEMANTIC_EDGEFLAG:
> +         prog->vp.edgeflag = i;
> +         break;
> +      case TGSI_SEMANTIC_BCOLOR:
> +         prog->vp.bfc[info->out[i].si] = i;
> +         break;
> +      case TGSI_SEMANTIC_LAYER:
> +         prog->gp.has_layer = true;
> +         prog->gp.layerid = n;
> +         break;
> +      case TGSI_SEMANTIC_VIEWPORT_INDEX:
> +         prog->gp.has_viewport = true;
> +         prog->gp.viewportid = n;
> +         break;
> +      default:
> +         break;
> +      }
> +      prog->out[i].id = i;
> +      prog->out[i].sn = info->out[i].sn;
> +      prog->out[i].si = info->out[i].si;
> +      prog->out[i].hw = n;
> +      prog->out[i].mask = info->out[i].mask;
> +
> +      for (c = 0; c < 4; ++c)
> +         if (info->out[i].mask & (1 << c))
> +            n++;
> +   }
> +   prog->out_nr = info->numOutputs;
> +   prog->max_out = n;
> +   if (!prog->max_out)
> +      prog->max_out = 1;
> +
> +   if (prog->vp.psiz < info->numOutputs)
> +      prog->vp.psiz = prog->out[prog->vp.psiz].hw;
> +
> +   return 0;
> +}
> +
>  static int
>  nv50_fragprog_assign_slots(struct nv50_ir_prog_info_out *info)
>  {
> @@ -248,6 +372,192 @@ nv50_fragprog_assign_slots(struct nv50_ir_prog_info_out *info)
>     return 0;
>  }
>  
> +static int
> +nv50_fragprog_assign_slots_info(struct nv50_ir_prog_info_out *info)
> +{
> +   struct nv50_program *prog = (struct nv50_program *)info->driverPriv;
> +   unsigned i, n, m, c;
> +   unsigned nintp = 0;
> +
> +   // TODO Can't they just all be zero?
> +   ubyte prog_max_out = prog->max_out;
> +   ubyte prog_in_nr = prog->in_nr;
> +   uint32_t prog_interp = prog->fp.interp;
> +
> +   unsigned prog_in_mask[16];
> +   for (i = 0; i < 16; i++)
> +      prog_in_mask[i] = prog->in[i].mask;
> +
> +   uint8_t prog_in_id[16];
> +   for (i = 0; i < 16; i++)
> +      prog_in_id[i] = prog->in[i].id;
> +
> +
> +   /* count recorded non-flat inputs */
> +   for (m = 0, i = 0; i < info->numInputs; ++i) {
> +      switch (info->in[i].sn) {
> +      case TGSI_SEMANTIC_POSITION:
> +         continue;
> +      default:
> +         m += info->in[i].flat ? 0 : 1;
> +         break;
> +      }
> +   }
> +
> +   /* careful: id may be != i in info->in[prog->in[i].id] */
> +
> +   /* Fill prog->in[] so that non-flat inputs are first and
> +    * kick out special inputs that don't use the RESULT_MAP.
> +    */
> +   for (n = 0, i = 0; i < info->numInputs; ++i) {
> +      if (info->in[i].sn == TGSI_SEMANTIC_POSITION) {
> +         prog_interp |= info->in[i].mask << 24;
> +         for (c = 0; c < 4; ++c)
> +            if (info->in[i].mask & (1 << c))
> +               info->in[i].slot[c] = nintp++;
> +      } else {
> +         unsigned j = info->in[i].flat ? m++ : n++;
> +         prog_in_id[j] = i;
> +         prog_in_mask[j] = info->in[i].mask;
> +         prog_in_nr++;
> +      }
> +   }
> +   if (!(prog_interp & (8 << 24)))
> +      ++nintp;
> +
> +   for (i = 0; i < prog_in_nr; ++i) {
> +      int j = prog_in_id[i];
> +
> +      for (c = 0; c < 4; ++c)
> +         if (prog_in_mask[i] & (1 << c))
> +            info->in[j].slot[c] = nintp++;
> +   }
> +
> +   /* FP outputs */
> +
> +   for (i = 0; i < info->numOutputs; ++i) {
> +       if (i == info->io.fragDepth || i == info->io.sampleMask)
> +         continue;
> +
> +      for (c = 0; c < 4; ++c)
> +         info->out[i].slot[c] = info->out[i].si * 4 + c;
> +
> +      prog_max_out = MAX2(prog_max_out, info->out[i].si * 4 + 4);
> +   }
> +
> +   if (info->io.sampleMask < PIPE_MAX_SHADER_OUTPUTS)
> +      info->out[info->io.sampleMask].slot[0] = prog_max_out++;
> +
> +   if (info->io.fragDepth < PIPE_MAX_SHADER_OUTPUTS)
> +      info->out[info->io.fragDepth].slot[2] = prog_max_out;
> +
> +   return 0;
> +}
> +
> +static int
> +nv50_fragprog_assign_slots_prog(struct nv50_ir_prog_info_out *info)
> +{
> +   struct nv50_program *prog = (struct nv50_program *)info->driverPriv;
> +   unsigned i, n, m, c;
> +   unsigned nvary;
> +   unsigned nflat;
> +   unsigned nintp = 0;
> +
> +   /* count recorded non-flat inputs */
> +   for (m = 0, i = 0; i < info->numInputs; ++i) {
> +      switch (info->in[i].sn) {
> +      case TGSI_SEMANTIC_POSITION:
> +         continue;
> +      default:
> +         m += info->in[i].flat ? 0 : 1;
> +         break;
> +      }
> +   }
> +   /* careful: id may be != i in info->in[prog->in[i].id] */
> +
> +   /* Fill prog->in[] so that non-flat inputs are first and
> +    * kick out special inputs that don't use the RESULT_MAP.
> +    */
> +   for (n = 0, i = 0; i < info->numInputs; ++i) {
> +      if (info->in[i].sn == TGSI_SEMANTIC_POSITION) {
> +         prog->fp.interp |= info->in[i].mask << 24;
> +         for (c = 0; c < 4; ++c)
> +            if (info->in[i].mask & (1 << c))
> +               nintp++;
> +      } else {
> +         unsigned j = info->in[i].flat ? m++ : n++;
> +
> +         if (info->in[i].sn == TGSI_SEMANTIC_COLOR)
> +            prog->vp.bfc[info->in[i].si] = j;
> +         else if (info->in[i].sn == TGSI_SEMANTIC_PRIMID)
> +            prog->vp.attrs[2] |= NV50_3D_VP_GP_BUILTIN_ATTR_EN_PRIMITIVE_ID;
> +
> +         prog->in[j].id = i;
> +         prog->in[j].mask = info->in[i].mask;
> +         prog->in[j].sn = info->in[i].sn;
> +         prog->in[j].si = info->in[i].si;
> +         prog->in[j].linear = info->in[i].linear;
> +
> +         prog->in_nr++;
> +      }
> +   }
> +   if (!(prog->fp.interp & (8 << 24))) {
> +      ++nintp;
> +      prog->fp.interp |= 8 << 24;
> +   }
> +
> +   for (i = 0; i < prog->in_nr; ++i) {
> +      prog->in[i].hw = nintp;
> +      for (c = 0; c < 4; ++c)
> +         if (prog->in[i].mask & (1 << c))
> +            nintp++;
> +   }
> +   /* (n == m) if m never increased, i.e. no flat inputs */
> +   nflat = (n < m) ? (nintp - prog->in[n].hw) : 0;
> +   nintp -= bitcount4(prog->fp.interp >> 24); /* subtract position inputs */
> +   nvary = nintp - nflat;
> +
> +   prog->fp.interp |= nvary << NV50_3D_FP_INTERPOLANT_CTRL_COUNT_NONFLAT__SHIFT;
> +   prog->fp.interp |= nintp << NV50_3D_FP_INTERPOLANT_CTRL_COUNT__SHIFT;
> +
> +   /* put front/back colors right after HPOS */
> +   prog->fp.colors = 4 << NV50_3D_SEMANTIC_COLOR_FFC0_ID__SHIFT;
> +   for (i = 0; i < 2; ++i)
> +      if (prog->vp.bfc[i] < 0xff)
> +         prog->fp.colors += bitcount4(prog->in[prog->vp.bfc[i]].mask) << 16;
> +
> +   /* FP outputs */
> +
> +   if (info->prop.fp.numColourResults > 1)
> +      prog->fp.flags[0] |= NV50_3D_FP_CONTROL_MULTIPLE_RESULTS;
> +
> +   for (i = 0; i < info->numOutputs; ++i) {
> +      prog->out[i].id = i;
> +      prog->out[i].sn = info->out[i].sn;
> +      prog->out[i].si = info->out[i].si;
> +      prog->out[i].mask = info->out[i].mask;
> +
> +      if (i == info->io.fragDepth || i == info->io.sampleMask)
> +         continue;
> +      prog->out[i].hw = info->out[i].si * 4;
> +
> +      prog->max_out = MAX2(prog->max_out, prog->out[i].hw + 4);
> +   }
> +
> +   if (info->io.sampleMask < PIPE_MAX_SHADER_OUTPUTS) {
> +      prog->max_out++;
> +      prog->fp.has_samplemask = 1;
> +   }
> +
> +   if (info->io.fragDepth < PIPE_MAX_SHADER_OUTPUTS)
> +      prog->max_out++;
> +
> +   if (!prog->max_out)
> +      prog->max_out = 4;
> +
> +   return 0;
> +}
> +
>  static int
>  nv50_program_assign_varying_slots(struct nv50_ir_prog_info_out *info)
>  {
> @@ -265,6 +575,40 @@ nv50_program_assign_varying_slots(struct nv50_ir_prog_info_out *info)
>     }
>  }
>  
> +static int
> +nv50_program_assign_varying_slots_info(struct nv50_ir_prog_info_out *info)
> +{
> +   switch (info->type) {
> +   case PIPE_SHADER_VERTEX:
> +      return nv50_vertprog_assign_slots_info(info);
> +   case PIPE_SHADER_GEOMETRY:
> +      return nv50_vertprog_assign_slots_info(info);
> +   case PIPE_SHADER_FRAGMENT:
> +      return nv50_fragprog_assign_slots_info(info);
> +   case PIPE_SHADER_COMPUTE:
> +      return 0;
> +   default:
> +      return -1;
> +   }
> +}
> +
> +static int
> +nv50_program_assign_varying_slots_prog(struct nv50_ir_prog_info_out *info)
> +{
> +   switch (info->type) {
> +   case PIPE_SHADER_VERTEX:
> +      return nv50_vertprog_assign_slots_prog(info);
> +   case PIPE_SHADER_GEOMETRY:
> +      return nv50_vertprog_assign_slots_prog(info);
> +   case PIPE_SHADER_FRAGMENT:
> +      return nv50_fragprog_assign_slots_prog(info);
> +   case PIPE_SHADER_COMPUTE:
> +      return 0;
> +   default:
> +      return -1;
> +   }
> +}
> +
>  static struct nv50_stream_output_state *
>  nv50_program_create_strmout_state(const struct nv50_ir_prog_info_out *info,
>                                    const struct pipe_stream_output_info *pso)



More information about the mesa-dev mailing list