1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2017 Connor Abbott 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include "nir_serialize.h" 25b8e80941Smrg#include "nir_control_flow.h" 26b8e80941Smrg#include "util/u_dynarray.h" 27b8e80941Smrg 28b8e80941Smrgtypedef struct { 29b8e80941Smrg size_t blob_offset; 30b8e80941Smrg nir_ssa_def *src; 31b8e80941Smrg nir_block *block; 32b8e80941Smrg} write_phi_fixup; 33b8e80941Smrg 34b8e80941Smrgtypedef struct { 35b8e80941Smrg const nir_shader *nir; 36b8e80941Smrg 37b8e80941Smrg struct blob *blob; 38b8e80941Smrg 39b8e80941Smrg /* maps pointer to index */ 40b8e80941Smrg struct hash_table *remap_table; 41b8e80941Smrg 42b8e80941Smrg /* the next index to assign to a NIR in-memory object */ 43b8e80941Smrg uintptr_t next_idx; 44b8e80941Smrg 45b8e80941Smrg /* Array of write_phi_fixup structs representing phi sources that need to 46b8e80941Smrg * be resolved in the second pass. 47b8e80941Smrg */ 48b8e80941Smrg struct util_dynarray phi_fixups; 49b8e80941Smrg} write_ctx; 50b8e80941Smrg 51b8e80941Smrgtypedef struct { 52b8e80941Smrg nir_shader *nir; 53b8e80941Smrg 54b8e80941Smrg struct blob_reader *blob; 55b8e80941Smrg 56b8e80941Smrg /* the next index to assign to a NIR in-memory object */ 57b8e80941Smrg uintptr_t next_idx; 58b8e80941Smrg 59b8e80941Smrg /* The length of the index -> object table */ 60b8e80941Smrg uintptr_t idx_table_len; 61b8e80941Smrg 62b8e80941Smrg /* map from index to deserialized pointer */ 63b8e80941Smrg void **idx_table; 64b8e80941Smrg 65b8e80941Smrg /* List of phi sources. */ 66b8e80941Smrg struct list_head phi_srcs; 67b8e80941Smrg 68b8e80941Smrg} read_ctx; 69b8e80941Smrg 70b8e80941Smrgstatic void 71b8e80941Smrgwrite_add_object(write_ctx *ctx, const void *obj) 72b8e80941Smrg{ 73b8e80941Smrg uintptr_t index = ctx->next_idx++; 74b8e80941Smrg _mesa_hash_table_insert(ctx->remap_table, obj, (void *) index); 75b8e80941Smrg} 76b8e80941Smrg 77b8e80941Smrgstatic uintptr_t 78b8e80941Smrgwrite_lookup_object(write_ctx *ctx, const void *obj) 79b8e80941Smrg{ 80b8e80941Smrg struct hash_entry *entry = _mesa_hash_table_search(ctx->remap_table, obj); 81b8e80941Smrg assert(entry); 82b8e80941Smrg return (uintptr_t) entry->data; 83b8e80941Smrg} 84b8e80941Smrg 85b8e80941Smrgstatic void 86b8e80941Smrgwrite_object(write_ctx *ctx, const void *obj) 87b8e80941Smrg{ 88b8e80941Smrg blob_write_intptr(ctx->blob, write_lookup_object(ctx, obj)); 89b8e80941Smrg} 90b8e80941Smrg 91b8e80941Smrgstatic void 92b8e80941Smrgread_add_object(read_ctx *ctx, void *obj) 93b8e80941Smrg{ 94b8e80941Smrg assert(ctx->next_idx < ctx->idx_table_len); 95b8e80941Smrg ctx->idx_table[ctx->next_idx++] = obj; 96b8e80941Smrg} 97b8e80941Smrg 98b8e80941Smrgstatic void * 99b8e80941Smrgread_lookup_object(read_ctx *ctx, uintptr_t idx) 100b8e80941Smrg{ 101b8e80941Smrg assert(idx < ctx->idx_table_len); 102b8e80941Smrg return ctx->idx_table[idx]; 103b8e80941Smrg} 104b8e80941Smrg 105b8e80941Smrgstatic void * 106b8e80941Smrgread_object(read_ctx *ctx) 107b8e80941Smrg{ 108b8e80941Smrg return read_lookup_object(ctx, blob_read_intptr(ctx->blob)); 109b8e80941Smrg} 110b8e80941Smrg 111b8e80941Smrgstatic void 112b8e80941Smrgwrite_constant(write_ctx *ctx, const nir_constant *c) 113b8e80941Smrg{ 114b8e80941Smrg blob_write_bytes(ctx->blob, c->values, sizeof(c->values)); 115b8e80941Smrg blob_write_uint32(ctx->blob, c->num_elements); 116b8e80941Smrg for (unsigned i = 0; i < c->num_elements; i++) 117b8e80941Smrg write_constant(ctx, c->elements[i]); 118b8e80941Smrg} 119b8e80941Smrg 120b8e80941Smrgstatic nir_constant * 121b8e80941Smrgread_constant(read_ctx *ctx, nir_variable *nvar) 122b8e80941Smrg{ 123b8e80941Smrg nir_constant *c = ralloc(nvar, nir_constant); 124b8e80941Smrg 125b8e80941Smrg blob_copy_bytes(ctx->blob, (uint8_t *)c->values, sizeof(c->values)); 126b8e80941Smrg c->num_elements = blob_read_uint32(ctx->blob); 127b8e80941Smrg c->elements = ralloc_array(nvar, nir_constant *, c->num_elements); 128b8e80941Smrg for (unsigned i = 0; i < c->num_elements; i++) 129b8e80941Smrg c->elements[i] = read_constant(ctx, nvar); 130b8e80941Smrg 131b8e80941Smrg return c; 132b8e80941Smrg} 133b8e80941Smrg 134b8e80941Smrgstatic void 135b8e80941Smrgwrite_variable(write_ctx *ctx, const nir_variable *var) 136b8e80941Smrg{ 137b8e80941Smrg write_add_object(ctx, var); 138b8e80941Smrg encode_type_to_blob(ctx->blob, var->type); 139b8e80941Smrg blob_write_uint32(ctx->blob, !!(var->name)); 140b8e80941Smrg if (var->name) 141b8e80941Smrg blob_write_string(ctx->blob, var->name); 142b8e80941Smrg blob_write_bytes(ctx->blob, (uint8_t *) &var->data, sizeof(var->data)); 143b8e80941Smrg blob_write_uint32(ctx->blob, var->num_state_slots); 144b8e80941Smrg for (unsigned i = 0; i < var->num_state_slots; i++) { 145b8e80941Smrg for (unsigned j = 0; j < STATE_LENGTH; j++) 146b8e80941Smrg blob_write_uint32(ctx->blob, var->state_slots[i].tokens[j]); 147b8e80941Smrg blob_write_uint32(ctx->blob, var->state_slots[i].swizzle); 148b8e80941Smrg } 149b8e80941Smrg blob_write_uint32(ctx->blob, !!(var->constant_initializer)); 150b8e80941Smrg if (var->constant_initializer) 151b8e80941Smrg write_constant(ctx, var->constant_initializer); 152b8e80941Smrg blob_write_uint32(ctx->blob, !!(var->interface_type)); 153b8e80941Smrg if (var->interface_type) 154b8e80941Smrg encode_type_to_blob(ctx->blob, var->interface_type); 155b8e80941Smrg blob_write_uint32(ctx->blob, var->num_members); 156b8e80941Smrg if (var->num_members > 0) { 157b8e80941Smrg blob_write_bytes(ctx->blob, (uint8_t *) var->members, 158b8e80941Smrg var->num_members * sizeof(*var->members)); 159b8e80941Smrg } 160b8e80941Smrg} 161b8e80941Smrg 162b8e80941Smrgstatic nir_variable * 163b8e80941Smrgread_variable(read_ctx *ctx) 164b8e80941Smrg{ 165b8e80941Smrg nir_variable *var = rzalloc(ctx->nir, nir_variable); 166b8e80941Smrg read_add_object(ctx, var); 167b8e80941Smrg 168b8e80941Smrg var->type = decode_type_from_blob(ctx->blob); 169b8e80941Smrg bool has_name = blob_read_uint32(ctx->blob); 170b8e80941Smrg if (has_name) { 171b8e80941Smrg const char *name = blob_read_string(ctx->blob); 172b8e80941Smrg var->name = ralloc_strdup(var, name); 173b8e80941Smrg } else { 174b8e80941Smrg var->name = NULL; 175b8e80941Smrg } 176b8e80941Smrg blob_copy_bytes(ctx->blob, (uint8_t *) &var->data, sizeof(var->data)); 177b8e80941Smrg var->num_state_slots = blob_read_uint32(ctx->blob); 178b8e80941Smrg if (var->num_state_slots != 0) { 179b8e80941Smrg var->state_slots = ralloc_array(var, nir_state_slot, 180b8e80941Smrg var->num_state_slots); 181b8e80941Smrg for (unsigned i = 0; i < var->num_state_slots; i++) { 182b8e80941Smrg for (unsigned j = 0; j < STATE_LENGTH; j++) 183b8e80941Smrg var->state_slots[i].tokens[j] = blob_read_uint32(ctx->blob); 184b8e80941Smrg var->state_slots[i].swizzle = blob_read_uint32(ctx->blob); 185b8e80941Smrg } 186b8e80941Smrg } 187b8e80941Smrg bool has_const_initializer = blob_read_uint32(ctx->blob); 188b8e80941Smrg if (has_const_initializer) 189b8e80941Smrg var->constant_initializer = read_constant(ctx, var); 190b8e80941Smrg else 191b8e80941Smrg var->constant_initializer = NULL; 192b8e80941Smrg bool has_interface_type = blob_read_uint32(ctx->blob); 193b8e80941Smrg if (has_interface_type) 194b8e80941Smrg var->interface_type = decode_type_from_blob(ctx->blob); 195b8e80941Smrg else 196b8e80941Smrg var->interface_type = NULL; 197b8e80941Smrg var->num_members = blob_read_uint32(ctx->blob); 198b8e80941Smrg if (var->num_members > 0) { 199b8e80941Smrg var->members = ralloc_array(var, struct nir_variable_data, 200b8e80941Smrg var->num_members); 201b8e80941Smrg blob_copy_bytes(ctx->blob, (uint8_t *) var->members, 202b8e80941Smrg var->num_members * sizeof(*var->members)); 203b8e80941Smrg } 204b8e80941Smrg 205b8e80941Smrg return var; 206b8e80941Smrg} 207b8e80941Smrg 208b8e80941Smrgstatic void 209b8e80941Smrgwrite_var_list(write_ctx *ctx, const struct exec_list *src) 210b8e80941Smrg{ 211b8e80941Smrg blob_write_uint32(ctx->blob, exec_list_length(src)); 212b8e80941Smrg foreach_list_typed(nir_variable, var, node, src) { 213b8e80941Smrg write_variable(ctx, var); 214b8e80941Smrg } 215b8e80941Smrg} 216b8e80941Smrg 217b8e80941Smrgstatic void 218b8e80941Smrgread_var_list(read_ctx *ctx, struct exec_list *dst) 219b8e80941Smrg{ 220b8e80941Smrg exec_list_make_empty(dst); 221b8e80941Smrg unsigned num_vars = blob_read_uint32(ctx->blob); 222b8e80941Smrg for (unsigned i = 0; i < num_vars; i++) { 223b8e80941Smrg nir_variable *var = read_variable(ctx); 224b8e80941Smrg exec_list_push_tail(dst, &var->node); 225b8e80941Smrg } 226b8e80941Smrg} 227b8e80941Smrg 228b8e80941Smrgstatic void 229b8e80941Smrgwrite_register(write_ctx *ctx, const nir_register *reg) 230b8e80941Smrg{ 231b8e80941Smrg write_add_object(ctx, reg); 232b8e80941Smrg blob_write_uint32(ctx->blob, reg->num_components); 233b8e80941Smrg blob_write_uint32(ctx->blob, reg->bit_size); 234b8e80941Smrg blob_write_uint32(ctx->blob, reg->num_array_elems); 235b8e80941Smrg blob_write_uint32(ctx->blob, reg->index); 236b8e80941Smrg blob_write_uint32(ctx->blob, !!(reg->name)); 237b8e80941Smrg if (reg->name) 238b8e80941Smrg blob_write_string(ctx->blob, reg->name); 239b8e80941Smrg} 240b8e80941Smrg 241b8e80941Smrgstatic nir_register * 242b8e80941Smrgread_register(read_ctx *ctx) 243b8e80941Smrg{ 244b8e80941Smrg nir_register *reg = ralloc(ctx->nir, nir_register); 245b8e80941Smrg read_add_object(ctx, reg); 246b8e80941Smrg reg->num_components = blob_read_uint32(ctx->blob); 247b8e80941Smrg reg->bit_size = blob_read_uint32(ctx->blob); 248b8e80941Smrg reg->num_array_elems = blob_read_uint32(ctx->blob); 249b8e80941Smrg reg->index = blob_read_uint32(ctx->blob); 250b8e80941Smrg bool has_name = blob_read_uint32(ctx->blob); 251b8e80941Smrg if (has_name) { 252b8e80941Smrg const char *name = blob_read_string(ctx->blob); 253b8e80941Smrg reg->name = ralloc_strdup(reg, name); 254b8e80941Smrg } else { 255b8e80941Smrg reg->name = NULL; 256b8e80941Smrg } 257b8e80941Smrg 258b8e80941Smrg list_inithead(®->uses); 259b8e80941Smrg list_inithead(®->defs); 260b8e80941Smrg list_inithead(®->if_uses); 261b8e80941Smrg 262b8e80941Smrg return reg; 263b8e80941Smrg} 264b8e80941Smrg 265b8e80941Smrgstatic void 266b8e80941Smrgwrite_reg_list(write_ctx *ctx, const struct exec_list *src) 267b8e80941Smrg{ 268b8e80941Smrg blob_write_uint32(ctx->blob, exec_list_length(src)); 269b8e80941Smrg foreach_list_typed(nir_register, reg, node, src) 270b8e80941Smrg write_register(ctx, reg); 271b8e80941Smrg} 272b8e80941Smrg 273b8e80941Smrgstatic void 274b8e80941Smrgread_reg_list(read_ctx *ctx, struct exec_list *dst) 275b8e80941Smrg{ 276b8e80941Smrg exec_list_make_empty(dst); 277b8e80941Smrg unsigned num_regs = blob_read_uint32(ctx->blob); 278b8e80941Smrg for (unsigned i = 0; i < num_regs; i++) { 279b8e80941Smrg nir_register *reg = read_register(ctx); 280b8e80941Smrg exec_list_push_tail(dst, ®->node); 281b8e80941Smrg } 282b8e80941Smrg} 283b8e80941Smrg 284b8e80941Smrgstatic void 285b8e80941Smrgwrite_src(write_ctx *ctx, const nir_src *src) 286b8e80941Smrg{ 287b8e80941Smrg /* Since sources are very frequent, we try to save some space when storing 288b8e80941Smrg * them. In particular, we store whether the source is a register and 289b8e80941Smrg * whether the register has an indirect index in the low two bits. We can 290b8e80941Smrg * assume that the high two bits of the index are zero, since otherwise our 291b8e80941Smrg * address space would've been exhausted allocating the remap table! 292b8e80941Smrg */ 293b8e80941Smrg if (src->is_ssa) { 294b8e80941Smrg uintptr_t idx = write_lookup_object(ctx, src->ssa) << 2; 295b8e80941Smrg idx |= 1; 296b8e80941Smrg blob_write_intptr(ctx->blob, idx); 297b8e80941Smrg } else { 298b8e80941Smrg uintptr_t idx = write_lookup_object(ctx, src->reg.reg) << 2; 299b8e80941Smrg if (src->reg.indirect) 300b8e80941Smrg idx |= 2; 301b8e80941Smrg blob_write_intptr(ctx->blob, idx); 302b8e80941Smrg blob_write_uint32(ctx->blob, src->reg.base_offset); 303b8e80941Smrg if (src->reg.indirect) { 304b8e80941Smrg write_src(ctx, src->reg.indirect); 305b8e80941Smrg } 306b8e80941Smrg } 307b8e80941Smrg} 308b8e80941Smrg 309b8e80941Smrgstatic void 310b8e80941Smrgread_src(read_ctx *ctx, nir_src *src, void *mem_ctx) 311b8e80941Smrg{ 312b8e80941Smrg uintptr_t val = blob_read_intptr(ctx->blob); 313b8e80941Smrg uintptr_t idx = val >> 2; 314b8e80941Smrg src->is_ssa = val & 0x1; 315b8e80941Smrg if (src->is_ssa) { 316b8e80941Smrg src->ssa = read_lookup_object(ctx, idx); 317b8e80941Smrg } else { 318b8e80941Smrg bool is_indirect = val & 0x2; 319b8e80941Smrg src->reg.reg = read_lookup_object(ctx, idx); 320b8e80941Smrg src->reg.base_offset = blob_read_uint32(ctx->blob); 321b8e80941Smrg if (is_indirect) { 322b8e80941Smrg src->reg.indirect = ralloc(mem_ctx, nir_src); 323b8e80941Smrg read_src(ctx, src->reg.indirect, mem_ctx); 324b8e80941Smrg } else { 325b8e80941Smrg src->reg.indirect = NULL; 326b8e80941Smrg } 327b8e80941Smrg } 328b8e80941Smrg} 329b8e80941Smrg 330b8e80941Smrgstatic void 331b8e80941Smrgwrite_dest(write_ctx *ctx, const nir_dest *dst) 332b8e80941Smrg{ 333b8e80941Smrg uint32_t val = dst->is_ssa; 334b8e80941Smrg if (dst->is_ssa) { 335b8e80941Smrg val |= !!(dst->ssa.name) << 1; 336b8e80941Smrg val |= dst->ssa.num_components << 2; 337b8e80941Smrg val |= dst->ssa.bit_size << 5; 338b8e80941Smrg } else { 339b8e80941Smrg val |= !!(dst->reg.indirect) << 1; 340b8e80941Smrg } 341b8e80941Smrg blob_write_uint32(ctx->blob, val); 342b8e80941Smrg if (dst->is_ssa) { 343b8e80941Smrg write_add_object(ctx, &dst->ssa); 344b8e80941Smrg if (dst->ssa.name) 345b8e80941Smrg blob_write_string(ctx->blob, dst->ssa.name); 346b8e80941Smrg } else { 347b8e80941Smrg blob_write_intptr(ctx->blob, write_lookup_object(ctx, dst->reg.reg)); 348b8e80941Smrg blob_write_uint32(ctx->blob, dst->reg.base_offset); 349b8e80941Smrg if (dst->reg.indirect) 350b8e80941Smrg write_src(ctx, dst->reg.indirect); 351b8e80941Smrg } 352b8e80941Smrg} 353b8e80941Smrg 354b8e80941Smrgstatic void 355b8e80941Smrgread_dest(read_ctx *ctx, nir_dest *dst, nir_instr *instr) 356b8e80941Smrg{ 357b8e80941Smrg uint32_t val = blob_read_uint32(ctx->blob); 358b8e80941Smrg bool is_ssa = val & 0x1; 359b8e80941Smrg if (is_ssa) { 360b8e80941Smrg bool has_name = val & 0x2; 361b8e80941Smrg unsigned num_components = (val >> 2) & 0x7; 362b8e80941Smrg unsigned bit_size = val >> 5; 363b8e80941Smrg char *name = has_name ? blob_read_string(ctx->blob) : NULL; 364b8e80941Smrg nir_ssa_dest_init(instr, dst, num_components, bit_size, name); 365b8e80941Smrg read_add_object(ctx, &dst->ssa); 366b8e80941Smrg } else { 367b8e80941Smrg bool is_indirect = val & 0x2; 368b8e80941Smrg dst->reg.reg = read_object(ctx); 369b8e80941Smrg dst->reg.base_offset = blob_read_uint32(ctx->blob); 370b8e80941Smrg if (is_indirect) { 371b8e80941Smrg dst->reg.indirect = ralloc(instr, nir_src); 372b8e80941Smrg read_src(ctx, dst->reg.indirect, instr); 373b8e80941Smrg } 374b8e80941Smrg } 375b8e80941Smrg} 376b8e80941Smrg 377b8e80941Smrgstatic void 378b8e80941Smrgwrite_alu(write_ctx *ctx, const nir_alu_instr *alu) 379b8e80941Smrg{ 380b8e80941Smrg blob_write_uint32(ctx->blob, alu->op); 381b8e80941Smrg uint32_t flags = alu->exact; 382b8e80941Smrg flags |= alu->dest.saturate << 1; 383b8e80941Smrg flags |= alu->dest.write_mask << 2; 384b8e80941Smrg blob_write_uint32(ctx->blob, flags); 385b8e80941Smrg 386b8e80941Smrg write_dest(ctx, &alu->dest.dest); 387b8e80941Smrg 388b8e80941Smrg for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++) { 389b8e80941Smrg write_src(ctx, &alu->src[i].src); 390b8e80941Smrg flags = alu->src[i].negate; 391b8e80941Smrg flags |= alu->src[i].abs << 1; 392b8e80941Smrg for (unsigned j = 0; j < 4; j++) 393b8e80941Smrg flags |= alu->src[i].swizzle[j] << (2 + 2 * j); 394b8e80941Smrg blob_write_uint32(ctx->blob, flags); 395b8e80941Smrg } 396b8e80941Smrg} 397b8e80941Smrg 398b8e80941Smrgstatic nir_alu_instr * 399b8e80941Smrgread_alu(read_ctx *ctx) 400b8e80941Smrg{ 401b8e80941Smrg nir_op op = blob_read_uint32(ctx->blob); 402b8e80941Smrg nir_alu_instr *alu = nir_alu_instr_create(ctx->nir, op); 403b8e80941Smrg 404b8e80941Smrg uint32_t flags = blob_read_uint32(ctx->blob); 405b8e80941Smrg alu->exact = flags & 1; 406b8e80941Smrg alu->dest.saturate = flags & 2; 407b8e80941Smrg alu->dest.write_mask = flags >> 2; 408b8e80941Smrg 409b8e80941Smrg read_dest(ctx, &alu->dest.dest, &alu->instr); 410b8e80941Smrg 411b8e80941Smrg for (unsigned i = 0; i < nir_op_infos[op].num_inputs; i++) { 412b8e80941Smrg read_src(ctx, &alu->src[i].src, &alu->instr); 413b8e80941Smrg flags = blob_read_uint32(ctx->blob); 414b8e80941Smrg alu->src[i].negate = flags & 1; 415b8e80941Smrg alu->src[i].abs = flags & 2; 416b8e80941Smrg for (unsigned j = 0; j < 4; j++) 417b8e80941Smrg alu->src[i].swizzle[j] = (flags >> (2 * j + 2)) & 3; 418b8e80941Smrg } 419b8e80941Smrg 420b8e80941Smrg return alu; 421b8e80941Smrg} 422b8e80941Smrg 423b8e80941Smrgstatic void 424b8e80941Smrgwrite_deref(write_ctx *ctx, const nir_deref_instr *deref) 425b8e80941Smrg{ 426b8e80941Smrg blob_write_uint32(ctx->blob, deref->deref_type); 427b8e80941Smrg 428b8e80941Smrg blob_write_uint32(ctx->blob, deref->mode); 429b8e80941Smrg encode_type_to_blob(ctx->blob, deref->type); 430b8e80941Smrg 431b8e80941Smrg write_dest(ctx, &deref->dest); 432b8e80941Smrg 433b8e80941Smrg if (deref->deref_type == nir_deref_type_var) { 434b8e80941Smrg write_object(ctx, deref->var); 435b8e80941Smrg return; 436b8e80941Smrg } 437b8e80941Smrg 438b8e80941Smrg write_src(ctx, &deref->parent); 439b8e80941Smrg 440b8e80941Smrg switch (deref->deref_type) { 441b8e80941Smrg case nir_deref_type_struct: 442b8e80941Smrg blob_write_uint32(ctx->blob, deref->strct.index); 443b8e80941Smrg break; 444b8e80941Smrg 445b8e80941Smrg case nir_deref_type_array: 446b8e80941Smrg case nir_deref_type_ptr_as_array: 447b8e80941Smrg write_src(ctx, &deref->arr.index); 448b8e80941Smrg break; 449b8e80941Smrg 450b8e80941Smrg case nir_deref_type_cast: 451b8e80941Smrg blob_write_uint32(ctx->blob, deref->cast.ptr_stride); 452b8e80941Smrg break; 453b8e80941Smrg 454b8e80941Smrg case nir_deref_type_array_wildcard: 455b8e80941Smrg /* Nothing to do */ 456b8e80941Smrg break; 457b8e80941Smrg 458b8e80941Smrg default: 459b8e80941Smrg unreachable("Invalid deref type"); 460b8e80941Smrg } 461b8e80941Smrg} 462b8e80941Smrg 463b8e80941Smrgstatic nir_deref_instr * 464b8e80941Smrgread_deref(read_ctx *ctx) 465b8e80941Smrg{ 466b8e80941Smrg nir_deref_type deref_type = blob_read_uint32(ctx->blob); 467b8e80941Smrg nir_deref_instr *deref = nir_deref_instr_create(ctx->nir, deref_type); 468b8e80941Smrg 469b8e80941Smrg deref->mode = blob_read_uint32(ctx->blob); 470b8e80941Smrg deref->type = decode_type_from_blob(ctx->blob); 471b8e80941Smrg 472b8e80941Smrg read_dest(ctx, &deref->dest, &deref->instr); 473b8e80941Smrg 474b8e80941Smrg if (deref_type == nir_deref_type_var) { 475b8e80941Smrg deref->var = read_object(ctx); 476b8e80941Smrg return deref; 477b8e80941Smrg } 478b8e80941Smrg 479b8e80941Smrg read_src(ctx, &deref->parent, &deref->instr); 480b8e80941Smrg 481b8e80941Smrg switch (deref->deref_type) { 482b8e80941Smrg case nir_deref_type_struct: 483b8e80941Smrg deref->strct.index = blob_read_uint32(ctx->blob); 484b8e80941Smrg break; 485b8e80941Smrg 486b8e80941Smrg case nir_deref_type_array: 487b8e80941Smrg case nir_deref_type_ptr_as_array: 488b8e80941Smrg read_src(ctx, &deref->arr.index, &deref->instr); 489b8e80941Smrg break; 490b8e80941Smrg 491b8e80941Smrg case nir_deref_type_cast: 492b8e80941Smrg deref->cast.ptr_stride = blob_read_uint32(ctx->blob); 493b8e80941Smrg break; 494b8e80941Smrg 495b8e80941Smrg case nir_deref_type_array_wildcard: 496b8e80941Smrg /* Nothing to do */ 497b8e80941Smrg break; 498b8e80941Smrg 499b8e80941Smrg default: 500b8e80941Smrg unreachable("Invalid deref type"); 501b8e80941Smrg } 502b8e80941Smrg 503b8e80941Smrg return deref; 504b8e80941Smrg} 505b8e80941Smrg 506b8e80941Smrgstatic void 507b8e80941Smrgwrite_intrinsic(write_ctx *ctx, const nir_intrinsic_instr *intrin) 508b8e80941Smrg{ 509b8e80941Smrg blob_write_uint32(ctx->blob, intrin->intrinsic); 510b8e80941Smrg 511b8e80941Smrg unsigned num_srcs = nir_intrinsic_infos[intrin->intrinsic].num_srcs; 512b8e80941Smrg unsigned num_indices = nir_intrinsic_infos[intrin->intrinsic].num_indices; 513b8e80941Smrg 514b8e80941Smrg blob_write_uint32(ctx->blob, intrin->num_components); 515b8e80941Smrg 516b8e80941Smrg if (nir_intrinsic_infos[intrin->intrinsic].has_dest) 517b8e80941Smrg write_dest(ctx, &intrin->dest); 518b8e80941Smrg 519b8e80941Smrg for (unsigned i = 0; i < num_srcs; i++) 520b8e80941Smrg write_src(ctx, &intrin->src[i]); 521b8e80941Smrg 522b8e80941Smrg for (unsigned i = 0; i < num_indices; i++) 523b8e80941Smrg blob_write_uint32(ctx->blob, intrin->const_index[i]); 524b8e80941Smrg} 525b8e80941Smrg 526b8e80941Smrgstatic nir_intrinsic_instr * 527b8e80941Smrgread_intrinsic(read_ctx *ctx) 528b8e80941Smrg{ 529b8e80941Smrg nir_intrinsic_op op = blob_read_uint32(ctx->blob); 530b8e80941Smrg 531b8e80941Smrg nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(ctx->nir, op); 532b8e80941Smrg 533b8e80941Smrg unsigned num_srcs = nir_intrinsic_infos[op].num_srcs; 534b8e80941Smrg unsigned num_indices = nir_intrinsic_infos[op].num_indices; 535b8e80941Smrg 536b8e80941Smrg intrin->num_components = blob_read_uint32(ctx->blob); 537b8e80941Smrg 538b8e80941Smrg if (nir_intrinsic_infos[op].has_dest) 539b8e80941Smrg read_dest(ctx, &intrin->dest, &intrin->instr); 540b8e80941Smrg 541b8e80941Smrg for (unsigned i = 0; i < num_srcs; i++) 542b8e80941Smrg read_src(ctx, &intrin->src[i], &intrin->instr); 543b8e80941Smrg 544b8e80941Smrg for (unsigned i = 0; i < num_indices; i++) 545b8e80941Smrg intrin->const_index[i] = blob_read_uint32(ctx->blob); 546b8e80941Smrg 547b8e80941Smrg return intrin; 548b8e80941Smrg} 549b8e80941Smrg 550b8e80941Smrgstatic void 551b8e80941Smrgwrite_load_const(write_ctx *ctx, const nir_load_const_instr *lc) 552b8e80941Smrg{ 553b8e80941Smrg uint32_t val = lc->def.num_components; 554b8e80941Smrg val |= lc->def.bit_size << 3; 555b8e80941Smrg blob_write_uint32(ctx->blob, val); 556b8e80941Smrg blob_write_bytes(ctx->blob, lc->value, sizeof(*lc->value) * lc->def.num_components); 557b8e80941Smrg write_add_object(ctx, &lc->def); 558b8e80941Smrg} 559b8e80941Smrg 560b8e80941Smrgstatic nir_load_const_instr * 561b8e80941Smrgread_load_const(read_ctx *ctx) 562b8e80941Smrg{ 563b8e80941Smrg uint32_t val = blob_read_uint32(ctx->blob); 564b8e80941Smrg 565b8e80941Smrg nir_load_const_instr *lc = 566b8e80941Smrg nir_load_const_instr_create(ctx->nir, val & 0x7, val >> 3); 567b8e80941Smrg 568b8e80941Smrg blob_copy_bytes(ctx->blob, lc->value, sizeof(*lc->value) * lc->def.num_components); 569b8e80941Smrg read_add_object(ctx, &lc->def); 570b8e80941Smrg return lc; 571b8e80941Smrg} 572b8e80941Smrg 573b8e80941Smrgstatic void 574b8e80941Smrgwrite_ssa_undef(write_ctx *ctx, const nir_ssa_undef_instr *undef) 575b8e80941Smrg{ 576b8e80941Smrg uint32_t val = undef->def.num_components; 577b8e80941Smrg val |= undef->def.bit_size << 3; 578b8e80941Smrg blob_write_uint32(ctx->blob, val); 579b8e80941Smrg write_add_object(ctx, &undef->def); 580b8e80941Smrg} 581b8e80941Smrg 582b8e80941Smrgstatic nir_ssa_undef_instr * 583b8e80941Smrgread_ssa_undef(read_ctx *ctx) 584b8e80941Smrg{ 585b8e80941Smrg uint32_t val = blob_read_uint32(ctx->blob); 586b8e80941Smrg 587b8e80941Smrg nir_ssa_undef_instr *undef = 588b8e80941Smrg nir_ssa_undef_instr_create(ctx->nir, val & 0x7, val >> 3); 589b8e80941Smrg 590b8e80941Smrg read_add_object(ctx, &undef->def); 591b8e80941Smrg return undef; 592b8e80941Smrg} 593b8e80941Smrg 594b8e80941Smrgunion packed_tex_data { 595b8e80941Smrg uint32_t u32; 596b8e80941Smrg struct { 597b8e80941Smrg enum glsl_sampler_dim sampler_dim:4; 598b8e80941Smrg nir_alu_type dest_type:8; 599b8e80941Smrg unsigned coord_components:3; 600b8e80941Smrg unsigned is_array:1; 601b8e80941Smrg unsigned is_shadow:1; 602b8e80941Smrg unsigned is_new_style_shadow:1; 603b8e80941Smrg unsigned component:2; 604b8e80941Smrg unsigned unused:10; /* Mark unused for valgrind. */ 605b8e80941Smrg } u; 606b8e80941Smrg}; 607b8e80941Smrg 608b8e80941Smrgstatic void 609b8e80941Smrgwrite_tex(write_ctx *ctx, const nir_tex_instr *tex) 610b8e80941Smrg{ 611b8e80941Smrg blob_write_uint32(ctx->blob, tex->num_srcs); 612b8e80941Smrg blob_write_uint32(ctx->blob, tex->op); 613b8e80941Smrg blob_write_uint32(ctx->blob, tex->texture_index); 614b8e80941Smrg blob_write_uint32(ctx->blob, tex->texture_array_size); 615b8e80941Smrg blob_write_uint32(ctx->blob, tex->sampler_index); 616b8e80941Smrg blob_write_bytes(ctx->blob, tex->tg4_offsets, sizeof(tex->tg4_offsets)); 617b8e80941Smrg 618b8e80941Smrg STATIC_ASSERT(sizeof(union packed_tex_data) == sizeof(uint32_t)); 619b8e80941Smrg union packed_tex_data packed = { 620b8e80941Smrg .u.sampler_dim = tex->sampler_dim, 621b8e80941Smrg .u.dest_type = tex->dest_type, 622b8e80941Smrg .u.coord_components = tex->coord_components, 623b8e80941Smrg .u.is_array = tex->is_array, 624b8e80941Smrg .u.is_shadow = tex->is_shadow, 625b8e80941Smrg .u.is_new_style_shadow = tex->is_new_style_shadow, 626b8e80941Smrg .u.component = tex->component, 627b8e80941Smrg }; 628b8e80941Smrg blob_write_uint32(ctx->blob, packed.u32); 629b8e80941Smrg 630b8e80941Smrg write_dest(ctx, &tex->dest); 631b8e80941Smrg for (unsigned i = 0; i < tex->num_srcs; i++) { 632b8e80941Smrg blob_write_uint32(ctx->blob, tex->src[i].src_type); 633b8e80941Smrg write_src(ctx, &tex->src[i].src); 634b8e80941Smrg } 635b8e80941Smrg} 636b8e80941Smrg 637b8e80941Smrgstatic nir_tex_instr * 638b8e80941Smrgread_tex(read_ctx *ctx) 639b8e80941Smrg{ 640b8e80941Smrg unsigned num_srcs = blob_read_uint32(ctx->blob); 641b8e80941Smrg nir_tex_instr *tex = nir_tex_instr_create(ctx->nir, num_srcs); 642b8e80941Smrg 643b8e80941Smrg tex->op = blob_read_uint32(ctx->blob); 644b8e80941Smrg tex->texture_index = blob_read_uint32(ctx->blob); 645b8e80941Smrg tex->texture_array_size = blob_read_uint32(ctx->blob); 646b8e80941Smrg tex->sampler_index = blob_read_uint32(ctx->blob); 647b8e80941Smrg blob_copy_bytes(ctx->blob, tex->tg4_offsets, sizeof(tex->tg4_offsets)); 648b8e80941Smrg 649b8e80941Smrg union packed_tex_data packed; 650b8e80941Smrg packed.u32 = blob_read_uint32(ctx->blob); 651b8e80941Smrg tex->sampler_dim = packed.u.sampler_dim; 652b8e80941Smrg tex->dest_type = packed.u.dest_type; 653b8e80941Smrg tex->coord_components = packed.u.coord_components; 654b8e80941Smrg tex->is_array = packed.u.is_array; 655b8e80941Smrg tex->is_shadow = packed.u.is_shadow; 656b8e80941Smrg tex->is_new_style_shadow = packed.u.is_new_style_shadow; 657b8e80941Smrg tex->component = packed.u.component; 658b8e80941Smrg 659b8e80941Smrg read_dest(ctx, &tex->dest, &tex->instr); 660b8e80941Smrg for (unsigned i = 0; i < tex->num_srcs; i++) { 661b8e80941Smrg tex->src[i].src_type = blob_read_uint32(ctx->blob); 662b8e80941Smrg read_src(ctx, &tex->src[i].src, &tex->instr); 663b8e80941Smrg } 664b8e80941Smrg 665b8e80941Smrg return tex; 666b8e80941Smrg} 667b8e80941Smrg 668b8e80941Smrgstatic void 669b8e80941Smrgwrite_phi(write_ctx *ctx, const nir_phi_instr *phi) 670b8e80941Smrg{ 671b8e80941Smrg /* Phi nodes are special, since they may reference SSA definitions and 672b8e80941Smrg * basic blocks that don't exist yet. We leave two empty uintptr_t's here, 673b8e80941Smrg * and then store enough information so that a later fixup pass can fill 674b8e80941Smrg * them in correctly. 675b8e80941Smrg */ 676b8e80941Smrg write_dest(ctx, &phi->dest); 677b8e80941Smrg 678b8e80941Smrg blob_write_uint32(ctx->blob, exec_list_length(&phi->srcs)); 679b8e80941Smrg 680b8e80941Smrg nir_foreach_phi_src(src, phi) { 681b8e80941Smrg assert(src->src.is_ssa); 682b8e80941Smrg size_t blob_offset = blob_reserve_intptr(ctx->blob); 683b8e80941Smrg MAYBE_UNUSED size_t blob_offset2 = blob_reserve_intptr(ctx->blob); 684b8e80941Smrg assert(blob_offset + sizeof(uintptr_t) == blob_offset2); 685b8e80941Smrg write_phi_fixup fixup = { 686b8e80941Smrg .blob_offset = blob_offset, 687b8e80941Smrg .src = src->src.ssa, 688b8e80941Smrg .block = src->pred, 689b8e80941Smrg }; 690b8e80941Smrg util_dynarray_append(&ctx->phi_fixups, write_phi_fixup, fixup); 691b8e80941Smrg } 692b8e80941Smrg} 693b8e80941Smrg 694b8e80941Smrgstatic void 695b8e80941Smrgwrite_fixup_phis(write_ctx *ctx) 696b8e80941Smrg{ 697b8e80941Smrg util_dynarray_foreach(&ctx->phi_fixups, write_phi_fixup, fixup) { 698b8e80941Smrg uintptr_t *blob_ptr = (uintptr_t *)(ctx->blob->data + fixup->blob_offset); 699b8e80941Smrg blob_ptr[0] = write_lookup_object(ctx, fixup->src); 700b8e80941Smrg blob_ptr[1] = write_lookup_object(ctx, fixup->block); 701b8e80941Smrg } 702b8e80941Smrg 703b8e80941Smrg util_dynarray_clear(&ctx->phi_fixups); 704b8e80941Smrg} 705b8e80941Smrg 706b8e80941Smrgstatic nir_phi_instr * 707b8e80941Smrgread_phi(read_ctx *ctx, nir_block *blk) 708b8e80941Smrg{ 709b8e80941Smrg nir_phi_instr *phi = nir_phi_instr_create(ctx->nir); 710b8e80941Smrg 711b8e80941Smrg read_dest(ctx, &phi->dest, &phi->instr); 712b8e80941Smrg 713b8e80941Smrg unsigned num_srcs = blob_read_uint32(ctx->blob); 714b8e80941Smrg 715b8e80941Smrg /* For similar reasons as before, we just store the index directly into the 716b8e80941Smrg * pointer, and let a later pass resolve the phi sources. 717b8e80941Smrg * 718b8e80941Smrg * In order to ensure that the copied sources (which are just the indices 719b8e80941Smrg * from the blob for now) don't get inserted into the old shader's use-def 720b8e80941Smrg * lists, we have to add the phi instruction *before* we set up its 721b8e80941Smrg * sources. 722b8e80941Smrg */ 723b8e80941Smrg nir_instr_insert_after_block(blk, &phi->instr); 724b8e80941Smrg 725b8e80941Smrg for (unsigned i = 0; i < num_srcs; i++) { 726b8e80941Smrg nir_phi_src *src = ralloc(phi, nir_phi_src); 727b8e80941Smrg 728b8e80941Smrg src->src.is_ssa = true; 729b8e80941Smrg src->src.ssa = (nir_ssa_def *) blob_read_intptr(ctx->blob); 730b8e80941Smrg src->pred = (nir_block *) blob_read_intptr(ctx->blob); 731b8e80941Smrg 732b8e80941Smrg /* Since we're not letting nir_insert_instr handle use/def stuff for us, 733b8e80941Smrg * we have to set the parent_instr manually. It doesn't really matter 734b8e80941Smrg * when we do it, so we might as well do it here. 735b8e80941Smrg */ 736b8e80941Smrg src->src.parent_instr = &phi->instr; 737b8e80941Smrg 738b8e80941Smrg /* Stash it in the list of phi sources. We'll walk this list and fix up 739b8e80941Smrg * sources at the very end of read_function_impl. 740b8e80941Smrg */ 741b8e80941Smrg list_add(&src->src.use_link, &ctx->phi_srcs); 742b8e80941Smrg 743b8e80941Smrg exec_list_push_tail(&phi->srcs, &src->node); 744b8e80941Smrg } 745b8e80941Smrg 746b8e80941Smrg return phi; 747b8e80941Smrg} 748b8e80941Smrg 749b8e80941Smrgstatic void 750b8e80941Smrgread_fixup_phis(read_ctx *ctx) 751b8e80941Smrg{ 752b8e80941Smrg list_for_each_entry_safe(nir_phi_src, src, &ctx->phi_srcs, src.use_link) { 753b8e80941Smrg src->pred = read_lookup_object(ctx, (uintptr_t)src->pred); 754b8e80941Smrg src->src.ssa = read_lookup_object(ctx, (uintptr_t)src->src.ssa); 755b8e80941Smrg 756b8e80941Smrg /* Remove from this list */ 757b8e80941Smrg list_del(&src->src.use_link); 758b8e80941Smrg 759b8e80941Smrg list_addtail(&src->src.use_link, &src->src.ssa->uses); 760b8e80941Smrg } 761b8e80941Smrg assert(list_empty(&ctx->phi_srcs)); 762b8e80941Smrg} 763b8e80941Smrg 764b8e80941Smrgstatic void 765b8e80941Smrgwrite_jump(write_ctx *ctx, const nir_jump_instr *jmp) 766b8e80941Smrg{ 767b8e80941Smrg blob_write_uint32(ctx->blob, jmp->type); 768b8e80941Smrg} 769b8e80941Smrg 770b8e80941Smrgstatic nir_jump_instr * 771b8e80941Smrgread_jump(read_ctx *ctx) 772b8e80941Smrg{ 773b8e80941Smrg nir_jump_type type = blob_read_uint32(ctx->blob); 774b8e80941Smrg nir_jump_instr *jmp = nir_jump_instr_create(ctx->nir, type); 775b8e80941Smrg return jmp; 776b8e80941Smrg} 777b8e80941Smrg 778b8e80941Smrgstatic void 779b8e80941Smrgwrite_call(write_ctx *ctx, const nir_call_instr *call) 780b8e80941Smrg{ 781b8e80941Smrg blob_write_intptr(ctx->blob, write_lookup_object(ctx, call->callee)); 782b8e80941Smrg 783b8e80941Smrg for (unsigned i = 0; i < call->num_params; i++) 784b8e80941Smrg write_src(ctx, &call->params[i]); 785b8e80941Smrg} 786b8e80941Smrg 787b8e80941Smrgstatic nir_call_instr * 788b8e80941Smrgread_call(read_ctx *ctx) 789b8e80941Smrg{ 790b8e80941Smrg nir_function *callee = read_object(ctx); 791b8e80941Smrg nir_call_instr *call = nir_call_instr_create(ctx->nir, callee); 792b8e80941Smrg 793b8e80941Smrg for (unsigned i = 0; i < call->num_params; i++) 794b8e80941Smrg read_src(ctx, &call->params[i], call); 795b8e80941Smrg 796b8e80941Smrg return call; 797b8e80941Smrg} 798b8e80941Smrg 799b8e80941Smrgstatic void 800b8e80941Smrgwrite_instr(write_ctx *ctx, const nir_instr *instr) 801b8e80941Smrg{ 802b8e80941Smrg blob_write_uint32(ctx->blob, instr->type); 803b8e80941Smrg switch (instr->type) { 804b8e80941Smrg case nir_instr_type_alu: 805b8e80941Smrg write_alu(ctx, nir_instr_as_alu(instr)); 806b8e80941Smrg break; 807b8e80941Smrg case nir_instr_type_deref: 808b8e80941Smrg write_deref(ctx, nir_instr_as_deref(instr)); 809b8e80941Smrg break; 810b8e80941Smrg case nir_instr_type_intrinsic: 811b8e80941Smrg write_intrinsic(ctx, nir_instr_as_intrinsic(instr)); 812b8e80941Smrg break; 813b8e80941Smrg case nir_instr_type_load_const: 814b8e80941Smrg write_load_const(ctx, nir_instr_as_load_const(instr)); 815b8e80941Smrg break; 816b8e80941Smrg case nir_instr_type_ssa_undef: 817b8e80941Smrg write_ssa_undef(ctx, nir_instr_as_ssa_undef(instr)); 818b8e80941Smrg break; 819b8e80941Smrg case nir_instr_type_tex: 820b8e80941Smrg write_tex(ctx, nir_instr_as_tex(instr)); 821b8e80941Smrg break; 822b8e80941Smrg case nir_instr_type_phi: 823b8e80941Smrg write_phi(ctx, nir_instr_as_phi(instr)); 824b8e80941Smrg break; 825b8e80941Smrg case nir_instr_type_jump: 826b8e80941Smrg write_jump(ctx, nir_instr_as_jump(instr)); 827b8e80941Smrg break; 828b8e80941Smrg case nir_instr_type_call: 829b8e80941Smrg write_call(ctx, nir_instr_as_call(instr)); 830b8e80941Smrg break; 831b8e80941Smrg case nir_instr_type_parallel_copy: 832b8e80941Smrg unreachable("Cannot write parallel copies"); 833b8e80941Smrg default: 834b8e80941Smrg unreachable("bad instr type"); 835b8e80941Smrg } 836b8e80941Smrg} 837b8e80941Smrg 838b8e80941Smrgstatic void 839b8e80941Smrgread_instr(read_ctx *ctx, nir_block *block) 840b8e80941Smrg{ 841b8e80941Smrg nir_instr_type type = blob_read_uint32(ctx->blob); 842b8e80941Smrg nir_instr *instr; 843b8e80941Smrg switch (type) { 844b8e80941Smrg case nir_instr_type_alu: 845b8e80941Smrg instr = &read_alu(ctx)->instr; 846b8e80941Smrg break; 847b8e80941Smrg case nir_instr_type_deref: 848b8e80941Smrg instr = &read_deref(ctx)->instr; 849b8e80941Smrg break; 850b8e80941Smrg case nir_instr_type_intrinsic: 851b8e80941Smrg instr = &read_intrinsic(ctx)->instr; 852b8e80941Smrg break; 853b8e80941Smrg case nir_instr_type_load_const: 854b8e80941Smrg instr = &read_load_const(ctx)->instr; 855b8e80941Smrg break; 856b8e80941Smrg case nir_instr_type_ssa_undef: 857b8e80941Smrg instr = &read_ssa_undef(ctx)->instr; 858b8e80941Smrg break; 859b8e80941Smrg case nir_instr_type_tex: 860b8e80941Smrg instr = &read_tex(ctx)->instr; 861b8e80941Smrg break; 862b8e80941Smrg case nir_instr_type_phi: 863b8e80941Smrg /* Phi instructions are a bit of a special case when reading because we 864b8e80941Smrg * don't want inserting the instruction to automatically handle use/defs 865b8e80941Smrg * for us. Instead, we need to wait until all the blocks/instructions 866b8e80941Smrg * are read so that we can set their sources up. 867b8e80941Smrg */ 868b8e80941Smrg read_phi(ctx, block); 869b8e80941Smrg return; 870b8e80941Smrg case nir_instr_type_jump: 871b8e80941Smrg instr = &read_jump(ctx)->instr; 872b8e80941Smrg break; 873b8e80941Smrg case nir_instr_type_call: 874b8e80941Smrg instr = &read_call(ctx)->instr; 875b8e80941Smrg break; 876b8e80941Smrg case nir_instr_type_parallel_copy: 877b8e80941Smrg unreachable("Cannot read parallel copies"); 878b8e80941Smrg default: 879b8e80941Smrg unreachable("bad instr type"); 880b8e80941Smrg } 881b8e80941Smrg 882b8e80941Smrg nir_instr_insert_after_block(block, instr); 883b8e80941Smrg} 884b8e80941Smrg 885b8e80941Smrgstatic void 886b8e80941Smrgwrite_block(write_ctx *ctx, const nir_block *block) 887b8e80941Smrg{ 888b8e80941Smrg write_add_object(ctx, block); 889b8e80941Smrg blob_write_uint32(ctx->blob, exec_list_length(&block->instr_list)); 890b8e80941Smrg nir_foreach_instr(instr, block) 891b8e80941Smrg write_instr(ctx, instr); 892b8e80941Smrg} 893b8e80941Smrg 894b8e80941Smrgstatic void 895b8e80941Smrgread_block(read_ctx *ctx, struct exec_list *cf_list) 896b8e80941Smrg{ 897b8e80941Smrg /* Don't actually create a new block. Just use the one from the tail of 898b8e80941Smrg * the list. NIR guarantees that the tail of the list is a block and that 899b8e80941Smrg * no two blocks are side-by-side in the IR; It should be empty. 900b8e80941Smrg */ 901b8e80941Smrg nir_block *block = 902b8e80941Smrg exec_node_data(nir_block, exec_list_get_tail(cf_list), cf_node.node); 903b8e80941Smrg 904b8e80941Smrg read_add_object(ctx, block); 905b8e80941Smrg unsigned num_instrs = blob_read_uint32(ctx->blob); 906b8e80941Smrg for (unsigned i = 0; i < num_instrs; i++) { 907b8e80941Smrg read_instr(ctx, block); 908b8e80941Smrg } 909b8e80941Smrg} 910b8e80941Smrg 911b8e80941Smrgstatic void 912b8e80941Smrgwrite_cf_list(write_ctx *ctx, const struct exec_list *cf_list); 913b8e80941Smrg 914b8e80941Smrgstatic void 915b8e80941Smrgread_cf_list(read_ctx *ctx, struct exec_list *cf_list); 916b8e80941Smrg 917b8e80941Smrgstatic void 918b8e80941Smrgwrite_if(write_ctx *ctx, nir_if *nif) 919b8e80941Smrg{ 920b8e80941Smrg write_src(ctx, &nif->condition); 921b8e80941Smrg 922b8e80941Smrg write_cf_list(ctx, &nif->then_list); 923b8e80941Smrg write_cf_list(ctx, &nif->else_list); 924b8e80941Smrg} 925b8e80941Smrg 926b8e80941Smrgstatic void 927b8e80941Smrgread_if(read_ctx *ctx, struct exec_list *cf_list) 928b8e80941Smrg{ 929b8e80941Smrg nir_if *nif = nir_if_create(ctx->nir); 930b8e80941Smrg 931b8e80941Smrg read_src(ctx, &nif->condition, nif); 932b8e80941Smrg 933b8e80941Smrg nir_cf_node_insert_end(cf_list, &nif->cf_node); 934b8e80941Smrg 935b8e80941Smrg read_cf_list(ctx, &nif->then_list); 936b8e80941Smrg read_cf_list(ctx, &nif->else_list); 937b8e80941Smrg} 938b8e80941Smrg 939b8e80941Smrgstatic void 940b8e80941Smrgwrite_loop(write_ctx *ctx, nir_loop *loop) 941b8e80941Smrg{ 942b8e80941Smrg write_cf_list(ctx, &loop->body); 943b8e80941Smrg} 944b8e80941Smrg 945b8e80941Smrgstatic void 946b8e80941Smrgread_loop(read_ctx *ctx, struct exec_list *cf_list) 947b8e80941Smrg{ 948b8e80941Smrg nir_loop *loop = nir_loop_create(ctx->nir); 949b8e80941Smrg 950b8e80941Smrg nir_cf_node_insert_end(cf_list, &loop->cf_node); 951b8e80941Smrg 952b8e80941Smrg read_cf_list(ctx, &loop->body); 953b8e80941Smrg} 954b8e80941Smrg 955b8e80941Smrgstatic void 956b8e80941Smrgwrite_cf_node(write_ctx *ctx, nir_cf_node *cf) 957b8e80941Smrg{ 958b8e80941Smrg blob_write_uint32(ctx->blob, cf->type); 959b8e80941Smrg 960b8e80941Smrg switch (cf->type) { 961b8e80941Smrg case nir_cf_node_block: 962b8e80941Smrg write_block(ctx, nir_cf_node_as_block(cf)); 963b8e80941Smrg break; 964b8e80941Smrg case nir_cf_node_if: 965b8e80941Smrg write_if(ctx, nir_cf_node_as_if(cf)); 966b8e80941Smrg break; 967b8e80941Smrg case nir_cf_node_loop: 968b8e80941Smrg write_loop(ctx, nir_cf_node_as_loop(cf)); 969b8e80941Smrg break; 970b8e80941Smrg default: 971b8e80941Smrg unreachable("bad cf type"); 972b8e80941Smrg } 973b8e80941Smrg} 974b8e80941Smrg 975b8e80941Smrgstatic void 976b8e80941Smrgread_cf_node(read_ctx *ctx, struct exec_list *list) 977b8e80941Smrg{ 978b8e80941Smrg nir_cf_node_type type = blob_read_uint32(ctx->blob); 979b8e80941Smrg 980b8e80941Smrg switch (type) { 981b8e80941Smrg case nir_cf_node_block: 982b8e80941Smrg read_block(ctx, list); 983b8e80941Smrg break; 984b8e80941Smrg case nir_cf_node_if: 985b8e80941Smrg read_if(ctx, list); 986b8e80941Smrg break; 987b8e80941Smrg case nir_cf_node_loop: 988b8e80941Smrg read_loop(ctx, list); 989b8e80941Smrg break; 990b8e80941Smrg default: 991b8e80941Smrg unreachable("bad cf type"); 992b8e80941Smrg } 993b8e80941Smrg} 994b8e80941Smrg 995b8e80941Smrgstatic void 996b8e80941Smrgwrite_cf_list(write_ctx *ctx, const struct exec_list *cf_list) 997b8e80941Smrg{ 998b8e80941Smrg blob_write_uint32(ctx->blob, exec_list_length(cf_list)); 999b8e80941Smrg foreach_list_typed(nir_cf_node, cf, node, cf_list) { 1000b8e80941Smrg write_cf_node(ctx, cf); 1001b8e80941Smrg } 1002b8e80941Smrg} 1003b8e80941Smrg 1004b8e80941Smrgstatic void 1005b8e80941Smrgread_cf_list(read_ctx *ctx, struct exec_list *cf_list) 1006b8e80941Smrg{ 1007b8e80941Smrg uint32_t num_cf_nodes = blob_read_uint32(ctx->blob); 1008b8e80941Smrg for (unsigned i = 0; i < num_cf_nodes; i++) 1009b8e80941Smrg read_cf_node(ctx, cf_list); 1010b8e80941Smrg} 1011b8e80941Smrg 1012b8e80941Smrgstatic void 1013b8e80941Smrgwrite_function_impl(write_ctx *ctx, const nir_function_impl *fi) 1014b8e80941Smrg{ 1015b8e80941Smrg write_var_list(ctx, &fi->locals); 1016b8e80941Smrg write_reg_list(ctx, &fi->registers); 1017b8e80941Smrg blob_write_uint32(ctx->blob, fi->reg_alloc); 1018b8e80941Smrg 1019b8e80941Smrg write_cf_list(ctx, &fi->body); 1020b8e80941Smrg write_fixup_phis(ctx); 1021b8e80941Smrg} 1022b8e80941Smrg 1023b8e80941Smrgstatic nir_function_impl * 1024b8e80941Smrgread_function_impl(read_ctx *ctx, nir_function *fxn) 1025b8e80941Smrg{ 1026b8e80941Smrg nir_function_impl *fi = nir_function_impl_create_bare(ctx->nir); 1027b8e80941Smrg fi->function = fxn; 1028b8e80941Smrg 1029b8e80941Smrg read_var_list(ctx, &fi->locals); 1030b8e80941Smrg read_reg_list(ctx, &fi->registers); 1031b8e80941Smrg fi->reg_alloc = blob_read_uint32(ctx->blob); 1032b8e80941Smrg 1033b8e80941Smrg read_cf_list(ctx, &fi->body); 1034b8e80941Smrg read_fixup_phis(ctx); 1035b8e80941Smrg 1036b8e80941Smrg fi->valid_metadata = 0; 1037b8e80941Smrg 1038b8e80941Smrg return fi; 1039b8e80941Smrg} 1040b8e80941Smrg 1041b8e80941Smrgstatic void 1042b8e80941Smrgwrite_function(write_ctx *ctx, const nir_function *fxn) 1043b8e80941Smrg{ 1044b8e80941Smrg blob_write_uint32(ctx->blob, !!(fxn->name)); 1045b8e80941Smrg if (fxn->name) 1046b8e80941Smrg blob_write_string(ctx->blob, fxn->name); 1047b8e80941Smrg 1048b8e80941Smrg write_add_object(ctx, fxn); 1049b8e80941Smrg 1050b8e80941Smrg blob_write_uint32(ctx->blob, fxn->num_params); 1051b8e80941Smrg for (unsigned i = 0; i < fxn->num_params; i++) { 1052b8e80941Smrg uint32_t val = 1053b8e80941Smrg ((uint32_t)fxn->params[i].num_components) | 1054b8e80941Smrg ((uint32_t)fxn->params[i].bit_size) << 8; 1055b8e80941Smrg blob_write_uint32(ctx->blob, val); 1056b8e80941Smrg } 1057b8e80941Smrg 1058b8e80941Smrg blob_write_uint32(ctx->blob, fxn->is_entrypoint); 1059b8e80941Smrg 1060b8e80941Smrg /* At first glance, it looks like we should write the function_impl here. 1061b8e80941Smrg * However, call instructions need to be able to reference at least the 1062b8e80941Smrg * function and those will get processed as we write the function_impls. 1063b8e80941Smrg * We stop here and write function_impls as a second pass. 1064b8e80941Smrg */ 1065b8e80941Smrg} 1066b8e80941Smrg 1067b8e80941Smrgstatic void 1068b8e80941Smrgread_function(read_ctx *ctx) 1069b8e80941Smrg{ 1070b8e80941Smrg bool has_name = blob_read_uint32(ctx->blob); 1071b8e80941Smrg char *name = has_name ? blob_read_string(ctx->blob) : NULL; 1072b8e80941Smrg 1073b8e80941Smrg nir_function *fxn = nir_function_create(ctx->nir, name); 1074b8e80941Smrg 1075b8e80941Smrg read_add_object(ctx, fxn); 1076b8e80941Smrg 1077b8e80941Smrg fxn->num_params = blob_read_uint32(ctx->blob); 1078b8e80941Smrg fxn->params = ralloc_array(fxn, nir_parameter, fxn->num_params); 1079b8e80941Smrg for (unsigned i = 0; i < fxn->num_params; i++) { 1080b8e80941Smrg uint32_t val = blob_read_uint32(ctx->blob); 1081b8e80941Smrg fxn->params[i].num_components = val & 0xff; 1082b8e80941Smrg fxn->params[i].bit_size = (val >> 8) & 0xff; 1083b8e80941Smrg } 1084b8e80941Smrg 1085b8e80941Smrg fxn->is_entrypoint = blob_read_uint32(ctx->blob); 1086b8e80941Smrg} 1087b8e80941Smrg 1088b8e80941Smrgvoid 1089b8e80941Smrgnir_serialize(struct blob *blob, const nir_shader *nir) 1090b8e80941Smrg{ 1091b8e80941Smrg write_ctx ctx; 1092b8e80941Smrg ctx.remap_table = _mesa_pointer_hash_table_create(NULL); 1093b8e80941Smrg ctx.next_idx = 0; 1094b8e80941Smrg ctx.blob = blob; 1095b8e80941Smrg ctx.nir = nir; 1096b8e80941Smrg util_dynarray_init(&ctx.phi_fixups, NULL); 1097b8e80941Smrg 1098b8e80941Smrg size_t idx_size_offset = blob_reserve_intptr(blob); 1099b8e80941Smrg 1100b8e80941Smrg struct shader_info info = nir->info; 1101b8e80941Smrg uint32_t strings = 0; 1102b8e80941Smrg if (info.name) 1103b8e80941Smrg strings |= 0x1; 1104b8e80941Smrg if (info.label) 1105b8e80941Smrg strings |= 0x2; 1106b8e80941Smrg blob_write_uint32(blob, strings); 1107b8e80941Smrg if (info.name) 1108b8e80941Smrg blob_write_string(blob, info.name); 1109b8e80941Smrg if (info.label) 1110b8e80941Smrg blob_write_string(blob, info.label); 1111b8e80941Smrg info.name = info.label = NULL; 1112b8e80941Smrg blob_write_bytes(blob, (uint8_t *) &info, sizeof(info)); 1113b8e80941Smrg 1114b8e80941Smrg write_var_list(&ctx, &nir->uniforms); 1115b8e80941Smrg write_var_list(&ctx, &nir->inputs); 1116b8e80941Smrg write_var_list(&ctx, &nir->outputs); 1117b8e80941Smrg write_var_list(&ctx, &nir->shared); 1118b8e80941Smrg write_var_list(&ctx, &nir->globals); 1119b8e80941Smrg write_var_list(&ctx, &nir->system_values); 1120b8e80941Smrg 1121b8e80941Smrg blob_write_uint32(blob, nir->num_inputs); 1122b8e80941Smrg blob_write_uint32(blob, nir->num_uniforms); 1123b8e80941Smrg blob_write_uint32(blob, nir->num_outputs); 1124b8e80941Smrg blob_write_uint32(blob, nir->num_shared); 1125b8e80941Smrg blob_write_uint32(blob, nir->scratch_size); 1126b8e80941Smrg 1127b8e80941Smrg blob_write_uint32(blob, exec_list_length(&nir->functions)); 1128b8e80941Smrg nir_foreach_function(fxn, nir) { 1129b8e80941Smrg write_function(&ctx, fxn); 1130b8e80941Smrg } 1131b8e80941Smrg 1132b8e80941Smrg nir_foreach_function(fxn, nir) { 1133b8e80941Smrg write_function_impl(&ctx, fxn->impl); 1134b8e80941Smrg } 1135b8e80941Smrg 1136b8e80941Smrg blob_write_uint32(blob, nir->constant_data_size); 1137b8e80941Smrg if (nir->constant_data_size > 0) 1138b8e80941Smrg blob_write_bytes(blob, nir->constant_data, nir->constant_data_size); 1139b8e80941Smrg 1140b8e80941Smrg *(uintptr_t *)(blob->data + idx_size_offset) = ctx.next_idx; 1141b8e80941Smrg 1142b8e80941Smrg _mesa_hash_table_destroy(ctx.remap_table, NULL); 1143b8e80941Smrg util_dynarray_fini(&ctx.phi_fixups); 1144b8e80941Smrg} 1145b8e80941Smrg 1146b8e80941Smrgnir_shader * 1147b8e80941Smrgnir_deserialize(void *mem_ctx, 1148b8e80941Smrg const struct nir_shader_compiler_options *options, 1149b8e80941Smrg struct blob_reader *blob) 1150b8e80941Smrg{ 1151b8e80941Smrg read_ctx ctx; 1152b8e80941Smrg ctx.blob = blob; 1153b8e80941Smrg list_inithead(&ctx.phi_srcs); 1154b8e80941Smrg ctx.idx_table_len = blob_read_intptr(blob); 1155b8e80941Smrg ctx.idx_table = calloc(ctx.idx_table_len, sizeof(uintptr_t)); 1156b8e80941Smrg ctx.next_idx = 0; 1157b8e80941Smrg 1158b8e80941Smrg uint32_t strings = blob_read_uint32(blob); 1159b8e80941Smrg char *name = (strings & 0x1) ? blob_read_string(blob) : NULL; 1160b8e80941Smrg char *label = (strings & 0x2) ? blob_read_string(blob) : NULL; 1161b8e80941Smrg 1162b8e80941Smrg struct shader_info info; 1163b8e80941Smrg blob_copy_bytes(blob, (uint8_t *) &info, sizeof(info)); 1164b8e80941Smrg 1165b8e80941Smrg ctx.nir = nir_shader_create(mem_ctx, info.stage, options, NULL); 1166b8e80941Smrg 1167b8e80941Smrg info.name = name ? ralloc_strdup(ctx.nir, name) : NULL; 1168b8e80941Smrg info.label = label ? ralloc_strdup(ctx.nir, label) : NULL; 1169b8e80941Smrg 1170b8e80941Smrg ctx.nir->info = info; 1171b8e80941Smrg 1172b8e80941Smrg read_var_list(&ctx, &ctx.nir->uniforms); 1173b8e80941Smrg read_var_list(&ctx, &ctx.nir->inputs); 1174b8e80941Smrg read_var_list(&ctx, &ctx.nir->outputs); 1175b8e80941Smrg read_var_list(&ctx, &ctx.nir->shared); 1176b8e80941Smrg read_var_list(&ctx, &ctx.nir->globals); 1177b8e80941Smrg read_var_list(&ctx, &ctx.nir->system_values); 1178b8e80941Smrg 1179b8e80941Smrg ctx.nir->num_inputs = blob_read_uint32(blob); 1180b8e80941Smrg ctx.nir->num_uniforms = blob_read_uint32(blob); 1181b8e80941Smrg ctx.nir->num_outputs = blob_read_uint32(blob); 1182b8e80941Smrg ctx.nir->num_shared = blob_read_uint32(blob); 1183b8e80941Smrg ctx.nir->scratch_size = blob_read_uint32(blob); 1184b8e80941Smrg 1185b8e80941Smrg unsigned num_functions = blob_read_uint32(blob); 1186b8e80941Smrg for (unsigned i = 0; i < num_functions; i++) 1187b8e80941Smrg read_function(&ctx); 1188b8e80941Smrg 1189b8e80941Smrg nir_foreach_function(fxn, ctx.nir) 1190b8e80941Smrg fxn->impl = read_function_impl(&ctx, fxn); 1191b8e80941Smrg 1192b8e80941Smrg ctx.nir->constant_data_size = blob_read_uint32(blob); 1193b8e80941Smrg if (ctx.nir->constant_data_size > 0) { 1194b8e80941Smrg ctx.nir->constant_data = 1195b8e80941Smrg ralloc_size(ctx.nir, ctx.nir->constant_data_size); 1196b8e80941Smrg blob_copy_bytes(blob, ctx.nir->constant_data, 1197b8e80941Smrg ctx.nir->constant_data_size); 1198b8e80941Smrg } 1199b8e80941Smrg 1200b8e80941Smrg free(ctx.idx_table); 1201b8e80941Smrg 1202b8e80941Smrg return ctx.nir; 1203b8e80941Smrg} 1204b8e80941Smrg 1205b8e80941Smrgnir_shader * 1206b8e80941Smrgnir_shader_serialize_deserialize(void *mem_ctx, nir_shader *s) 1207b8e80941Smrg{ 1208b8e80941Smrg const struct nir_shader_compiler_options *options = s->options; 1209b8e80941Smrg 1210b8e80941Smrg struct blob writer; 1211b8e80941Smrg blob_init(&writer); 1212b8e80941Smrg nir_serialize(&writer, s); 1213b8e80941Smrg ralloc_free(s); 1214b8e80941Smrg 1215b8e80941Smrg struct blob_reader reader; 1216b8e80941Smrg blob_reader_init(&reader, writer.data, writer.size); 1217b8e80941Smrg nir_shader *ns = nir_deserialize(mem_ctx, options, &reader); 1218b8e80941Smrg 1219b8e80941Smrg blob_finish(&writer); 1220b8e80941Smrg 1221b8e80941Smrg return ns; 1222b8e80941Smrg} 1223