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

Fix potential integer underflow in rounded up divisions #80390

Merged
merged 1 commit into from
Jan 2, 2024
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
16 changes: 16 additions & 0 deletions core/math/math_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,22 @@ class Math {
#endif
}

// These methods assume (p_num + p_den) doesn't overflow.
static _ALWAYS_INLINE_ int32_t division_round_up(int32_t p_num, int32_t p_den) {
int32_t offset = (p_num < 0 && p_den < 0) ? 1 : -1;
return (p_num + p_den + offset) / p_den;
}
static _ALWAYS_INLINE_ uint32_t division_round_up(uint32_t p_num, uint32_t p_den) {
return (p_num + p_den - 1) / p_den;
}
static _ALWAYS_INLINE_ int64_t division_round_up(int64_t p_num, int64_t p_den) {
int32_t offset = (p_num < 0 && p_den < 0) ? 1 : -1;
return (p_num + p_den + offset) / p_den;
}
static _ALWAYS_INLINE_ uint64_t division_round_up(uint64_t p_num, uint64_t p_den) {
return (p_num + p_den - 1) / p_den;
}

static _ALWAYS_INLINE_ bool is_finite(double p_val) { return isfinite(p_val); }
static _ALWAYS_INLINE_ bool is_finite(float p_val) { return isfinite(p_val); }

Expand Down
12 changes: 6 additions & 6 deletions drivers/gles3/storage/mesh_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
}
}
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE);
multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
multimesh->data_cache_dirty_regions[i] = false;
Expand All @@ -1549,7 +1549,7 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE;
#ifdef DEBUG_ENABLED
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE);
ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug
#endif
if (!multimesh->data_cache_dirty_regions[region_index]) {
Expand All @@ -1570,7 +1570,7 @@ void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool

void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) {
if (p_data) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE);

for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
if (!multimesh->data_cache_dirty_regions[i]) {
Expand Down Expand Up @@ -1917,7 +1917,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
multimesh->data_cache = multimesh->data_cache;
{
//clear dirty since nothing will be dirty anymore
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE);
for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
multimesh->data_cache_dirty_regions[i] = false;
}
Expand Down Expand Up @@ -2044,8 +2044,8 @@ void MeshStorage::_update_dirty_multimeshes() {
uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;

if (multimesh->data_cache_used_dirty_regions) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, (int)MULTIMESH_DIRTY_REGION_SIZE);
uint32_t visible_region_count = visible_instances == 0 ? 0 : Math::division_round_up(visible_instances, (uint32_t)MULTIMESH_DIRTY_REGION_SIZE);

GLint region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);

Expand Down
4 changes: 2 additions & 2 deletions modules/gdscript/gdscript_utility_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ struct GDScriptUtilityFunctionsDefinitions {
// Calculate how many.
int count = 0;
if (incr > 0) {
count = ((to - from - 1) / incr) + 1;
count = Math::division_round_up(to - from, incr);
} else {
count = ((from - to - 1) / -incr) + 1;
count = Math::division_round_up(from - to, -incr);
}

Error err = arr.resize(count);
Expand Down
22 changes: 11 additions & 11 deletions modules/lightmapper_rd/lightmapper_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShade
rd->compute_list_bind_uniform_set(compute_list, dilate_uniform_set, 1);
push_constant.region_ofs[0] = 0;
push_constant.region_ofs[1] = 0;
Vector3i group_size((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); //restore group size
Vector3i group_size(Math::division_round_up(atlas_size.x, 8), Math::division_round_up(atlas_size.y, 8), 1); //restore group size

for (int i = 0; i < atlas_slices; i++) {
push_constant.atlas_slice = i;
Expand Down Expand Up @@ -939,8 +939,8 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh
// We use a region with 1/4 the amount of pixels if we're denoising SH lightmaps, as
// all four of them are denoised in the shader in one dispatch.
const int max_region_size = p_bake_sh ? 512 : 1024;
int x_regions = (p_atlas_size.width - 1) / max_region_size + 1;
int y_regions = (p_atlas_size.height - 1) / max_region_size + 1;
int x_regions = Math::division_round_up(p_atlas_size.width, max_region_size);
int y_regions = Math::division_round_up(p_atlas_size.height, max_region_size);
for (int s = 0; s < p_atlas_slices; s++) {
p_push_constant.atlas_slice = s;

Expand All @@ -958,7 +958,7 @@ LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDSh
p_rd->compute_list_bind_uniform_set(compute_list, p_compute_base_uniform_set, 0);
p_rd->compute_list_bind_uniform_set(compute_list, denoise_uniform_set, 1);
p_rd->compute_list_set_push_constant(compute_list, &p_push_constant, sizeof(PushConstant));
p_rd->compute_list_dispatch(compute_list, (w - 1) / 8 + 1, (h - 1) / 8 + 1, 1);
p_rd->compute_list_dispatch(compute_list, Math::division_round_up(w, 8), Math::division_round_up(h, 8), 1);
p_rd->compute_list_end();

p_rd->submit();
Expand Down Expand Up @@ -1399,7 +1399,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
rd->free(compute_shader_secondary); \
rd->free(compute_shader_light_probes);

Vector3i group_size((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1);
Vector3i group_size(Math::division_round_up(atlas_size.x, 8), Math::division_round_up(atlas_size.y, 8), 1);
rd->submit();
rd->sync();

Expand Down Expand Up @@ -1592,10 +1592,10 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
int max_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/lightmapping/bake_performance/region_size")));
int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_pass");

int x_regions = (atlas_size.width - 1) / max_region_size + 1;
int y_regions = (atlas_size.height - 1) / max_region_size + 1;
int x_regions = Math::division_round_up(atlas_size.width, max_region_size);
int y_regions = Math::division_round_up(atlas_size.height, max_region_size);

int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1;
int ray_iterations = Math::division_round_up((int32_t)push_constant.ray_count, max_rays);

rd->submit();
rd->sync();
Expand All @@ -1614,7 +1614,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
push_constant.region_ofs[0] = x;
push_constant.region_ofs[1] = y;

group_size = Vector3i((w - 1) / 8 + 1, (h - 1) / 8 + 1, 1);
group_size = Vector3i(Math::division_round_up(w, 8), Math::division_round_up(h, 8), 1);

for (int k = 0; k < ray_iterations; k++) {
RD::ComputeListID compute_list = rd->compute_list_begin();
Expand Down Expand Up @@ -1700,7 +1700,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
push_constant.probe_count = probe_positions.size();

int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_probe_pass");
int ray_iterations = (push_constant.ray_count - 1) / max_rays + 1;
int ray_iterations = Math::division_round_up((int32_t)push_constant.ray_count, max_rays);

for (int i = 0; i < ray_iterations; i++) {
RD::ComputeListID compute_list = rd->compute_list_begin();
Expand All @@ -1711,7 +1711,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
push_constant.ray_from = i * max_rays;
push_constant.ray_to = MIN((i + 1) * max_rays, int32_t(push_constant.ray_count));
rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
rd->compute_list_dispatch(compute_list, (probe_positions.size() - 1) / 64 + 1, 1, 1);
rd->compute_list_dispatch(compute_list, Math::division_round_up(probe_positions.size(), 64), 1, 1);

rd->compute_list_end(); //done
rd->submit();
Expand Down
2 changes: 1 addition & 1 deletion scene/resources/bit_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void BitMap::create(const Size2i &p_size) {

ERR_FAIL_COND(static_cast<int64_t>(p_size.width) * static_cast<int64_t>(p_size.height) > INT32_MAX);

Error err = bitmask.resize((((p_size.width * p_size.height) - 1) / 8) + 1);
Error err = bitmask.resize(Math::division_round_up(p_size.width * p_size.height, 8));
ERR_FAIL_COND(err != OK);

width = p_size.width;
Expand Down
7 changes: 4 additions & 3 deletions servers/rendering/renderer_rd/cluster_builder_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID

screen_size = p_screen_size;

cluster_screen_size.width = (p_screen_size.width - 1) / cluster_size + 1;
cluster_screen_size.height = (p_screen_size.height - 1) / cluster_size + 1;
cluster_screen_size.width = Math::division_round_up((uint32_t)p_screen_size.width, cluster_size);
cluster_screen_size.height = Math::division_round_up((uint32_t)p_screen_size.height, cluster_size);

max_elements_by_type = p_max_elements;
if (max_elements_by_type % 32) { // Needs to be aligned to 32.
Expand Down Expand Up @@ -503,7 +503,8 @@ void ClusterBuilderRD::bake_cluster() {
push_constant.max_render_element_count_div_32 = render_element_max / 32;
push_constant.cluster_screen_size[0] = cluster_screen_size.x;
push_constant.cluster_screen_size[1] = cluster_screen_size.y;
push_constant.render_element_count_div_32 = render_element_count > 0 ? (render_element_count - 1) / 32 + 1 : 0;

push_constant.render_element_count_div_32 = Math::division_round_up(render_element_count, 32U);
push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32;
push_constant.pad1 = 0;
push_constant.pad2 = 0;
Expand Down
8 changes: 4 additions & 4 deletions servers/rendering/renderer_rd/effects/copy_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1050,8 +1050,8 @@ void CopyEffects::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, c
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_cubemap), 1);

int x_groups = (p_size.x - 1) / 8 + 1;
int y_groups = (p_size.y - 1) / 8 + 1;
int x_groups = Math::division_round_up(p_size.x, 8);
int y_groups = Math::division_round_up(p_size.y, 8);

RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));

Expand Down Expand Up @@ -1204,8 +1204,8 @@ void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture,

RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));

int x_groups = (p_size - 1) / 8 + 1;
int y_groups = (p_size - 1) / 8 + 1;
int x_groups = Math::division_round_up(p_size, 8);
int y_groups = x_groups;

RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1);

Expand Down
4 changes: 2 additions & 2 deletions servers/rendering/renderer_rd/environment/fog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1069,8 +1069,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
uint32_t cluster_size = p_settings.cluster_builder->get_cluster_size();
params.cluster_shift = get_shift_from_power_of_2(cluster_size);

uint32_t cluster_screen_width = (p_settings.rb_size.x - 1) / cluster_size + 1;
uint32_t cluster_screen_height = (p_settings.rb_size.y - 1) / cluster_size + 1;
uint32_t cluster_screen_width = Math::division_round_up((uint32_t)p_settings.rb_size.x, cluster_size);
uint32_t cluster_screen_height = Math::division_round_up((uint32_t)p_settings.rb_size.y, cluster_size);
params.max_cluster_element_count_div_32 = p_settings.max_cluster_elements / 32;
params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
params.cluster_width = cluster_screen_width;
Expand Down
4 changes: 2 additions & 2 deletions servers/rendering/renderer_rd/environment/gi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3143,7 +3143,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[0].uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1);
RD::get_singleton()->compute_list_dispatch(compute_list, Math::division_round_up(rect.size.x, 8), Math::division_round_up(rect.size.y, 8), 1);
//print_line("rect: " + itos(i) + ": " + rect);

for (int k = 1; k < dynamic_maps.size(); k++) {
Expand Down Expand Up @@ -3205,7 +3205,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
}
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[k].uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant));
RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1);
RD::get_singleton()->compute_list_dispatch(compute_list, Math::division_round_up(rect.size.x, 8), Math::division_round_up(rect.size.y, 8), 1);
}

RD::get_singleton()->compute_list_end();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,8 +626,8 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.cluster_shift = get_shift_from_power_of_2(p_render_data->cluster_size);
scene_state.ubo.max_cluster_element_count_div_32 = p_render_data->cluster_max_elements / 32;
{
uint32_t cluster_screen_width = (p_screen_size.width - 1) / p_render_data->cluster_size + 1;
uint32_t cluster_screen_height = (p_screen_size.height - 1) / p_render_data->cluster_size + 1;
uint32_t cluster_screen_width = Math::division_round_up((uint32_t)p_screen_size.width, p_render_data->cluster_size);
uint32_t cluster_screen_height = Math::division_round_up((uint32_t)p_screen_size.height, p_render_data->cluster_size);
scene_state.ubo.cluster_type_size = cluster_screen_width * cluster_screen_height * (scene_state.ubo.max_cluster_element_count_div_32 + 32);
scene_state.ubo.cluster_width = cluster_screen_width;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@ void main() {

if (local == ivec3(0) && store_position_count > 0) {
store_from_index = atomicAdd(dispatch_data.total_count, store_position_count);
uint group_count = (store_from_index + store_position_count - 1) / 64 + 1;
uint group_count = Math::division_round_up(store_from_index + store_position_count, 64);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not have been merged, the shader does not even compile.
Was this PR even tested?

Copy link
Member

@akien-mga akien-mga Jan 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake, I added this yesterday and didn't notice it was touching a .glsl file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by 7abaac6.

atomicMax(dispatch_data.x, group_count);
}

Expand Down
12 changes: 6 additions & 6 deletions servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1553,7 +1553,7 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
memset(w, 0, buffer_size * sizeof(float));
}
}
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE);
multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
memset(multimesh->data_cache_dirty_regions, 0, data_cache_dirty_region_count * sizeof(bool));
multimesh->data_cache_dirty_region_count = 0;
Expand Down Expand Up @@ -1581,7 +1581,7 @@ void MeshStorage::_multimesh_update_motion_vectors_data_cache(MultiMesh *multime
uint32_t current_ofs = multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float);
uint32_t previous_ofs = multimesh->motion_vectors_previous_offset * multimesh->stride_cache * sizeof(float);
uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t visible_region_count = visible_instances == 0 ? 0 : Math::division_round_up(visible_instances, (uint32_t)MULTIMESH_DIRTY_REGION_SIZE);
uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
for (uint32_t i = 0; i < visible_region_count; i++) {
Expand All @@ -1601,7 +1601,7 @@ bool MeshStorage::_multimesh_uses_motion_vectors(MultiMesh *multimesh) {
void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE;
#ifdef DEBUG_ENABLED
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE);
ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug
#endif
if (!multimesh->data_cache_dirty_regions[region_index]) {
Expand All @@ -1622,7 +1622,7 @@ void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool

void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) {
if (p_data) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE);

for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
if (!multimesh->data_cache_dirty_regions[i]) {
Expand Down Expand Up @@ -2021,8 +2021,8 @@ void MeshStorage::_update_dirty_multimeshes() {

uint32_t total_dirty_regions = multimesh->data_cache_dirty_region_count + multimesh->previous_data_cache_dirty_region_count;
if (total_dirty_regions != 0) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t data_cache_dirty_region_count = Math::division_round_up(multimesh->instances, (int)MULTIMESH_DIRTY_REGION_SIZE);
uint32_t visible_region_count = visible_instances == 0 ? 0 : Math::division_round_up(visible_instances, (uint32_t)MULTIMESH_DIRTY_REGION_SIZE);

uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
if (total_dirty_regions > 32 || total_dirty_regions > visible_region_count / 2) {
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/rendering_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5009,7 +5009,7 @@ void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32

#endif

compute_list_dispatch(p_list, (p_x_threads - 1) / cl->state.local_group_size[0] + 1, (p_y_threads - 1) / cl->state.local_group_size[1] + 1, (p_z_threads - 1) / cl->state.local_group_size[2] + 1);
compute_list_dispatch(p_list, Math::division_round_up(p_x_threads, cl->state.local_group_size[0]), Math::division_round_up(p_y_threads, cl->state.local_group_size[1]), Math::division_round_up(p_z_threads, cl->state.local_group_size[2]));
}

void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) {
Expand Down
Loading
Loading