From: Junyan He Date: Wed, 11 Sep 2013 10:07:39 +0000 (+0800) Subject: Add the serialization support for backend X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8471af99fc3634d5cdbc0cb707b14354c5c25841;p=contrib%2Fbeignet.git Add the serialization support for backend 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 Reviewed-by: Ruiling Song Reviewed-by: "Yang, Rong R" --- 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 #include +#include +#include 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..68bb17e 100644 --- a/backend/src/backend/program.cpp +++ b/backend/src/backend/program.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include /* Not defined for LLVM 3.0 */ @@ -124,6 +125,321 @@ 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+1]; + ins.read(c_name, name_len*sizeof(char)); + total_size += sizeof(char)*name_len; + c_name[name_len] = 0; + 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 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 kernels; /*! Global (constants) outside any kernel */ diff --git a/backend/src/ir/constant.cpp b/backend/src/ir/constant.cpp index c9f5bfe..7a8f80f 100644 --- a/backend/src/ir/constant.cpp +++ b/backend/src/ir/constant.cpp @@ -40,6 +40,107 @@ 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+1]; + ins.read(c_name, name_len); + total_size += sizeof(char)*name_len; + c_name[name_len] = 0; + + uint32_t size, align, offset; + uint16_t reg; + IN_UPDATE_SZ(size); + IN_UPDATE_SZ(align); + IN_UPDATE_SZ(offset); + IN_UPDATE_SZ(reg); + + ir::Constant constant(c_name, size, align, offset); + constant.setReg(reg); + 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 data; //!< The constant data serialized in one array vector 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 regMap; map 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 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 #include #include +#include +#include +#include #include #include @@ -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 ////////////////////////////////////////////////////////////////////////////////