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, ¶meter));
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