• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/lite/delegates/gpu/gl/serialization.h"
17 
18 #include "absl/types/variant.h"
19 #include "tensorflow/lite/delegates/gpu/common/data_type.h"
20 #include "tensorflow/lite/delegates/gpu/common/status.h"
21 #include "tensorflow/lite/delegates/gpu/common/types.h"
22 #include "tensorflow/lite/delegates/gpu/gl/variable.h"
23 
24 namespace tflite {
25 namespace gpu {
26 namespace gl {
27 
28 using flatbuffers::Offset;
29 using flatbuffers::Vector;
30 
31 namespace {
32 
33 struct ParameterValueGetter {
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter34   Offset<void> operator()(int32_t value) {
35     auto offset = builder->CreateVector(std::vector<int32_t>{value});
36     data::DataInt32Builder data(*builder);
37     data.add_data(offset);
38     return data.Finish().Union();
39   }
40 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter41   Offset<void> operator()(const int2& value) {
42     auto offset = builder->CreateVector(std::vector<int32_t>{value.x, value.y});
43     data::DataInt32Builder data(*builder);
44     data.add_data(offset);
45     return data.Finish().Union();
46   }
47 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter48   Offset<void> operator()(const int4& value) {
49     auto offset = builder->CreateVector(
50         std::vector<int32_t>{value.x, value.y, value.z, value.w});
51     data::DataInt32Builder data(*builder);
52     data.add_data(offset);
53     return data.Finish().Union();
54   }
55 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter56   Offset<void> operator()(const std::vector<int2>& value) {
57     std::vector<int32_t> d(value.size() * 2);
58     for (size_t i = 0; i < value.size(); ++i) {
59       d[i * 2] = value[i].x;
60       d[i * 2 + 1] = value[i].y;
61     }
62     auto offset = builder->CreateVector(d);
63     data::DataInt32Builder data(*builder);
64     data.add_data(offset);
65     return data.Finish().Union();
66   }
67 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter68   Offset<void> operator()(uint32_t value) {
69     auto offset = builder->CreateVector(std::vector<uint32_t>{value});
70     data::DataUint32Builder data(*builder);
71     data.add_data(offset);
72     return data.Finish().Union();
73   }
74 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter75   Offset<void> operator()(const uint4& value) {
76     auto offset = builder->CreateVector(
77         std::vector<uint32_t>{value.x, value.y, value.z, value.w});
78     data::DataUint32Builder data(*builder);
79     data.add_data(offset);
80     return data.Finish().Union();
81   }
82 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter83   Offset<void> operator()(float value) {
84     auto offset = builder->CreateVector(std::vector<float>{value});
85     data::DataFloatBuilder data(*builder);
86     data.add_data(offset);
87     return data.Finish().Union();
88   }
89 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter90   Offset<void> operator()(const float2& value) {
91     auto offset = builder->CreateVector(std::vector<float>{value.x, value.y});
92     data::DataFloatBuilder data(*builder);
93     data.add_data(offset);
94     return data.Finish().Union();
95   }
96 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter97   Offset<void> operator()(const float4& value) {
98     auto offset = builder->CreateVector(
99         std::vector<float>{value.x, value.y, value.z, value.w});
100     data::DataFloatBuilder data(*builder);
101     data.add_data(offset);
102     return data.Finish().Union();
103   }
104 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterValueGetter105   Offset<void> operator()(const std::vector<float4>& value) {
106     std::vector<float> d(value.size() * 4);
107     for (size_t i = 0; i < value.size(); ++i) {
108       d[i * 4] = value[i].x;
109       d[i * 4 + 1] = value[i].y;
110       d[i * 4 + 2] = value[i].z;
111       d[i * 4 + 3] = value[i].w;
112     }
113     auto offset = builder->CreateVector(d);
114     data::DataFloatBuilder data(*builder);
115     data.add_data(offset);
116     return data.Finish().Union();
117   }
118 
119   ::flatbuffers::FlatBufferBuilder* builder;
120 };
121 
122 struct DataVariantTypeGetter {
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter123   data::DataVariant operator()(int32_t) const {
124     return data::DataVariant::DataInt32;
125   }
126 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter127   data::DataVariant operator()(const int2&) const {
128     return data::DataVariant::DataInt32;
129   }
130 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter131   data::DataVariant operator()(const int4&) const {
132     return data::DataVariant::DataInt32;
133   }
134 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter135   data::DataVariant operator()(const std::vector<int2>&) const {
136     return data::DataVariant::DataInt32;
137   }
138 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter139   data::DataVariant operator()(uint32_t) const {
140     return data::DataVariant::DataUint32;
141   }
142 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter143   data::DataVariant operator()(const uint4&) const {
144     return data::DataVariant::DataUint32;
145   }
146 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter147   data::DataVariant operator()(float) const {
148     return data::DataVariant::DataFloat;
149   }
150 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter151   data::DataVariant operator()(const float2&) const {
152     return data::DataVariant::DataFloat;
153   }
154 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter155   data::DataVariant operator()(const float4&) const {
156     return data::DataVariant::DataFloat;
157   }
158 
operator ()tflite::gpu::gl::__anon37d11ee50111::DataVariantTypeGetter159   data::DataVariant operator()(const std::vector<float4>&) const {
160     return data::DataVariant::DataFloat;
161   }
162 };
163 
164 struct ParameterTypeGetter {
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter165   data::ParameterType operator()(int32_t) const {
166     return data::ParameterType::INT32;
167   }
168 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter169   data::ParameterType operator()(const int2&) const {
170     return data::ParameterType::INT32;
171   }
172 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter173   data::ParameterType operator()(const int4&) const {
174     return data::ParameterType::INT32;
175   }
176 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter177   data::ParameterType operator()(const std::vector<int2>&) const {
178     return data::ParameterType::INT32_2;
179   }
180 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter181   data::ParameterType operator()(uint32_t) const {
182     return data::ParameterType::UINT32;
183   }
184 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter185   data::ParameterType operator()(const uint4&) const {
186     return data::ParameterType::UINT32;
187   }
188 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter189   data::ParameterType operator()(float) const {
190     return data::ParameterType::FLOAT32;
191   }
192 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter193   data::ParameterType operator()(const float2&) const {
194     return data::ParameterType::FLOAT32;
195   }
196 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter197   data::ParameterType operator()(const float4&) const {
198     return data::ParameterType::FLOAT32;
199   }
200 
operator ()tflite::gpu::gl::__anon37d11ee50111::ParameterTypeGetter201   data::ParameterType operator()(const std::vector<float4>&) const {
202     return data::ParameterType::FLOAT32;
203   }
204 };
205 
ToFB(DataType type)206 data::DataType ToFB(DataType type) {
207   switch (type) {
208     case DataType::INT16:
209       return data::DataType::INT16;
210     case DataType::INT32:
211       return data::DataType::INT32;
212     case DataType::FLOAT16:
213       return data::DataType::FLOAT16;
214     case DataType::FLOAT32:
215       return data::DataType::FLOAT32;
216     default:
217       return data::DataType::UNKNOWN;
218   }
219 }
220 
ToFB(ObjectType type)221 data::ObjectType ToFB(ObjectType type) {
222   switch (type) {
223     case ObjectType::TEXTURE:
224       return data::ObjectType::TEXTURE;
225     case ObjectType::BUFFER:
226       return data::ObjectType::BUFFER;
227     default:
228       return data::ObjectType::UNKNOWN;
229   }
230 }
231 
232 struct ObjectSizeGetter {
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectSizeGetter233   Offset<void> operator()(const uint3& shape) {
234     data::Uint3Builder shape_builder(*builder);
235     shape_builder.add_x(shape.x);
236     shape_builder.add_y(shape.y);
237     shape_builder.add_z(shape.z);
238     return shape_builder.Finish().Union();
239   }
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectSizeGetter240   Offset<void> operator()(const uint2& shape) {
241     data::Uint2Builder shape_builder(*builder);
242     shape_builder.add_x(shape.x);
243     shape_builder.add_y(shape.y);
244     return shape_builder.Finish().Union();
245   }
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectSizeGetter246   Offset<void> operator()(uint32_t shape) {
247     data::Uint1Builder shape_builder(*builder);
248     shape_builder.add_x(shape);
249     return shape_builder.Finish().Union();
250   }
251 
252   ::flatbuffers::FlatBufferBuilder* builder;
253 };
254 
255 struct ObjectSizeTypeGetter {
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectSizeTypeGetter256   data::ObjectSize operator()(const uint3&) const {
257     return data::ObjectSize::Uint3;
258   }
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectSizeTypeGetter259   data::ObjectSize operator()(const uint2&) const {
260     return data::ObjectSize::Uint2;
261   }
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectSizeTypeGetter262   data::ObjectSize operator()(const uint32_t&) const {
263     return data::ObjectSize::Uint1;
264   }
265 };
266 
267 struct ObjectGetter {
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectGetter268   Offset<void> operator()(const ObjectData& data) {
269     auto fb_data = builder->CreateVector(data);
270     data::ObjectDataBuilder data_builder(*builder);
271     data_builder.add_data(fb_data);
272     return data_builder.Finish().Union();
273   }
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectGetter274   Offset<void> operator()(ObjectRef ref) {
275     data::ObjectRefBuilder ref_builder(*builder);
276     ref_builder.add_global_id(ref);
277     return ref_builder.Finish().Union();
278   }
279 
280   ::flatbuffers::FlatBufferBuilder* builder;
281 };
282 
283 struct ObjectTypeGetter {
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectTypeGetter284   data::ObjectVariant operator()(const ObjectData&) const {
285     return data::ObjectVariant::ObjectData;
286   }
operator ()tflite::gpu::gl::__anon37d11ee50111::ObjectTypeGetter287   data::ObjectVariant operator()(const ObjectRef&) const {
288     return data::ObjectVariant::ObjectRef;
289   }
290 };
291 
ToFB(AccessType type)292 data::AccessType ToFB(AccessType type) {
293   switch (type) {
294     case AccessType::READ:
295       return data::AccessType::READ;
296     case AccessType::WRITE:
297       return data::AccessType::WRITE;
298     case AccessType::READ_WRITE:
299       return data::AccessType::READ_WRITE;
300   }
301 }
302 
Encode(const uint3 & v,::flatbuffers::FlatBufferBuilder * builder)303 Offset<data::Uint3> Encode(const uint3& v,
304                            ::flatbuffers::FlatBufferBuilder* builder) {
305   data::Uint3Builder uint3_builder(*builder);
306   uint3_builder.add_x(v.x);
307   uint3_builder.add_y(v.y);
308   uint3_builder.add_z(v.z);
309   return uint3_builder.Finish();
310 }
311 
Encode(const CompiledModelOptions & options,::flatbuffers::FlatBufferBuilder * builder)312 Offset<data::Parameters> Encode(const CompiledModelOptions& options,
313                                 ::flatbuffers::FlatBufferBuilder* builder) {
314   data::ParametersBuilder params_builder(*builder);
315   params_builder.add_dynamic_batch(options.dynamic_batch);
316   return params_builder.Finish();
317 }
318 
319 }  // namespace
320 
AddShader(const std::string & shader_src)321 void SerializedCompiledModelBuilder::AddShader(const std::string& shader_src) {
322   shaders_.push_back(builder_.CreateString(shader_src));
323 }
324 
AddProgram(const std::vector<Variable> & parameters,const std::vector<Object> & objects,const uint3 & workgroup_size,const uint3 & num_workgroups,size_t shader_index)325 void SerializedCompiledModelBuilder::AddProgram(
326     const std::vector<Variable>& parameters, const std::vector<Object>& objects,
327     const uint3& workgroup_size, const uint3& num_workgroups,
328     size_t shader_index) {
329   Offset<data::Uint3> fb_workgroups = Encode(num_workgroups, &builder_);
330   Offset<data::Uint3> fb_workgroup_size = Encode(workgroup_size, &builder_);
331 
332   Offset<Vector<Offset<data::UniformParameter>>> fb_params;
333   {
334     std::vector<Offset<data::UniformParameter>> offsets;
335     for (const Variable& param : parameters) {
336       auto name = builder_.CreateString(param.name);
337       auto data = absl::visit(ParameterValueGetter{&builder_}, param.value);
338       data::UniformParameterBuilder builder(builder_);
339       builder.add_name(name);
340       builder.add_data_type(absl::visit(DataVariantTypeGetter{}, param.value));
341       builder.add_data(data);
342       builder.add_type(absl::visit(ParameterTypeGetter{}, param.value));
343       offsets.push_back(builder.Finish());
344     }
345     fb_params = builder_.CreateVector(offsets);
346   }
347 
348   Offset<Vector<Offset<data::Object>>> fb_objects;
349   {
350     std::vector<Offset<data::Object>> offsets;
351     for (const Object& object : objects) {
352       auto object_variant = absl::visit(ObjectGetter{&builder_}, object.object);
353       auto size = absl::visit(ObjectSizeGetter{&builder_}, object.size);
354 
355       data::ObjectBuilder builder(builder_);
356       builder.add_access(ToFB(object.access));
357       builder.add_binding(object.binding);
358       builder.add_type(ToFB(object.object_type));
359       builder.add_data_type(ToFB(object.data_type));
360       builder.add_size_type(absl::visit(ObjectSizeTypeGetter{}, object.size));
361       builder.add_size(size);
362       builder.add_object_type(absl::visit(ObjectTypeGetter{}, object.object));
363       builder.add_object(object_variant);
364       offsets.push_back(builder.Finish());
365     }
366     fb_objects = builder_.CreateVector(offsets);
367   }
368 
369   data::ProgramBuilder program_builder(builder_);
370   program_builder.add_number_workgroups(fb_workgroups);
371   program_builder.add_workgroup_size(fb_workgroup_size);
372   program_builder.add_parameters(fb_params);
373   program_builder.add_objects(fb_objects);
374   program_builder.add_shader_index(shader_index);
375   programs_.push_back(program_builder.Finish());
376 }
377 
Finalize(const CompiledModelOptions & options)378 absl::Span<const uint8_t> SerializedCompiledModelBuilder::Finalize(
379     const CompiledModelOptions& options) {
380   auto shaders = builder_.CreateVector(shaders_);
381   auto programs = builder_.CreateVector(programs_);
382   auto parameters = Encode(options, &builder_);
383   data::CompiledModelBuilder model_builder(builder_);
384   model_builder.add_shaders(shaders);
385   model_builder.add_programs(programs);
386   model_builder.add_parameters(parameters);
387   data::FinishCompiledModelBuffer(builder_, model_builder.Finish());
388   return absl::MakeConstSpan(builder_.GetBufferPointer(), builder_.GetSize());
389 }
390 
391 namespace {
392 
ParseParameter(const data::UniformParameter & fb_parameter,Variable * parameter)393 absl::Status ParseParameter(const data::UniformParameter& fb_parameter,
394                             Variable* parameter) {
395   parameter->name = fb_parameter.name()->str();
396   switch (fb_parameter.type()) {
397     case data::ParameterType::INT32: {
398       auto* ptr = fb_parameter.data_as_DataInt32();
399       if (ptr == nullptr) {
400         return absl::InvalidArgumentError("Unexpected data type '" +
401                                           parameter->name + "'");
402       }
403       switch (ptr->data()->size()) {
404         case 1:
405           parameter->value = (*ptr->data())[0];
406           break;
407         case 2:
408           parameter->value = int2((*ptr->data())[0], (*ptr->data())[1]);
409           break;
410         case 4:
411           parameter->value = int4((*ptr->data())[0], (*ptr->data())[1],
412                                   (*ptr->data())[2], (*ptr->data())[3]);
413           break;
414         default:
415           return absl::InvalidArgumentError("Unexpected size for parameter '" +
416                                             parameter->name + "'");
417       }
418       break;
419     }
420     case data::ParameterType::UINT32: {
421       auto* ptr = fb_parameter.data_as_DataUint32();
422       if (ptr == nullptr) {
423         return absl::InvalidArgumentError("Unexpected data type '" +
424                                           parameter->name + "'");
425       }
426       switch (ptr->data()->size()) {
427         case 1:
428           parameter->value = (*ptr->data())[0];
429           break;
430         case 4:
431           parameter->value = uint4((*ptr->data())[0], (*ptr->data())[1],
432                                    (*ptr->data())[2], (*ptr->data())[3]);
433           break;
434         default:
435           return absl::InvalidArgumentError("Unexpected size for parameter '" +
436                                             parameter->name + "'");
437       }
438       break;
439     }
440     case data::ParameterType::FLOAT32: {
441       auto* ptr = fb_parameter.data_as_DataFloat();
442       if (ptr == nullptr) {
443         return absl::InvalidArgumentError("Unexpected data type '" +
444                                           parameter->name + "'");
445       }
446       switch (ptr->data()->size()) {
447         case 1:
448           parameter->value = (*ptr->data())[0];
449           break;
450         case 2:
451           parameter->value = float2((*ptr->data())[0], (*ptr->data())[1]);
452           break;
453         case 4:
454           parameter->value = float4((*ptr->data())[0], (*ptr->data())[1],
455                                     (*ptr->data())[2], (*ptr->data())[3]);
456           break;
457         default:
458           return absl::InvalidArgumentError("Unexpected size for parameter '" +
459                                             parameter->name + "'");
460       }
461       break;
462     }
463     case data::ParameterType::INT32_2: {
464       auto* ptr = fb_parameter.data_as_DataInt32();
465       if (ptr == nullptr) {
466         return absl::InvalidArgumentError("Unexpected data type '" +
467                                           parameter->name + "'");
468       }
469 
470       if (ptr->data()->size() % 2 != 0) {
471         return absl::InvalidArgumentError("Unexpected size for parameter '" +
472                                           parameter->name + "'");
473       }
474 
475       std::vector<int2> values(ptr->data()->size() / 2);
476       for (int i = 0; i < values.size(); ++i) {
477         values[i] = int2((*ptr->data())[i * 2], (*ptr->data())[i * 2 + 1]);
478       }
479       parameter->value = values;
480       break;
481     }
482   }
483   return absl::OkStatus();
484 }
485 
ToEnum(data::DataType type)486 DataType ToEnum(data::DataType type) {
487   switch (type) {
488     case data::DataType::INT16:
489       return DataType::INT16;
490     case data::DataType::INT32:
491       return DataType::INT32;
492     case data::DataType::FLOAT16:
493       return DataType::FLOAT16;
494     case data::DataType::FLOAT32:
495       return DataType::FLOAT32;
496     default:
497       return DataType::UNKNOWN;
498   }
499 }
500 
ToEnum(data::ObjectType type)501 ObjectType ToEnum(data::ObjectType type) {
502   switch (type) {
503     case data::ObjectType::TEXTURE:
504       return ObjectType::TEXTURE;
505     case data::ObjectType::BUFFER:
506       return ObjectType::BUFFER;
507     default:
508       return ObjectType::UNKNOWN;
509   }
510 }
511 
ToEnum(data::AccessType type)512 AccessType ToEnum(data::AccessType type) {
513   switch (type) {
514     case data::AccessType::READ:
515       return AccessType::READ;
516     case data::AccessType::WRITE:
517       return AccessType::WRITE;
518     case data::AccessType::READ_WRITE:
519       return AccessType::READ_WRITE;
520   }
521 }
522 
ParseObject(const data::Object & fb_object,Object * object)523 absl::Status ParseObject(const data::Object& fb_object, Object* object) {
524   object->access = ToEnum(fb_object.access());
525   object->binding = fb_object.binding();
526   object->object_type = ToEnum(fb_object.type());
527   object->data_type = ToEnum(fb_object.data_type());
528 
529   switch (fb_object.size_type()) {
530     case data::ObjectSize::Uint3: {
531       auto* size = fb_object.size_as_Uint3();
532       object->size = uint3(size->x(), size->y(), size->z());
533       break;
534     }
535     case data::ObjectSize::Uint2: {
536       auto* size = fb_object.size_as_Uint2();
537       object->size = uint2(size->x(), size->y());
538       break;
539     }
540     case data::ObjectSize::Uint1: {
541       auto* size = fb_object.size_as_Uint1();
542       object->size = size->x();
543       break;
544     }
545     case data::ObjectSize::NONE:
546       return absl::InvalidArgumentError("Texture size is not set");
547   }
548 
549   switch (fb_object.object_type()) {
550     case data::ObjectVariant::ObjectData: {
551       auto* fb_data = fb_object.object_as_ObjectData();
552       object->object = std::vector<uint8_t>(
553           fb_data->data()->data(),
554           fb_data->data()->data() + fb_data->data()->size());
555       break;
556     }
557     case data::ObjectVariant::ObjectRef: {
558       auto* fb_ref = fb_object.object_as_ObjectRef();
559       object->object = fb_ref->global_id();
560       break;
561     }
562     case data::ObjectVariant::NONE: {
563       return absl::InvalidArgumentError("Object is not set");
564     }
565   }
566   return absl::OkStatus();
567 }
568 
ParseParameters(const data::Parameters & fb_parameters)569 CompiledModelOptions ParseParameters(const data::Parameters& fb_parameters) {
570   CompiledModelOptions options;
571   options.dynamic_batch = fb_parameters.dynamic_batch();
572   return options;
573 }
574 
575 }  // namespace
576 
DeserializeCompiledModel(absl::Span<const uint8_t> serialized,DeserializationHandler * handler)577 absl::Status DeserializeCompiledModel(absl::Span<const uint8_t> serialized,
578                                       DeserializationHandler* handler) {
579   flatbuffers::Verifier verifier(serialized.data(), serialized.size());
580   if (!data::VerifyCompiledModelBuffer(verifier)) {
581     return absl::InvalidArgumentError("Serialized model is corrupted.");
582   }
583 
584   auto model = data::GetCompiledModel(serialized.data());
585   for (auto shader : *model->shaders()) {
586     RETURN_IF_ERROR(
587         handler->OnShader(absl::MakeSpan(shader->c_str(), shader->size())));
588   }
589   std::vector<Variable> parameters;
590   std::vector<Object> objects;
591   for (auto program : *model->programs()) {
592     parameters.clear();
593     objects.clear();
594     for (auto fb_parameter : *program->parameters()) {
595       Variable parameter;
596       RETURN_IF_ERROR(ParseParameter(*fb_parameter, &parameter));
597       parameters.push_back(std::move(parameter));
598     }
599     for (auto fb_object : *program->objects()) {
600       Object object;
601       RETURN_IF_ERROR(ParseObject(*fb_object, &object));
602       objects.push_back(std::move(object));
603     }
604     uint3 workgroup_size(program->workgroup_size()->x(),
605                          program->workgroup_size()->y(),
606                          program->workgroup_size()->z());
607     uint3 num_workgroups(program->number_workgroups()->x(),
608                          program->number_workgroups()->y(),
609                          program->number_workgroups()->z());
610     RETURN_IF_ERROR(handler->OnProgram(parameters, objects, workgroup_size,
611                                        num_workgroups,
612                                        program->shader_index()));
613   }
614   handler->OnOptions(ParseParameters(*model->parameters()));
615   return absl::OkStatus();
616 }
617 
618 }  // namespace gl
619 }  // namespace gpu
620 }  // namespace tflite
621