101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2014 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2101e04c3fSmrg * DEALINGS IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg/**
2501e04c3fSmrg * \file serialize.cpp
2601e04c3fSmrg *
2701e04c3fSmrg * GLSL serialization
2801e04c3fSmrg *
2901e04c3fSmrg * Supports serializing and deserializing glsl programs using a blob.
3001e04c3fSmrg */
3101e04c3fSmrg
3201e04c3fSmrg#include "compiler/glsl_types.h"
3301e04c3fSmrg#include "compiler/shader_info.h"
3401e04c3fSmrg#include "ir_uniform.h"
3501e04c3fSmrg#include "main/mtypes.h"
3601e04c3fSmrg#include "main/shaderobj.h"
3701e04c3fSmrg#include "program/program.h"
3801e04c3fSmrg#include "string_to_uint_map.h"
3901e04c3fSmrg#include "util/bitscan.h"
4001e04c3fSmrg
4101e04c3fSmrg
4201e04c3fSmrgstatic void
4301e04c3fSmrgwrite_subroutines(struct blob *metadata, struct gl_shader_program *prog)
4401e04c3fSmrg{
4501e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
4601e04c3fSmrg      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
4701e04c3fSmrg      if (!sh)
4801e04c3fSmrg         continue;
4901e04c3fSmrg
5001e04c3fSmrg      struct gl_program *glprog = sh->Program;
5101e04c3fSmrg
5201e04c3fSmrg      blob_write_uint32(metadata, glprog->sh.NumSubroutineUniforms);
5301e04c3fSmrg      blob_write_uint32(metadata, glprog->sh.MaxSubroutineFunctionIndex);
5401e04c3fSmrg      blob_write_uint32(metadata, glprog->sh.NumSubroutineFunctions);
5501e04c3fSmrg      for (unsigned j = 0; j < glprog->sh.NumSubroutineFunctions; j++) {
5601e04c3fSmrg         int num_types = glprog->sh.SubroutineFunctions[j].num_compat_types;
5701e04c3fSmrg
5801e04c3fSmrg         blob_write_string(metadata, glprog->sh.SubroutineFunctions[j].name);
5901e04c3fSmrg         blob_write_uint32(metadata, glprog->sh.SubroutineFunctions[j].index);
6001e04c3fSmrg         blob_write_uint32(metadata, num_types);
6101e04c3fSmrg
6201e04c3fSmrg         for (int k = 0; k < num_types; k++) {
6301e04c3fSmrg            encode_type_to_blob(metadata,
6401e04c3fSmrg                                glprog->sh.SubroutineFunctions[j].types[k]);
6501e04c3fSmrg         }
6601e04c3fSmrg      }
6701e04c3fSmrg   }
6801e04c3fSmrg}
6901e04c3fSmrg
7001e04c3fSmrgstatic void
7101e04c3fSmrgread_subroutines(struct blob_reader *metadata, struct gl_shader_program *prog)
7201e04c3fSmrg{
7301e04c3fSmrg   struct gl_subroutine_function *subs;
7401e04c3fSmrg
7501e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
7601e04c3fSmrg      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
7701e04c3fSmrg      if (!sh)
7801e04c3fSmrg         continue;
7901e04c3fSmrg
8001e04c3fSmrg      struct gl_program *glprog = sh->Program;
8101e04c3fSmrg
8201e04c3fSmrg      glprog->sh.NumSubroutineUniforms = blob_read_uint32(metadata);
8301e04c3fSmrg      glprog->sh.MaxSubroutineFunctionIndex = blob_read_uint32(metadata);
8401e04c3fSmrg      glprog->sh.NumSubroutineFunctions = blob_read_uint32(metadata);
8501e04c3fSmrg
8601e04c3fSmrg      subs = rzalloc_array(prog, struct gl_subroutine_function,
8701e04c3fSmrg                           glprog->sh.NumSubroutineFunctions);
8801e04c3fSmrg      glprog->sh.SubroutineFunctions = subs;
8901e04c3fSmrg
9001e04c3fSmrg      for (unsigned j = 0; j < glprog->sh.NumSubroutineFunctions; j++) {
9101e04c3fSmrg         subs[j].name = ralloc_strdup(prog, blob_read_string (metadata));
9201e04c3fSmrg         subs[j].index = (int) blob_read_uint32(metadata);
9301e04c3fSmrg         subs[j].num_compat_types = (int) blob_read_uint32(metadata);
9401e04c3fSmrg
9501e04c3fSmrg         subs[j].types = rzalloc_array(prog, const struct glsl_type *,
9601e04c3fSmrg                                       subs[j].num_compat_types);
9701e04c3fSmrg         for (int k = 0; k < subs[j].num_compat_types; k++) {
9801e04c3fSmrg            subs[j].types[k] = decode_type_from_blob(metadata);
9901e04c3fSmrg         }
10001e04c3fSmrg      }
10101e04c3fSmrg   }
10201e04c3fSmrg}
10301e04c3fSmrg
10401e04c3fSmrgstatic void
10501e04c3fSmrgwrite_buffer_block(struct blob *metadata, struct gl_uniform_block *b)
10601e04c3fSmrg{
10701e04c3fSmrg   blob_write_string(metadata, b->Name);
10801e04c3fSmrg   blob_write_uint32(metadata, b->NumUniforms);
10901e04c3fSmrg   blob_write_uint32(metadata, b->Binding);
11001e04c3fSmrg   blob_write_uint32(metadata, b->UniformBufferSize);
11101e04c3fSmrg   blob_write_uint32(metadata, b->stageref);
11201e04c3fSmrg
11301e04c3fSmrg   for (unsigned j = 0; j < b->NumUniforms; j++) {
11401e04c3fSmrg      blob_write_string(metadata, b->Uniforms[j].Name);
11501e04c3fSmrg      blob_write_string(metadata, b->Uniforms[j].IndexName);
11601e04c3fSmrg      encode_type_to_blob(metadata, b->Uniforms[j].Type);
11701e04c3fSmrg      blob_write_uint32(metadata, b->Uniforms[j].Offset);
11801e04c3fSmrg   }
11901e04c3fSmrg}
12001e04c3fSmrg
12101e04c3fSmrgstatic void
12201e04c3fSmrgwrite_buffer_blocks(struct blob *metadata, struct gl_shader_program *prog)
12301e04c3fSmrg{
12401e04c3fSmrg   blob_write_uint32(metadata, prog->data->NumUniformBlocks);
12501e04c3fSmrg   blob_write_uint32(metadata, prog->data->NumShaderStorageBlocks);
12601e04c3fSmrg
12701e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
12801e04c3fSmrg      write_buffer_block(metadata, &prog->data->UniformBlocks[i]);
12901e04c3fSmrg   }
13001e04c3fSmrg
13101e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
13201e04c3fSmrg      write_buffer_block(metadata, &prog->data->ShaderStorageBlocks[i]);
13301e04c3fSmrg   }
13401e04c3fSmrg
13501e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
13601e04c3fSmrg      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
13701e04c3fSmrg      if (!sh)
13801e04c3fSmrg         continue;
13901e04c3fSmrg
14001e04c3fSmrg      struct gl_program *glprog = sh->Program;
14101e04c3fSmrg
1427ec681f3Smrg      blob_write_uint32(metadata, glprog->sh.NumUniformBlocks);
14301e04c3fSmrg      blob_write_uint32(metadata, glprog->info.num_ssbos);
14401e04c3fSmrg
1457ec681f3Smrg      for (unsigned j = 0; j < glprog->sh.NumUniformBlocks; j++) {
14601e04c3fSmrg         uint32_t offset =
14701e04c3fSmrg            glprog->sh.UniformBlocks[j] - prog->data->UniformBlocks;
14801e04c3fSmrg         blob_write_uint32(metadata, offset);
14901e04c3fSmrg      }
15001e04c3fSmrg
15101e04c3fSmrg      for (unsigned j = 0; j < glprog->info.num_ssbos; j++) {
15201e04c3fSmrg         uint32_t offset = glprog->sh.ShaderStorageBlocks[j] -
15301e04c3fSmrg            prog->data->ShaderStorageBlocks;
15401e04c3fSmrg         blob_write_uint32(metadata, offset);
15501e04c3fSmrg      }
15601e04c3fSmrg   }
15701e04c3fSmrg}
15801e04c3fSmrg
15901e04c3fSmrgstatic void
16001e04c3fSmrgread_buffer_block(struct blob_reader *metadata, struct gl_uniform_block *b,
16101e04c3fSmrg                  struct gl_shader_program *prog)
16201e04c3fSmrg{
16301e04c3fSmrg      b->Name = ralloc_strdup(prog->data, blob_read_string (metadata));
16401e04c3fSmrg      b->NumUniforms = blob_read_uint32(metadata);
16501e04c3fSmrg      b->Binding = blob_read_uint32(metadata);
16601e04c3fSmrg      b->UniformBufferSize = blob_read_uint32(metadata);
16701e04c3fSmrg      b->stageref = blob_read_uint32(metadata);
16801e04c3fSmrg
16901e04c3fSmrg      b->Uniforms =
17001e04c3fSmrg         rzalloc_array(prog->data, struct gl_uniform_buffer_variable,
17101e04c3fSmrg                       b->NumUniforms);
17201e04c3fSmrg      for (unsigned j = 0; j < b->NumUniforms; j++) {
17301e04c3fSmrg         b->Uniforms[j].Name = ralloc_strdup(prog->data,
17401e04c3fSmrg                                             blob_read_string (metadata));
17501e04c3fSmrg
17601e04c3fSmrg         char *index_name = blob_read_string(metadata);
17701e04c3fSmrg         if (strcmp(b->Uniforms[j].Name, index_name) == 0) {
17801e04c3fSmrg            b->Uniforms[j].IndexName = b->Uniforms[j].Name;
17901e04c3fSmrg         } else {
18001e04c3fSmrg            b->Uniforms[j].IndexName = ralloc_strdup(prog->data, index_name);
18101e04c3fSmrg         }
18201e04c3fSmrg
18301e04c3fSmrg         b->Uniforms[j].Type = decode_type_from_blob(metadata);
18401e04c3fSmrg         b->Uniforms[j].Offset = blob_read_uint32(metadata);
18501e04c3fSmrg      }
18601e04c3fSmrg}
18701e04c3fSmrg
18801e04c3fSmrgstatic void
18901e04c3fSmrgread_buffer_blocks(struct blob_reader *metadata,
19001e04c3fSmrg                   struct gl_shader_program *prog)
19101e04c3fSmrg{
19201e04c3fSmrg   prog->data->NumUniformBlocks = blob_read_uint32(metadata);
19301e04c3fSmrg   prog->data->NumShaderStorageBlocks = blob_read_uint32(metadata);
19401e04c3fSmrg
19501e04c3fSmrg   prog->data->UniformBlocks =
19601e04c3fSmrg      rzalloc_array(prog->data, struct gl_uniform_block,
19701e04c3fSmrg                    prog->data->NumUniformBlocks);
19801e04c3fSmrg
19901e04c3fSmrg   prog->data->ShaderStorageBlocks =
20001e04c3fSmrg      rzalloc_array(prog->data, struct gl_uniform_block,
20101e04c3fSmrg                    prog->data->NumShaderStorageBlocks);
20201e04c3fSmrg
20301e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
20401e04c3fSmrg      read_buffer_block(metadata, &prog->data->UniformBlocks[i], prog);
20501e04c3fSmrg   }
20601e04c3fSmrg
20701e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
20801e04c3fSmrg      read_buffer_block(metadata, &prog->data->ShaderStorageBlocks[i], prog);
20901e04c3fSmrg   }
21001e04c3fSmrg
21101e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
21201e04c3fSmrg      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
21301e04c3fSmrg      if (!sh)
21401e04c3fSmrg         continue;
21501e04c3fSmrg
21601e04c3fSmrg      struct gl_program *glprog = sh->Program;
21701e04c3fSmrg
2187ec681f3Smrg      glprog->sh.NumUniformBlocks = blob_read_uint32(metadata);
21901e04c3fSmrg      glprog->info.num_ssbos = blob_read_uint32(metadata);
22001e04c3fSmrg
22101e04c3fSmrg      glprog->sh.UniformBlocks =
2227ec681f3Smrg         rzalloc_array(glprog, gl_uniform_block *, glprog->sh.NumUniformBlocks);
22301e04c3fSmrg      glprog->sh.ShaderStorageBlocks =
22401e04c3fSmrg         rzalloc_array(glprog, gl_uniform_block *, glprog->info.num_ssbos);
22501e04c3fSmrg
2267ec681f3Smrg      for (unsigned j = 0; j < glprog->sh.NumUniformBlocks; j++) {
22701e04c3fSmrg         uint32_t offset = blob_read_uint32(metadata);
22801e04c3fSmrg         glprog->sh.UniformBlocks[j] = prog->data->UniformBlocks + offset;
22901e04c3fSmrg      }
23001e04c3fSmrg
23101e04c3fSmrg      for (unsigned j = 0; j < glprog->info.num_ssbos; j++) {
23201e04c3fSmrg         uint32_t offset = blob_read_uint32(metadata);
23301e04c3fSmrg         glprog->sh.ShaderStorageBlocks[j] =
23401e04c3fSmrg            prog->data->ShaderStorageBlocks + offset;
23501e04c3fSmrg      }
23601e04c3fSmrg   }
23701e04c3fSmrg}
23801e04c3fSmrg
23901e04c3fSmrgstatic void
24001e04c3fSmrgwrite_atomic_buffers(struct blob *metadata, struct gl_shader_program *prog)
24101e04c3fSmrg{
24201e04c3fSmrg   blob_write_uint32(metadata, prog->data->NumAtomicBuffers);
24301e04c3fSmrg
24401e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
24501e04c3fSmrg      if (prog->_LinkedShaders[i]) {
24601e04c3fSmrg         struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
24701e04c3fSmrg         blob_write_uint32(metadata, glprog->info.num_abos);
24801e04c3fSmrg      }
24901e04c3fSmrg   }
25001e04c3fSmrg
25101e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
25201e04c3fSmrg      blob_write_uint32(metadata, prog->data->AtomicBuffers[i].Binding);
25301e04c3fSmrg      blob_write_uint32(metadata, prog->data->AtomicBuffers[i].MinimumSize);
25401e04c3fSmrg      blob_write_uint32(metadata, prog->data->AtomicBuffers[i].NumUniforms);
25501e04c3fSmrg
25601e04c3fSmrg      blob_write_bytes(metadata, prog->data->AtomicBuffers[i].StageReferences,
25701e04c3fSmrg                       sizeof(prog->data->AtomicBuffers[i].StageReferences));
25801e04c3fSmrg
25901e04c3fSmrg      for (unsigned j = 0; j < prog->data->AtomicBuffers[i].NumUniforms; j++) {
26001e04c3fSmrg         blob_write_uint32(metadata, prog->data->AtomicBuffers[i].Uniforms[j]);
26101e04c3fSmrg      }
26201e04c3fSmrg   }
26301e04c3fSmrg}
26401e04c3fSmrg
26501e04c3fSmrgstatic void
26601e04c3fSmrgread_atomic_buffers(struct blob_reader *metadata,
26701e04c3fSmrg                     struct gl_shader_program *prog)
26801e04c3fSmrg{
26901e04c3fSmrg   prog->data->NumAtomicBuffers = blob_read_uint32(metadata);
27001e04c3fSmrg   prog->data->AtomicBuffers =
27101e04c3fSmrg      rzalloc_array(prog, gl_active_atomic_buffer,
27201e04c3fSmrg                    prog->data->NumAtomicBuffers);
27301e04c3fSmrg
27401e04c3fSmrg   struct gl_active_atomic_buffer **stage_buff_list[MESA_SHADER_STAGES];
27501e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
27601e04c3fSmrg      if (prog->_LinkedShaders[i]) {
27701e04c3fSmrg         struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
27801e04c3fSmrg
27901e04c3fSmrg         glprog->info.num_abos = blob_read_uint32(metadata);
28001e04c3fSmrg         glprog->sh.AtomicBuffers =
28101e04c3fSmrg            rzalloc_array(glprog, gl_active_atomic_buffer *,
28201e04c3fSmrg                          glprog->info.num_abos);
28301e04c3fSmrg         stage_buff_list[i] = glprog->sh.AtomicBuffers;
28401e04c3fSmrg      }
28501e04c3fSmrg   }
28601e04c3fSmrg
28701e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
28801e04c3fSmrg      prog->data->AtomicBuffers[i].Binding = blob_read_uint32(metadata);
28901e04c3fSmrg      prog->data->AtomicBuffers[i].MinimumSize = blob_read_uint32(metadata);
29001e04c3fSmrg      prog->data->AtomicBuffers[i].NumUniforms = blob_read_uint32(metadata);
29101e04c3fSmrg
29201e04c3fSmrg      blob_copy_bytes(metadata,
29301e04c3fSmrg                      (uint8_t *) &prog->data->AtomicBuffers[i].StageReferences,
29401e04c3fSmrg                      sizeof(prog->data->AtomicBuffers[i].StageReferences));
29501e04c3fSmrg
29601e04c3fSmrg      prog->data->AtomicBuffers[i].Uniforms = rzalloc_array(prog, unsigned,
29701e04c3fSmrg         prog->data->AtomicBuffers[i].NumUniforms);
29801e04c3fSmrg
29901e04c3fSmrg      for (unsigned j = 0; j < prog->data->AtomicBuffers[i].NumUniforms; j++) {
30001e04c3fSmrg         prog->data->AtomicBuffers[i].Uniforms[j] = blob_read_uint32(metadata);
30101e04c3fSmrg      }
30201e04c3fSmrg
30301e04c3fSmrg      for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
30401e04c3fSmrg         if (prog->data->AtomicBuffers[i].StageReferences[j]) {
30501e04c3fSmrg            *stage_buff_list[j] = &prog->data->AtomicBuffers[i];
30601e04c3fSmrg            stage_buff_list[j]++;
30701e04c3fSmrg         }
30801e04c3fSmrg      }
30901e04c3fSmrg   }
31001e04c3fSmrg}
31101e04c3fSmrg
31201e04c3fSmrgstatic void
31301e04c3fSmrgwrite_xfb(struct blob *metadata, struct gl_shader_program *shProg)
31401e04c3fSmrg{
31501e04c3fSmrg   struct gl_program *prog = shProg->last_vert_prog;
31601e04c3fSmrg
31701e04c3fSmrg   if (!prog) {
31801e04c3fSmrg      blob_write_uint32(metadata, ~0u);
31901e04c3fSmrg      return;
32001e04c3fSmrg   }
32101e04c3fSmrg
32201e04c3fSmrg   struct gl_transform_feedback_info *ltf = prog->sh.LinkedTransformFeedback;
32301e04c3fSmrg
32401e04c3fSmrg   blob_write_uint32(metadata, prog->info.stage);
32501e04c3fSmrg
32601e04c3fSmrg   /* Data set by glTransformFeedbackVaryings. */
32701e04c3fSmrg   blob_write_uint32(metadata, shProg->TransformFeedback.BufferMode);
32801e04c3fSmrg   blob_write_bytes(metadata, shProg->TransformFeedback.BufferStride,
32901e04c3fSmrg                    sizeof(shProg->TransformFeedback.BufferStride));
33001e04c3fSmrg   blob_write_uint32(metadata, shProg->TransformFeedback.NumVarying);
33101e04c3fSmrg   for (unsigned i = 0; i < shProg->TransformFeedback.NumVarying; i++)
33201e04c3fSmrg      blob_write_string(metadata, shProg->TransformFeedback.VaryingNames[i]);
33301e04c3fSmrg
33401e04c3fSmrg   blob_write_uint32(metadata, ltf->NumOutputs);
33501e04c3fSmrg   blob_write_uint32(metadata, ltf->ActiveBuffers);
33601e04c3fSmrg   blob_write_uint32(metadata, ltf->NumVarying);
33701e04c3fSmrg
33801e04c3fSmrg   blob_write_bytes(metadata, ltf->Outputs,
33901e04c3fSmrg                    sizeof(struct gl_transform_feedback_output) *
34001e04c3fSmrg                       ltf->NumOutputs);
34101e04c3fSmrg
34201e04c3fSmrg   for (int i = 0; i < ltf->NumVarying; i++) {
34301e04c3fSmrg      blob_write_string(metadata, ltf->Varyings[i].Name);
34401e04c3fSmrg      blob_write_uint32(metadata, ltf->Varyings[i].Type);
34501e04c3fSmrg      blob_write_uint32(metadata, ltf->Varyings[i].BufferIndex);
34601e04c3fSmrg      blob_write_uint32(metadata, ltf->Varyings[i].Size);
34701e04c3fSmrg      blob_write_uint32(metadata, ltf->Varyings[i].Offset);
34801e04c3fSmrg   }
34901e04c3fSmrg
35001e04c3fSmrg   blob_write_bytes(metadata, ltf->Buffers,
35101e04c3fSmrg                    sizeof(struct gl_transform_feedback_buffer) *
35201e04c3fSmrg                       MAX_FEEDBACK_BUFFERS);
35301e04c3fSmrg}
35401e04c3fSmrg
35501e04c3fSmrgstatic void
35601e04c3fSmrgread_xfb(struct blob_reader *metadata, struct gl_shader_program *shProg)
35701e04c3fSmrg{
35801e04c3fSmrg   unsigned xfb_stage = blob_read_uint32(metadata);
35901e04c3fSmrg
36001e04c3fSmrg   if (xfb_stage == ~0u)
36101e04c3fSmrg      return;
36201e04c3fSmrg
36301e04c3fSmrg   if (shProg->TransformFeedback.VaryingNames)  {
36401e04c3fSmrg      for (unsigned i = 0; i < shProg->TransformFeedback.NumVarying; ++i)
36501e04c3fSmrg         free(shProg->TransformFeedback.VaryingNames[i]);
36601e04c3fSmrg   }
36701e04c3fSmrg
36801e04c3fSmrg   /* Data set by glTransformFeedbackVaryings. */
36901e04c3fSmrg   shProg->TransformFeedback.BufferMode = blob_read_uint32(metadata);
37001e04c3fSmrg   blob_copy_bytes(metadata, &shProg->TransformFeedback.BufferStride,
37101e04c3fSmrg                   sizeof(shProg->TransformFeedback.BufferStride));
37201e04c3fSmrg   shProg->TransformFeedback.NumVarying = blob_read_uint32(metadata);
37301e04c3fSmrg
37401e04c3fSmrg   shProg->TransformFeedback.VaryingNames = (char **)
37501e04c3fSmrg      realloc(shProg->TransformFeedback.VaryingNames,
37601e04c3fSmrg             shProg->TransformFeedback.NumVarying * sizeof(GLchar *));
37701e04c3fSmrg   /* Note, malloc used with VaryingNames. */
37801e04c3fSmrg   for (unsigned i = 0; i < shProg->TransformFeedback.NumVarying; i++)
37901e04c3fSmrg      shProg->TransformFeedback.VaryingNames[i] =
38001e04c3fSmrg         strdup(blob_read_string(metadata));
38101e04c3fSmrg
38201e04c3fSmrg   struct gl_program *prog = shProg->_LinkedShaders[xfb_stage]->Program;
38301e04c3fSmrg   struct gl_transform_feedback_info *ltf =
38401e04c3fSmrg      rzalloc(prog, struct gl_transform_feedback_info);
38501e04c3fSmrg
38601e04c3fSmrg   prog->sh.LinkedTransformFeedback = ltf;
38701e04c3fSmrg   shProg->last_vert_prog = prog;
38801e04c3fSmrg
38901e04c3fSmrg   ltf->NumOutputs = blob_read_uint32(metadata);
39001e04c3fSmrg   ltf->ActiveBuffers = blob_read_uint32(metadata);
39101e04c3fSmrg   ltf->NumVarying = blob_read_uint32(metadata);
39201e04c3fSmrg
39301e04c3fSmrg   ltf->Outputs = rzalloc_array(prog, struct gl_transform_feedback_output,
39401e04c3fSmrg                                ltf->NumOutputs);
39501e04c3fSmrg
39601e04c3fSmrg   blob_copy_bytes(metadata, (uint8_t *) ltf->Outputs,
39701e04c3fSmrg                   sizeof(struct gl_transform_feedback_output) *
39801e04c3fSmrg                      ltf->NumOutputs);
39901e04c3fSmrg
40001e04c3fSmrg   ltf->Varyings = rzalloc_array(prog,
40101e04c3fSmrg                                 struct gl_transform_feedback_varying_info,
40201e04c3fSmrg                                 ltf->NumVarying);
40301e04c3fSmrg
40401e04c3fSmrg   for (int i = 0; i < ltf->NumVarying; i++) {
40501e04c3fSmrg      ltf->Varyings[i].Name = ralloc_strdup(prog, blob_read_string(metadata));
40601e04c3fSmrg      ltf->Varyings[i].Type = blob_read_uint32(metadata);
40701e04c3fSmrg      ltf->Varyings[i].BufferIndex = blob_read_uint32(metadata);
40801e04c3fSmrg      ltf->Varyings[i].Size = blob_read_uint32(metadata);
40901e04c3fSmrg      ltf->Varyings[i].Offset = blob_read_uint32(metadata);
41001e04c3fSmrg   }
41101e04c3fSmrg
41201e04c3fSmrg   blob_copy_bytes(metadata, (uint8_t *) ltf->Buffers,
41301e04c3fSmrg                   sizeof(struct gl_transform_feedback_buffer) *
41401e04c3fSmrg                      MAX_FEEDBACK_BUFFERS);
41501e04c3fSmrg}
41601e04c3fSmrg
41701e04c3fSmrgstatic bool
41801e04c3fSmrghas_uniform_storage(struct gl_shader_program *prog, unsigned idx)
41901e04c3fSmrg{
42001e04c3fSmrg   if (!prog->data->UniformStorage[idx].builtin &&
42101e04c3fSmrg       !prog->data->UniformStorage[idx].is_shader_storage &&
42201e04c3fSmrg       prog->data->UniformStorage[idx].block_index == -1)
42301e04c3fSmrg      return true;
42401e04c3fSmrg
42501e04c3fSmrg   return false;
42601e04c3fSmrg}
42701e04c3fSmrg
42801e04c3fSmrgstatic void
42901e04c3fSmrgwrite_uniforms(struct blob *metadata, struct gl_shader_program *prog)
43001e04c3fSmrg{
43101e04c3fSmrg   blob_write_uint32(metadata, prog->SamplersValidated);
43201e04c3fSmrg   blob_write_uint32(metadata, prog->data->NumUniformStorage);
43301e04c3fSmrg   blob_write_uint32(metadata, prog->data->NumUniformDataSlots);
43401e04c3fSmrg
43501e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
43601e04c3fSmrg      encode_type_to_blob(metadata, prog->data->UniformStorage[i].type);
43701e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].array_elements);
4387ec681f3Smrg      if (prog->data->UniformStorage[i].name) {
4397ec681f3Smrg         blob_write_string(metadata, prog->data->UniformStorage[i].name);
4407ec681f3Smrg      } else {
4417ec681f3Smrg         blob_write_string(metadata, "");
4427ec681f3Smrg      }
44301e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].builtin);
44401e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].remap_location);
44501e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].block_index);
44601e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].atomic_buffer_index);
44701e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].offset);
44801e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].array_stride);
44901e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].hidden);
45001e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].is_shader_storage);
45101e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].active_shader_mask);
45201e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].matrix_stride);
45301e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].row_major);
45401e04c3fSmrg      blob_write_uint32(metadata, prog->data->UniformStorage[i].is_bindless);
45501e04c3fSmrg      blob_write_uint32(metadata,
45601e04c3fSmrg                        prog->data->UniformStorage[i].num_compatible_subroutines);
45701e04c3fSmrg      blob_write_uint32(metadata,
45801e04c3fSmrg                        prog->data->UniformStorage[i].top_level_array_size);
45901e04c3fSmrg      blob_write_uint32(metadata,
46001e04c3fSmrg                        prog->data->UniformStorage[i].top_level_array_stride);
46101e04c3fSmrg
46201e04c3fSmrg     if (has_uniform_storage(prog, i)) {
46301e04c3fSmrg         blob_write_uint32(metadata, prog->data->UniformStorage[i].storage -
46401e04c3fSmrg                                     prog->data->UniformDataSlots);
46501e04c3fSmrg      }
46601e04c3fSmrg
46701e04c3fSmrg      blob_write_bytes(metadata, prog->data->UniformStorage[i].opaque,
46801e04c3fSmrg                       sizeof(prog->data->UniformStorage[i].opaque));
46901e04c3fSmrg   }
47001e04c3fSmrg
47101e04c3fSmrg   /* Here we cache all uniform values. We do this to retain values for
47201e04c3fSmrg    * uniforms with initialisers and also hidden uniforms that may be lowered
47301e04c3fSmrg    * constant arrays. We could possibly just store the values we need but for
47401e04c3fSmrg    * now we just store everything.
47501e04c3fSmrg    */
47601e04c3fSmrg   blob_write_uint32(metadata, prog->data->NumHiddenUniforms);
47701e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
47801e04c3fSmrg      if (has_uniform_storage(prog, i)) {
47901e04c3fSmrg         unsigned vec_size =
48001e04c3fSmrg            prog->data->UniformStorage[i].type->component_slots() *
48101e04c3fSmrg            MAX2(prog->data->UniformStorage[i].array_elements, 1);
48201e04c3fSmrg         unsigned slot =
48301e04c3fSmrg            prog->data->UniformStorage[i].storage -
48401e04c3fSmrg            prog->data->UniformDataSlots;
48501e04c3fSmrg         blob_write_bytes(metadata, &prog->data->UniformDataDefaults[slot],
48601e04c3fSmrg                          sizeof(union gl_constant_value) * vec_size);
48701e04c3fSmrg      }
48801e04c3fSmrg   }
48901e04c3fSmrg}
49001e04c3fSmrg
49101e04c3fSmrgstatic void
49201e04c3fSmrgread_uniforms(struct blob_reader *metadata, struct gl_shader_program *prog)
49301e04c3fSmrg{
49401e04c3fSmrg   struct gl_uniform_storage *uniforms;
49501e04c3fSmrg   union gl_constant_value *data;
49601e04c3fSmrg
49701e04c3fSmrg   prog->SamplersValidated = blob_read_uint32(metadata);
49801e04c3fSmrg   prog->data->NumUniformStorage = blob_read_uint32(metadata);
49901e04c3fSmrg   prog->data->NumUniformDataSlots = blob_read_uint32(metadata);
50001e04c3fSmrg
50101e04c3fSmrg   uniforms = rzalloc_array(prog->data, struct gl_uniform_storage,
50201e04c3fSmrg                            prog->data->NumUniformStorage);
50301e04c3fSmrg   prog->data->UniformStorage = uniforms;
50401e04c3fSmrg
50501e04c3fSmrg   data = rzalloc_array(uniforms, union gl_constant_value,
50601e04c3fSmrg                        prog->data->NumUniformDataSlots);
50701e04c3fSmrg   prog->data->UniformDataSlots = data;
50801e04c3fSmrg   prog->data->UniformDataDefaults =
50901e04c3fSmrg      rzalloc_array(uniforms, union gl_constant_value,
51001e04c3fSmrg                    prog->data->NumUniformDataSlots);
51101e04c3fSmrg
51201e04c3fSmrg   prog->UniformHash = new string_to_uint_map;
51301e04c3fSmrg
51401e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
51501e04c3fSmrg      uniforms[i].type = decode_type_from_blob(metadata);
51601e04c3fSmrg      uniforms[i].array_elements = blob_read_uint32(metadata);
51701e04c3fSmrg      uniforms[i].name = ralloc_strdup(prog, blob_read_string (metadata));
51801e04c3fSmrg      uniforms[i].builtin = blob_read_uint32(metadata);
51901e04c3fSmrg      uniforms[i].remap_location = blob_read_uint32(metadata);
52001e04c3fSmrg      uniforms[i].block_index = blob_read_uint32(metadata);
52101e04c3fSmrg      uniforms[i].atomic_buffer_index = blob_read_uint32(metadata);
52201e04c3fSmrg      uniforms[i].offset = blob_read_uint32(metadata);
52301e04c3fSmrg      uniforms[i].array_stride = blob_read_uint32(metadata);
52401e04c3fSmrg      uniforms[i].hidden = blob_read_uint32(metadata);
52501e04c3fSmrg      uniforms[i].is_shader_storage = blob_read_uint32(metadata);
52601e04c3fSmrg      uniforms[i].active_shader_mask = blob_read_uint32(metadata);
52701e04c3fSmrg      uniforms[i].matrix_stride = blob_read_uint32(metadata);
52801e04c3fSmrg      uniforms[i].row_major = blob_read_uint32(metadata);
52901e04c3fSmrg      uniforms[i].is_bindless = blob_read_uint32(metadata);
53001e04c3fSmrg      uniforms[i].num_compatible_subroutines = blob_read_uint32(metadata);
53101e04c3fSmrg      uniforms[i].top_level_array_size = blob_read_uint32(metadata);
53201e04c3fSmrg      uniforms[i].top_level_array_stride = blob_read_uint32(metadata);
53301e04c3fSmrg      prog->UniformHash->put(i, uniforms[i].name);
53401e04c3fSmrg
53501e04c3fSmrg      if (has_uniform_storage(prog, i)) {
53601e04c3fSmrg         uniforms[i].storage = data + blob_read_uint32(metadata);
53701e04c3fSmrg      }
53801e04c3fSmrg
53901e04c3fSmrg      memcpy(uniforms[i].opaque,
54001e04c3fSmrg             blob_read_bytes(metadata, sizeof(uniforms[i].opaque)),
54101e04c3fSmrg             sizeof(uniforms[i].opaque));
54201e04c3fSmrg   }
54301e04c3fSmrg
54401e04c3fSmrg   /* Restore uniform values. */
54501e04c3fSmrg   prog->data->NumHiddenUniforms = blob_read_uint32(metadata);
54601e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
54701e04c3fSmrg      if (has_uniform_storage(prog, i)) {
54801e04c3fSmrg         unsigned vec_size =
54901e04c3fSmrg            prog->data->UniformStorage[i].type->component_slots() *
55001e04c3fSmrg            MAX2(prog->data->UniformStorage[i].array_elements, 1);
55101e04c3fSmrg         unsigned slot =
55201e04c3fSmrg            prog->data->UniformStorage[i].storage -
55301e04c3fSmrg            prog->data->UniformDataSlots;
55401e04c3fSmrg         blob_copy_bytes(metadata,
55501e04c3fSmrg                         (uint8_t *) &prog->data->UniformDataSlots[slot],
55601e04c3fSmrg                         sizeof(union gl_constant_value) * vec_size);
55701e04c3fSmrg
55801e04c3fSmrg        assert(vec_size + prog->data->UniformStorage[i].storage <=
55901e04c3fSmrg               data +  prog->data->NumUniformDataSlots);
56001e04c3fSmrg      }
56101e04c3fSmrg   }
56201e04c3fSmrg
56301e04c3fSmrg   memcpy(prog->data->UniformDataDefaults, prog->data->UniformDataSlots,
56401e04c3fSmrg          sizeof(union gl_constant_value) * prog->data->NumUniformDataSlots);
56501e04c3fSmrg}
56601e04c3fSmrg
56701e04c3fSmrgenum uniform_remap_type
56801e04c3fSmrg{
56901e04c3fSmrg   remap_type_inactive_explicit_location,
57001e04c3fSmrg   remap_type_null_ptr,
5717ec681f3Smrg   remap_type_uniform_offset,
5727ec681f3Smrg   remap_type_uniform_offsets_equal,
57301e04c3fSmrg};
57401e04c3fSmrg
57501e04c3fSmrgstatic void
5767ec681f3Smrgwrite_uniform_remap_table(struct blob *metadata,
5777ec681f3Smrg                          unsigned num_entries,
5787ec681f3Smrg                          gl_uniform_storage *uniform_storage,
5797ec681f3Smrg                          gl_uniform_storage **remap_table)
58001e04c3fSmrg{
5817ec681f3Smrg   blob_write_uint32(metadata, num_entries);
58201e04c3fSmrg
5837ec681f3Smrg   for (unsigned i = 0; i < num_entries; i++) {
5847ec681f3Smrg      gl_uniform_storage *entry = remap_table[i];
58501e04c3fSmrg      uint32_t offset = entry - uniform_storage;
5867ec681f3Smrg
5877ec681f3Smrg      if (entry == INACTIVE_UNIFORM_EXPLICIT_LOCATION) {
5887ec681f3Smrg         blob_write_uint32(metadata, remap_type_inactive_explicit_location);
5897ec681f3Smrg      } else if (entry == NULL) {
5907ec681f3Smrg         blob_write_uint32(metadata, remap_type_null_ptr);
5917ec681f3Smrg      } else if (i+1 < num_entries && entry == remap_table[i+1]) {
5927ec681f3Smrg         blob_write_uint32(metadata, remap_type_uniform_offsets_equal);
5937ec681f3Smrg
5947ec681f3Smrg         /* If many offsets are equal, write only one offset and the number
5957ec681f3Smrg          * of consecutive entries being equal.
5967ec681f3Smrg          */
5977ec681f3Smrg         unsigned count = 1;
5987ec681f3Smrg         for (unsigned j = i + 1; j < num_entries; j++) {
5997ec681f3Smrg            if (entry != remap_table[j])
6007ec681f3Smrg               break;
6017ec681f3Smrg
6027ec681f3Smrg            count++;
6037ec681f3Smrg         }
6047ec681f3Smrg
6057ec681f3Smrg         blob_write_uint32(metadata, offset);
6067ec681f3Smrg         blob_write_uint32(metadata, count);
6077ec681f3Smrg         i += count - 1;
6087ec681f3Smrg      } else {
6097ec681f3Smrg         blob_write_uint32(metadata, remap_type_uniform_offset);
6107ec681f3Smrg
6117ec681f3Smrg         blob_write_uint32(metadata, offset);
6127ec681f3Smrg      }
61301e04c3fSmrg   }
61401e04c3fSmrg}
61501e04c3fSmrg
61601e04c3fSmrgstatic void
61701e04c3fSmrgwrite_uniform_remap_tables(struct blob *metadata,
61801e04c3fSmrg                           struct gl_shader_program *prog)
61901e04c3fSmrg{
6207ec681f3Smrg   write_uniform_remap_table(metadata, prog->NumUniformRemapTable,
6217ec681f3Smrg                             prog->data->UniformStorage,
6227ec681f3Smrg                             prog->UniformRemapTable);
62301e04c3fSmrg
62401e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
62501e04c3fSmrg      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
62601e04c3fSmrg      if (sh) {
6277ec681f3Smrg         write_uniform_remap_table(metadata,
6287ec681f3Smrg                                   sh->Program->sh.NumSubroutineUniformRemapTable,
6297ec681f3Smrg                                   prog->data->UniformStorage,
6307ec681f3Smrg                                   sh->Program->sh.SubroutineUniformRemapTable);
63101e04c3fSmrg      }
63201e04c3fSmrg   }
63301e04c3fSmrg}
63401e04c3fSmrg
6357ec681f3Smrgstatic struct gl_uniform_storage **
6367ec681f3Smrgread_uniform_remap_table(struct blob_reader *metadata,
6377ec681f3Smrg                         struct gl_shader_program *prog,
6387ec681f3Smrg                         unsigned *num_entries,
6397ec681f3Smrg                         gl_uniform_storage *uniform_storage)
64001e04c3fSmrg{
6417ec681f3Smrg   unsigned num = blob_read_uint32(metadata);
6427ec681f3Smrg   *num_entries = num;
6437ec681f3Smrg
6447ec681f3Smrg   struct gl_uniform_storage **remap_table =
6457ec681f3Smrg      rzalloc_array(prog, struct gl_uniform_storage *, num);
6467ec681f3Smrg
6477ec681f3Smrg   for (unsigned i = 0; i < num; i++) {
6487ec681f3Smrg      enum uniform_remap_type type =
6497ec681f3Smrg         (enum uniform_remap_type) blob_read_uint32(metadata);
6507ec681f3Smrg
6517ec681f3Smrg      if (type == remap_type_inactive_explicit_location) {
6527ec681f3Smrg         remap_table[i] = INACTIVE_UNIFORM_EXPLICIT_LOCATION;
6537ec681f3Smrg      } else if (type == remap_type_null_ptr) {
6547ec681f3Smrg         remap_table[i] = NULL;
6557ec681f3Smrg      } else if (type == remap_type_uniform_offsets_equal) {
6567ec681f3Smrg         uint32_t uni_offset = blob_read_uint32(metadata);
6577ec681f3Smrg         uint32_t count = blob_read_uint32(metadata);
6587ec681f3Smrg         struct gl_uniform_storage *entry = uniform_storage + uni_offset;
6597ec681f3Smrg
6607ec681f3Smrg         for (unsigned j = 0; j < count; j++)
6617ec681f3Smrg            remap_table[i+j] = entry;
6627ec681f3Smrg         i += count - 1;
6637ec681f3Smrg      } else {
6647ec681f3Smrg         uint32_t uni_offset = blob_read_uint32(metadata);
6657ec681f3Smrg         remap_table[i] = uniform_storage + uni_offset;
6667ec681f3Smrg      }
66701e04c3fSmrg   }
6687ec681f3Smrg   return remap_table;
66901e04c3fSmrg}
67001e04c3fSmrg
67101e04c3fSmrgstatic void
67201e04c3fSmrgread_uniform_remap_tables(struct blob_reader *metadata,
67301e04c3fSmrg                          struct gl_shader_program *prog)
67401e04c3fSmrg{
6757ec681f3Smrg   prog->UniformRemapTable =
6767ec681f3Smrg      read_uniform_remap_table(metadata, prog, &prog->NumUniformRemapTable,
6777ec681f3Smrg                               prog->data->UniformStorage);
67801e04c3fSmrg
67901e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
68001e04c3fSmrg      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
68101e04c3fSmrg      if (sh) {
68201e04c3fSmrg         struct gl_program *glprog = sh->Program;
68301e04c3fSmrg
68401e04c3fSmrg         glprog->sh.SubroutineUniformRemapTable =
6857ec681f3Smrg            read_uniform_remap_table(metadata, prog,
6867ec681f3Smrg                                     &glprog->sh.NumSubroutineUniformRemapTable,
6877ec681f3Smrg                                     prog->data->UniformStorage);
68801e04c3fSmrg      }
68901e04c3fSmrg   }
69001e04c3fSmrg}
69101e04c3fSmrg
69201e04c3fSmrgstruct whte_closure
69301e04c3fSmrg{
69401e04c3fSmrg   struct blob *blob;
69501e04c3fSmrg   size_t num_entries;
69601e04c3fSmrg};
69701e04c3fSmrg
69801e04c3fSmrgstatic void
69901e04c3fSmrgwrite_hash_table_entry(const char *key, unsigned value, void *closure)
70001e04c3fSmrg{
70101e04c3fSmrg   struct whte_closure *whte = (struct whte_closure *) closure;
70201e04c3fSmrg
70301e04c3fSmrg   blob_write_string(whte->blob, key);
70401e04c3fSmrg   blob_write_uint32(whte->blob, value);
70501e04c3fSmrg
70601e04c3fSmrg   whte->num_entries++;
70701e04c3fSmrg}
70801e04c3fSmrg
70901e04c3fSmrgstatic void
71001e04c3fSmrgwrite_hash_table(struct blob *metadata, struct string_to_uint_map *hash)
71101e04c3fSmrg{
71201e04c3fSmrg   size_t offset;
71301e04c3fSmrg   struct whte_closure whte;
71401e04c3fSmrg
71501e04c3fSmrg   whte.blob = metadata;
71601e04c3fSmrg   whte.num_entries = 0;
71701e04c3fSmrg
71801e04c3fSmrg   offset = metadata->size;
71901e04c3fSmrg
72001e04c3fSmrg   /* Write a placeholder for the hashtable size. */
72101e04c3fSmrg   blob_write_uint32 (metadata, 0);
72201e04c3fSmrg
72301e04c3fSmrg   hash->iterate(write_hash_table_entry, &whte);
72401e04c3fSmrg
72501e04c3fSmrg   /* Overwrite with the computed number of entries written. */
72601e04c3fSmrg   blob_overwrite_uint32 (metadata, offset, whte.num_entries);
72701e04c3fSmrg}
72801e04c3fSmrg
72901e04c3fSmrgstatic void
73001e04c3fSmrgread_hash_table(struct blob_reader *metadata, struct string_to_uint_map *hash)
73101e04c3fSmrg{
73201e04c3fSmrg   size_t i, num_entries;
73301e04c3fSmrg   const char *key;
73401e04c3fSmrg   uint32_t value;
73501e04c3fSmrg
73601e04c3fSmrg   num_entries = blob_read_uint32 (metadata);
73701e04c3fSmrg
73801e04c3fSmrg   for (i = 0; i < num_entries; i++) {
73901e04c3fSmrg      key = blob_read_string(metadata);
74001e04c3fSmrg      value = blob_read_uint32(metadata);
74101e04c3fSmrg
74201e04c3fSmrg      hash->put(value, key);
74301e04c3fSmrg   }
74401e04c3fSmrg}
74501e04c3fSmrg
74601e04c3fSmrgstatic void
74701e04c3fSmrgwrite_hash_tables(struct blob *metadata, struct gl_shader_program *prog)
74801e04c3fSmrg{
74901e04c3fSmrg   write_hash_table(metadata, prog->AttributeBindings);
75001e04c3fSmrg   write_hash_table(metadata, prog->FragDataBindings);
75101e04c3fSmrg   write_hash_table(metadata, prog->FragDataIndexBindings);
75201e04c3fSmrg}
75301e04c3fSmrg
75401e04c3fSmrgstatic void
75501e04c3fSmrgread_hash_tables(struct blob_reader *metadata, struct gl_shader_program *prog)
75601e04c3fSmrg{
75701e04c3fSmrg   read_hash_table(metadata, prog->AttributeBindings);
75801e04c3fSmrg   read_hash_table(metadata, prog->FragDataBindings);
75901e04c3fSmrg   read_hash_table(metadata, prog->FragDataIndexBindings);
76001e04c3fSmrg}
76101e04c3fSmrg
76201e04c3fSmrgstatic void
76301e04c3fSmrgwrite_shader_subroutine_index(struct blob *metadata,
76401e04c3fSmrg                              struct gl_linked_shader *sh,
76501e04c3fSmrg                              struct gl_program_resource *res)
76601e04c3fSmrg{
76701e04c3fSmrg   assert(sh);
76801e04c3fSmrg
76901e04c3fSmrg   for (unsigned j = 0; j < sh->Program->sh.NumSubroutineFunctions; j++) {
77001e04c3fSmrg      if (strcmp(((gl_subroutine_function *)res->Data)->name,
77101e04c3fSmrg                 sh->Program->sh.SubroutineFunctions[j].name) == 0) {
77201e04c3fSmrg         blob_write_uint32(metadata, j);
77301e04c3fSmrg         break;
77401e04c3fSmrg      }
77501e04c3fSmrg   }
77601e04c3fSmrg}
77701e04c3fSmrg
77801e04c3fSmrgstatic void
77901e04c3fSmrgget_shader_var_and_pointer_sizes(size_t *s_var_size, size_t *s_var_ptrs,
78001e04c3fSmrg                                 const gl_shader_variable *var)
78101e04c3fSmrg{
78201e04c3fSmrg   *s_var_size = sizeof(gl_shader_variable);
78301e04c3fSmrg   *s_var_ptrs =
78401e04c3fSmrg      sizeof(var->type) +
78501e04c3fSmrg      sizeof(var->interface_type) +
78601e04c3fSmrg      sizeof(var->outermost_struct_type) +
78701e04c3fSmrg      sizeof(var->name);
78801e04c3fSmrg}
78901e04c3fSmrg
79001e04c3fSmrgenum uniform_type
79101e04c3fSmrg{
79201e04c3fSmrg   uniform_remapped,
79301e04c3fSmrg   uniform_not_remapped
79401e04c3fSmrg};
79501e04c3fSmrg
79601e04c3fSmrgstatic void
79701e04c3fSmrgwrite_program_resource_data(struct blob *metadata,
79801e04c3fSmrg                            struct gl_shader_program *prog,
79901e04c3fSmrg                            struct gl_program_resource *res)
80001e04c3fSmrg{
80101e04c3fSmrg   struct gl_linked_shader *sh;
80201e04c3fSmrg
80301e04c3fSmrg   switch(res->Type) {
80401e04c3fSmrg   case GL_PROGRAM_INPUT:
80501e04c3fSmrg   case GL_PROGRAM_OUTPUT: {
80601e04c3fSmrg      const gl_shader_variable *var = (gl_shader_variable *)res->Data;
80701e04c3fSmrg
80801e04c3fSmrg      encode_type_to_blob(metadata, var->type);
80901e04c3fSmrg      encode_type_to_blob(metadata, var->interface_type);
81001e04c3fSmrg      encode_type_to_blob(metadata, var->outermost_struct_type);
81101e04c3fSmrg
8127ec681f3Smrg      if (var->name) {
8137ec681f3Smrg         blob_write_string(metadata, var->name);
8147ec681f3Smrg      } else {
8157ec681f3Smrg         blob_write_string(metadata, "");
8167ec681f3Smrg      }
81701e04c3fSmrg
81801e04c3fSmrg      size_t s_var_size, s_var_ptrs;
81901e04c3fSmrg      get_shader_var_and_pointer_sizes(&s_var_size, &s_var_ptrs, var);
82001e04c3fSmrg
82101e04c3fSmrg      /* Write gl_shader_variable skipping over the pointers */
82201e04c3fSmrg      blob_write_bytes(metadata, ((char *)var) + s_var_ptrs,
82301e04c3fSmrg                       s_var_size - s_var_ptrs);
82401e04c3fSmrg      break;
82501e04c3fSmrg   }
82601e04c3fSmrg   case GL_UNIFORM_BLOCK:
82701e04c3fSmrg      for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
82801e04c3fSmrg         if (strcmp(((gl_uniform_block *)res->Data)->Name,
82901e04c3fSmrg                    prog->data->UniformBlocks[i].Name) == 0) {
83001e04c3fSmrg            blob_write_uint32(metadata, i);
83101e04c3fSmrg            break;
83201e04c3fSmrg         }
83301e04c3fSmrg      }
83401e04c3fSmrg      break;
83501e04c3fSmrg   case GL_SHADER_STORAGE_BLOCK:
83601e04c3fSmrg      for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
83701e04c3fSmrg         if (strcmp(((gl_uniform_block *)res->Data)->Name,
83801e04c3fSmrg                    prog->data->ShaderStorageBlocks[i].Name) == 0) {
83901e04c3fSmrg            blob_write_uint32(metadata, i);
84001e04c3fSmrg            break;
84101e04c3fSmrg         }
84201e04c3fSmrg      }
84301e04c3fSmrg      break;
84401e04c3fSmrg   case GL_BUFFER_VARIABLE:
84501e04c3fSmrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
84601e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
84701e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
84801e04c3fSmrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
84901e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
85001e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
85101e04c3fSmrg   case GL_UNIFORM:
85201e04c3fSmrg      if (((gl_uniform_storage *)res->Data)->builtin ||
85301e04c3fSmrg          res->Type != GL_UNIFORM) {
85401e04c3fSmrg         blob_write_uint32(metadata, uniform_not_remapped);
85501e04c3fSmrg         for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
85601e04c3fSmrg            if (strcmp(((gl_uniform_storage *)res->Data)->name,
85701e04c3fSmrg                       prog->data->UniformStorage[i].name) == 0) {
85801e04c3fSmrg               blob_write_uint32(metadata, i);
85901e04c3fSmrg               break;
86001e04c3fSmrg            }
86101e04c3fSmrg         }
86201e04c3fSmrg      } else {
86301e04c3fSmrg         blob_write_uint32(metadata, uniform_remapped);
86401e04c3fSmrg         blob_write_uint32(metadata, ((gl_uniform_storage *)res->Data)->remap_location);
86501e04c3fSmrg      }
86601e04c3fSmrg      break;
86701e04c3fSmrg   case GL_ATOMIC_COUNTER_BUFFER:
86801e04c3fSmrg      for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
86901e04c3fSmrg         if (((gl_active_atomic_buffer *)res->Data)->Binding ==
87001e04c3fSmrg             prog->data->AtomicBuffers[i].Binding) {
87101e04c3fSmrg            blob_write_uint32(metadata, i);
87201e04c3fSmrg            break;
87301e04c3fSmrg         }
87401e04c3fSmrg      }
87501e04c3fSmrg      break;
87601e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
87701e04c3fSmrg      for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
87801e04c3fSmrg         if (((gl_transform_feedback_buffer *)res->Data)->Binding ==
87901e04c3fSmrg             prog->last_vert_prog->sh.LinkedTransformFeedback->Buffers[i].Binding) {
88001e04c3fSmrg            blob_write_uint32(metadata, i);
88101e04c3fSmrg            break;
88201e04c3fSmrg         }
88301e04c3fSmrg      }
88401e04c3fSmrg      break;
88501e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_VARYING:
88601e04c3fSmrg      for (int i = 0; i < prog->last_vert_prog->sh.LinkedTransformFeedback->NumVarying; i++) {
88701e04c3fSmrg         if (strcmp(((gl_transform_feedback_varying_info *)res->Data)->Name,
88801e04c3fSmrg                    prog->last_vert_prog->sh.LinkedTransformFeedback->Varyings[i].Name) == 0) {
88901e04c3fSmrg            blob_write_uint32(metadata, i);
89001e04c3fSmrg            break;
89101e04c3fSmrg         }
89201e04c3fSmrg      }
89301e04c3fSmrg      break;
89401e04c3fSmrg   case GL_VERTEX_SUBROUTINE:
89501e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE:
89601e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE:
89701e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE:
89801e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE:
89901e04c3fSmrg   case GL_COMPUTE_SUBROUTINE:
90001e04c3fSmrg      sh =
90101e04c3fSmrg         prog->_LinkedShaders[_mesa_shader_stage_from_subroutine(res->Type)];
90201e04c3fSmrg      write_shader_subroutine_index(metadata, sh, res);
90301e04c3fSmrg      break;
90401e04c3fSmrg   default:
90501e04c3fSmrg      assert(!"Support for writing resource not yet implemented.");
90601e04c3fSmrg   }
90701e04c3fSmrg}
90801e04c3fSmrg
90901e04c3fSmrgstatic void
91001e04c3fSmrgread_program_resource_data(struct blob_reader *metadata,
91101e04c3fSmrg                           struct gl_shader_program *prog,
91201e04c3fSmrg                           struct gl_program_resource *res)
91301e04c3fSmrg{
91401e04c3fSmrg   struct gl_linked_shader *sh;
91501e04c3fSmrg
91601e04c3fSmrg   switch(res->Type) {
91701e04c3fSmrg   case GL_PROGRAM_INPUT:
91801e04c3fSmrg   case GL_PROGRAM_OUTPUT: {
91901e04c3fSmrg      gl_shader_variable *var = ralloc(prog, struct gl_shader_variable);
92001e04c3fSmrg
92101e04c3fSmrg      var->type = decode_type_from_blob(metadata);
92201e04c3fSmrg      var->interface_type = decode_type_from_blob(metadata);
92301e04c3fSmrg      var->outermost_struct_type = decode_type_from_blob(metadata);
92401e04c3fSmrg
92501e04c3fSmrg      var->name = ralloc_strdup(prog, blob_read_string(metadata));
92601e04c3fSmrg
92701e04c3fSmrg      size_t s_var_size, s_var_ptrs;
92801e04c3fSmrg      get_shader_var_and_pointer_sizes(&s_var_size, &s_var_ptrs, var);
92901e04c3fSmrg
93001e04c3fSmrg      blob_copy_bytes(metadata, ((uint8_t *) var) + s_var_ptrs,
93101e04c3fSmrg                      s_var_size - s_var_ptrs);
93201e04c3fSmrg
93301e04c3fSmrg      res->Data = var;
93401e04c3fSmrg      break;
93501e04c3fSmrg   }
93601e04c3fSmrg   case GL_UNIFORM_BLOCK:
93701e04c3fSmrg      res->Data = &prog->data->UniformBlocks[blob_read_uint32(metadata)];
93801e04c3fSmrg      break;
93901e04c3fSmrg   case GL_SHADER_STORAGE_BLOCK:
94001e04c3fSmrg      res->Data = &prog->data->ShaderStorageBlocks[blob_read_uint32(metadata)];
94101e04c3fSmrg      break;
94201e04c3fSmrg   case GL_BUFFER_VARIABLE:
94301e04c3fSmrg   case GL_VERTEX_SUBROUTINE_UNIFORM:
94401e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
94501e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
94601e04c3fSmrg   case GL_COMPUTE_SUBROUTINE_UNIFORM:
94701e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
94801e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
94901e04c3fSmrg   case GL_UNIFORM: {
95001e04c3fSmrg      enum uniform_type type = (enum uniform_type) blob_read_uint32(metadata);
95101e04c3fSmrg      if (type == uniform_not_remapped) {
95201e04c3fSmrg         res->Data = &prog->data->UniformStorage[blob_read_uint32(metadata)];
95301e04c3fSmrg      } else {
95401e04c3fSmrg         res->Data = prog->UniformRemapTable[blob_read_uint32(metadata)];
95501e04c3fSmrg      }
95601e04c3fSmrg      break;
95701e04c3fSmrg   }
95801e04c3fSmrg   case GL_ATOMIC_COUNTER_BUFFER:
95901e04c3fSmrg      res->Data = &prog->data->AtomicBuffers[blob_read_uint32(metadata)];
96001e04c3fSmrg      break;
96101e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
96201e04c3fSmrg      res->Data = &prog->last_vert_prog->
96301e04c3fSmrg         sh.LinkedTransformFeedback->Buffers[blob_read_uint32(metadata)];
96401e04c3fSmrg      break;
96501e04c3fSmrg   case GL_TRANSFORM_FEEDBACK_VARYING:
96601e04c3fSmrg      res->Data = &prog->last_vert_prog->
96701e04c3fSmrg         sh.LinkedTransformFeedback->Varyings[blob_read_uint32(metadata)];
96801e04c3fSmrg      break;
96901e04c3fSmrg   case GL_VERTEX_SUBROUTINE:
97001e04c3fSmrg   case GL_TESS_CONTROL_SUBROUTINE:
97101e04c3fSmrg   case GL_TESS_EVALUATION_SUBROUTINE:
97201e04c3fSmrg   case GL_GEOMETRY_SUBROUTINE:
97301e04c3fSmrg   case GL_FRAGMENT_SUBROUTINE:
97401e04c3fSmrg   case GL_COMPUTE_SUBROUTINE:
97501e04c3fSmrg      sh =
97601e04c3fSmrg         prog->_LinkedShaders[_mesa_shader_stage_from_subroutine(res->Type)];
97701e04c3fSmrg      res->Data =
97801e04c3fSmrg         &sh->Program->sh.SubroutineFunctions[blob_read_uint32(metadata)];
97901e04c3fSmrg      break;
98001e04c3fSmrg   default:
98101e04c3fSmrg      assert(!"Support for reading resource not yet implemented.");
98201e04c3fSmrg   }
98301e04c3fSmrg}
98401e04c3fSmrg
98501e04c3fSmrgstatic void
98601e04c3fSmrgwrite_program_resource_list(struct blob *metadata,
98701e04c3fSmrg                            struct gl_shader_program *prog)
98801e04c3fSmrg{
98901e04c3fSmrg   blob_write_uint32(metadata, prog->data->NumProgramResourceList);
99001e04c3fSmrg
99101e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumProgramResourceList; i++) {
99201e04c3fSmrg      blob_write_uint32(metadata, prog->data->ProgramResourceList[i].Type);
99301e04c3fSmrg      write_program_resource_data(metadata, prog,
99401e04c3fSmrg                                  &prog->data->ProgramResourceList[i]);
99501e04c3fSmrg      blob_write_bytes(metadata,
99601e04c3fSmrg                       &prog->data->ProgramResourceList[i].StageReferences,
99701e04c3fSmrg                       sizeof(prog->data->ProgramResourceList[i].StageReferences));
99801e04c3fSmrg   }
99901e04c3fSmrg}
100001e04c3fSmrg
100101e04c3fSmrgstatic void
100201e04c3fSmrgread_program_resource_list(struct blob_reader *metadata,
100301e04c3fSmrg                           struct gl_shader_program *prog)
100401e04c3fSmrg{
100501e04c3fSmrg   prog->data->NumProgramResourceList = blob_read_uint32(metadata);
100601e04c3fSmrg
100701e04c3fSmrg   prog->data->ProgramResourceList =
100801e04c3fSmrg      ralloc_array(prog->data, gl_program_resource,
100901e04c3fSmrg                   prog->data->NumProgramResourceList);
101001e04c3fSmrg
101101e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumProgramResourceList; i++) {
101201e04c3fSmrg      prog->data->ProgramResourceList[i].Type = blob_read_uint32(metadata);
101301e04c3fSmrg      read_program_resource_data(metadata, prog,
101401e04c3fSmrg                                 &prog->data->ProgramResourceList[i]);
101501e04c3fSmrg      blob_copy_bytes(metadata,
101601e04c3fSmrg                      (uint8_t *) &prog->data->ProgramResourceList[i].StageReferences,
101701e04c3fSmrg                      sizeof(prog->data->ProgramResourceList[i].StageReferences));
101801e04c3fSmrg   }
101901e04c3fSmrg}
102001e04c3fSmrg
102101e04c3fSmrgstatic void
102201e04c3fSmrgwrite_shader_parameters(struct blob *metadata,
102301e04c3fSmrg                        struct gl_program_parameter_list *params)
102401e04c3fSmrg{
102501e04c3fSmrg   blob_write_uint32(metadata, params->NumParameters);
102601e04c3fSmrg   uint32_t i = 0;
102701e04c3fSmrg
102801e04c3fSmrg   while (i < params->NumParameters) {
102901e04c3fSmrg      struct gl_program_parameter *param = &params->Parameters[i];
103001e04c3fSmrg      blob_write_uint32(metadata, param->Type);
103101e04c3fSmrg      blob_write_string(metadata, param->Name);
103201e04c3fSmrg      blob_write_uint32(metadata, param->Size);
1033993e1d59Smrg      blob_write_uint32(metadata, param->Padded);
103401e04c3fSmrg      blob_write_uint32(metadata, param->DataType);
103501e04c3fSmrg      blob_write_bytes(metadata, param->StateIndexes,
103601e04c3fSmrg                       sizeof(param->StateIndexes));
10377ec681f3Smrg      blob_write_uint32(metadata, param->UniformStorageIndex);
10387ec681f3Smrg      blob_write_uint32(metadata, param->MainUniformStorageIndex);
103901e04c3fSmrg
104001e04c3fSmrg      i++;
104101e04c3fSmrg   }
104201e04c3fSmrg
104301e04c3fSmrg   blob_write_bytes(metadata, params->ParameterValues,
104401e04c3fSmrg                    sizeof(gl_constant_value) * params->NumParameterValues);
104501e04c3fSmrg
104601e04c3fSmrg   blob_write_uint32(metadata, params->StateFlags);
10477ec681f3Smrg   blob_write_uint32(metadata, params->UniformBytes);
10487ec681f3Smrg   blob_write_uint32(metadata, params->FirstStateVarIndex);
10497ec681f3Smrg   blob_write_uint32(metadata, params->LastStateVarIndex);
105001e04c3fSmrg}
105101e04c3fSmrg
105201e04c3fSmrgstatic void
105301e04c3fSmrgread_shader_parameters(struct blob_reader *metadata,
105401e04c3fSmrg                       struct gl_program_parameter_list *params)
105501e04c3fSmrg{
105601e04c3fSmrg   gl_state_index16 state_indexes[STATE_LENGTH];
105701e04c3fSmrg   uint32_t i = 0;
105801e04c3fSmrg   uint32_t num_parameters = blob_read_uint32(metadata);
105901e04c3fSmrg
10607ec681f3Smrg   _mesa_reserve_parameter_storage(params, num_parameters, num_parameters);
106101e04c3fSmrg   while (i < num_parameters) {
106201e04c3fSmrg      gl_register_file type = (gl_register_file) blob_read_uint32(metadata);
106301e04c3fSmrg      const char *name = blob_read_string(metadata);
106401e04c3fSmrg      unsigned size = blob_read_uint32(metadata);
1065993e1d59Smrg      bool padded = blob_read_uint32(metadata);
106601e04c3fSmrg      unsigned data_type = blob_read_uint32(metadata);
106701e04c3fSmrg      blob_copy_bytes(metadata, (uint8_t *) state_indexes,
106801e04c3fSmrg                      sizeof(state_indexes));
106901e04c3fSmrg
107001e04c3fSmrg      _mesa_add_parameter(params, type, name, size, data_type,
1071993e1d59Smrg                          NULL, state_indexes, padded);
107201e04c3fSmrg
10737ec681f3Smrg      gl_program_parameter *param = &params->Parameters[i];
10747ec681f3Smrg      param->UniformStorageIndex = blob_read_uint32(metadata);
10757ec681f3Smrg      param->MainUniformStorageIndex = blob_read_uint32(metadata);
10767ec681f3Smrg
107701e04c3fSmrg      i++;
107801e04c3fSmrg   }
107901e04c3fSmrg
108001e04c3fSmrg   blob_copy_bytes(metadata, (uint8_t *) params->ParameterValues,
1081993e1d59Smrg                   sizeof(gl_constant_value) * params->NumParameterValues);
108201e04c3fSmrg
108301e04c3fSmrg   params->StateFlags = blob_read_uint32(metadata);
10847ec681f3Smrg   params->UniformBytes = blob_read_uint32(metadata);
10857ec681f3Smrg   params->FirstStateVarIndex = blob_read_uint32(metadata);
10867ec681f3Smrg   params->LastStateVarIndex = blob_read_uint32(metadata);
108701e04c3fSmrg}
108801e04c3fSmrg
108901e04c3fSmrgstatic void
109001e04c3fSmrgwrite_shader_metadata(struct blob *metadata, gl_linked_shader *shader)
109101e04c3fSmrg{
109201e04c3fSmrg   assert(shader->Program);
109301e04c3fSmrg   struct gl_program *glprog = shader->Program;
109401e04c3fSmrg   unsigned i;
109501e04c3fSmrg
109601e04c3fSmrg   blob_write_uint64(metadata, glprog->DualSlotInputs);
109701e04c3fSmrg   blob_write_bytes(metadata, glprog->TexturesUsed,
109801e04c3fSmrg                    sizeof(glprog->TexturesUsed));
109901e04c3fSmrg   blob_write_uint64(metadata, glprog->SamplersUsed);
110001e04c3fSmrg
110101e04c3fSmrg   blob_write_bytes(metadata, glprog->SamplerUnits,
110201e04c3fSmrg                    sizeof(glprog->SamplerUnits));
110301e04c3fSmrg   blob_write_bytes(metadata, glprog->sh.SamplerTargets,
110401e04c3fSmrg                    sizeof(glprog->sh.SamplerTargets));
110501e04c3fSmrg   blob_write_uint32(metadata, glprog->ShadowSamplers);
110601e04c3fSmrg   blob_write_uint32(metadata, glprog->ExternalSamplersUsed);
11077e102996Smaya   blob_write_uint32(metadata, glprog->sh.ShaderStorageBlocksWriteAccess);
110801e04c3fSmrg
110901e04c3fSmrg   blob_write_bytes(metadata, glprog->sh.ImageAccess,
111001e04c3fSmrg                    sizeof(glprog->sh.ImageAccess));
111101e04c3fSmrg   blob_write_bytes(metadata, glprog->sh.ImageUnits,
111201e04c3fSmrg                    sizeof(glprog->sh.ImageUnits));
111301e04c3fSmrg
111401e04c3fSmrg   size_t ptr_size = sizeof(GLvoid *);
111501e04c3fSmrg
111601e04c3fSmrg   blob_write_uint32(metadata, glprog->sh.NumBindlessSamplers);
111701e04c3fSmrg   blob_write_uint32(metadata, glprog->sh.HasBoundBindlessSampler);
111801e04c3fSmrg   for (i = 0; i < glprog->sh.NumBindlessSamplers; i++) {
111901e04c3fSmrg      blob_write_bytes(metadata, &glprog->sh.BindlessSamplers[i],
112001e04c3fSmrg                       sizeof(struct gl_bindless_sampler) - ptr_size);
112101e04c3fSmrg   }
112201e04c3fSmrg
112301e04c3fSmrg   blob_write_uint32(metadata, glprog->sh.NumBindlessImages);
112401e04c3fSmrg   blob_write_uint32(metadata, glprog->sh.HasBoundBindlessImage);
112501e04c3fSmrg   for (i = 0; i < glprog->sh.NumBindlessImages; i++) {
112601e04c3fSmrg      blob_write_bytes(metadata, &glprog->sh.BindlessImages[i],
112701e04c3fSmrg                       sizeof(struct gl_bindless_image) - ptr_size);
112801e04c3fSmrg   }
112901e04c3fSmrg
113001e04c3fSmrg   write_shader_parameters(metadata, glprog->Parameters);
113101e04c3fSmrg
113201e04c3fSmrg   assert((glprog->driver_cache_blob == NULL) ==
113301e04c3fSmrg          (glprog->driver_cache_blob_size == 0));
113401e04c3fSmrg   blob_write_uint32(metadata, (uint32_t)glprog->driver_cache_blob_size);
113501e04c3fSmrg   if (glprog->driver_cache_blob_size > 0) {
113601e04c3fSmrg      blob_write_bytes(metadata, glprog->driver_cache_blob,
113701e04c3fSmrg                       glprog->driver_cache_blob_size);
113801e04c3fSmrg   }
113901e04c3fSmrg}
114001e04c3fSmrg
114101e04c3fSmrgstatic void
114201e04c3fSmrgread_shader_metadata(struct blob_reader *metadata,
114301e04c3fSmrg                     struct gl_program *glprog,
114401e04c3fSmrg                     gl_linked_shader *linked)
114501e04c3fSmrg{
114601e04c3fSmrg   unsigned i;
114701e04c3fSmrg
114801e04c3fSmrg   glprog->DualSlotInputs = blob_read_uint64(metadata);
114901e04c3fSmrg   blob_copy_bytes(metadata, (uint8_t *) glprog->TexturesUsed,
115001e04c3fSmrg                   sizeof(glprog->TexturesUsed));
115101e04c3fSmrg   glprog->SamplersUsed = blob_read_uint64(metadata);
115201e04c3fSmrg
115301e04c3fSmrg   blob_copy_bytes(metadata, (uint8_t *) glprog->SamplerUnits,
115401e04c3fSmrg                   sizeof(glprog->SamplerUnits));
115501e04c3fSmrg   blob_copy_bytes(metadata, (uint8_t *) glprog->sh.SamplerTargets,
115601e04c3fSmrg                   sizeof(glprog->sh.SamplerTargets));
115701e04c3fSmrg   glprog->ShadowSamplers = blob_read_uint32(metadata);
115801e04c3fSmrg   glprog->ExternalSamplersUsed = blob_read_uint32(metadata);
11597e102996Smaya   glprog->sh.ShaderStorageBlocksWriteAccess = blob_read_uint32(metadata);
116001e04c3fSmrg
116101e04c3fSmrg   blob_copy_bytes(metadata, (uint8_t *) glprog->sh.ImageAccess,
116201e04c3fSmrg                   sizeof(glprog->sh.ImageAccess));
116301e04c3fSmrg   blob_copy_bytes(metadata, (uint8_t *) glprog->sh.ImageUnits,
116401e04c3fSmrg                   sizeof(glprog->sh.ImageUnits));
116501e04c3fSmrg
116601e04c3fSmrg   size_t ptr_size = sizeof(GLvoid *);
116701e04c3fSmrg
116801e04c3fSmrg   glprog->sh.NumBindlessSamplers = blob_read_uint32(metadata);
116901e04c3fSmrg   glprog->sh.HasBoundBindlessSampler = blob_read_uint32(metadata);
117001e04c3fSmrg   if (glprog->sh.NumBindlessSamplers > 0) {
117101e04c3fSmrg      glprog->sh.BindlessSamplers =
117201e04c3fSmrg         rzalloc_array(glprog, gl_bindless_sampler,
117301e04c3fSmrg                       glprog->sh.NumBindlessSamplers);
117401e04c3fSmrg
117501e04c3fSmrg      for (i = 0; i < glprog->sh.NumBindlessSamplers; i++) {
117601e04c3fSmrg         blob_copy_bytes(metadata, (uint8_t *) &glprog->sh.BindlessSamplers[i],
117701e04c3fSmrg                         sizeof(struct gl_bindless_sampler) - ptr_size);
117801e04c3fSmrg      }
117901e04c3fSmrg   }
118001e04c3fSmrg
118101e04c3fSmrg   glprog->sh.NumBindlessImages = blob_read_uint32(metadata);
118201e04c3fSmrg   glprog->sh.HasBoundBindlessImage = blob_read_uint32(metadata);
118301e04c3fSmrg   if (glprog->sh.NumBindlessImages > 0) {
118401e04c3fSmrg      glprog->sh.BindlessImages =
118501e04c3fSmrg         rzalloc_array(glprog, gl_bindless_image,
118601e04c3fSmrg                       glprog->sh.NumBindlessImages);
118701e04c3fSmrg
118801e04c3fSmrg      for (i = 0; i < glprog->sh.NumBindlessImages; i++) {
118901e04c3fSmrg         blob_copy_bytes(metadata, (uint8_t *) &glprog->sh.BindlessImages[i],
119001e04c3fSmrg                        sizeof(struct gl_bindless_image) - ptr_size);
119101e04c3fSmrg      }
119201e04c3fSmrg   }
119301e04c3fSmrg
119401e04c3fSmrg   glprog->Parameters = _mesa_new_parameter_list();
119501e04c3fSmrg   read_shader_parameters(metadata, glprog->Parameters);
119601e04c3fSmrg
119701e04c3fSmrg   glprog->driver_cache_blob_size = (size_t)blob_read_uint32(metadata);
119801e04c3fSmrg   if (glprog->driver_cache_blob_size > 0) {
119901e04c3fSmrg      glprog->driver_cache_blob =
120001e04c3fSmrg         (uint8_t*)ralloc_size(glprog, glprog->driver_cache_blob_size);
120101e04c3fSmrg      blob_copy_bytes(metadata, glprog->driver_cache_blob,
120201e04c3fSmrg                      glprog->driver_cache_blob_size);
120301e04c3fSmrg   }
120401e04c3fSmrg}
120501e04c3fSmrg
120601e04c3fSmrgstatic void
120701e04c3fSmrgget_shader_info_and_pointer_sizes(size_t *s_info_size, size_t *s_info_ptrs,
120801e04c3fSmrg                                  shader_info *info)
120901e04c3fSmrg{
121001e04c3fSmrg   *s_info_size = sizeof(shader_info);
121101e04c3fSmrg   *s_info_ptrs = sizeof(info->name) + sizeof(info->label);
121201e04c3fSmrg}
121301e04c3fSmrg
121401e04c3fSmrgstatic void
121501e04c3fSmrgcreate_linked_shader_and_program(struct gl_context *ctx,
121601e04c3fSmrg                                 gl_shader_stage stage,
121701e04c3fSmrg                                 struct gl_shader_program *prog,
121801e04c3fSmrg                                 struct blob_reader *metadata)
121901e04c3fSmrg{
122001e04c3fSmrg   struct gl_program *glprog;
122101e04c3fSmrg
122201e04c3fSmrg   struct gl_linked_shader *linked = rzalloc(NULL, struct gl_linked_shader);
122301e04c3fSmrg   linked->Stage = stage;
122401e04c3fSmrg
12257ec681f3Smrg   glprog = ctx->Driver.NewProgram(ctx, stage, prog->Name, false);
122601e04c3fSmrg   glprog->info.stage = stage;
122701e04c3fSmrg   linked->Program = glprog;
122801e04c3fSmrg
122901e04c3fSmrg   read_shader_metadata(metadata, glprog, linked);
123001e04c3fSmrg
123101e04c3fSmrg   glprog->info.name = ralloc_strdup(glprog, blob_read_string(metadata));
123201e04c3fSmrg   glprog->info.label = ralloc_strdup(glprog, blob_read_string(metadata));
123301e04c3fSmrg
123401e04c3fSmrg   size_t s_info_size, s_info_ptrs;
123501e04c3fSmrg   get_shader_info_and_pointer_sizes(&s_info_size, &s_info_ptrs,
123601e04c3fSmrg                                     &glprog->info);
123701e04c3fSmrg
123801e04c3fSmrg   /* Restore shader info */
123901e04c3fSmrg   blob_copy_bytes(metadata, ((uint8_t *) &glprog->info) + s_info_ptrs,
124001e04c3fSmrg                   s_info_size - s_info_ptrs);
124101e04c3fSmrg
124201e04c3fSmrg   _mesa_reference_shader_program_data(ctx, &glprog->sh.data, prog->data);
124301e04c3fSmrg   _mesa_reference_program(ctx, &linked->Program, glprog);
124401e04c3fSmrg   prog->_LinkedShaders[stage] = linked;
124501e04c3fSmrg}
124601e04c3fSmrg
124701e04c3fSmrgextern "C" void
124801e04c3fSmrgserialize_glsl_program(struct blob *blob, struct gl_context *ctx,
124901e04c3fSmrg                       struct gl_shader_program *prog)
125001e04c3fSmrg{
125101e04c3fSmrg   blob_write_bytes(blob, prog->data->sha1, sizeof(prog->data->sha1));
125201e04c3fSmrg
125301e04c3fSmrg   write_uniforms(blob, prog);
125401e04c3fSmrg
125501e04c3fSmrg   write_hash_tables(blob, prog);
125601e04c3fSmrg
125701e04c3fSmrg   blob_write_uint32(blob, prog->data->Version);
12587ec681f3Smrg   blob_write_uint32(blob, prog->IsES);
125901e04c3fSmrg   blob_write_uint32(blob, prog->data->linked_stages);
126001e04c3fSmrg
126101e04c3fSmrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
126201e04c3fSmrg      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
126301e04c3fSmrg      if (sh) {
126401e04c3fSmrg         write_shader_metadata(blob, sh);
126501e04c3fSmrg
126601e04c3fSmrg         if (sh->Program->info.name)
126701e04c3fSmrg            blob_write_string(blob, sh->Program->info.name);
126801e04c3fSmrg         else
126901e04c3fSmrg            blob_write_string(blob, "");
127001e04c3fSmrg
127101e04c3fSmrg         if (sh->Program->info.label)
127201e04c3fSmrg            blob_write_string(blob, sh->Program->info.label);
127301e04c3fSmrg         else
127401e04c3fSmrg            blob_write_string(blob, "");
127501e04c3fSmrg
127601e04c3fSmrg         size_t s_info_size, s_info_ptrs;
127701e04c3fSmrg         get_shader_info_and_pointer_sizes(&s_info_size, &s_info_ptrs,
127801e04c3fSmrg                                           &sh->Program->info);
127901e04c3fSmrg
128001e04c3fSmrg         /* Store shader info */
128101e04c3fSmrg         blob_write_bytes(blob,
128201e04c3fSmrg                          ((char *) &sh->Program->info) + s_info_ptrs,
128301e04c3fSmrg                          s_info_size - s_info_ptrs);
128401e04c3fSmrg      }
128501e04c3fSmrg   }
128601e04c3fSmrg
128701e04c3fSmrg   write_xfb(blob, prog);
128801e04c3fSmrg
128901e04c3fSmrg   write_uniform_remap_tables(blob, prog);
129001e04c3fSmrg
129101e04c3fSmrg   write_atomic_buffers(blob, prog);
129201e04c3fSmrg
129301e04c3fSmrg   write_buffer_blocks(blob, prog);
129401e04c3fSmrg
129501e04c3fSmrg   write_subroutines(blob, prog);
129601e04c3fSmrg
129701e04c3fSmrg   write_program_resource_list(blob, prog);
129801e04c3fSmrg}
129901e04c3fSmrg
130001e04c3fSmrgextern "C" bool
130101e04c3fSmrgdeserialize_glsl_program(struct blob_reader *blob, struct gl_context *ctx,
130201e04c3fSmrg                         struct gl_shader_program *prog)
130301e04c3fSmrg{
130401e04c3fSmrg   /* Fixed function programs generated by Mesa can't be serialized. */
130501e04c3fSmrg   if (prog->Name == 0)
130601e04c3fSmrg      return false;
130701e04c3fSmrg
130801e04c3fSmrg   assert(prog->data->UniformStorage == NULL);
130901e04c3fSmrg
131001e04c3fSmrg   blob_copy_bytes(blob, prog->data->sha1, sizeof(prog->data->sha1));
131101e04c3fSmrg
131201e04c3fSmrg   read_uniforms(blob, prog);
131301e04c3fSmrg
131401e04c3fSmrg   read_hash_tables(blob, prog);
131501e04c3fSmrg
131601e04c3fSmrg   prog->data->Version = blob_read_uint32(blob);
13177ec681f3Smrg   prog->IsES = blob_read_uint32(blob);
131801e04c3fSmrg   prog->data->linked_stages = blob_read_uint32(blob);
131901e04c3fSmrg
132001e04c3fSmrg   unsigned mask = prog->data->linked_stages;
132101e04c3fSmrg   while (mask) {
132201e04c3fSmrg      const int j = u_bit_scan(&mask);
132301e04c3fSmrg      create_linked_shader_and_program(ctx, (gl_shader_stage) j, prog,
132401e04c3fSmrg                                       blob);
132501e04c3fSmrg   }
132601e04c3fSmrg
132701e04c3fSmrg   read_xfb(blob, prog);
132801e04c3fSmrg
132901e04c3fSmrg   read_uniform_remap_tables(blob, prog);
133001e04c3fSmrg
133101e04c3fSmrg   read_atomic_buffers(blob, prog);
133201e04c3fSmrg
133301e04c3fSmrg   read_buffer_blocks(blob, prog);
133401e04c3fSmrg
133501e04c3fSmrg   read_subroutines(blob, prog);
133601e04c3fSmrg
133701e04c3fSmrg   read_program_resource_list(blob, prog);
133801e04c3fSmrg
133901e04c3fSmrg   return !blob->overrun;
134001e04c3fSmrg}
1341