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