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