1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
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 "device_gles.h"
17
18 #include <algorithm>
19
20 #include <base/containers/string.h>
21 #include <base/math/vector.h>
22 #include <base/util/compile_time_hashes.h>
23 #include <render/namespace.h>
24
25 #include "device/gpu_acceleration_structure.h"
26 #include "device/gpu_program_util.h"
27 #include "device/gpu_resource_manager.h"
28 #include "device/shader_manager.h"
29 #include "device/shader_module.h"
30 #include "gles/gl_functions.h"
31 #include "gles/gpu_buffer_gles.h"
32 #include "gles/gpu_image_gles.h"
33 #include "gles/gpu_program_gles.h"
34 #include "gles/gpu_sampler_gles.h"
35 #include "gles/node_context_descriptor_set_manager_gles.h"
36 #include "gles/node_context_pool_manager_gles.h"
37 #include "gles/pipeline_state_object_gles.h"
38 #include "gles/render_backend_gles.h"
39 #include "gles/render_frame_sync_gles.h"
40 #include "gles/shader_module_gles.h"
41 #include "gles/swapchain_gles.h"
42 #include "util/log.h"
43
44 using namespace BASE_NS;
45
46 RENDER_BEGIN_NAMESPACE()
47 namespace {
48 // Make all temporary binds to unit GL_TEXTURE15. (should use the last available unit, so as to least affect actual
49 // usage) "The number of texture units is implementation-dependent, but must be at least 32. texture must be one of
50 // GL_TEXTUREi, where i ranges from zero to the value of GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS minus one." Currently our
51 // there is an implementation limit in our resource caching which limits it to 16... (this is why we use 16 instead of
52 // 32)
53 constexpr const uint32_t TEMP_BIND_UNIT = 15;
54 #if RENDER_GL_DEBUG
55 #define DUMP(a) \
56 { \
57 GLint val; \
58 glGetIntegerv(a, &val); \
59 PLUGIN_LOG_V(#a ": %d", val); \
60 }
61
62 #define DUMP_INDEX(a, index) \
63 { \
64 GLint val; \
65 glGetIntegeri_v(a, index, &val); \
66 PLUGIN_LOG_V(#a "[%d]: %d", index, val); \
67 }
68 static bool (*filterErrorFunc)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
69 const string_view message, const void* userParam) noexcept = nullptr;
70 #define DOCASE(x) \
71 case x: \
72 return #x; \
73 break;
SourceName(GLenum source)74 static auto SourceName(GLenum source)
75 {
76 switch (source) {
77 DOCASE(GL_DEBUG_SOURCE_API);
78 DOCASE(GL_DEBUG_SOURCE_WINDOW_SYSTEM);
79 DOCASE(GL_DEBUG_SOURCE_SHADER_COMPILER);
80 DOCASE(GL_DEBUG_SOURCE_THIRD_PARTY);
81 DOCASE(GL_DEBUG_SOURCE_APPLICATION);
82 DOCASE(GL_DEBUG_SOURCE_OTHER);
83 default:
84 break;
85 }
86 return "UNKNOWN";
87 }
TypeName(GLenum type)88 static auto TypeName(GLenum type)
89 {
90 switch (type) {
91 DOCASE(GL_DEBUG_TYPE_ERROR);
92 DOCASE(GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR);
93 DOCASE(GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR);
94 DOCASE(GL_DEBUG_TYPE_PORTABILITY);
95 DOCASE(GL_DEBUG_TYPE_PERFORMANCE);
96 DOCASE(GL_DEBUG_TYPE_MARKER);
97 DOCASE(GL_DEBUG_TYPE_PUSH_GROUP);
98 DOCASE(GL_DEBUG_TYPE_POP_GROUP);
99 DOCASE(GL_DEBUG_TYPE_OTHER);
100 default:
101 break;
102 }
103 return "UNKNOWN";
104 }
SeverityName(GLenum severity)105 static auto SeverityName(GLenum severity)
106 {
107 switch (severity) {
108 DOCASE(GL_DEBUG_SEVERITY_LOW);
109 DOCASE(GL_DEBUG_SEVERITY_MEDIUM);
110 DOCASE(GL_DEBUG_SEVERITY_HIGH);
111 DOCASE(GL_DEBUG_SEVERITY_NOTIFICATION);
112 default:
113 break;
114 }
115 return "UNKNOWN";
116 }
117 #ifndef APIENTRY
118 #define APIENTRY
119 #endif
OnGlError(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)120 static void APIENTRY OnGlError(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
121 const GLchar* message, const void* userParam) noexcept
122 {
123 if (type == GL_DEBUG_TYPE_PUSH_GROUP) {
124 return;
125 } else if (type == GL_DEBUG_TYPE_POP_GROUP) {
126 return;
127 } else if ((filterErrorFunc) && (filterErrorFunc(source, type, id, severity, length, message, userParam))) {
128 return;
129 } else if (type == GL_DEBUG_TYPE_ERROR) {
130 PLUGIN_LOG_E("---------------------opengl-callback-start------------\n"
131 "source: %s\n"
132 "type: %s\n"
133 "id: %d\n"
134 "severity: %s\n"
135 "message: %s\n"
136 "---------------------opengl-callback-end--------------\n",
137 SourceName(source), TypeName(type), id, SeverityName(severity), message);
138 } else {
139 PLUGIN_LOG_D("---------------------opengl-callback-start------------\n"
140 "source: %s\n"
141 "type: %s\n"
142 "id: %d\n"
143 "severity: %s\n"
144 "message: %s\n"
145 "---------------------opengl-callback-end--------------\n",
146 SourceName(source), TypeName(type), id, SeverityName(severity), message);
147 }
148 }
149 #else
150 #define DUMP(a)
151 #define DUMP_INDEX(a, index)
152 #endif
153
154 // Dont allow SRGB_R8 and SRGB_R8G8 internal formats, instead use the GL_SRGB8 with swizzle as workaround.
155 #define USE_EXTENSION_FORMATS
156
157 #define BLOCK_BITS_8 1
158 #define BLOCK_BITS_16 2
159 #define BLOCK_BITS_32 4
160 #define BLOCK_BITS_64 8
161 #define BLOCK_BITS_128 16
162
163 // GL_EXT_texture_sRGB_R8 extension
164 #if (defined(GL_EXT_texture_sRGB_R8) && (GL_EXT_texture_sRGB_R8))
165 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_SRGB_R8[] = {
166 { BASE_FORMAT_R8_SRGB, GL_RED, GL_SR8_EXT, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
167 { GL_RED, GL_ZERO, GL_ZERO, GL_ONE } },
168 };
169 #endif
170
171 // GL_EXT_texture_sRGB_RG8 extension
172 #if (defined(GL_EXT_texture_sRGB_RG8) && (GL_EXT_texture_sRGB_RG8))
173 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_SRGB_RG8[] = {
174 { BASE_FORMAT_R8G8_SRGB, GL_RG, GL_SRG8_EXT, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
175 { GL_RED, GL_GREEN, GL_ZERO, GL_ONE } },
176 };
177 #endif
178
179 // GL_EXT_texture_sRGB extension
180 #if defined(GL_EXT_texture_sRGB) && (GL_EXT_texture_sRGB)
181 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_SRGB[] = {
182 { BASE_FORMAT_BC1_RGB_SRGB_BLOCK, GL_RGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, 0,
183 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
184 { BASE_FORMAT_BC1_RGBA_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, 0,
185 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
186 { BASE_FORMAT_BC2_SRGB_BLOCK, GL_RGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE, 0,
187 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
188 { BASE_FORMAT_BC3_SRGB_BLOCK, GL_RGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE, 0,
189 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
190 };
191 #endif
192
193 // GL_EXT_texture_format_BGRA8888 extension
194 #if defined(GL_EXT_texture_format_BGRA8888) && (GL_EXT_texture_format_BGRA8888)
195 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_BGRA[] = {
196 { BASE_FORMAT_B8G8R8A8_UNORM, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 4, { false, 0, 0, 0 },
197 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
198 };
199 #endif
200
201 #if defined(GL_EXT_texture_norm16) && (GL_EXT_texture_norm16)
202 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_NORM16[] = {
203 { BASE_FORMAT_R16_UNORM, GL_RED, GL_R16_EXT, GL_UNSIGNED_SHORT, 2, { false, 0, 0, 0 },
204 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
205 { BASE_FORMAT_R16G16_UNORM, GL_RG, GL_RG16_EXT, GL_UNSIGNED_SHORT, 4, { false, 0, 0, 0 },
206 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
207 // three component UNORM format not supported -> fallback to half float
208 { BASE_FORMAT_R16G16B16_UNORM, GL_RGB, GL_RGB16F, GL_HALF_FLOAT, 6, { false, 0, 0, 0 },
209 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
210 { BASE_FORMAT_R16G16B16A16_UNORM, GL_RGBA, GL_RGBA16_EXT, GL_UNSIGNED_SHORT, 8, { false, 0, 0, 0 },
211 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
212 };
213 #endif
214
215 // GL_EXT_texture_compression_s3tc extension
216 #if defined(GL_EXT_texture_compression_s3tc) && (GL_EXT_texture_compression_s3tc)
217 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_S3TC[] = {
218 { BASE_FORMAT_BC1_RGB_UNORM_BLOCK, GL_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, 0,
219 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
220 { BASE_FORMAT_BC1_RGBA_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, 0,
221 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
222 { BASE_FORMAT_BC2_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE, 0,
223 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
224 { BASE_FORMAT_BC3_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE, 0,
225 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
226 };
227 #endif
228
229 // GL_ARB_texture_compression_bptc extension
230 #if defined(GL_ARB_texture_compression_bptc) && (GL_ARB_texture_compression_bptc)
231 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_BPTC[] = {
232 { BASE_FORMAT_BC7_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_UNSIGNED_BYTE, 0,
233 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
234 { BASE_FORMAT_BC7_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, GL_UNSIGNED_BYTE, 0,
235 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
236 { BASE_FORMAT_BC6H_SFLOAT_BLOCK, GL_RGB, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_FLOAT, 0,
237 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
238 { BASE_FORMAT_BC6H_UFLOAT_BLOCK, GL_RGB, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB, GL_FLOAT, 0,
239 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
240 };
241 #endif
242
243 // GL_EXT_texture_norm16 extension
244 #if defined(GL_EXT_texture_compression_rgtc) && (GL_EXT_texture_compression_rgtc)
245 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_EXT_RGTC[] = {
246 { BASE_FORMAT_BC4_UNORM_BLOCK, GL_RED, GL_COMPRESSED_RED_RGTC1_EXT, GL_UNSIGNED_BYTE, 0,
247 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
248 { BASE_FORMAT_BC4_SNORM_BLOCK, GL_RED, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, GL_UNSIGNED_BYTE, 0,
249 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
250 { BASE_FORMAT_BC5_UNORM_BLOCK, GL_RG, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, GL_UNSIGNED_BYTE, 0,
251 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
252 { BASE_FORMAT_BC5_SNORM_BLOCK, GL_RG, GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, GL_UNSIGNED_BYTE, 0,
253 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
254 };
255 #endif
256
257 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS_FALLBACK[] = {
258 { BASE_FORMAT_R4G4_UNORM_PACK8, GL_RG, GL_RGBA4, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
259 { GL_RED, GL_GREEN, GL_ZERO, GL_ONE } },
260 { BASE_FORMAT_B4G4R4A4_UNORM_PACK16, GL_RGBA, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, 2, { false, 0, 0, 0 },
261 { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
262 { BASE_FORMAT_B5G6R5_UNORM_PACK16, GL_RGB, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, 2, { false, 0, 0, 0 },
263 { GL_BLUE, GL_GREEN, GL_RED, GL_ONE } },
264 { BASE_FORMAT_B5G5R5A1_UNORM_PACK16, GL_RGBA, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, 2, { false, 0, 0, 0 },
265 { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
266 { BASE_FORMAT_A1R5G5B5_UNORM_PACK16, GL_RGBA, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, 2, { false, 0, 0, 0 },
267 { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
268
269 // not available in desktop, available as an extension in opengles. "GL_EXT_texture_sRGB_RG8"
270 { BASE_FORMAT_R8_SRGB, GL_RED, GL_SRGB8, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
271 { GL_RED, GL_ZERO, GL_ZERO, GL_ONE } },
272 { BASE_FORMAT_R8G8_SRGB, GL_RG, GL_SRGB8, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
273 { GL_RED, GL_GREEN, GL_ZERO, GL_ONE } },
274
275 { BASE_FORMAT_A2R10G10B10_UNORM_PACK32, GL_RGBA, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, 4, { false, 0, 0, 0 },
276 { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
277 { BASE_FORMAT_A2R10G10B10_UINT_PACK32, GL_RGBA, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, 4,
278 { false, 0, 0, 0 }, { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA } },
279
280 // available as an extension in opengles. "GL_EXT_texture_norm16" -> fallback to half float
281 { BASE_FORMAT_R16_UNORM, GL_RED, GL_R16F, GL_HALF_FLOAT, 2, { false, 0, 0, 0 },
282 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
283 { BASE_FORMAT_R16G16_UNORM, GL_RG, GL_RG16F, GL_HALF_FLOAT, 4, { false, 0, 0, 0 },
284 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
285 { BASE_FORMAT_R16G16B16_UNORM, GL_RGB, GL_RGB16F, GL_HALF_FLOAT, 6, { false, 0, 0, 0 },
286 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
287 { BASE_FORMAT_R16G16B16A16_UNORM, GL_RGBA, GL_RGBA16F, GL_HALF_FLOAT, 8, { false, 0, 0, 0 },
288 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
289 };
290
291 // NOTE: verify this table. add missing formats.
292 static constexpr DeviceGLES::ImageFormat IMAGE_FORMATS[] = {
293 { BASE_FORMAT_UNDEFINED, GL_NONE, GL_NONE, GL_NONE, 0, { false, 0, 0, 0 },
294 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
295 // These are required in GL and GLES
296 { BASE_FORMAT_R8_UNORM, GL_RED, GL_R8, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
297 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
298 { BASE_FORMAT_R8_SNORM, GL_RED, GL_R8, GL_BYTE, 1, { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
299 { BASE_FORMAT_R8G8_UNORM, GL_RG, GL_RG8, GL_UNSIGNED_BYTE, 2, { false, 0, 0, 0 },
300 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
301 { BASE_FORMAT_R8G8_SNORM, GL_RG, GL_RG8, GL_BYTE, 2, { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
302 { BASE_FORMAT_R5G6B5_UNORM_PACK16, GL_RGB, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, 2, { false, 0, 0, 0 },
303 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
304 { BASE_FORMAT_R8G8B8_UNORM, GL_RGB, GL_RGB8, GL_UNSIGNED_BYTE, 3, { false, 0, 0, 0 },
305 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
306 { BASE_FORMAT_R8G8B8_SNORM, GL_RGB, GL_RGB8, GL_BYTE, 3, { false, 0, 0, 0 },
307 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
308 { BASE_FORMAT_R4G4B4A4_UNORM_PACK16, GL_RGBA, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, 2, { false, 0, 0, 0 },
309 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
310 { BASE_FORMAT_R5G5B5A1_UNORM_PACK16, GL_RGBA, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, 2, { false, 0, 0, 0 },
311 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
312 { BASE_FORMAT_R8G8B8A8_UNORM, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, 4, { false, 0, 0, 0 },
313 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
314 { BASE_FORMAT_R8G8B8A8_SNORM, GL_RGBA, GL_RGBA8, GL_BYTE, 4, { false, 0, 0, 0 },
315 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
316 { BASE_FORMAT_A2B10G10R10_UNORM_PACK32, GL_RGBA, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, 4, { false, 0, 0, 0 },
317 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
318 { BASE_FORMAT_A2B10G10R10_UINT_PACK32, GL_RGBA, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, 4,
319 { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
320 { BASE_FORMAT_R8G8B8_SRGB, GL_RGB, GL_SRGB8, GL_UNSIGNED_BYTE, 3, { false, 0, 0, 0 },
321 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
322 { BASE_FORMAT_R8G8B8A8_SRGB, GL_RGBA, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, 4, { false, 0, 0, 0 },
323 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
324 { BASE_FORMAT_R16_SFLOAT, GL_RED, GL_R16F, GL_HALF_FLOAT, 2, { false, 0, 0, 0 },
325 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
326 { BASE_FORMAT_R16G16_SFLOAT, GL_RG, GL_RG16F, GL_HALF_FLOAT, 4, { false, 0, 0, 0 },
327 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
328 { BASE_FORMAT_R16G16B16_SFLOAT, GL_RGB, GL_RGB16F, GL_HALF_FLOAT, 6, { false, 0, 0, 0 },
329 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
330 { BASE_FORMAT_R16G16B16A16_SFLOAT, GL_RGBA, GL_RGBA16F, GL_HALF_FLOAT, 8, { false, 0, 0, 0 },
331 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
332 { BASE_FORMAT_R32_SFLOAT, GL_RED, GL_R32F, GL_FLOAT, 4, { false, 0, 0, 0 },
333 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
334 { BASE_FORMAT_R32G32_SFLOAT, GL_RG, GL_RG32F, GL_FLOAT, 8, { false, 0, 0, 0 },
335 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
336 { BASE_FORMAT_R32G32B32_SFLOAT, GL_RGB, GL_RGB32F, GL_FLOAT, 12, { false, 0, 0, 0 },
337 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
338 { BASE_FORMAT_R32G32B32A32_SFLOAT, GL_RGBA, GL_RGBA32F, GL_FLOAT, 16, { false, 0, 0, 0 },
339 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
340 // Special R11 G11 B10 float format. This format does not work with compute on GLES, but works as a texture. (this
341 // is handled elsewhere)
342 { BASE_FORMAT_B10G11R11_UFLOAT_PACK32, GL_RGB, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, 4,
343 { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
344 { BASE_FORMAT_E5B9G9R9_UFLOAT_PACK32, GL_RGB, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, 4, { false, 0, 0, 0 },
345 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
346 { BASE_FORMAT_R8_SINT, GL_RED_INTEGER, GL_R8I, GL_BYTE, 1, { false, 0, 0, 0 },
347 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
348 { BASE_FORMAT_R8_UINT, GL_RED_INTEGER, GL_R8UI, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
349 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
350 { BASE_FORMAT_R16_SINT, GL_RED_INTEGER, GL_R16I, GL_SHORT, 2, { false, 0, 0, 0 },
351 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
352 { BASE_FORMAT_R16_UINT, GL_RED_INTEGER, GL_R16UI, GL_UNSIGNED_SHORT, 2, { false, 0, 0, 0 },
353 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
354 { BASE_FORMAT_R32_SINT, GL_RED_INTEGER, GL_R32I, GL_INT, 4, { false, 0, 0, 0 },
355 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
356 { BASE_FORMAT_R32_UINT, GL_RED_INTEGER, GL_R32UI, GL_UNSIGNED_INT, 4, { false, 0, 0, 0 },
357 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
358 { BASE_FORMAT_R8G8_SINT, GL_RG_INTEGER, GL_RG8I, GL_BYTE, 2, { false, 0, 0, 0 },
359 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
360 { BASE_FORMAT_R8G8_UINT, GL_RG_INTEGER, GL_R8UI, GL_UNSIGNED_BYTE, 2, { false, 0, 0, 0 },
361 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
362 { BASE_FORMAT_R16G16_SINT, GL_RG_INTEGER, GL_RG16I, GL_SHORT, 4, { false, 0, 0, 0 },
363 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
364 { BASE_FORMAT_R16G16_UINT, GL_RG_INTEGER, GL_RG16UI, GL_UNSIGNED_SHORT, 4, { false, 0, 0, 0 },
365 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
366 { BASE_FORMAT_R32G32_SINT, GL_RG_INTEGER, GL_RG32I, GL_INT, 8, { false, 0, 0, 0 },
367 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
368 { BASE_FORMAT_R32G32_UINT, GL_RG_INTEGER, GL_RG32UI, GL_UNSIGNED_INT, 8, { false, 0, 0, 0 },
369 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
370 { BASE_FORMAT_R8G8B8_SINT, GL_RGB_INTEGER, GL_RGB8I, GL_BYTE, 3, { false, 0, 0, 0 },
371 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
372 { BASE_FORMAT_R8G8B8_UINT, GL_RGB_INTEGER, GL_RGB8UI, GL_UNSIGNED_BYTE, 3, { false, 0, 0, 0 },
373 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
374 { BASE_FORMAT_R16G16B16_SINT, GL_RGB_INTEGER, GL_RGB16I, GL_SHORT, 6, { false, 0, 0, 0 },
375 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
376 { BASE_FORMAT_R16G16B16_UINT, GL_RGB_INTEGER, GL_RGB16UI, GL_UNSIGNED_SHORT, 6, { false, 0, 0, 0 },
377 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
378 { BASE_FORMAT_R32G32B32_SINT, GL_RGB_INTEGER, GL_RGB32I, GL_INT, 12, { false, 0, 0, 0 },
379 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
380 { BASE_FORMAT_R32G32B32_UINT, GL_RGB_INTEGER, GL_RGB32UI, GL_UNSIGNED_INT, 12, { false, 0, 0, 0 },
381 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
382 { BASE_FORMAT_R8G8B8A8_SINT, GL_RGBA_INTEGER, GL_RGBA8I, GL_BYTE, 4, { false, 0, 0, 0 },
383 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
384 { BASE_FORMAT_R8G8B8A8_UINT, GL_RGBA_INTEGER, GL_RGBA8UI, GL_UNSIGNED_BYTE, 4, { false, 0, 0, 0 },
385 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
386 { BASE_FORMAT_R16G16B16A16_SINT, GL_RGBA_INTEGER, GL_RGBA16I, GL_SHORT, 8, { false, 0, 0, 0 },
387 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
388 { BASE_FORMAT_R16G16B16A16_UINT, GL_RGBA_INTEGER, GL_RGBA16UI, GL_UNSIGNED_SHORT, 8, { false, 0, 0, 0 },
389 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
390 { BASE_FORMAT_R32G32B32A32_SINT, GL_RGBA_INTEGER, GL_RGBA32I, GL_INT, 16, { false, 0, 0, 0 },
391 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
392 { BASE_FORMAT_R32G32B32A32_UINT, GL_RGBA_INTEGER, GL_RGBA32UI, GL_UNSIGNED_INT, 16, { false, 0, 0, 0 },
393 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
394 { BASE_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, 2, { false, 0, 0, 0 },
395 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
396 { BASE_FORMAT_X8_D24_UNORM_PACK32, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, 4, { false, 0, 0, 0 },
397 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
398 { BASE_FORMAT_D32_SFLOAT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT32F, GL_FLOAT, 4, { false, 0, 0, 0 },
399 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
400 { BASE_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH_STENCIL, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, 4, { false, 0, 0, 0 },
401 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
402 // DEPTH32F_STENCIL8 not in base formats
403 { BASE_FORMAT_S8_UINT, GL_STENCIL_INDEX, GL_STENCIL_INDEX8, GL_UNSIGNED_BYTE, 1, { false, 0, 0, 0 },
404 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
405 // EAC
406 { BASE_FORMAT_EAC_R11_UNORM_BLOCK, GL_RED, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, 0,
407 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
408 { BASE_FORMAT_EAC_R11_SNORM_BLOCK, GL_RED, GL_COMPRESSED_SIGNED_R11_EAC, GL_BYTE, 0, { true, 4, 4, BLOCK_BITS_64 },
409 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
410 { BASE_FORMAT_EAC_R11G11_UNORM_BLOCK, GL_RG, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, 0,
411 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
412 { BASE_FORMAT_EAC_R11G11_SNORM_BLOCK, GL_RG, GL_COMPRESSED_SIGNED_RG11_EAC, GL_BYTE, 0,
413 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
414 // ETC
415 { BASE_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, GL_RGB, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, 0,
416 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
417 { BASE_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, GL_RGB, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, 0,
418 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
419 { BASE_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, 0,
420 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
421 { BASE_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, 0,
422 { true, 4, 4, BLOCK_BITS_64 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
423 { BASE_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, 0,
424 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
425 { BASE_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, 0,
426 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
427 #if RENDER_HAS_GL_BACKEND
428 // required by GL
429 { BASE_FORMAT_R16_UNORM, GL_RED, GL_R16, GL_UNSIGNED_SHORT, 2, { false, 0, 0, 0 },
430 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
431 { BASE_FORMAT_R16_SNORM, GL_RED, GL_R16, GL_SHORT, 2, { false, 0, 0, 0 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
432 { BASE_FORMAT_R16G16_UNORM, GL_RG, GL_RG16, GL_UNSIGNED_SHORT, 4, { false, 0, 0, 0 },
433 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
434 { BASE_FORMAT_R16G16_SNORM, GL_RG, GL_RG16, GL_SHORT, 4, { false, 0, 0, 0 },
435 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
436 // GL_R3_G3_B2, RGB4, RGB5, RGB10, RGB12 not in base formats
437 { BASE_FORMAT_R16G16B16_UNORM, GL_RGB, GL_RGB16, GL_UNSIGNED_SHORT, 6, { false, 0, 0, 0 },
438 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
439 { BASE_FORMAT_R16G16B16_SNORM, GL_RGB, GL_RGB16, GL_SHORT, 6, { false, 0, 0, 0 },
440 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
441 // RGBA2, RGBA12 not in base formats
442 { BASE_FORMAT_R16G16B16A16_UNORM, GL_RGBA, GL_RGBA16, GL_UNSIGNED_SHORT, 8, { false, 0, 0, 0 },
443 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
444 { BASE_FORMAT_R16G16B16A16_SNORM, GL_RGBA, GL_RGBA16, GL_SHORT, 8, { false, 0, 0, 0 },
445 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
446 // STENCIL_INDEX1, STENCIL_INDEX4, STENCIL_INDEX16 not in base formats
447 { BASE_FORMAT_B4G4R4A4_UNORM_PACK16, GL_BGRA, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4_REV, 2, { false, 0, 0, 0 },
448 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
449 { BASE_FORMAT_A1R5G5B5_UNORM_PACK16, GL_BGRA, GL_RGB5_A1, GL_UNSIGNED_SHORT_1_5_5_5_REV, 2, { false, 0, 0, 0 },
450 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
451 { BASE_FORMAT_B5G6R5_UNORM_PACK16, GL_BGR, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5_REV, 2, { false, 0, 0, 0 },
452 { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
453 #elif RENDER_HAS_GLES_BACKEND
454 // required by GLES
455 { BASE_FORMAT_ASTC_4x4_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, 0,
456 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
457 { BASE_FORMAT_ASTC_5x4_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, 0,
458 { true, 5, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
459 { BASE_FORMAT_ASTC_5x5_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, 0,
460 { true, 5, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
461 { BASE_FORMAT_ASTC_6x5_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, 0,
462 { true, 6, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
463 { BASE_FORMAT_ASTC_6x6_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, 0,
464 { true, 6, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
465 { BASE_FORMAT_ASTC_8x5_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, 0,
466 { true, 8, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
467 { BASE_FORMAT_ASTC_8x6_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, 0,
468 { true, 8, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
469 { BASE_FORMAT_ASTC_8x8_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, 0,
470 { true, 8, 8, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
471 { BASE_FORMAT_ASTC_10x5_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, 0,
472 { true, 10, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
473 { BASE_FORMAT_ASTC_10x6_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, 0,
474 { true, 10, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
475 { BASE_FORMAT_ASTC_10x8_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, 0,
476 { true, 10, 8, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
477 { BASE_FORMAT_ASTC_10x10_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, 0,
478 { true, 10, 10, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
479 { BASE_FORMAT_ASTC_12x10_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, 0,
480 { true, 12, 10, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
481 { BASE_FORMAT_ASTC_12x12_UNORM_BLOCK, GL_RGBA, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, 0,
482 { true, 12, 12, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
483 { BASE_FORMAT_ASTC_4x4_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, 0,
484 { true, 4, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
485 { BASE_FORMAT_ASTC_5x4_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, 0,
486 { true, 5, 4, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
487 { BASE_FORMAT_ASTC_5x5_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, 0,
488 { true, 5, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
489 { BASE_FORMAT_ASTC_6x5_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, 0,
490 { true, 6, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
491 { BASE_FORMAT_ASTC_6x6_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, 0,
492 { true, 6, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
493 { BASE_FORMAT_ASTC_8x5_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, 0,
494 { true, 8, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
495 { BASE_FORMAT_ASTC_8x6_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, 0,
496 { true, 8, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
497 { BASE_FORMAT_ASTC_8x8_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, 0,
498 { true, 8, 8, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
499 { BASE_FORMAT_ASTC_10x5_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, 0,
500 { true, 10, 5, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
501 { BASE_FORMAT_ASTC_10x6_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, 0,
502 { true, 10, 6, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
503 { BASE_FORMAT_ASTC_10x8_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, 0,
504 { true, 10, 8, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
505 { BASE_FORMAT_ASTC_10x10_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, 0,
506 { true, 10, 10, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
507 { BASE_FORMAT_ASTC_12x10_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, 0,
508 { true, 12, 10, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
509 { BASE_FORMAT_ASTC_12x12_SRGB_BLOCK, GL_RGBA, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, 0,
510 { true, 12, 12, BLOCK_BITS_128 }, { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA } },
511 #endif
512 };
513
FillExtensionFormats(const DeviceGLES & device,BASE_NS::vector<DeviceGLES::ImageFormat> & sf)514 void FillExtensionFormats(const DeviceGLES& device, BASE_NS::vector<DeviceGLES::ImageFormat>& sf)
515 {
516 #if (defined(GL_EXT_texture_sRGB_R8) && (GL_EXT_texture_sRGB_R8))
517 if (device.HasExtension("GL_EXT_texture_sRGB_R8")) {
518 sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_SRGB_R8), std::end(IMAGE_FORMATS_EXT_SRGB_R8));
519 }
520 #endif
521
522 #if (defined(GL_EXT_texture_sRGB_RG8) && (GL_EXT_texture_sRGB_RG8))
523 if (device.HasExtension("GL_EXT_texture_sRGB_RG8")) {
524 sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_SRGB_RG8), std::end(IMAGE_FORMATS_EXT_SRGB_RG8));
525 }
526 #endif
527
528 #if defined(GL_EXT_texture_sRGB) && (GL_EXT_texture_sRGB)
529 if (device.HasExtension("GL_EXT_texture_sRGB")) {
530 sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_SRGB), std::end(IMAGE_FORMATS_EXT_SRGB));
531 }
532 #endif
533
534 #if defined(GL_EXT_texture_format_BGRA8888) && (GL_EXT_texture_format_BGRA8888)
535 if (device.HasExtension("GL_EXT_texture_format_BGRA8888")) {
536 sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_BGRA), std::end(IMAGE_FORMATS_EXT_BGRA));
537 }
538 #endif
539
540 #if defined(GL_EXT_texture_norm16) && (GL_EXT_texture_norm16)
541 if (device.HasExtension("GL_EXT_texture_norm16")) {
542 sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_NORM16), std::end(IMAGE_FORMATS_EXT_NORM16));
543 }
544 #endif
545
546 #if defined(GL_EXT_texture_compression_s3tc) && (GL_EXT_texture_compression_s3tc)
547 if (device.HasExtension("GL_EXT_texture_compression_s3tc")) {
548 sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_S3TC), std::end(IMAGE_FORMATS_EXT_S3TC));
549 }
550 #endif
551
552 #if defined(GL_ARB_texture_compression_bptc) && (GL_ARB_texture_compression_bptc)
553 if (device.HasExtension("GL_ARB_texture_compression_bptc")) {
554 sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_BPTC), std::end(IMAGE_FORMATS_EXT_BPTC));
555 }
556 #endif
557
558 #if defined(GL_EXT_texture_compression_rgtc) && (GL_EXT_texture_compression_rgtc)
559 if (device.HasExtension("GL_EXT_texture_compression_rgtc")) {
560 sf.insert(sf.end(), std::begin(IMAGE_FORMATS_EXT_RGTC), std::end(IMAGE_FORMATS_EXT_RGTC));
561 }
562 #endif
563 }
564 } // namespace
565
566 // Some OpenGL/ES features are supported and using them will lead to an assertion unless
567 // the following define is added locally or as part of the build command: #define HANDLE_UNSUPPORTED_ENUMS
TargetToBinding(uint32_t target)568 inline uint32_t DeviceGLES::TargetToBinding(uint32_t target)
569 {
570 if (target == GL_UNIFORM_BUFFER) {
571 return GL_UNIFORM_BUFFER_BINDING;
572 } else if (target == GL_SHADER_STORAGE_BUFFER) {
573 return GL_SHADER_STORAGE_BUFFER_BINDING;
574 } else if (target == GL_PIXEL_UNPACK_BUFFER) {
575 return GL_PIXEL_UNPACK_BUFFER_BINDING;
576 } else if (target == GL_COPY_READ_BUFFER) {
577 return GL_COPY_READ_BUFFER_BINDING;
578 } else if (target == GL_COPY_WRITE_BUFFER) {
579 return GL_COPY_WRITE_BUFFER_BINDING;
580 #ifdef HANDLE_UNSUPPORTED_ENUMS
581 } else if (target == GL_ATOMIC_COUNTER_BUFFER) {
582 return GL_ATOMIC_COUNTER_BUFFER_BINDING;
583 } else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
584 return GL_TRANSFORM_FEEDBACK_BUFFER_BINDING;
585 } else if (target == GL_PIXEL_PACK_BUFFER) {
586 return GL_PIXEL_PACK_BUFFER_BINDING;
587 } else if (target == GL_QUERY_BUFFER) {
588 return GL_QUERY_BUFFER_BINDING;
589 } else if (target == GL_ARRAY_BUFFER) {
590 return GL_ARRAY_BUFFER_BINDING;
591 } else if (target == GL_DISPATCH_INDIRECT_BUFFER) {
592 return GL_DISPATCH_INDIRECT_BUFFER_BINDING;
593 } else if (target == GL_DRAW_INDIRECT_BUFFER) {
594 return GL_DRAW_INDIRECT_BUFFER_BINDING;
595 } else if (target == GL_ELEMENT_ARRAY_BUFFER) { // stored in VAO state...
596 return GL_ELEMENT_ARRAY_BUFFER_BINDING;
597 } else if (target == GL_TEXTURE_BUFFER) {
598 return GL_TEXTURE_BUFFER_BINDING;
599 #endif
600 }
601 PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET UNIT");
602 return GL_NONE;
603 }
604
IndexedTargetToTargetId(uint32_t target)605 inline DeviceGLES::BufferBindId DeviceGLES::IndexedTargetToTargetId(uint32_t target)
606 {
607 if (target == GL_UNIFORM_BUFFER) {
608 return BufferBindId::UNIFORM_BUFFER_BIND;
609 } else if (target == GL_SHADER_STORAGE_BUFFER) {
610 return BufferBindId::SHADER_STORAGE_BUFFER_BIND;
611 #ifdef HANDLE_UNSUPPORTED_ENUMS
612 } else if (target == GL_ATOMIC_COUNTER_BUFFER) {
613 return BufferBindId::ATOMIC_COUNTER_BUFFER;
614 } else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
615 return BufferBindId::TRANSFORM_FEEDBACK_BUFFER;
616 #endif
617 }
618 PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET UNIT");
619 return BufferBindId::MAX_BUFFER_BIND_ID;
620 }
621
IndexedTargetIdToTarget(DeviceGLES::BufferBindId target)622 inline uint32_t DeviceGLES::IndexedTargetIdToTarget(DeviceGLES::BufferBindId target)
623 {
624 if (target == BufferBindId::UNIFORM_BUFFER_BIND) {
625 return GL_UNIFORM_BUFFER;
626 } else if (target == BufferBindId::SHADER_STORAGE_BUFFER_BIND) {
627 return GL_SHADER_STORAGE_BUFFER;
628 #ifdef HANDLE_UNSUPPORTED_ENUMS
629 } else if (target == BufferBindId::ATOMIC_COUNTER_BUFFER_BIND) {
630 return GL_ATOMIC_COUNTER_BUFFER;
631 } else if (target == BufferBindId::TRANSFORM_FEEDBACK_BUFFER_BIND) {
632 return GL_TRANSFORM_FEEDBACK_BUFFER;
633 #endif
634 }
635 PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET UNIT");
636 return 0;
637 }
638
GenericTargetToTargetId(uint32_t target)639 inline DeviceGLES::BufferTargetId DeviceGLES::GenericTargetToTargetId(uint32_t target)
640 {
641 if (target == GL_PIXEL_UNPACK_BUFFER) {
642 return BufferTargetId::PIXEL_UNPACK_BUFFER;
643 } else if (target == GL_PIXEL_PACK_BUFFER) {
644 return BufferTargetId::PIXEL_PACK_BUFFER;
645 } else if (target == GL_COPY_READ_BUFFER) {
646 return BufferTargetId::COPY_READ_BUFFER;
647 } else if (target == GL_COPY_WRITE_BUFFER) {
648 return BufferTargetId::COPY_WRITE_BUFFER;
649 } else if (target == GL_UNIFORM_BUFFER) {
650 return BufferTargetId::UNIFORM_BUFFER;
651 } else if (target == GL_SHADER_STORAGE_BUFFER) {
652 return BufferTargetId::SHADER_STORAGE_BUFFER;
653 } else if (target == GL_DISPATCH_INDIRECT_BUFFER) {
654 return BufferTargetId::DISPATCH_INDIRECT_BUFFER;
655 } else if (target == GL_DRAW_INDIRECT_BUFFER) {
656 return BufferTargetId::DRAW_INDIRECT_BUFFER;
657 #ifdef HANDLE_UNSUPPORTED_ENUMS
658 } else if (target == GL_ATOMIC_COUNTER_BUFFER) {
659 return BufferTargetId::ATOMIC_COUNTER_BUFFER;
660 } else if (target == GL_QUERY_BUFFER) {
661 return BufferTargetId::QUERY_BUFFER;
662 } else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) {
663 return BufferTargetId::TRANSFORM_FEEDBACK_BUFFER;
664 } else if (target == GL_ARRAY_BUFFER) {
665 return BufferTargetId::ARRAY_BUFFER;
666 } else if (target == GL_ELEMENT_ARRAY_BUFFER) { // stored in VAO state...
667 return BufferTargetId::ELEMENT_ARRAY_BUFFER;
668 } else if (target == GL_TEXTURE_BUFFER) {
669 return BufferTargetId::TEXTURE_BUFFER;
670 #endif
671 }
672 PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET");
673 return BufferTargetId::MAX_BUFFER_TARGET_ID;
674 }
675
GenericTargetIdToTarget(BufferTargetId target)676 inline uint32_t DeviceGLES::GenericTargetIdToTarget(BufferTargetId target)
677 {
678 if (target == BufferTargetId::PIXEL_UNPACK_BUFFER) {
679 return GL_PIXEL_UNPACK_BUFFER;
680 } else if (target == BufferTargetId::PIXEL_PACK_BUFFER) {
681 return GL_PIXEL_PACK_BUFFER;
682 } else if (target == BufferTargetId::COPY_READ_BUFFER) {
683 return GL_COPY_READ_BUFFER;
684 } else if (target == BufferTargetId::COPY_WRITE_BUFFER) {
685 return GL_COPY_WRITE_BUFFER;
686 } else if (target == BufferTargetId::UNIFORM_BUFFER) {
687 return GL_UNIFORM_BUFFER;
688 } else if (target == BufferTargetId::SHADER_STORAGE_BUFFER) {
689 return GL_SHADER_STORAGE_BUFFER;
690 } else if (target == BufferTargetId::DISPATCH_INDIRECT_BUFFER) {
691 return GL_DISPATCH_INDIRECT_BUFFER;
692 } else if (target == BufferTargetId::DRAW_INDIRECT_BUFFER) {
693 return GL_DRAW_INDIRECT_BUFFER;
694 #ifdef HANDLE_UNSUPPORTED_ENUMS
695 } else if (target == BufferTargetId::ATOMIC_COUNTER_BUFFER) {
696 return GL_ATOMIC_COUNTER_BUFFER;
697 } else if (target == BufferTargetId::QUERY_BUFFER) {
698 return GL_QUERY_BUFFER;
699 } else if (target == BufferTargetId::TRANSFORM_FEEDBACK_BUFFER) {
700 return GL_TRANSFORM_FEEDBACK_BUFFER;
701 } else if (target == BufferTargetId::ARRAY_BUFFER) {
702 return GL_ARRAY_BUFFER;
703 } else if (target == BufferTargetId::ELEMENT_ARRAY_BUFFER) { // stored in VAO state...
704 return GL_ELEMENT_ARRAY_BUFFER;
705 } else if (target == BufferTargetId::TEXTURE_BUFFER) {
706 return GL_TEXTURE_BUFFER;
707 #endif
708 }
709 PLUGIN_ASSERT_MSG(false, "UNHANDLED BUFFER BIND TARGET");
710 return 0;
711 }
712
TextureTargetToTargetId(uint32_t target)713 inline DeviceGLES::TextureTargetId DeviceGLES::TextureTargetToTargetId(uint32_t target)
714 {
715 if (target == GL_TEXTURE_2D) {
716 return TextureTargetId::TEXTURE_2D;
717 } else if ((target == GL_TEXTURE_CUBE_MAP_POSITIVE_X) || (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X) ||
718 (target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y) || (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) ||
719 (target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z) || (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ||
720 (target == GL_TEXTURE_CUBE_MAP)) {
721 return TextureTargetId::TEXTURE_CUBE_MAP;
722 #if RENDER_HAS_GLES_BACKEND
723 } else if (target == GL_TEXTURE_EXTERNAL_OES) {
724 return TextureTargetId::TEXTURE_EXTERNAL_OES;
725 #endif
726 } else if (target == GL_TEXTURE_2D_MULTISAMPLE) {
727 return TextureTargetId::TEXTURE_2D_MULTISAMPLE;
728 } else if (target == GL_TEXTURE_2D_ARRAY) {
729 return TextureTargetId::TEXTURE_2D_ARRAY;
730 }
731 PLUGIN_ASSERT_MSG(false, "UNHANDLED TEXTURE TARGET UNIT");
732 return TextureTargetId::MAX_TEXTURE_TARGET_ID;
733 }
734
TextureTargetIdToTarget(DeviceGLES::TextureTargetId target)735 inline uint32_t DeviceGLES::TextureTargetIdToTarget(DeviceGLES::TextureTargetId target)
736 {
737 if (target == TextureTargetId::TEXTURE_2D) {
738 return GL_TEXTURE_2D;
739 } else if (target == TextureTargetId::TEXTURE_CUBE_MAP) {
740 return GL_TEXTURE_CUBE_MAP;
741 #if RENDER_HAS_GLES_BACKEND
742 } else if (target == TextureTargetId::TEXTURE_EXTERNAL_OES) {
743 return GL_TEXTURE_EXTERNAL_OES;
744 #endif
745 } else if (target == TextureTargetId::TEXTURE_2D_MULTISAMPLE) {
746 return GL_TEXTURE_2D_MULTISAMPLE;
747 } else if (target == TextureTargetId::TEXTURE_2D_ARRAY) {
748 return GL_TEXTURE_2D_ARRAY;
749 }
750 PLUGIN_ASSERT_MSG(false, "UNHANDLED TEXTURE TARGET UNIT");
751 return 0;
752 }
753
754 #if RENDER_HAS_GL_BACKEND
GetEglState() const755 const WGLHelpers::WGLState& DeviceGLES::GetEglState()
756 #endif
757 #if RENDER_HAS_GLES_BACKEND
758 const EGLHelpers::EGLState& DeviceGLES::GetEglState()
759 #endif
760 {
761 return eglState_;
762 }
763
DeviceGLES(RenderContext & renderContext,DeviceCreateInfo const & createInfo)764 DeviceGLES::DeviceGLES(RenderContext& renderContext, DeviceCreateInfo const& createInfo)
765 : Device(renderContext, createInfo)
766 {
767 eglState_.CreateContext(createInfo);
768 if (!eglState_.IsValid()) {
769 PLUGIN_LOG_F("Failed to create a context");
770 return;
771 }
772 eglState_.GlInitialize();
773 #if RENDER_GL_DEBUG
774 filterErrorFunc = (decltype(filterErrorFunc))eglState_.ErrorFilter();
775 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
776 glDebugMessageCallback(OnGlError, NULL);
777 GLuint unusedIds = 0;
778 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, &unusedIds, true);
779 #endif
780 PLUGIN_LOG_I("GL_VENDOR: %s", glGetString(GL_VENDOR));
781 PLUGIN_LOG_I("GL_RENDERER: %s", glGetString(GL_RENDERER));
782 PLUGIN_LOG_I("GL_VERSION: %s", glGetString(GL_VERSION));
783 PLUGIN_LOG_I("GL_SHADING_LANGUAGE_VERSION: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
784 GLint n = 0;
785 glGetIntegerv(GL_NUM_EXTENSIONS, &n);
786 for (GLint i = 0; i < n; i++) {
787 const auto ext = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, static_cast<GLuint>(i)));
788 PLUGIN_LOG_D(" GL_EXTENSION: %s", ext);
789 extensions_[ext] = true;
790 }
791 #if RENDER_HAS_GL_BACKEND
792 // Extension in OpenGL ES, but part of core in OpenGL.
793 extensions_["GL_EXT_buffer_storage"] = true;
794 // Seamless cubemaps are always on in vulkan and gles 3.0..
795 // (3.0 made it required, not supported prior to 3.0 es)
796 // on desktop gl, it's optional.
797 // (but must be supported since 3.2)
798 // So just enable it always, so that desktop GL works as vulkan and GLES.
799 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
800 #endif
801 #if RENDER_GL_DEBUG
802 // Dump interesting constants.
803 DUMP(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
804 DUMP(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
805 DUMP(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
806 DUMP(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
807 DUMP(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS);
808 DUMP(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
809 #endif
810 boundReadFbo_ = boundWriteFbo_ = 0;
811 eglState_.RestoreContext();
812 #ifdef RENDER_OPTIMIZE_FOR_INTEGRATED_GPU
813 // NOTE: we expect e.g. mobile devices to have integrated memory, where we can bypass staging and write directly to
814 // linear gpu buffers without additional copies and performance decrease
815 deviceSharedMemoryPropertyFlags_ = CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
816 #endif
817 SetDeviceStatus(true);
818
819 // First dump required formats and then add based on supported extensions
820 supportedFormats_.insert(supportedFormats_.end(), std::begin(IMAGE_FORMATS), std::end(IMAGE_FORMATS));
821
822 FillExtensionFormats(*this, supportedFormats_);
823
824 // Keep the list sorted for faster lookup
825 std::sort(supportedFormats_.begin(), supportedFormats_.end(),
826 [](const ImageFormat& lhs, const ImageFormat& rhs) { return lhs.coreFormat < rhs.coreFormat; });
827
828 // Add fallbacks for unsupported formats
829 for (const auto& fallback : IMAGE_FORMATS_FALLBACK) {
830 if (const auto pos = std::lower_bound(supportedFormats_.begin(), supportedFormats_.end(), fallback.coreFormat,
831 [](const ImageFormat& element, const Format value) { return element.coreFormat < value; });
832 (pos == supportedFormats_.end()) || (pos->coreFormat != fallback.coreFormat)) {
833 supportedFormats_.insert(pos, fallback);
834 }
835 }
836 const GpuResourceManager::CreateInfo grmCreateInfo {
837 GpuResourceManager::GPU_RESOURCE_MANAGER_OPTIMIZE_STAGING_MEMORY,
838 };
839 gpuResourceMgr_ = make_unique<GpuResourceManager>(*this, grmCreateInfo);
840 shaderMgr_ = make_unique<ShaderManager>(*this);
841
842 lowLevelDevice_ = make_unique<LowLevelDeviceGLES>(*this);
843 }
844
~DeviceGLES()845 DeviceGLES::~DeviceGLES()
846 {
847 if (eglState_.IsValid()) {
848 Activate(); // make sure we are active during teardown..
849 WaitForIdle();
850
851 gpuResourceMgr_.reset();
852 shaderMgr_.reset();
853 swapchain_.reset();
854 eglState_.DestroyContext();
855 Deactivate(); // make sure the previous context is still active..
856 }
857 }
858
HasExtension(const string_view extension) const859 bool DeviceGLES::HasExtension(const string_view extension) const
860 {
861 return (extensions_.find({ extension.data(), extension.size() }) != extensions_.end());
862 }
863
GetBackendType() const864 DeviceBackendType DeviceGLES::GetBackendType() const
865 {
866 return backendType_;
867 }
868
GetPlatformData() const869 const DevicePlatformData& DeviceGLES::GetPlatformData() const
870 {
871 return eglState_.GetPlatformData();
872 }
873
GetLowLevelDevice() const874 ILowLevelDevice& DeviceGLES::GetLowLevelDevice() const
875 {
876 return *lowLevelDevice_;
877 }
878
GetFormatProperties(const Format format) const879 FormatProperties DeviceGLES::GetFormatProperties(const Format format) const
880 {
881 // NOTE: not currently implemented, but GL(ES) driver fixes most of the issues
882 return FormatProperties {
883 DeviceFormatSupportConstants::ALL_FLAGS_SUPPORTED,
884 DeviceFormatSupportConstants::ALL_FLAGS_SUPPORTED,
885 DeviceFormatSupportConstants::ALL_FLAGS_SUPPORTED,
886 GpuProgramUtil::FormatByteSize(format),
887 };
888 }
889
GetAccelerationStructureBuildSizes(const AccelerationStructureBuildGeometryInfo & geometry,BASE_NS::array_view<const AccelerationStructureGeometryTrianglesInfo> triangles,BASE_NS::array_view<const AccelerationStructureGeometryAabbsInfo> aabbs,BASE_NS::array_view<const AccelerationStructureGeometryInstancesInfo> instances) const890 AccelerationStructureBuildSizes DeviceGLES::GetAccelerationStructureBuildSizes(
891 const AccelerationStructureBuildGeometryInfo& geometry,
892 BASE_NS::array_view<const AccelerationStructureGeometryTrianglesInfo> triangles,
893 BASE_NS::array_view<const AccelerationStructureGeometryAabbsInfo> aabbs,
894 BASE_NS::array_view<const AccelerationStructureGeometryInstancesInfo> instances) const
895 {
896 return {};
897 }
898
GetPlatformGpuMemoryAllocator()899 PlatformGpuMemoryAllocator* DeviceGLES::GetPlatformGpuMemoryAllocator()
900 {
901 PLUGIN_ASSERT_MSG(false, "DeviceGLES::GetPlatformGpuMemoryAllocator called!");
902 return nullptr;
903 }
904
GetSwapchain()905 SwapchainGLES* DeviceGLES::GetSwapchain()
906 {
907 PLUGIN_ASSERT(HasSwapchain());
908 return static_cast<SwapchainGLES*>(swapchain_.get());
909 }
910
911 // (re-)create swapchain
CreateDeviceSwapchain(const SwapchainCreateInfo & swapchainCreateInfo)912 void DeviceGLES::CreateDeviceSwapchain(const SwapchainCreateInfo& swapchainCreateInfo)
913 {
914 PLUGIN_ASSERT(IsActive());
915 WaitForIdle();
916 swapchain_ = make_unique<SwapchainGLES>(*this, swapchainCreateInfo);
917 // Switch to the new swapchain.
918 eglState_.SetContext(GetSwapchain());
919 }
920
DestroyDeviceSwapchain()921 void DeviceGLES::DestroyDeviceSwapchain()
922 {
923 PLUGIN_ASSERT(IsActive());
924 WaitForIdle();
925 swapchain_.reset();
926 // Drop to dummycontext (ie. 1x1 surface etc...)
927 eglState_.SetContext(nullptr);
928 }
929
IsActive() const930 bool DeviceGLES::IsActive() const
931 {
932 return isActive_ > 0;
933 }
934
Activate()935 void DeviceGLES::Activate()
936 {
937 activeMutex_.lock();
938 if (isActive_ == 0) {
939 eglState_.SaveContext();
940 if (HasSwapchain()) {
941 eglState_.SetContext(GetSwapchain());
942 } else {
943 // bind the dummy surface as there is no swapchain.
944 eglState_.SetContext(nullptr);
945 }
946 }
947 isActive_++;
948 }
949
Deactivate()950 void DeviceGLES::Deactivate()
951 {
952 PLUGIN_ASSERT_MSG(isActive_ > 0, "Deactivate called while already inactive");
953 if (isActive_ > 0) {
954 isActive_--;
955 }
956 if (isActive_ == 0) {
957 eglState_.RestoreContext();
958 isActive_ = false;
959 }
960 activeMutex_.unlock();
961 }
962
GetValidGpuQueue(const GpuQueue & gpuQueue) const963 GpuQueue DeviceGLES::GetValidGpuQueue(const GpuQueue& gpuQueue) const
964 {
965 return { GpuQueue::QueueType::GRAPHICS, 0 }; // no queues -> graphics
966 }
967
GetGpuQueueCount() const968 uint32_t DeviceGLES::GetGpuQueueCount() const
969 {
970 return 1;
971 }
972
InitializePipelineCache(array_view<const uint8_t> initialData)973 void DeviceGLES::InitializePipelineCache(array_view<const uint8_t> initialData)
974 {
975 // NOTE: not implemented.
976 }
977
GetPipelineCache() const978 vector<uint8_t> DeviceGLES::GetPipelineCache() const
979 {
980 // NOTE: not implemented. could probably be done by gathering glGetProgramBinary results together.
981 return {};
982 }
983
WaitForIdle()984 void DeviceGLES::WaitForIdle()
985 {
986 const bool activeState = IsActive();
987 if (!activeState) {
988 Activate();
989 }
990 if (!isRenderbackendRunning_) {
991 PLUGIN_LOG_D("Device - WaitForIdle");
992 glFinish();
993 } else {
994 PLUGIN_LOG_E("Device WaitForIdle can only called when render backend is not running");
995 }
996 if (!activeState) {
997 Deactivate();
998 }
999 }
1000
1001 #if (RENDER_HAS_GL_BACKEND)
CreateDeviceGL(RenderContext & renderContext,DeviceCreateInfo const & createInfo)1002 unique_ptr<Device> CreateDeviceGL(RenderContext& renderContext, DeviceCreateInfo const& createInfo)
1003 {
1004 if (auto device = make_unique<DeviceGLES>(renderContext, createInfo); device) {
1005 const auto& plat = static_cast<const DevicePlatformDataGL&>(device->GetPlatformData());
1006 if (plat.context != nullptr) {
1007 return device;
1008 }
1009 }
1010 return nullptr;
1011 }
1012 #endif
1013 #if (RENDER_HAS_GLES_BACKEND)
CreateDeviceGLES(RenderContext & renderContext,DeviceCreateInfo const & createInfo)1014 unique_ptr<Device> CreateDeviceGLES(RenderContext& renderContext, DeviceCreateInfo const& createInfo)
1015 {
1016 if (auto device = make_unique<DeviceGLES>(renderContext, createInfo); device) {
1017 const auto& plat = static_cast<const DevicePlatformDataGLES&>(device->GetPlatformData());
1018 if (plat.context != EGL_NO_CONTEXT) {
1019 return device;
1020 }
1021 }
1022 return nullptr;
1023 }
1024 #endif
1025
ReleaseShader(uint32_t type,uint32_t shader)1026 void DeviceGLES::ReleaseShader(uint32_t type, uint32_t shader)
1027 {
1028 vector<ShaderCache::Entry>* cache = nullptr;
1029 if (type == GL_FRAGMENT_SHADER) {
1030 cache = &caches[DeviceGLES::FRAGMENT_CACHE].cache;
1031 } else if (type == GL_VERTEX_SHADER) {
1032 cache = &caches[DeviceGLES::VERTEX_CACHE].cache;
1033 } else if (type == GL_COMPUTE_SHADER) {
1034 cache = &caches[DeviceGLES::COMPUTE_CACHE].cache;
1035 } else {
1036 return;
1037 }
1038
1039 const auto pos = std::find_if(
1040 cache->begin(), cache->end(), [shader](const ShaderCache::Entry& entry) { return entry.shader == shader; });
1041 if (pos != cache->end()) {
1042 ShaderCache::Entry& entry = *pos;
1043 entry.refCount--;
1044 if (entry.refCount == 0) {
1045 glDeleteShader(entry.shader);
1046 cache->erase(pos);
1047 }
1048 return;
1049 }
1050
1051 PLUGIN_ASSERT_MSG(false, "Tried to release a non-existant shader?");
1052 }
1053
ReleaseProgram(uint32_t program)1054 void DeviceGLES::ReleaseProgram(uint32_t program)
1055 {
1056 PLUGIN_ASSERT_MSG(isActive_, "Device not active when releasing shaders");
1057 for (auto it = programs_.begin(); it != programs_.end(); it++) {
1058 auto& t = *it;
1059 if (t.program == program) {
1060 t.refCount--;
1061 if (t.refCount == 0) {
1062 if (t.fragShader) {
1063 ReleaseShader(GL_FRAGMENT_SHADER, t.fragShader);
1064 }
1065 if (t.vertShader) {
1066 ReleaseShader(GL_VERTEX_SHADER, t.vertShader);
1067 }
1068 if (t.compShader) {
1069 ReleaseShader(GL_COMPUTE_SHADER, t.compShader);
1070 }
1071 glDeleteProgram(t.program);
1072 programs_.erase(it);
1073 }
1074 return;
1075 }
1076 }
1077 PLUGIN_ASSERT_MSG(false, "Tried to release a non-existant program?");
1078 }
1079
CacheShader(int type,const string_view source)1080 const DeviceGLES::ShaderCache::Entry& DeviceGLES::CacheShader(int type, const string_view source)
1081 {
1082 PLUGIN_ASSERT(type < MAX_CACHES);
1083 if (source.empty()) {
1084 static constexpr DeviceGLES::ShaderCache::Entry invalid {};
1085 return invalid;
1086 }
1087 constexpr GLenum types[] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, GL_COMPUTE_SHADER };
1088 // NOTE: check other hash functions, also i guess verify (strcmp) on collision would be prudent.
1089 const uint64_t hash = FNV1aHash(source.data(), source.size());
1090 PLUGIN_ASSERT(hash != 0);
1091 for (auto& t : caches[type].cache) {
1092 if (t.hash == hash) {
1093 caches[type].hit++;
1094 t.refCount++;
1095 return t;
1096 }
1097 }
1098 caches[type].miss++;
1099 DeviceGLES::ShaderCache::Entry entry;
1100 entry.hash = hash;
1101 entry.shader = glCreateShader(types[type]);
1102 entry.refCount = 1;
1103 const GLint len = static_cast<GLint>(source.length());
1104 const auto data = source.data();
1105 glShaderSource(entry.shader, 1, &data, &len);
1106 glCompileShader(entry.shader);
1107 GLint result = GL_FALSE;
1108 glGetShaderiv(entry.shader, GL_COMPILE_STATUS, &result);
1109 if (result == GL_FALSE) {
1110 GLint logLength = 0;
1111 glGetShaderiv(entry.shader, GL_INFO_LOG_LENGTH, &logLength);
1112 string messages;
1113 messages.resize(static_cast<size_t>(logLength));
1114 glGetShaderInfoLog(entry.shader, logLength, 0, messages.data());
1115 PLUGIN_LOG_F("Shader compilation error: %s", messages.c_str());
1116 PLUGIN_ASSERT_MSG(result == GL_TRUE, "GpuProgram shader compile failed");
1117 }
1118 caches[type].cache.push_back(entry);
1119 return caches[type].cache.back();
1120 }
1121
CacheProgram(const string_view vertSource,const string_view fragSource,const string_view compSource)1122 uint32_t DeviceGLES::CacheProgram(
1123 const string_view vertSource, const string_view fragSource, const string_view compSource)
1124 {
1125 PLUGIN_ASSERT_MSG(isActive_, "Device not active when building shaders");
1126 // Hash and cache shader sources.
1127 const auto& vEntry = CacheShader(DeviceGLES::VERTEX_CACHE, vertSource);
1128 const auto& fEntry = CacheShader(DeviceGLES::FRAGMENT_CACHE, fragSource);
1129 const auto& cEntry = CacheShader(DeviceGLES::COMPUTE_CACHE, compSource);
1130 // Then check if we have the program already cached (ie. matching shaders linked)
1131 for (ProgramCache& t : programs_) {
1132 if ((t.hashVert != vEntry.hash) || (t.hashFrag != fEntry.hash) || (t.hashComp != cEntry.hash)) {
1133 continue;
1134 }
1135 pCacheHit_++;
1136 t.refCount++;
1137 return t.program;
1138 }
1139 // Create new program
1140 pCacheMiss_++;
1141 const GLuint program = glCreateProgram();
1142 #if defined(CORE_USE_SEPARATE_SHADER_OBJECTS) && (CORE_USE_SEPARATE_SHADER_OBJECTS == 1)
1143 // enable separable programs.
1144 glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
1145 #endif
1146 // Attach and link
1147 if (vEntry.shader) {
1148 glAttachShader(program, vEntry.shader);
1149 }
1150 if (fEntry.shader) {
1151 glAttachShader(program, fEntry.shader);
1152 }
1153 if (cEntry.shader) {
1154 glAttachShader(program, cEntry.shader);
1155 }
1156 glLinkProgram(program);
1157 GLint result = GL_FALSE;
1158 glGetProgramiv(program, GL_LINK_STATUS, &result);
1159 if (result == GL_FALSE) {
1160 GLint logLength = 0;
1161 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
1162 string messages;
1163 messages.resize(static_cast<size_t>(logLength));
1164 glGetProgramInfoLog(program, logLength, 0, messages.data());
1165 PLUGIN_LOG_F("Shader linking error: %s", messages.c_str());
1166 PLUGIN_ASSERT_MSG(result == GL_TRUE, "GpuProgram linking failed");
1167 }
1168 // Add the program to cache
1169 programs_.push_back(
1170 { program, vEntry.shader, fEntry.shader, cEntry.shader, vEntry.hash, fEntry.hash, cEntry.hash, 1 });
1171 return program;
1172 }
1173
UseProgram(uint32_t program)1174 void DeviceGLES::UseProgram(uint32_t program)
1175 {
1176 if (boundProgram_ != program) {
1177 boundProgram_ = program;
1178 glUseProgram(static_cast<GLuint>(program));
1179 }
1180 }
1181
BindBuffer(uint32_t target,uint32_t buffer)1182 void DeviceGLES::BindBuffer(uint32_t target, uint32_t buffer)
1183 {
1184 const uint32_t targetId = GenericTargetToTargetId(target);
1185 auto& state = bufferBound_[targetId];
1186 if ((!state.bound) || (state.buffer != buffer)) {
1187 state.bound = true;
1188 state.buffer = buffer;
1189 glBindBuffer(target, static_cast<GLuint>(buffer));
1190 }
1191 }
1192
BindBufferRange(uint32_t target,uint32_t binding,uint32_t buffer,uint64_t offset,uint64_t size)1193 void DeviceGLES::BindBufferRange(uint32_t target, uint32_t binding, uint32_t buffer, uint64_t offset, uint64_t size)
1194 {
1195 const uint32_t targetId = IndexedTargetToTargetId(target);
1196 auto& slot = boundBuffers_[targetId][binding];
1197
1198 if ((slot.cached == false) || (slot.buffer != buffer) || (slot.offset != offset) || (slot.size != size)) {
1199 slot.cached = true;
1200 slot.buffer = buffer;
1201 slot.offset = offset;
1202 slot.size = size;
1203 glBindBufferRange(target, binding, buffer, static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
1204 // BindBufferRange sets the "generic" binding too. so make sure cache state is correct.
1205 const uint32_t targetId2 = GenericTargetToTargetId(target);
1206 auto& state = bufferBound_[targetId2];
1207 state.bound = true;
1208 state.buffer = buffer;
1209 }
1210 // NOTE: we are not forcing the generic bind point here. use BindBuffer to set the generic one if needed!
1211 }
1212
BindSampler(uint32_t textureUnit,uint32_t sampler)1213 void DeviceGLES::BindSampler(uint32_t textureUnit, uint32_t sampler)
1214 {
1215 if ((sampler + 1) != boundSampler_[textureUnit]) {
1216 boundSampler_[textureUnit] = sampler + 1;
1217 glBindSampler(textureUnit, sampler);
1218 }
1219 }
1220
BoundReadFrameBuffer() const1221 uint32_t DeviceGLES::BoundReadFrameBuffer() const
1222 {
1223 return boundReadFbo_;
1224 }
1225
BoundWriteFrameBuffer() const1226 uint32_t DeviceGLES::BoundWriteFrameBuffer() const
1227 {
1228 return boundWriteFbo_;
1229 }
1230
BoundProgram() const1231 uint32_t DeviceGLES::BoundProgram() const
1232 {
1233 return boundProgram_;
1234 }
1235
BoundBuffer(uint32_t target) const1236 uint32_t DeviceGLES::BoundBuffer(uint32_t target) const
1237 {
1238 const uint32_t targetId = GenericTargetToTargetId(target);
1239 const auto& slot = bufferBound_[targetId];
1240 if (!slot.bound) {
1241 return 0;
1242 }
1243 return slot.buffer;
1244 }
1245
BoundBuffer(uint32_t target,uint32_t binding) const1246 uint32_t DeviceGLES::BoundBuffer(uint32_t target, uint32_t binding) const
1247 {
1248 const uint32_t targetId = IndexedTargetToTargetId(target);
1249 const auto& slot = boundBuffers_[targetId][binding];
1250 if (!slot.cached) {
1251 return 0;
1252 }
1253 return slot.buffer;
1254 }
1255
BoundSampler(uint32_t textureUnit) const1256 uint32_t DeviceGLES::BoundSampler(uint32_t textureUnit) const
1257 {
1258 const uint32_t bound = boundSampler_[textureUnit];
1259 return bound ? (bound - 1) : bound;
1260 }
1261
BoundTexture(uint32_t textureUnit,uint32_t target) const1262 uint32_t DeviceGLES::BoundTexture(uint32_t textureUnit, uint32_t target) const
1263 {
1264 const uint32_t targetId = TextureTargetToTargetId(target);
1265 const uint32_t bound = boundTexture_[textureUnit][targetId];
1266 if (bound == 0) {
1267 return 0; // bound 0 == nothing has been bound via cache yet.
1268 }
1269 return bound - 1;
1270 }
1271
BindImageTexture(uint32_t unit,uint32_t texture,uint32_t level,bool layered,uint32_t layer,uint32_t access,uint32_t format)1272 void DeviceGLES::BindImageTexture(
1273 uint32_t unit, uint32_t texture, uint32_t level, bool layered, uint32_t layer, uint32_t access, uint32_t format)
1274 {
1275 auto& image = boundImage_[unit];
1276 if ((!image.bound) || (image.texture != texture) || (image.level != level) || (image.layered != layered) ||
1277 (image.access != access) || (image.format != format)) {
1278 image.bound = true;
1279 image.texture = texture;
1280 image.level = level;
1281 image.layered = layered;
1282 image.access = access;
1283 image.format = format;
1284 glBindImageTexture(static_cast<GLuint>(unit), static_cast<GLuint>(texture), static_cast<GLint>(level),
1285 static_cast<GLboolean>(layered), static_cast<GLint>(layer), static_cast<GLenum>(access),
1286 static_cast<GLenum>(format));
1287 }
1288 }
1289
SetActiveTextureUnit(uint32_t textureUnit)1290 void DeviceGLES::SetActiveTextureUnit(uint32_t textureUnit)
1291 {
1292 if ((textureUnit + 1) != activeTextureUnit_) {
1293 activeTextureUnit_ = textureUnit + 1;
1294 glActiveTexture(GL_TEXTURE0 + textureUnit);
1295 }
1296 }
1297
BindTexture(uint32_t textureUnit,uint32_t target,uint32_t texture)1298 void DeviceGLES::BindTexture(uint32_t textureUnit, uint32_t target, uint32_t texture)
1299 {
1300 const uint32_t targetId = TextureTargetToTargetId(target);
1301 #if RENDER_HAS_GLES_BACKEND
1302 if (target == GL_TEXTURE_EXTERNAL_OES) {
1303 // Work around for oes textures needing a bind to zero to update.
1304 SetActiveTextureUnit(textureUnit);
1305 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
1306 boundTexture_[textureUnit][targetId] = 0;
1307 // Force the default sampler for OES textures.
1308 BindSampler(textureUnit, 0);
1309 }
1310 #endif
1311 if ((texture + 1) != boundTexture_[textureUnit][targetId]) {
1312 SetActiveTextureUnit(textureUnit);
1313 boundTexture_[textureUnit][targetId] = texture + 1;
1314 // remap the cubemap layer ids...
1315 switch (target) {
1316 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1317 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1318 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1319 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1320 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1321 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1322 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
1323 break;
1324 default:
1325 glBindTexture(target, texture);
1326 break;
1327 }
1328 }
1329 }
1330
TexSwizzle(uint32_t image,uint32_t target,const Math::UVec4 & swizzle)1331 void DeviceGLES::TexSwizzle(uint32_t image, uint32_t target, const Math::UVec4& swizzle)
1332 {
1333 // set only if not default..
1334 if ((swizzle.x != GL_RED) || (swizzle.y != GL_GREEN) || (swizzle.z != GL_BLUE) || (swizzle.w != GL_ALPHA)) {
1335 SetActiveTextureUnit(TEMP_BIND_UNIT);
1336 BindTexture(TEMP_BIND_UNIT, target, image);
1337 glTexParameteri(static_cast<GLenum>(target), GL_TEXTURE_SWIZZLE_R, static_cast<GLint>(swizzle.x));
1338 glTexParameteri(static_cast<GLenum>(target), GL_TEXTURE_SWIZZLE_G, static_cast<GLint>(swizzle.y));
1339 glTexParameteri(static_cast<GLenum>(target), GL_TEXTURE_SWIZZLE_B, static_cast<GLint>(swizzle.z));
1340 glTexParameteri(static_cast<GLenum>(target), GL_TEXTURE_SWIZZLE_A, static_cast<GLint>(swizzle.w));
1341 }
1342 }
1343
TexStorage2D(uint32_t image,uint32_t target,uint32_t levels,uint32_t internalformat,const Math::UVec2 & extent)1344 void DeviceGLES::TexStorage2D(
1345 uint32_t image, uint32_t target, uint32_t levels, uint32_t internalformat, const Math::UVec2& extent)
1346 {
1347 SetActiveTextureUnit(TEMP_BIND_UNIT);
1348 BindTexture(TEMP_BIND_UNIT, target, image);
1349 glTexStorage2D(static_cast<GLenum>(target), static_cast<GLsizei>(levels), static_cast<GLenum>(internalformat),
1350 static_cast<GLsizei>(extent.x), static_cast<GLsizei>(extent.y));
1351 }
1352
TexStorage2DMultisample(uint32_t image,uint32_t target,uint32_t samples,uint32_t internalformat,const Math::UVec2 & extent,bool fixedsamplelocations)1353 void DeviceGLES::TexStorage2DMultisample(uint32_t image, uint32_t target, uint32_t samples, uint32_t internalformat,
1354 const Math::UVec2& extent, bool fixedsamplelocations)
1355 {
1356 SetActiveTextureUnit(TEMP_BIND_UNIT);
1357 BindTexture(TEMP_BIND_UNIT, target, image);
1358 glTexStorage2DMultisample(static_cast<GLenum>(target), static_cast<GLsizei>(samples),
1359 static_cast<GLenum>(internalformat), static_cast<GLsizei>(extent.x), static_cast<GLsizei>(extent.y),
1360 fixedsamplelocations);
1361 }
1362
TexStorage3D(uint32_t image,uint32_t target,uint32_t levels,uint32_t internalformat,const Math::UVec3 & extent)1363 void DeviceGLES::TexStorage3D(
1364 uint32_t image, uint32_t target, uint32_t levels, uint32_t internalformat, const Math::UVec3& extent)
1365 {
1366 SetActiveTextureUnit(TEMP_BIND_UNIT);
1367 BindTexture(TEMP_BIND_UNIT, target, image);
1368 glTexStorage3D((GLenum)target, (GLsizei)levels, (GLenum)internalformat, (GLsizei)extent.x, (GLsizei)extent.y,
1369 (GLsizei)extent.z);
1370 }
1371
TexSubImage2D(uint32_t image,uint32_t target,uint32_t level,const Math::UVec2 & offset,const Math::UVec2 & extent,uint32_t format,uint32_t type,const void * pixels)1372 void DeviceGLES::TexSubImage2D(uint32_t image, uint32_t target, uint32_t level, const Math::UVec2& offset,
1373 const Math::UVec2& extent, uint32_t format, uint32_t type, const void* pixels)
1374 {
1375 SetActiveTextureUnit(TEMP_BIND_UNIT);
1376 BindTexture(TEMP_BIND_UNIT, target, image);
1377 glTexSubImage2D((GLenum)target, (GLint)level, (GLint)offset.x, (GLint)offset.y, (GLsizei)extent.x,
1378 (GLsizei)extent.y, (GLenum)format, (GLenum)type, pixels);
1379 }
1380
TexSubImage3D(uint32_t image,uint32_t target,uint32_t level,const Math::UVec3 & offset,const Math::UVec3 & extent,uint32_t format,uint32_t type,const void * pixels)1381 void DeviceGLES::TexSubImage3D(uint32_t image, uint32_t target, uint32_t level, const Math::UVec3& offset,
1382 const Math::UVec3& extent, uint32_t format, uint32_t type, const void* pixels)
1383 {
1384 SetActiveTextureUnit(TEMP_BIND_UNIT);
1385 BindTexture(TEMP_BIND_UNIT, target, image);
1386 glTexSubImage3D((GLenum)target, (GLint)level, (GLint)offset.x, (GLint)offset.y, (GLint)offset.z, (GLsizei)extent.x,
1387 (GLsizei)extent.y, (GLsizei)extent.z, (GLenum)format, (GLenum)type, pixels);
1388 }
1389
CompressedTexSubImage2D(uint32_t image,uint32_t target,uint32_t level,const Math::UVec2 & offset,const Math::UVec2 & extent,uint32_t format,uint32_t imageSize,const void * data)1390 void DeviceGLES::CompressedTexSubImage2D(uint32_t image, uint32_t target, uint32_t level, const Math::UVec2& offset,
1391 const Math::UVec2& extent, uint32_t format, uint32_t imageSize, const void* data)
1392 {
1393 SetActiveTextureUnit(TEMP_BIND_UNIT);
1394 BindTexture(TEMP_BIND_UNIT, target, image);
1395 glCompressedTexSubImage2D((GLenum)target, (GLint)level, (GLint)offset.x, (GLint)offset.y, (GLsizei)extent.x,
1396 (GLsizei)extent.y, (GLenum)format, (GLint)imageSize, data);
1397 }
1398
CompressedTexSubImage3D(uint32_t image,uint32_t target,uint32_t level,const Math::UVec3 & offset,const Math::UVec3 & extent,uint32_t format,uint32_t imageSize,const void * data)1399 void DeviceGLES::CompressedTexSubImage3D(uint32_t image, uint32_t target, uint32_t level, const Math::UVec3& offset,
1400 const Math::UVec3& extent, uint32_t format, uint32_t imageSize, const void* data)
1401 {
1402 SetActiveTextureUnit(TEMP_BIND_UNIT);
1403 BindTexture(TEMP_BIND_UNIT, target, image);
1404 glCompressedTexSubImage3D((GLenum)target, (GLint)level, (GLint)offset.x, (GLint)offset.y, (GLint)offset.z,
1405 (GLsizei)extent.x, (GLsizei)extent.y, (GLsizei)extent.z, (GLenum)format, (GLint)imageSize, data);
1406 }
1407
GetGlImageFormat(const Format format) const1408 const DeviceGLES::ImageFormat& DeviceGLES::GetGlImageFormat(const Format format) const
1409 {
1410 if (const auto pos = std::lower_bound(supportedFormats_.begin(), supportedFormats_.end(), format,
1411 [](const ImageFormat& element, const Format value) { return element.coreFormat < value; });
1412 (pos != supportedFormats_.end()) && (pos->coreFormat == format)) {
1413 return *pos;
1414 }
1415 PLUGIN_LOG_I("asking for unsupported format %u", format);
1416 return supportedFormats_[0];
1417 }
1418
DeleteTexture(uint32_t texture)1419 void DeviceGLES::DeleteTexture(uint32_t texture)
1420 {
1421 UnBindTexture(texture);
1422 glDeleteTextures(1, &texture);
1423 }
1424
DeleteBuffer(uint32_t buffer)1425 void DeviceGLES::DeleteBuffer(uint32_t buffer)
1426 {
1427 UnBindBuffer(buffer);
1428 glDeleteBuffers(1, &buffer);
1429 }
1430
DeleteSampler(uint32_t sampler)1431 void DeviceGLES::DeleteSampler(uint32_t sampler)
1432 {
1433 UnBindSampler(sampler);
1434 glDeleteSamplers(1, &sampler);
1435 }
1436
CreateVertexArray()1437 uint32_t DeviceGLES::CreateVertexArray()
1438 {
1439 GLuint vao;
1440 glGenVertexArrays(1, &vao);
1441 if (vaoStatesInUse_ == vaoStates_.size()) {
1442 for (auto it = vaoStates_.begin(); it != vaoStates_.end(); it++) {
1443 if (it->vao == 0) {
1444 // re-use old "object"
1445 it->vao = vao;
1446 vaoStatesInUse_++;
1447 return static_cast<uint32_t>(1 + (it - vaoStates_.begin()));
1448 }
1449 }
1450 }
1451 VAOState v;
1452 v.vao = vao;
1453 vaoStates_.push_back(v);
1454 vaoStatesInUse_++;
1455 return static_cast<uint32_t>(vaoStates_.size());
1456 }
1457
DeleteVertexArray(uint32_t vao)1458 void DeviceGLES::DeleteVertexArray(uint32_t vao)
1459 {
1460 PLUGIN_ASSERT(!vaoStates_.empty());
1461 if (vao > 0) {
1462 UnBindVertexArray(vao);
1463 auto& state = vaoStates_[vao - 1];
1464 glDeleteVertexArrays(1, &state.vao);
1465 state = {}; // clear the object.
1466 vaoStatesInUse_--;
1467 }
1468 }
1469
DeleteFrameBuffer(uint32_t fbo)1470 void DeviceGLES::DeleteFrameBuffer(uint32_t fbo)
1471 {
1472 PLUGIN_ASSERT(IsActive());
1473 UnBindFrameBuffer(fbo);
1474 glDeleteFramebuffers(1, &fbo);
1475 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
1476 PLUGIN_LOG_D("fbo id <: %u", fbo);
1477 #endif
1478 }
1479
UnBindTexture(uint32_t texture)1480 void DeviceGLES::UnBindTexture(uint32_t texture)
1481 {
1482 uint32_t unit = 0;
1483 for (auto& textureUnit : boundTexture_) {
1484 uint32_t targetId = 0;
1485 for (uint32_t& typeBinding : textureUnit) {
1486 if (typeBinding == texture + 1) {
1487 SetActiveTextureUnit(unit);
1488 const uint32_t target = TextureTargetIdToTarget(TextureTargetId { targetId });
1489 glBindTexture(target, 0);
1490 typeBinding = 0;
1491 }
1492 targetId++;
1493 }
1494 unit++;
1495 }
1496
1497 unit = 0;
1498 for (auto& image : boundImage_) {
1499 if ((image.bound) && (image.texture == texture)) {
1500 glBindImageTexture(static_cast<GLuint>(unit), 0, 0, false, 0, GL_READ_ONLY, GL_R32UI);
1501 // set default state...
1502 image.bound = false;
1503 image.texture = 0;
1504 image.level = 0;
1505 image.layered = false;
1506 image.access = GL_READ_ONLY;
1507 image.format = GL_R32UI;
1508 }
1509 unit++;
1510 }
1511 }
1512
UnBindBuffer(uint32_t buffer)1513 void DeviceGLES::UnBindBuffer(uint32_t buffer)
1514 {
1515 uint32_t tid = 0;
1516 for (auto& buffers : boundBuffers_) {
1517 const uint32_t targetId = IndexedTargetIdToTarget(BufferBindId { tid });
1518 uint32_t bid = 0;
1519 for (auto& slot : buffers) {
1520 if (slot.buffer == buffer) {
1521 glBindBufferRange(targetId, bid, 0, 0, 0);
1522 // nothing bound
1523 slot.cached = false;
1524 slot.buffer = 0;
1525 slot.offset = 0;
1526 slot.size = 0;
1527 }
1528 bid++;
1529 }
1530 tid++;
1531 }
1532
1533 tid = 0;
1534 for (auto& slot : bufferBound_) {
1535 if (slot.buffer == buffer) {
1536 const uint32_t targetId = GenericTargetIdToTarget(BufferTargetId { tid });
1537 glBindBuffer(targetId, 0);
1538 // nothing bound
1539 slot.bound = false;
1540 slot.buffer = 0;
1541 }
1542 tid++;
1543 }
1544
1545 // scan VAOs also..
1546 UnBindBufferFromVertexArray(buffer);
1547 }
1548
UnBindBufferFromVertexArray(uint32_t buffer)1549 void DeviceGLES::UnBindBufferFromVertexArray(uint32_t buffer)
1550 {
1551 uint32_t vao = 1;
1552 uint32_t wasbound = BoundVertexArray();
1553 for (auto& state : vaoStates_) {
1554 if (state.vao > 0) {
1555 auto& elementBuffer = state.elementBuffer;
1556 auto& vertexBufferBinds = state.vertexBufferBinds;
1557 int slot = 0;
1558 for (auto& t : vertexBufferBinds) {
1559 if ((t.bound) && (t.buffer == buffer)) {
1560 // detach the buffer from vao.
1561 BindVertexArray(vao);
1562 glBindVertexBuffer((GLuint)slot, 0, 0, 0);
1563 t.bound = false;
1564 t.buffer = 0;
1565 t.offset = 0;
1566 t.stride = 0;
1567 }
1568 slot++;
1569 }
1570 if ((elementBuffer.bound) && (elementBuffer.buffer == buffer)) {
1571 // detach the buffer from vao.
1572 BindVertexArray(vao);
1573 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1574 elementBuffer.bound = false;
1575 elementBuffer.buffer = 0;
1576 }
1577 }
1578 vao++;
1579 }
1580 BindVertexArray(wasbound);
1581 }
1582
UnBindSampler(uint32_t sampler)1583 void DeviceGLES::UnBindSampler(uint32_t sampler)
1584 {
1585 for (uint32_t& boundSampler : boundSampler_) {
1586 if ((sampler + 1) == boundSampler) {
1587 glBindSampler((sampler + 1), 0);
1588 boundSampler = 0;
1589 }
1590 }
1591 }
1592
UnBindVertexArray(uint32_t vao)1593 void DeviceGLES::UnBindVertexArray(uint32_t vao)
1594 {
1595 if (boundVao_ == vao) {
1596 glBindVertexArray(0);
1597 boundVao_ = 0;
1598 }
1599 }
1600
UnBindFrameBuffer(uint32_t fbo)1601 void DeviceGLES::UnBindFrameBuffer(uint32_t fbo)
1602 {
1603 if ((fbo == boundReadFbo_) && (fbo == boundWriteFbo_)) {
1604 boundReadFbo_ = 0;
1605 boundWriteFbo_ = 0;
1606 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1607 } else if (boundWriteFbo_ == fbo) {
1608 boundWriteFbo_ = 0;
1609 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1610 } else if (boundReadFbo_ == fbo) {
1611 boundReadFbo_ = 0;
1612 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1613 }
1614 }
1615
BoundVertexArray() const1616 uint32_t DeviceGLES::BoundVertexArray() const
1617 {
1618 return boundVao_;
1619 }
1620
BindFrameBuffer(uint32_t fbo)1621 void DeviceGLES::BindFrameBuffer(uint32_t fbo)
1622 {
1623 if ((boundReadFbo_ != fbo) && (boundWriteFbo_ != fbo)) {
1624 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1625 boundReadFbo_ = boundWriteFbo_ = fbo;
1626 } else if (boundWriteFbo_ != fbo) {
1627 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1628 boundWriteFbo_ = fbo;
1629 } else if (boundReadFbo_ != fbo) {
1630 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1631 boundReadFbo_ = fbo;
1632 }
1633 }
1634
BindReadFrameBuffer(uint32_t fbo)1635 void DeviceGLES::BindReadFrameBuffer(uint32_t fbo)
1636 {
1637 if (boundReadFbo_ != fbo) {
1638 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1639 boundReadFbo_ = fbo;
1640 }
1641 }
1642
BindWriteFrameBuffer(uint32_t fbo)1643 void DeviceGLES::BindWriteFrameBuffer(uint32_t fbo)
1644 {
1645 if (boundWriteFbo_ != fbo) {
1646 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1647 boundWriteFbo_ = fbo;
1648 }
1649 }
1650
BindVertexArray(uint32_t vao)1651 void DeviceGLES::BindVertexArray(uint32_t vao)
1652 {
1653 if (boundVao_ != vao) {
1654 PLUGIN_ASSERT(vao <= vaoStates_.size());
1655 if (vao > 0) {
1656 glBindVertexArray(vaoStates_[vao - 1].vao);
1657 } else {
1658 glBindVertexArray(0);
1659 }
1660 boundVao_ = vao;
1661 }
1662 }
1663
BindVertexBuffer(uint32_t slot,uint32_t buffer,intptr_t offset,intptr_t stride)1664 void DeviceGLES::BindVertexBuffer(uint32_t slot, uint32_t buffer, intptr_t offset, intptr_t stride)
1665 {
1666 PLUGIN_ASSERT(boundVao_ > 0);
1667 PLUGIN_ASSERT(boundVao_ <= vaoStates_.size());
1668 auto& vertexBufferBinds = vaoStates_[boundVao_ - 1].vertexBufferBinds;
1669 bool bind = true;
1670 if (vertexBufferBinds[slot].bound) {
1671 bind = (vertexBufferBinds[slot].buffer != buffer) || (vertexBufferBinds[slot].offset != offset) ||
1672 (vertexBufferBinds[slot].stride != stride);
1673 }
1674 if (bind) {
1675 vertexBufferBinds[slot].bound = true;
1676 vertexBufferBinds[slot].buffer = buffer;
1677 vertexBufferBinds[slot].offset = offset;
1678 vertexBufferBinds[slot].stride = stride;
1679 glBindVertexBuffer((GLuint)slot, (GLuint)buffer, (GLintptr)offset, (GLsizei)stride);
1680 }
1681 }
1682
VertexBindingDivisor(uint32_t slot,uint32_t divisor)1683 void DeviceGLES::VertexBindingDivisor(uint32_t slot, uint32_t divisor)
1684 {
1685 PLUGIN_ASSERT(boundVao_ > 0);
1686 PLUGIN_ASSERT(boundVao_ <= vaoStates_.size());
1687 auto& vertexBufferBinds = vaoStates_[boundVao_ - 1].vertexBufferBinds;
1688 if (vertexBufferBinds[slot].divisor != divisor) {
1689 vertexBufferBinds[slot].divisor = divisor;
1690 glVertexBindingDivisor(slot, divisor);
1691 }
1692 }
1693
BindElementBuffer(uint32_t buffer)1694 void DeviceGLES::BindElementBuffer(uint32_t buffer)
1695 {
1696 PLUGIN_ASSERT(boundVao_ > 0);
1697 PLUGIN_ASSERT(boundVao_ <= vaoStates_.size());
1698 auto& elementBuffer = vaoStates_[boundVao_ - 1].elementBuffer;
1699 bool bind = true;
1700 if (elementBuffer.bound) {
1701 bind = (buffer != elementBuffer.buffer);
1702 }
1703 if (bind) {
1704 elementBuffer.bound = true;
1705 elementBuffer.buffer = buffer;
1706 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
1707 }
1708 }
1709
AllowThreadedProcessing() const1710 bool DeviceGLES::AllowThreadedProcessing() const
1711 {
1712 return HasExtension("GL_EXT_buffer_storage");
1713 }
1714
CreateGpuBuffer(const GpuBufferDesc & desc)1715 unique_ptr<GpuBuffer> DeviceGLES::CreateGpuBuffer(const GpuBufferDesc& desc)
1716 {
1717 return make_unique<GpuBufferGLES>(*this, desc);
1718 }
1719
CreateGpuImage(const GpuImageDesc & desc)1720 unique_ptr<GpuImage> DeviceGLES::CreateGpuImage(const GpuImageDesc& desc)
1721 {
1722 return make_unique<GpuImageGLES>(*this, desc);
1723 }
1724
CreateGpuImageView(const GpuImageDesc & desc,const GpuImagePlatformData & platformData)1725 unique_ptr<GpuImage> DeviceGLES::CreateGpuImageView(const GpuImageDesc& desc, const GpuImagePlatformData& platformData)
1726 {
1727 PLUGIN_ASSERT(IsActive());
1728 return make_unique<GpuImageGLES>(*this, desc, platformData);
1729 }
1730
CreateGpuImageViews(const Swapchain & platformSwapchain)1731 vector<unique_ptr<GpuImage>> DeviceGLES::CreateGpuImageViews(const Swapchain& platformSwapchain)
1732 {
1733 vector<unique_ptr<GpuImage>> gpuImages;
1734 const SwapchainGLES& swapchain = (const SwapchainGLES&)platformSwapchain;
1735 const GpuImageDesc& desc = swapchain.GetDesc();
1736 const auto& swapchainPlat = swapchain.GetPlatformData();
1737
1738 gpuImages.resize(swapchainPlat.swapchainImages.images.size());
1739
1740 PLUGIN_ASSERT(IsActive());
1741 for (size_t idx = 0; idx < gpuImages.size(); ++idx) {
1742 GpuImagePlatformDataGL gpuImagePlat {};
1743 gpuImagePlat.image = swapchainPlat.swapchainImages.images[idx];
1744 gpuImagePlat.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
1745 gpuImages[idx] = CreateGpuImageView(desc, gpuImagePlat);
1746 }
1747 return gpuImages;
1748 }
1749
CreateGpuImageView(const GpuImageDesc & desc,const BackendSpecificImageDesc & platformData)1750 unique_ptr<GpuImage> DeviceGLES::CreateGpuImageView(
1751 const GpuImageDesc& desc, const BackendSpecificImageDesc& platformData)
1752 {
1753 PLUGIN_ASSERT(IsActive());
1754 GpuImagePlatformDataGL data {};
1755 #if RENDER_HAS_GLES_BACKEND
1756 if (backendType_ == DeviceBackendType::OPENGLES) {
1757 const ImageDescGLES& tmp = (const ImageDescGLES&)platformData;
1758 data.type = tmp.type;
1759 data.image = tmp.image;
1760 data.bytesperpixel = tmp.bytesperpixel;
1761 data.dataType = tmp.dataType;
1762 data.format = tmp.format;
1763 data.internalFormat = tmp.internalFormat;
1764 data.eglImage = tmp.eglImage;
1765 }
1766 #endif
1767 #if RENDER_HAS_GL_BACKEND
1768 if (backendType_ == DeviceBackendType::OPENGL) {
1769 const ImageDescGL& tmp = (const ImageDescGL&)platformData;
1770 data.type = tmp.type;
1771 data.image = tmp.image;
1772 data.bytesperpixel = tmp.bytesperpixel;
1773 data.dataType = tmp.dataType;
1774 data.format = tmp.format;
1775 data.internalFormat = tmp.internalFormat;
1776 }
1777 #endif
1778 data.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
1779 return CreateGpuImageView(desc, data);
1780 }
1781
CreateGpuSampler(const GpuSamplerDesc & desc)1782 unique_ptr<GpuSampler> DeviceGLES::CreateGpuSampler(const GpuSamplerDesc& desc)
1783 {
1784 return make_unique<GpuSamplerGLES>(*this, desc);
1785 }
1786
CreateGpuAccelerationStructure(const GpuAccelerationStructureDesc & desc)1787 unique_ptr<GpuAccelerationStructure> DeviceGLES::CreateGpuAccelerationStructure(
1788 const GpuAccelerationStructureDesc& desc)
1789 {
1790 // NOTE: not supported
1791 return nullptr;
1792 }
1793
CreateRenderFrameSync()1794 unique_ptr<RenderFrameSync> DeviceGLES::CreateRenderFrameSync()
1795 {
1796 return make_unique<RenderFrameSyncGLES>(*this);
1797 }
1798
CreateRenderBackend(GpuResourceManager & gpuResourceMgr,const CORE_NS::IParallelTaskQueue::Ptr &)1799 unique_ptr<RenderBackend> DeviceGLES::CreateRenderBackend(
1800 GpuResourceManager& gpuResourceMgr, const CORE_NS::IParallelTaskQueue::Ptr&)
1801 {
1802 return make_unique<RenderBackendGLES>(*this, gpuResourceMgr);
1803 }
1804
CreateShaderModule(const ShaderModuleCreateInfo & data)1805 unique_ptr<ShaderModule> DeviceGLES::CreateShaderModule(const ShaderModuleCreateInfo& data)
1806 {
1807 return make_unique<ShaderModuleGLES>(*this, data);
1808 }
1809
CreateComputeShaderModule(const ShaderModuleCreateInfo & data)1810 unique_ptr<ShaderModule> DeviceGLES::CreateComputeShaderModule(const ShaderModuleCreateInfo& data)
1811 {
1812 return make_unique<ShaderModuleGLES>(*this, data);
1813 }
1814
CreateGpuShaderProgram(const GpuShaderProgramCreateData & data)1815 unique_ptr<GpuShaderProgram> DeviceGLES::CreateGpuShaderProgram(const GpuShaderProgramCreateData& data)
1816 {
1817 return make_unique<GpuShaderProgramGLES>(*this, data);
1818 }
1819
CreateGpuComputeProgram(const GpuComputeProgramCreateData & data)1820 unique_ptr<GpuComputeProgram> DeviceGLES::CreateGpuComputeProgram(const GpuComputeProgramCreateData& data)
1821 {
1822 return make_unique<GpuComputeProgramGLES>(*this, data);
1823 }
1824
CreateNodeContextDescriptorSetManager()1825 unique_ptr<NodeContextDescriptorSetManager> DeviceGLES::CreateNodeContextDescriptorSetManager()
1826 {
1827 return make_unique<NodeContextDescriptorSetManagerGLES>(*this);
1828 }
1829
CreateNodeContextPoolManager(GpuResourceManager & gpuResourceMgr,const GpuQueue & gpuQueue)1830 unique_ptr<NodeContextPoolManager> DeviceGLES::CreateNodeContextPoolManager(
1831 GpuResourceManager& gpuResourceMgr, const GpuQueue& gpuQueue)
1832 {
1833 return make_unique<NodeContextPoolManagerGLES>(*this, gpuResourceMgr);
1834 }
1835
CreateGraphicsPipelineStateObject(const GpuShaderProgram & gpuProgram,const GraphicsState & graphicsState,const PipelineLayout & pipelineLayout,const VertexInputDeclarationView & vertexInputDeclaration,const ShaderSpecializationConstantDataView & specializationConstants,const DynamicStateFlags dynamicStateFlags,const RenderPassDesc & renderPassDesc,const array_view<const RenderPassSubpassDesc> & renderPassSubpassDescs,const uint32_t subpassIndex,const LowLevelRenderPassData * renderPassData,const LowLevelPipelineLayoutData * pipelineLayoutData)1836 unique_ptr<GraphicsPipelineStateObject> DeviceGLES::CreateGraphicsPipelineStateObject(
1837 const GpuShaderProgram& gpuProgram, const GraphicsState& graphicsState, const PipelineLayout& pipelineLayout,
1838 const VertexInputDeclarationView& vertexInputDeclaration,
1839 const ShaderSpecializationConstantDataView& specializationConstants, const DynamicStateFlags dynamicStateFlags,
1840 const RenderPassDesc& renderPassDesc, const array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs,
1841 const uint32_t subpassIndex, const LowLevelRenderPassData* renderPassData,
1842 const LowLevelPipelineLayoutData* pipelineLayoutData)
1843 {
1844 PLUGIN_ASSERT(!renderPassData);
1845 PLUGIN_ASSERT(!pipelineLayoutData);
1846 return make_unique<GraphicsPipelineStateObjectGLES>(*this, gpuProgram, graphicsState, pipelineLayout,
1847 vertexInputDeclaration, specializationConstants, dynamicStateFlags, renderPassDesc, renderPassSubpassDescs,
1848 subpassIndex);
1849 }
1850
CreateComputePipelineStateObject(const GpuComputeProgram & gpuProgram,const PipelineLayout & pipelineLayout,const ShaderSpecializationConstantDataView & specializationConstants,const LowLevelPipelineLayoutData * pipelineLayoutData)1851 unique_ptr<ComputePipelineStateObject> DeviceGLES::CreateComputePipelineStateObject(const GpuComputeProgram& gpuProgram,
1852 const PipelineLayout& pipelineLayout, const ShaderSpecializationConstantDataView& specializationConstants,
1853 const LowLevelPipelineLayoutData* pipelineLayoutData)
1854 {
1855 PLUGIN_ASSERT(!pipelineLayoutData);
1856 return make_unique<ComputePipelineStateObjectGLES>(*this, gpuProgram, pipelineLayout, specializationConstants);
1857 }
1858
LowLevelDeviceGLES(DeviceGLES & deviceGLES)1859 LowLevelDeviceGLES::LowLevelDeviceGLES(DeviceGLES& deviceGLES)
1860 : deviceGLES_(deviceGLES), gpuResourceMgr_(static_cast<GpuResourceManager&>(deviceGLES.GetGpuResourceManager()))
1861 {}
1862
GetBackendType() const1863 DeviceBackendType LowLevelDeviceGLES::GetBackendType() const
1864 {
1865 return deviceGLES_.GetBackendType();
1866 }
1867 RENDER_END_NAMESPACE()
1868