[Mesa-dev] [PATCH 3/8] nv50/ir: Add nv50_ir_prog_info_out serialize and deserialize

Karol Herbst kherbst at redhat.com
Mon Feb 17 19:56:52 UTC 2020


On Mon, Feb 17, 2020 at 6:41 PM Mark Menzynski <mmenzyns at redhat.com> wrote:
>
> Adds functions for serializing and deserializing
> nv50_ir_prog_info_out structure, which are needed for shader caching.
>
> Signed-off-by: Mark Menzynski <mmenzyns at redhat.com>
> ---
>  .../drivers/nouveau/codegen/nv50_ir_driver.h  |  44 ++++
>  .../nouveau/codegen/nv50_ir_emit_gk110.cpp    |  14 +-
>  .../nouveau/codegen/nv50_ir_emit_gm107.cpp    |  14 +-
>  .../nouveau/codegen/nv50_ir_emit_nv50.cpp     |   6 +-
>  .../nouveau/codegen/nv50_ir_emit_nvc0.cpp     |  14 +-
>  .../nouveau/codegen/nv50_ir_serialize.cpp     | 196 ++++++++++++++++++
>  src/gallium/drivers/nouveau/meson.build       |   1 +
>  7 files changed, 265 insertions(+), 24 deletions(-)
>  create mode 100644 src/gallium/drivers/nouveau/codegen/nv50_ir_serialize.cpp
>
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
> index f6b5415bc95..bc92a3bc4ee 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
> @@ -25,6 +25,7 @@
>
>  #include "pipe/p_shader_tokens.h"
>
> +#include "util/blob.h"
>  #include "tgsi/tgsi_util.h"
>  #include "tgsi/tgsi_parse.h"
>  #include "tgsi/tgsi_scan.h"
> @@ -242,6 +243,49 @@ nv50_ir_apply_fixups(void *fixupData, uint32_t *code,
>  extern void nv50_ir_get_target_library(uint32_t chipset,
>                                         const uint32_t **code, uint32_t *size);
>
> +
> +#ifdef __cplusplus
> +namespace nv50_ir
> +{
> +   class FixupEntry;
> +   class FixupData;
> +
> +   void
> +   gk110_interpApply(const nv50_ir::FixupEntry *entry, uint32_t *code,
> +                     const nv50_ir::FixupData& data);
> +   void
> +   gm107_interpApply(const nv50_ir::FixupEntry *entry, uint32_t *code,
> +                     const nv50_ir::FixupData& data);
> +   void
> +   nv50_interpApply(const nv50_ir::FixupEntry *entry, uint32_t *code,
> +                    const nv50_ir::FixupData& data);
> +   void
> +   nvc0_interpApply(const nv50_ir::FixupEntry *entry, uint32_t *code,
> +                    const nv50_ir::FixupData& data);
> +   void
> +   gk110_selpFlip(const nv50_ir::FixupEntry *entry, uint32_t *code,
> +                  const nv50_ir::FixupData& data);
> +   void
> +   gm107_selpFlip(const nv50_ir::FixupEntry *entry, uint32_t *code,
> +                  const nv50_ir::FixupData& data);
> +   void
> +   nvc0_selpFlip(const nv50_ir::FixupEntry *entry, uint32_t *code,
> +                 const nv50_ir::FixupData& data);
> +
> +}
> +#endif
> +
> +/* Serialize a nv50_ir_prog_info_out structure and save it into blob */
> +extern bool
> +nv50_ir_prog_info_out_serialize(struct blob *, struct nv50_ir_prog_info_out *);
> +
> +/* Deserialize from data and save into a nv50_ir_prog_info_out structure
> + * using a pointer. Size is a total size of the serialized data.
> + * Offset points to where info_out in data is located. */
> +extern bool
> +nv50_ir_prog_info_out_deserialize(void *data, size_t size, size_t offset,
> +                             struct nv50_ir_prog_info_out *);

some spaces missing. Also I'd drop the offset argument and require the
callee to pass in an adjusted pointer already.

> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
> index 2118c3153f7..e651d7fdcb0 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
> @@ -1209,8 +1209,8 @@ CodeEmitterGK110::emitSLCT(const CmpInstruction *i)
>     }
>  }
>
> -static void
> -selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
> +void
> +gk110_selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
>  {
>     int loc = entry->loc;
>     if (data.force_persample_interp)
> @@ -1227,7 +1227,7 @@ void CodeEmitterGK110::emitSELP(const Instruction *i)
>        code[1] |= 1 << 13;
>
>     if (i->subOp == 1) {
> -      addInterp(0, 0, selpFlip);
> +      addInterp(0, 0, gk110_selpFlip);
>     }
>  }
>
> @@ -2042,8 +2042,8 @@ CodeEmitterGK110::emitInterpMode(const Instruction *i)
>     code[1] |= (i->ipa & 0xc) << (19 - 2);
>  }
>
> -static void
> -interpApply(const FixupEntry *entry, uint32_t *code, const FixupData& data)
> +void
> +gk110_interpApply(const struct FixupEntry *entry, uint32_t *code, const FixupData& data)
>  {
>     int ipa = entry->ipa;
>     int reg = entry->reg;
> @@ -2078,10 +2078,10 @@ CodeEmitterGK110::emitINTERP(const Instruction *i)
>
>     if (i->op == OP_PINTERP) {
>        srcId(i->src(1), 23);
> -      addInterp(i->ipa, SDATA(i->src(1)).id, interpApply);
> +      addInterp(i->ipa, SDATA(i->src(1)).id, gk110_interpApply);
>     } else {
>        code[0] |= 0xff << 23;
> -      addInterp(i->ipa, 0xff, interpApply);
> +      addInterp(i->ipa, 0xff, gk110_interpApply);
>     }
>
>     srcId(i->src(0).getIndirect(0), 10);
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
> index e244bd0d610..4970f14cb33 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
> @@ -947,8 +947,8 @@ CodeEmitterGM107::emitI2I()
>     emitGPR  (0x00, insn->def(0));
>  }
>
> -static void
> -selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
> +void
> +gm107_selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
>  {
>     int loc = entry->loc;
>     if (data.force_persample_interp)
> @@ -984,7 +984,7 @@ CodeEmitterGM107::emitSEL()
>     emitGPR (0x00, insn->def(0));
>
>     if (insn->subOp == 1) {
> -      addInterp(0, 0, selpFlip);
> +      addInterp(0, 0, gm107_selpFlip);
>     }
>  }
>
> @@ -2527,8 +2527,8 @@ CodeEmitterGM107::emitAL2P()
>     emitGPR  (0x00, insn->def(0));
>  }
>
> -static void
> -interpApply(const FixupEntry *entry, uint32_t *code, const FixupData& data)
> +void
> +gm107_interpApply(const FixupEntry *entry, uint32_t *code, const FixupData& data)
>  {
>     int ipa = entry->ipa;
>     int reg = entry->reg;
> @@ -2588,12 +2588,12 @@ CodeEmitterGM107::emitIPA()
>        emitGPR(0x14, insn->src(1));
>        if (insn->getSampleMode() == NV50_IR_INTERP_OFFSET)
>           emitGPR(0x27, insn->src(2));
> -      addInterp(insn->ipa, insn->getSrc(1)->reg.data.id, interpApply);
> +      addInterp(insn->ipa, insn->getSrc(1)->reg.data.id, gm107_interpApply);
>     } else {
>        if (insn->getSampleMode() == NV50_IR_INTERP_OFFSET)
>           emitGPR(0x27, insn->src(1));
>        emitGPR(0x14);
> -      addInterp(insn->ipa, 0xff, interpApply);
> +      addInterp(insn->ipa, 0xff, gm107_interpApply);
>     }
>
>     if (insn->getSampleMode() != NV50_IR_INTERP_OFFSET)
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp
> index 03fada1415e..60e800ad502 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp
> @@ -881,8 +881,8 @@ CodeEmitterNV50::emitPFETCH(const Instruction *i)
>     emitFlagsRd(i);
>  }
>
> -static void
> -interpApply(const FixupEntry *entry, uint32_t *code, const FixupData& data)
> +void
> +nv50_interpApply(const FixupEntry *entry, uint32_t *code, const FixupData& data)
>  {
>     int ipa = entry->ipa;
>     int encSize = entry->reg;
> @@ -934,7 +934,7 @@ CodeEmitterNV50::emitINTERP(const Instruction *i)
>        emitFlagsRd(i);
>     }
>
> -   addInterp(i->ipa, i->encSize, interpApply);
> +   addInterp(i->ipa, i->encSize, nv50_interpApply);
>  }
>
>  void
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
> index b6e35dd0ee4..0a82c6de20d 100644
> --- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
> @@ -1255,8 +1255,8 @@ CodeEmitterNVC0::emitSLCT(const CmpInstruction *i)
>        code[0] |= 1 << 5;
>  }
>
> -static void
> -selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
> +void
> +nvc0_selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
>  {
>     int loc = entry->loc;
>     if (data.force_persample_interp)
> @@ -1273,7 +1273,7 @@ void CodeEmitterNVC0::emitSELP(const Instruction *i)
>        code[1] |= 1 << 20;
>
>     if (i->subOp == 1) {
> -      addInterp(0, 0, selpFlip);
> +      addInterp(0, 0, nvc0_selpFlip);
>     }
>  }
>
> @@ -1726,8 +1726,8 @@ CodeEmitterNVC0::emitInterpMode(const Instruction *i)
>     }
>  }
>
> -static void
> -interpApply(const FixupEntry *entry, uint32_t *code, const FixupData& data)
> +void
> +nvc0_interpApply(const FixupEntry *entry, uint32_t *code, const FixupData& data)
>  {
>     int ipa = entry->ipa;
>     int reg = entry->reg;
> @@ -1762,10 +1762,10 @@ CodeEmitterNVC0::emitINTERP(const Instruction *i)
>
>        if (i->op == OP_PINTERP) {
>           srcId(i->src(1), 26);
> -         addInterp(i->ipa, SDATA(i->src(1)).id, interpApply);
> +         addInterp(i->ipa, SDATA(i->src(1)).id, nvc0_interpApply);
>        } else {
>           code[0] |= 0x3f << 26;
> -         addInterp(i->ipa, 0x3f, interpApply);
> +         addInterp(i->ipa, 0x3f, nvc0_interpApply);
>        }
>
>        srcId(i->src(0).getIndirect(0), 20);
> diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_serialize.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_serialize.cpp
> new file mode 100644
> index 00000000000..077f3eba6c8
> --- /dev/null
> +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_serialize.cpp
> @@ -0,0 +1,196 @@
> +#include "util/blob.h"
> +#include "codegen/nv50_ir_driver.h"
> +#include "codegen/nv50_ir.h"
> +#include "codegen/nv50_ir_target.h"
> +#include "nv50_ir_driver.h"
> +#include "tgsi/tgsi_parse.h"
> +#include "compiler/nir/nir_serialize.h"
> +
> +enum InterpApply {

maybe call it FixupFuncPointer or something instead?

> +   APPLY_UNDEFINED = 0,
> +   APPLY_NV50 = 1,
> +   APPLY_NVC0 = 2,
> +   APPLY_GK110 = 3,
> +   APPLY_GM107 = 4,
> +   FLIP_NVC0 = 5,
> +   FLIP_GK110 = 6,
> +   FLIP_GM107 = 7
> +};
> +
> +extern bool
> +nv50_ir_prog_info_out_serialize(struct blob *blob,
> +                           struct nv50_ir_prog_info_out *info_out)

more spaces

> +{
> +   blob_write_uint16(blob, info_out->target);
> +   blob_write_uint8(blob, info_out->type);
> +
> +   blob_write_uint16(blob, info_out->bin.maxGPR);
> +   blob_write_uint32(blob, info_out->bin.tlsSpace);
> +   blob_write_uint32(blob, info_out->bin.smemSize);
> +   blob_write_uint32(blob, info_out->bin.codeSize);
> +   blob_write_bytes(blob, info_out->bin.code, info_out->bin.codeSize);
> +   blob_write_uint32(blob, info_out->bin.instructions);
> +
> +   /* Writing byte suggesting if RelocInfo is contained */
> +   blob_write_uint8(blob, info_out->bin.relocData != NULL);
> +   if (info_out->bin.relocData) {
> +      nv50_ir::RelocInfo *reloc = (nv50_ir::RelocInfo *)info_out->bin.relocData;
> +      blob_write_uint32(blob, reloc->count);
> +      blob_write_uint32(blob, reloc->codePos);
> +      blob_write_uint32(blob, reloc->libPos);
> +      blob_write_uint32(blob, reloc->dataPos);
> +      blob_write_bytes(blob, reloc->entry, sizeof(*reloc->entry) * reloc->count);
> +   }
> +
> +   /* Writing byte suggesting FixupInfo is contained */
> +   blob_write_uint8(blob, info_out->bin.fixupData != NULL);
> +   if (info_out->bin.fixupData) {
> +      nv50_ir::FixupInfo *fixup = (nv50_ir::FixupInfo *)info_out->bin.fixupData;
> +      blob_write_uint32(blob, fixup->count);
> +
> +      /* Going through each entry */
> +      for (uint32_t i = 0; i < fixup->count; i++) {
> +         blob_write_uint32(blob, fixup->entry[i].ipa);
> +         blob_write_uint32(blob, fixup->entry[i].reg);
> +         blob_write_uint32(blob, fixup->entry[i].loc);
> +
> +         /* Compare function pointers, for when at serializing
> +          * to know which function to apply */
> +         if (fixup->entry[i].apply == NULL)
> +            blob_write_uint8(blob, APPLY_UNDEFINED);
> +         else if (fixup->entry[i].apply == nv50_ir::nv50_interpApply)
> +            blob_write_uint8(blob, APPLY_NV50);
> +         else if (fixup->entry[i].apply == nv50_ir::nvc0_interpApply)
> +            blob_write_uint8(blob, APPLY_NVC0);
> +         else if (fixup->entry[i].apply == nv50_ir::gk110_interpApply)
> +            blob_write_uint8(blob, APPLY_GK110);
> +         else if (fixup->entry[i].apply == nv50_ir::gm107_interpApply)
> +            blob_write_uint8(blob, APPLY_GM107);
> +         else if (fixup->entry[i].apply == nv50_ir::nvc0_selpFlip)
> +            blob_write_uint8(blob, FLIP_NVC0);
> +         else if (fixup->entry[i].apply == nv50_ir::gk110_selpFlip)
> +            blob_write_uint8(blob, FLIP_GK110);
> +         else if (fixup->entry[i].apply == nv50_ir::gm107_selpFlip)
> +            blob_write_uint8(blob, FLIP_GM107);
> +         else {
> +            blob_write_uint8(blob, APPLY_UNDEFINED);
> +            assert(!"unhandled fixup apply function pointer");
> +            return false;
> +         }
> +      }
> +   }
> +
> +   blob_write_bytes(blob, info_out->sv, sizeof(info_out->sv));
> +   blob_write_bytes(blob, info_out->in, sizeof(info_out->in));
> +   blob_write_bytes(blob, info_out->out, sizeof(info_out->out));
> +
> +   blob_write_uint8(blob, info_out->numInputs);
> +   blob_write_uint8(blob, info_out->numOutputs);
> +   blob_write_uint8(blob, info_out->numPatchConstants);
> +   blob_write_uint8(blob, info_out->numSysVals);
> +   blob_write_bytes(blob, &(info_out->prop), sizeof(info_out->prop));
> +   blob_write_bytes(blob, &(info_out->io), sizeof(info_out->io));

you can drop the brackets around prop and io.

> +   blob_write_uint8(blob, info_out->numBarriers);
> +
> +   return true;
> +}
> +
> +extern bool
> +nv50_ir_prog_info_out_deserialize(void *data, size_t size, size_t offset,
> +                             struct nv50_ir_prog_info_out *info_out)

missing spaces

> +{
> +   struct blob_reader reader;
> +   blob_reader_init(&reader, data, size);
> +   blob_skip_bytes(&reader, offset);
> +
> +   info_out->target = blob_read_uint16(&reader);
> +   info_out->type = blob_read_uint8(&reader);
> +
> +   info_out->bin.maxGPR = blob_read_uint16(&reader);
> +   info_out->bin.tlsSpace = blob_read_uint32(&reader);
> +   info_out->bin.smemSize = blob_read_uint32(&reader);
> +   info_out->bin.codeSize = blob_read_uint32(&reader);
> +   info_out->bin.code = (uint32_t *)malloc(info_out->bin.codeSize);
> +   blob_copy_bytes(&reader, info_out->bin.code, info_out->bin.codeSize);
> +   info_out->bin.instructions = blob_read_uint32(&reader);
> +
> +   info_out->bin.relocData = NULL;
> +   /*  Check if data contains RelocInfo */
> +   if (blob_read_uint8(&reader) == true) {
> +      uint32_t count = blob_read_uint32(&reader);
> +
> +      nv50_ir::RelocInfo *reloc =
> +                  CALLOC_VARIANT_LENGTH_STRUCT(nv50_ir::RelocInfo,
> +                                               count * sizeof(*reloc->entry));
> +      reloc->codePos = blob_read_uint32(&reader);
> +      reloc->libPos = blob_read_uint32(&reader);
> +      reloc->dataPos = blob_read_uint32(&reader);
> +      reloc->count = count;
> +
> +      blob_copy_bytes(&reader, reloc->entry, sizeof(*reloc->entry) * reloc->count);
> +      info_out->bin.relocData = reloc;
> +   }
> +
> +   info_out->bin.fixupData = NULL;
> +   /* Check if data contains FixupInfo */
> +   if (blob_read_uint8(&reader) == true) {

you can drop the "== true" here and further below

> +      uint32_t count = blob_read_uint32(&reader);
> +
> +      nv50_ir::FixupInfo *fixup =
> +                  CALLOC_VARIANT_LENGTH_STRUCT(nv50_ir::FixupInfo,
> +                                               count * sizeof(*fixup->entry));
> +      fixup->count = count;
> +
> +      for (uint32_t i = 0; i < count; i++) {
> +         fixup->entry[i].ipa = blob_read_uint32(&reader);
> +         fixup->entry[i].reg = blob_read_uint32(&reader);
> +         fixup->entry[i].loc = blob_read_uint32(&reader);
> +
> +         /* Assign back function pointer depending on stored enum */
> +         enum InterpApply apply = (enum InterpApply)blob_read_uint8(&reader);
> +         switch(apply) {
> +            case APPLY_UNDEFINED:
> +               fixup->entry[i].apply = NULL;
> +               break;
> +            case APPLY_NV50:
> +               fixup->entry[i].apply = nv50_ir::nv50_interpApply;
> +               break;
> +            case APPLY_NVC0:
> +               fixup->entry[i].apply = nv50_ir::nvc0_interpApply;
> +               break;
> +            case APPLY_GK110:
> +               fixup->entry[i].apply = nv50_ir::gk110_interpApply;
> +               break;
> +            case APPLY_GM107:
> +               fixup->entry[i].apply = nv50_ir::gm107_interpApply;
> +               break;
> +            case FLIP_NVC0:
> +               fixup->entry[i].apply = nv50_ir::nvc0_selpFlip;
> +               break;
> +            case FLIP_GK110:
> +               fixup->entry[i].apply = nv50_ir::gk110_selpFlip;
> +               break;
> +            case FLIP_GM107:
> +               fixup->entry[i].apply = nv50_ir::gm107_selpFlip;
> +               break;
> +            default:
> +               assert(!"unhandled apply function switch case");
> +               return false;

you don't need to add a default case if all enum values are handled.

> +         }
> +      }
> +      info_out->bin.fixupData = fixup;
> +   }
> +
> +   blob_copy_bytes(&reader, info_out->sv, sizeof(info_out->sv));
> +   blob_copy_bytes(&reader, info_out->in, sizeof(info_out->in));
> +   blob_copy_bytes(&reader, info_out->out, sizeof(info_out->out));
> +   info_out->numInputs = blob_read_uint8(&reader);
> +   info_out->numOutputs = blob_read_uint8(&reader);
> +   info_out->numPatchConstants = blob_read_uint8(&reader);
> +   info_out->numSysVals = blob_read_uint8(&reader);
> +   blob_copy_bytes(&reader, &(info_out->prop), sizeof(info_out->prop));
> +   blob_copy_bytes(&reader, &(info_out->io), sizeof(info_out->io));
> +   info_out->numBarriers = blob_read_uint8(&reader);
> +
> +   return true;
> +}
> diff --git a/src/gallium/drivers/nouveau/meson.build b/src/gallium/drivers/nouveau/meson.build
> index e48b61b8955..21793e86b38 100644
> --- a/src/gallium/drivers/nouveau/meson.build
> +++ b/src/gallium/drivers/nouveau/meson.build
> @@ -142,6 +142,7 @@ files_libnouveau = files(
>    'codegen/nv50_ir_peephole.cpp',
>    'codegen/nv50_ir_print.cpp',
>    'codegen/nv50_ir_ra.cpp',
> +  'codegen/nv50_ir_serialize.cpp',
>    'codegen/nv50_ir_ssa.cpp',
>    'codegen/nv50_ir_target.cpp',
>    'codegen/nv50_ir_target.h',
> --
> 2.21.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>



More information about the mesa-dev mailing list