1#include "util/blob.h"
2#include "nv50_ir_driver.h"
3#include "nv50_ir.h"
4#include "nv50_ir_target.h"
5#include "nv50_ir_driver.h"
6#include "tgsi/tgsi_parse.h"
7#include "compiler/nir/nir_serialize.h"
8
9enum FixupApplyFunc {
10   APPLY_NV50,
11   APPLY_NVC0,
12   APPLY_GK110,
13   APPLY_GM107,
14   APPLY_GV100,
15   FLIP_NVC0,
16   FLIP_GK110,
17   FLIP_GM107,
18   FLIP_GV100,
19};
20
21extern bool
22nv50_ir_prog_info_serialize(struct blob *blob, struct nv50_ir_prog_info *info)
23{
24   blob_write_uint32(blob, info->bin.smemSize);
25   blob_write_uint16(blob, info->target);
26   blob_write_uint8(blob, info->type);
27   blob_write_uint8(blob, info->optLevel);
28   blob_write_uint8(blob, info->dbgFlags);
29   blob_write_uint8(blob, info->omitLineNum);
30   blob_write_uint8(blob, info->bin.sourceRep);
31
32   switch(info->bin.sourceRep) {
33      case PIPE_SHADER_IR_TGSI: {
34         struct tgsi_token *tokens = (struct tgsi_token *)info->bin.source;
35         unsigned int num_tokens = tgsi_num_tokens(tokens);
36
37         blob_write_uint32(blob, num_tokens);
38         blob_write_bytes(blob, tokens, num_tokens * sizeof(struct tgsi_token));
39         break;
40      }
41      case PIPE_SHADER_IR_NIR: {
42         struct nir_shader *nir = (struct nir_shader *)info->bin.source;
43         nir_serialize(blob, nir, true);
44         break;
45      }
46      default:
47         ERROR("unhandled info->bin.sourceRep switch case\n");
48         assert(false);
49         return false;
50   }
51
52   if (info->type == PIPE_SHADER_COMPUTE)
53      blob_write_bytes(blob, &info->prop.cp, sizeof(info->prop.cp));
54
55   blob_write_bytes(blob, &info->io, sizeof(info->io));
56
57   return true;
58}
59
60extern bool
61nv50_ir_prog_info_out_serialize(struct blob *blob,
62                                struct nv50_ir_prog_info_out *info_out)
63{
64   blob_write_uint16(blob, info_out->target);
65   blob_write_uint8(blob, info_out->type);
66   blob_write_uint8(blob, info_out->numPatchConstants);
67
68   blob_write_uint16(blob, info_out->bin.maxGPR);
69   blob_write_uint32(blob, info_out->bin.tlsSpace);
70   blob_write_uint32(blob, info_out->bin.smemSize);
71   blob_write_uint32(blob, info_out->bin.codeSize);
72   blob_write_bytes(blob, info_out->bin.code, info_out->bin.codeSize);
73   blob_write_uint32(blob, info_out->bin.instructions);
74
75   if (!info_out->bin.relocData) {
76      blob_write_uint32(blob, 0); // reloc count 0
77   } else {
78      nv50_ir::RelocInfo *reloc = (nv50_ir::RelocInfo *)info_out->bin.relocData;
79      blob_write_uint32(blob, reloc->count);
80      blob_write_uint32(blob, reloc->codePos);
81      blob_write_uint32(blob, reloc->libPos);
82      blob_write_uint32(blob, reloc->dataPos);
83      blob_write_bytes(blob, reloc->entry, sizeof(*reloc->entry) * reloc->count);
84   }
85
86   if (!info_out->bin.fixupData) {
87      blob_write_uint32(blob, 0); // fixup count 0
88   } else {
89      nv50_ir::FixupInfo *fixup = (nv50_ir::FixupInfo *)info_out->bin.fixupData;
90      blob_write_uint32(blob, fixup->count);
91
92      /* Going through each entry */
93      for (uint32_t i = 0; i < fixup->count; i++) {
94         blob_write_uint32(blob, fixup->entry[i].val);
95         assert(fixup->entry[i].apply);
96         /* Compare function pointers, for when at serializing
97          * to know which function to apply */
98         if (fixup->entry[i].apply == nv50_ir::nv50_interpApply)
99            blob_write_uint8(blob, APPLY_NV50);
100         else if (fixup->entry[i].apply == nv50_ir::nvc0_interpApply)
101            blob_write_uint8(blob, APPLY_NVC0);
102         else if (fixup->entry[i].apply == nv50_ir::gk110_interpApply)
103            blob_write_uint8(blob, APPLY_GK110);
104         else if (fixup->entry[i].apply == nv50_ir::gm107_interpApply)
105            blob_write_uint8(blob, APPLY_GM107);
106         else if (fixup->entry[i].apply == nv50_ir::gv100_interpApply)
107            blob_write_uint8(blob, APPLY_GV100);
108         else if (fixup->entry[i].apply == nv50_ir::nvc0_selpFlip)
109            blob_write_uint8(blob, FLIP_NVC0);
110         else if (fixup->entry[i].apply == nv50_ir::gk110_selpFlip)
111            blob_write_uint8(blob, FLIP_GK110);
112         else if (fixup->entry[i].apply == nv50_ir::gm107_selpFlip)
113            blob_write_uint8(blob, FLIP_GM107);
114         else if (fixup->entry[i].apply == nv50_ir::gv100_selpFlip)
115            blob_write_uint8(blob, FLIP_GV100);
116         else {
117            ERROR("unhandled fixup apply function pointer\n");
118            assert(false);
119            return false;
120         }
121      }
122   }
123
124   blob_write_uint8(blob, info_out->numInputs);
125   blob_write_uint8(blob, info_out->numOutputs);
126   blob_write_uint8(blob, info_out->numSysVals);
127   blob_write_bytes(blob, info_out->sv, info_out->numSysVals * sizeof(info_out->sv[0]));
128   blob_write_bytes(blob, info_out->in, info_out->numInputs * sizeof(info_out->in[0]));
129   blob_write_bytes(blob, info_out->out, info_out->numOutputs * sizeof(info_out->out[0]));
130
131   switch(info_out->type) {
132      case PIPE_SHADER_VERTEX:
133         blob_write_bytes(blob, &info_out->prop.vp, sizeof(info_out->prop.vp));
134         break;
135      case PIPE_SHADER_TESS_CTRL:
136      case PIPE_SHADER_TESS_EVAL:
137         blob_write_bytes(blob, &info_out->prop.tp, sizeof(info_out->prop.tp));
138         break;
139      case PIPE_SHADER_GEOMETRY:
140         blob_write_bytes(blob, &info_out->prop.gp, sizeof(info_out->prop.gp));
141         break;
142      case PIPE_SHADER_FRAGMENT:
143         blob_write_bytes(blob, &info_out->prop.fp, sizeof(info_out->prop.fp));
144         break;
145      case PIPE_SHADER_COMPUTE:
146         blob_write_bytes(blob, &info_out->prop.cp, sizeof(info_out->prop.cp));
147         break;
148      default:
149         break;
150   }
151   blob_write_bytes(blob, &info_out->io, sizeof(info_out->io));
152   blob_write_uint8(blob, info_out->numBarriers);
153
154   return true;
155}
156
157extern bool
158nv50_ir_prog_info_out_deserialize(void *data, size_t size, size_t offset,
159                                  struct nv50_ir_prog_info_out *info_out)
160{
161   struct blob_reader reader;
162   blob_reader_init(&reader, data, size);
163   blob_skip_bytes(&reader, offset);
164
165   info_out->target = blob_read_uint16(&reader);
166   info_out->type = blob_read_uint8(&reader);
167   info_out->numPatchConstants = blob_read_uint8(&reader);
168
169   info_out->bin.maxGPR = blob_read_uint16(&reader);
170   info_out->bin.tlsSpace = blob_read_uint32(&reader);
171   info_out->bin.smemSize = blob_read_uint32(&reader);
172   info_out->bin.codeSize = blob_read_uint32(&reader);
173   info_out->bin.code = (uint32_t *)MALLOC(info_out->bin.codeSize);
174   blob_copy_bytes(&reader, info_out->bin.code, info_out->bin.codeSize);
175   info_out->bin.instructions = blob_read_uint32(&reader);
176
177   info_out->bin.relocData = NULL;
178   /*  Check if data contains RelocInfo */
179   uint32_t count = blob_read_uint32(&reader);
180   if (count) {
181      nv50_ir::RelocInfo *reloc =
182                  CALLOC_VARIANT_LENGTH_STRUCT(nv50_ir::RelocInfo,
183                                               count * sizeof(*reloc->entry));
184      reloc->codePos = blob_read_uint32(&reader);
185      reloc->libPos = blob_read_uint32(&reader);
186      reloc->dataPos = blob_read_uint32(&reader);
187      reloc->count = count;
188
189      blob_copy_bytes(&reader, reloc->entry, sizeof(*reloc->entry) * reloc->count);
190      info_out->bin.relocData = reloc;
191   }
192
193   info_out->bin.fixupData = NULL;
194   /* Check if data contains FixupInfo */
195   count = blob_read_uint32(&reader);
196   if (count) {
197      nv50_ir::FixupInfo *fixup =
198                  CALLOC_VARIANT_LENGTH_STRUCT(nv50_ir::FixupInfo,
199                                               count * sizeof(*fixup->entry));
200      fixup->count = count;
201
202      for (uint32_t i = 0; i < count; i++) {
203         fixup->entry[i].val = blob_read_uint32(&reader);
204
205         /* Assign back function pointer depending on stored enum */
206         enum FixupApplyFunc apply = (enum FixupApplyFunc)blob_read_uint8(&reader);
207         switch(apply) {
208            case APPLY_NV50:
209               fixup->entry[i].apply = nv50_ir::nv50_interpApply;
210               break;
211            case APPLY_NVC0:
212               fixup->entry[i].apply = nv50_ir::nvc0_interpApply;
213               break;
214            case APPLY_GK110:
215               fixup->entry[i].apply = nv50_ir::gk110_interpApply;
216               break;
217            case APPLY_GM107:
218               fixup->entry[i].apply = nv50_ir::gm107_interpApply;
219               break;
220            case APPLY_GV100:
221               fixup->entry[i].apply = nv50_ir::gv100_interpApply;
222               break;
223            case FLIP_NVC0:
224               fixup->entry[i].apply = nv50_ir::nvc0_selpFlip;
225               break;
226            case FLIP_GK110:
227               fixup->entry[i].apply = nv50_ir::gk110_selpFlip;
228               break;
229            case FLIP_GM107:
230               fixup->entry[i].apply = nv50_ir::gm107_selpFlip;
231               break;
232            case FLIP_GV100:
233               fixup->entry[i].apply = nv50_ir::gv100_selpFlip;
234               break;
235            default:
236               ERROR("unhandled fixup apply function switch case");
237               assert(false);
238               return false;
239         }
240      }
241      info_out->bin.fixupData = fixup;
242   }
243
244   info_out->numInputs = blob_read_uint8(&reader);
245   info_out->numOutputs = blob_read_uint8(&reader);
246   info_out->numSysVals = blob_read_uint8(&reader);
247   blob_copy_bytes(&reader, info_out->sv, info_out->numSysVals * sizeof(info_out->sv[0]));
248   blob_copy_bytes(&reader, info_out->in, info_out->numInputs * sizeof(info_out->in[0]));
249   blob_copy_bytes(&reader, info_out->out, info_out->numOutputs * sizeof(info_out->out[0]));
250
251   switch(info_out->type) {
252      case PIPE_SHADER_VERTEX:
253         blob_copy_bytes(&reader, &info_out->prop.vp, sizeof(info_out->prop.vp));
254         break;
255      case PIPE_SHADER_TESS_CTRL:
256      case PIPE_SHADER_TESS_EVAL:
257         blob_copy_bytes(&reader, &info_out->prop.tp, sizeof(info_out->prop.tp));
258         break;
259      case PIPE_SHADER_GEOMETRY:
260         blob_copy_bytes(&reader, &info_out->prop.gp, sizeof(info_out->prop.gp));
261         break;
262      case PIPE_SHADER_FRAGMENT:
263         blob_copy_bytes(&reader, &info_out->prop.fp, sizeof(info_out->prop.fp));
264         break;
265      case PIPE_SHADER_COMPUTE:
266         blob_copy_bytes(&reader, &info_out->prop.cp, sizeof(info_out->prop.cp));
267         break;
268      default:
269         break;
270   }
271   blob_copy_bytes(&reader, &(info_out->io), sizeof(info_out->io));
272   info_out->numBarriers = blob_read_uint8(&reader);
273
274   return true;
275}
276