Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Fix glGet overflows by using 64 bit versions #83031

Merged
merged 1 commit into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion drivers/gles2/rasterizer_storage_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ void RasterizerStorageGLES2::GLWrapper::reset() {
texture_unit_table.blank();
}

int32_t RasterizerStorageGLES2::safe_gl_get_integer(unsigned int p_gl_param_name, int32_t p_max_accepted) {
// There is no glGetInteger64v in the base GLES2 spec as far as I can see.
// So we will just have a capped 32 bit version for GLES2.
int32_t temp;
glGetIntegerv(p_gl_param_name, &temp);
temp = MIN(temp, p_max_accepted);
return temp;
}

void RasterizerStorageGLES2::bind_quad_array() const {
glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, nullptr);
Expand Down Expand Up @@ -6316,7 +6325,7 @@ void RasterizerStorageGLES2::initialize() {
config.depth_type = GL_UNSIGNED_INT;

// Initialize GLWrapper early on, as required for any calls to glActiveTexture.
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
config.max_texture_image_units = safe_gl_get_integer(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, Config::max_desired_texture_image_units);
gl_wrapper.initialize(config.max_texture_image_units);

#ifdef GLES_OVER_GL
Expand Down
3 changes: 3 additions & 0 deletions drivers/gles2/rasterizer_storage_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class RasterizerStorageGLES2 : public RasterizerStorage {

int max_vertex_texture_image_units;
int max_texture_image_units;
static const int32_t max_desired_texture_image_units = 64;
int max_texture_size;
int max_cubemap_texture_size;
int max_viewport_dimensions[2];
Expand Down Expand Up @@ -1390,6 +1391,8 @@ class RasterizerStorageGLES2 : public RasterizerStorage {
virtual String get_video_adapter_name() const;
virtual String get_video_adapter_vendor() const;

static int32_t safe_gl_get_integer(unsigned int p_gl_param_name, int32_t p_max_accepted = INT32_MAX);

// NOTE : THESE SIZES ARE IN BYTES. BUFFER SIZES MAY NOT BE SPECIFIED IN BYTES SO REMEMBER TO CONVERT THEM WHEN CALLING.
void buffer_orphan_and_upload(unsigned int p_buffer_size_bytes, unsigned int p_offset_bytes, unsigned int p_data_size_bytes, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER, GLenum p_usage = GL_DYNAMIC_DRAW, bool p_optional_orphan = false) const;
bool safe_buffer_sub_data(unsigned int p_total_buffer_size, GLenum p_target, unsigned int p_offset, unsigned int p_data_size, const void *p_data, unsigned int &r_offset_after) const;
Expand Down
3 changes: 2 additions & 1 deletion drivers/gles2/shader_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,8 @@ void ShaderGLES2::setup(
}
}

glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_image_units);
// The upper limit must match the version used in storage.
max_image_units = RasterizerStorageGLES2::safe_gl_get_integer(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, RasterizerStorageGLES2::Config::max_desired_texture_image_units);
}

void ShaderGLES2::finish() {
Expand Down
18 changes: 16 additions & 2 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5152,8 +5152,22 @@ void RasterizerSceneGLES3::initialize() {
{
//spot and omni ubos

int max_ubo_size;
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_ubo_size);
// SPECIAL CASE for GL_MAX_UNIFORM_BLOCK_SIZE.
// Under ANGLE, in some situations this will return INT32_MAX + 1
// (or very high values).
// This seems to be because ANGLE supports system memory backing,
// but the true hardware GPU max may be lower.
// Afaik we have no way of querying this hardware supported value.
// We also ideally want to take advantage of GPUs that *do* support large uniform
// blocks in hardware (although this is probably not taken advantage of in Godot 3.x currently).

// This logic is thus a compromise.
int max_ubo_size = RasterizerStorageGLES3::safe_gl_get_integer(GL_MAX_UNIFORM_BLOCK_SIZE);

// Some maximum we are likely to currently need, currently 1 meg.
// Not really necessary but provides a small guard against excessive sizes.
max_ubo_size = MIN(max_ubo_size, 1024 * 1024);

const int ubo_light_size = 160;
state.ubo_light_size = ubo_light_size;
state.max_ubo_lights = MIN(render_list.max_lights, max_ubo_size / ubo_light_size);
Expand Down
20 changes: 15 additions & 5 deletions drivers/gles3/rasterizer_storage_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ void RasterizerStorageGLES3::GLWrapper::reset() {
texture_unit_table.blank();
}

int32_t RasterizerStorageGLES3::safe_gl_get_integer(unsigned int p_gl_param_name, int32_t p_max_accepted) {
lawnjelly marked this conversation as resolved.
Show resolved Hide resolved
int64_t temp;
glGetInteger64v(p_gl_param_name, &temp);
temp = MIN(temp, (int64_t)p_max_accepted);
return temp;
}

Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &r_srgb, bool p_force_decompress) const {
r_compressed = false;
r_gl_format = 0;
Expand Down Expand Up @@ -8143,8 +8150,7 @@ void RasterizerStorageGLES3::initialize() {
///

{
int max_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &max_extensions);
int max_extensions = safe_gl_get_integer(GL_NUM_EXTENSIONS);
for (int i = 0; i < max_extensions; i++) {
const GLubyte *s = glGetStringi(GL_EXTENSIONS, i);
if (!s) {
Expand All @@ -8157,8 +8163,12 @@ void RasterizerStorageGLES3::initialize() {
config.shrink_textures_x2 = false;
config.use_fast_texture_filter = int(ProjectSettings::get_singleton()->get("rendering/quality/filters/use_nearest_mipmap_filter"));

// Cap max_texture_image_units as we don't need large numbers of units,
// just in case an implementation provides a large number, as we want to keep
// the table in gl_wrapper small.
config.max_texture_image_units = safe_gl_get_integer(GL_MAX_TEXTURE_IMAGE_UNITS, Config::max_desired_texture_image_units);

// Initialize GLWrapper early on, as required for any calls to glActiveTexture.
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
gl_wrapper.initialize(config.max_texture_image_units);

config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
Expand Down Expand Up @@ -8392,8 +8402,8 @@ void RasterizerStorageGLES3::initialize() {
glBindTexture(GL_TEXTURE_2D, 0);
}

glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &config.max_cubemap_texture_size);
config.max_texture_size = safe_gl_get_integer(GL_MAX_TEXTURE_SIZE);
config.max_cubemap_texture_size = safe_gl_get_integer(GL_MAX_CUBE_MAP_TEXTURE_SIZE);

config.use_rgba_2d_shadows = !config.framebuffer_float_supported;

Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/rasterizer_storage_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class RasterizerStorageGLES3 : public RasterizerStorage {
float anisotropic_level;

int max_texture_image_units;
static const int32_t max_desired_texture_image_units = 64;
int max_texture_size;
int max_cubemap_texture_size;

Expand Down Expand Up @@ -1530,6 +1531,8 @@ class RasterizerStorageGLES3 : public RasterizerStorage {
void initialize();
void finalize();

static int32_t safe_gl_get_integer(unsigned int p_gl_param_name, int32_t p_max_accepted = INT32_MAX);

virtual bool has_os_feature(const String &p_feature) const;

virtual void update_dirty_resources();
Expand Down
4 changes: 3 additions & 1 deletion drivers/gles3/shader_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "core/os/os.h"
#include "core/print_string.h"
#include "core/threaded_callable_queue.h"
#include "drivers/gles3/rasterizer_storage_gles3.h"
#include "drivers/gles3/shader_cache_gles3.h"
#include "servers/visual_server.h"

Expand Down Expand Up @@ -1216,7 +1217,8 @@ void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_co
}
}

glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_image_units);
// The upper limit must match the version used in storage.
max_image_units = RasterizerStorageGLES3::safe_gl_get_integer(GL_MAX_TEXTURE_IMAGE_UNITS, RasterizerStorageGLES3::Config::max_desired_texture_image_units);
}

void ShaderGLES3::init_async_compilation() {
Expand Down
Loading