diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 934c75b5d3a..18691cd7101 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -711,6 +711,22 @@ class Math { } return p_target; } + + // Divides num / dem and the result is rounded up: + // Examples: + // 0 / 64 = 0 + // 63 / 64 = 1 + // 64 / 64 = 1 + // 65 / 64 = 2 + // + // Will not work correctly if numerator + denominator - 1u results in an overflow. + static _ALWAYS_INLINE_ uint32_t divide_round_up(uint32_t p_numerator, uint32_t p_denominator) { + return (p_numerator + p_denominator - 1u) / p_denominator; + } + + static _ALWAYS_INLINE_ uint64_t divide_round_up(uint64_t p_numerator, uint64_t p_denominator) { + return (p_numerator + p_denominator - 1u) / p_denominator; + } }; #endif // MATH_FUNCS_H diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index a96a491517f..6441a7e9d0d 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -1347,7 +1347,7 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } -#define MULTIMESH_DIRTY_REGION_SIZE 512 +#define MULTIMESH_DIRTY_REGION_SIZE 512u void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { if (multimesh->data_cache.size() > 0 || multimesh->instances == 0) { @@ -1371,7 +1371,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::divide_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; @@ -1382,7 +1382,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::divide_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]) { @@ -1403,7 +1403,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::divide_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]) { @@ -1750,7 +1750,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector &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::divide_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; } @@ -1877,8 +1877,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::divide_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); + uint32_t visible_region_count = Math::divide_round_up(visible_instances, uint32_t(MULTIMESH_DIRTY_REGION_SIZE)); GLint region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 803a109863b..9c2205f8075 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -8208,7 +8208,9 @@ void RenderingDeviceVulkan::compute_list_dispatch_threads(ComputeListID p_list, #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::divide_round_up(p_x_threads, cl->state.local_group_size[0]), + Math::divide_round_up(p_y_threads, cl->state.local_group_size[1]), + Math::divide_round_up(p_z_threads, cl->state.local_group_size[2])); } void RenderingDeviceVulkan::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) { diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 748e8ae50ca..51b76d589c4 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -641,7 +641,7 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Refcompute_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::divide_round_up(atlas_size.x, 8u), Math::divide_round_up(atlas_size.y, 8u), 1); //restore group size for (int i = 0; i < atlas_slices; i++) { push_constant.atlas_slice = i; @@ -1036,7 +1036,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d push_constant.environment_xform[11] = 0; } - Vector3i group_size((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); + Vector3i group_size(Math::divide_round_up(atlas_size.x, 8u), Math::divide_round_up(atlas_size.y, 8u), 1); rd->submit(); rd->sync(); @@ -1246,9 +1246,9 @@ 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 ray_iterations = (push_constant.ray_count - 1) / max_rays + 1; + int x_regions = Math::divide_round_up(uint32_t(atlas_size.width), max_region_size); + int y_regions = Math::divide_round_up(uint32_t(atlas_size.height), max_region_size); + int ray_iterations = Math::divide_round_up(push_constant.ray_count, max_rays); rd->submit(); rd->sync(); diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index dd20dc1c66a..ea1ae4999a4 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -39,7 +39,7 @@ void BitMap::create(const Size2i &p_size) { ERR_FAIL_COND(static_cast(p_size.width) * static_cast(p_size.height) > INT32_MAX); - Error err = bitmask.resize((((p_size.width * p_size.height) - 1) / 8) + 1); + Error err = bitmask.resize(Math::divide_round_up(p_size.width * p_size.height, 8u)); ERR_FAIL_COND(err != OK); width = p_size.width; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index f99a5254bb8..f4836668cb7 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -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::divide_round_up(p_screen_size.width, cluster_size); + cluster_screen_size.height = Math::divide_round_up(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. @@ -503,7 +503,7 @@ 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::divide_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; diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index 834653f5c25..76d0a039029 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -1018,8 +1018,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::divide_round_up(p_size.x, 8u); + int y_groups = Math::divide_round_up(p_size.y, 8u); RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant)); diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 8402cc74446..9f7eaaad637 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -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::divide_round_up(p_settings.rb_size.x, cluster_size); + uint32_t cluster_screen_height = Math::divide_round_up(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; diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index d623553273e..6f90ccd651d 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -2966,7 +2966,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vectorcompute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant)); @@ -2987,7 +2987,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vectorcompute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIPushConstant)); @@ -3138,7 +3138,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vectorcompute_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::divide_round_up(rect.size.x, 8u), Math::divide_round_up(rect.size.y, 8u), 1); //print_line("rect: " + itos(i) + ": " + rect); for (int k = 1; k < dynamic_maps.size(); k++) { @@ -3200,7 +3200,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vectorcompute_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::divide_round_up(rect.size.x, 8u), Math::divide_round_up(rect.size.y, 8u), 1); } RD::get_singleton()->compute_list_end(); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 2e64946fd26..5d5c2061022 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -605,8 +605,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::divide_round_up(p_screen_size.width, p_render_data->cluster_size); + uint32_t cluster_screen_height = Math::divide_round_up(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; } diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 439d0702f52..84f24223919 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -1432,7 +1432,7 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } -#define MULTIMESH_DIRTY_REGION_SIZE 512 +#define MULTIMESH_DIRTY_REGION_SIZE 512u void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { if (multimesh->data_cache.size() > 0) { @@ -1459,7 +1459,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::divide_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; @@ -1487,7 +1487,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 = Math::divide_round_up(visible_instances, 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++) { @@ -1503,7 +1503,7 @@ void MeshStorage::_multimesh_update_motion_vectors_data_cache(MultiMesh *multime 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::divide_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]) { @@ -1524,7 +1524,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::divide_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]) { @@ -1923,8 +1923,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::divide_round_up(multimesh->instances, MULTIMESH_DIRTY_REGION_SIZE); + uint32_t visible_region_count = Math::divide_round_up(visible_instances, 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) {