Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/drivers/gles3/storage/render_scene_buffers_gles3.cpp
10005 views
1
/**************************************************************************/
2
/* render_scene_buffers_gles3.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#ifdef GLES3_ENABLED
32
33
#include "render_scene_buffers_gles3.h"
34
#include "config.h"
35
#include "texture_storage.h"
36
#include "utilities.h"
37
38
#ifdef ANDROID_ENABLED
39
#define glFramebufferTextureMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultiviewOVR
40
#define glTexStorage3DMultisample GLES3::Config::get_singleton()->eglTexStorage3DMultisample
41
#define glFramebufferTexture2DMultisampleEXT GLES3::Config::get_singleton()->eglFramebufferTexture2DMultisampleEXT
42
#define glFramebufferTextureMultisampleMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultisampleMultiviewOVR
43
#endif // ANDROID_ENABLED
44
45
// Will only be defined if GLES 3.2 headers are included
46
#ifndef GL_TEXTURE_2D_MULTISAMPLE_ARRAY
47
#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
48
#endif
49
50
RenderSceneBuffersGLES3::RenderSceneBuffersGLES3() {
51
for (int i = 0; i < 4; i++) {
52
glow.levels[i].color = 0;
53
glow.levels[i].fbo = 0;
54
}
55
}
56
57
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
58
free_render_buffer_data();
59
}
60
61
void RenderSceneBuffersGLES3::_rt_attach_textures(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count, bool p_depth_has_stencil) {
62
if (p_view_count > 1) {
63
if (p_samples > 1) {
64
#if defined(ANDROID_ENABLED) || defined(WEB_ENABLED)
65
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, p_samples, 0, p_view_count);
66
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, p_depth_has_stencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, p_depth, 0, p_samples, 0, p_view_count);
67
#else
68
ERR_PRINT_ONCE("Multiview MSAA isn't supported on this platform.");
69
#endif
70
} else {
71
#ifndef IOS_ENABLED
72
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, p_color, 0, 0, p_view_count);
73
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, p_depth_has_stencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, p_depth, 0, 0, p_view_count);
74
#else
75
ERR_PRINT_ONCE("Multiview isn't supported on this platform.");
76
#endif
77
}
78
} else {
79
if (p_samples > 1) {
80
#ifdef ANDROID_ENABLED
81
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0, p_samples);
82
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, p_depth_has_stencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0, p_samples);
83
#else
84
ERR_PRINT_ONCE("MSAA via EXT_multisampled_render_to_texture isn't supported on this platform.");
85
#endif
86
} else {
87
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_color, 0);
88
glFramebufferTexture2D(GL_FRAMEBUFFER, p_depth_has_stencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, p_depth, 0);
89
}
90
}
91
}
92
93
GLuint RenderSceneBuffersGLES3::_rt_get_cached_fbo(GLuint p_color, GLuint p_depth, GLsizei p_samples, uint32_t p_view_count) {
94
FBDEF new_fbo;
95
96
#if defined(ANDROID_ENABLED) || defined(WEB_ENABLED)
97
// There shouldn't be more then 3 entries in this...
98
for (const FBDEF &cached_fbo : msaa3d.cached_fbos) {
99
if (cached_fbo.color == p_color && cached_fbo.depth == p_depth) {
100
return cached_fbo.fbo;
101
}
102
}
103
104
new_fbo.color = p_color;
105
new_fbo.depth = p_depth;
106
107
glGenFramebuffers(1, &new_fbo.fbo);
108
glBindFramebuffer(GL_FRAMEBUFFER, new_fbo.fbo);
109
110
_rt_attach_textures(p_color, p_depth, p_samples, p_view_count, true);
111
112
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
113
if (status != GL_FRAMEBUFFER_COMPLETE) {
114
WARN_PRINT("Could not create 3D MSAA framebuffer, status: " + GLES3::TextureStorage::get_singleton()->get_framebuffer_error(status));
115
116
glDeleteFramebuffers(1, &new_fbo.fbo);
117
118
new_fbo.fbo = 0;
119
} else {
120
// cache it!
121
msaa3d.cached_fbos.push_back(new_fbo);
122
}
123
124
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
125
#endif
126
127
return new_fbo.fbo;
128
}
129
130
void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p_config) {
131
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
132
GLES3::Config *config = GLES3::Config::get_singleton();
133
134
free_render_buffer_data();
135
136
internal_size = p_config->get_internal_size();
137
target_size = p_config->get_target_size();
138
scaling_3d_mode = p_config->get_scaling_3d_mode();
139
//fsr_sharpness = p_config->get_fsr_sharpness();
140
//texture_mipmap_bias = p_config->get_texture_mipmap_bias();
141
//anisotropic_filtering_level = p_config->get_anisotropic_filtering_level();
142
render_target = p_config->get_render_target();
143
msaa3d.mode = p_config->get_msaa_3d();
144
//screen_space_aa = p_config->get_screen_space_aa();
145
//use_debanding = p_config->get_use_debanding();
146
view_count = config->multiview_supported ? p_config->get_view_count() : 1;
147
148
bool use_multiview = view_count > 1;
149
150
// Get color format data from our render target so we match those
151
if (render_target.is_valid()) {
152
color_internal_format = texture_storage->render_target_get_color_internal_format(render_target);
153
color_format = texture_storage->render_target_get_color_format(render_target);
154
color_type = texture_storage->render_target_get_color_type(render_target);
155
color_format_size = texture_storage->render_target_get_color_format_size(render_target);
156
} else {
157
// reflection probe? or error?
158
color_internal_format = GL_RGBA8;
159
color_format = GL_RGBA;
160
color_type = GL_UNSIGNED_BYTE;
161
color_format_size = 4;
162
}
163
164
// Check our scaling mode
165
if (scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF && internal_size.x == 0 && internal_size.y == 0) {
166
// Disable, no size set.
167
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
168
} else if (scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF && internal_size == target_size) {
169
// If size matches, we won't use scaling.
170
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
171
} else if (scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF && scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_BILINEAR) {
172
// We only support bilinear scaling atm.
173
WARN_PRINT_ONCE("GLES only supports bilinear scaling.");
174
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
175
}
176
177
// Check if we support MSAA.
178
if (msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && internal_size.x == 0 && internal_size.y == 0) {
179
// Disable, no size set.
180
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
181
} else if (!use_multiview && msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && !config->msaa_supported && !config->rt_msaa_supported) {
182
WARN_PRINT_ONCE("MSAA is not supported on this device.");
183
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
184
} else if (use_multiview && msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && !config->msaa_multiview_supported && !config->rt_msaa_multiview_supported) {
185
WARN_PRINT_ONCE("Multiview MSAA is not supported on this device.");
186
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
187
}
188
189
// We don't create our buffers right away because post effects can be made active at any time and change our buffer configuration.
190
}
191
192
void RenderSceneBuffersGLES3::_check_render_buffers() {
193
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
194
GLES3::Config *config = GLES3::Config::get_singleton();
195
196
ERR_FAIL_COND(view_count == 0);
197
198
bool use_internal_buffer = scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF || apply_color_adjustments_in_post;
199
GLenum depth_format = GL_DEPTH24_STENCIL8;
200
uint32_t depth_format_size = 4;
201
bool use_multiview = view_count > 1;
202
203
if ((!use_internal_buffer || internal3d.color != 0) && (msaa3d.mode == RS::VIEWPORT_MSAA_DISABLED || msaa3d.color != 0)) {
204
// already setup!
205
return;
206
}
207
208
if (use_internal_buffer && internal3d.color == 0) {
209
// Setup our internal buffer.
210
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
211
212
// Create our color buffer.
213
glGenTextures(1, &internal3d.color);
214
glBindTexture(texture_target, internal3d.color);
215
216
if (use_multiview) {
217
glTexImage3D(texture_target, 0, color_internal_format, internal_size.x, internal_size.y, view_count, 0, color_format, color_type, nullptr);
218
} else {
219
glTexImage2D(texture_target, 0, color_internal_format, internal_size.x, internal_size.y, 0, color_format, color_type, nullptr);
220
}
221
222
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
223
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
224
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
225
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
226
227
GLES3::Utilities::get_singleton()->texture_allocated_data(internal3d.color, internal_size.x * internal_size.y * view_count * color_format_size, "3D color texture");
228
229
// Create our depth buffer.
230
glGenTextures(1, &internal3d.depth);
231
glBindTexture(texture_target, internal3d.depth);
232
233
if (use_multiview) {
234
glTexImage3D(texture_target, 0, depth_format, internal_size.x, internal_size.y, view_count, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
235
} else {
236
glTexImage2D(texture_target, 0, depth_format, internal_size.x, internal_size.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
237
}
238
239
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
240
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
241
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
242
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
243
244
GLES3::Utilities::get_singleton()->texture_allocated_data(internal3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size, "3D depth texture");
245
246
// Create our internal 3D FBO.
247
// Note that if MSAA is used and our rt_msaa_* extensions are available, this is only used for blitting and effects.
248
glGenFramebuffers(1, &internal3d.fbo);
249
glBindFramebuffer(GL_FRAMEBUFFER, internal3d.fbo);
250
251
#ifndef IOS_ENABLED
252
if (use_multiview) {
253
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, internal3d.color, 0, 0, view_count);
254
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, internal3d.depth, 0, 0, view_count);
255
} else {
256
#else
257
{
258
#endif
259
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, internal3d.color, 0);
260
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texture_target, internal3d.depth, 0);
261
}
262
263
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
264
if (status != GL_FRAMEBUFFER_COMPLETE) {
265
_clear_intermediate_buffers();
266
WARN_PRINT("Could not create 3D internal buffers, status: " + texture_storage->get_framebuffer_error(status));
267
}
268
269
glBindTexture(texture_target, 0);
270
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
271
}
272
273
if (msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && msaa3d.color == 0) {
274
// Setup MSAA.
275
const GLsizei samples[] = { 1, 2, 4, 8 };
276
msaa3d.samples = samples[msaa3d.mode];
277
278
// Constrain by limits of OpenGL driver.
279
if (msaa3d.samples > config->msaa_max_samples) {
280
msaa3d.samples = config->msaa_max_samples;
281
}
282
283
if (!use_multiview && !config->rt_msaa_supported) {
284
// Render to texture extensions not supported? fall back to MSAA framebuffer through GL_EXT_framebuffer_multisample.
285
// Note, if 2D MSAA matches 3D MSAA and we're not scaling, it would be ideal if we reuse our 2D MSAA buffer here.
286
// We can't however because we don't trigger a change in configuration if 2D MSAA changes.
287
// We'll accept the overhead in this situation.
288
289
msaa3d.needs_resolve = true;
290
msaa3d.check_fbo_cache = false;
291
292
// Create our color buffer.
293
glGenRenderbuffers(1, &msaa3d.color);
294
glBindRenderbuffer(GL_RENDERBUFFER, msaa3d.color);
295
296
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa3d.samples, color_internal_format, internal_size.x, internal_size.y);
297
GLES3::Utilities::get_singleton()->render_buffer_allocated_data(msaa3d.color, internal_size.x * internal_size.y * view_count * 4 * msaa3d.samples, "MSAA 3D color render buffer");
298
299
// Create our depth buffer.
300
glGenRenderbuffers(1, &msaa3d.depth);
301
glBindRenderbuffer(GL_RENDERBUFFER, msaa3d.depth);
302
303
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa3d.samples, depth_format, internal_size.x, internal_size.y);
304
GLES3::Utilities::get_singleton()->render_buffer_allocated_data(msaa3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size * msaa3d.samples, "MSAA 3D depth render buffer");
305
306
// Create our MSAA 3D FBO.
307
glGenFramebuffers(1, &msaa3d.fbo);
308
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
309
310
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaa3d.color);
311
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, msaa3d.depth);
312
313
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
314
if (status != GL_FRAMEBUFFER_COMPLETE) {
315
_clear_msaa3d_buffers();
316
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
317
WARN_PRINT("Could not create 3D MSAA buffers, status: " + texture_storage->get_framebuffer_error(status));
318
}
319
320
glBindRenderbuffer(GL_RENDERBUFFER, 0);
321
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
322
#if !defined(IOS_ENABLED) && !defined(WEB_ENABLED)
323
} else if (use_multiview && !config->rt_msaa_multiview_supported) {
324
// Render to texture extensions not supported? fall back to MSAA textures through GL_EXT_multiview_texture_multisample.
325
msaa3d.needs_resolve = true;
326
msaa3d.check_fbo_cache = false;
327
328
// Create our color buffer.
329
glGenTextures(1, &msaa3d.color);
330
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.color);
331
332
#ifdef ANDROID_ENABLED
333
glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, color_internal_format, internal_size.x, internal_size.y, view_count, GL_TRUE);
334
#else
335
glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, color_internal_format, internal_size.x, internal_size.y, view_count, GL_TRUE);
336
#endif
337
338
GLES3::Utilities::get_singleton()->texture_allocated_data(msaa3d.color, internal_size.x * internal_size.y * view_count * color_format_size * msaa3d.samples, "MSAA 3D color texture");
339
340
// Create our depth buffer.
341
glGenTextures(1, &msaa3d.depth);
342
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.depth);
343
344
#ifdef ANDROID_ENABLED
345
glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, depth_format, internal_size.x, internal_size.y, view_count, GL_TRUE);
346
#else
347
glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, msaa3d.samples, depth_format, internal_size.x, internal_size.y, view_count, GL_TRUE);
348
#endif
349
350
GLES3::Utilities::get_singleton()->texture_allocated_data(msaa3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size * msaa3d.samples, "MSAA 3D depth texture");
351
352
// Create our MSAA 3D FBO.
353
glGenFramebuffers(1, &msaa3d.fbo);
354
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
355
356
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, msaa3d.color, 0, 0, view_count);
357
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, msaa3d.depth, 0, 0, view_count);
358
359
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
360
if (status != GL_FRAMEBUFFER_COMPLETE) {
361
_clear_msaa3d_buffers();
362
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
363
WARN_PRINT("Could not create 3D MSAA buffers, status: " + texture_storage->get_framebuffer_error(status));
364
}
365
366
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
367
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
368
#endif
369
#if defined(ANDROID_ENABLED) || defined(WEB_ENABLED) // Only supported on OpenGLES!
370
} else if (!use_internal_buffer) {
371
// We are going to render directly into our render target textures,
372
// these can change from frame to frame as we cycle through swapchains,
373
// hence we'll use our FBO cache here.
374
msaa3d.needs_resolve = false;
375
msaa3d.check_fbo_cache = true;
376
} else if (use_internal_buffer) {
377
// We can combine MSAA and scaling/effects.
378
msaa3d.needs_resolve = false;
379
msaa3d.check_fbo_cache = false;
380
381
// We render to our internal textures, MSAA is only done in tile memory only.
382
// On mobile this means MSAA never leaves tile memory = efficiency!
383
glGenFramebuffers(1, &msaa3d.fbo);
384
glBindFramebuffer(GL_FRAMEBUFFER, msaa3d.fbo);
385
386
_rt_attach_textures(internal3d.color, internal3d.depth, msaa3d.samples, view_count, true);
387
388
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
389
if (status != GL_FRAMEBUFFER_COMPLETE) {
390
_clear_msaa3d_buffers();
391
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
392
WARN_PRINT("Could not create 3D MSAA framebuffer, status: " + texture_storage->get_framebuffer_error(status));
393
}
394
395
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
396
#endif
397
} else {
398
// HUH? how did we get here?
399
WARN_PRINT_ONCE("MSAA is not supported on this device.");
400
msaa3d.mode = RS::VIEWPORT_MSAA_DISABLED;
401
msaa3d.samples = 1;
402
msaa3d.check_fbo_cache = false;
403
}
404
} else {
405
msaa3d.samples = 1;
406
msaa3d.check_fbo_cache = false;
407
}
408
}
409
410
void RenderSceneBuffersGLES3::configure_for_probe(Size2i p_size) {
411
internal_size = p_size;
412
target_size = p_size;
413
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
414
view_count = 1;
415
}
416
417
void RenderSceneBuffersGLES3::_clear_msaa3d_buffers() {
418
for (const FBDEF &cached_fbo : msaa3d.cached_fbos) {
419
GLuint fbo = cached_fbo.fbo;
420
glDeleteFramebuffers(1, &fbo);
421
}
422
msaa3d.cached_fbos.clear();
423
424
if (msaa3d.fbo) {
425
glDeleteFramebuffers(1, &msaa3d.fbo);
426
msaa3d.fbo = 0;
427
}
428
429
if (msaa3d.color != 0) {
430
if (view_count == 1) {
431
GLES3::Utilities::get_singleton()->render_buffer_free_data(msaa3d.color);
432
} else {
433
GLES3::Utilities::get_singleton()->texture_free_data(msaa3d.color);
434
}
435
msaa3d.color = 0;
436
}
437
438
if (msaa3d.depth != 0) {
439
if (view_count == 1) {
440
GLES3::Utilities::get_singleton()->render_buffer_free_data(msaa3d.depth);
441
} else {
442
GLES3::Utilities::get_singleton()->texture_free_data(msaa3d.depth);
443
}
444
msaa3d.depth = 0;
445
}
446
}
447
448
void RenderSceneBuffersGLES3::_clear_intermediate_buffers() {
449
if (internal3d.fbo) {
450
glDeleteFramebuffers(1, &internal3d.fbo);
451
internal3d.fbo = 0;
452
}
453
454
if (internal3d.color != 0) {
455
GLES3::Utilities::get_singleton()->texture_free_data(internal3d.color);
456
internal3d.color = 0;
457
}
458
459
if (internal3d.depth != 0) {
460
GLES3::Utilities::get_singleton()->texture_free_data(internal3d.depth);
461
internal3d.depth = 0;
462
}
463
}
464
465
void RenderSceneBuffersGLES3::check_backbuffer(bool p_need_color, bool p_need_depth) {
466
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
467
468
// Setup our back buffer
469
470
if (backbuffer3d.fbo == 0) {
471
glGenFramebuffers(1, &backbuffer3d.fbo);
472
}
473
474
glBindFramebuffer(GL_FRAMEBUFFER, backbuffer3d.fbo);
475
476
bool use_multiview = view_count > 1 && GLES3::Config::get_singleton()->multiview_supported;
477
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
478
GLenum depth_format = GL_DEPTH24_STENCIL8;
479
uint32_t depth_format_size = 4;
480
481
if (backbuffer3d.color == 0 && p_need_color) {
482
glGenTextures(1, &backbuffer3d.color);
483
glBindTexture(texture_target, backbuffer3d.color);
484
485
if (use_multiview) {
486
glTexImage3D(texture_target, 0, color_internal_format, internal_size.x, internal_size.y, view_count, 0, color_format, color_type, nullptr);
487
} else {
488
glTexImage2D(texture_target, 0, color_internal_format, internal_size.x, internal_size.y, 0, color_format, color_type, nullptr);
489
}
490
491
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
492
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
493
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
494
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
495
496
GLES3::Utilities::get_singleton()->texture_allocated_data(backbuffer3d.color, internal_size.x * internal_size.y * view_count * color_format_size, "3D Back buffer color texture");
497
498
#ifndef IOS_ENABLED
499
if (use_multiview) {
500
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, backbuffer3d.color, 0, 0, view_count);
501
} else {
502
#else
503
{
504
#endif
505
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, backbuffer3d.color, 0);
506
}
507
}
508
509
if (backbuffer3d.depth == 0 && p_need_depth) {
510
glGenTextures(1, &backbuffer3d.depth);
511
glBindTexture(texture_target, backbuffer3d.depth);
512
513
if (use_multiview) {
514
glTexImage3D(texture_target, 0, depth_format, internal_size.x, internal_size.y, view_count, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT, nullptr);
515
} else {
516
glTexImage2D(texture_target, 0, depth_format, internal_size.x, internal_size.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT, nullptr);
517
}
518
519
glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
520
glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
521
glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
522
glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
523
524
GLES3::Utilities::get_singleton()->texture_allocated_data(backbuffer3d.depth, internal_size.x * internal_size.y * view_count * depth_format_size, "3D back buffer depth texture");
525
526
#ifndef IOS_ENABLED
527
if (use_multiview) {
528
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, backbuffer3d.depth, 0, 0, view_count);
529
} else {
530
#else
531
{
532
#endif
533
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, texture_target, backbuffer3d.depth, 0);
534
}
535
}
536
537
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
538
if (status != GL_FRAMEBUFFER_COMPLETE) {
539
_clear_back_buffers();
540
WARN_PRINT("Could not create 3D back buffers, status: " + texture_storage->get_framebuffer_error(status));
541
}
542
543
glBindTexture(texture_target, 0);
544
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
545
}
546
547
void RenderSceneBuffersGLES3::_clear_back_buffers() {
548
if (backbuffer3d.fbo) {
549
glDeleteFramebuffers(1, &backbuffer3d.fbo);
550
backbuffer3d.fbo = 0;
551
}
552
553
if (backbuffer3d.color != 0) {
554
GLES3::Utilities::get_singleton()->texture_free_data(backbuffer3d.color);
555
backbuffer3d.color = 0;
556
}
557
558
if (backbuffer3d.depth != 0) {
559
GLES3::Utilities::get_singleton()->texture_free_data(backbuffer3d.depth);
560
backbuffer3d.depth = 0;
561
}
562
}
563
564
void RenderSceneBuffersGLES3::set_apply_color_adjustments_in_post(bool p_apply_in_post) {
565
apply_color_adjustments_in_post = p_apply_in_post;
566
}
567
568
void RenderSceneBuffersGLES3::check_glow_buffers() {
569
if (glow.levels[0].color != 0) {
570
// already have these setup..
571
return;
572
}
573
574
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
575
Size2i level_size = internal_size;
576
for (int i = 0; i < 4; i++) {
577
level_size = Size2i(level_size.x >> 1, level_size.y >> 1).maxi(4);
578
579
glow.levels[i].size = level_size;
580
581
// Create our texture
582
glGenTextures(1, &glow.levels[i].color);
583
glActiveTexture(GL_TEXTURE0);
584
glBindTexture(GL_TEXTURE_2D, glow.levels[i].color);
585
586
glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, level_size.x, level_size.y, 0, color_format, color_type, nullptr);
587
588
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
589
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
590
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
591
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
592
593
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
594
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
595
596
GLES3::Utilities::get_singleton()->texture_allocated_data(glow.levels[i].color, level_size.x * level_size.y * color_format_size, String("Glow buffer ") + String::num_int64(i));
597
598
// Create our FBO
599
glGenFramebuffers(1, &glow.levels[i].fbo);
600
glBindFramebuffer(GL_FRAMEBUFFER, glow.levels[i].fbo);
601
602
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glow.levels[i].color, 0);
603
604
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
605
if (status != GL_FRAMEBUFFER_COMPLETE) {
606
WARN_PRINT("Could not create glow buffers, status: " + texture_storage->get_framebuffer_error(status));
607
_clear_glow_buffers();
608
break;
609
}
610
}
611
612
glBindTexture(GL_TEXTURE_2D, 0);
613
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
614
}
615
616
void RenderSceneBuffersGLES3::_clear_glow_buffers() {
617
for (int i = 0; i < 4; i++) {
618
if (glow.levels[i].fbo != 0) {
619
glDeleteFramebuffers(1, &glow.levels[i].fbo);
620
glow.levels[i].fbo = 0;
621
}
622
623
if (glow.levels[i].color != 0) {
624
GLES3::Utilities::get_singleton()->texture_free_data(glow.levels[i].color);
625
glow.levels[i].color = 0;
626
}
627
}
628
}
629
630
void RenderSceneBuffersGLES3::free_render_buffer_data() {
631
_clear_msaa3d_buffers();
632
_clear_intermediate_buffers();
633
_clear_back_buffers();
634
_clear_glow_buffers();
635
}
636
637
GLuint RenderSceneBuffersGLES3::get_render_fbo() {
638
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
639
GLuint rt_fbo = 0;
640
641
_check_render_buffers();
642
643
if (msaa3d.check_fbo_cache) {
644
GLuint color = texture_storage->render_target_get_color(render_target);
645
GLuint depth = texture_storage->render_target_get_depth(render_target);
646
647
rt_fbo = _rt_get_cached_fbo(color, depth, msaa3d.samples, view_count);
648
if (rt_fbo == 0) {
649
// Somehow couldn't obtain this? Just render without MSAA.
650
rt_fbo = texture_storage->render_target_get_fbo(render_target);
651
}
652
} else if (msaa3d.fbo != 0) {
653
// We have an MSAA fbo, render to our MSAA buffer
654
return msaa3d.fbo;
655
} else if (internal3d.fbo != 0) {
656
// We have an internal buffer, render to our internal buffer!
657
return internal3d.fbo;
658
} else {
659
rt_fbo = texture_storage->render_target_get_fbo(render_target);
660
}
661
662
if (texture_storage->render_target_is_reattach_textures(render_target)) {
663
GLuint color = texture_storage->render_target_get_color(render_target);
664
GLuint depth = texture_storage->render_target_get_depth(render_target);
665
bool depth_has_stencil = texture_storage->render_target_get_depth_has_stencil(render_target);
666
667
glBindFramebuffer(GL_FRAMEBUFFER, rt_fbo);
668
_rt_attach_textures(color, depth, msaa3d.samples, view_count, depth_has_stencil);
669
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
670
}
671
672
return rt_fbo;
673
}
674
675
#endif // GLES3_ENABLED
676
677