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