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