summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/egl/egl_manager.cpp89
-rw-r--r--drivers/egl/egl_manager.h2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp3
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h6
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp9
-rw-r--r--drivers/gles3/rasterizer_gles3.h2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp15
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h2
-rw-r--r--drivers/gles3/shader_gles3.cpp5
-rw-r--r--drivers/gles3/shader_gles3.h2
-rw-r--r--drivers/gles3/shaders/scene.glsl3
-rw-r--r--drivers/gles3/storage/config.cpp44
-rw-r--r--drivers/gles3/storage/config.h15
-rw-r--r--drivers/gles3/storage/material_storage.cpp9
-rw-r--r--drivers/gles3/storage/particles_storage.cpp4
-rw-r--r--drivers/gles3/storage/particles_storage.h3
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.cpp18
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.h5
-rw-r--r--drivers/gles3/storage/utilities.cpp5
19 files changed, 165 insertions, 76 deletions
diff --git a/drivers/egl/egl_manager.cpp b/drivers/egl/egl_manager.cpp
index 6073856747..9c1d08331d 100644
--- a/drivers/egl/egl_manager.cpp
+++ b/drivers/egl/egl_manager.cpp
@@ -33,10 +33,22 @@
#ifdef EGL_ENABLED
#if defined(EGL_STATIC)
-#define KHRONOS_STATIC 1
+
#define GLAD_EGL_VERSION_1_5 true
+
+#ifdef EGL_EXT_platform_base
+#define GLAD_EGL_EXT_platform_base 1
+#endif
+
+#define KHRONOS_STATIC 1
extern "C" EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+extern "C" EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);
#undef KHRONOS_STATIC
+
+#endif // defined(EGL_STATIC)
+
+#ifndef EGL_EXT_platform_base
+#define GLAD_EGL_EXT_platform_base 0
#endif
// Creates and caches a GLDisplay. Returns -1 on error.
@@ -56,10 +68,23 @@ int EGLManager::_get_gldisplay_id(void *p_display) {
if (GLAD_EGL_VERSION_1_5) {
Vector<EGLAttrib> attribs = _get_platform_display_attributes();
new_gldisplay.egl_display = eglGetPlatformDisplay(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr);
+ } else if (GLAD_EGL_EXT_platform_base) {
+#ifdef EGL_EXT_platform_base
+ // eglGetPlatformDisplayEXT wants its attributes as EGLint, so we'll truncate
+ // what we already have. It's a bit naughty but I'm really not sure what else
+ // we could do here.
+ Vector<EGLint> attribs;
+ for (const EGLAttrib &attrib : _get_platform_display_attributes()) {
+ attribs.push_back((EGLint)attrib);
+ }
+
+ new_gldisplay.egl_display = eglGetPlatformDisplayEXT(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr);
+#endif // EGL_EXT_platform_base
} else {
NativeDisplayType *native_display_type = (NativeDisplayType *)new_gldisplay.display;
new_gldisplay.egl_display = eglGetDisplay(*native_display_type);
}
+
ERR_FAIL_COND_V(eglGetError() != EGL_SUCCESS, -1);
ERR_FAIL_COND_V_MSG(new_gldisplay.egl_display == EGL_NO_DISPLAY, -1, "Can't create an EGL display.");
@@ -326,30 +351,51 @@ EGLContext EGLManager::get_context(DisplayServer::WindowID p_window_id) {
return display.egl_context;
}
-Error EGLManager::initialize() {
+Error EGLManager::initialize(void *p_native_display) {
#if defined(GLAD_ENABLED) && !defined(EGL_STATIC)
- // Passing a null display loads just the bare minimum to create one. We'll have
- // to create a temporary test display and reload EGL with it to get a good idea
- // of what version is supported on this machine. Currently we're looking for
- // 1.5, the latest at the time of writing, which is actually pretty old.
- if (!gladLoaderLoadEGL(nullptr)) {
+ // Loading EGL with a new display gets us just the bare minimum API. We'll then
+ // have to temporarily get a proper display and reload EGL once again to
+ // initialize everything else.
+ if (!gladLoaderLoadEGL(EGL_NO_DISPLAY)) {
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL.");
}
- // NOTE: EGL_DEFAULT_DISPLAY returns whatever the O.S. deems suitable. I have
- // no idea if this may cause problems with multiple display servers and if we
- // should handle different EGL contexts in another way.
- EGLDisplay tmp_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- ERR_FAIL_COND_V(tmp_display == EGL_NO_DISPLAY, ERR_UNAVAILABLE);
+ EGLDisplay tmp_display = EGL_NO_DISPLAY;
+
+ if (GLAD_EGL_EXT_platform_base) {
+#ifdef EGL_EXT_platform_base
+ // eglGetPlatformDisplayEXT wants its attributes as EGLint.
+ Vector<EGLint> attribs;
+ for (const EGLAttrib &attrib : _get_platform_display_attributes()) {
+ attribs.push_back((EGLint)attrib);
+ }
+ tmp_display = eglGetPlatformDisplayEXT(_get_platform_extension_enum(), p_native_display, attribs.ptr());
+#endif // EGL_EXT_platform_base
+ } else {
+ WARN_PRINT("EGL: EGL_EXT_platform_base not found during init, using default platform.");
+ EGLNativeDisplayType *native_display_type = (EGLNativeDisplayType *)p_native_display;
+ tmp_display = eglGetDisplay(*native_display_type);
+ }
+
+ if (tmp_display == EGL_NO_DISPLAY) {
+ eglTerminate(tmp_display);
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't get a valid initial EGL display.");
+ }
eglInitialize(tmp_display, nullptr, nullptr);
int version = gladLoaderLoadEGL(tmp_display);
+ if (!version) {
+ eglTerminate(tmp_display);
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL.");
+ }
+
+ int major = GLAD_VERSION_MAJOR(version);
+ int minor = GLAD_VERSION_MINOR(version);
- ERR_FAIL_COND_V_MSG(!version, ERR_UNAVAILABLE, "Can't load EGL.");
- print_verbose(vformat("Loaded EGL %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)));
+ print_verbose(vformat("Loaded EGL %d.%d", major, minor));
- ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_4, ERR_UNAVAILABLE, "EGL version is too old!");
+ ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_4, ERR_UNAVAILABLE, vformat("EGL version is too old! %d.%d < 1.4", major, minor));
eglTerminate(tmp_display);
#endif
@@ -378,13 +424,14 @@ Error EGLManager::initialize() {
}
#endif
- String extensions_string = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- // The above method should always work. If it doesn't, something's very wrong.
- ERR_FAIL_COND_V(eglGetError() != EGL_SUCCESS, ERR_BUG);
+ String client_extensions_string = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- const char *platform = _get_platform_extension_name();
- if (!extensions_string.split(" ").has(platform)) {
- ERR_FAIL_V_MSG(ERR_UNAVAILABLE, vformat("EGL platform extension \"%s\" not found.", platform));
+ // If the above method fails, we don't support client extensions, so there's nothing to check.
+ if (eglGetError() == EGL_SUCCESS) {
+ const char *platform = _get_platform_extension_name();
+ if (!client_extensions_string.split(" ").has(platform)) {
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, vformat("EGL platform extension \"%s\" not found.", platform));
+ }
}
return OK;
diff --git a/drivers/egl/egl_manager.h b/drivers/egl/egl_manager.h
index 83779349f0..a4502c0687 100644
--- a/drivers/egl/egl_manager.h
+++ b/drivers/egl/egl_manager.h
@@ -107,7 +107,7 @@ public:
EGLContext get_context(DisplayServer::WindowID p_window_id);
- Error initialize();
+ Error initialize(void *p_native_display = nullptr);
EGLManager();
virtual ~EGLManager();
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 5fabeb94f5..941b1a1b28 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -2742,8 +2742,7 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
- int uniform_max_size = config->max_uniform_buffer_size;
- if (uniform_max_size < 65536) {
+ if (config->max_uniform_buffer_size < 65536) {
data.max_lights_per_render = 64;
} else {
data.max_lights_per_render = 256;
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index a3762e828e..7fc9992c3d 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -157,6 +157,8 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
float atlas_rect[4];
};
+ static_assert(sizeof(LightUniform) % 16 == 0, "2D light UBO size must be a multiple of 16 bytes");
+
public:
enum {
BASE_UNIFORM_LOCATION = 0,
@@ -186,6 +188,8 @@ public:
uint32_t pad2;
};
+ static_assert(sizeof(StateBuffer) % 16 == 0, "2D state UBO size must be a multiple of 16 bytes");
+
struct PolygonBuffers {
GLuint vertex_buffer = 0;
GLuint vertex_array = 0;
@@ -230,6 +234,8 @@ public:
uint32_t lights[4];
};
+ static_assert(sizeof(InstanceData) == 128, "2D instance data struct size must be 128 bytes");
+
struct Data {
GLuint canvas_quad_vertices;
GLuint canvas_quad_array;
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 993197e371..ae39c86d44 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -195,9 +195,9 @@ void RasterizerGLES3::initialize() {
Engine::get_singleton()->print_header(vformat("OpenGL API %s - Compatibility - Using Device: %s - %s", RS::get_singleton()->get_video_adapter_api_version(), RS::get_singleton()->get_video_adapter_vendor(), RS::get_singleton()->get_video_adapter_name()));
// FLIP XY Bug: Are more devices affected?
- // Confirmed so far: all Adreno 3xx
+ // Confirmed so far: all Adreno 3xx with old driver (until 2018)
// ok on some tested Adreno devices: 4xx, 5xx and 6xx
- flip_xy_bugfix = GLES3::Config::get_singleton()->adreno_3xx_compatibility;
+ flip_xy_workaround = GLES3::Config::get_singleton()->flip_xy_workaround;
}
void RasterizerGLES3::finalize() {
@@ -398,8 +398,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
// Viewport doesn't cover entire window so clear window to black before blitting.
// Querying the actual window size from the DisplayServer would deadlock in separate render thread mode,
// so let's set the biggest viewport the implementation supports, to be sure the window is fully covered.
- GLsizei max_vp[2] = {};
- glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_vp);
+ Size2i max_vp = GLES3::Utilities::get_singleton()->get_maximum_viewport_size();
glViewport(0, 0, max_vp[0], max_vp[1]);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
@@ -411,7 +410,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
// Adreno (TM) 3xx devices have a bug that create wrong Landscape rotation of 180 degree
// Reversing both the X and Y axis is equivalent to rotating 180 degrees
bool flip_x = false;
- if (flip_xy_bugfix && screen_rect_end.x > screen_rect_end.y) {
+ if (flip_xy_workaround && screen_rect_end.x > screen_rect_end.y) {
flip_y = !flip_y;
flip_x = !flip_x;
}
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 09d3c7bd52..0d0c26016d 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -56,7 +56,7 @@ private:
float delta = 0;
double time_total = 0.0;
- bool flip_xy_bugfix = false;
+ bool flip_xy_workaround = false;
static bool gles_over_gl;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 6a51ce6b70..9ea030bbd4 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -2245,9 +2245,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
}
bool glow_enabled = false;
- if (p_environment.is_valid() && rb.is_valid()) {
+ if (p_environment.is_valid()) {
glow_enabled = environment_get_glow_enabled(p_environment);
- rb->set_glow_enabled(glow_enabled); // ensure our intermediate buffer is available if glow is enabled
+ rb->ensure_internal_buffers(); // Ensure our intermediate buffer is available if glow is enabled
if (glow_enabled) {
// If glow is enabled, we apply tonemapping etc. in post, so disable it during rendering
apply_color_adjustments_in_post = true;
@@ -2339,6 +2339,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
if (render_data.environment.is_valid()) {
bool use_bcs = environment_get_adjustments_enabled(render_data.environment);
if (use_bcs) {
+ rb->ensure_internal_buffers();
apply_color_adjustments_in_post = true;
}
@@ -2397,6 +2398,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
float bg_energy_multiplier = environment_get_bg_energy_multiplier(render_data.environment);
bg_energy_multiplier *= environment_get_bg_intensity(render_data.environment);
RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(render_data.environment);
+ RS::EnvironmentAmbientSource ambient_source = environment_get_ambient_source(render_data.environment);
if (render_data.camera_attributes.is_valid()) {
bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(render_data.camera_attributes);
@@ -2437,8 +2439,13 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
}
}
+ bool sky_reflections = reflection_source == RS::ENV_REFLECTION_SOURCE_SKY;
+ sky_reflections |= reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY;
+ bool sky_ambient = ambient_source == RS::ENV_AMBIENT_SOURCE_SKY;
+ sky_ambient |= ambient_source == RS::ENV_AMBIENT_SOURCE_BG && bg_mode == RS::ENV_BG_SKY;
+
// setup sky if used for ambient, reflections, or background
- if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+ if (draw_sky || draw_sky_fog_only || sky_reflections || sky_ambient) {
RENDER_TIMESTAMP("Setup Sky");
Projection projection = render_data.cam_projection;
if (is_reflection_probe) {
@@ -2452,7 +2459,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
_setup_sky(&render_data, *render_data.lights, projection, render_data.cam_transform, screen_size);
if (environment_get_sky(render_data.environment).is_valid()) {
- if (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY || (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_BG && environment_get_background(render_data.environment) == RS::ENV_BG_SKY)) {
+ if (sky_reflections || sky_ambient) {
_update_sky_radiance(render_data.environment, projection, render_data.cam_transform, sky_energy_multiplier);
}
} else {
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index b6c7a0c5a5..4c70c43244 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -428,6 +428,7 @@ private:
bool pancake_shadows;
};
static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes");
+ static_assert(sizeof(UBO) < 16384, "Scene UBO size must be 16384 bytes or smaller");
struct MultiviewUBO {
float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
@@ -435,6 +436,7 @@ private:
float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4];
};
static_assert(sizeof(MultiviewUBO) % 16 == 0, "Multiview UBO size must be a multiple of 16 bytes");
+ static_assert(sizeof(MultiviewUBO) < 16384, "MultiviewUBO size must be 16384 bytes or smaller");
struct TonemapUBO {
float exposure = 1.0;
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 876309d22c..4a15ed827a 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -37,6 +37,7 @@
#include "core/io/file_access.h"
#include "drivers/gles3/rasterizer_gles3.h"
+#include "drivers/gles3/storage/config.h"
static String _mkid(const String &p_id) {
String id = "m_" + p_id.replace("__", "_dus_");
@@ -801,7 +802,9 @@ void ShaderGLES3::initialize(const String &p_general_defines, int p_base_texture
print_verbose("Shader '" + name + "' SHA256: " + base_sha256);
}
- glGetInteger64v(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units);
+ GLES3::Config *config = GLES3::Config::get_singleton();
+ ERR_FAIL_NULL(config);
+ max_image_units = config->max_texture_image_units;
}
void ShaderGLES3::set_shader_cache_dir(const String &p_dir) {
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index 8968e76c12..9ee939e343 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -148,7 +148,7 @@ private:
static bool shader_cache_save_debug;
bool shader_cache_dir_valid = false;
- int64_t max_image_units = 0;
+ GLint max_image_units = 0;
enum StageType {
STAGE_TYPE_VERTEX,
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 2b372cb88d..be7a6aba57 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1523,6 +1523,9 @@ void main() {
#CODE : FRAGMENT
}
+ // Keep albedo values in positive number range as negative values "wraparound" into positive numbers resulting in wrong colors
+ albedo = max(albedo, vec3(0.0));
+
#ifdef LIGHT_VERTEX_USED
vertex = light_vertex;
#ifdef USE_MULTIVIEW
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 6b5e227782..1a14902c7c 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -45,9 +45,9 @@ Config::Config() {
singleton = this;
{
- int64_t max_extensions = 0;
- glGetInteger64v(GL_NUM_EXTENSIONS, &max_extensions);
- for (int64_t i = 0; i < max_extensions; i++) {
+ GLint max_extensions = 0;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &max_extensions);
+ for (int i = 0; i < max_extensions; i++) {
const GLubyte *s = glGetStringi(GL_EXTENSIONS, i);
if (!s) {
break;
@@ -80,11 +80,14 @@ Config::Config() {
rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc");
}
- glGetInteger64v(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
- glGetInteger64v(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units);
- glGetInteger64v(GL_MAX_TEXTURE_SIZE, &max_texture_size);
+ glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units);
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
+ glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
- glGetInteger64v(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
+
+ // sanity clamp buffer size to 16K..1MB
+ max_uniform_buffer_size = CLAMP(max_uniform_buffer_size, 16384, 1048576);
support_anisotropic_filter = extensions.has("GL_EXT_texture_filter_anisotropic");
if (support_anisotropic_filter) {
@@ -169,8 +172,31 @@ Config::Config() {
//Adreno 3xx Compatibility
const String rendering_device_name = String::utf8((const char *)glGetString(GL_RENDERER));
- //TODO: Check the number between 300 and 399(?)
- adreno_3xx_compatibility = (rendering_device_name.left(13) == "Adreno (TM) 3");
+ if (rendering_device_name.left(13) == "Adreno (TM) 3") {
+ flip_xy_workaround = true;
+ disable_particles_workaround = true;
+
+ // ignore driver version 331+
+ const String gl_version = String::utf8((const char *)glGetString(GL_VERSION));
+ // Adreno 3xx examples (https://opengles.gpuinfo.org/listreports.php):
+ // ===========================================================================
+ // OpenGL ES 3.0 V@84.0 AU@ (CL@)
+ // OpenGL ES 3.0 V@127.0 AU@ (GIT@I96aee987eb)
+ // OpenGL ES 3.0 V@140.0 AU@ (GIT@Ifd751822f5)
+ // OpenGL ES 3.0 V@251.0 AU@08.00.00.312.030 (GIT@Ie4790512f3)
+ // OpenGL ES 3.0 V@269.0 AU@ (GIT@I109c45a694)
+ // OpenGL ES 3.0 V@331.0 (GIT@35e467f, Ice9844a736) (Date:04/15/19)
+ // OpenGL ES 3.0 V@415.0 (GIT@d39f783, I79de86aa2c, 1591296226) (Date:06/04/20)
+ // OpenGL ES 3.0 V@0502.0 (GIT@09fef447e8, I1fe547a144, 1661493934) (Date:08/25/22)
+ String driver_version = gl_version.get_slice("V@", 1).get_slice(" ", 0);
+ if (driver_version.is_valid_float() && driver_version.to_float() >= 331.0) {
+ flip_xy_workaround = false;
+
+ //TODO: also 'GPUParticles'?
+ //https://github.com/godotengine/godot/issues/92662#issuecomment-2161199477
+ //disable_particles_workaround = false;
+ }
+ }
}
Config::~Config() {
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index c3ab65f0bc..0c9f9bc275 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -57,11 +57,12 @@ public:
bool use_nearest_mip_filter = false;
bool use_depth_prepass = true;
- int64_t max_vertex_texture_image_units = 0;
- int64_t max_texture_image_units = 0;
- int64_t max_texture_size = 0;
- int64_t max_viewport_size[2] = { 0, 0 };
- int64_t max_uniform_buffer_size = 0;
+ GLint max_vertex_texture_image_units = 0;
+ GLint max_texture_image_units = 0;
+ GLint max_texture_size = 0;
+ GLint max_viewport_size[2] = { 0, 0 };
+ GLint64 max_uniform_buffer_size = 0;
+
int64_t max_renderable_elements = 0;
int64_t max_renderable_lights = 0;
int64_t max_lights_per_object = 0;
@@ -91,7 +92,9 @@ public:
bool rt_msaa_multiview_supported = false;
bool multiview_supported = false;
- bool adreno_3xx_compatibility = false;
+ // Adreno 3XX compatibility
+ bool disable_particles_workaround = false; // set to 'true' to disable 'GPUParticles'
+ bool flip_xy_workaround = false;
#ifdef ANDROID_ENABLED
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr;
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index 996c205042..bacf607c66 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -1055,6 +1055,7 @@ void MaterialData::update_parameters_internal(const HashMap<StringName, Variant>
ubo_data.resize(p_ubo_size);
if (ubo_data.size()) {
+ ERR_FAIL_COND(p_ubo_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size));
memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
}
}
@@ -1108,10 +1109,10 @@ MaterialStorage::MaterialStorage() {
static_assert(sizeof(GlobalShaderUniforms::Value) == 16);
- global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
- if (global_shader_uniforms.buffer_size > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) {
- global_shader_uniforms.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size);
- WARN_PRINT("Project setting \"rendering/limits/global_shader_variables/buffer_size\" exceeds maximum uniform buffer size of: " + itos(Config::get_singleton()->max_uniform_buffer_size));
+ global_shader_uniforms.buffer_size = MAX(16, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ if (global_shader_uniforms.buffer_size * sizeof(GlobalShaderUniforms::Value) > uint32_t(Config::get_singleton()->max_uniform_buffer_size)) {
+ global_shader_uniforms.buffer_size = uint32_t(Config::get_singleton()->max_uniform_buffer_size) / sizeof(GlobalShaderUniforms::Value);
+ WARN_PRINT("Project setting \"rendering/limits/global_shader_variables/buffer_size\" exceeds maximum uniform buffer size of: " + itos(Config::get_singleton()->max_uniform_buffer_size / sizeof(GlobalShaderUniforms::Value)) + ". Falling back on maximum buffer size.");
}
global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size);
diff --git a/drivers/gles3/storage/particles_storage.cpp b/drivers/gles3/storage/particles_storage.cpp
index fee90599e0..b600681280 100644
--- a/drivers/gles3/storage/particles_storage.cpp
+++ b/drivers/gles3/storage/particles_storage.cpp
@@ -122,7 +122,7 @@ void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_m
}
void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
- ERR_FAIL_COND_MSG(GLES3::Config::get_singleton()->adreno_3xx_compatibility, "Due to driver bugs, GPUParticles are not supported on Adreno 3XX devices. Please use CPUParticles instead.");
+ ERR_FAIL_COND_MSG(GLES3::Config::get_singleton()->disable_particles_workaround, "Due to driver bugs, GPUParticles are not supported on Adreno 3XX devices. Please use CPUParticles instead.");
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
@@ -131,7 +131,7 @@ void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting)
}
bool ParticlesStorage::particles_get_emitting(RID p_particles) {
- if (GLES3::Config::get_singleton()->adreno_3xx_compatibility) {
+ if (GLES3::Config::get_singleton()->disable_particles_workaround) {
return false;
}
diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h
index ca347ed070..086f5f7936 100644
--- a/drivers/gles3/storage/particles_storage.h
+++ b/drivers/gles3/storage/particles_storage.h
@@ -145,6 +145,9 @@ private:
Collider colliders[MAX_COLLIDERS];
};
+ static_assert(sizeof(ParticlesFrameParams) % 16 == 0, "ParticlesFrameParams size must be a multiple of 16 bytes");
+ static_assert(sizeof(ParticlesFrameParams) < 16384, "ParticlesFrameParams must be 16384 bytes or smaller");
+
struct Particles {
RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
bool inactive = true;
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.cpp b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
index cb194933ed..e4f1a01f68 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.cpp
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
@@ -194,7 +194,7 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
ERR_FAIL_COND(view_count == 0);
- bool use_internal_buffer = scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF || glow.glow_enabled;
+ bool use_internal_buffer = scaling_3d_mode != RS::VIEWPORT_SCALING_3D_MODE_OFF || needs_internal_buffers;
uint32_t depth_format_size = 3;
bool use_multiview = view_count > 1;
@@ -203,7 +203,7 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
return;
}
- if (use_internal_buffer) {
+ if (use_internal_buffer && internal3d.color == 0) {
// Setup our internal buffer.
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
@@ -261,14 +261,14 @@ void RenderSceneBuffersGLES3::_check_render_buffers() {
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
_clear_intermediate_buffers();
- WARN_PRINT("Could not create 3D buffers, status: " + texture_storage->get_framebuffer_error(status));
+ WARN_PRINT("Could not create 3D internal buffers, status: " + texture_storage->get_framebuffer_error(status));
}
glBindTexture(texture_target, 0);
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
}
- if (msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED) {
+ if (msaa3d.mode != RS::VIEWPORT_MSAA_DISABLED && msaa3d.color == 0) {
// Setup MSAA.
const GLsizei samples[] = { 1, 2, 4, 8 };
msaa3d.samples = samples[msaa3d.mode];
@@ -558,14 +558,8 @@ void RenderSceneBuffersGLES3::_clear_back_buffers() {
}
}
-void RenderSceneBuffersGLES3::set_glow_enabled(bool p_glow_enabled) {
- if (glow.glow_enabled != p_glow_enabled) {
- glow.glow_enabled = p_glow_enabled;
-
- // Clear our main buffers, this can impact them.
- _clear_msaa3d_buffers();
- _clear_intermediate_buffers();
- }
+void RenderSceneBuffersGLES3::ensure_internal_buffers() {
+ needs_internal_buffers = true;
}
void RenderSceneBuffersGLES3::check_glow_buffers() {
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.h b/drivers/gles3/storage/render_scene_buffers_gles3.h
index 04b9113b91..8273c18b8e 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.h
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.h
@@ -50,6 +50,7 @@ public:
//bool use_taa = false;
//bool use_debanding = false;
uint32_t view_count = 1;
+ bool needs_internal_buffers = false;
RID render_target;
@@ -83,7 +84,6 @@ public:
// Buffers for our glow implementation
struct GLOW {
- bool glow_enabled = false;
GLES3::Glow::GLOWLEVEL levels[4];
} glow;
@@ -111,6 +111,7 @@ public:
void check_backbuffer(bool p_need_color, bool p_need_depth); // Check if we need to initialize our backbuffer.
void check_glow_buffers(); // Check if we need to initialize our glow buffers.
+ void ensure_internal_buffers();
GLuint get_render_fbo();
GLuint get_msaa3d_fbo() {
@@ -145,8 +146,6 @@ public:
GLuint get_backbuffer() const { return backbuffer3d.color; }
GLuint get_backbuffer_depth() const { return backbuffer3d.depth; }
- bool get_glow_enabled() const { return glow.glow_enabled; }
- void set_glow_enabled(bool p_glow_enabled);
const GLES3::Glow::GLOWLEVEL *get_glow_buffers() const { return &glow.levels[0]; }
// Getters
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index 356dc06733..7f0be36466 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -463,10 +463,7 @@ String Utilities::get_video_adapter_api_version() const {
Size2i Utilities::get_maximum_viewport_size() const {
Config *config = Config::get_singleton();
- if (!config) {
- return Size2i();
- }
-
+ ERR_FAIL_NULL_V(config, Size2i());
return Size2i(config->max_viewport_size[0], config->max_viewport_size[1]);
}