diff options
author | clayjohn <claynjohn@gmail.com> | 2024-05-30 12:30:53 -0700 |
---|---|---|
committer | clayjohn <claynjohn@gmail.com> | 2024-06-14 12:56:29 -0700 |
commit | ea4be9afa6207cf0c2f5b66dbba5b826ba5e8d5c (patch) | |
tree | e21ea7c7a1c0f07d606de975b96dbcc4e6ee774e | |
parent | 71699e08c9df78b7203fa4ef9cede28e995d6ace (diff) | |
download | redot-engine-ea4be9afa6207cf0c2f5b66dbba5b826ba5e8d5c.tar.gz |
Add more validation to UBO size and alignment in Compatibility renderer
-rw-r--r-- | doc/classes/ProjectSettings.xml | 2 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.h | 6 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 2 | ||||
-rw-r--r-- | drivers/gles3/storage/material_storage.cpp | 9 | ||||
-rw-r--r-- | drivers/gles3/storage/particles_storage.h | 3 | ||||
-rw-r--r-- | servers/rendering_server.cpp | 2 |
6 files changed, 19 insertions, 5 deletions
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index c8a11427b9..84542b755c 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -2634,6 +2634,8 @@ [b]Note:[/b] This setting is only effective when using the Forward+ rendering method, not Mobile and Compatibility. </member> <member name="rendering/limits/global_shader_variables/buffer_size" type="int" setter="" getter="" default="65536"> + The maximum number of uniforms that can be used by the global shader uniform buffer. Each item takes up one slot. In other words, a single uniform float and a uniform vec4 will take the same amount of space in the buffer. + [b]Note:[/b] When using the Compatibility backend, most mobile devices (and all web exports) will be limited to a maximum size of 1024 due to hardware constraints. </member> <member name="rendering/limits/opengl/max_lights_per_object" type="int" setter="" getter="" default="8"> Max number of omnilights and spotlights renderable per object. At the default value of 8, this means that each surface can be affected by up to 8 omnilights and 8 spotlights. This is further limited by hardware support and [member rendering/limits/opengl/max_renderable_lights]. Setting this low will slightly reduce memory usage, may decrease shader compile times, and may result in faster rendering on low-end, mobile, or web devices. 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_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/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.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/servers/rendering_server.cpp b/servers/rendering_server.cpp index 7637d4e7da..dd3491f62c 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -3610,7 +3610,7 @@ void RenderingServer::init() { GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/environment/subsurface_scattering/subsurface_scattering_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"), 0.05); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001"), 0.01); - GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/limits/global_shader_variables/buffer_size", PROPERTY_HINT_RANGE, "1,1048576,1"), 65536); + GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/limits/global_shader_variables/buffer_size", PROPERTY_HINT_RANGE, "16,1048576,1"), 65536); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/lightmapping/probe_capture/update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001"), 15); GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/lightmapping/primitive_meshes/texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.2); |