[Beignet] [V2 PATCH 1/4] Add the serialization support for backend

junyan.he at inbox.com junyan.he at inbox.com
Thu Sep 5 03:48:24 PDT 2013


From: Junyan He <junyan.he at linux.intel.com>

The Serializable class define the interface of serialize_to/deserialize_from
functions for internal binary and llvm binary. And also a print status
function for debugging.
The class which may need the serializaion support need to derive from it,
these classes including: Program, Kernel, ConstantSet, ImageSet and SamplerSet.
This patch just add serialize_to/deserialize_from internal binary support for
all these classes.

Signed-off-by: Junyan He <junyan.he at linux.intel.com>
---
 backend/src/backend/gen_program.cpp |   27 +++
 backend/src/backend/gen_program.hpp |   10 +-
 backend/src/backend/program.cpp     |  315 +++++++++++++++++++++++++++++++++++
 backend/src/backend/program.hpp     |   59 ++++++-
 backend/src/ir/constant.cpp         |   99 +++++++++++
 backend/src/ir/constant.hpp         |   28 +++-
 backend/src/ir/image.cpp            |  139 ++++++++++++++++
 backend/src/ir/image.hpp            |   25 ++-
 backend/src/ir/sampler.cpp          |   98 +++++++++++
 backend/src/ir/sampler.hpp          |   25 ++-
 backend/src/sys/platform.hpp        |   42 +++++
 11 files changed, 859 insertions(+), 8 deletions(-)

diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index 3d7bedd..bdd3441 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -27,12 +27,15 @@
 #include "backend/gen_program.hpp"
 #include "backend/gen_context.hpp"
 #include "backend/gen_defs.hpp"
+#include "backend/gen/gen_mesa_disasm.h"
 #include "backend/gen_reg_allocation.hpp"
 #include "ir/unit.hpp"
 #include "llvm/llvm_to_gen.hpp"
 
 #include <cstring>
 #include <memory>
+#include <iostream>
+#include <fstream>
 
 namespace gbe {
 
@@ -41,8 +44,32 @@ namespace gbe {
   {}
   GenKernel::~GenKernel(void) { GBE_SAFE_DELETE_ARRAY(insns); }
   const char *GenKernel::getCode(void) const { return (const char*) insns; }
+  const void GenKernel::setCode(const char * ins, size_t size) {
+    insns = (GenInstruction *)ins;
+    insnNum = size / sizeof(GenInstruction);
+  }
   size_t GenKernel::getCodeSize(void) const { return insnNum * sizeof(GenInstruction); }
 
+  void GenKernel::printStatus(int indent, std::ostream& outs) {
+    Kernel::printStatus(indent, outs);
+
+    FILE *f = fopen("/dev/null", "w");
+    char *buf = new char[4096];
+    setbuffer(f, buf, 4096);
+
+    for (uint32_t i = 0; i < insnNum; i++) {
+      gen_disasm(f, insns+i);
+      outs << buf;
+      fflush(f);
+      setbuffer(f, NULL, 0);
+      setbuffer(f, buf, 4096);
+    }
+
+    setbuffer(f, NULL, 0);
+    delete [] buf;
+    fclose(f);
+  }
+
   GenProgram::GenProgram(void) {}
   GenProgram::~GenProgram(void) {}
 
diff --git a/backend/src/backend/gen_program.hpp b/backend/src/backend/gen_program.hpp
index 68b0427..f78e324 100644
--- a/backend/src/backend/gen_program.hpp
+++ b/backend/src/backend/gen_program.hpp
@@ -42,8 +42,12 @@ namespace gbe
     virtual ~GenKernel(void);
     /*! Implements base class */
     virtual const char *getCode(void) const;
-    /*! Implements base class */
+    /*! Set the instruction stream (to be implemented) */
+    virtual const void setCode(const char *, size_t size);
+    /*! Implements get the code size */
     virtual size_t getCodeSize(void) const;
+    /*! Implements printStatus*/
+    virtual void printStatus(int indent, std::ostream& outs);
     GenInstruction *insns; //!< Instruction stream
     uint32_t insnNum;      //!< Number of instructions
     GBE_CLASS(GenKernel);  //!< Use custom allocators
@@ -59,6 +63,10 @@ namespace gbe
     virtual ~GenProgram(void);
     /*! Implements base class */
     virtual Kernel *compileKernel(const ir::Unit &unit, const std::string &name);
+    /*! Allocate an empty kernel. */
+    virtual Kernel *allocateKernel(const std::string &name) {
+      return GBE_NEW(GenKernel, name);
+    }
     /*! Use custom allocators */
     GBE_CLASS(GenProgram);
   };
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index 35d3a7c..f487bf6 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -37,6 +37,7 @@
 #include <fstream>
 #include <dlfcn.h>
 #include <sstream>
+#include <iostream>
 #include <unistd.h>
 
 /* Not defined for LLVM 3.0 */
@@ -124,6 +125,320 @@ namespace gbe {
     return true;
   }
 
+#define OUT_UPDATE_SZ(elt) SERIALIZE_OUT(elt, outs, ret_size)
+#define IN_UPDATE_SZ(elt) DESERIALIZE_IN(elt, ins, total_size)
+
+  size_t Program::serializeToBin(std::ostream& outs) {
+    size_t ret_size = 0;
+    size_t ker_num = kernels.size();
+    int has_constset = 0;
+
+    OUT_UPDATE_SZ(magic_begin);
+
+    if (constantSet) {
+      has_constset = 1;
+      OUT_UPDATE_SZ(has_constset);
+      size_t sz = constantSet->serializeToBin(outs);
+      if (!sz)
+        return 0;
+
+      ret_size += sz;
+    } else {
+      OUT_UPDATE_SZ(has_constset);
+    }
+
+    OUT_UPDATE_SZ(ker_num);
+    for (auto ker : kernels) {
+      size_t sz = ker.second->serializeToBin(outs);
+      if (!sz)
+        return 0;
+
+      ret_size += sz;
+    }
+
+    OUT_UPDATE_SZ(magic_end);
+
+    OUT_UPDATE_SZ(ret_size);
+    return ret_size;
+  }
+
+  size_t Program::deserializeFromBin(std::istream& ins) {
+    size_t total_size = 0;
+    int has_constset = 0;
+    size_t ker_num;
+    uint32_t magic;
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_begin)
+      return 0;
+
+    IN_UPDATE_SZ(has_constset);
+    if(has_constset) {
+      constantSet = new ir::ConstantSet;
+      size_t sz = constantSet->deserializeFromBin(ins);
+
+      if (sz == 0) {
+        return 0;
+      }
+
+      total_size += sz;
+    }
+
+    IN_UPDATE_SZ(ker_num);
+
+    for (size_t i = 0; i < ker_num; i++) {
+      size_t ker_serial_sz;
+      std::string ker_name; // Just a empty name here.
+      Kernel* ker = allocateKernel(ker_name);
+
+      if(!(ker_serial_sz = ker->deserializeFromBin(ins)))
+        return 0;
+
+      kernels.insert(std::make_pair(ker->getName(), ker));
+      total_size += ker_serial_sz;
+    }
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_end)
+      return 0;
+
+    size_t total_bytes;
+    IN_UPDATE_SZ(total_bytes);
+    if (total_bytes + sizeof(total_size) != total_size)
+      return 0;
+
+    return total_size;
+  }
+
+  size_t Kernel::serializeToBin(std::ostream& outs) {
+    unsigned int i;
+    size_t ret_size = 0;
+    int has_samplerset = 0;
+    int has_imageset = 0;
+
+    OUT_UPDATE_SZ(magic_begin);
+
+    OUT_UPDATE_SZ(name.size());
+    outs.write(name.c_str(), name.size());
+    ret_size += sizeof(char)*name.size();
+
+    OUT_UPDATE_SZ(argNum);
+    for (i = 0; i < argNum; i++) {
+      KernelArgument& arg = args[i];
+      OUT_UPDATE_SZ(arg.type);
+      OUT_UPDATE_SZ(arg.size);
+      OUT_UPDATE_SZ(arg.bufSize);
+    }
+
+    OUT_UPDATE_SZ(patches.size());
+    for (auto patch : patches) {
+      unsigned int tmp;
+      tmp = patch.type;
+      OUT_UPDATE_SZ(tmp);
+      tmp = patch.subType;
+      OUT_UPDATE_SZ(tmp);
+      tmp = patch.offset;
+      OUT_UPDATE_SZ(tmp);
+    }
+
+    OUT_UPDATE_SZ(curbeSize);
+    OUT_UPDATE_SZ(simdWidth);
+    OUT_UPDATE_SZ(stackSize);
+    OUT_UPDATE_SZ(useSLM);
+
+    /* samplers. */
+    if (samplerSet) {
+      has_samplerset = 1;
+      OUT_UPDATE_SZ(has_samplerset);
+      size_t sz = samplerSet->serializeToBin(outs);
+      if (!sz)
+        return 0;
+
+      ret_size += sz;
+    } else {
+      OUT_UPDATE_SZ(has_samplerset);
+    }
+
+    /* images. */
+    if (imageSet) {
+      has_imageset = 1;
+      OUT_UPDATE_SZ(has_imageset);
+      size_t sz = imageSet->serializeToBin(outs);
+      if (!sz)
+        return 0;
+
+      ret_size += sz;
+    } else {
+      OUT_UPDATE_SZ(has_imageset);
+    }
+
+    /* Code. */
+    const char * code = getCode();
+    OUT_UPDATE_SZ(getCodeSize());
+    outs.write(code, getCodeSize()*sizeof(char));
+    ret_size += getCodeSize()*sizeof(char);
+
+    OUT_UPDATE_SZ(magic_end);
+
+    OUT_UPDATE_SZ(ret_size);
+    return ret_size;
+  }
+
+  size_t Kernel::deserializeFromBin(std::istream& ins) {
+    size_t total_size = 0;
+    int has_samplerset = 0;
+    int has_imageset = 0;
+    size_t code_size = 0;
+    uint32_t magic = 0;
+    size_t patch_num = 0;
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_begin)
+      return 0;
+
+    size_t name_len;
+    IN_UPDATE_SZ(name_len);
+    char* c_name = new char[name_len];
+    ins.read(c_name, name_len*sizeof(char));
+    total_size += sizeof(char)*name_len;
+    name = c_name;
+    delete[] c_name;
+
+    IN_UPDATE_SZ(argNum);
+    args = GBE_NEW_ARRAY_NO_ARG(KernelArgument, argNum);
+    for (uint32_t i = 0; i < argNum; i++) {
+      KernelArgument& arg = args[i];
+      IN_UPDATE_SZ(arg.type);
+      IN_UPDATE_SZ(arg.size);
+      IN_UPDATE_SZ(arg.bufSize);
+    }
+
+    IN_UPDATE_SZ(patch_num);
+    for (uint32_t i = 0; i < patch_num; i++) {
+      unsigned int tmp;
+      PatchInfo patch;
+      IN_UPDATE_SZ(tmp);
+      patch.type = tmp;
+      IN_UPDATE_SZ(tmp);
+      patch.subType = tmp;
+      IN_UPDATE_SZ(tmp);
+      patch.offset = tmp;
+
+      patches.push_back(patch);
+    }
+
+    IN_UPDATE_SZ(curbeSize);
+    IN_UPDATE_SZ(simdWidth);
+    IN_UPDATE_SZ(stackSize);
+    IN_UPDATE_SZ(useSLM);
+
+    IN_UPDATE_SZ(has_samplerset);
+    if (has_samplerset) {
+      samplerSet = GBE_NEW(ir::SamplerSet);
+      size_t sz = samplerSet->deserializeFromBin(ins);
+      if (sz == 0) {
+        return 0;
+      }
+
+      total_size += sz;
+    }
+
+    IN_UPDATE_SZ(has_imageset);
+    if (has_imageset) {
+      imageSet = GBE_NEW(ir::ImageSet);
+      size_t sz = imageSet->deserializeFromBin(ins);
+      if (sz == 0) {
+        return 0;
+      }
+
+      total_size += sz;
+    }
+
+    IN_UPDATE_SZ(code_size);
+    if (code_size) {
+      char* code = GBE_NEW_ARRAY_NO_ARG(char, code_size);
+      ins.read(code, code_size*sizeof(char));
+      total_size += sizeof(char)*code_size;
+      setCode(code, code_size);
+    }
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_end)
+      return 0;
+
+    size_t total_bytes;
+    IN_UPDATE_SZ(total_bytes);
+    if (total_bytes + sizeof(total_size) != total_size)
+      return 0;
+
+    return total_size;
+  }
+
+#undef OUT_UPDATE_SZ
+#undef IN_UPDATE_SZ
+
+  void Program::printStatus(int indent, std::ostream& outs) {
+    using namespace std;
+    string spaces = indent_to_str(indent);
+
+    outs << spaces << "=============== Begin Program ===============" << "\n";
+
+    if (constantSet) {
+      constantSet->printStatus(indent + 4, outs);
+    }
+
+    for (auto ker : kernels) {
+      ker.second->printStatus(indent + 4, outs);
+    }
+
+    outs << spaces << "================ End Program ================" << "\n";
+  }
+
+  void Kernel::printStatus(int indent, std::ostream& outs) {
+    using namespace std;
+    string spaces = indent_to_str(indent);
+    string spaces_nl = indent_to_str(indent + 4);
+    int num;
+
+    outs << spaces << "+++++++++++ Begin Kernel +++++++++++" << "\n";
+    outs << spaces_nl << "Kernel Name: " << name << "\n";
+    outs << spaces_nl << "  curbeSize: " << curbeSize << "\n";
+    outs << spaces_nl << "  simdWidth: " << simdWidth << "\n";
+    outs << spaces_nl << "  stackSize: " << stackSize << "\n";
+    outs << spaces_nl << "  useSLM: " << useSLM << "\n";
+
+    outs << spaces_nl << "  Argument Number is " << argNum << "\n";
+    for (uint32_t i = 0; i < argNum; i++) {
+      KernelArgument& arg = args[i];
+      outs << spaces_nl << "  Arg " << i << ":\n";
+      outs << spaces_nl << "      type value: "<< arg.type << "\n";
+      outs << spaces_nl << "      size: "<< arg.size << "\n";
+      outs << spaces_nl << "      bufSize: "<< arg.bufSize << "\n";
+    }
+
+    outs << spaces_nl << "  Patches Number is " << patches.size() << "\n";
+    num = 0;
+    for (auto patch : patches) {
+      num++;
+      outs << spaces_nl << "  patch " << num << ":\n";
+      outs << spaces_nl << "      type value: "<< patch.type << "\n";
+      outs << spaces_nl << "      subtype value: "<< patch.subType << "\n";
+      outs << spaces_nl << "      offset: "<< patch.offset << "\n";
+    }
+
+    if (samplerSet) {
+      samplerSet->printStatus(indent + 4, outs);
+    }
+
+    if (imageSet) {
+      imageSet->printStatus(indent + 4, outs);
+    }
+
+    outs << spaces << "++++++++++++ End Kernel ++++++++++++" << "\n";
+  }
+
+  /*********************** End of Program class member function *************************/
+
   static void programDelete(gbe_program gbeProgram) {
     gbe::Program *program = (gbe::Program*)(gbeProgram);
     GBE_SAFE_DELETE(program);
diff --git a/backend/src/backend/program.hpp b/backend/src/backend/program.hpp
index 83aaab8..28a792d 100644
--- a/backend/src/backend/program.hpp
+++ b/backend/src/backend/program.hpp
@@ -67,7 +67,7 @@ namespace gbe {
   }
 
   /*! Describe a compiled kernel */
-  class Kernel : public NonCopyable
+  class Kernel : public NonCopyable, public Serializable
   {
   public:
     /*! Create an empty kernel with the given name */
@@ -76,6 +76,8 @@ namespace gbe {
     virtual ~Kernel(void);
     /*! Return the instruction stream (to be implemented) */
     virtual const char *getCode(void) const = 0;
+    /*! Set the instruction stream.*/
+    virtual const void setCode(const char *, size_t size) = 0;
     /*! Return the instruction stream size (to be implemented) */
     virtual size_t getCodeSize(void) const = 0;
     /*! Get the kernel name */
@@ -128,9 +130,37 @@ namespace gbe {
     size_t getImageSize(void) const { return imageSet->getDataSize(); }
     /*! Get defined image value array */
     void getImageData(ImageInfo *images) const { imageSet->getData(images); }
+
+    static const uint32_t magic_begin = TO_MAGIC('K', 'E', 'R', 'N');
+    static const uint32_t magic_end = TO_MAGIC('N', 'R', 'E', 'K');
+
+    /* format:
+       magic_begin       |
+       name_size         |
+       name              |
+       arg_num           |
+       args              |
+       PatchInfo_num     |
+       PatchInfo         |
+       curbeSize         |
+       simdWidth         |
+       stackSize         |
+       useSLM            |
+       samplers          |
+       images            |
+       code_size         |
+       code              |
+       magic_end
+    */
+
+    /*! Implements the serialization. */
+    virtual size_t serializeToBin(std::ostream& outs);
+    virtual size_t deserializeFromBin(std::istream& ins);
+    virtual void printStatus(int indent, std::ostream& outs);
+
   protected:
     friend class Context;      //!< Owns the kernels
-    const std::string name;    //!< Kernel name
+    std::string name;    //!< Kernel name
     KernelArgument *args;      //!< Each argument
     vector<PatchInfo> patches; //!< Indicates how to build the curbe
     uint32_t argNum;           //!< Number of function arguments
@@ -146,7 +176,7 @@ namespace gbe {
   };
 
   /*! Describe a compiled program */
-  class Program : public NonCopyable
+  class Program : public NonCopyable, public Serializable
   {
   public:
     /*! Create an empty program */
@@ -186,9 +216,32 @@ namespace gbe {
     size_t getGlobalConstantSize(void) const { return constantSet->getDataSize(); }
     /*! Get the content of global constant arrays */
     void getGlobalConstantData(char *mem) const { constantSet->getData(mem); }
+
+    static const uint32_t magic_begin = TO_MAGIC('P', 'R', 'O', 'G');
+    static const uint32_t magic_end = TO_MAGIC('G', 'O', 'R', 'P');
+
+    /* format:
+       magic_begin       |
+       constantSet_flag  |
+       constSet_data     |
+       kernel_num        |
+       kernel_1          |
+       ........          |
+       kernel_n          |
+       magic_end         |
+       total_size
+    */
+
+    /*! Implements the serialization. */
+    virtual size_t serializeToBin(std::ostream& outs);
+    virtual size_t deserializeFromBin(std::istream& ins);
+    virtual void printStatus(int indent, std::ostream& outs);
+
   protected:
     /*! Compile a kernel */
     virtual Kernel *compileKernel(const ir::Unit &unit, const std::string &name) = 0;
+    /*! Allocate an empty kernel. */
+    virtual Kernel *allocateKernel(const std::string &name) = 0;
     /*! Kernels sorted by their name */
     hash_map<std::string, Kernel*> kernels;
     /*! Global (constants) outside any kernel */
diff --git a/backend/src/ir/constant.cpp b/backend/src/ir/constant.cpp
index c9f5bfe..2bf52cc 100644
--- a/backend/src/ir/constant.cpp
+++ b/backend/src/ir/constant.cpp
@@ -40,6 +40,105 @@ namespace ir {
     for (uint32_t i = 0; i < size; ++i) this->data.push_back(data[i]);
   }
 
+#define OUT_UPDATE_SZ(elt) SERIALIZE_OUT(elt, outs, ret_size)
+#define IN_UPDATE_SZ(elt) DESERIALIZE_IN(elt, ins, total_size)
+
+  size_t ConstantSet::serializeToBin(std::ostream& outs) {
+    size_t ret_size = 0;
+
+    OUT_UPDATE_SZ(magic_begin);
+
+    /* output the const data. */
+    OUT_UPDATE_SZ((data.size()*sizeof(char)));
+    if(data.size() > 0) {
+      outs.write(data.data(), data.size()*sizeof(char));
+      ret_size += data.size()*sizeof(char);
+    }
+
+    OUT_UPDATE_SZ(constants.size());
+    for (auto const &cnst : constants) {
+      size_t bytes = sizeof(cnst.getName().size())        //name length self
+                     + cnst.getName().size()*sizeof(char) //name
+                     + sizeof(cnst.getSize())             //size
+                     + sizeof(cnst.getAlignment())        //alignment
+                     + sizeof(cnst.getOffset())	          //offset
+                     + sizeof(cnst.getReg());             //reg
+      OUT_UPDATE_SZ(bytes);
+
+      OUT_UPDATE_SZ(cnst.getName().size());
+      outs.write(cnst.getName().c_str(), cnst.getName().size());
+      ret_size += sizeof(char)*cnst.getName().size();
+      OUT_UPDATE_SZ(cnst.getSize());
+      OUT_UPDATE_SZ(cnst.getAlignment());
+      OUT_UPDATE_SZ(cnst.getOffset());
+      OUT_UPDATE_SZ(cnst.getReg());
+    }
+
+    OUT_UPDATE_SZ(magic_end);
+    OUT_UPDATE_SZ(ret_size);
+
+    return ret_size;
+  }
+
+  size_t ConstantSet::deserializeFromBin(std::istream& ins) {
+    size_t total_size = 0;
+    size_t global_data_sz = 0;
+    size_t const_num;
+    uint32_t magic;
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_begin)
+      return 0;
+
+    IN_UPDATE_SZ(global_data_sz);
+    for (size_t i = 0; i < global_data_sz; i++) {
+      char elt;
+      IN_UPDATE_SZ(elt);
+      data.push_back(elt);
+    }
+
+    IN_UPDATE_SZ(const_num);
+    for (size_t i = 0; i < const_num; i++) {
+      size_t bytes;
+      IN_UPDATE_SZ(bytes);
+
+      size_t name_len;
+      IN_UPDATE_SZ(name_len);
+
+      char* c_name = new char[name_len];
+      ins.read(c_name, name_len);
+      total_size += sizeof(char)*name_len;
+
+      uint32_t size, align, offset;
+      uint16_t reg;
+      IN_UPDATE_SZ(size);
+      IN_UPDATE_SZ(align);
+      IN_UPDATE_SZ(offset);
+      IN_UPDATE_SZ(reg);
+
+      const ir::Constant constant(c_name, size, align, offset);
+      constants.push_back(constant);
+
+      delete[] c_name;
+
+      /* Saint check */
+      if (bytes != sizeof(name_len) + sizeof(char)*name_len + sizeof(size)
+              + sizeof(align) + sizeof(offset) + sizeof(reg))
+        return 0;
+    }
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_end)
+      return 0;
+
+    size_t total_bytes;
+    IN_UPDATE_SZ(total_bytes);
+    if (total_bytes + sizeof(total_size) != total_size)
+      return 0;
+
+    return total_size;
+  }
+
 } /* namespace ir */
 } /* namespace gbe */
 
diff --git a/backend/src/ir/constant.hpp b/backend/src/ir/constant.hpp
index 0717391..4bb549e 100644
--- a/backend/src/ir/constant.hpp
+++ b/backend/src/ir/constant.hpp
@@ -52,6 +52,8 @@ namespace ir {
     /*! Nothing happens here */
     INLINE ~Constant(void) {}
     const std::string& getName(void) const { return name; }
+    uint32_t getSize (void) const { return size; }
+    uint32_t getAlignment (void) const { return alignment; }
     uint32_t getOffset(void) const { return offset; }
     uint16_t getReg(void) const { return reg; }
     void setReg(uint16_t reg) { this->reg = reg; }
@@ -67,7 +69,7 @@ namespace ir {
   /*! A constant set is a set of immutable data associated to a compilation
    *  unit
    */
-  class ConstantSet
+  class ConstantSet : public Serializable
   {
   public:
     /*! Append a new constant in the constant set */
@@ -93,7 +95,8 @@ namespace ir {
         mem[i] = data[i];
     }
     ConstantSet() {}
-    ConstantSet(const ConstantSet& other) : data(other.data), constants(other.constants) {}
+    ConstantSet(const ConstantSet& other) : Serializable(other),
+                data(other.data), constants(other.constants) {}
     ConstantSet & operator = (const ConstantSet& other) {
       if (&other != this) {
         data = other.data;
@@ -101,6 +104,27 @@ namespace ir {
       }
       return *this;
     }
+
+    static const uint32_t magic_begin = TO_MAGIC('C', 'N', 'S', 'T');
+    static const uint32_t magic_end = TO_MAGIC('T', 'S', 'N', 'C');
+
+    /* format:
+       magic_begin     |
+       const_data_size |
+       const_data      |
+       constant_1_size |
+       constant_1      |
+       ........        |
+       constant_n_size |
+       constant_n      |
+       magic_end       |
+       total_size
+    */
+
+    /*! Implements the serialization. */
+    virtual size_t serializeToBin(std::ostream& outs);
+    virtual size_t deserializeFromBin(std::istream& ins);
+
   private:
     vector<char> data;         //!< The constant data serialized in one array
     vector<Constant> constants;//!< Each constant description
diff --git a/backend/src/ir/image.cpp b/backend/src/ir/image.cpp
index 486fde1..b901a12 100644
--- a/backend/src/ir/image.cpp
+++ b/backend/src/ir/image.cpp
@@ -110,5 +110,144 @@ namespace ir {
       GBE_DELETE(it.second);
   }
 
+#define OUT_UPDATE_SZ(elt) SERIALIZE_OUT(elt, outs, ret_size)
+#define IN_UPDATE_SZ(elt) DESERIALIZE_IN(elt, ins, total_size)
+
+  /*! Implements the serialization. */
+  size_t ImageSet::serializeToBin(std::ostream& outs) {
+    size_t ret_size = 0;
+
+    OUT_UPDATE_SZ(magic_begin);
+
+    OUT_UPDATE_SZ(regMap.size());
+    for (auto iter : regMap) {
+      OUT_UPDATE_SZ(iter.first);
+      OUT_UPDATE_SZ(iter.second->arg_idx);
+      OUT_UPDATE_SZ(iter.second->idx);
+      OUT_UPDATE_SZ(iter.second->wSlot);
+      OUT_UPDATE_SZ(iter.second->hSlot);
+      OUT_UPDATE_SZ(iter.second->depthSlot);
+      OUT_UPDATE_SZ(iter.second->dataTypeSlot);
+      OUT_UPDATE_SZ(iter.second->channelOrderSlot);
+      OUT_UPDATE_SZ(iter.second->dimOrderSlot);
+    }
+
+    OUT_UPDATE_SZ(indexMap.size());
+    for (auto iter : indexMap) {
+      OUT_UPDATE_SZ(iter.first);
+      OUT_UPDATE_SZ(iter.second->arg_idx);
+      OUT_UPDATE_SZ(iter.second->idx);
+      OUT_UPDATE_SZ(iter.second->wSlot);
+      OUT_UPDATE_SZ(iter.second->hSlot);
+      OUT_UPDATE_SZ(iter.second->depthSlot);
+      OUT_UPDATE_SZ(iter.second->dataTypeSlot);
+      OUT_UPDATE_SZ(iter.second->channelOrderSlot);
+      OUT_UPDATE_SZ(iter.second->dimOrderSlot);
+    }
+
+    OUT_UPDATE_SZ(magic_end);
+    OUT_UPDATE_SZ(ret_size);
+
+    return ret_size;
+  }
+
+  size_t ImageSet::deserializeFromBin(std::istream& ins) {
+    size_t total_size = 0;
+    uint32_t magic;
+    size_t image_map_sz = 0;
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_begin)
+      return 0;
+
+    IN_UPDATE_SZ(image_map_sz); //regMap
+    for (size_t i = 0; i < image_map_sz; i++) {
+      ir::Register reg;
+      ImageInfo *img_info = GBE_NEW(struct ImageInfo);;
+
+      IN_UPDATE_SZ(reg);
+      IN_UPDATE_SZ(img_info->arg_idx);
+      IN_UPDATE_SZ(img_info->idx);
+      IN_UPDATE_SZ(img_info->wSlot);
+      IN_UPDATE_SZ(img_info->hSlot);
+      IN_UPDATE_SZ(img_info->depthSlot);
+      IN_UPDATE_SZ(img_info->dataTypeSlot);
+      IN_UPDATE_SZ(img_info->channelOrderSlot);
+      IN_UPDATE_SZ(img_info->dimOrderSlot);
+
+      regMap.insert(std::make_pair(reg, img_info));
+    }
+
+    IN_UPDATE_SZ(image_map_sz); //indexMap
+    for (uint32_t i = 0; i < image_map_sz; i++) {
+      uint32_t index;
+      ImageInfo *img_info = GBE_NEW(struct ImageInfo);;
+
+      IN_UPDATE_SZ(index);
+      IN_UPDATE_SZ(img_info->arg_idx);
+      IN_UPDATE_SZ(img_info->idx);
+      IN_UPDATE_SZ(img_info->wSlot);
+      IN_UPDATE_SZ(img_info->hSlot);
+      IN_UPDATE_SZ(img_info->depthSlot);
+      IN_UPDATE_SZ(img_info->dataTypeSlot);
+      IN_UPDATE_SZ(img_info->channelOrderSlot);
+      IN_UPDATE_SZ(img_info->dimOrderSlot);
+
+      indexMap.insert(std::make_pair(index, img_info));
+    }
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_end)
+      return 0;
+
+    size_t total_bytes;
+    IN_UPDATE_SZ(total_bytes);
+    if (total_bytes + sizeof(total_size) != total_size)
+      return 0;
+
+    return total_size;
+  }
+
+  void ImageSet::printStatus(int indent, std::ostream& outs) {
+    using namespace std;
+    string spaces = indent_to_str(indent);
+    string spaces_nl = indent_to_str(indent + 4);
+
+    outs << spaces << "------------ Begin ImageSet ------------" << "\n";
+
+    outs << spaces_nl  << "  ImageSet Map: [reg, arg_idx, idx, wSlot, hSlot, depthSlot, "
+                "dataTypeSlot, channelOrderSlot, dimOrderSlot]\n";
+    outs << spaces_nl << "     regMap size: " << regMap.size() << "\n";
+    for (auto iter : regMap) {
+      outs << spaces_nl << "         [" << iter.first << ", "
+           << iter.second->arg_idx << ", "
+           << iter.second->idx << ", "
+           << iter.second->wSlot << ", "
+           << iter.second->hSlot << ", "
+           << iter.second->depthSlot << ", "
+           << iter.second->dataTypeSlot << ", "
+           << iter.second->channelOrderSlot << ", "
+           << iter.second->dimOrderSlot << "]" << "\n";
+   }
+
+   outs << spaces_nl << "  ImageSet Map: [index, arg_idx, idx, wSlot, hSlot, depthSlot, "
+           "dataTypeSlot, channelOrderSlot, dimOrderSlot]\n";
+   outs << spaces_nl << "     regMap size: " << indexMap.size() << "\n";
+   for (auto iter : indexMap) {
+     outs << spaces_nl << "         [" << iter.first << ", "
+          << iter.second->arg_idx << ", "
+          << iter.second->idx << ", "
+          << iter.second->wSlot << ", "
+          << iter.second->hSlot << ", "
+          << iter.second->depthSlot << ", "
+          << iter.second->dataTypeSlot << ", "
+          << iter.second->channelOrderSlot << ", "
+          << iter.second->dimOrderSlot << ", " << "\n";
+   }
+
+   outs << spaces << "------------- End ImageSet -------------" << "\n";
+  }
+
+
 } /* namespace ir */
 } /* namespace gbe */
diff --git a/backend/src/ir/image.hpp b/backend/src/ir/image.hpp
index 04e78e6..c084c7d 100644
--- a/backend/src/ir/image.hpp
+++ b/backend/src/ir/image.hpp
@@ -40,7 +40,7 @@ namespace ir {
    *  for each individual image. And that individual image could be used
    *  at backend to identify this image's location.
    */
-  class ImageSet
+  class ImageSet : public Serializable
   {
   public:
     /*! Append an image argument. */
@@ -60,6 +60,29 @@ namespace ir {
     ImageSet(const ImageSet& other) : regMap(other.regMap.begin(), other.regMap.end()) { }
     ImageSet() {}
     ~ImageSet();
+
+    static const uint32_t magic_begin = TO_MAGIC('I', 'M', 'A', 'G');
+    static const uint32_t magic_end = TO_MAGIC('G', 'A', 'M', 'I');
+
+    /* format:
+       magic_begin     |
+       regMap_size     |
+       element_1       |
+       ........        |
+       element_n       |
+       indexMap_size   |
+       element_1       |
+       ........        |
+       element_n       |
+       magic_end       |
+       total_size
+    */
+
+    /*! Implements the serialization. */
+    virtual size_t serializeToBin(std::ostream& outs);
+    virtual size_t deserializeFromBin(std::istream& ins);
+    virtual void printStatus(int indent, std::ostream& outs);
+
   private:
     map<Register, struct ImageInfo *> regMap;
     map<uint32_t, struct ImageInfo *> indexMap;
diff --git a/backend/src/ir/sampler.cpp b/backend/src/ir/sampler.cpp
index 62bdc16..cff1012 100644
--- a/backend/src/ir/sampler.cpp
+++ b/backend/src/ir/sampler.cpp
@@ -74,5 +74,103 @@ namespace ir {
     appendReg(samplerReg, SAMPLER_ID(id), ctx);
   }
 
+
+#define OUT_UPDATE_SZ(elt) SERIALIZE_OUT(elt, outs, ret_size)
+#define IN_UPDATE_SZ(elt) DESERIALIZE_IN(elt, ins, total_size)
+
+  /*! Implements the serialization. */
+  size_t SamplerSet::serializeToBin(std::ostream& outs) {
+    size_t ret_size = 0;
+
+    OUT_UPDATE_SZ(magic_begin);
+
+    OUT_UPDATE_SZ(samplerMap.size());
+    for (auto iter : samplerMap) {
+      OUT_UPDATE_SZ(iter.first);
+      OUT_UPDATE_SZ(iter.second.reg);
+      OUT_UPDATE_SZ(iter.second.slot);
+    }
+
+    OUT_UPDATE_SZ(regMap.size());
+    for (auto iter : regMap) {
+      OUT_UPDATE_SZ(iter.first);
+      OUT_UPDATE_SZ(iter.second.reg);
+      OUT_UPDATE_SZ(iter.second.slot);
+    }
+
+    OUT_UPDATE_SZ(magic_end);
+    OUT_UPDATE_SZ(ret_size);
+
+    return ret_size;
+  }
+
+  size_t SamplerSet::deserializeFromBin(std::istream& ins) {
+    size_t total_size = 0;
+    uint32_t magic;
+    size_t sampler_map_sz = 0;
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_begin)
+      return 0;
+
+    IN_UPDATE_SZ(sampler_map_sz);
+    for (size_t i = 0; i < sampler_map_sz; i++) {
+      uint32_t key;
+      ir::SamplerRegSlot reg_slot;
+
+      IN_UPDATE_SZ(key);
+      IN_UPDATE_SZ(reg_slot.reg);
+      IN_UPDATE_SZ(reg_slot.slot);
+      samplerMap.insert(std::make_pair(key, reg_slot));
+    }
+
+    IN_UPDATE_SZ(sampler_map_sz);
+    for (size_t i = 0; i < sampler_map_sz; i++) {
+      ir::Register key;
+      ir::SamplerRegSlot reg_slot;
+
+      IN_UPDATE_SZ(key);
+      IN_UPDATE_SZ(reg_slot.reg);
+      IN_UPDATE_SZ(reg_slot.slot);
+      regMap.insert(std::make_pair(key, reg_slot));
+    }
+
+    IN_UPDATE_SZ(magic);
+    if (magic != magic_end)
+      return 0;
+
+    size_t total_bytes;
+    IN_UPDATE_SZ(total_bytes);
+    if (total_bytes + sizeof(total_size) != total_size)
+      return 0;
+
+    return total_size;
+  }
+
+  void SamplerSet::printStatus(int indent, std::ostream& outs) {
+    using namespace std;
+    string spaces = indent_to_str(indent);
+    string spaces_nl = indent_to_str(indent + 4);
+
+    outs << spaces << "------------ Begin SamplerSet ------------" << "\n";
+
+    outs << spaces_nl << "  SamplerSet Map: [index, sampler_reg, sampler_slot]\n";
+    outs << spaces_nl << "     samplerMap size: " << samplerMap.size() << "\n";
+
+    for (auto iter : samplerMap) {
+      outs << spaces_nl <<  "     [" << iter.first << ", "
+           << iter.second.reg << ", " << iter.second.slot << "]\n";
+    }
+
+    outs << spaces_nl << "  SamplerSet Map: [reg, sampler_reg, sampler_slot]\n";
+    outs << spaces_nl << "     regMap size: " << regMap.size() << "\n";
+    for (auto iter : regMap) {
+      outs << spaces_nl << "     [" << iter.first << ", "
+           << iter.second.reg << ", " << iter.second.slot << "]\n";
+    }
+
+    outs << spaces << "------------- End SamplerSet -------------" << "\n";
+  }
+
 } /* namespace ir */
 } /* namespace gbe */
diff --git a/backend/src/ir/sampler.hpp b/backend/src/ir/sampler.hpp
index f968299..3c72e3e 100644
--- a/backend/src/ir/sampler.hpp
+++ b/backend/src/ir/sampler.hpp
@@ -41,7 +41,7 @@ namespace ir {
     uint32_t slot;
   };
 
-  class SamplerSet
+  class SamplerSet : public Serializable
   {
   public:
     /*! Append the specified sampler and return the allocated offset.
@@ -66,6 +66,29 @@ namespace ir {
 
     SamplerSet(const SamplerSet& other) : samplerMap(other.samplerMap.begin(), other.samplerMap.end()) { }
     SamplerSet() {}
+
+    static const uint32_t magic_begin = TO_MAGIC('S', 'A', 'M', 'P');
+    static const uint32_t magic_end = TO_MAGIC('P', 'M', 'A', 'S');
+
+    /* format:
+       magic_begin     |
+       samplerMap_size |
+       element_1       |
+       ........        |
+       element_n       |
+       regMap_size     |
+       element_1       |
+       ........        |
+       element_n       |
+       magic_end       |
+       total_size
+    */
+
+    /*! Implements the serialization. */
+    virtual size_t serializeToBin(std::ostream& outs);
+    virtual size_t deserializeFromBin(std::istream& ins);
+    virtual void printStatus(int indent, std::ostream& outs);
+
   private:
     void appendReg(const Register reg, uint32_t key, Context *ctx);
     map<uint32_t, SamplerRegSlot> samplerMap;
diff --git a/backend/src/sys/platform.hpp b/backend/src/sys/platform.hpp
index a665356..783b665 100644
--- a/backend/src/sys/platform.hpp
+++ b/backend/src/sys/platform.hpp
@@ -24,6 +24,9 @@
 #include <cstdlib>
 #include <cstdio>
 #include <iostream>
+#include <ostream>
+#include <istream>
+#include <string>
 #include <cassert>
 #include <new>
 
@@ -323,6 +326,45 @@ private:
   INLINE NonCopyable& operator= (const NonCopyable&) {return *this;}
 };
 
+#define TO_MAGIC(A, B, C, D)  (A<<24 | B<<16 | C<<8 | D)
+
+class Serializable
+{
+public:
+  INLINE Serializable(void) = default;
+  INLINE Serializable(const Serializable&) = default;
+  INLINE Serializable& operator= (const Serializable&) = default;
+
+  virtual size_t serializeToBin(std::ostream& outs) = 0;
+  virtual size_t deserializeFromBin(std::istream& ins) = 0;
+
+  /* These two will follow LLVM's ABI. */
+  virtual size_t serializeToLLVM(void) { return 0;/* not implemented now. */}
+  virtual size_t deserializeFromLLVM(void) { return 0;/* not implemented now. */}
+
+  virtual void printStatus(int indent = 0, std::ostream& outs = std::cout) { }
+
+protected:
+  static std::string indent_to_str(int indent) {
+    std::string ind(indent, ' ');
+    return ind;
+  }
+};
+
+/* Help Macro for serialization. */
+#define SERIALIZE_OUT(elt, out, sz)			\
+     do {						\
+	  auto tmp_val = elt;				\
+	  out.write((char *)(&tmp_val), sizeof(elt));	\
+	  sz += sizeof(elt);				\
+     } while(0)
+
+#define DESERIALIZE_IN(elt, in, sz)			\
+     do {						\
+	  in.read((char *)(&(elt)), sizeof(elt));	\
+	  sz += sizeof(elt);				\
+     } while(0)
+
 ////////////////////////////////////////////////////////////////////////////////
 /// Disable some compiler warnings
 ////////////////////////////////////////////////////////////////////////////////
-- 
1.7.9.5



More information about the Beignet mailing list