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