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 #ifndef TENSORFLOW_LITE_DELEGATES_GPU_GL_OBJECT_H_
17 #define TENSORFLOW_LITE_DELEGATES_GPU_GL_OBJECT_H_
18
19 #include <array>
20 #include <cstdint>
21 #include <cstring>
22 #include <string>
23 #include <vector>
24
25 #include "absl/types/variant.h"
26 #include "tensorflow/lite/delegates/gpu/common/access_type.h"
27 #include "tensorflow/lite/delegates/gpu/common/data_type.h"
28 #include "tensorflow/lite/delegates/gpu/common/shape.h"
29 #include "tensorflow/lite/delegates/gpu/common/types.h"
30 #include "tensorflow/lite/delegates/gpu/common/util.h"
31
32 namespace tflite {
33 namespace gpu {
34 namespace gl {
35
36 using ObjectData = std::vector<uint8_t>;
37
38 // Generic identifier to be used to lookup an object.
39 using ObjectRef = uint32_t;
40
41 constexpr ObjectRef kInvalidObjectRef = ~0;
42
43 enum class ObjectType : int {
44 UNKNOWN = 0,
45 TEXTURE = 1,
46 BUFFER = 2,
47 };
48
49 using ObjectSize = absl::variant<size_t, uint2, uint3>;
50
51 // An object represents a reference to or pre-defined constant OpenGL Buffer or
52 // Texture. NodeShader is supposed to set all fields but leave binding = 0
53 // that will be set later by a compiler.
54 struct Object {
55 AccessType access;
56
57 DataType data_type;
58
59 ObjectType object_type;
60
61 // OpenGL-specific binding information
62 uint32_t binding;
63
64 // Indicates size of 1D, 2D or 3D object in elements, where single element
65 // consists of 4 values.
66 ObjectSize size;
67
68 absl::variant<ObjectData, ObjectRef> object;
69 };
70
71 // @return true if object is a reference.
IsRef(const Object & object)72 inline bool IsRef(const Object& object) {
73 return !absl::holds_alternative<ObjectData>(object.object);
74 }
75
GetRef(const Object & object)76 inline ObjectRef GetRef(const Object& object) {
77 auto ref = absl::get_if<ObjectRef>(&object.object);
78 return ref ? *ref : kInvalidObjectRef;
79 }
80
GetData(const Object & object)81 inline const ObjectData* GetData(const Object& object) {
82 return absl::get_if<ObjectData>(&object.object);
83 }
84
85 inline size_t ByteSizeOf(const Object& object);
86
87 // @return object that references an object created externally.
MakeObjectRef(ObjectRef unique_id,const ObjectSize & size,AccessType access_type)88 inline Object MakeObjectRef(ObjectRef unique_id, const ObjectSize& size,
89 AccessType access_type) {
90 return Object{access_type, DataType::FLOAT32, ObjectType::UNKNOWN, 0,
91 size, unique_id};
92 }
93
94 namespace internal_object {
95
96 template <typename T>
ToBytesVector(const std::vector<T> & data,size_t alignment)97 std::vector<uint8_t> ToBytesVector(const std::vector<T>& data,
98 size_t alignment) {
99 std::vector<uint8_t> t(AlignByN(data.size() * sizeof(T), alignment));
100 std::memcpy(t.data(), data.data(), data.size() * sizeof(T));
101 return t;
102 }
103
104 struct ObjectSizer {
operatorObjectSizer105 size_t operator()(const uint3& size) const {
106 return size.x * size.y * size.z;
107 }
108
operatorObjectSizer109 size_t operator()(const uint2& size) const { return size.x * size.y; }
110
operatorObjectSizer111 size_t operator()(uint32_t size) const { return size; }
112 };
113
114 } // namespace internal_object
115
NumElements(const ObjectSize & size)116 inline size_t NumElements(const ObjectSize& size) {
117 return absl::visit(internal_object::ObjectSizer{}, size);
118 }
119
ByteSizeOf(const Object & object)120 inline size_t ByteSizeOf(const Object& object) {
121 return SizeOf(object.data_type) * /* vec4 */ 4 * NumElements(object.size);
122 }
123
MakeReadonlyObject(const ObjectSize & size,const std::vector<float> & data)124 inline Object MakeReadonlyObject(const ObjectSize& size,
125 const std::vector<float>& data) {
126 return Object{AccessType::READ,
127 DataType::FLOAT32,
128 ObjectType::UNKNOWN,
129 0,
130 size,
131 internal_object::ToBytesVector(data, 16)};
132 }
133
MakeReadonlyTexture(const ObjectSize & size,const std::vector<float> & data)134 inline Object MakeReadonlyTexture(const ObjectSize& size,
135 const std::vector<float>& data) {
136 return Object{AccessType::READ,
137 DataType::FLOAT32,
138 ObjectType::TEXTURE,
139 0,
140 size,
141 internal_object::ToBytesVector(data, 16)};
142 }
143
MakeReadonlyBuffer(const ObjectSize & size,const std::vector<float> & data)144 inline Object MakeReadonlyBuffer(const ObjectSize& size,
145 const std::vector<float>& data) {
146 return Object{AccessType::READ,
147 DataType::FLOAT32,
148 ObjectType::BUFFER,
149 0,
150 size,
151 internal_object::ToBytesVector(data, 16)};
152 }
153
MakeReadonlyObject(const std::vector<float> & data)154 inline Object MakeReadonlyObject(const std::vector<float>& data) {
155 return MakeReadonlyObject(
156 DivideRoundUp(static_cast<uint32_t>(data.size()), 4U), data);
157 }
158
MakeReadonlyTexture(const std::vector<float> & data)159 inline Object MakeReadonlyTexture(const std::vector<float>& data) {
160 return MakeReadonlyTexture(
161 DivideRoundUp(static_cast<uint32_t>(data.size()), 4U), data);
162 }
163
MakeReadonlyBuffer(const std::vector<float> & data)164 inline Object MakeReadonlyBuffer(const std::vector<float>& data) {
165 return MakeReadonlyBuffer(
166 DivideRoundUp(static_cast<uint32_t>(data.size()), 4U), data);
167 }
168
169 // TODO(akulik): find better place for functions below.
170
GetPHWC4Size(const BHWC & shape)171 inline uint3 GetPHWC4Size(const BHWC& shape) {
172 uint3 size;
173 size.x = shape.w;
174 size.y = shape.h;
175 size.z = shape.b * DivideRoundUp(shape.c, 4);
176 return size;
177 }
178
MakePHWC4Ref(uint32_t global_id,const BHWC & shape)179 inline Object MakePHWC4Ref(uint32_t global_id, const BHWC& shape) {
180 return MakeObjectRef(global_id, GetPHWC4Size(shape), AccessType::READ_WRITE);
181 }
182
183 } // namespace gl
184 } // namespace gpu
185 } // namespace tflite
186
187 #endif // TENSORFLOW_LITE_DELEGATES_GPU_GL_OBJECT_H_
188