diff options
162 files changed, 2675 insertions, 2061 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 49b974596f7..cc0e5a2491f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -367,7 +367,7 @@ option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF) option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF) option(WITH_CYCLES_CUDA_BUILD_SERIAL "Build cubins one after another (useful on machines with limited RAM)" OFF) mark_as_advanced(WITH_CYCLES_CUDA_BUILD_SERIAL) -set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 CACHE STRING "CUDA architectures to build binaries for") +set(CYCLES_CUDA_BINARIES_ARCH sm_30 sm_35 sm_37 sm_50 sm_52 sm_60 sm_61 sm_70 sm_75 compute_75 CACHE STRING "CUDA architectures to build binaries for") mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH) unset(PLATFORM_DEFAULT) option(WITH_CYCLES_LOGGING "Build Cycles with logging support" ON) diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index 5fce64ce719..e6fc73a75ed 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -53,7 +53,7 @@ set(WITH_USD ON CACHE BOOL "" FORCE) set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE) set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE) set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE) -set(CYCLES_CUDA_BINARIES_ARCH sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61;sm_70;sm_75 CACHE STRING "" FORCE) +set(CYCLES_CUDA_BINARIES_ARCH sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61;sm_70;sm_75;compute_75 CACHE STRING "" FORCE) set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE) # platform dependent options diff --git a/intern/cycles/device/cuda/device_cuda_impl.cpp b/intern/cycles/device/cuda/device_cuda_impl.cpp index 0be2c322dfa..3a2eb8df95b 100644 --- a/intern/cycles/device/cuda/device_cuda_impl.cpp +++ b/intern/cycles/device/cuda/device_cuda_impl.cpp @@ -383,11 +383,24 @@ string CUDADevice::compile_kernel(const DeviceRequestedFeatures &requested_featu } } - const string ptx = path_get(string_printf("lib/%s_compute_%d%d.ptx", name, major, minor)); - VLOG(1) << "Testing for pre-compiled kernel " << ptx << "."; - if (path_exists(ptx)) { - VLOG(1) << "Using precompiled kernel."; - return ptx; + /* The driver can JIT-compile PTX generated for older generations, so find the closest one. */ + int ptx_major = major, ptx_minor = minor; + while (ptx_major >= 3) { + const string ptx = path_get( + string_printf("lib/%s_compute_%d%d.ptx", name, ptx_major, ptx_minor)); + VLOG(1) << "Testing for pre-compiled kernel " << ptx << "."; + if (path_exists(ptx)) { + VLOG(1) << "Using precompiled kernel."; + return ptx; + } + + if (ptx_minor > 0) { + ptx_minor--; + } + else { + ptx_major--; + ptx_minor = 9; + } } } diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 7cc0d32d521..5533eeb006d 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -539,7 +539,7 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES) ${SRC_UTIL_HEADERS} COMMAND ${CUBIN_CC_ENV} "$<TARGET_FILE:cycles_cubin_cc>" - -target 30 + -target 52 -ptx -i ${CMAKE_CURRENT_SOURCE_DIR}/${input} ${cuda_flags} @@ -563,7 +563,7 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES) COMMAND ${CUDA_NVCC_EXECUTABLE} --ptx - -arch=sm_30 + -arch=sm_52 ${cuda_flags} ${input} WORKING_DIRECTORY diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl index acb198a9852..a12e7a9dc17 100644 --- a/intern/cycles/kernel/shaders/node_sky_texture.osl +++ b/intern/cycles/kernel/shaders/node_sky_texture.osl @@ -204,8 +204,8 @@ color sky_radiance_nishita(vector dir, float nishita_data[10], string filename) mul; } } - /* convert to RGB and adjust strength */ - return xyz_to_rgb(xyz[0], xyz[1], xyz[2]) * 120000.0; + /* convert to RGB */ + return xyz_to_rgb(xyz[0], xyz[1], xyz[2]); } shader node_sky_texture( diff --git a/intern/cycles/kernel/svm/svm_sky.h b/intern/cycles/kernel/svm/svm_sky.h index be2c8ccdacf..f824184c1d4 100644 --- a/intern/cycles/kernel/svm/svm_sky.h +++ b/intern/cycles/kernel/svm/svm_sky.h @@ -205,8 +205,8 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals *kg, } } - /* convert to rgb and adjust strength */ - return xyz_to_rgb(kg, xyz) * 120000.0f; + /* convert to RGB */ + return xyz_to_rgb(kg, xyz); } ccl_device void svm_node_tex_sky( diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 1a29663ec5e..d5f65fb54db 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -798,7 +798,7 @@ NODE_DEFINE(SkyTextureNode) SOCKET_BOOLEAN(sun_disc, "Sun Disc", true); SOCKET_FLOAT(sun_size, "Sun Size", 0.009512f); SOCKET_FLOAT(sun_intensity, "Sun Intensity", 1.0f); - SOCKET_FLOAT(sun_elevation, "Sun Elevation", M_PI_2_F); + SOCKET_FLOAT(sun_elevation, "Sun Elevation", 15.0f * M_PI_F / 180.0f); SOCKET_FLOAT(sun_rotation, "Sun Rotation", 0.0f); SOCKET_FLOAT(altitude, "Altitude", 1.0f); SOCKET_FLOAT(air_density, "Air", 1.0f); diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h index 1dbfc6bdd9c..3da1d8f53f0 100644 --- a/intern/mantaflow/extern/manta_fluid_API.h +++ b/intern/mantaflow/extern/manta_fluid_API.h @@ -111,46 +111,16 @@ float *manta_get_phioutstatic_in(struct MANTA *fluid); /* Smoke functions */ void manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *fmd); -void manta_smoke_export(struct MANTA *smoke, - float *dt, - float *dx, - float **dens, - float **react, - float **flame, - float **fuel, - float **heat, - float **vx, - float **vy, - float **vz, - float **r, - float **g, - float **b, - int **flags, - float **shadow); -void manta_smoke_turbulence_export(struct MANTA *smoke, - float **dens, - float **react, - float **flame, - float **fuel, - float **r, - float **g, - float **b, - float **tcu, - float **tcv, - float **tcw, - float **tcu2, - float **tcv2, - float **tcw2); void manta_smoke_get_rgba(struct MANTA *smoke, float *data, int sequential); -void manta_smoke_turbulence_get_rgba(struct MANTA *smoke, float *data, int sequential); +void manta_noise_get_rgba(struct MANTA *smoke, float *data, int sequential); void manta_smoke_get_rgba_fixed_color(struct MANTA *smoke, float color[3], float *data, int sequential); -void manta_smoke_turbulence_get_rgba_fixed_color(struct MANTA *smoke, - float color[3], - float *data, - int sequential); +void manta_noise_get_rgba_fixed_color(struct MANTA *smoke, + float color[3], + float *data, + int sequential); void manta_smoke_ensure_heat(struct MANTA *smoke, struct FluidModifierData *fmd); void manta_smoke_ensure_fire(struct MANTA *smoke, struct FluidModifierData *fmd); void manta_smoke_ensure_colors(struct MANTA *smoke, struct FluidModifierData *fmd); @@ -177,17 +147,23 @@ float *manta_smoke_get_emission_in(struct MANTA *smoke); int manta_smoke_has_heat(struct MANTA *smoke); int manta_smoke_has_fuel(struct MANTA *smoke); int manta_smoke_has_colors(struct MANTA *smoke); -float *manta_smoke_turbulence_get_density(struct MANTA *smoke); -float *manta_smoke_turbulence_get_fuel(struct MANTA *smoke); -float *manta_smoke_turbulence_get_react(struct MANTA *smoke); -float *manta_smoke_turbulence_get_color_r(struct MANTA *smoke); -float *manta_smoke_turbulence_get_color_g(struct MANTA *smoke); -float *manta_smoke_turbulence_get_color_b(struct MANTA *smoke); -float *manta_smoke_turbulence_get_flame(struct MANTA *smoke); -int manta_smoke_turbulence_has_fuel(struct MANTA *smoke); -int manta_smoke_turbulence_has_colors(struct MANTA *smoke); -void manta_smoke_turbulence_get_res(struct MANTA *smoke, int *res); -int manta_smoke_turbulence_get_cells(struct MANTA *smoke); +float *manta_noise_get_density(struct MANTA *smoke); +float *manta_noise_get_fuel(struct MANTA *smoke); +float *manta_noise_get_react(struct MANTA *smoke); +float *manta_noise_get_color_r(struct MANTA *smoke); +float *manta_noise_get_color_g(struct MANTA *smoke); +float *manta_noise_get_color_b(struct MANTA *smoke); +float *manta_noise_get_texture_u(struct MANTA *smoke); +float *manta_noise_get_texture_v(struct MANTA *smoke); +float *manta_noise_get_texture_w(struct MANTA *smoke); +float *manta_noise_get_texture_u2(struct MANTA *smoke); +float *manta_noise_get_texture_v2(struct MANTA *smoke); +float *manta_noise_get_texture_w2(struct MANTA *smoke); +float *manta_noise_get_flame(struct MANTA *smoke); +int manta_noise_has_fuel(struct MANTA *smoke); +int manta_noise_has_colors(struct MANTA *smoke); +void manta_noise_get_res(struct MANTA *smoke, int *res); +int manta_noise_get_cells(struct MANTA *smoke); /* Liquid functions */ void manta_liquid_export_script(struct MANTA *smoke, struct FluidModifierData *fmd); diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp index 1db3da63ecc..60546bc1183 100644 --- a/intern/mantaflow/intern/manta_fluid_API.cpp +++ b/intern/mantaflow/intern/manta_fluid_API.cpp @@ -368,89 +368,6 @@ void manta_smoke_export_script(MANTA *smoke, FluidModifierData *fmd) smoke->exportSmokeScript(fmd); } -void manta_smoke_export(MANTA *smoke, - float *dt, - float *dx, - float **dens, - float **react, - float **flame, - float **fuel, - float **heat, - float **vx, - float **vy, - float **vz, - float **r, - float **g, - float **b, - int **flags, - float **shadow) -{ - if (dens) - *dens = smoke->getDensity(); - if (fuel) - *fuel = smoke->getFuel(); - if (react) - *react = smoke->getReact(); - if (flame) - *flame = smoke->getFlame(); - if (heat) - *heat = smoke->getHeat(); - *vx = smoke->getVelocityX(); - *vy = smoke->getVelocityY(); - *vz = smoke->getVelocityZ(); - if (r) - *r = smoke->getColorR(); - if (g) - *g = smoke->getColorG(); - if (b) - *b = smoke->getColorB(); - *flags = smoke->getFlags(); - if (shadow) - *shadow = smoke->getShadow(); - *dt = 1; // dummy value, not needed for smoke - *dx = 1; // dummy value, not needed for smoke -} - -void manta_smoke_turbulence_export(MANTA *smoke, - float **dens, - float **react, - float **flame, - float **fuel, - float **r, - float **g, - float **b, - float **tcu, - float **tcv, - float **tcw, - float **tcu2, - float **tcv2, - float **tcw2) -{ - if (!smoke && !(smoke->usingNoise())) - return; - - *dens = smoke->getDensityHigh(); - if (fuel) - *fuel = smoke->getFuelHigh(); - if (react) - *react = smoke->getReactHigh(); - if (flame) - *flame = smoke->getFlameHigh(); - if (r) - *r = smoke->getColorRHigh(); - if (g) - *g = smoke->getColorGHigh(); - if (b) - *b = smoke->getColorBHigh(); - *tcu = smoke->getTextureU(); - *tcv = smoke->getTextureV(); - *tcw = smoke->getTextureW(); - - *tcu2 = smoke->getTextureU2(); - *tcv2 = smoke->getTextureV2(); - *tcw2 = smoke->getTextureW2(); -} - static void get_rgba( float *r, float *g, float *b, float *a, int total_cells, float *data, int sequential) { @@ -484,7 +401,7 @@ void manta_smoke_get_rgba(MANTA *smoke, float *data, int sequential) sequential); } -void manta_smoke_turbulence_get_rgba(MANTA *smoke, float *data, int sequential) +void manta_noise_get_rgba(MANTA *smoke, float *data, int sequential) { get_rgba(smoke->getColorRHigh(), smoke->getColorGHigh(), @@ -519,10 +436,7 @@ void manta_smoke_get_rgba_fixed_color(MANTA *smoke, float color[3], float *data, get_rgba_fixed_color(color, smoke->getTotalCells(), data, sequential); } -void manta_smoke_turbulence_get_rgba_fixed_color(MANTA *smoke, - float color[3], - float *data, - int sequential) +void manta_noise_get_rgba_fixed_color(MANTA *smoke, float color[3], float *data, int sequential) { get_rgba_fixed_color(color, smoke->getTotalCellsHigh(), data, sequential); } @@ -647,45 +561,69 @@ int manta_smoke_has_colors(MANTA *smoke) return (smoke->getColorR() && smoke->getColorG() && smoke->getColorB()) ? 1 : 0; } -float *manta_smoke_turbulence_get_density(MANTA *smoke) +float *manta_noise_get_density(MANTA *smoke) { return (smoke && smoke->usingNoise()) ? smoke->getDensityHigh() : nullptr; } -float *manta_smoke_turbulence_get_fuel(MANTA *smoke) +float *manta_noise_get_fuel(MANTA *smoke) { return (smoke && smoke->usingNoise()) ? smoke->getFuelHigh() : nullptr; } -float *manta_smoke_turbulence_get_react(MANTA *smoke) +float *manta_noise_get_react(MANTA *smoke) { return (smoke && smoke->usingNoise()) ? smoke->getReactHigh() : nullptr; } -float *manta_smoke_turbulence_get_color_r(MANTA *smoke) +float *manta_noise_get_color_r(MANTA *smoke) { return (smoke && smoke->usingNoise()) ? smoke->getColorRHigh() : nullptr; } -float *manta_smoke_turbulence_get_color_g(MANTA *smoke) +float *manta_noise_get_color_g(MANTA *smoke) { return (smoke && smoke->usingNoise()) ? smoke->getColorGHigh() : nullptr; } -float *manta_smoke_turbulence_get_color_b(MANTA *smoke) +float *manta_noise_get_color_b(MANTA *smoke) { return (smoke && smoke->usingNoise()) ? smoke->getColorBHigh() : nullptr; } -float *manta_smoke_turbulence_get_flame(MANTA *smoke) +float *manta_noise_get_flame(MANTA *smoke) { return (smoke && smoke->usingNoise()) ? smoke->getFlameHigh() : nullptr; } +float *manta_noise_get_texture_u(MANTA *smoke) +{ + return (smoke && smoke->usingNoise()) ? smoke->getTextureU() : nullptr; +} +float *manta_noise_get_texture_v(MANTA *smoke) +{ + return (smoke && smoke->usingNoise()) ? smoke->getTextureV() : nullptr; +} +float *manta_noise_get_texture_w(MANTA *smoke) +{ + return (smoke && smoke->usingNoise()) ? smoke->getTextureW() : nullptr; +} +float *manta_noise_get_texture_u2(MANTA *smoke) +{ + return (smoke && smoke->usingNoise()) ? smoke->getTextureU2() : nullptr; +} +float *manta_noise_get_texture_v2(MANTA *smoke) +{ + return (smoke && smoke->usingNoise()) ? smoke->getTextureV2() : nullptr; +} +float *manta_noise_get_texture_w2(MANTA *smoke) +{ + return (smoke && smoke->usingNoise()) ? smoke->getTextureW2() : nullptr; +} -int manta_smoke_turbulence_has_fuel(MANTA *smoke) +int manta_noise_has_fuel(MANTA *smoke) { return (smoke->getFuelHigh()) ? 1 : 0; } -int manta_smoke_turbulence_has_colors(MANTA *smoke) +int manta_noise_has_colors(MANTA *smoke) { return (smoke->getColorRHigh() && smoke->getColorGHigh() && smoke->getColorBHigh()) ? 1 : 0; } -void manta_smoke_turbulence_get_res(MANTA *smoke, int *res) +void manta_noise_get_res(MANTA *smoke, int *res) { if (smoke && smoke->usingNoise()) { res[0] = smoke->getResXHigh(); @@ -693,7 +631,7 @@ void manta_smoke_turbulence_get_res(MANTA *smoke, int *res) res[2] = smoke->getResZHigh(); } } -int manta_smoke_turbulence_get_cells(MANTA *smoke) +int manta_noise_get_cells(MANTA *smoke) { int total_cells_high = smoke->getResXHigh() * smoke->getResYHigh() * smoke->getResZHigh(); return (smoke && smoke->usingNoise()) ? total_cells_high : 0; diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h index 612d01b85ef..332aa2342ee 100644 --- a/intern/mantaflow/intern/strings/smoke_script.h +++ b/intern/mantaflow/intern/strings/smoke_script.h @@ -100,6 +100,9 @@ color_r_in_s$ID$ = None\n\ color_g_in_s$ID$ = None\n\ color_b_in_s$ID$ = None\n\ \n\ +# Set some initial values\n\ +shadow_s$ID$.setConst(-1)\n\ +\n\ # Keep track of important objects in dict to load them later on\n\ smoke_data_dict_final_s$ID$ = { 'density' : density_s$ID$, 'shadow' : shadow_s$ID$ }\n\ smoke_data_dict_resume_s$ID$ = { 'densityIn' : densityIn_s$ID$, 'emission' : emission_s$ID$ }\n"; @@ -490,6 +493,9 @@ def step_noise_$ID$():\n\ advectSemiLagrange(flags=flags_s$ID$, vel=vel_s$ID$, grid=uvGrid1_s$ID$, order=2)\n\ updateUvWeight(resetTime=sn$ID$.timestep*10.0 , index=1, numUvs=uvs_s$ID$, uv=uvGrid1_s$ID$, offset=uvs_offset_s$ID$)\n\ \n\ + if not domainClosed_s$ID$ or using_outflow_s$ID$:\n\ + resetOutflow(flags=flags_sn$ID$, real=density_sn$ID$)\n\ + \n\ mantaMsg('Energy')\n\ computeEnergy(flags=flags_s$ID$, vel=vel_s$ID$, energy=energy_s$ID$)\n\ \n\ diff --git a/intern/sky/source/sky_nishita.cpp b/intern/sky/source/sky_nishita.cpp index eae95dc73fe..f36bfcc3d7b 100644 --- a/intern/sky/source/sky_nishita.cpp +++ b/intern/sky/source/sky_nishita.cpp @@ -18,20 +18,21 @@ #include "sky_model.h" /* Constants */ -static const float rayleigh_scale = 8000.0f; // Rayleigh scale height (m) -static const float mie_scale = 1200.0f; // Mie scale height (m) -static const float mie_coeff = 2e-5f; // Mie scattering coefficient -static const float mie_G = 0.76f; // aerosols anisotropy -static const float sqr_G = mie_G * mie_G; // squared aerosols anisotropy -static const float earth_radius = 6360000.0f; // radius of Earth (m) -static const float atmosphere_radius = 6420000.0f; // radius of atmosphere (m) -static const int steps = 32; // segments per primary ray -static const int steps_light = 16; // segments per sun connection ray -static const int num_wavelengths = 21; // number of wavelengths -static const int max_luminous_efficacy = 683; // maximum luminous efficacy -static const float step_lambda = (num_wavelengths - 1) * - 1e-9f; // step between each sampled wavelength -/* irradiance at top of atmosphere */ +static const float rayleigh_scale = 8e3f; // Rayleigh scale height (m) +static const float mie_scale = 1.2e3f; // Mie scale height (m) +static const float mie_coeff = 2e-5f; // Mie scattering coefficient (m^-1) +static const float mie_G = 0.76f; // aerosols anisotropy +static const float sqr_G = mie_G * mie_G; // squared aerosols anisotropy +static const float earth_radius = 6360e3f; // radius of Earth (m) +static const float atmosphere_radius = 6420e3f; // radius of atmosphere (m) +static const int steps = 32; // segments of primary ray +static const int steps_light = 16; // segments of sun connection ray +static const int num_wavelengths = 21; // number of wavelengths +static const int min_wavelength = 380; // lowest sampled wavelength (nm) +static const int max_wavelength = 780; // highest sampled wavelength (nm) +// step between each sampled wavelength (nm) +static const float step_lambda = (max_wavelength - min_wavelength) / (num_wavelengths - 1); +/* Sun irradiance on top of the atmosphere (W*m^-2*nm^-1) */ static const float irradiance[] = { 1.45756829855592995315f, 1.56596305559738380175f, 1.65148449067670455293f, 1.71496242737209314555f, 1.75797983805020541226f, 1.78256407885924539336f, @@ -40,7 +41,7 @@ static const float irradiance[] = { 1.61993437242451854274f, 1.57083597368892080581f, 1.51932335059305478886f, 1.46628494965214395407f, 1.41245852740172450623f, 1.35844961970384092709f, 1.30474913844739281998f, 1.25174963272610817455f, 1.19975998755420620867f}; -/* Rayleigh scattering coefficient */ +/* Rayleigh scattering coefficient (m^-1) */ static const float rayleigh_coeff[] = { 0.00005424820087636473f, 0.00004418549866505454f, 0.00003635151910165377f, 0.00003017929012024763f, 0.00002526320226989157f, 0.00002130859310621843f, @@ -49,7 +50,7 @@ static const float rayleigh_coeff[] = { 0.00000765513700977967f, 0.00000674217203751443f, 0.00000596134125832052f, 0.00000529034598065810f, 0.00000471115687557433f, 0.00000420910481110487f, 0.00000377218381260133f, 0.00000339051255477280f, 0.00000305591531679811f}; -/* Ozone absorption coefficient */ +/* Ozone absorption coefficient (m^-1) */ static const float ozone_coeff[] = { 0.00000000325126849861f, 0.00000000585395365047f, 0.00000001977191155085f, 0.00000007309568762914f, 0.00000020084561514287f, 0.00000040383958096161f, @@ -94,11 +95,10 @@ static float3 spec_to_xyz(float *spectrum) xyz.y += cmf_xyz[i][1] * spectrum[i]; xyz.z += cmf_xyz[i][2] * spectrum[i]; } - return xyz * step_lambda * max_luminous_efficacy; + return xyz * step_lambda; } /* Atmosphere volume models */ - static float density_rayleigh(float height) { return expf(-height / rayleigh_scale); @@ -135,11 +135,13 @@ static bool surface_intersection(float3 pos, float3 dir) { if (dir.z >= 0) return false; - float t = dot(dir, -pos) / len_squared(dir); - float D = pos.x * pos.x - 2.0f * (-pos.x) * dir.x * t + dir.x * t * dir.x * t + pos.y * pos.y - - 2.0f * (-pos.y) * dir.y * t + (dir.y * t) * (dir.y * t) + pos.z * pos.z - - 2.0f * (-pos.z) * dir.z * t + dir.z * t * dir.z * t; - return (D <= sqr(earth_radius)); + float b = -2.0f * dot(dir, -pos); + float c = len_squared(pos) - sqr(earth_radius); + float t = b * b - 4.0f * c; + if (t >= 0.0f) + return true; + else + return false; } static float3 atmosphere_intersection(float3 pos, float3 dir) @@ -152,41 +154,40 @@ static float3 atmosphere_intersection(float3 pos, float3 dir) static float3 ray_optical_depth(float3 ray_origin, float3 ray_dir) { - /* This code computes the optical depth along a ray through the atmosphere. */ + /* this code computes the optical depth along a ray through the atmosphere */ float3 ray_end = atmosphere_intersection(ray_origin, ray_dir); float ray_length = distance(ray_origin, ray_end); - /* To compute the optical depth, we step along the ray in segments and - * accumulate the optical depth along each segment. */ + /* to compute the optical depth, we step along the ray in segments and + * accumulate the optical depth along each segment */ float segment_length = ray_length / steps_light; float3 segment = segment_length * ray_dir; - /* Instead of tracking the transmission spectrum across all wavelengths directly, + /* instead of tracking the transmission spectrum across all wavelengths directly, * we use the fact that the density always has the same spectrum for each type of * scattering, so we split the density into a constant spectrum and a factor and - * only track the factors. */ + * only track the factors */ float3 optical_depth = make_float3(0.0f, 0.0f, 0.0f); - /* The density of each segment is evaluated at its middle. */ + /* the density of each segment is evaluated at its middle */ float3 P = ray_origin + 0.5f * segment; for (int i = 0; i < steps_light; i++) { - /* Compute height above sea level. */ + /* height above sea level */ float height = len(P) - earth_radius; - /* Accumulate optical depth of this segment (density is assumed to be constant along it). */ + /* accumulate optical depth of this segment (density is assumed to be constant along it) */ float3 density = make_float3( density_rayleigh(height), density_mie(height), density_ozone(height)); optical_depth += density; - /* Advance along ray. */ + /* advance along ray */ P += segment; } return optical_depth * segment_length; } -/* Single Scattering implementation */ static void single_scattering(float3 ray_dir, float3 sun_dir, float3 ray_origin, @@ -195,45 +196,45 @@ static void single_scattering(float3 ray_dir, float ozone_density, float *r_spectrum) { - /* This code computes single-inscattering along a ray through the atmosphere. */ + /* this code computes single-inscattering along a ray through the atmosphere */ float3 ray_end = atmosphere_intersection(ray_origin, ray_dir); float ray_length = distance(ray_origin, ray_end); - /* To compute the inscattering, we step along the ray in segments and accumulate - * the inscattering as well as the optical depth along each segment. */ + /* to compute the inscattering, we step along the ray in segments and accumulate + * the inscattering as well as the optical depth along each segment */ float segment_length = ray_length / steps; float3 segment = segment_length * ray_dir; - /* Instead of tracking the transmission spectrum across all wavelengths directly, + /* instead of tracking the transmission spectrum across all wavelengths directly, * we use the fact that the density always has the same spectrum for each type of * scattering, so we split the density into a constant spectrum and a factor and - * only track the factors. */ + * only track the factors */ float3 optical_depth = make_float3(0.0f, 0.0f, 0.0f); - /* Zero out light accumulation. */ + /* zero out light accumulation */ for (int wl = 0; wl < num_wavelengths; wl++) { r_spectrum[wl] = 0.0f; } - /* Compute phase function for scattering and the density scale factor. */ + /* phase function for scattering and the density scale factor */ float mu = dot(ray_dir, sun_dir); float3 phase_function = make_float3(phase_rayleigh(mu), phase_mie(mu), 0.0f); float3 density_scale = make_float3(air_density, dust_density, ozone_density); - /* The density and in-scattering of each segment is evaluated at its middle. */ + /* the density and in-scattering of each segment is evaluated at its middle */ float3 P = ray_origin + 0.5f * segment; for (int i = 0; i < steps; i++) { - /* Compute height above sea level. */ + /* height above sea level */ float height = len(P) - earth_radius; - /* Evaluate and accumulate optical depth along the ray. */ + /* evaluate and accumulate optical depth along the ray */ float3 density = density_scale * make_float3(density_rayleigh(height), density_mie(height), density_ozone(height)); optical_depth += segment_length * density; - /* If the earth isn't in the way, evaluate inscattering from the sun. */ + /* if the Earth isn't in the way, evaluate inscattering from the sun */ if (!surface_intersection(P, sun_dir)) { float3 light_optical_depth = density_scale * ray_optical_depth(P, sun_dir); float3 total_optical_depth = optical_depth + light_optical_depth; @@ -247,7 +248,7 @@ static void single_scattering(float3 ray_dir, float3 scattering_density = density * make_float3(rayleigh_coeff[wl], mie_coeff, 0.0f); - /* The total inscattered radiance from one segment is: + /* the total inscattered radiance from one segment is: * Tr(A<->B) * Tr(B<->C) * sigma_s * phase * L * segment_length * * These terms are: @@ -258,19 +259,18 @@ static void single_scattering(float3 ray_dir, * length of the segment * * The code here is just that, with a bit of additional optimization to not store full - * spectra for the optical depth. + * spectra for the optical depth */ r_spectrum[wl] += attenuation * reduce_add(phase_function * scattering_density) * irradiance[wl] * segment_length; } } - /* Advance along ray. */ + /* advance along ray */ P += segment; } } -/* calculate texture array */ void SKY_nishita_skymodel_precompute_texture(float *pixels, int stride, int start_y, @@ -305,6 +305,7 @@ void SKY_nishita_skymodel_precompute_texture(float *pixels, single_scattering(dir, sun_dir, cam_pos, air_density, dust_density, ozone_density, spectrum); float3 xyz = spec_to_xyz(spectrum); + /* store pixels */ int pos_x = x * stride; pixel_row[pos_x] = xyz.x; pixel_row[pos_x + 1] = xyz.y; @@ -318,7 +319,7 @@ void SKY_nishita_skymodel_precompute_texture(float *pixels, } } -/* Sun disc */ +/*********** Sun ***********/ static void sun_radiation(float3 cam_dir, float altitude, float air_density, @@ -329,9 +330,9 @@ static void sun_radiation(float3 cam_dir, float3 cam_pos = make_float3(0, 0, earth_radius + altitude); float3 optical_depth = ray_optical_depth(cam_pos, cam_dir); - /* Compute final spectrum. */ + /* compute final spectrum */ for (int i = 0; i < num_wavelengths; i++) { - /* Combine spectra and the optical depth into transmittance. */ + /* combine spectra and the optical depth into transmittance */ float transmittance = rayleigh_coeff[i] * optical_depth.x * air_density + 1.11f * mie_coeff * optical_depth.y * dust_density; r_spectrum[i] = irradiance[i] * expf(-transmittance) / solid_angle; diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index f37edd05fd2..257ef420ef9 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -97,9 +97,7 @@ class FILEBROWSER_PT_filter(Panel): params = space.params is_lib_browser = params.use_library_browsing - row = layout.row(align=True) - row.prop(params, "use_filter", text="", toggle=False) - row.label(text="Filter") + layout.prop(params, "use_filter", text="Filter", toggle=False) col = layout.column() col.active = params.use_filter diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index 080e66b59e7..50316f50474 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -271,19 +271,24 @@ class ToolSelectPanelHelper: yield item, i i += 1 - # Special internal function, gives use items that contain keymaps. @staticmethod - def _tools_flatten_with_keymap(tools): + def _tools_flatten_with_dynamic(tools, *, context): + """ + Expands dynamic items, indices aren't aligned with other flatten functions. + The context may be None, use as signal to return all items. + """ for item_parent in tools: if item_parent is None: - continue + yield None for item in item_parent if (type(item_parent) is tuple) else (item_parent,): - # skip None or generator function - if item is None or _item_is_fn(item): - continue - if item.keymap is not None: + if item is None: + yield None + elif _item_is_fn(item): + yield from ToolSelectPanelHelper._tools_flatten_with_dynamic(item(context), context=context) + else: yield item + @classmethod def _tool_get_active(cls, context, space_type, mode, with_icon=False): """ @@ -484,8 +489,12 @@ class ToolSelectPanelHelper: else: context_descr = context_mode.replace("_", " ").title() - for item in cls._tools_flatten_with_keymap(tools): + for item in cls._tools_flatten_with_dynamic(tools, context=None): + if item is None: + continue keymap_data = item.keymap + if keymap_data is None: + continue if callable(keymap_data[0]): cls._km_action_simple(kc_default, kc_default, context_descr, item.label, keymap_data) @@ -498,8 +507,13 @@ class ToolSelectPanelHelper: for context_mode_test, tools in cls.tools_all(): if context_mode_test == context_mode: - for item in cls._tools_flatten_with_keymap(tools): - km_name = item.keymap[0] + for item in cls._tools_flatten(tools): + if item is None: + continue + keymap_data = item.keymap + if keymap_data is None: + continue + km_name = keymap_data[0] # print((km.name, cls.bl_space_type, 'WINDOW', [])) if km_name in visited: diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index b7852eb92e0..ce48b92c419 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -2496,15 +2496,17 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_sculpt.cloth_filter, lambda context: ( (_defs_sculpt.color_filter,) - if bpy.context.preferences.view.show_developer_ui and \ - bpy.context.preferences.experimental.use_sculpt_vertex_colors + if context is None or ( + context.preferences.view.show_developer_ui and + context.preferences.experimental.use_sculpt_vertex_colors) else () ), None, lambda context: ( (_defs_sculpt.mask_by_color,) - if bpy.context.preferences.view.show_developer_ui and \ - bpy.context.preferences.experimental.use_sculpt_vertex_colors + if context is None or ( + context.preferences.view.show_developer_ui and + context.preferences.experimental.use_sculpt_vertex_colors) else () ), None, diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 077b53559aa..007b8c933ce 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -6169,7 +6169,7 @@ class VIEW3D_PT_overlay_motion_tracking(Panel): def draw_header(self, context): view = context.space_data - self.layout.prop(view, "show_reconstruction", text="") + self.layout.prop(view, "show_reconstruction", text=self.bl_label) def draw(self, context): layout = self.layout diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 104582be932..43071c2966d 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -32,6 +32,7 @@ extern "C" { #endif /* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */ +struct AnimationEvalContext; struct FCurve; struct Main; struct Object; @@ -202,7 +203,7 @@ void what_does_obaction(struct Object *ob, struct bPose *pose, struct bAction *act, char groupname[], - float cframe); + const struct AnimationEvalContext *anim_eval_context); /* for proxy */ void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto, diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 4a2ad28f90f..ddfe6b61cfb 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -48,6 +48,23 @@ struct bAction; struct bActionGroup; struct bContext; +/* Container for data required to do FCurve and Driver evaluation. */ +typedef struct AnimationEvalContext { + /* For drivers, so that they have access to the dependency graph and the current view layer. See + * T77086. */ + struct Depsgraph *depsgraph; + + /* FCurves and Drivers can be evaluated at a different time than the current scene time, for + * example when evaluating NLA strips. This means that, even though the current time is stored in + * the dependency graph, we need an explicit evaluation time. */ + float eval_time; +} AnimationEvalContext; + +AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, + float eval_time); +AnimationEvalContext BKE_animsys_eval_context_construct_at( + const AnimationEvalContext *anim_eval_context, float eval_time); + /* ************************************* */ /* KeyingSets API */ @@ -172,11 +189,12 @@ void BKE_fcurves_id_cb(struct ID *id, ID_FCurve_Edit_Callback func, void *user_d typedef struct NlaKeyframingContext NlaKeyframingContext; -struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *cache, - struct PointerRNA *ptr, - struct AnimData *adt, - float ctime, - const bool flush_to_original); +struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( + struct ListBase *cache, + struct PointerRNA *ptr, + struct AnimData *adt, + const struct AnimationEvalContext *anim_eval_context, + const bool flush_to_original); bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, struct PointerRNA *prop_ptr, struct PropertyRNA *prop, @@ -209,7 +227,7 @@ bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float /* Evaluation loop for evaluating animation data */ void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, - float ctime, + const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, const bool flush_to_original); @@ -229,14 +247,14 @@ void BKE_animsys_evaluate_all_animation(struct Main *main, /* Evaluate Action (F-Curve Bag) */ void animsys_evaluate_action(struct PointerRNA *ptr, struct bAction *act, - float ctime, + const struct AnimationEvalContext *anim_eval_context, const bool flush_to_original); /* Evaluate Action Group */ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, struct bActionGroup *agrp, - float ctime); + const struct AnimationEvalContext *anim_eval_context); /* ************************************* */ diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index db2fe651c91..25bc2006ee3 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -153,7 +153,8 @@ bool BKE_collection_move(struct Main *bmain, bool relative_after, struct Collection *collection); -bool BKE_collection_find_cycle(struct Collection *new_ancestor, struct Collection *collection); +bool BKE_collection_cycle_find(struct Collection *new_ancestor, struct Collection *collection); +bool BKE_collection_cycles_fix(struct Main *bmain, struct Collection *collection); bool BKE_collection_has_collection(struct Collection *parent, struct Collection *collection); diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index ddd0cc286ab..b846e2e5b7b 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -36,6 +36,7 @@ struct FCurve; struct FModifier; struct AnimData; +struct AnimationEvalContext; struct BezTriple; struct LibraryForeachIDData; struct PathResolvedRNA; @@ -281,10 +282,12 @@ float evaluate_fcurve_only_curve(struct FCurve *fcu, float evaltime); float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, struct ChannelDriver *driver_orig, - float evaltime); + const struct AnimationEvalContext *anim_eval_context); bool BKE_fcurve_is_empty(struct FCurve *fcu); /* evaluate fcurve and store value */ -float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime); +float calculate_fcurve(struct PathResolvedRNA *anim_rna, + struct FCurve *fcu, + const struct AnimationEvalContext *anim_eval_context); /* ************* F-Curve Samples API ******************** */ diff --git a/source/blender/blenkernel/BKE_fcurve_driver.h b/source/blender/blenkernel/BKE_fcurve_driver.h index 563ed408ed7..6803485f843 100644 --- a/source/blender/blenkernel/BKE_fcurve_driver.h +++ b/source/blender/blenkernel/BKE_fcurve_driver.h @@ -30,6 +30,7 @@ extern "C" { #endif +struct AnimationEvalContext; struct ChannelDriver; struct DriverTarget; struct DriverVar; @@ -97,7 +98,7 @@ void BKE_driver_invalidate_expression(struct ChannelDriver *driver, float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, struct ChannelDriver *driver_orig, - const float evaltime); + const struct AnimationEvalContext *anim_eval_context); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index b35d2183408..0ee2fcb1963 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1612,8 +1612,12 @@ void BKE_pose_tag_recalc(Main *bmain, bPose *pose) /* For the calculation of the effects of an Action at the given frame on an object * This is currently only used for the Action Constraint */ -void what_does_obaction( - Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe) +void what_does_obaction(Object *ob, + Object *workob, + bPose *pose, + bAction *act, + char groupname[], + const AnimationEvalContext *anim_eval_context) { bActionGroup *agrp = BKE_action_group_find_name(act, groupname); @@ -1669,7 +1673,7 @@ void what_does_obaction( RNA_id_pointer_create(&workob->id, &id_ptr); /* execute action for this group only */ - animsys_evaluate_action_group(&id_ptr, act, agrp, cframe); + animsys_evaluate_action_group(&id_ptr, act, agrp, anim_eval_context); } else { AnimData adt = {NULL}; @@ -1680,6 +1684,6 @@ void what_does_obaction( adt.action = act; /* execute effects of Action on to workob (or it's PoseChannels) */ - BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false); } } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 09d6ba4ff44..ea5a4bd99d1 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -538,7 +538,7 @@ static void animsys_write_orig_anim_rna(PointerRNA *ptr, */ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, - float ctime, + const AnimationEvalContext *anim_eval_context, bool flush_to_original) { /* Calculate then execute each curve. */ @@ -557,7 +557,7 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, } PathResolvedRNA anim_rna; if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context); BKE_animsys_write_rna_setting(&anim_rna, curval); if (flush_to_original) { animsys_write_orig_anim_rna(ptr, fcu->rna_path, fcu->array_index, curval); @@ -569,8 +569,26 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, /* ***************************************** */ /* Driver Evaluation */ +AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, + float eval_time) +{ + AnimationEvalContext ctx = { + .depsgraph = depsgraph, + .eval_time = eval_time, + }; + return ctx; +} + +AnimationEvalContext BKE_animsys_eval_context_construct_at( + const AnimationEvalContext *anim_eval_context, float eval_time) +{ + return BKE_animsys_eval_context_construct(anim_eval_context->depsgraph, eval_time); +} + /* Evaluate Drivers */ -static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime) +static void animsys_evaluate_drivers(PointerRNA *ptr, + AnimData *adt, + const AnimationEvalContext *anim_eval_context) { FCurve *fcu; @@ -591,7 +609,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime * before adding new to only be done when drivers only changed. */ PathResolvedRNA anim_rna; if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context); ok = BKE_animsys_write_rna_setting(&anim_rna, curval); } @@ -647,7 +665,10 @@ static void action_idcode_patch_check(ID *id, bAction *act) /* ----------------------------------------- */ /* Evaluate Action Group */ -void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *agrp, float ctime) +void animsys_evaluate_action_group(PointerRNA *ptr, + bAction *act, + bActionGroup *agrp, + const AnimationEvalContext *anim_eval_context) { FCurve *fcu; @@ -669,7 +690,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0 && !BKE_fcurve_is_empty(fcu)) { PathResolvedRNA anim_rna; if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context); BKE_animsys_write_rna_setting(&anim_rna, curval); } } @@ -679,7 +700,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * /* Evaluate Action (F-Curve Bag) */ static void animsys_evaluate_action_ex(PointerRNA *ptr, bAction *act, - float ctime, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ @@ -690,15 +711,15 @@ static void animsys_evaluate_action_ex(PointerRNA *ptr, action_idcode_patch_check(ptr->owner_id, act); /* calculate then execute each curve */ - animsys_evaluate_fcurves(ptr, &act->curves, ctime, flush_to_original); + animsys_evaluate_fcurves(ptr, &act->curves, anim_eval_context, flush_to_original); } void animsys_evaluate_action(PointerRNA *ptr, bAction *act, - float ctime, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { - animsys_evaluate_action_ex(ptr, act, ctime, flush_to_original); + animsys_evaluate_action_ex(ptr, act, anim_eval_context, flush_to_original); } /* ***************************************** */ @@ -726,7 +747,9 @@ static float nlastrip_get_influence(NlaStrip *strip, float cframe) } /* evaluate the evaluation time and influence for the strip, storing the results in the strip */ -static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool flush_to_original) +static void nlastrip_evaluate_controls(NlaStrip *strip, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) { /* now strip's evaluate F-Curves for these settings (if applicable) */ if (strip->fcurves.first) { @@ -736,7 +759,7 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); /* execute these settings as per normal */ - animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, ctime, flush_to_original); + animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, anim_eval_context, flush_to_original); } /* analytically generate values for influence and time (if applicable) @@ -744,17 +767,18 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool * in case the override has been turned off. */ if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) { - strip->influence = nlastrip_get_influence(strip, ctime); + strip->influence = nlastrip_get_influence(strip, anim_eval_context->eval_time); } /* Bypass evaluation time computation if time mapping is disabled. */ if ((strip->flag & NLASTRIP_FLAG_NO_TIME_MAP) != 0) { - strip->strip_time = ctime; + strip->strip_time = anim_eval_context->eval_time; return; } if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) { - strip->strip_time = nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL); + strip->strip_time = nlastrip_get_frame( + strip, anim_eval_context->eval_time, NLATIME_CONVERT_EVAL); } /* if user can control the evaluation time (using F-Curves), consider the option which allows @@ -768,12 +792,16 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool } /* gets the strip active at the current time for a list of strips for evaluation purposes */ -NlaEvalStrip *nlastrips_ctime_get_strip( - ListBase *list, ListBase *strips, short index, float ctime, const bool flush_to_original) +NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, + ListBase *strips, + short index, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) { NlaStrip *strip, *estrip = NULL; NlaEvalStrip *nes; short side = 0; + float ctime = anim_eval_context->eval_time; /* loop over strips, checking if they fall within the range */ for (strip = strips->first; strip; strip = strip->next) { @@ -852,7 +880,9 @@ NlaEvalStrip *nlastrips_ctime_get_strip( */ /* TODO: this sounds a bit hacky having a few isolated F-Curves * stuck on some data it operates on... */ - nlastrip_evaluate_controls(estrip, ctime, flush_to_original); + AnimationEvalContext clamped_eval_context = BKE_animsys_eval_context_construct_at( + anim_eval_context, ctime); + nlastrip_evaluate_controls(estrip, &clamped_eval_context, flush_to_original); if (estrip->influence <= 0.0f) { return NULL; } @@ -874,8 +904,12 @@ NlaEvalStrip *nlastrips_ctime_get_strip( } /* evaluate controls for the relevant extents of the bordering strips... */ - nlastrip_evaluate_controls(estrip->prev, estrip->start, flush_to_original); - nlastrip_evaluate_controls(estrip->next, estrip->end, flush_to_original); + AnimationEvalContext start_eval_context = BKE_animsys_eval_context_construct_at( + anim_eval_context, estrip->start); + AnimationEvalContext end_eval_context = BKE_animsys_eval_context_construct_at( + anim_eval_context, estrip->end); + nlastrip_evaluate_controls(estrip->prev, &start_eval_context, flush_to_original); + nlastrip_evaluate_controls(estrip->next, &end_eval_context, flush_to_original); break; } @@ -1795,6 +1829,7 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { ListBase tmp_modifiers = {NULL, NULL}; @@ -1836,13 +1871,15 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr, tmp_nes.strip_mode = NES_TIME_TRANSITION_START; tmp_nes.strip = s1; nlaeval_snapshot_init(&snapshot1, channels, snapshot); - nlastrip_evaluate(ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot1, flush_to_original); + nlastrip_evaluate( + ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot1, anim_eval_context, flush_to_original); /* second strip */ tmp_nes.strip_mode = NES_TIME_TRANSITION_END; tmp_nes.strip = s2; nlaeval_snapshot_init(&snapshot2, channels, snapshot); - nlastrip_evaluate(ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, flush_to_original); + nlastrip_evaluate( + ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, anim_eval_context, flush_to_original); /* accumulate temp-buffer and full-buffer, using the 'real' strip */ nlaeval_snapshot_mix_and_free(channels, snapshot, &snapshot1, &snapshot2, nes->strip_time); @@ -1857,6 +1894,7 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { ListBase tmp_modifiers = {NULL, NULL}; @@ -1877,13 +1915,16 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr, /* find the child-strip to evaluate */ evaltime = (nes->strip_time * (strip->end - strip->start)) + strip->start; - tmp_nes = nlastrips_ctime_get_strip(NULL, &strip->strips, -1, evaltime, flush_to_original); + AnimationEvalContext child_context = BKE_animsys_eval_context_construct_at(anim_eval_context, + evaltime); + tmp_nes = nlastrips_ctime_get_strip(NULL, &strip->strips, -1, &child_context, flush_to_original); /* directly evaluate child strip into accumulation buffer... * - there's no need to use a temporary buffer (as it causes issues [T40082]) */ if (tmp_nes) { - nlastrip_evaluate(ptr, channels, &tmp_modifiers, tmp_nes, snapshot, flush_to_original); + nlastrip_evaluate( + ptr, channels, &tmp_modifiers, tmp_nes, snapshot, &child_context, flush_to_original); /* free temp eval-strip */ MEM_freeN(tmp_nes); @@ -1899,6 +1940,7 @@ void nlastrip_evaluate(PointerRNA *ptr, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { NlaStrip *strip = nes->strip; @@ -1921,10 +1963,12 @@ void nlastrip_evaluate(PointerRNA *ptr, nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes, snapshot); break; case NLASTRIP_TYPE_TRANSITION: /* transition */ - nlastrip_evaluate_transition(ptr, channels, modifiers, nes, snapshot, flush_to_original); + nlastrip_evaluate_transition( + ptr, channels, modifiers, nes, snapshot, anim_eval_context, flush_to_original); break; case NLASTRIP_TYPE_META: /* meta */ - nlastrip_evaluate_meta(ptr, channels, modifiers, nes, snapshot, flush_to_original); + nlastrip_evaluate_meta( + ptr, channels, modifiers, nes, snapshot, anim_eval_context, flush_to_original); break; default: /* do nothing */ @@ -2072,7 +2116,7 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels, static bool animsys_evaluate_nla(NlaEvalData *echannels, PointerRNA *ptr, AnimData *adt, - float ctime, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original, NlaKeyframingContext *r_context) { @@ -2120,7 +2164,8 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, } /* otherwise, get strip to evaluate for this channel */ - nes = nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime, flush_to_original); + nes = nlastrips_ctime_get_strip( + &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original); if (nes) { nes->track = nlt; } @@ -2186,7 +2231,8 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, /* add this to our list of evaluation strips */ if (r_context == NULL) { - nlastrips_ctime_get_strip(&estrips, &dummy_trackslist, -1, ctime, flush_to_original); + nlastrips_ctime_get_strip( + &estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original); } /* If computing the context for keyframing, store data there instead of the list. */ else { @@ -2196,7 +2242,7 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, NLASTRIP_EXTEND_HOLD; r_context->eval_strip = nes = nlastrips_ctime_get_strip( - NULL, &dummy_trackslist, -1, ctime, flush_to_original); + NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original); /* These setting combinations require no data from strips below, so exit immediately. */ if ((nes == NULL) || @@ -2221,7 +2267,13 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, /* 2. for each strip, evaluate then accumulate on top of existing channels, * but don't set values yet. */ for (nes = estrips.first; nes; nes = nes->next) { - nlastrip_evaluate(ptr, echannels, NULL, nes, &echannels->eval_snapshot, flush_to_original); + nlastrip_evaluate(ptr, + echannels, + NULL, + nes, + &echannels->eval_snapshot, + anim_eval_context, + flush_to_original); } /* 3. free temporary evaluation data that's not used elsewhere */ @@ -2235,7 +2287,7 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, */ static void animsys_calculate_nla(PointerRNA *ptr, AnimData *adt, - float ctime, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { NlaEvalData echannels; @@ -2243,7 +2295,7 @@ static void animsys_calculate_nla(PointerRNA *ptr, nlaeval_init(&echannels); /* evaluate the NLA stack, obtaining a set of values to flush */ - if (animsys_evaluate_nla(&echannels, ptr, adt, ctime, flush_to_original, NULL)) { + if (animsys_evaluate_nla(&echannels, ptr, adt, anim_eval_context, flush_to_original, NULL)) { /* reset any channels touched by currently inactive actions to default value */ animsys_evaluate_nla_domain(ptr, &echannels, adt); @@ -2257,7 +2309,7 @@ static void animsys_calculate_nla(PointerRNA *ptr, CLOG_WARN(&LOG, "NLA Eval: Stopgap for active action on NLA Stack - no strips case"); } - animsys_evaluate_action(ptr, adt->action, ctime, flush_to_original); + animsys_evaluate_action(ptr, adt->action, anim_eval_context, flush_to_original); } /* free temp data */ @@ -2275,11 +2327,12 @@ static void animsys_calculate_nla(PointerRNA *ptr, * \param ptr: RNA pointer to the Object with the animation. * \return Keyframing context, or NULL if not necessary. */ -NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *cache, - struct PointerRNA *ptr, - struct AnimData *adt, - float ctime, - const bool flush_to_original) +NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( + struct ListBase *cache, + struct PointerRNA *ptr, + struct AnimData *adt, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) { /* No remapping needed if NLA is off or no action. */ if ((adt == NULL) || (adt->action == NULL) || (adt->nla_tracks.first == NULL) || @@ -2302,7 +2355,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *ca ctx->adt = adt; nlaeval_init(&ctx->nla_channels); - animsys_evaluate_nla(&ctx->nla_channels, ptr, adt, ctime, flush_to_original, ctx); + animsys_evaluate_nla(&ctx->nla_channels, ptr, adt, anim_eval_context, flush_to_original, ctx); BLI_assert(ELEM(ctx->strip.act, NULL, adt->action)); BLI_addtail(cache, ctx); @@ -2492,8 +2545,11 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) * and that the flags for which parts of the anim-data settings need to be recalculated * have been set already by the depsgraph. Now, we use the recalc */ -void BKE_animsys_evaluate_animdata( - ID *id, AnimData *adt, float ctime, eAnimData_Recalc recalc, const bool flush_to_original) +void BKE_animsys_evaluate_animdata(ID *id, + AnimData *adt, + const AnimationEvalContext *anim_eval_context, + eAnimData_Recalc recalc, + const bool flush_to_original) { PointerRNA id_ptr; @@ -2516,11 +2572,11 @@ void BKE_animsys_evaluate_animdata( /* evaluate NLA-stack * - active action is evaluated as part of the NLA stack as the last item */ - animsys_calculate_nla(&id_ptr, adt, ctime, flush_to_original); + animsys_calculate_nla(&id_ptr, adt, anim_eval_context, flush_to_original); } /* evaluate Active Action only */ else if (adt->action) { - animsys_evaluate_action_ex(&id_ptr, adt->action, ctime, flush_to_original); + animsys_evaluate_action_ex(&id_ptr, adt->action, anim_eval_context, flush_to_original); } } @@ -2530,7 +2586,7 @@ void BKE_animsys_evaluate_animdata( * - Drivers should be in the appropriate order to be evaluated without problems... */ if (recalc & ADT_RECALC_DRIVERS) { - animsys_evaluate_drivers(&id_ptr, adt, ctime); + animsys_evaluate_drivers(&id_ptr, adt, anim_eval_context); } /* always execute 'overrides' @@ -2558,6 +2614,8 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float } const bool flush_to_original = DEG_is_active(depsgraph); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + ctime); /* macros for less typing * - only evaluate animation data for id if it has users (and not just fake ones) @@ -2568,7 +2626,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float for (id = first; id; id = id->next) { \ if (ID_REAL_USERS(id) > 0) { \ AnimData *adt = BKE_animdata_from_id(id); \ - BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2587,9 +2645,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float if (ntp->nodetree) { \ AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \ BKE_animsys_evaluate_animdata( \ - &ntp->nodetree->id, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \ + &ntp->nodetree->id, adt2, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); \ } \ - BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2706,7 +2764,10 @@ void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id) * which should get handled as part of the dependency graph instead. */ DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime); const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM, flush_to_original); + + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + ctime); + BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); } void BKE_animsys_update_driver_array(ID *id) @@ -2768,7 +2829,9 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCu if (BKE_animsys_store_rna_setting(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { /* Evaluate driver, and write results to COW-domain destination */ const float ctime = DEG_get_ctime(depsgraph); - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, ctime); + const float curval = calculate_fcurve(&anim_rna, fcu, &anim_eval_context); ok = BKE_animsys_write_rna_setting(&anim_rna, curval); /* Flush results & status codes to original data for UI (T59984) */ diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 4bd0c77af28..6118325c231 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -1147,7 +1147,7 @@ void BKE_collections_after_lib_link(Main *bmain) /** \name Collection Children * \{ */ -static bool collection_find_instance_recursive(Collection *collection, +static bool collection_instance_find_recursive(Collection *collection, Collection *instance_collection) { LISTBASE_FOREACH (CollectionObject *, collection_object, &collection->gobject) { @@ -1159,7 +1159,7 @@ static bool collection_find_instance_recursive(Collection *collection, } LISTBASE_FOREACH (CollectionChild *, collection_child, &collection->children) { - if (collection_find_instance_recursive(collection_child->collection, instance_collection)) { + if (collection_instance_find_recursive(collection_child->collection, instance_collection)) { return true; } } @@ -1167,21 +1167,88 @@ static bool collection_find_instance_recursive(Collection *collection, return false; } -bool BKE_collection_find_cycle(Collection *new_ancestor, Collection *collection) +/** + * Find potential cycles in collections. + * + * \param new_ancestor the potential new owner of given \a collection, or the collection to check + * if the later is NULL. + * \param collection the collection we want to add to \a new_ancestor, may be NULL if we just want + * to ensure \a new_ancestor does not already have cycles. + * \return true if a cycle is found. + */ +bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection) { if (collection == new_ancestor) { return true; } + if (collection == NULL) { + collection = new_ancestor; + } + LISTBASE_FOREACH (CollectionParent *, parent, &new_ancestor->parents) { - if (BKE_collection_find_cycle(parent->collection, collection)) { + if (BKE_collection_cycle_find(parent->collection, collection)) { return true; } } /* Find possible objects in collection or its children, that would instantiate the given ancestor * collection (that would also make a fully invalid cycle of dependencies) .*/ - return collection_find_instance_recursive(collection, new_ancestor); + return collection_instance_find_recursive(collection, new_ancestor); +} + +static bool collection_instance_fix_recursive(Collection *parent_collection, + Collection *collection) +{ + bool cycles_found = false; + + LISTBASE_FOREACH (CollectionObject *, collection_object, &parent_collection->gobject) { + if (collection_object->ob != NULL && + collection_object->ob->instance_collection == collection) { + id_us_min(&collection->id); + collection_object->ob->instance_collection = NULL; + cycles_found = true; + } + } + + LISTBASE_FOREACH (CollectionChild *, collection_child, &parent_collection->children) { + if (collection_instance_fix_recursive(collection_child->collection, collection)) { + cycles_found = true; + } + } + + return cycles_found; +} + +static bool collection_cycle_fix_recursive(Main *bmain, + Collection *parent_collection, + Collection *collection) +{ + bool cycles_found = false; + + LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &parent_collection->parents) { + if (BKE_collection_cycle_find(parent->collection, collection)) { + BKE_collection_child_remove(bmain, parent->collection, parent_collection); + cycles_found = true; + } + else if (collection_cycle_fix_recursive(bmain, parent->collection, collection)) { + cycles_found = true; + } + } + + return cycles_found; +} + +/** + * Find and fix potential cycles in collections. + * + * \param collection the collection to check for existing cycles. + * \return true if cycles are found and fixed. + */ +bool BKE_collection_cycles_fix(Main *bmain, Collection *collection) +{ + return collection_cycle_fix_recursive(bmain, collection, collection) || + collection_instance_fix_recursive(collection, collection); } static CollectionChild *collection_find_child(Collection *parent, Collection *collection) @@ -1223,7 +1290,7 @@ static bool collection_child_add(Collection *parent, if (child) { return false; } - if (BKE_collection_find_cycle(parent, collection)) { + if (BKE_collection_cycle_find(parent, collection)) { return false; } @@ -1301,7 +1368,7 @@ void BKE_collection_parent_relations_rebuild(Collection *collection) child = child_next) { child_next = child->next; - if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) { + if (child->collection == NULL || BKE_collection_cycle_find(collection, child->collection)) { BLI_freelinkN(&collection->children, child); } else { @@ -1464,7 +1531,7 @@ bool BKE_collection_move(Main *bmain, if (collection->flag & COLLECTION_IS_MASTER) { return false; } - if (BKE_collection_find_cycle(to_parent, collection)) { + if (BKE_collection_cycle_find(to_parent, collection)) { return false; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 06c28776840..2ef32895db9 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -53,6 +53,7 @@ #include "BKE_action.h" #include "BKE_anim_path.h" +#include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_bvhutils.h" #include "BKE_cachefile.h" @@ -2625,7 +2626,7 @@ static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy) } } -static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), +static void actcon_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, @@ -2679,6 +2680,8 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), s = (vec[axis] - data->min) / (data->max - data->min); CLAMP(s, 0, 1); t = (s * (data->end - data->start)) + data->start; + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + t); if (G.debug & G_DEBUG) { printf("do Action Constraint %s - Ob %s Pchan %s\n", @@ -2693,7 +2696,7 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), /* evaluate using workob */ /* FIXME: we don't have any consistent standards on limiting effects on object... */ - what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, t); + what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, &anim_eval_context); BKE_object_to_mat4(&workob, ct->matrix); } else if (cob->type == CONSTRAINT_OBTYPE_BONE) { @@ -2710,7 +2713,7 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), tchan->rotmode = pchan->rotmode; /* evaluate action using workob (it will only set the PoseChannel in question) */ - what_does_obaction(cob->ob, &workob, &pose, data->act, pchan->name, t); + what_does_obaction(cob->ob, &workob, &pose, data->act, pchan->name, &anim_eval_context); /* convert animation to matrices for use here */ BKE_pchan_calc_mat(tchan); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 746aff1697c..acbbf50701a 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1872,17 +1872,18 @@ float evaluate_fcurve_only_curve(FCurve *fcu, float evaltime) float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, ChannelDriver *driver_orig, - float evaltime) + const AnimationEvalContext *anim_eval_context) { BLI_assert(fcu->driver != NULL); float cvalue = 0.0f; + float evaltime = anim_eval_context->eval_time; /* If there is a driver (only if this F-Curve is acting as 'driver'), * evaluate it to find value to use as "evaltime" since drivers essentially act as alternative * input (i.e. in place of 'time') for F-Curves. */ if (fcu->driver) { /* evaltime now serves as input for the curve */ - evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, evaltime); + evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, anim_eval_context); /* only do a default 1-1 mapping if it's unlikely that anything else will set a value... */ if (fcu->totvert == 0) { @@ -1924,7 +1925,9 @@ bool BKE_fcurve_is_empty(FCurve *fcu) } /* Calculate the value of the given F-Curve at the given frame, and set its curval */ -float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime) +float calculate_fcurve(PathResolvedRNA *anim_rna, + FCurve *fcu, + const AnimationEvalContext *anim_eval_context) { /* only calculate + set curval (overriding the existing value) if curve has * any data which warrants this... @@ -1936,10 +1939,10 @@ float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime) /* calculate and set curval (evaluates driver too if necessary) */ float curval; if (fcu->driver) { - curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime); + curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, anim_eval_context); } else { - curval = evaluate_fcurve(fcu, evaltime); + curval = evaluate_fcurve(fcu, anim_eval_context->eval_time); } fcu->curval = curval; /* debug display only, not thread safe! */ return curval; diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c index a0625918a62..10d804f437e 100644 --- a/source/blender/blenkernel/intern/fcurve_driver.c +++ b/source/blender/blenkernel/intern/fcurve_driver.c @@ -43,6 +43,7 @@ #include "BLT_translation.h" #include "BKE_action.h" +#include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_constraint.h" #include "BKE_fcurve_driver.h" @@ -1232,24 +1233,25 @@ static void evaluate_driver_min_max(ChannelDriver *driver) static void evaluate_driver_python(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, - const float evaltime) + const AnimationEvalContext *anim_eval_context) { /* check for empty or invalid expression */ if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) { driver->curval = 0.0f; } - else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) { + else if (!driver_try_evaluate_simple_expr( + driver, driver_orig, &driver->curval, anim_eval_context->eval_time)) { #ifdef WITH_PYTHON /* this evaluates the expression using Python, and returns its result: * - on errors it reports, then returns 0.0f */ BLI_mutex_lock(&python_driver_lock); - driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime); + driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, anim_eval_context); BLI_mutex_unlock(&python_driver_lock); #else /* WITH_PYTHON*/ - UNUSED_VARS(anim_rna, evaltime); + UNUSED_VARS(anim_rna, anim_eval_context); #endif /* WITH_PYTHON*/ } } @@ -1262,7 +1264,7 @@ static void evaluate_driver_python(PathResolvedRNA *anim_rna, float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, - const float evaltime) + const AnimationEvalContext *anim_eval_context) { /* check if driver can be evaluated */ if (driver_orig->flag & DRIVER_FLAG_INVALID) { @@ -1279,7 +1281,7 @@ float evaluate_driver(PathResolvedRNA *anim_rna, evaluate_driver_min_max(driver); break; case DRIVER_TYPE_PYTHON: /* expression */ - evaluate_driver_python(anim_rna, driver, driver_orig, evaltime); + evaluate_driver_python(anim_rna, driver, driver_orig, anim_eval_context); break; default: /* special 'hack' - just use stored value diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 52a3521189b..5086145c0ff 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -143,103 +143,78 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds, int o_shift[3], int n_shift[3]) { - int x, y, z; struct MANTA *fluid_old = fds->fluid; const int block_size = fds->noise_scale; int new_shift[3] = {0}; sub_v3_v3v3_int(new_shift, n_shift, o_shift); - /* allocate new fluid data */ + /* Allocate new fluid data. */ BKE_fluid_reallocate_fluid(fds, n_res, 0); int o_total_cells = o_res[0] * o_res[1] * o_res[2]; int n_total_cells = n_res[0] * n_res[1] * n_res[2]; - /* boundary cells will be skipped when copying data */ - int bwidth = fds->boundary_width; - - /* copy values from old fluid to new */ + /* Copy values from old fluid to new fluid object. */ if (o_total_cells > 1 && n_total_cells > 1) { - /* base smoke */ - float *o_dens, *o_react, *o_flame, *o_fuel, *o_heat, *o_vx, *o_vy, *o_vz, *o_r, *o_g, *o_b; - float *n_dens, *n_react, *n_flame, *n_fuel, *n_heat, *n_vx, *n_vy, *n_vz, *n_r, *n_g, *n_b; - float dummy, *dummy_s; - int *dummy_p; - /* noise smoke */ + float *o_dens = manta_smoke_get_density(fluid_old); + float *o_react = manta_smoke_get_react(fluid_old); + float *o_flame = manta_smoke_get_flame(fluid_old); + float *o_fuel = manta_smoke_get_fuel(fluid_old); + float *o_heat = manta_smoke_get_heat(fluid_old); + float *o_vx = manta_get_velocity_x(fluid_old); + float *o_vy = manta_get_velocity_y(fluid_old); + float *o_vz = manta_get_velocity_z(fluid_old); + float *o_r = manta_smoke_get_color_r(fluid_old); + float *o_g = manta_smoke_get_color_g(fluid_old); + float *o_b = manta_smoke_get_color_b(fluid_old); + + float *n_dens = manta_smoke_get_density(fds->fluid); + float *n_react = manta_smoke_get_react(fds->fluid); + float *n_flame = manta_smoke_get_flame(fds->fluid); + float *n_fuel = manta_smoke_get_fuel(fds->fluid); + float *n_heat = manta_smoke_get_heat(fds->fluid); + float *n_vx = manta_get_velocity_x(fds->fluid); + float *n_vy = manta_get_velocity_y(fds->fluid); + float *n_vz = manta_get_velocity_z(fds->fluid); + float *n_r = manta_smoke_get_color_r(fds->fluid); + float *n_g = manta_smoke_get_color_g(fds->fluid); + float *n_b = manta_smoke_get_color_b(fds->fluid); + + /* Noise smoke fields. */ int wt_res_old[3]; - float *o_wt_dens, *o_wt_react, *o_wt_flame, *o_wt_fuel, *o_wt_tcu, *o_wt_tcv, *o_wt_tcw, - *o_wt_tcu2, *o_wt_tcv2, *o_wt_tcw2, *o_wt_r, *o_wt_g, *o_wt_b; - float *n_wt_dens, *n_wt_react, *n_wt_flame, *n_wt_fuel, *n_wt_tcu, *n_wt_tcv, *n_wt_tcw, - *n_wt_tcu2, *n_wt_tcv2, *n_wt_tcw2, *n_wt_r, *n_wt_g, *n_wt_b; - - if (fds->flags & FLUID_DOMAIN_USE_NOISE) { - manta_smoke_turbulence_export(fluid_old, - &o_wt_dens, - &o_wt_react, - &o_wt_flame, - &o_wt_fuel, - &o_wt_r, - &o_wt_g, - &o_wt_b, - &o_wt_tcu, - &o_wt_tcv, - &o_wt_tcw, - &o_wt_tcu2, - &o_wt_tcv2, - &o_wt_tcw2); - manta_smoke_turbulence_get_res(fluid_old, wt_res_old); - manta_smoke_turbulence_export(fds->fluid, - &n_wt_dens, - &n_wt_react, - &n_wt_flame, - &n_wt_fuel, - &n_wt_r, - &n_wt_g, - &n_wt_b, - &n_wt_tcu, - &n_wt_tcv, - &n_wt_tcw, - &n_wt_tcu2, - &n_wt_tcv2, - &n_wt_tcw2); - } - - manta_smoke_export(fluid_old, - &dummy, - &dummy, - &o_dens, - &o_react, - &o_flame, - &o_fuel, - &o_heat, - &o_vx, - &o_vy, - &o_vz, - &o_r, - &o_g, - &o_b, - &dummy_p, - &dummy_s); - manta_smoke_export(fds->fluid, - &dummy, - &dummy, - &n_dens, - &n_react, - &n_flame, - &n_fuel, - &n_heat, - &n_vx, - &n_vy, - &n_vz, - &n_r, - &n_g, - &n_b, - &dummy_p, - &dummy_s); - - for (x = o_min[0]; x < o_max[0]; x++) { - for (y = o_min[1]; y < o_max[1]; y++) { - for (z = o_min[2]; z < o_max[2]; z++) { + float *o_wt_dens = manta_noise_get_density(fluid_old); + float *o_wt_react = manta_noise_get_react(fluid_old); + float *o_wt_flame = manta_noise_get_flame(fluid_old); + float *o_wt_fuel = manta_noise_get_fuel(fluid_old); + float *o_wt_r = manta_noise_get_color_r(fluid_old); + float *o_wt_g = manta_noise_get_color_g(fluid_old); + float *o_wt_b = manta_noise_get_color_b(fluid_old); + float *o_wt_tcu = manta_noise_get_texture_u(fluid_old); + float *o_wt_tcv = manta_noise_get_texture_v(fluid_old); + float *o_wt_tcw = manta_noise_get_texture_w(fluid_old); + float *o_wt_tcu2 = manta_noise_get_texture_u2(fluid_old); + float *o_wt_tcv2 = manta_noise_get_texture_v2(fluid_old); + float *o_wt_tcw2 = manta_noise_get_texture_w2(fluid_old); + + float *n_wt_dens = manta_noise_get_density(fds->fluid); + float *n_wt_react = manta_noise_get_react(fds->fluid); + float *n_wt_flame = manta_noise_get_flame(fds->fluid); + float *n_wt_fuel = manta_noise_get_fuel(fds->fluid); + float *n_wt_r = manta_noise_get_color_r(fds->fluid); + float *n_wt_g = manta_noise_get_color_g(fds->fluid); + float *n_wt_b = manta_noise_get_color_b(fds->fluid); + float *n_wt_tcu = manta_noise_get_texture_u(fds->fluid); + float *n_wt_tcv = manta_noise_get_texture_v(fds->fluid); + float *n_wt_tcw = manta_noise_get_texture_w(fds->fluid); + float *n_wt_tcu2 = manta_noise_get_texture_u2(fds->fluid); + float *n_wt_tcv2 = manta_noise_get_texture_v2(fds->fluid); + float *n_wt_tcw2 = manta_noise_get_texture_w2(fds->fluid); + + manta_noise_get_res(fluid_old, wt_res_old); + + for (int z = o_min[2]; z < o_max[2]; z++) { + for (int y = o_min[1]; y < o_max[1]; y++) { + for (int x = o_min[0]; x < o_max[0]; x++) { /* old grid index */ int xo = x - o_min[0]; int yo = y - o_min[1]; @@ -251,20 +226,31 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds, int zn = z - n_min[2] - new_shift[2]; int index_new = manta_get_index(xn, n_res[0], yn, n_res[1], zn); - /* skip if outside new domain */ + /* Skip if outside new domain. */ if (xn < 0 || xn >= n_res[0] || yn < 0 || yn >= n_res[1] || zn < 0 || zn >= n_res[2]) { continue; } - /* skip if trying to copy from old boundary cell */ +# if 0 + /* Note (sebbas): + * Disabling this "skip section" as not copying borders results in weird cut-off effects. + * It is possible that this cutting off is the reason for line effects as seen in T74559. + * Since domain borders will be handled on the simulation side anyways, + * copying border values should not be an issue. */ + + /* boundary cells will be skipped when copying data */ + int bwidth = fds->boundary_width; + + /* Skip if trying to copy from old boundary cell. */ if (xo < bwidth || yo < bwidth || zo < bwidth || xo >= o_res[0] - bwidth || yo >= o_res[1] - bwidth || zo >= o_res[2] - bwidth) { continue; } - /* skip if trying to copy into new boundary cell */ + /* Skip if trying to copy into new boundary cell. */ if (xn < bwidth || yn < bwidth || zn < bwidth || xn >= n_res[0] - bwidth || yn >= n_res[1] - bwidth || zn >= n_res[2] - bwidth) { continue; } +# endif /* copy data */ if (fds->flags & FLUID_DOMAIN_USE_NOISE) { @@ -1406,8 +1392,7 @@ static void update_obstacles(Depsgraph *depsgraph, /* Cannot use static mode with adaptive domain. * The adaptive domain might expand and only later in the simulations discover the static * object. */ - bool is_static = is_static_object(effecobj) && - ((fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) == 0); + bool is_static = is_static_object(effecobj) && !use_adaptivedomain; /* Check for initialized effector object. */ if ((fmd2->type & MOD_FLUID_TYPE_EFFEC) && fmd2->effector) { @@ -2264,15 +2249,15 @@ static void adaptive_domain_adjust( int x, y, z; float *density = manta_smoke_get_density(fds->fluid); float *fuel = manta_smoke_get_fuel(fds->fluid); - float *bigdensity = manta_smoke_turbulence_get_density(fds->fluid); - float *bigfuel = manta_smoke_turbulence_get_fuel(fds->fluid); + float *bigdensity = manta_noise_get_density(fds->fluid); + float *bigfuel = manta_noise_get_fuel(fds->fluid); float *vx = manta_get_velocity_x(fds->fluid); float *vy = manta_get_velocity_y(fds->fluid); float *vz = manta_get_velocity_z(fds->fluid); int wt_res[3]; if (fds->flags & FLUID_DOMAIN_USE_NOISE && fds->fluid) { - manta_smoke_turbulence_get_res(fds->fluid, wt_res); + manta_noise_get_res(fds->fluid, wt_res); } INIT_MINMAX(min_vel, max_vel); @@ -3951,6 +3936,12 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, break; } + /* Adaptive domain needs to know about current state, so save it here. */ + copy_v3_v3_int(o_res, fds->res); + copy_v3_v3_int(o_min, fds->res_min); + copy_v3_v3_int(o_max, fds->res_max); + copy_v3_v3_int(o_shift, fds->shift); + bool read_partial = false, read_all = false; /* Try to read from cache and keep track of read success. */ if (read_cache) { @@ -3983,28 +3974,15 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, has_config = manta_read_config(fds->fluid, fmd, noise_frame); /* Only reallocate when just reading cache or when resuming during bake. */ - if ((!baking_noise || (baking_noise && resume_noise)) && has_config && - manta_needs_realloc(fds->fluid, fmd)) { - BKE_fluid_reallocate_fluid(fds, fds->res, 1); + if (has_data && has_config && manta_needs_realloc(fds->fluid, fmd)) { + BKE_fluid_reallocate_copy_fluid( + fds, o_res, fds->res, o_min, fds->res_min, o_max, o_shift, fds->shift); } read_partial = !baking_data && !baking_noise && next_noise; read_all = !read_partial && with_resumable_cache; has_noise = manta_read_noise(fds->fluid, fmd, noise_frame, read_all); - /* When using the adaptive domain, copy all data that was read to a new fluid object. */ - if (with_adaptive && baking_noise) { - /* Adaptive domain needs to know about current state, so save it, then copy. */ - copy_v3_v3_int(o_res, fds->res); - copy_v3_v3_int(o_min, fds->res_min); - copy_v3_v3_int(o_max, fds->res_max); - copy_v3_v3_int(o_shift, fds->shift); - if (has_config && manta_needs_realloc(fds->fluid, fmd)) { - BKE_fluid_reallocate_copy_fluid( - fds, o_res, fds->res, o_min, fds->res_min, o_max, o_shift, fds->shift); - } - } - read_partial = !baking_data && !baking_noise && next_data && next_noise; read_all = !read_partial && with_resumable_cache; has_data = manta_read_data(fds->fluid, fmd, data_frame, read_all); @@ -4316,7 +4294,7 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *v { float bv[6] = {0}; float light[3]; - int a, z, slabsize = fds->res[0] * fds->res[1], size = fds->res[0] * fds->res[1] * fds->res[2]; + int slabsize = fds->res[0] * fds->res[1]; float *density = manta_smoke_get_density(fds->fluid); float *shadow = manta_smoke_get_shadow(fds->fluid); float correct = -7.0f * fds->dx; @@ -4325,54 +4303,49 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *v return; } - /* convert light pos to sim cell space */ + /* Convert light pos to sim cell space. */ mul_m4_v3(fds->imat, light); light[0] = (light[0] - fds->p0[0]) / fds->cell_size[0] - 0.5f - (float)fds->res_min[0]; light[1] = (light[1] - fds->p0[1]) / fds->cell_size[1] - 0.5f - (float)fds->res_min[1]; light[2] = (light[2] - fds->p0[2]) / fds->cell_size[2] - 0.5f - (float)fds->res_min[2]; - for (a = 0; a < size; a++) { - shadow[a] = -1.0f; - } - - /* calculate domain bounds in sim cell space */ + /* Calculate domain bounds in sim cell space. */ // 0,2,4 = 0.0f bv[1] = (float)fds->res[0]; // x bv[3] = (float)fds->res[1]; // y bv[5] = (float)fds->res[2]; // z - for (z = 0; z < fds->res[2]; z++) { + for (int z = 0; z < fds->res[2]; z++) { size_t index = z * slabsize; - int x, y; - for (y = 0; y < fds->res[1]; y++) { - for (x = 0; x < fds->res[0]; x++, index++) { + for (int y = 0; y < fds->res[1]; y++) { + for (int x = 0; x < fds->res[0]; x++, index++) { float voxel_center[3]; float pos[3]; int cell[3]; float t_ray = 1.0; - if (shadow[index] >= 0.0f) { - continue; - } + /* Reset shadow value.*/ + shadow[index] = -1.0f; + voxel_center[0] = (float)x; voxel_center[1] = (float)y; voxel_center[2] = (float)z; - // get starting cell (light pos) + /* Get starting cell (light pos). */ if (BLI_bvhtree_bb_raycast(bv, light, voxel_center, pos) > FLT_EPSILON) { - // we're outside -> use point on side of domain + /* We're outside -> use point on side of domain. */ cell[0] = (int)floor(pos[0]); cell[1] = (int)floor(pos[1]); cell[2] = (int)floor(pos[2]); } else { - // we're inside -> use light itself + /* We're inside -> use light itself. */ cell[0] = (int)floor(light[0]); cell[1] = (int)floor(light[1]); cell[2] = (int)floor(light[2]); } - /* clamp within grid bounds */ + /* Clamp within grid bounds */ CLAMP(cell[0], 0, fds->res[0] - 1); CLAMP(cell[1], 0, fds->res[1] - 1); CLAMP(cell[2], 0, fds->res[2] - 1); @@ -4390,7 +4363,7 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *v fds->res, correct); - // convention -> from a RGBA float array, use G value for t_ray + /* Convention -> from a RGBA float array, use G value for t_ray. */ shadow[index] = t_ray; } } diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index b4f2caac861..561db7d62c2 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -144,15 +144,14 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i } #endif + Key *key = ((flag & LIB_ID_FREE_NO_MAIN) == 0) ? BKE_key_from_id(id) : NULL; + if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) { BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0); } - if ((flag & LIB_ID_FREE_NO_MAIN) == 0) { - Key *key = BKE_key_from_id(id); - if (key != NULL) { - BKE_id_free_ex(bmain, &key->id, flag, use_flag_from_idtag); - } + if ((flag & LIB_ID_FREE_NO_MAIN) == 0 && key != NULL) { + BKE_id_free_ex(bmain, &key->id, flag, use_flag_from_idtag); } BKE_libblock_free_datablock(id, flag); diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index a6e2b6a7835..322149bc3ce 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1120,11 +1120,11 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for TaskPool *task_pool = BLI_task_pool_create(bmain, TASK_PRIORITY_HIGH); FOREACH_MAIN_ID_BEGIN (bmain, id) { - if ((ID_IS_OVERRIDE_LIBRARY_REAL(id) && force_auto) || - (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH)) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && + (force_auto || (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) { BLI_task_pool_push(task_pool, lib_override_library_operations_create_cb, id, false, NULL); - id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH; } + id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH; } FOREACH_MAIN_ID_END; @@ -1276,8 +1276,6 @@ void BKE_lib_override_library_update(Main *bmain, ID *local) Key *local_key = BKE_key_from_id(local); Key *tmp_key = BKE_key_from_id(tmp_id); if (local_key != NULL && tmp_key != NULL) { - /* This is some kind of hard-coded 'always enforced override'... */ - tmp_key->from = local_key->from; tmp_key->id.flag |= (local_key->id.flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE); } @@ -1296,6 +1294,12 @@ void BKE_lib_override_library_update(Main *bmain, ID *local) * So when we'll free tmp_id, we'll actually free old, outdated data from local. */ BKE_lib_id_swap(bmain, local, tmp_id); + if (local_key != NULL && tmp_key != NULL) { + /* This is some kind of hard-coded 'always enforced override'... */ + BKE_lib_id_swap(bmain, &local_key->id, &tmp_key->id); + tmp_key->id.flag |= (local_key->id.flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE); + } + /* Again, horribly inn-efficient in our case, we need something off-Main * (aka more generic nolib copy/free stuff)! */ /* XXX And crashing in complex cases (e.g. because depsgraph uses same data...). */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d48ea33cc65..a344d2a163f 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2746,7 +2746,10 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o { /* Execute drivers and animation. */ const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + ctime); + BKE_animsys_evaluate_animdata( + &ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ALL, flush_to_original); object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL); } @@ -4643,9 +4646,13 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* was originally ID_RECALC_ALL - TODO - which flags are really needed??? */ /* TODO(sergey): What about animation? */ + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + frame); + ob->id.recalc |= ID_RECALC_ALL; if (update_mesh) { - BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata( + &ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); /* ignore cache clear during subframe updates * to not mess up cache validity */ object_cacheIgnoreClear(ob, 1); @@ -4659,12 +4666,14 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* for curve following objects, parented curve has to be updated too */ if (ob->type == OB_CURVE) { Curve *cu = ob->data; - BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata( + &cu->id, cu->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); } /* and armatures... */ if (ob->type == OB_ARMATURE) { bArmature *arm = ob->data; - BKE_animsys_evaluate_animdata(&arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata( + &arm->id, arm->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); BKE_pose_where_is(depsgraph, scene, ob); } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index bf9aea81181..bec9cbbad79 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4854,8 +4854,10 @@ void particle_system_update(struct Depsgraph *depsgraph, for (i = 0; i <= part->hair_step; i++) { hcfra = 100.0f * (float)i / (float)psys->part->hair_step; if ((part->flag & PART_HAIR_REGROW) == 0) { + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, hcfra); BKE_animsys_evaluate_animdata( - &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false); + &part_local->id, part_local->adt, &anim_eval_context, ADT_RECALC_ANIM, false); } system_step(&sim, hcfra, use_render_params); psys->cfra = hcfra; diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c index 30a371b5b28..ff3829bdebb 100644 --- a/source/blender/blenkernel/intern/seqprefetch.c +++ b/source/blender/blenkernel/intern/seqprefetch.c @@ -183,6 +183,10 @@ static float seq_prefetch_cfra(PrefetchJob *pfjob) { return pfjob->cfra + pfjob->num_frames_prefetched; } +static AnimationEvalContext seq_prefetch_anim_eval_context(PrefetchJob *pfjob) +{ + return BKE_animsys_eval_context_construct(pfjob->depsgraph, seq_prefetch_cfra(pfjob)); +} void BKE_sequencer_prefetch_get_time_range(Scene *scene, int *start, int *end) { @@ -435,8 +439,9 @@ static void *seq_prefetch_frames(void *job) seq_prefetch_update_depsgraph(pfjob); AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id); + AnimationEvalContext anim_eval_context = seq_prefetch_anim_eval_context(pfjob); BKE_animsys_evaluate_animdata( - &pfjob->context_cpy.scene->id, adt, seq_prefetch_cfra(pfjob), ADT_RECALC_ALL, false); + &pfjob->context_cpy.scene->id, adt, &anim_eval_context, ADT_RECALC_ALL, false); /* This is quite hacky solution: * We need cross-reference original scene with copy for cache. diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 6921a13e2c2..31ae71622f7 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3361,7 +3361,9 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr /* anim-data */ adt = BKE_animdata_from_id(&mask->id); - BKE_animsys_evaluate_animdata(&mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + context->depsgraph, mask->sfra + nr); + BKE_animsys_evaluate_animdata(&mask_temp->id, adt, &anim_eval_context, ADT_RECALC_ANIM, false); maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__); diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index c72747a8c51..67e9afdf7fa 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -32,6 +32,8 @@ extern "C" { #endif +struct AnimationEvalContext; + /* --------------- NLA Evaluation DataTypes ----------------------- */ /* used for list of strips to accumulate at current time */ @@ -168,13 +170,17 @@ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode); /* these functions are only defined here to avoid problems with the order * in which they get defined. */ -NlaEvalStrip *nlastrips_ctime_get_strip( - ListBase *list, ListBase *strips, short index, float ctime, const bool flush_to_original); +NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, + ListBase *strips, + short index, + const struct AnimationEvalContext *anim_eval_context, + const bool flush_to_original); void nlastrip_evaluate(PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, + const struct AnimationEvalContext *anim_eval_context, const bool flush_to_original); void nladata_flush_channels(PointerRNA *ptr, NlaEvalData *channels, diff --git a/source/blender/blenlib/BLI_allocator.hh b/source/blender/blenlib/BLI_allocator.hh index d57703f71bc..d49b98cb33b 100644 --- a/source/blender/blenlib/BLI_allocator.hh +++ b/source/blender/blenlib/BLI_allocator.hh @@ -84,8 +84,8 @@ class RawAllocator { void *ptr = malloc(size + alignment + sizeof(MemHead)); void *used_ptr = (void *)((uintptr_t)POINTER_OFFSET(ptr, alignment + sizeof(MemHead)) & ~((uintptr_t)alignment - 1)); - uint offset = (uint)((uintptr_t)used_ptr - (uintptr_t)ptr); - BLI_assert(offset >= sizeof(MemHead)); + int offset = (int)((uintptr_t)used_ptr - (uintptr_t)ptr); + BLI_assert((size_t)offset >= sizeof(MemHead)); ((MemHead *)used_ptr - 1)->offset = (int)offset; return used_ptr; } diff --git a/source/blender/blenlib/BLI_array.hh b/source/blender/blenlib/BLI_array.hh index c411fc50f15..c7b4bdc977f 100644 --- a/source/blender/blenlib/BLI_array.hh +++ b/source/blender/blenlib/BLI_array.hh @@ -13,6 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #ifndef __BLI_ARRAY_HH__ #define __BLI_ARRAY_HH__ @@ -52,11 +53,8 @@ template< typename T, /** * The number of values that can be stored in the array, without doing a heap allocation. - * - * When T is large, the small buffer optimization is disabled by default to avoid large - * unexpected allocations on the stack. It can still be enabled explicitly though. */ - uint InlineBufferCapacity = (sizeof(T) < 100) ? 4 : 0, + int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T)), /** * The allocator used by this array. Should rarely be changed, except when you don't want that * MEM_* functions are used internally. @@ -68,7 +66,7 @@ class Array { T *data_; /** Number of elements in the array. */ - uint size_; + int64_t size_; /** Used for allocations when the inline buffer is too small. */ Allocator allocator_; @@ -117,7 +115,7 @@ class Array { * even for non-trivial types. This should not be the default though, because one can easily mess * up when dealing with uninitialized memory. */ - explicit Array(uint size) + explicit Array(int64_t size) { size_ = size; data_ = this->get_buffer_for_size(size); @@ -128,8 +126,9 @@ class Array { * Create a new array with the given size. All values will be initialized by copying the given * default. */ - Array(uint size, const T &value) + Array(int64_t size, const T &value) { + BLI_assert(size >= 0); size_ = size; data_ = this->get_buffer_for_size(size); uninitialized_fill_n(data_, size_, value); @@ -147,8 +146,9 @@ class Array { * Usage: * Array<std::string> my_strings(10, NoInitialization()); */ - Array(uint size, NoInitialization) + Array(int64_t size, NoInitialization) { + BLI_assert(size >= 0); size_ = size; data_ = this->get_buffer_for_size(size); } @@ -203,14 +203,16 @@ class Array { return *this; } - T &operator[](uint index) + T &operator[](int64_t index) { + BLI_assert(index >= 0); BLI_assert(index < size_); return data_[index]; } - const T &operator[](uint index) const + const T &operator[](int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index < size_); return data_[index]; } @@ -250,7 +252,7 @@ class Array { /** * Returns the number of elements in the array. */ - uint size() const + int64_t size() const { return size_; } @@ -264,22 +266,14 @@ class Array { } /** - * Copies the value to all indices in the array. + * Copies the given value to every element in the array. */ - void fill(const T &value) + void fill(const T &value) const { initialized_fill_n(data_, size_, value); } /** - * Copies the value to the given indices in the array. - */ - void fill_indices(Span<uint> indices, const T &value) - { - MutableSpan<T>(*this).fill_indices(indices, value); - } - - /** * Get a pointer to the beginning of the array. */ const T *data() const @@ -340,13 +334,13 @@ class Array { * Get the value of the InlineBufferCapacity template argument. This is the number of elements * that can be stored without doing an allocation. */ - static uint inline_buffer_capacity() + static int64_t inline_buffer_capacity() { return InlineBufferCapacity; } private: - T *get_buffer_for_size(uint size) + T *get_buffer_for_size(int64_t size) { if (size <= InlineBufferCapacity) { return inline_buffer_; @@ -356,9 +350,9 @@ class Array { } } - T *allocate(uint size) + T *allocate(int64_t size) { - return (T *)allocator_.allocate(size * sizeof(T), alignof(T), AT); + return (T *)allocator_.allocate((size_t)size * sizeof(T), alignof(T), AT); } bool uses_inline_buffer() const @@ -367,6 +361,13 @@ class Array { } }; +/** + * Same as a normal Array, but does not use Blender's guarded allocator. This is useful when + * allocating memory with static storage duration. + */ +template<typename T, int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T))> +using RawArray = Array<T, InlineBufferCapacity, RawAllocator>; + } // namespace blender #endif /* __BLI_ARRAY_HH__ */ diff --git a/source/blender/blenlib/BLI_color.hh b/source/blender/blenlib/BLI_color.hh index 265013c0013..72caa5b1118 100644 --- a/source/blender/blenlib/BLI_color.hh +++ b/source/blender/blenlib/BLI_color.hh @@ -62,12 +62,12 @@ struct Color4f { return !(a == b); } - uint32_t hash() const + uint64_t hash() const { - uint32_t x1 = *(uint32_t *)&r; - uint32_t x2 = *(uint32_t *)&g; - uint32_t x3 = *(uint32_t *)&b; - uint32_t x4 = *(uint32_t *)&a; + uint64_t x1 = *(uint32_t *)&r; + uint64_t x2 = *(uint32_t *)&g; + uint64_t x3 = *(uint32_t *)&b; + uint64_t x4 = *(uint32_t *)&a; return (x1 * 1283591) ^ (x2 * 850177) ^ (x3 * 735391) ^ (x4 * 442319); } }; @@ -119,10 +119,10 @@ struct Color4b { return !(a == b); } - uint32_t hash() const + uint64_t hash() const { - return ((uint32_t)r * 1283591) ^ ((uint32_t)g * 850177) ^ ((uint32_t)b * 735391) ^ - ((uint32_t)a * 442319); + return ((uint64_t)r * 1283591) ^ ((uint64_t)g * 850177) ^ ((uint64_t)b * 735391) ^ + ((uint64_t)a * 442319); } }; diff --git a/source/blender/blenlib/BLI_disjoint_set.hh b/source/blender/blenlib/BLI_disjoint_set.hh index 3b8453669aa..e0580709a44 100644 --- a/source/blender/blenlib/BLI_disjoint_set.hh +++ b/source/blender/blenlib/BLI_disjoint_set.hh @@ -29,16 +29,17 @@ namespace blender { class DisjointSet { private: - Array<uint> parents_; - Array<uint> ranks_; + Array<int64_t> parents_; + Array<int64_t> ranks_; public: /** * Create a new disjoint set with the given size. Initially, every element is in a separate set. */ - DisjointSet(uint size) : parents_(size), ranks_(size, 0) + DisjointSet(int64_t size) : parents_(size), ranks_(size, 0) { - for (uint i = 0; i < size; i++) { + BLI_assert(size >= 0); + for (int64_t i = 0; i < size; i++) { parents_[i] = i; } } @@ -47,10 +48,10 @@ class DisjointSet { * Join the sets containing elements x and y. Nothing happens when they have been in the same set * before. */ - void join(uint x, uint y) + void join(int64_t x, int64_t y) { - uint root1 = this->find_root(x); - uint root2 = this->find_root(y); + int64_t root1 = this->find_root(x); + int64_t root2 = this->find_root(y); /* x and y are in the same set already. */ if (root1 == root2) { @@ -71,27 +72,27 @@ class DisjointSet { /** * Return true when x and y are in the same set. */ - bool in_same_set(uint x, uint y) + bool in_same_set(int64_t x, int64_t y) { - uint root1 = this->find_root(x); - uint root2 = this->find_root(y); + int64_t root1 = this->find_root(x); + int64_t root2 = this->find_root(y); return root1 == root2; } /** * Find the element that represents the set containing x currently. */ - uint find_root(uint x) + int64_t find_root(int64_t x) { /* Find root by following parents. */ - uint root = x; + int64_t root = x; while (parents_[root] != root) { root = parents_[root]; } /* Compress path. */ while (parents_[x] != root) { - uint parent = parents_[x]; + int64_t parent = parents_[x]; parents_[x] = root; x = parent; } diff --git a/source/blender/blenlib/BLI_dot_export.hh b/source/blender/blenlib/BLI_dot_export.hh index a7c5f1436d1..0870d8c4c30 100644 --- a/source/blender/blenlib/BLI_dot_export.hh +++ b/source/blender/blenlib/BLI_dot_export.hh @@ -274,13 +274,13 @@ class NodeWithSocketsRef { return *node_; } - NodePort input(uint index) const + NodePort input(int index) const { std::string port = "\"in" + std::to_string(index) + "\""; return NodePort(*node_, port); } - NodePort output(uint index) const + NodePort output(int index) const { std::string port = "\"out" + std::to_string(index) + "\""; return NodePort(*node_, port); diff --git a/source/blender/blenlib/BLI_float3.hh b/source/blender/blenlib/BLI_float3.hh index a36cedad41d..b2633985ac7 100644 --- a/source/blender/blenlib/BLI_float3.hh +++ b/source/blender/blenlib/BLI_float3.hh @@ -188,11 +188,11 @@ struct float3 { z = -z; } - uint32_t hash() const + uint64_t hash() const { - uint32_t x1 = *(uint32_t *)&x; - uint32_t x2 = *(uint32_t *)&y; - uint32_t x3 = *(uint32_t *)&z; + uint64_t x1 = *(uint32_t *)&x; + uint64_t x2 = *(uint32_t *)&y; + uint64_t x3 = *(uint32_t *)&z; return (x1 * 435109) ^ (x2 * 380867) ^ (x3 * 1059217); } diff --git a/source/blender/blenlib/BLI_float4x4.hh b/source/blender/blenlib/BLI_float4x4.hh index ef83f9ffc19..185cffd13ac 100644 --- a/source/blender/blenlib/BLI_float4x4.hh +++ b/source/blender/blenlib/BLI_float4x4.hh @@ -109,10 +109,10 @@ struct float4x4 { return result; } - uint32_t hash() const + uint64_t hash() const { - uint32_t h = 435109; - for (uint i = 0; i < 16; i++) { + uint64_t h = 435109; + for (int i = 0; i < 16; i++) { float value = ((const float *)this)[i]; h = h * 33 + (*(uint32_t *)&value); } diff --git a/source/blender/blenlib/BLI_hash.hh b/source/blender/blenlib/BLI_hash.hh index 5cd4ce3c1a9..b14a4ca933c 100644 --- a/source/blender/blenlib/BLI_hash.hh +++ b/source/blender/blenlib/BLI_hash.hh @@ -38,7 +38,7 @@ * multiple `operator()` in a specialization of #DefaultHash. All those methods have to compute the * same hash for values that compare equal. * - * The computed hash is an unsigned 32 bit integer. Ideally, the hash function would generate + * The computed hash is an unsigned 64 bit integer. Ideally, the hash function would generate * uniformly random hash values for a set of keys. However, in many cases trivial hash functions * are faster and produce a good enough distribution. In general it is better when more information * is in the lower bits of the hash. By choosing a good probing strategy, the effects of a bad hash @@ -49,7 +49,7 @@ * There are three main ways to provide a hash table implementation with a custom hash function. * * - When you want to provide a default hash function for your own custom type: Add a `hash` - * member function to it. The function should return `uint32_t` and take no arguments. This + * member function to it. The function should return `uint64_t` and take no arguments. This * method will be called by the default implementation of #DefaultHash. It will automatically be * used by hash table implementations. * @@ -58,7 +58,7 @@ * either global or BLI namespace. * * template<> struct blender::DefaultHash<TheType> { - * uint32_t operator()(const TheType &value) const { + * uint64_t operator()(const TheType &value) const { * return ...; * } * }; @@ -68,7 +68,7 @@ * table explicitly. * * struct MyCustomHash { - * uint32_t operator()(const TheType &value) const { + * uint64_t operator()(const TheType &value) const { * return ...; * } * }; @@ -91,7 +91,7 @@ namespace blender { * that you have to implement a hash function using one of three strategies listed above. */ template<typename T> struct DefaultHash { - uint32_t operator()(const T &value) const + uint64_t operator()(const T &value) const { return value.hash(); } @@ -101,7 +101,7 @@ template<typename T> struct DefaultHash { * Use the same hash function for const and non const variants of a type. */ template<typename T> struct DefaultHash<const T> { - uint32_t operator()(const T &value) const + uint64_t operator()(const T &value) const { return DefaultHash<T>{}(value); } @@ -109,9 +109,9 @@ template<typename T> struct DefaultHash<const T> { #define TRIVIAL_DEFAULT_INT_HASH(TYPE) \ template<> struct DefaultHash<TYPE> { \ - uint32_t operator()(TYPE value) const \ + uint64_t operator()(TYPE value) const \ { \ - return (uint32_t)value; \ + return (uint64_t)value; \ } \ } @@ -127,43 +127,29 @@ TRIVIAL_DEFAULT_INT_HASH(int16_t); TRIVIAL_DEFAULT_INT_HASH(uint16_t); TRIVIAL_DEFAULT_INT_HASH(int32_t); TRIVIAL_DEFAULT_INT_HASH(uint32_t); - -template<> struct DefaultHash<uint64_t> { - uint32_t operator()(uint64_t value) const - { - uint32_t low = (uint32_t)value; - uint32_t high = (uint32_t)(value >> 32); - return low ^ (high * 0x45d9f3b); - } -}; - -template<> struct DefaultHash<int64_t> { - uint32_t operator()(uint64_t value) const - { - return DefaultHash<uint64_t>{}((uint64_t)value); - } -}; +TRIVIAL_DEFAULT_INT_HASH(int64_t); +TRIVIAL_DEFAULT_INT_HASH(uint64_t); /** * One should try to avoid using floats as keys in hash tables, but sometimes it is convenient. */ template<> struct DefaultHash<float> { - uint32_t operator()(float value) const + uint64_t operator()(float value) const { return *(uint32_t *)&value; } }; template<> struct DefaultHash<bool> { - uint32_t operator()(bool value) const + uint64_t operator()(bool value) const { - return (uint32_t)(value != false) * 1298191; + return (uint64_t)(value != false) * 1298191; } }; -inline uint32_t hash_string(StringRef str) +inline uint64_t hash_string(StringRef str) { - uint32_t hash = 5381; + uint64_t hash = 5381; for (char c : str) { hash = hash * 33 + c; } @@ -175,21 +161,21 @@ template<> struct DefaultHash<std::string> { * Take a #StringRef as parameter to support heterogeneous lookups in hash table implementations * when std::string is used as key. */ - uint32_t operator()(StringRef value) const + uint64_t operator()(StringRef value) const { return hash_string(value); } }; template<> struct DefaultHash<StringRef> { - uint32_t operator()(StringRef value) const + uint64_t operator()(StringRef value) const { return hash_string(value); } }; template<> struct DefaultHash<StringRefNull> { - uint32_t operator()(StringRef value) const + uint64_t operator()(StringRef value) const { return hash_string(value); } @@ -199,26 +185,26 @@ template<> struct DefaultHash<StringRefNull> { * While we cannot guarantee that the lower 4 bits of a pointer are zero, it is often the case. */ template<typename T> struct DefaultHash<T *> { - uint32_t operator()(const T *value) const + uint64_t operator()(const T *value) const { uintptr_t ptr = (uintptr_t)value; - uint32_t hash = (uint32_t)(ptr >> 4); + uint64_t hash = (uint64_t)(ptr >> 4); return hash; } }; template<typename T> struct DefaultHash<std::unique_ptr<T>> { - uint32_t operator()(const std::unique_ptr<T> &value) const + uint64_t operator()(const std::unique_ptr<T> &value) const { return DefaultHash<T *>{}(value.get()); } }; template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> { - uint32_t operator()(const std::pair<T1, T2> &value) const + uint64_t operator()(const std::pair<T1, T2> &value) const { - uint32_t hash1 = DefaultHash<T1>{}(value.first); - uint32_t hash2 = DefaultHash<T2>{}(value.second); + uint64_t hash1 = DefaultHash<T1>{}(value.first); + uint64_t hash2 = DefaultHash<T2>{}(value.second); return hash1 ^ (hash2 * 33); } }; diff --git a/source/blender/blenlib/BLI_hash_tables.hh b/source/blender/blenlib/BLI_hash_tables.hh index aaed772071d..5d8f8862a09 100644 --- a/source/blender/blenlib/BLI_hash_tables.hh +++ b/source/blender/blenlib/BLI_hash_tables.hh @@ -42,59 +42,64 @@ namespace blender { * Those should eventually be de-duplicated with functions in BLI_math_base.h. * \{ */ -inline constexpr int is_power_of_2_i_constexpr(const int n) +inline constexpr int64_t is_power_of_2_constexpr(const int64_t x) { - return (n & (n - 1)) == 0; + BLI_assert(x >= 0); + return (x & (x - 1)) == 0; } -inline constexpr uint32_t log2_floor_u_constexpr(const uint32_t x) +inline constexpr int64_t log2_floor_constexpr(const int64_t x) { - return x <= 1 ? 0 : 1 + log2_floor_u_constexpr(x >> 1); + BLI_assert(x >= 0); + return x <= 1 ? 0 : 1 + log2_floor_constexpr(x >> 1); } -inline constexpr uint32_t log2_ceil_u_constexpr(const uint32_t x) +inline constexpr int64_t log2_ceil_constexpr(const int64_t x) { - return (is_power_of_2_i_constexpr((int)x)) ? log2_floor_u_constexpr(x) : - log2_floor_u_constexpr(x) + 1; + BLI_assert(x >= 0); + return (is_power_of_2_constexpr((int)x)) ? log2_floor_constexpr(x) : log2_floor_constexpr(x) + 1; } -inline constexpr uint32_t power_of_2_max_u_constexpr(const uint32_t x) +inline constexpr int64_t power_of_2_max_constexpr(const int64_t x) { - return 1u << log2_ceil_u_constexpr(x); + BLI_assert(x >= 0); + return 1ll << log2_ceil_constexpr(x); } template<typename IntT> inline constexpr IntT ceil_division(const IntT x, const IntT y) { - BLI_STATIC_ASSERT(!std::is_signed_v<IntT>, ""); + BLI_assert(x >= 0); + BLI_assert(y >= 0); return x / y + ((x % y) != 0); } template<typename IntT> inline constexpr IntT floor_division(const IntT x, const IntT y) { - BLI_STATIC_ASSERT(!std::is_signed_v<IntT>, ""); + BLI_assert(x >= 0); + BLI_assert(y >= 0); return x / y; } -inline constexpr uint32_t ceil_division_by_fraction(const uint32_t x, - const uint32_t numerator, - const uint32_t denominator) +inline constexpr int64_t ceil_division_by_fraction(const int64_t x, + const int64_t numerator, + const int64_t denominator) { - return (uint32_t)ceil_division((uint64_t)x * (uint64_t)denominator, (uint64_t)numerator); + return (int64_t)ceil_division((uint64_t)x * (uint64_t)denominator, (uint64_t)numerator); } -inline constexpr uint32_t floor_multiplication_with_fraction(const uint32_t x, - const uint32_t numerator, - const uint32_t denominator) +inline constexpr int64_t floor_multiplication_with_fraction(const int64_t x, + const int64_t numerator, + const int64_t denominator) { - return (uint32_t)((uint64_t)x * (uint64_t)numerator / (uint64_t)denominator); + return (int64_t)((uint64_t)x * (uint64_t)numerator / (uint64_t)denominator); } -inline constexpr uint32_t total_slot_amount_for_usable_slots( - const uint32_t min_usable_slots, - const uint32_t max_load_factor_numerator, - const uint32_t max_load_factor_denominator) +inline constexpr int64_t total_slot_amount_for_usable_slots( + const int64_t min_usable_slots, + const int64_t max_load_factor_numerator, + const int64_t max_load_factor_denominator) { - return power_of_2_max_u_constexpr(ceil_division_by_fraction( + return power_of_2_max_constexpr(ceil_division_by_fraction( min_usable_slots, max_load_factor_numerator, max_load_factor_denominator)); } @@ -121,16 +126,16 @@ class LoadFactor { BLI_assert(numerator < denominator); } - void compute_total_and_usable_slots(uint32_t min_total_slots, - uint32_t min_usable_slots, - uint32_t *r_total_slots, - uint32_t *r_usable_slots) const + void compute_total_and_usable_slots(int64_t min_total_slots, + int64_t min_usable_slots, + int64_t *r_total_slots, + int64_t *r_usable_slots) const { BLI_assert(is_power_of_2_i((int)min_total_slots)); - uint32_t total_slots = this->compute_total_slots(min_usable_slots, numerator_, denominator_); + int64_t total_slots = this->compute_total_slots(min_usable_slots, numerator_, denominator_); total_slots = std::max(total_slots, min_total_slots); - const uint32_t usable_slots = floor_multiplication_with_fraction( + const int64_t usable_slots = floor_multiplication_with_fraction( total_slots, numerator_, denominator_); BLI_assert(min_usable_slots <= usable_slots); @@ -138,9 +143,9 @@ class LoadFactor { *r_usable_slots = usable_slots; } - static constexpr uint32_t compute_total_slots(uint32_t min_usable_slots, - uint8_t numerator, - uint8_t denominator) + static constexpr int64_t compute_total_slots(int64_t min_usable_slots, + uint8_t numerator, + uint8_t denominator) { return total_slot_amount_for_usable_slots(min_usable_slots, numerator, denominator); } @@ -262,27 +267,27 @@ template<typename Pointer> struct PointerKeyInfo { class HashTableStats { private: - Vector<uint32_t> keys_by_collision_count_; - uint32_t total_collisions_; + Vector<int64_t> keys_by_collision_count_; + int64_t total_collisions_; float average_collisions_; - uint32_t size_; - uint32_t capacity_; - uint32_t removed_amount_; + int64_t size_; + int64_t capacity_; + int64_t removed_amount_; float load_factor_; float removed_load_factor_; - uint32_t size_per_element_; - uint32_t size_in_bytes_; + int64_t size_per_element_; + int64_t size_in_bytes_; const void *address_; public: /** * Requires that the hash table has the following methods: - * - count_collisions(key) -> uint32_t - * - size() -> uint32_t - * - capacity() -> uint32_t - * - removed_amount() -> uint32_t - * - size_per_element() -> uint32_t - * - size_in_bytes() -> uint32_t + * - count_collisions(key) -> int64_t + * - size() -> int64_t + * - capacity() -> int64_t + * - removed_amount() -> int64_t + * - size_per_element() -> int64_t + * - size_in_bytes() -> int64_t */ template<typename HashTable, typename Keys> HashTableStats(const HashTable &hash_table, const Keys &keys) @@ -296,7 +301,7 @@ class HashTableStats { address_ = (const void *)&hash_table; for (const auto &key : keys) { - uint32_t collisions = hash_table.count_collisions(key); + int64_t collisions = hash_table.count_collisions(key); if (keys_by_collision_count_.size() <= collisions) { keys_by_collision_count_.append_n_times(0, collisions - keys_by_collision_count_.size() + 1); @@ -325,7 +330,7 @@ class HashTableStats { std::cout << " Size per Slot: " << size_per_element_ << " bytes\n"; std::cout << " Average Collisions: " << average_collisions_ << "\n"; - for (uint32_t collision_count : keys_by_collision_count_.index_range()) { + for (int64_t collision_count : keys_by_collision_count_.index_range()) { std::cout << " " << collision_count << " Collisions: " << keys_by_collision_count_[collision_count] << "\n"; } diff --git a/source/blender/blenlib/BLI_index_mask.hh b/source/blender/blenlib/BLI_index_mask.hh index 93bbb269d30..ff271faa0c2 100644 --- a/source/blender/blenlib/BLI_index_mask.hh +++ b/source/blender/blenlib/BLI_index_mask.hh @@ -46,7 +46,7 @@ namespace blender { class IndexMask { private: /* The underlying reference to sorted integers. */ - Span<uint> indices_; + Span<int64_t> indices_; public: /* Creates an IndexMask that contains no indices. */ @@ -57,10 +57,10 @@ class IndexMask { * This constructor asserts that the given integers are in ascending order and that there are no * duplicates. */ - IndexMask(Span<uint> indices) : indices_(indices) + IndexMask(Span<int64_t> indices) : indices_(indices) { #ifdef DEBUG - for (uint i = 1; i < indices.size(); i++) { + for (int64_t i = 1; i < indices.size(); i++) { BLI_assert(indices[i - 1] < indices[i]); } #endif @@ -84,28 +84,28 @@ class IndexMask { * Do this: * do_something_with_an_index_mask({3, 4, 5}); */ - IndexMask(const std::initializer_list<uint> &indices) : IndexMask(Span<uint>(indices)) + IndexMask(const std::initializer_list<int64_t> &indices) : IndexMask(Span<int64_t>(indices)) { } /** * Creates an IndexMask that references the indices [0, n-1]. */ - explicit IndexMask(uint n) : IndexMask(IndexRange(n)) + explicit IndexMask(int64_t n) : IndexMask(IndexRange(n)) { } - operator Span<uint>() const + operator Span<int64_t>() const { return indices_; } - const uint *begin() const + const int64_t *begin() const { return indices_.begin(); } - const uint *end() const + const int64_t *end() const { return indices_.end(); } @@ -114,7 +114,7 @@ class IndexMask { * Returns the n-th index referenced by this IndexMask. The `index_mask` method returns an * IndexRange containing all indices that can be used as parameter here. */ - uint operator[](uint n) const + int64_t operator[](int64_t n) const { return indices_[n]; } @@ -123,7 +123,7 @@ class IndexMask { * Returns the minimum size an array has to have, if the integers in this IndexMask are going to * be used as indices in that array. */ - uint min_array_size() const + int64_t min_array_size() const { if (indices_.size() == 0) { return 0; @@ -133,7 +133,7 @@ class IndexMask { } } - Span<uint> indices() const + Span<int64_t> indices() const { return indices_; } @@ -167,12 +167,12 @@ class IndexMask { { if (this->is_range()) { IndexRange range = this->as_range(); - for (uint i : range) { + for (int64_t i : range) { callback(i); } } else { - for (uint i : indices_) { + for (int64_t i : indices_) { callback(i); } } @@ -193,7 +193,7 @@ class IndexMask { /** * Returns the largest index that is referenced by this IndexMask. */ - uint last() const + int64_t last() const { return indices_.last(); } @@ -201,7 +201,7 @@ class IndexMask { /** * Returns the number of indices referenced by this IndexMask. */ - uint size() const + int64_t size() const { return indices_.size(); } diff --git a/source/blender/blenlib/BLI_index_range.hh b/source/blender/blenlib/BLI_index_range.hh index 1ae08e834ae..7c813f58b2c 100644 --- a/source/blender/blenlib/BLI_index_range.hh +++ b/source/blender/blenlib/BLI_index_range.hh @@ -27,29 +27,29 @@ * I'd argue that the second loop is more readable and less error prone than the first one. That is * not necessarily always the case, but often it is. * - * for (uint i = 0; i < 10; i++) { - * for (uint j = 0; j < 20; j++) { - * for (uint k = 0; k < 30; k++) { + * for (int64_t i = 0; i < 10; i++) { + * for (int64_t j = 0; j < 20; j++) { + * for (int64_t k = 0; k < 30; k++) { * - * for (uint i : IndexRange(10)) { - * for (uint j : IndexRange(20)) { - * for (uint k : IndexRange(30)) { + * for (int64_t i : IndexRange(10)) { + * for (int64_t j : IndexRange(20)) { + * for (int64_t k : IndexRange(30)) { * * Some containers like blender::Vector have an index_range() method. This will return the * IndexRange that contains all indices that can be used to access the container. This is * particularly useful when you want to iterate over the indices and the elements (much like * Python's enumerate(), just worse). Again, I think the second example here is better: * - * for (uint i = 0; i < my_vector_with_a_long_name.size(); i++) { + * for (int64_t i = 0; i < my_vector_with_a_long_name.size(); i++) { * do_something(i, my_vector_with_a_long_name[i]); * - * for (uint i : my_vector_with_a_long_name.index_range()) { + * for (int64_t i : my_vector_with_a_long_name.index_range()) { * do_something(i, my_vector_with_a_long_name[i]); * * Ideally this could be could be even closer to Python's enumerate(). We might get that in the * future with newer C++ versions. * - * One other important feature is the as_span method. This method returns an Span<uint> + * One other important feature is the as_span method. This method returns an Span<int64_t> * that contains the interval as individual numbers. */ @@ -70,18 +70,21 @@ template<typename T> class Span; class IndexRange { private: - uint start_ = 0; - uint size_ = 0; + int64_t start_ = 0; + int64_t size_ = 0; public: IndexRange() = default; - explicit IndexRange(uint size) : start_(0), size_(size) + explicit IndexRange(int64_t size) : start_(0), size_(size) { + BLI_assert(size >= 0); } - IndexRange(uint start, uint size) : start_(start), size_(size) + IndexRange(int64_t start, int64_t size) : start_(start), size_(size) { + BLI_assert(start >= 0); + BLI_assert(size >= 0); } template<typename T> @@ -91,10 +94,10 @@ class IndexRange { class Iterator { private: - uint current_; + int64_t current_; public: - Iterator(uint current) : current_(current) + Iterator(int64_t current) : current_(current) { } @@ -109,7 +112,7 @@ class IndexRange { return current_ != iterator.current_; } - uint operator*() const + int64_t operator*() const { return current_; } @@ -128,8 +131,9 @@ class IndexRange { /** * Access an element in the range. */ - uint operator[](uint index) const + int64_t operator[](int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index < this->size()); return start_ + index; } @@ -145,7 +149,7 @@ class IndexRange { /** * Get the amount of numbers in the range. */ - uint size() const + int64_t size() const { return size_; } @@ -153,16 +157,18 @@ class IndexRange { /** * Create a new range starting at the end of the current one. */ - IndexRange after(uint n) const + IndexRange after(int64_t n) const { + BLI_assert(n >= 0); return IndexRange(start_ + size_, n); } /** * Create a new range that ends at the start of the current one. */ - IndexRange before(uint n) const + IndexRange before(int64_t n) const { + BLI_assert(n >= 0); return IndexRange(start_ - n, n); } @@ -170,7 +176,7 @@ class IndexRange { * Get the first element in the range. * Asserts when the range is empty. */ - uint first() const + int64_t first() const { BLI_assert(this->size() > 0); return start_; @@ -180,7 +186,7 @@ class IndexRange { * Get the last element in the range. * Asserts when the range is empty. */ - uint last() const + int64_t last() const { BLI_assert(this->size() > 0); return start_ + size_ - 1; @@ -189,7 +195,7 @@ class IndexRange { /** * Get the element one after the end. The returned value is undefined when the range is empty. */ - uint one_after_last() const + int64_t one_after_last() const { return start_ + size_; } @@ -197,7 +203,7 @@ class IndexRange { /** * Get the first element in the range. The returned value is undefined when the range is empty. */ - uint start() const + int64_t start() const { return start_; } @@ -205,7 +211,7 @@ class IndexRange { /** * Returns true when the range contains a certain number, otherwise false. */ - bool contains(uint value) const + bool contains(int64_t value) const { return value >= start_ && value < start_ + size_; } @@ -213,9 +219,11 @@ class IndexRange { /** * Returns a new range, that contains a sub-interval of the current one. */ - IndexRange slice(uint start, uint size) const + IndexRange slice(int64_t start, int64_t size) const { - uint new_start = start_ + start; + BLI_assert(start >= 0); + BLI_assert(size >= 0); + int64_t new_start = start_ + start; BLI_assert(new_start + size <= start_ + size_ || size == 0); return IndexRange(new_start, size); } @@ -227,7 +235,7 @@ class IndexRange { /** * Get read-only access to a memory buffer that contains the range as actual numbers. */ - Span<uint> as_span() const; + Span<int64_t> as_span() const; friend std::ostream &operator<<(std::ostream &stream, IndexRange range) { diff --git a/source/blender/blenlib/BLI_linear_allocator.hh b/source/blender/blenlib/BLI_linear_allocator.hh index b13d88d5b93..39a3ed27f42 100644 --- a/source/blender/blenlib/BLI_linear_allocator.hh +++ b/source/blender/blenlib/BLI_linear_allocator.hh @@ -39,10 +39,10 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya uintptr_t current_begin_; uintptr_t current_end_; - uint next_min_alloc_size_; + int64_t next_min_alloc_size_; #ifdef DEBUG - uint debug_allocated_amount_ = 0; + int64_t debug_allocated_amount_ = 0; #endif public: @@ -66,8 +66,9 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya * * The alignment has to be a power of 2. */ - void *allocate(const uint size, const uint alignment) + void *allocate(const int64_t size, const int64_t alignment) { + BLI_assert(size >= 0); BLI_assert(alignment >= 1); BLI_assert(is_power_of_2_i(alignment)); @@ -105,7 +106,7 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya * * This method only allocates memory and does not construct the instance. */ - template<typename T> MutableSpan<T> allocate_array(uint size) + template<typename T> MutableSpan<T> allocate_array(int64_t size) { return MutableSpan<T>((T *)this->allocate(sizeof(T) * size, alignof(T)), size); } @@ -141,22 +142,22 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya */ StringRefNull copy_string(StringRef str) { - const uint alloc_size = str.size() + 1; + const int64_t alloc_size = str.size() + 1; char *buffer = (char *)this->allocate(alloc_size, 1); str.copy(buffer, alloc_size); return StringRefNull((const char *)buffer); } - MutableSpan<void *> allocate_elements_and_pointer_array(uint element_amount, - uint element_size, - uint element_alignment) + MutableSpan<void *> allocate_elements_and_pointer_array(int64_t element_amount, + int64_t element_size, + int64_t element_alignment) { void *pointer_buffer = this->allocate(element_amount * sizeof(void *), alignof(void *)); void *elements_buffer = this->allocate(element_amount * element_size, element_alignment); MutableSpan<void *> pointers((void **)pointer_buffer, element_amount); void *next_element_buffer = elements_buffer; - for (uint i : IndexRange(element_amount)) { + for (int64_t i : IndexRange(element_amount)) { pointers[i] = next_element_buffer; next_element_buffer = POINTER_OFFSET(next_element_buffer, element_size); } @@ -165,13 +166,13 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya } template<typename T, typename... Args> - Span<T *> construct_elements_and_pointer_array(uint n, Args &&... args) + Span<T *> construct_elements_and_pointer_array(int64_t n, Args &&... args) { MutableSpan<void *> void_pointers = this->allocate_elements_and_pointer_array( n, sizeof(T), alignof(T)); MutableSpan<T *> pointers = void_pointers.cast<T *>(); - for (uint i : IndexRange(n)) { + for (int64_t i : IndexRange(n)) { new ((void *)pointers[i]) T(std::forward<Args>(args)...); } @@ -194,9 +195,9 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya } private: - void allocate_new_buffer(uint min_allocation_size) + void allocate_new_buffer(int64_t min_allocation_size) { - for (uint i : unused_borrowed_buffers_.index_range()) { + for (int64_t i : unused_borrowed_buffers_.index_range()) { Span<char> buffer = unused_borrowed_buffers_[i]; if (buffer.size() >= min_allocation_size) { unused_borrowed_buffers_.remove_and_reorder(i); @@ -206,7 +207,7 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya } } - const uint size_in_bytes = power_of_2_min_u( + const int64_t size_in_bytes = power_of_2_min_u( std::max(min_allocation_size, next_min_alloc_size_)); next_min_alloc_size_ = size_in_bytes * 2; diff --git a/source/blender/blenlib/BLI_listbase_wrapper.hh b/source/blender/blenlib/BLI_listbase_wrapper.hh index 047099eb36e..46f4a9d49fa 100644 --- a/source/blender/blenlib/BLI_listbase_wrapper.hh +++ b/source/blender/blenlib/BLI_listbase_wrapper.hh @@ -96,9 +96,9 @@ template<typename T> class ListBaseWrapper { return (T *)ptr; } - uint index_of(const T *value) const + int64_t index_of(const T *value) const { - uint index = 0; + int64_t index = 0; for (T *ptr : *this) { if (ptr == value) { return index; @@ -106,7 +106,7 @@ template<typename T> class ListBaseWrapper { index++; } BLI_assert(false); - return 0; + return -1; } }; diff --git a/source/blender/blenlib/BLI_map.hh b/source/blender/blenlib/BLI_map.hh index 6bbd4ee09db..dd375272fdb 100644 --- a/source/blender/blenlib/BLI_map.hh +++ b/source/blender/blenlib/BLI_map.hh @@ -92,11 +92,8 @@ template< * The minimum number of elements that can be stored in this Map without doing a heap * allocation. This is useful when you expect to have many small maps. However, keep in mind * that (unlike vector) initializing a map has a O(n) cost in the number of slots. - * - * When Key or Value are large, the small buffer optimization is disabled by default to avoid - * large unexpected allocations on the stack. It can still be enabled explicitly though. */ - uint32_t InlineBufferCapacity = (sizeof(Key) + sizeof(Value) < 100) ? 4 : 0, + int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key) + sizeof(Value)), /** * The strategy used to deal with collisions. They are defined in BLI_probing_strategies.hh. */ @@ -129,20 +126,20 @@ class Map { * Slots are either empty, occupied or removed. The number of occupied slots can be computed by * subtracting the removed slots from the occupied-and-removed slots. */ - uint32_t removed_slots_; - uint32_t occupied_and_removed_slots_; + int64_t removed_slots_; + int64_t occupied_and_removed_slots_; /** * The maximum number of slots that can be used (either occupied or removed) until the set has to * grow. This is the total number of slots times the max load factor. */ - uint32_t usable_slots_; + int64_t usable_slots_; /** * The number of slots minus one. This is a bit mask that can be used to turn any integer into a * valid slot index efficiently. */ - uint32_t slot_mask_; + uint64_t slot_mask_; /** This is called to hash incoming keys. */ Hash hash_; @@ -577,8 +574,8 @@ class Map { */ template<typename FuncT> void foreach_item(const FuncT &func) const { - uint32_t size = slots_.size(); - for (uint32_t i = 0; i < size; i++) { + int64_t size = slots_.size(); + for (int64_t i = 0; i < size; i++) { const Slot &slot = slots_[i]; if (slot.is_occupied()) { const Key &key = *slot.key(); @@ -594,10 +591,10 @@ class Map { */ template<typename SubIterator> struct BaseIterator { Slot *slots_; - uint32_t total_slots_; - uint32_t current_slot_; + int64_t total_slots_; + int64_t current_slot_; - BaseIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot) + BaseIterator(const Slot *slots, int64_t total_slots, int64_t current_slot) : slots_(const_cast<Slot *>(slots)), total_slots_(total_slots), current_slot_(current_slot) { } @@ -621,7 +618,7 @@ class Map { SubIterator begin() const { - for (uint32_t i = 0; i < total_slots_; i++) { + for (int64_t i = 0; i < total_slots_; i++) { if (slots_[i].is_occupied()) { return SubIterator(slots_, total_slots_, i); } @@ -642,7 +639,7 @@ class Map { class KeyIterator final : public BaseIterator<KeyIterator> { public: - KeyIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot) + KeyIterator(const Slot *slots, int64_t total_slots, int64_t current_slot) : BaseIterator<KeyIterator>(slots, total_slots, current_slot) { } @@ -655,7 +652,7 @@ class Map { class ValueIterator final : public BaseIterator<ValueIterator> { public: - ValueIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot) + ValueIterator(const Slot *slots, int64_t total_slots, int64_t current_slot) : BaseIterator<ValueIterator>(slots, total_slots, current_slot) { } @@ -668,7 +665,7 @@ class Map { class MutableValueIterator final : public BaseIterator<MutableValueIterator> { public: - MutableValueIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot) + MutableValueIterator(const Slot *slots, int64_t total_slots, int64_t current_slot) : BaseIterator<MutableValueIterator>(slots, total_slots, current_slot) { } @@ -696,7 +693,7 @@ class Map { class ItemIterator final : public BaseIterator<ItemIterator> { public: - ItemIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot) + ItemIterator(const Slot *slots, int64_t total_slots, int64_t current_slot) : BaseIterator<ItemIterator>(slots, total_slots, current_slot) { } @@ -710,7 +707,7 @@ class Map { class MutableItemIterator final : public BaseIterator<MutableItemIterator> { public: - MutableItemIterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot) + MutableItemIterator(const Slot *slots, int64_t total_slots, int64_t current_slot) : BaseIterator<MutableItemIterator>(slots, total_slots, current_slot) { } @@ -783,7 +780,7 @@ class Map { /** * Return the number of key-value-pairs that are stored in the map. */ - uint32_t size() const + int64_t size() const { return occupied_and_removed_slots_ - removed_slots_; } @@ -801,7 +798,7 @@ class Map { /** * Returns the number of available slots. This is mostly for debugging purposes. */ - uint32_t capacity() const + int64_t capacity() const { return slots_.size(); } @@ -809,7 +806,7 @@ class Map { /** * Returns the amount of removed slots in the set. This is mostly for debugging purposes. */ - uint32_t removed_amount() const + int64_t removed_amount() const { return removed_slots_; } @@ -817,7 +814,7 @@ class Map { /** * Returns the bytes required per element. This is mostly for debugging purposes. */ - uint32_t size_per_element() const + int64_t size_per_element() const { return sizeof(Slot); } @@ -826,16 +823,16 @@ class Map { * Returns the approximate memory requirements of the map in bytes. This becomes more exact the * larger the map becomes. */ - uint32_t size_in_bytes() const + int64_t size_in_bytes() const { - return (uint32_t)(sizeof(Slot) * slots_.size()); + return (int64_t)(sizeof(Slot) * slots_.size()); } /** * Potentially resize the map such that the specified number of elements can be added without * another grow operation. */ - void reserve(uint32_t n) + void reserve(int64_t n) { if (usable_slots_ < n) { this->realloc_and_reinsert(n); @@ -855,18 +852,19 @@ class Map { * Get the number of collisions that the probing strategy has to go through to find the key or * determine that it is not in the map. */ - uint32_t count_collisions(const Key &key) const + int64_t count_collisions(const Key &key) const { return this->count_collisions__impl(key, hash_(key)); } private: - BLI_NOINLINE void realloc_and_reinsert(uint32_t min_usable_slots) + BLI_NOINLINE void realloc_and_reinsert(int64_t min_usable_slots) { - uint32_t total_slots, usable_slots; + int64_t total_slots, usable_slots; max_load_factor_.compute_total_and_usable_slots( SlotArray::inline_buffer_capacity(), min_usable_slots, &total_slots, &usable_slots); - uint32_t new_slot_mask = total_slots - 1; + BLI_assert(total_slots >= 1); + const uint64_t new_slot_mask = (uint64_t)total_slots - 1; /** * Optimize the case when the map was empty beforehand. We can avoid some copies here. @@ -901,9 +899,9 @@ class Map { void add_after_grow_and_destruct_old(Slot &old_slot, SlotArray &new_slots, - uint32_t new_slot_mask) + uint64_t new_slot_mask) { - uint32_t hash = old_slot.get_hash(Hash()); + uint64_t hash = old_slot.get_hash(Hash()); SLOT_PROBING_BEGIN (ProbingStrategy, hash, new_slot_mask, slot_index) { Slot &slot = new_slots[slot_index]; if (slot.is_empty()) { @@ -914,7 +912,7 @@ class Map { SLOT_PROBING_END(); } - template<typename ForwardKey> bool contains__impl(const ForwardKey &key, uint32_t hash) const + template<typename ForwardKey> bool contains__impl(const ForwardKey &key, uint64_t hash) const { MAP_SLOT_PROBING_BEGIN (hash, slot) { if (slot.is_empty()) { @@ -928,7 +926,7 @@ class Map { } template<typename ForwardKey, typename ForwardValue> - void add_new__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash) + void add_new__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash) { BLI_assert(!this->contains_as(key)); @@ -945,7 +943,7 @@ class Map { } template<typename ForwardKey, typename ForwardValue> - bool add__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash) + bool add__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash) { this->ensure_can_add(); @@ -962,7 +960,7 @@ class Map { MAP_SLOT_PROBING_END(); } - template<typename ForwardKey> bool remove__impl(const ForwardKey &key, uint32_t hash) + template<typename ForwardKey> bool remove__impl(const ForwardKey &key, uint64_t hash) { MAP_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash)) { @@ -977,7 +975,7 @@ class Map { MAP_SLOT_PROBING_END(); } - template<typename ForwardKey> void remove_contained__impl(const ForwardKey &key, uint32_t hash) + template<typename ForwardKey> void remove_contained__impl(const ForwardKey &key, uint64_t hash) { BLI_assert(this->contains_as(key)); @@ -992,7 +990,7 @@ class Map { MAP_SLOT_PROBING_END(); } - template<typename ForwardKey> Value pop__impl(const ForwardKey &key, uint32_t hash) + template<typename ForwardKey> Value pop__impl(const ForwardKey &key, uint64_t hash) { BLI_assert(this->contains_as(key)); @@ -1009,7 +1007,7 @@ class Map { } template<typename ForwardKey> - std::optional<Value> pop_try__impl(const ForwardKey &key, uint32_t hash) + std::optional<Value> pop_try__impl(const ForwardKey &key, uint64_t hash) { MAP_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash)) { @@ -1026,7 +1024,7 @@ class Map { } template<typename ForwardKey, typename ForwardValue> - Value pop_default__impl(const ForwardKey &key, ForwardValue &&default_value, uint32_t hash) + Value pop_default__impl(const ForwardKey &key, ForwardValue &&default_value, uint64_t hash) { MAP_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash)) { @@ -1046,7 +1044,7 @@ class Map { auto add_or_modify__impl(ForwardKey &&key, const CreateValueF &create_value, const ModifyValueF &modify_value, - uint32_t hash) -> decltype(create_value(nullptr)) + uint64_t hash) -> decltype(create_value(nullptr)) { using CreateReturnT = decltype(create_value(nullptr)); using ModifyReturnT = decltype(modify_value(nullptr)); @@ -1071,7 +1069,7 @@ class Map { } template<typename ForwardKey, typename CreateValueF> - Value &lookup_or_add_cb__impl(ForwardKey &&key, const CreateValueF &create_value, uint32_t hash) + Value &lookup_or_add_cb__impl(ForwardKey &&key, const CreateValueF &create_value, uint64_t hash) { this->ensure_can_add(); @@ -1089,7 +1087,7 @@ class Map { } template<typename ForwardKey, typename ForwardValue> - Value &lookup_or_add__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash) + Value &lookup_or_add__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash) { this->ensure_can_add(); @@ -1107,7 +1105,7 @@ class Map { } template<typename ForwardKey, typename ForwardValue> - bool add_overwrite__impl(ForwardKey &&key, ForwardValue &&value, uint32_t hash) + bool add_overwrite__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash) { auto create_func = [&](Value *ptr) { new ((void *)ptr) Value(std::forward<ForwardValue>(value)); @@ -1122,7 +1120,7 @@ class Map { } template<typename ForwardKey> - const Value *lookup_ptr__impl(const ForwardKey &key, uint32_t hash) const + const Value *lookup_ptr__impl(const ForwardKey &key, uint64_t hash) const { MAP_SLOT_PROBING_BEGIN (hash, slot) { if (slot.is_empty()) { @@ -1136,9 +1134,9 @@ class Map { } template<typename ForwardKey> - uint32_t count_collisions__impl(const ForwardKey &key, uint32_t hash) const + int64_t count_collisions__impl(const ForwardKey &key, uint64_t hash) const { - uint32_t collisions = 0; + int64_t collisions = 0; MAP_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash)) { @@ -1162,6 +1160,21 @@ class Map { }; /** + * Same as a normal Map, but does not use Blender's guarded allocator. This is useful when + * allocating memory with static storage duration. + */ +template<typename Key, + typename Value, + int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key) + + sizeof(Value)), + typename ProbingStrategy = DefaultProbingStrategy, + typename Hash = DefaultHash<Key>, + typename IsEqual = DefaultEquality, + typename Slot = typename DefaultMapSlot<Key, Value>::type> +using RawMap = + Map<Key, Value, InlineBufferCapacity, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>; + +/** * A wrapper for std::unordered_map with the API of blender::Map. This can be used for * benchmarking. */ @@ -1171,9 +1184,9 @@ template<typename Key, typename Value> class StdUnorderedMapWrapper { MapType map_; public: - uint32_t size() const + int64_t size() const { - return (uint32_t)map_.size(); + return (int64_t)map_.size(); } bool is_empty() const @@ -1181,7 +1194,7 @@ template<typename Key, typename Value> class StdUnorderedMapWrapper { return map_.empty(); } - void reserve(uint32_t n) + void reserve(int64_t n) { map_.reserve(n); } diff --git a/source/blender/blenlib/BLI_map_slots.hh b/source/blender/blenlib/BLI_map_slots.hh index ff3ed34eb9d..b5360795a13 100644 --- a/source/blender/blenlib/BLI_map_slots.hh +++ b/source/blender/blenlib/BLI_map_slots.hh @@ -155,7 +155,7 @@ template<typename Key, typename Value> class SimpleMapSlot { * Returns the hash of the currently stored key. In this simple map slot implementation, we just * computed the hash here. Other implementations might store the hash in the slot instead. */ - template<typename Hash> uint32_t get_hash(const Hash &hash) + template<typename Hash> uint64_t get_hash(const Hash &hash) { BLI_assert(this->is_occupied()); return hash(*key_buffer_); @@ -165,7 +165,7 @@ template<typename Key, typename Value> class SimpleMapSlot { * Move the other slot into this slot and destruct it. We do destruction here, because this way * we can avoid a comparison with the state, since we know the slot is occupied. */ - void relocate_occupied_here(SimpleMapSlot &other, uint32_t UNUSED(hash)) + void relocate_occupied_here(SimpleMapSlot &other, uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); BLI_assert(other.is_occupied()); @@ -181,7 +181,7 @@ template<typename Key, typename Value> class SimpleMapSlot { * key. The hash can be used by other slot implementations to determine inequality faster. */ template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, uint32_t UNUSED(hash)) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const { if (state_ == Occupied) { return is_equal(key, *key_buffer_); @@ -194,7 +194,7 @@ template<typename Key, typename Value> class SimpleMapSlot { * constructed by calling the constructor with the given key/value as parameter. */ template<typename ForwardKey, typename ForwardValue> - void occupy(ForwardKey &&key, ForwardValue &&value, uint32_t hash) + void occupy(ForwardKey &&key, ForwardValue &&value, uint64_t hash) { BLI_assert(!this->is_occupied()); this->occupy_without_value(std::forward<ForwardKey>(key), hash); @@ -205,7 +205,7 @@ template<typename Key, typename Value> class SimpleMapSlot { * Change the state of this slot from empty/removed to occupied, but leave the value * uninitialized. The caller is responsible to construct the value afterwards. */ - template<typename ForwardKey> void occupy_without_value(ForwardKey &&key, uint32_t UNUSED(hash)) + template<typename ForwardKey> void occupy_without_value(ForwardKey &&key, uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); state_ = Occupied; @@ -292,13 +292,13 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot return KeyInfo::is_empty(key_); } - template<typename Hash> uint32_t get_hash(const Hash &hash) + template<typename Hash> uint64_t get_hash(const Hash &hash) { BLI_assert(this->is_occupied()); return hash(key_); } - void relocate_occupied_here(IntrusiveMapSlot &other, uint32_t UNUSED(hash)) + void relocate_occupied_here(IntrusiveMapSlot &other, uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); BLI_assert(other.is_occupied()); @@ -309,14 +309,14 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot } template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, uint32_t UNUSED(hash)) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const { BLI_assert(KeyInfo::is_not_empty_or_removed(key)); return is_equal(key, key_); } template<typename ForwardKey, typename ForwardValue> - void occupy(ForwardKey &&key, ForwardValue &&value, uint32_t hash) + void occupy(ForwardKey &&key, ForwardValue &&value, uint64_t hash) { BLI_assert(!this->is_occupied()); BLI_assert(KeyInfo::is_not_empty_or_removed(key)); @@ -324,7 +324,7 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot new (&value_buffer_) Value(std::forward<ForwardValue>(value)); } - template<typename ForwardKey> void occupy_without_value(ForwardKey &&key, uint32_t UNUSED(hash)) + template<typename ForwardKey> void occupy_without_value(ForwardKey &&key, uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); BLI_assert(KeyInfo::is_not_empty_or_removed(key)); diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index b73e0e95312..9f65fe0742e 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -43,8 +43,10 @@ namespace blender { * After: * ptr: uninitialized */ -template<typename T> void destruct_n(T *ptr, uint n) +template<typename T> void destruct_n(T *ptr, int64_t n) { + BLI_assert(n >= 0); + static_assert(std::is_nothrow_destructible_v<T>, "This should be true for all types. Destructors are noexcept by default."); @@ -54,7 +56,7 @@ template<typename T> void destruct_n(T *ptr, uint n) return; } - for (uint i = 0; i < n; i++) { + for (int64_t i = 0; i < n; i++) { ptr[i].~T(); } } @@ -70,15 +72,17 @@ template<typename T> void destruct_n(T *ptr, uint n) * After: * ptr: initialized */ -template<typename T> void default_construct_n(T *ptr, uint n) +template<typename T> void default_construct_n(T *ptr, int64_t n) { + BLI_assert(n >= 0); + /* This is not strictly necessary, because the loop below will be optimized away anyway. It is * nice to make behavior this explicitly, though. */ if (std::is_trivially_constructible_v<T>) { return; } - uint current = 0; + int64_t current = 0; try { for (; current < n; current++) { new ((void *)(ptr + current)) T; @@ -102,9 +106,11 @@ template<typename T> void default_construct_n(T *ptr, uint n) * src: initialized * dst: initialized */ -template<typename T> void initialized_copy_n(const T *src, uint n, T *dst) +template<typename T> void initialized_copy_n(const T *src, int64_t n, T *dst) { - for (uint i = 0; i < n; i++) { + BLI_assert(n >= 0); + + for (int64_t i = 0; i < n; i++) { dst[i] = src[i]; } } @@ -121,9 +127,11 @@ template<typename T> void initialized_copy_n(const T *src, uint n, T *dst) * src: initialized * dst: initialized */ -template<typename T> void uninitialized_copy_n(const T *src, uint n, T *dst) +template<typename T> void uninitialized_copy_n(const T *src, int64_t n, T *dst) { - uint current = 0; + BLI_assert(n >= 0); + + int64_t current = 0; try { for (; current < n; current++) { new ((void *)(dst + current)) T(src[current]); @@ -147,9 +155,12 @@ template<typename T> void uninitialized_copy_n(const T *src, uint n, T *dst) * src: initialized * dst: initialized */ -template<typename From, typename To> void uninitialized_convert_n(const From *src, uint n, To *dst) +template<typename From, typename To> +void uninitialized_convert_n(const From *src, int64_t n, To *dst) { - uint current = 0; + BLI_assert(n >= 0); + + int64_t current = 0; try { for (; current < n; current++) { new ((void *)(dst + current)) To((To)src[current]); @@ -173,9 +184,11 @@ template<typename From, typename To> void uninitialized_convert_n(const From *sr * src: initialized, moved-from * dst: initialized */ -template<typename T> void initialized_move_n(T *src, uint n, T *dst) +template<typename T> void initialized_move_n(T *src, int64_t n, T *dst) { - for (uint i = 0; i < n; i++) { + BLI_assert(n >= 0); + + for (int64_t i = 0; i < n; i++) { dst[i] = std::move(src[i]); } } @@ -192,9 +205,11 @@ template<typename T> void initialized_move_n(T *src, uint n, T *dst) * src: initialized, moved-from * dst: initialized */ -template<typename T> void uninitialized_move_n(T *src, uint n, T *dst) +template<typename T> void uninitialized_move_n(T *src, int64_t n, T *dst) { - uint current = 0; + BLI_assert(n >= 0); + + int64_t current = 0; try { for (; current < n; current++) { new ((void *)(dst + current)) T(std::move(src[current])); @@ -219,8 +234,10 @@ template<typename T> void uninitialized_move_n(T *src, uint n, T *dst) * src: uninitialized * dst: initialized */ -template<typename T> void initialized_relocate_n(T *src, uint n, T *dst) +template<typename T> void initialized_relocate_n(T *src, int64_t n, T *dst) { + BLI_assert(n >= 0); + initialized_move_n(src, n, dst); destruct_n(src, n); } @@ -238,8 +255,10 @@ template<typename T> void initialized_relocate_n(T *src, uint n, T *dst) * src: uninitialized * dst: initialized */ -template<typename T> void uninitialized_relocate_n(T *src, uint n, T *dst) +template<typename T> void uninitialized_relocate_n(T *src, int64_t n, T *dst) { + BLI_assert(n >= 0); + uninitialized_move_n(src, n, dst); destruct_n(src, n); } @@ -254,9 +273,11 @@ template<typename T> void uninitialized_relocate_n(T *src, uint n, T *dst) * After: * dst: initialized */ -template<typename T> void initialized_fill_n(T *dst, uint n, const T &value) +template<typename T> void initialized_fill_n(T *dst, int64_t n, const T &value) { - for (uint i = 0; i < n; i++) { + BLI_assert(n >= 0); + + for (int64_t i = 0; i < n; i++) { dst[i] = value; } } @@ -271,9 +292,11 @@ template<typename T> void initialized_fill_n(T *dst, uint n, const T &value) * After: * dst: initialized */ -template<typename T> void uninitialized_fill_n(T *dst, uint n, const T &value) +template<typename T> void uninitialized_fill_n(T *dst, int64_t n, const T &value) { - uint current = 0; + BLI_assert(n >= 0); + + int64_t current = 0; try { for (; current < n; current++) { new ((void *)(dst + current)) T(value); @@ -334,9 +357,9 @@ template<size_t Size, size_t Alignment> class alignas(Alignment) AlignedBuffer { * lifetime of the object they are embedded in. It's used by containers with small buffer * optimization and hash table implementations. */ -template<typename T, size_t Size = 1> class TypedBuffer { +template<typename T, int64_t Size = 1> class TypedBuffer { private: - AlignedBuffer<sizeof(T) * Size, alignof(T)> buffer_; + AlignedBuffer<sizeof(T) * (size_t)Size, alignof(T)> buffer_; public: operator T *() @@ -396,6 +419,15 @@ template<typename From, typename To> inline constexpr bool is_convertible_pointer_v = std::is_convertible_v<From, To> &&std::is_pointer_v<From> &&std::is_pointer_v<To>; +/** + * Inline buffers for small-object-optimization should be disable by default. Otherwise we might + * get large unexpected allocations on the stack. + */ +inline constexpr int64_t default_inline_buffer_capacity(size_t element_size) +{ + return ((int64_t)element_size < 100) ? 4 : 0; +} + } // namespace blender #endif /* __BLI_MEMORY_UTILS_HH__ */ diff --git a/source/blender/blenlib/BLI_probing_strategies.hh b/source/blender/blenlib/BLI_probing_strategies.hh index d2b16ac3516..0e5338fa6ed 100644 --- a/source/blender/blenlib/BLI_probing_strategies.hh +++ b/source/blender/blenlib/BLI_probing_strategies.hh @@ -25,17 +25,17 @@ * values based on an initial hash value. * * A probing strategy has to implement the following methods: - * - Constructor(uint32_t hash): Start a new probing sequence based on the given hash. - * - get() const -> uint32_t: Get the current value in the sequence. + * - Constructor(uint64_t hash): Start a new probing sequence based on the given hash. + * - get() const -> uint64_t: Get the current value in the sequence. * - next() -> void: Update the internal state, so that the next value can be accessed with get(). - * - linear_steps() -> uint32_t: Returns number of linear probing steps that should be done. + * - linear_steps() -> int64_t: Returns number of linear probing steps that should be done. * * Using linear probing steps between larger jumps can result in better performance, due to * improved cache usage. It's a way of getting the benefits or linear probing without the * clustering issues. However, more linear steps can also make things slower when the initial hash * produces many collisions. * - * Every probing strategy has to guarantee, that every possible uint32_t is returned eventually. + * Every probing strategy has to guarantee, that every possible uint64_t is returned eventually. * This is necessary for correctness. If this is not the case, empty slots might not be found. * * The SLOT_PROBING_BEGIN and SLOT_PROBING_END macros can be used to implement a loop that iterates @@ -65,10 +65,10 @@ namespace blender { */ class LinearProbingStrategy { private: - uint32_t hash_; + uint64_t hash_; public: - LinearProbingStrategy(const uint32_t hash) : hash_(hash) + LinearProbingStrategy(const uint64_t hash) : hash_(hash) { } @@ -77,12 +77,12 @@ class LinearProbingStrategy { hash_++; } - uint32_t get() const + uint64_t get() const { return hash_; } - uint32_t linear_steps() const + int64_t linear_steps() const { return UINT32_MAX; } @@ -101,12 +101,12 @@ class LinearProbingStrategy { */ class QuadraticProbingStrategy { private: - uint32_t original_hash_; - uint32_t current_hash_; - uint32_t iteration_; + uint64_t original_hash_; + uint64_t current_hash_; + uint64_t iteration_; public: - QuadraticProbingStrategy(const uint32_t hash) + QuadraticProbingStrategy(const uint64_t hash) : original_hash_(hash), current_hash_(hash), iteration_(1) { } @@ -117,12 +117,12 @@ class QuadraticProbingStrategy { iteration_++; } - uint32_t get() const + uint64_t get() const { return current_hash_; } - uint32_t linear_steps() const + int64_t linear_steps() const { return 1; } @@ -138,13 +138,13 @@ class QuadraticProbingStrategy { * PreShuffle: When true, the initial call to next() will be done to the constructor. This can help * when the hash function has put little information into the lower bits. */ -template<uint32_t LinearSteps = 1, bool PreShuffle = false> class PythonProbingStrategy { +template<uint64_t LinearSteps = 1, bool PreShuffle = false> class PythonProbingStrategy { private: - uint32_t hash_; - uint32_t perturb_; + uint64_t hash_; + uint64_t perturb_; public: - PythonProbingStrategy(const uint32_t hash) : hash_(hash), perturb_(hash) + PythonProbingStrategy(const uint64_t hash) : hash_(hash), perturb_(hash) { if (PreShuffle) { this->next(); @@ -157,12 +157,12 @@ template<uint32_t LinearSteps = 1, bool PreShuffle = false> class PythonProbingS hash_ = 5 * hash_ + 1 + perturb_; } - uint32_t get() const + uint64_t get() const { return hash_; } - uint32_t linear_steps() const + int64_t linear_steps() const { return LinearSteps; } @@ -173,13 +173,13 @@ template<uint32_t LinearSteps = 1, bool PreShuffle = false> class PythonProbingS * method. This way more bits are taken into account earlier. After a couple of collisions (that * should happen rarely), it will fallback to a sequence that hits every slot. */ -template<uint32_t LinearSteps = 2, bool PreShuffle = false> class ShuffleProbingStrategy { +template<uint64_t LinearSteps = 2, bool PreShuffle = false> class ShuffleProbingStrategy { private: - uint32_t hash_; - uint32_t perturb_; + uint64_t hash_; + uint64_t perturb_; public: - ShuffleProbingStrategy(const uint32_t hash) : hash_(hash), perturb_(hash) + ShuffleProbingStrategy(const uint64_t hash) : hash_(hash), perturb_(hash) { if (PreShuffle) { this->next(); @@ -197,12 +197,12 @@ template<uint32_t LinearSteps = 2, bool PreShuffle = false> class ShuffleProbing } } - uint32_t get() const + uint64_t get() const { return hash_; } - uint32_t linear_steps() const + int64_t linear_steps() const { return LinearSteps; } @@ -233,10 +233,10 @@ using DefaultProbingStrategy = PythonProbingStrategy<>; #define SLOT_PROBING_BEGIN(PROBING_STRATEGY, HASH, MASK, R_SLOT_INDEX) \ PROBING_STRATEGY probing_strategy(HASH); \ do { \ - uint32_t linear_offset = 0; \ - uint32_t current_hash = probing_strategy.get(); \ + int64_t linear_offset = 0; \ + uint64_t current_hash = probing_strategy.get(); \ do { \ - uint32_t R_SLOT_INDEX = (current_hash + linear_offset) & MASK; + int64_t R_SLOT_INDEX = (int64_t)((current_hash + (uint64_t)linear_offset) & MASK); #define SLOT_PROBING_END() \ } while (++linear_offset < probing_strategy.linear_steps()); \ diff --git a/source/blender/blenlib/BLI_rand.hh b/source/blender/blenlib/BLI_rand.hh index bfc4d276165..612ac0bbe19 100644 --- a/source/blender/blenlib/BLI_rand.hh +++ b/source/blender/blenlib/BLI_rand.hh @@ -86,7 +86,7 @@ class RandomNumberGenerator { /** * Simulate getting \a n random values. */ - void skip(uint n) + void skip(int64_t n) { while (n--) { this->step(); diff --git a/source/blender/blenlib/BLI_resource_collector.hh b/source/blender/blenlib/BLI_resource_collector.hh index 672a1269962..10d610da618 100644 --- a/source/blender/blenlib/BLI_resource_collector.hh +++ b/source/blender/blenlib/BLI_resource_collector.hh @@ -51,7 +51,7 @@ class ResourceCollector : NonCopyable, NonMovable { ~ResourceCollector() { /* Free in reversed order. */ - for (uint i = m_resources.size(); i--;) { + for (int64_t i = m_resources.size(); i--;) { ResourceData &data = m_resources[i]; data.free(data.data); } diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh index c5096f84c80..90adea69e06 100644 --- a/source/blender/blenlib/BLI_set.hh +++ b/source/blender/blenlib/BLI_set.hh @@ -89,11 +89,8 @@ template< * The minimum number of elements that can be stored in this Set without doing a heap * allocation. This is useful when you expect to have many small sets. However, keep in mind * that (unlike vector) initializing a set has a O(n) cost in the number of slots. - * - * When Key is large, the small buffer optimization is disabled by default to avoid large - * unexpected allocations on the stack. It can still be enabled explicitly though. */ - uint32_t InlineBufferCapacity = (sizeof(Key) < 100) ? 4 : 0, + int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key)), /** * The strategy used to deal with collisions. They are defined in BLI_probing_strategies.hh. */ @@ -128,20 +125,20 @@ class Set { * Slots are either empty, occupied or removed. The number of occupied slots can be computed by * subtracting the removed slots from the occupied-and-removed slots. */ - uint32_t removed_slots_; - uint32_t occupied_and_removed_slots_; + int64_t removed_slots_; + int64_t occupied_and_removed_slots_; /** * The maximum number of slots that can be used (either occupied or removed) until the set has to * grow. This is the total number of slots times the max load factor. */ - uint32_t usable_slots_; + int64_t usable_slots_; /** * The number of slots minus one. This is a bit mask that can be used to turn any integer into a * valid slot index efficiently. */ - uint32_t slot_mask_; + uint64_t slot_mask_; /** This is called to hash incoming keys. */ Hash hash_; @@ -384,11 +381,11 @@ class Set { class Iterator { private: const Slot *slots_; - uint32_t total_slots_; - uint32_t current_slot_; + int64_t total_slots_; + int64_t current_slot_; public: - Iterator(const Slot *slots, uint32_t total_slots, uint32_t current_slot) + Iterator(const Slot *slots, int64_t total_slots, int64_t current_slot) : slots_(slots), total_slots_(total_slots), current_slot_(current_slot) { } @@ -418,7 +415,7 @@ class Set { Iterator begin() const { - for (uint32_t i = 0; i < slots_.size(); i++) { + for (int64_t i = 0; i < slots_.size(); i++) { if (slots_[i].is_occupied()) { return Iterator(slots_.data(), slots_.size(), i); } @@ -444,7 +441,7 @@ class Set { * Get the number of collisions that the probing strategy has to go through to find the key or * determine that it is not in the set. */ - uint32_t count_collisions(const Key &key) const + int64_t count_collisions(const Key &key) const { return this->count_collisions__impl(key, hash_(key)); } @@ -470,7 +467,7 @@ class Set { /** * Returns the number of keys stored in the set. */ - uint32_t size() const + int64_t size() const { return occupied_and_removed_slots_ - removed_slots_; } @@ -486,7 +483,7 @@ class Set { /** * Returns the number of available slots. This is mostly for debugging purposes. */ - uint32_t capacity() const + int64_t capacity() const { return slots_.size(); } @@ -494,7 +491,7 @@ class Set { /** * Returns the amount of removed slots in the set. This is mostly for debugging purposes. */ - uint32_t removed_amount() const + int64_t removed_amount() const { return removed_slots_; } @@ -502,7 +499,7 @@ class Set { /** * Returns the bytes required per element. This is mostly for debugging purposes. */ - uint32_t size_per_element() const + int64_t size_per_element() const { return sizeof(Slot); } @@ -511,7 +508,7 @@ class Set { * Returns the approximate memory requirements of the set in bytes. This is more correct for * larger sets. */ - uint32_t size_in_bytes() const + int64_t size_in_bytes() const { return sizeof(Slot) * slots_.size(); } @@ -520,7 +517,7 @@ class Set { * Potentially resize the set such that it can hold the specified number of keys without another * grow operation. */ - void reserve(const uint32_t n) + void reserve(const int64_t n) { if (usable_slots_ < n) { this->realloc_and_reinsert(n); @@ -554,12 +551,13 @@ class Set { } private: - BLI_NOINLINE void realloc_and_reinsert(const uint32_t min_usable_slots) + BLI_NOINLINE void realloc_and_reinsert(const int64_t min_usable_slots) { - uint32_t total_slots, usable_slots; + int64_t total_slots, usable_slots; max_load_factor_.compute_total_and_usable_slots( SlotArray::inline_buffer_capacity(), min_usable_slots, &total_slots, &usable_slots); - const uint32_t new_slot_mask = total_slots - 1; + BLI_assert(total_slots >= 1); + const uint64_t new_slot_mask = (uint64_t)total_slots - 1; /** * Optimize the case when the set was empty beforehand. We can avoid some copies here. @@ -595,9 +593,9 @@ class Set { void add_after_grow_and_destruct_old(Slot &old_slot, SlotArray &new_slots, - const uint32_t new_slot_mask) + const uint64_t new_slot_mask) { - const uint32_t hash = old_slot.get_hash(Hash()); + const uint64_t hash = old_slot.get_hash(Hash()); SLOT_PROBING_BEGIN (ProbingStrategy, hash, new_slot_mask, slot_index) { Slot &slot = new_slots[slot_index]; @@ -610,7 +608,7 @@ class Set { } template<typename ForwardKey> - bool contains__impl(const ForwardKey &key, const uint32_t hash) const + bool contains__impl(const ForwardKey &key, const uint64_t hash) const { SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.is_empty()) { @@ -624,7 +622,7 @@ class Set { } template<typename ForwardKey> - const Key &lookup_key__impl(const ForwardKey &key, const uint32_t hash) const + const Key &lookup_key__impl(const ForwardKey &key, const uint64_t hash) const { BLI_assert(this->contains_as(key)); @@ -637,7 +635,7 @@ class Set { } template<typename ForwardKey> - const Key *lookup_key_ptr__impl(const ForwardKey &key, const uint32_t hash) const + const Key *lookup_key_ptr__impl(const ForwardKey &key, const uint64_t hash) const { SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash)) { @@ -650,7 +648,7 @@ class Set { SET_SLOT_PROBING_END(); } - template<typename ForwardKey> void add_new__impl(ForwardKey &&key, const uint32_t hash) + template<typename ForwardKey> void add_new__impl(ForwardKey &&key, const uint64_t hash) { BLI_assert(!this->contains_as(key)); @@ -666,7 +664,7 @@ class Set { SET_SLOT_PROBING_END(); } - template<typename ForwardKey> bool add__impl(ForwardKey &&key, const uint32_t hash) + template<typename ForwardKey> bool add__impl(ForwardKey &&key, const uint64_t hash) { this->ensure_can_add(); @@ -683,7 +681,7 @@ class Set { SET_SLOT_PROBING_END(); } - template<typename ForwardKey> bool remove__impl(const ForwardKey &key, const uint32_t hash) + template<typename ForwardKey> bool remove__impl(const ForwardKey &key, const uint64_t hash) { SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash)) { @@ -699,7 +697,7 @@ class Set { } template<typename ForwardKey> - void remove_contained__impl(const ForwardKey &key, const uint32_t hash) + void remove_contained__impl(const ForwardKey &key, const uint64_t hash) { BLI_assert(this->contains_as(key)); removed_slots_++; @@ -714,9 +712,9 @@ class Set { } template<typename ForwardKey> - uint32_t count_collisions__impl(const ForwardKey &key, const uint32_t hash) const + int64_t count_collisions__impl(const ForwardKey &key, const uint64_t hash) const { - uint32_t collisions = 0; + int64_t collisions = 0; SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash)) { @@ -749,9 +747,9 @@ template<typename Key> class StdUnorderedSetWrapper { SetType set_; public: - uint32_t size() const + int64_t size() const { - return (uint32_t)set_.size(); + return (int64_t)set_.size(); } bool is_empty() const @@ -759,7 +757,7 @@ template<typename Key> class StdUnorderedSetWrapper { return set_.empty(); } - void reserve(uint32_t n) + void reserve(int64_t n) { set_.reserve(n); } @@ -820,6 +818,18 @@ template<typename Key> class StdUnorderedSetWrapper { } }; +/** + * Same as a normal Set, but does not use Blender's guarded allocator. This is useful when + * allocating memory with static storage duration. + */ +template<typename Key, + int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key)), + typename ProbingStrategy = DefaultProbingStrategy, + typename Hash = DefaultHash<Key>, + typename IsEqual = DefaultEquality, + typename Slot = typename DefaultSetSlot<Key>::type> +using RawSet = Set<Key, InlineBufferCapacity, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>; + } // namespace blender #endif /* __BLI_SET_HH__ */ diff --git a/source/blender/blenlib/BLI_set_slots.hh b/source/blender/blenlib/BLI_set_slots.hh index d3891e78b52..b78ed37f534 100644 --- a/source/blender/blenlib/BLI_set_slots.hh +++ b/source/blender/blenlib/BLI_set_slots.hh @@ -133,7 +133,7 @@ template<typename Key> class SimpleSetSlot { * Return the hash of the currently stored key. In this simple set slot implementation, we just * compute the hash here. Other implementations might store the hash in the slot instead. */ - template<typename Hash> uint32_t get_hash(const Hash &hash) const + template<typename Hash> uint64_t get_hash(const Hash &hash) const { BLI_assert(this->is_occupied()); return hash(*key_buffer_); @@ -143,7 +143,7 @@ template<typename Key> class SimpleSetSlot { * Move the other slot into this slot and destruct it. We do destruction here, because this way * we can avoid a comparison with the state, since we know the slot is occupied. */ - void relocate_occupied_here(SimpleSetSlot &other, uint32_t UNUSED(hash)) + void relocate_occupied_here(SimpleSetSlot &other, uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); BLI_assert(other.is_occupied()); @@ -157,7 +157,7 @@ template<typename Key> class SimpleSetSlot { * key. The hash is used by other slot implementations to determine inequality faster. */ template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, uint32_t UNUSED(hash)) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const { if (state_ == Occupied) { return is_equal(key, *key_buffer_); @@ -169,7 +169,7 @@ template<typename Key> class SimpleSetSlot { * Change the state of this slot from empty/removed to occupied. The key has to be constructed * by calling the constructor with the given key as parameter. */ - template<typename ForwardKey> void occupy(ForwardKey &&key, uint32_t UNUSED(hash)) + template<typename ForwardKey> void occupy(ForwardKey &&key, uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); state_ = Occupied; @@ -199,7 +199,7 @@ template<typename Key> class HashedSetSlot { Removed = 2, }; - uint32_t hash_; + uint64_t hash_; State state_; TypedBuffer<Key> key_buffer_; @@ -254,13 +254,13 @@ template<typename Key> class HashedSetSlot { return state_ == Empty; } - template<typename Hash> uint32_t get_hash(const Hash &UNUSED(hash)) const + template<typename Hash> uint64_t get_hash(const Hash &UNUSED(hash)) const { BLI_assert(this->is_occupied()); return hash_; } - void relocate_occupied_here(HashedSetSlot &other, const uint32_t hash) + void relocate_occupied_here(HashedSetSlot &other, const uint64_t hash) { BLI_assert(!this->is_occupied()); BLI_assert(other.is_occupied()); @@ -271,7 +271,7 @@ template<typename Key> class HashedSetSlot { } template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint32_t hash) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t hash) const { /* hash_ might be uninitialized here, but that is ok. */ if (hash_ == hash) { @@ -282,7 +282,7 @@ template<typename Key> class HashedSetSlot { return false; } - template<typename ForwardKey> void occupy(ForwardKey &&key, const uint32_t hash) + template<typename ForwardKey> void occupy(ForwardKey &&key, const uint64_t hash) { BLI_assert(!this->is_occupied()); state_ = Occupied; @@ -336,13 +336,13 @@ template<typename Key, typename KeyInfo> class IntrusiveSetSlot { return KeyInfo::is_empty(key_); } - template<typename Hash> uint32_t get_hash(const Hash &hash) const + template<typename Hash> uint64_t get_hash(const Hash &hash) const { BLI_assert(this->is_occupied()); return hash(key_); } - void relocate_occupied_here(IntrusiveSetSlot &other, const uint32_t UNUSED(hash)) + void relocate_occupied_here(IntrusiveSetSlot &other, const uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); BLI_assert(other.is_occupied()); @@ -351,13 +351,13 @@ template<typename Key, typename KeyInfo> class IntrusiveSetSlot { } template<typename ForwardKey, typename IsEqual> - bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint32_t UNUSED(hash)) const + bool contains(const ForwardKey &key, const IsEqual &is_equal, const uint64_t UNUSED(hash)) const { BLI_assert(KeyInfo::is_not_empty_or_removed(key)); return is_equal(key_, key); } - template<typename ForwardKey> void occupy(ForwardKey &&key, const uint32_t UNUSED(hash)) + template<typename ForwardKey> void occupy(ForwardKey &&key, const uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); BLI_assert(KeyInfo::is_not_empty_or_removed(key)); diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh index 57ef9ce9eb6..2d875fe73be 100644 --- a/source/blender/blenlib/BLI_span.hh +++ b/source/blender/blenlib/BLI_span.hh @@ -88,7 +88,7 @@ namespace blender { template<typename T> class Span { private: const T *start_ = nullptr; - uint size_ = 0; + int64_t size_ = 0; public: /** @@ -96,13 +96,15 @@ template<typename T> class Span { */ Span() = default; - Span(const T *start, uint size) : start_(start), size_(size) + Span(const T *start, int64_t size) : start_(start), size_(size) { + BLI_assert(size >= 0); } template<typename U, typename std::enable_if_t<is_convertible_pointer_v<U, T>> * = nullptr> - Span(const U *start, uint size) : start_((const T *)start), size_(size) + Span(const U *start, int64_t size) : start_((const T *)start), size_(size) { + BLI_assert(size >= 0); } /** @@ -116,11 +118,11 @@ template<typename T> class Span { * Span<int> span = {1, 2, 3, 4}; * call_function_with_array(span); */ - Span(const std::initializer_list<T> &list) : Span(list.begin(), (uint)list.size()) + Span(const std::initializer_list<T> &list) : Span(list.begin(), (int64_t)list.size()) { } - Span(const std::vector<T> &vector) : Span(vector.data(), (uint)vector.size()) + Span(const std::vector<T> &vector) : Span(vector.data(), (int64_t)vector.size()) { } @@ -142,8 +144,10 @@ template<typename T> class Span { * Returns a contiguous part of the array. This invokes undefined behavior when the slice does * not stay within the bounds of the array. */ - Span slice(uint start, uint size) const + Span slice(int64_t start, int64_t size) const { + BLI_assert(start >= 0); + BLI_assert(size >= 0); BLI_assert(start + size <= this->size() || size == 0); return Span(start_ + start, size); } @@ -157,8 +161,9 @@ template<typename T> class Span { * Returns a new Span with n elements removed from the beginning. This invokes undefined * behavior when the array is too small. */ - Span drop_front(uint n) const + Span drop_front(int64_t n) const { + BLI_assert(n >= 0); BLI_assert(n <= this->size()); return this->slice(n, this->size() - n); } @@ -167,8 +172,9 @@ template<typename T> class Span { * Returns a new Span with n elements removed from the beginning. This invokes undefined * behavior when the array is too small. */ - Span drop_back(uint n) const + Span drop_back(int64_t n) const { + BLI_assert(n >= 0); BLI_assert(n <= this->size()); return this->slice(0, this->size() - n); } @@ -177,8 +183,9 @@ template<typename T> class Span { * Returns a new Span that only contains the first n elements. This invokes undefined * behavior when the array is too small. */ - Span take_front(uint n) const + Span take_front(int64_t n) const { + BLI_assert(n >= 0); BLI_assert(n <= this->size()); return this->slice(0, n); } @@ -187,8 +194,9 @@ template<typename T> class Span { * Returns a new Span that only contains the last n elements. This invokes undefined * behavior when the array is too small. */ - Span take_back(uint n) const + Span take_back(int64_t n) const { + BLI_assert(n >= 0); BLI_assert(n <= this->size()); return this->slice(this->size() - n, n); } @@ -216,8 +224,9 @@ template<typename T> class Span { * Access an element in the array. This invokes undefined behavior when the index is out of * bounds. */ - const T &operator[](uint index) const + const T &operator[](int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index < size_); return start_[index]; } @@ -225,7 +234,7 @@ template<typename T> class Span { /** * Returns the number of elements in the referenced array. */ - uint size() const + int64_t size() const { return size_; } @@ -241,7 +250,7 @@ template<typename T> class Span { /** * Returns the number of bytes referenced by this Span. */ - uint size_in_bytes() const + int64_t size_in_bytes() const { return sizeof(T) * size_; } @@ -273,9 +282,9 @@ template<typename T> class Span { * Does a linear search to count how often the value is in the array. * Returns the number of occurrences. */ - uint count(const T &value) const + int64_t count(const T &value) const { - uint counter = 0; + int64_t counter = 0; for (const T &element : *this) { if (element == value) { counter++; @@ -308,9 +317,9 @@ template<typename T> class Span { * Returns the element at the given index. If the index is out of range, return the fallback * value. */ - T get(uint index, const T &fallback) const + T get(int64_t index, const T &fallback) const { - if (index < size_) { + if (index < size_ && index >= 0) { return start_[index]; } return fallback; @@ -326,9 +335,9 @@ template<typename T> class Span { * changed. */ BLI_assert(size_ < 1000); - for (uint i = 0; i < size_; i++) { + for (int64_t i = 0; i < size_; i++) { const T &value = start_[i]; - for (uint j = i + 1; j < size_; j++) { + for (int64_t j = i + 1; j < size_; j++) { if (value == start_[j]) { return true; } @@ -348,7 +357,7 @@ template<typename T> class Span { * changed. */ BLI_assert(size_ < 1000); - for (uint i = 0; i < size_; i++) { + for (int64_t i = 0; i < size_; i++) { const T &value = start_[i]; if (other.contains(value)) { return true; @@ -361,19 +370,19 @@ template<typename T> class Span { * Returns the index of the first occurrence of the given value. This invokes undefined behavior * when the value is not in the array. */ - uint first_index(const T &search_value) const + int64_t first_index(const T &search_value) const { - const int index = this->first_index_try(search_value); + const int64_t index = this->first_index_try(search_value); BLI_assert(index >= 0); - return (uint)index; + return (int64_t)index; } /** * Returns the index of the first occurrence of the given value or -1 if it does not exist. */ - int first_index_try(const T &search_value) const + int64_t first_index_try(const T &search_value) const { - for (uint i = 0; i < size_; i++) { + for (int64_t i = 0; i < size_; i++) { if (start_[i] == search_value) { return i; } @@ -396,7 +405,7 @@ template<typename T> class Span { template<typename NewT> Span<NewT> cast() const { BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0); - uint new_size = size_ * sizeof(T) / sizeof(NewT); + int64_t new_size = size_ * sizeof(T) / sizeof(NewT); return Span<NewT>(reinterpret_cast<const NewT *>(start_), new_size); } @@ -431,12 +440,12 @@ template<typename T> class Span { template<typename T> class MutableSpan { private: T *start_; - uint size_; + int64_t size_; public: MutableSpan() = default; - MutableSpan(T *start, const uint size) : start_(start), size_(size) + MutableSpan(T *start, const int64_t size) : start_(start), size_(size) { } @@ -456,7 +465,7 @@ template<typename T> class MutableSpan { /** * Returns the number of elements in the array. */ - uint size() const + int64_t size() const { return size_; } @@ -473,9 +482,9 @@ template<typename T> class MutableSpan { * Replace a subset of all elements with the given value. This invokes undefined behavior when * one of the indices is out of bounds. */ - void fill_indices(Span<uint> indices, const T &value) + void fill_indices(Span<int64_t> indices, const T &value) { - for (uint i : indices) { + for (int64_t i : indices) { BLI_assert(i < size_); start_[i] = value; } @@ -500,7 +509,7 @@ template<typename T> class MutableSpan { return start_ + size_; } - T &operator[](const uint index) const + T &operator[](const int64_t index) const { BLI_assert(index < this->size()); return start_[index]; @@ -510,7 +519,7 @@ template<typename T> class MutableSpan { * Returns a contiguous part of the array. This invokes undefined behavior when the slice would * go out of bounds. */ - MutableSpan slice(const uint start, const uint length) const + MutableSpan slice(const int64_t start, const int64_t length) const { BLI_assert(start + length <= this->size()); return MutableSpan(start_ + start, length); @@ -520,7 +529,7 @@ template<typename T> class MutableSpan { * Returns a new MutableSpan with n elements removed from the beginning. This invokes * undefined behavior when the array is too small. */ - MutableSpan drop_front(const uint n) const + MutableSpan drop_front(const int64_t n) const { BLI_assert(n <= this->size()); return this->slice(n, this->size() - n); @@ -530,7 +539,7 @@ template<typename T> class MutableSpan { * Returns a new MutableSpan with n elements removed from the end. This invokes undefined * behavior when the array is too small. */ - MutableSpan drop_back(const uint n) const + MutableSpan drop_back(const int64_t n) const { BLI_assert(n <= this->size()); return this->slice(0, this->size() - n); @@ -540,7 +549,7 @@ template<typename T> class MutableSpan { * Returns a new MutableSpan that only contains the first n elements. This invokes undefined * behavior when the array is too small. */ - MutableSpan take_front(const uint n) const + MutableSpan take_front(const int64_t n) const { BLI_assert(n <= this->size()); return this->slice(0, n); @@ -550,7 +559,7 @@ template<typename T> class MutableSpan { * Return a new MutableSpan that only contains the last n elements. This invokes undefined * behavior when the array is too small. */ - MutableSpan take_back(const uint n) const + MutableSpan take_back(const int64_t n) const { BLI_assert(n <= this->size()); return this->slice(this->size() - n, n); @@ -585,12 +594,27 @@ template<typename T> class MutableSpan { } /** + * Does a linear search to count how often the value is in the array. + * Returns the number of occurrences. + */ + int64_t count(const T &value) const + { + int64_t counter = 0; + for (const T &element : *this) { + if (element == value) { + counter++; + } + } + return counter; + } + + /** * Returns a new span to the same underlying memory buffer. No conversions are done. */ template<typename NewT> MutableSpan<NewT> cast() const { BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0); - uint new_size = size_ * sizeof(T) / sizeof(NewT); + int64_t new_size = size_ * sizeof(T) / sizeof(NewT); return MutableSpan<NewT>(reinterpret_cast<NewT *>(start_), new_size); } }; @@ -602,7 +626,7 @@ template<typename T1, typename T2> void assert_same_size(const T1 &v1, const T2 { UNUSED_VARS_NDEBUG(v1, v2); #ifdef DEBUG - uint size = v1.size(); + int64_t size = v1.size(); BLI_assert(size == v1.size()); BLI_assert(size == v2.size()); #endif @@ -613,7 +637,7 @@ void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3) { UNUSED_VARS_NDEBUG(v1, v2, v3); #ifdef DEBUG - uint size = v1.size(); + int64_t size = v1.size(); BLI_assert(size == v1.size()); BLI_assert(size == v2.size()); BLI_assert(size == v3.size()); diff --git a/source/blender/blenlib/BLI_stack.hh b/source/blender/blenlib/BLI_stack.hh index a5a95186e37..75ae9df79a4 100644 --- a/source/blender/blenlib/BLI_stack.hh +++ b/source/blender/blenlib/BLI_stack.hh @@ -60,7 +60,7 @@ template<typename T> struct StackChunk { /** Pointer to one element past the end of the referenced buffer. */ T *capacity_end; - uint capacity() const + int64_t capacity() const { return capacity_end - begin; } @@ -73,11 +73,8 @@ template< * The number of values that can be stored in this stack, without doing a heap allocation. * Sometimes it can make sense to increase this value a lot. The memory in the inline buffer is * not initialized when it is not needed. - * - * When T is large, the small buffer optimization is disabled by default to avoid large - * unexpected allocations on the stack. It can still be enabled explicitly though. */ - uint InlineBufferCapacity = (sizeof(T) < 100) ? 4 : 0, + int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T)), /** * The allocator used by this stack. Should rarely be changed, except when you don't want that * MEM_* is used internally. @@ -103,7 +100,7 @@ class Stack { /** * Number of elements in the entire stack. The sum of initialized element counts in the chunks. */ - uint size_; + int64_t size_; /** The buffer used to implement small object optimization. */ TypedBuffer<T, InlineBufferCapacity> inline_buffer_; @@ -298,8 +295,8 @@ class Stack { this->activate_next_chunk(remaining_values.size()); } - const uint remaining_capacity = top_chunk_->capacity_end - top_; - const uint amount = std::min(remaining_values.size(), remaining_capacity); + const int64_t remaining_capacity = top_chunk_->capacity_end - top_; + const int64_t amount = std::min(remaining_values.size(), remaining_capacity); uninitialized_copy_n(remaining_values.data(), amount, top_); top_ += amount; @@ -320,7 +317,7 @@ class Stack { /** * Returns the number of elements in the stack. */ - uint size() const + int64_t size() const { return size_; } @@ -344,11 +341,11 @@ class Stack { * * This invokes undefined behavior when the currently active chunk is not full. */ - void activate_next_chunk(const uint size_hint) + void activate_next_chunk(const int64_t size_hint) { BLI_assert(top_ == top_chunk_->capacity_end); if (top_chunk_->above == nullptr) { - const uint new_capacity = std::max(size_hint, top_chunk_->capacity() * 2 + 10); + const int64_t new_capacity = std::max(size_hint, top_chunk_->capacity() * 2 + 10); /* Do a single memory allocation for the Chunk and the array it references. */ void *buffer = allocator_.allocate( @@ -381,6 +378,13 @@ class Stack { } }; +/** + * Same as a normal Stack, but does not use Blender's guarded allocator. This is useful when + * allocating memory with static storage duration. + */ +template<typename T, int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T))> +using RawStack = Stack<T, InlineBufferCapacity, RawAllocator>; + } /* namespace blender */ #endif /* __BLI_STACK_HH__ */ diff --git a/source/blender/blenlib/BLI_string_ref.hh b/source/blender/blenlib/BLI_string_ref.hh index 5b555b8cd1d..06fc66f6b55 100644 --- a/source/blender/blenlib/BLI_string_ref.hh +++ b/source/blender/blenlib/BLI_string_ref.hh @@ -60,9 +60,9 @@ class StringRef; class StringRefBase { protected: const char *data_; - uint size_; + int64_t size_; - StringRefBase(const char *data, const uint size) : data_(data), size_(size) + StringRefBase(const char *data, const int64_t size) : data_(data), size_(size) { } @@ -70,7 +70,7 @@ class StringRefBase { /** * Return the (byte-)length of the referenced string, without any null-terminator. */ - uint size() const + int64_t size() const { return size_; } @@ -94,7 +94,7 @@ class StringRefBase { */ operator std::string() const { - return std::string(data_, size_); + return std::string(data_, (size_t)size_); } const char *begin() const @@ -114,7 +114,7 @@ class StringRefBase { */ void unsafe_copy(char *dst) const { - memcpy(dst, data_, size_); + memcpy(dst, data_, (size_t)size_); dst[size_] = '\0'; } @@ -122,7 +122,7 @@ class StringRefBase { * Copy the string into a buffer. The copied string will be null-terminated. This invokes * undefined behavior when dst_size is too small. (Should we define the behavior?) */ - void copy(char *dst, const uint dst_size) const + void copy(char *dst, const int64_t dst_size) const { if (size_ < dst_size) { this->unsafe_copy(dst); @@ -137,7 +137,7 @@ class StringRefBase { * Copy the string into a char array. The copied string will be null-terminated. This invokes * undefined behavior when dst is too small. */ - template<uint N> void copy(char (&dst)[N]) + template<size_t N> void copy(char (&dst)[N]) { this->copy(dst, N); } @@ -152,7 +152,7 @@ class StringRefBase { */ bool endswith(StringRef suffix) const; - StringRef substr(uint start, const uint size) const; + StringRef substr(int64_t start, const int64_t size) const; }; /** @@ -168,7 +168,7 @@ class StringRefNull : public StringRefBase { /** * Construct a StringRefNull from a null terminated c-string. The pointer must not point to NULL. */ - StringRefNull(const char *str) : StringRefBase(str, (uint)strlen(str)) + StringRefNull(const char *str) : StringRefBase(str, (int64_t)strlen(str)) { BLI_assert(str != NULL); BLI_assert(data_[size_] == '\0'); @@ -178,9 +178,9 @@ class StringRefNull : public StringRefBase { * Construct a StringRefNull from a null terminated c-string. This invokes undefined behavior * when the given size is not the correct size of the string. */ - StringRefNull(const char *str, const uint size) : StringRefBase(str, size) + StringRefNull(const char *str, const int64_t size) : StringRefBase(str, size) { - BLI_assert((uint)strlen(str) == size); + BLI_assert((int64_t)strlen(str) == size); } /** @@ -194,8 +194,9 @@ class StringRefNull : public StringRefBase { /** * Get the char at the given index. */ - char operator[](const uint index) const + char operator[](const int64_t index) const { + BLI_assert(index >= 0); /* Use '<=' instead of just '<', so that the null character can be accessed as well. */ BLI_assert(index <= size_); return data_[index]; @@ -231,11 +232,11 @@ class StringRef : public StringRefBase { /** * Create a StringRef from a null-terminated c-string. */ - StringRef(const char *str) : StringRefBase(str, str ? (uint)strlen(str) : 0) + StringRef(const char *str) : StringRefBase(str, str ? (int64_t)strlen(str) : 0) { } - StringRef(const char *str, const uint length) : StringRefBase(str, length) + StringRef(const char *str, const int64_t length) : StringRefBase(str, length) { } @@ -244,7 +245,7 @@ class StringRef : public StringRefBase { * second point points to a smaller address than the first one. */ StringRef(const char *begin, const char *one_after_end) - : StringRefBase(begin, (uint)(one_after_end - begin)) + : StringRefBase(begin, (int64_t)(one_after_end - begin)) { BLI_assert(begin <= one_after_end); } @@ -253,15 +254,16 @@ class StringRef : public StringRefBase { * Reference a std::string. Remember that when the std::string is destructed, the StringRef * will point to uninitialized memory. */ - StringRef(const std::string &str) : StringRefBase(str.data(), (uint)str.size()) + StringRef(const std::string &str) : StringRefBase(str.data(), (int64_t)str.size()) { } /** * Return a new StringRef that does not contain the first n chars. */ - StringRef drop_prefix(const uint n) const + StringRef drop_prefix(const int64_t n) const { + BLI_assert(n >= 0); BLI_assert(n <= size_); return StringRef(data_ + n, size_ - n); } @@ -279,8 +281,9 @@ class StringRef : public StringRefBase { /** * Get the char at the given index. */ - char operator[](uint index) const + char operator[](int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index < size_); return data_[index]; } @@ -297,7 +300,7 @@ inline std::ostream &operator<<(std::ostream &stream, StringRef ref) inline std::ostream &operator<<(std::ostream &stream, StringRefNull ref) { - stream << std::string(ref.data(), ref.size()); + stream << std::string(ref.data(), (size_t)ref.size()); return stream; } @@ -315,7 +318,7 @@ inline bool operator==(StringRef a, StringRef b) if (a.size() != b.size()) { return false; } - return STREQLEN(a.data(), b.data(), a.size()); + return STREQLEN(a.data(), b.data(), (size_t)a.size()); } inline bool operator!=(StringRef a, StringRef b) @@ -331,7 +334,7 @@ inline bool StringRefBase::startswith(StringRef prefix) const if (size_ < prefix.size_) { return false; } - for (uint i = 0; i < prefix.size_; i++) { + for (int64_t i = 0; i < prefix.size_; i++) { if (data_[i] != prefix.data_[i]) { return false; } @@ -347,8 +350,8 @@ inline bool StringRefBase::endswith(StringRef suffix) const if (size_ < suffix.size_) { return false; } - const uint offset = size_ - suffix.size_; - for (uint i = 0; i < suffix.size_; i++) { + const int64_t offset = size_ - suffix.size_; + for (int64_t i = 0; i < suffix.size_; i++) { if (data_[offset + i] != suffix.data_[i]) { return false; } @@ -359,8 +362,10 @@ inline bool StringRefBase::endswith(StringRef suffix) const /** * Return a new #StringRef containing only a sub-string of the original string. */ -inline StringRef StringRefBase::substr(const uint start, const uint size) const +inline StringRef StringRefBase::substr(const int64_t start, const int64_t size) const { + BLI_assert(size >= 0); + BLI_assert(start >= 0); BLI_assert(start + size <= size_); return StringRef(data_ + start, size); } diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh index 1fe38464ad0..1bb674093bb 100644 --- a/source/blender/blenlib/BLI_vector.hh +++ b/source/blender/blenlib/BLI_vector.hh @@ -70,7 +70,7 @@ template< * When T is large, the small buffer optimization is disabled by default to avoid large * unexpected allocations on the stack. It can still be enabled explicitly though. */ - uint InlineBufferCapacity = (sizeof(T) < 100) ? 4 : 0, + int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T)), /** * The allocator used by this vector. Should rarely be changed, except when you don't want that * MEM_* is used internally. @@ -100,8 +100,8 @@ class Vector { * annoying. Knowing the size of a vector is often quite essential when debugging some code. */ #ifndef NDEBUG - uint debug_size_; -# define UPDATE_VECTOR_SIZE(ptr) (ptr)->debug_size_ = (uint)((ptr)->end_ - (ptr)->begin_) + int64_t debug_size_; +# define UPDATE_VECTOR_SIZE(ptr) (ptr)->debug_size_ = (int64_t)((ptr)->end_ - (ptr)->begin_) #else # define UPDATE_VECTOR_SIZE(ptr) ((void)0) #endif @@ -110,7 +110,7 @@ class Vector { * Be a friend with other vector instantiations. This is necessary to implement some memory * management logic. */ - template<typename OtherT, uint OtherInlineBufferCapacity, typename OtherAllocator> + template<typename OtherT, int64_t OtherInlineBufferCapacity, typename OtherAllocator> friend class Vector; public: @@ -131,7 +131,7 @@ class Vector { * The elements will be default constructed. * If T is trivially constructible, the elements in the vector are not touched. */ - explicit Vector(uint size) : Vector() + explicit Vector(int64_t size) : Vector() { this->resize(size); } @@ -139,7 +139,7 @@ class Vector { /** * Create a vector filled with a specific value. */ - Vector(uint size, const T &value) : Vector() + Vector(int64_t size, const T &value) : Vector() { this->resize(size, value); } @@ -150,7 +150,7 @@ class Vector { template<typename U, typename std::enable_if_t<std::is_convertible_v<U, T>> * = nullptr> Vector(Span<U> values, Allocator allocator = {}) : Vector(allocator) { - const uint size = values.size(); + const int64_t size = values.size(); this->reserve(size); this->increase_size_by_unchecked(size); uninitialized_convert_n<U, T>(values.data(), size, begin_); @@ -217,7 +217,7 @@ class Vector { * Create a copy of a vector with a different InlineBufferCapacity. This needs to be handled * separately, so that the other one is a valid copy constructor. */ - template<uint OtherInlineBufferCapacity> + template<int64_t OtherInlineBufferCapacity> Vector(const Vector<T, OtherInlineBufferCapacity, Allocator> &other) : Vector(other.as_span(), other.allocator_) { @@ -227,11 +227,11 @@ class Vector { * Steal the elements from another vector. This does not do an allocation. The other vector will * have zero elements afterwards. */ - template<uint OtherInlineBufferCapacity> + template<int64_t OtherInlineBufferCapacity> Vector(Vector<T, OtherInlineBufferCapacity, Allocator> &&other) noexcept : allocator_(other.allocator_) { - const uint size = other.size(); + const int64_t size = other.size(); if (other.is_inline()) { if (size <= InlineBufferCapacity) { @@ -243,8 +243,8 @@ class Vector { } else { /* Copy from inline buffer to newly allocated buffer. */ - const uint capacity = size; - begin_ = (T *)allocator_.allocate(sizeof(T) * capacity, alignof(T), AT); + const int64_t capacity = size; + begin_ = (T *)allocator_.allocate(sizeof(T) * (size_t)capacity, alignof(T), AT); end_ = begin_ + size; capacity_end_ = begin_ + capacity; uninitialized_relocate_n(other.begin_, size, begin_); @@ -302,14 +302,16 @@ class Vector { * Get the value at the given index. This invokes undefined behavior when the index is out of * bounds. */ - const T &operator[](uint index) const + const T &operator[](int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index < this->size()); return begin_[index]; } - T &operator[](uint index) + T &operator[](int64_t index) { + BLI_assert(index >= 0); BLI_assert(index < this->size()); return begin_[index]; } @@ -351,7 +353,7 @@ class Vector { * This won't necessarily make an allocation when min_capacity is small. * The actual size of the vector does not change. */ - void reserve(const uint min_capacity) + void reserve(const int64_t min_capacity) { if (min_capacity > this->capacity()) { this->realloc_to_at_least(min_capacity); @@ -364,9 +366,10 @@ class Vector { * destructed. If new_size is larger than the old size, the new elements at the end are default * constructed. If T is trivially constructible, the memory is not touched by this function. */ - void resize(const uint new_size) + void resize(const int64_t new_size) { - const uint old_size = this->size(); + BLI_assert(new_size >= 0); + const int64_t old_size = this->size(); if (new_size > old_size) { this->reserve(new_size); default_construct_n(begin_ + old_size, new_size - old_size); @@ -384,9 +387,10 @@ class Vector { * destructed. If new_size is larger than the old size, the new elements will be copy constructed * from the given value. */ - void resize(const uint new_size, const T &value) + void resize(const int64_t new_size, const T &value) { - const uint old_size = this->size(); + BLI_assert(new_size >= 0); + const int64_t old_size = this->size(); if (new_size > old_size) { this->reserve(new_size); uninitialized_fill_n(begin_ + old_size, new_size - old_size, value); @@ -447,9 +451,9 @@ class Vector { * Append the value to the vector and return the index that can be used to access the newly * added value. */ - uint append_and_get_index(const T &value) + int64_t append_and_get_index(const T &value) { - const uint index = this->size(); + const int64_t index = this->size(); this->append(value); return index; } @@ -490,8 +494,9 @@ class Vector { * Insert the same element n times at the end of the vector. * This might result in a reallocation internally. */ - void append_n_times(const T &value, const uint n) + void append_n_times(const T &value, const int64_t n) { + BLI_assert(n >= 0); this->reserve(this->size() + n); blender::uninitialized_fill_n(end_, n, value); this->increase_size_by_unchecked(n); @@ -503,7 +508,7 @@ class Vector { * useful when you want to call constructors in the vector yourself. This should only be done in * very rare cases and has to be justified every time. */ - void increase_size_by_unchecked(const uint n) + void increase_size_by_unchecked(const int64_t n) { BLI_assert(end_ + n <= capacity_end_); end_ += n; @@ -519,7 +524,7 @@ class Vector { { this->extend(array.data(), array.size()); } - void extend(const T *start, uint amount) + void extend(const T *start, int64_t amount) { this->reserve(this->size() + amount); this->extend_unchecked(start, amount); @@ -545,8 +550,9 @@ class Vector { { this->extend_unchecked(array.data(), array.size()); } - void extend_unchecked(const T *start, uint amount) + void extend_unchecked(const T *start, int64_t amount) { + BLI_assert(amount >= 0); BLI_assert(begin_ + amount <= capacity_end_); blender::uninitialized_copy_n(start, amount, end_); end_ += amount; @@ -569,28 +575,12 @@ class Vector { } /** - * Replace every element with a new value. - */ - void fill(const T &value) - { - initialized_fill_n(begin_, this->size(), value); - } - - /** - * Copy the value to all positions specified by the indices array. - */ - void fill_indices(Span<uint> indices, const T &value) - { - MutableSpan<T>(*this).fill_indices(indices, value); - } - - /** * Return how many values are currently stored in the vector. */ - uint size() const + int64_t size() const { - BLI_assert(debug_size_ == (uint)(end_ - begin_)); - return (uint)(end_ - begin_); + BLI_assert(debug_size_ == (int64_t)(end_ - begin_)); + return (int64_t)(end_ - begin_); } /** @@ -635,8 +625,9 @@ class Vector { * Delete any element in the vector. The empty space will be filled by the previously last * element. This takes O(1) time. */ - void remove_and_reorder(const uint index) + void remove_and_reorder(const int64_t index) { + BLI_assert(index >= 0); BLI_assert(index < this->size()); T *element_to_remove = begin_ + index; end_--; @@ -653,8 +644,8 @@ class Vector { */ void remove_first_occurrence_and_reorder(const T &value) { - const uint index = this->first_index_of(value); - this->remove_and_reorder((uint)index); + const int64_t index = this->first_index_of(value); + this->remove_and_reorder(index); } /** @@ -664,11 +655,12 @@ class Vector { * * This is similar to std::vector::erase. */ - void remove(const uint index) + void remove(const int64_t index) { + BLI_assert(index >= 0); BLI_assert(index < this->size()); - const uint last_index = this->size() - 1; - for (uint i = index; i < last_index; i++) { + const int64_t last_index = this->size() - 1; + for (int64_t i = index; i < last_index; i++) { begin_[i] = std::move(begin_[i + 1]); } begin_[last_index].~T(); @@ -680,11 +672,11 @@ class Vector { * Do a linear search to find the value in the vector. * When found, return the first index, otherwise return -1. */ - int first_index_of_try(const T &value) const + int64_t first_index_of_try(const T &value) const { for (const T *current = begin_; current != end_; current++) { if (*current == value) { - return (int)(current - begin_); + return (int64_t)(current - begin_); } } return -1; @@ -694,11 +686,11 @@ class Vector { * Do a linear search to find the value in the vector and return the found index. This invokes * undefined behavior when the value is not in the vector. */ - uint first_index_of(const T &value) const + int64_t first_index_of(const T &value) const { - const int index = this->first_index_of_try(value); + const int64_t index = this->first_index_of_try(value); BLI_assert(index >= 0); - return (uint)index; + return index; } /** @@ -711,6 +703,14 @@ class Vector { } /** + * Copies the given value to every element in the vector. + */ + void fill(const T &value) const + { + initialized_fill_n(begin_, this->size(), value); + } + + /** * Get access to the underlying array. */ T *data() @@ -748,9 +748,9 @@ class Vector { * Get the current capacity of the vector, i.e. the maximum number of elements the vector can * hold, before it has to reallocate. */ - uint capacity() const + int64_t capacity() const { - return (uint)(capacity_end_ - begin_); + return (int64_t)(capacity_end_ - begin_); } /** @@ -758,7 +758,7 @@ class Vector { * Obviously, this should only be used when you actually need the index in the loop. * * Example: - * for (uint i : myvector.index_range()) { + * for (int64_t i : myvector.index_range()) { * do_something(i, my_vector[i]); * } */ @@ -796,7 +796,7 @@ class Vector { } } - BLI_NOINLINE void realloc_to_at_least(const uint min_capacity) + BLI_NOINLINE void realloc_to_at_least(const int64_t min_capacity) { if (this->capacity() >= min_capacity) { return; @@ -804,12 +804,12 @@ class Vector { /* At least double the size of the previous allocation. Otherwise consecutive calls to grow can * cause a reallocation every time even though min_capacity only increments. */ - const uint min_new_capacity = this->capacity() * 2; + const int64_t min_new_capacity = this->capacity() * 2; - const uint new_capacity = std::max(min_capacity, min_new_capacity); - const uint size = this->size(); + const int64_t new_capacity = std::max(min_capacity, min_new_capacity); + const int64_t size = this->size(); - T *new_array = (T *)allocator_.allocate(new_capacity * (uint)sizeof(T), alignof(T), AT); + T *new_array = (T *)allocator_.allocate((size_t)new_capacity * sizeof(T), alignof(T), AT); uninitialized_relocate_n(begin_, size, new_array); if (!this->is_inline()) { @@ -824,6 +824,13 @@ class Vector { #undef UPDATE_VECTOR_SIZE +/** + * Same as a normal Vector, but does not use Blender's guarded allocator. This is useful when + * allocating memory with static storage duration. + */ +template<typename T, int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(T))> +using RawVector = Vector<T, InlineBufferCapacity, RawAllocator>; + } /* namespace blender */ #endif /* __BLI_VECTOR_HH__ */ diff --git a/source/blender/blenlib/BLI_vector_set.hh b/source/blender/blenlib/BLI_vector_set.hh index dd1b17653c0..f007d41118f 100644 --- a/source/blender/blenlib/BLI_vector_set.hh +++ b/source/blender/blenlib/BLI_vector_set.hh @@ -106,20 +106,20 @@ class VectorSet { * Slots are either empty, occupied or removed. The number of occupied slots can be computed by * subtracting the removed slots from the occupied-and-removed slots. */ - uint32_t removed_slots_; - uint32_t occupied_and_removed_slots_; + int64_t removed_slots_; + int64_t occupied_and_removed_slots_; /** * The maximum number of slots that can be used (either occupied or removed) until the set has to * grow. This is the total number of slots times the max load factor. */ - uint32_t usable_slots_; + int64_t usable_slots_; /** * The number of slots minus one. This is a bit mask that can be used to turn any integer into a * valid slot index efficiently. */ - uint32_t slot_mask_; + uint64_t slot_mask_; /** This is called to hash incoming keys. */ Hash hash_; @@ -238,8 +238,9 @@ class VectorSet { /** * Get the key stored at the given position in the vector. */ - const Key &operator[](const uint32_t index) const + const Key &operator[](const int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index <= this->size()); return keys_[index]; } @@ -362,11 +363,11 @@ class VectorSet { * Return the location of the key in the vector. It is assumed, that the key is in the vector * set. If this is not necessarily the case, use `index_of_try`. */ - uint32_t index_of(const Key &key) const + int64_t index_of(const Key &key) const { return this->index_of_as(key); } - template<typename ForwardKey> uint32_t index_of_as(const ForwardKey &key) const + template<typename ForwardKey> int64_t index_of_as(const ForwardKey &key) const { return this->index_of__impl(key, hash_(key)); } @@ -375,11 +376,11 @@ class VectorSet { * Return the location of the key in the vector. If the key is not in the set, -1 is returned. * If you know for sure that the key is in the set, it is better to use `index_of` instead. */ - int32_t index_of_try(const Key &key) const + int64_t index_of_try(const Key &key) const { - return (int32_t)this->index_of_try_as(key); + return this->index_of_try_as(key); } - template<typename ForwardKey> int32_t index_of_try_as(const ForwardKey &key) const + template<typename ForwardKey> int64_t index_of_try_as(const ForwardKey &key) const { return this->index_of_try__impl(key, hash_(key)); } @@ -414,7 +415,7 @@ class VectorSet { /** * Returns the number of keys stored in the vector set. */ - uint32_t size() const + int64_t size() const { return occupied_and_removed_slots_ - removed_slots_; } @@ -430,7 +431,7 @@ class VectorSet { /** * Returns the number of available slots. This is mostly for debugging purposes. */ - uint32_t capacity() const + int64_t capacity() const { return slots_.size(); } @@ -438,7 +439,7 @@ class VectorSet { /** * Returns the amount of removed slots in the set. This is mostly for debugging purposes. */ - uint32_t removed_amount() const + int64_t removed_amount() const { return removed_slots_; } @@ -446,7 +447,7 @@ class VectorSet { /** * Returns the bytes required per element. This is mostly for debugging purposes. */ - uint32_t size_per_element() const + int64_t size_per_element() const { return sizeof(Slot) + sizeof(Key); } @@ -455,15 +456,15 @@ class VectorSet { * Returns the approximate memory requirements of the set in bytes. This is more correct for * larger sets. */ - uint32_t size_in_bytes() const + int64_t size_in_bytes() const { - return (uint32_t)(sizeof(Slot) * slots_.size() + sizeof(Key) * usable_slots_); + return (int64_t)(sizeof(Slot) * slots_.size() + sizeof(Key) * usable_slots_); } /** * Potentially resize the vector set such that it can hold n elements without doing another grow. */ - void reserve(const uint32_t n) + void reserve(const int64_t n) { if (usable_slots_ < n) { this->realloc_and_reinsert(n); @@ -474,18 +475,19 @@ class VectorSet { * Get the number of collisions that the probing strategy has to go through to find the key or * determine that it is not in the set. */ - uint32_t count_collisions(const Key &key) const + int64_t count_collisions(const Key &key) const { return this->count_collisions__impl(key, hash_(key)); } private: - BLI_NOINLINE void realloc_and_reinsert(const uint32_t min_usable_slots) + BLI_NOINLINE void realloc_and_reinsert(const int64_t min_usable_slots) { - uint32_t total_slots, usable_slots; + int64_t total_slots, usable_slots; max_load_factor_.compute_total_and_usable_slots( SlotArray::inline_buffer_capacity(), min_usable_slots, &total_slots, &usable_slots); - const uint32_t new_slot_mask = total_slots - 1; + BLI_assert(total_slots >= 1); + const uint64_t new_slot_mask = (uint64_t)total_slots - 1; /* Optimize the case when the set was empty beforehand. We can avoid some copies here. */ if (this->size() == 0) { @@ -524,10 +526,10 @@ class VectorSet { void add_after_grow_and_destruct_old(Slot &old_slot, SlotArray &new_slots, - const uint32_t new_slot_mask) + const uint64_t new_slot_mask) { const Key &key = keys_[old_slot.index()]; - const uint32_t hash = old_slot.get_hash(key, Hash()); + const uint64_t hash = old_slot.get_hash(key, Hash()); SLOT_PROBING_BEGIN (ProbingStrategy, hash, new_slot_mask, slot_index) { Slot &slot = new_slots[slot_index]; @@ -540,7 +542,7 @@ class VectorSet { } template<typename ForwardKey> - bool contains__impl(const ForwardKey &key, const uint32_t hash) const + bool contains__impl(const ForwardKey &key, const uint64_t hash) const { VECTOR_SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.is_empty()) { @@ -553,7 +555,7 @@ class VectorSet { VECTOR_SET_SLOT_PROBING_END(); } - template<typename ForwardKey> void add_new__impl(ForwardKey &&key, const uint32_t hash) + template<typename ForwardKey> void add_new__impl(ForwardKey &&key, const uint64_t hash) { BLI_assert(!this->contains_as(key)); @@ -561,7 +563,7 @@ class VectorSet { VECTOR_SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.is_empty()) { - uint32_t index = this->size(); + int64_t index = this->size(); new (keys_ + index) Key(std::forward<ForwardKey>(key)); slot.occupy(index, hash); occupied_and_removed_slots_++; @@ -571,13 +573,13 @@ class VectorSet { VECTOR_SET_SLOT_PROBING_END(); } - template<typename ForwardKey> bool add__impl(ForwardKey &&key, const uint32_t hash) + template<typename ForwardKey> bool add__impl(ForwardKey &&key, const uint64_t hash) { this->ensure_can_add(); VECTOR_SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.is_empty()) { - uint32_t index = this->size(); + int64_t index = this->size(); new (keys_ + index) Key(std::forward<ForwardKey>(key)); occupied_and_removed_slots_++; slot.occupy(index, hash); @@ -591,7 +593,7 @@ class VectorSet { } template<typename ForwardKey> - uint32_t index_of__impl(const ForwardKey &key, const uint32_t hash) const + int64_t index_of__impl(const ForwardKey &key, const uint64_t hash) const { BLI_assert(this->contains_as(key)); @@ -604,11 +606,11 @@ class VectorSet { } template<typename ForwardKey> - int32_t index_of_try__impl(const ForwardKey &key, const uint32_t hash) const + int64_t index_of_try__impl(const ForwardKey &key, const uint64_t hash) const { VECTOR_SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash, keys_)) { - return (int32_t)slot.index(); + return slot.index(); } if (slot.is_empty()) { return -1; @@ -621,10 +623,10 @@ class VectorSet { { BLI_assert(this->size() > 0); - const uint32_t index_to_pop = this->size() - 1; + const int64_t index_to_pop = this->size() - 1; Key key = std::move(keys_[index_to_pop]); keys_[index_to_pop].~Key(); - const uint32_t hash = hash_(key); + const uint64_t hash = hash_(key); removed_slots_++; @@ -637,7 +639,7 @@ class VectorSet { VECTOR_SET_SLOT_PROBING_END(); } - template<typename ForwardKey> bool remove__impl(const ForwardKey &key, const uint32_t hash) + template<typename ForwardKey> bool remove__impl(const ForwardKey &key, const uint64_t hash) { VECTOR_SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash, keys_)) { @@ -652,7 +654,7 @@ class VectorSet { } template<typename ForwardKey> - void remove_contained__impl(const ForwardKey &key, const uint32_t hash) + void remove_contained__impl(const ForwardKey &key, const uint64_t hash) { BLI_assert(this->contains_as(key)); @@ -667,9 +669,9 @@ class VectorSet { void remove_key_internal(Slot &slot) { - uint32_t index_to_remove = slot.index(); - uint32_t size = this->size(); - uint32_t last_element_index = size - 1; + int64_t index_to_remove = slot.index(); + int64_t size = this->size(); + int64_t last_element_index = size - 1; if (index_to_remove < last_element_index) { keys_[index_to_remove] = std::move(keys_[last_element_index]); @@ -682,9 +684,9 @@ class VectorSet { return; } - void update_slot_index(const Key &key, const uint32_t old_index, const uint32_t new_index) + void update_slot_index(const Key &key, const int64_t old_index, const int64_t new_index) { - uint32_t hash = hash_(key); + uint64_t hash = hash_(key); VECTOR_SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.has_index(old_index)) { slot.update_index(new_index); @@ -695,9 +697,9 @@ class VectorSet { } template<typename ForwardKey> - uint32_t count_collisions__impl(const ForwardKey &key, const uint32_t hash) const + int64_t count_collisions__impl(const ForwardKey &key, const uint64_t hash) const { - uint32_t collisions = 0; + int64_t collisions = 0; VECTOR_SET_SLOT_PROBING_BEGIN (hash, slot) { if (slot.contains(key, is_equal_, hash, keys_)) { @@ -719,9 +721,9 @@ class VectorSet { } } - Key *allocate_keys_array(const uint32_t size) + Key *allocate_keys_array(const int64_t size) { - return (Key *)slots_.allocator().allocate((uint32_t)sizeof(Key) * size, alignof(Key), AT); + return (Key *)slots_.allocator().allocate(sizeof(Key) * (size_t)size, alignof(Key), AT); } void deallocate_keys_array(Key *keys) @@ -730,6 +732,17 @@ class VectorSet { } }; +/** + * Same as a normal VectorSet, but does not use Blender's guarded allocator. This is useful when + * allocating memory with static storage duration. + */ +template<typename Key, + typename ProbingStrategy = DefaultProbingStrategy, + typename Hash = DefaultHash<Key>, + typename IsEqual = DefaultEquality, + typename Slot = typename DefaultVectorSetSlot<Key>::type> +using RawVectorSet = VectorSet<Key, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator>; + } // namespace blender #endif /* __BLI_VECTOR_SET_HH__ */ diff --git a/source/blender/blenlib/BLI_vector_set_slots.hh b/source/blender/blenlib/BLI_vector_set_slots.hh index e43b892b3f7..49e6d4daedb 100644 --- a/source/blender/blenlib/BLI_vector_set_slots.hh +++ b/source/blender/blenlib/BLI_vector_set_slots.hh @@ -53,7 +53,7 @@ template<typename Key> class SimpleVectorSetSlot { /** * After the default constructor has run, the slot has to be in the empty state. */ - int32_t state_ = s_is_empty; + int64_t state_ = s_is_empty; public: /** @@ -75,10 +75,10 @@ template<typename Key> class SimpleVectorSetSlot { /** * Return the stored index. It is assumed that the slot is occupied. */ - uint32_t index() const + int64_t index() const { BLI_assert(this->is_occupied()); - return (uint32_t)state_; + return state_; } /** @@ -88,7 +88,7 @@ template<typename Key> class SimpleVectorSetSlot { template<typename ForwardKey, typename IsEqual> bool contains(const ForwardKey &key, const IsEqual &is_equal, - uint32_t UNUSED(hash), + uint64_t UNUSED(hash), const Key *keys) const { if (state_ >= 0) { @@ -102,7 +102,7 @@ template<typename Key> class SimpleVectorSetSlot { * we can avoid a comparison with the state, since we know the slot is occupied. For this * specific slot implementation, this does not make a difference. */ - void relocate_occupied_here(SimpleVectorSetSlot &other, uint32_t UNUSED(hash)) + void relocate_occupied_here(SimpleVectorSetSlot &other, uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); BLI_assert(other.is_occupied()); @@ -113,20 +113,20 @@ template<typename Key> class SimpleVectorSetSlot { * Change the state of this slot from empty/removed to occupied. The hash can be used by other * slot implementations. */ - void occupy(uint32_t index, uint32_t UNUSED(hash)) + void occupy(int64_t index, uint64_t UNUSED(hash)) { BLI_assert(!this->is_occupied()); - state_ = (int32_t)index; + state_ = index; } /** * The key has changed its position in the vector, so the index has to be updated. This method * can assume that the slot is currently occupied. */ - void update_index(uint32_t index) + void update_index(int64_t index) { BLI_assert(this->is_occupied()); - state_ = (int32_t)index; + state_ = index; } /** @@ -141,16 +141,16 @@ template<typename Key> class SimpleVectorSetSlot { /** * Return true if this slot is currently occupied and its corresponding key has the given index. */ - bool has_index(uint32_t index) const + bool has_index(int64_t index) const { - return (uint32_t)state_ == index; + return state_ == index; } /** * Return the hash of the currently stored key. In this simple set slot implementation, we just * compute the hash here. Other implementations might store the hash in the slot instead. */ - template<typename Hash> uint32_t get_hash(const Key &key, const Hash &hash) const + template<typename Hash> uint64_t get_hash(const Key &key, const Hash &hash) const { BLI_assert(this->is_occupied()); return hash(key); diff --git a/source/blender/blenlib/intern/BLI_index_range.cc b/source/blender/blenlib/intern/BLI_index_range.cc index 9fa19143f91..43c6265a17d 100644 --- a/source/blender/blenlib/intern/BLI_index_range.cc +++ b/source/blender/blenlib/intern/BLI_index_range.cc @@ -24,28 +24,28 @@ namespace blender { -static Vector<Array<uint, 0, RawAllocator>, 1, RawAllocator> arrays; -static uint current_array_size = 0; -static uint *current_array = nullptr; +static RawVector<RawArray<int64_t, 0>> arrays; +static int64_t current_array_size = 0; +static int64_t *current_array = nullptr; static std::mutex current_array_mutex; -Span<uint> IndexRange::as_span() const +Span<int64_t> IndexRange::as_span() const { - uint min_required_size = start_ + size_; + int64_t min_required_size = start_ + size_; if (min_required_size <= current_array_size) { - return Span<uint>(current_array + start_, size_); + return Span<int64_t>(current_array + start_, size_); } std::lock_guard<std::mutex> lock(current_array_mutex); if (min_required_size <= current_array_size) { - return Span<uint>(current_array + start_, size_); + return Span<int64_t>(current_array + start_, size_); } - uint new_size = std::max<uint>(1000, power_of_2_max_u(min_required_size)); - Array<uint, 0, RawAllocator> new_array(new_size); - for (uint i = 0; i < new_size; i++) { + int64_t new_size = std::max<int64_t>(1000, power_of_2_max_u(min_required_size)); + RawArray<int64_t, 0> new_array(new_size); + for (int64_t i = 0; i < new_size; i++) { new_array[i] = i; } arrays.append(std::move(new_array)); @@ -54,7 +54,7 @@ Span<uint> IndexRange::as_span() const std::atomic_thread_fence(std::memory_order_seq_cst); current_array_size = new_size; - return Span<uint>(current_array + start_, size_); + return Span<int64_t>(current_array + start_, size_); } } // namespace blender diff --git a/source/blender/blenlib/intern/dot_export.cc b/source/blender/blenlib/intern/dot_export.cc index 0f60ea6fd1b..48b6dc826d0 100644 --- a/source/blender/blenlib/intern/dot_export.cc +++ b/source/blender/blenlib/intern/dot_export.cc @@ -263,8 +263,8 @@ NodeWithSocketsRef::NodeWithSocketsRef(Node &node, ss << "</b></td></tr>"; /* Sockets */ - uint socket_max_amount = std::max(input_names.size(), output_names.size()); - for (uint i = 0; i < socket_max_amount; i++) { + int socket_max_amount = std::max(input_names.size(), output_names.size()); + for (int i = 0; i < socket_max_amount; i++) { ss << "<tr>"; if (i < input_names.size()) { StringRef name = input_names[i]; diff --git a/source/blender/blenlib/intern/rand.cc b/source/blender/blenlib/intern/rand.cc index 279682ea171..9bafc422db5 100644 --- a/source/blender/blenlib/intern/rand.cc +++ b/source/blender/blenlib/intern/rand.cc @@ -93,8 +93,7 @@ void BLI_rng_srandom(RNG *rng, unsigned int seed) void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len) { - BLI_assert(bytes_len > UINT32_MAX); - rng->rng.get_bytes(blender::MutableSpan(bytes, (uint32_t)bytes_len)); + rng->rng.get_bytes(blender::MutableSpan(bytes, (int64_t)bytes_len)); } int BLI_rng_get_int(RNG *rng) @@ -428,11 +427,11 @@ float2 RandomNumberGenerator::get_triangle_sample(float2 v1, float2 v2, float2 v void RandomNumberGenerator::get_bytes(MutableSpan<char> r_bytes) { - constexpr uint mask_bytes = 2; - constexpr uint rand_stride = (uint)sizeof(x_) - mask_bytes; + constexpr int64_t mask_bytes = 2; + constexpr int64_t rand_stride = (int64_t)sizeof(x_) - mask_bytes; - uint last_len = 0; - uint trim_len = r_bytes.size(); + int64_t last_len = 0; + int64_t trim_len = r_bytes.size(); if (trim_len > rand_stride) { last_len = trim_len % rand_stride; @@ -444,13 +443,13 @@ void RandomNumberGenerator::get_bytes(MutableSpan<char> r_bytes) } const char *data_src = (const char *)&x_; - uint i = 0; + int64_t i = 0; while (i != trim_len) { BLI_assert(i < trim_len); #ifdef __BIG_ENDIAN__ - for (uint j = (rand_stride + mask_bytes) - 1; j != mask_bytes - 1; j--) + for (int64_t j = (rand_stride + mask_bytes) - 1; j != mask_bytes - 1; j--) #else - for (uint j = 0; j != rand_stride; j++) + for (int64_t j = 0; j != rand_stride; j++) #endif { r_bytes[i++] = data_src[j]; @@ -458,7 +457,7 @@ void RandomNumberGenerator::get_bytes(MutableSpan<char> r_bytes) this->step(); } if (last_len) { - for (uint j = 0; j != last_len; j++) { + for (int64_t j = 0; j != last_len; j++) { r_bytes[i++] = data_src[j]; } } diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index f17c04a8a5c..12da7629017 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -197,6 +197,14 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) * \note Keep this message at the bottom of the function. */ { + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_cycles_fix(bmain, collection)) { + printf( + "WARNING: Cycle detected in collection '%s', fixed as best as possible.\n" + "You may have to reconstruct your View Layers...\n", + collection->id.name); + } + } /* Keep this block, even when empty. */ } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc index 1095905c570..750bccf0e52 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc @@ -72,11 +72,11 @@ bool operator==(const AnimatedPropertyID &a, const AnimatedPropertyID &b) return a.data == b.data && a.property_rna == b.property_rna; } -uint32_t AnimatedPropertyID::hash() const +uint64_t AnimatedPropertyID::hash() const { uintptr_t ptr1 = (uintptr_t)data; uintptr_t ptr2 = (uintptr_t)property_rna; - return (uint32_t)(((ptr1 >> 4) * 33) ^ (ptr2 >> 4)); + return (uint64_t)(((ptr1 >> 4) * 33) ^ (ptr2 >> 4)); } namespace { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.h b/source/blender/depsgraph/intern/builder/deg_builder_cache.h index 43348e3bf23..e04ae3a3727 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.h @@ -47,7 +47,7 @@ class AnimatedPropertyID { AnimatedPropertyID(ID *id, StructRNA *type, const char *property_name); AnimatedPropertyID(ID *id, StructRNA *type, void *data, const char *property_name); - uint32_t hash() const; + uint64_t hash() const; friend bool operator==(const AnimatedPropertyID &a, const AnimatedPropertyID &b); /* Corresponds to PointerRNA.data. */ diff --git a/source/blender/depsgraph/intern/depsgraph_registry.cc b/source/blender/depsgraph/intern/depsgraph_registry.cc index 6bfd2e881cc..c9d03e47ded 100644 --- a/source/blender/depsgraph/intern/depsgraph_registry.cc +++ b/source/blender/depsgraph/intern/depsgraph_registry.cc @@ -30,7 +30,7 @@ namespace blender { namespace deg { -static Map<Main *, VectorSet<Depsgraph *>> g_graph_registry; +static RawMap<Main *, RawVectorSet<Depsgraph *>> g_graph_registry; void register_graph(Depsgraph *depsgraph) { @@ -41,7 +41,7 @@ void register_graph(Depsgraph *depsgraph) void unregister_graph(Depsgraph *depsgraph) { Main *bmain = depsgraph->bmain; - VectorSet<Depsgraph *> &graphs = g_graph_registry.lookup(bmain); + RawVectorSet<Depsgraph *> &graphs = g_graph_registry.lookup(bmain); graphs.remove(depsgraph); // If this was the last depsgraph associated with the main, remove the main entry as well. @@ -52,7 +52,7 @@ void unregister_graph(Depsgraph *depsgraph) Span<Depsgraph *> get_all_registered_graphs(Main *bmain) { - VectorSet<Depsgraph *> *graphs = g_graph_registry.lookup_ptr(bmain); + RawVectorSet<Depsgraph *> *graphs = g_graph_registry.lookup_ptr(bmain); if (graphs != nullptr) { return *graphs; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc index f2d9a87ca9d..934403674a9 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc @@ -41,7 +41,7 @@ bool operator==(const ModifierDataBackupID &a, const ModifierDataBackupID &b) return a.modifier_data == b.modifier_data && a.type == b.type; } -uint32_t ModifierDataBackupID::hash() const +uint64_t ModifierDataBackupID::hash() const { uintptr_t ptr = (uintptr_t)modifier_data; return (ptr >> 4) ^ (uintptr_t)type; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h index dc16bdcc1b8..a5bdf2359ee 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h @@ -49,7 +49,7 @@ class ModifierDataBackupID { friend bool operator==(const ModifierDataBackupID &a, const ModifierDataBackupID &b); - uint32_t hash() const; + uint64_t hash() const; ModifierData *modifier_data; ModifierType type; diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index 34514ba9bd7..cd82b7be050 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -72,7 +72,7 @@ bool ComponentNode::OperationIDKey::operator==(const OperationIDKey &other) cons return (opcode == other.opcode) && (STREQ(name, other.name)) && (name_tag == other.name_tag); } -uint32_t ComponentNode::OperationIDKey::hash() const +uint64_t ComponentNode::OperationIDKey::hash() const { const int opcode_as_int = static_cast<int>(opcode); return BLI_ghashutil_combine_hash( diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h index 3757a1dea5b..06582c88d8b 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.h +++ b/source/blender/depsgraph/intern/node/deg_node_component.h @@ -54,7 +54,7 @@ struct ComponentNode : public Node { string identifier() const; bool operator==(const OperationIDKey &other) const; - uint32_t hash() const; + uint64_t hash() const; }; /* Typedef for container of operations */ diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index d0c23f326ce..8d19949adc8 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -67,7 +67,7 @@ bool IDNode::ComponentIDKey::operator==(const ComponentIDKey &other) const return type == other.type && STREQ(name, other.name); } -uint32_t IDNode::ComponentIDKey::hash() const +uint64_t IDNode::ComponentIDKey::hash() const { const int type_as_int = static_cast<int>(type); return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int), diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index 9bd6130bbdc..04a9006ac10 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -51,7 +51,7 @@ const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state); struct IDNode : public Node { struct ComponentIDKey { ComponentIDKey(NodeType type, const char *name = ""); - uint32_t hash() const; + uint64_t hash() const; bool operator==(const ComponentIDKey &other) const; NodeType type; diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 6c835c6d7ae..bc4efd82a03 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -43,6 +43,7 @@ struct GPUViewport; struct ID; struct Main; struct Object; +struct Render; struct RenderEngine; struct RenderEngineType; struct Scene; @@ -137,6 +138,9 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph struct DRWInstanceDataList *DRW_instance_data_list_create(void); void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist); +void DRW_render_context_enable(struct Render *render); +void DRW_render_context_disable(struct Render *render); + void DRW_opengl_context_create(void); void DRW_opengl_context_destroy(void); void DRW_opengl_context_enable(void); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index bac96ab1079..f42c60b04bf 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -601,7 +601,7 @@ RenderEngineType DRW_engine_viewport_eevee_type = { NULL, EEVEE_ENGINE, N_("Eevee"), - RE_INTERNAL | RE_USE_PREVIEW | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_PREVIEW | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, &DRW_render_to_image, NULL, diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index bb7c947a0b9..8cee6c4ee9f 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -378,7 +378,7 @@ RenderEngineType DRW_engine_viewport_select_type = { NULL, SELECT_ENGINE, N_("Select ID"), - RE_INTERNAL | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, NULL, NULL, diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 5fff55e2f26..53119723fab 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -641,7 +641,7 @@ RenderEngineType DRW_engine_viewport_workbench_type = { NULL, WORKBENCH_ENGINE, N_("Workbench"), - RE_INTERNAL | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, &DRW_render_to_image, NULL, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 08fb80c11d2..712a93e8880 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1660,24 +1660,8 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph RenderEngineType *engine_type = engine->type; RenderData *r = &scene->r; Render *render = engine->re; - /* Changing Context */ - if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); - } - void *re_gl_context = RE_gl_context_get(render); - void *re_gpu_context = NULL; - - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_opengl_render_context_enable(re_gl_context); - /* We need to query gpu context after a gl context has been bound. */ - re_gpu_context = RE_gpu_context_get(render); - DRW_gpu_render_context_enable(re_gpu_context); - } - else { - DRW_opengl_context_enable(); - } + DRW_render_context_enable(render); /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -1729,14 +1713,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph /* Restore Drawing area. */ GPU_framebuffer_restore(); - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_gpu_render_context_disable(re_gpu_context); - DRW_opengl_render_context_disable(re_gl_context); - } - else { - DRW_opengl_context_disable(); - } + DRW_render_context_disable(render); DST.buffer_finish_called = false; } @@ -1749,24 +1726,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) DrawEngineType *draw_engine_type = engine_type->draw_engine; Render *render = engine->re; - if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); - } - - void *re_gl_context = RE_gl_context_get(render); - void *re_gpu_context = NULL; - - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_opengl_render_context_enable(re_gl_context); - /* We need to query gpu context after a gl context has been bound. */ - re_gpu_context = RE_gpu_context_get(render); - DRW_gpu_render_context_enable(re_gpu_context); - } - else { - DRW_opengl_context_enable(); - } - /* IMPORTANT: We don't support immediate mode in render mode! * This shall remain in effect until immediate mode supports * multiple threads. */ @@ -1842,15 +1801,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* Reset state after drawing */ DRW_state_reset(); - - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_gpu_render_context_disable(re_gpu_context); - DRW_opengl_render_context_disable(re_gl_context); - } - else { - DRW_opengl_context_disable(); - } } void DRW_render_object_iter( @@ -2763,6 +2713,42 @@ void DRW_engines_free(void) DRW_opengl_context_disable(); } +void DRW_render_context_enable(Render *render) +{ + if (G.background && DST.gl_context == NULL) { + WM_init_opengl(G_MAIN); + } + + void *re_gl_context = RE_gl_context_get(render); + + /* Changing Context */ + if (re_gl_context != NULL) { + DRW_opengl_render_context_enable(re_gl_context); + /* We need to query gpu context after a gl context has been bound. */ + void *re_gpu_context = NULL; + re_gpu_context = RE_gpu_context_get(render); + DRW_gpu_render_context_enable(re_gpu_context); + } + else { + DRW_opengl_context_enable(); + } +} + +void DRW_render_context_disable(Render *render) +{ + void *re_gl_context = RE_gl_context_get(render); + + if (re_gl_context != NULL) { + void *re_gpu_context = NULL; + re_gpu_context = RE_gpu_context_get(render); + DRW_gpu_render_context_disable(re_gpu_context); + DRW_opengl_render_context_disable(re_gl_context); + } + else { + DRW_opengl_context_disable(); + } +} + /** \} */ /** \name Init/Exit (DRW_opengl_ctx) @@ -2903,8 +2889,8 @@ void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context)) * switch to it just to submit the final frame, which has notable performance impact. * * We could "inject" a context through DRW_opengl_render_context_enable(), but that would have to - * work from the main thread, which is tricky to get working too. The preferable solution would be - * using a separate thread for VR drawing where a single context can stay active. */ + * work from the main thread, which is tricky to get working too. The preferable solution would + * be using a separate thread for VR drawing where a single context can stay active. */ void *DRW_xr_opengl_context_get(void) { return DST.gl_context; diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 79c465c1f33..53401e0c05a 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -4708,6 +4708,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi ReportList *reports = CTX_wm_reports(C); Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); ToolSettings *ts = scene->toolsettings; ListBase nla_cache = {NULL, NULL}; PointerRNA id_ptr, ptr; @@ -4720,8 +4721,10 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi RNA_id_pointer_create(id, &id_ptr); /* Get NLA context for value remapping */ + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + (float)CFRA); NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context( - &nla_cache, &id_ptr, adt, (float)CFRA, false); + &nla_cache, &id_ptr, adt, &anim_eval_context, false); /* get current frame and apply NLA-mapping to it (if applicable) */ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); @@ -4738,7 +4741,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi /* insert a keyframe for this F-Curve */ done = insert_keyframe_direct( - reports, ptr, prop, fcu, cfra, ts->keyframe_type, nla_context, flag); + reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, nla_context, flag); if (done) { if (adt->action != NULL) { @@ -4762,23 +4765,26 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi ReportList *reports = CTX_wm_reports(C); Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); ToolSettings *ts = scene->toolsettings; ListBase nla_cache = {NULL, NULL}; PointerRNA id_ptr, ptr; PropertyRNA *prop; eInsertKeyFlags flag = 0; bool done = false; - float cfra; /* Get RNA pointer */ RNA_id_pointer_create((ID *)key, &id_ptr); /* Get NLA context for value remapping */ + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + (float)CFRA); NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context( - &nla_cache, &id_ptr, key->adt, (float)CFRA, false); + &nla_cache, &id_ptr, key->adt, &anim_eval_context, false); /* get current frame and apply NLA-mapping to it (if applicable) */ - cfra = BKE_nla_tweakedit_remap(key->adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + const float remapped_frame = BKE_nla_tweakedit_remap( + key->adt, anim_eval_context.eval_time, NLATIME_CONVERT_UNMAP); /* get flags for keyframing */ flag = ANIM_get_keyframing_flags(scene, true); @@ -4791,13 +4797,21 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi FCurve *fcu = ED_action_fcurve_ensure(bmain, act, NULL, &ptr, rna_path, 0); /* set the special 'replace' flag if on a keyframe */ - if (fcurve_frame_has_keyframe(fcu, cfra, 0)) { + if (fcurve_frame_has_keyframe(fcu, remapped_frame, 0)) { flag |= INSERTKEY_REPLACE; } /* insert a keyframe for this F-Curve */ - done = insert_keyframe_direct( - reports, ptr, prop, fcu, cfra, ts->keyframe_type, nla_context, flag); + const AnimationEvalContext remapped_anim_eval_context = BKE_animsys_eval_context_construct_at( + &anim_eval_context, remapped_frame); + done = insert_keyframe_direct(reports, + ptr, + prop, + fcu, + &remapped_anim_eval_context, + ts->keyframe_type, + nla_context, + flag); if (done) { WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); @@ -4848,7 +4862,11 @@ static void achannel_setting_slider_nla_curve_cb(bContext *C, } /* insert a keyframe for this F-Curve */ - done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, flag); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + cfra); + done = insert_keyframe_direct( + reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, flag); if (done) { WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index bbb673caa71..50733afe6fb 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -419,6 +419,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) ac->markers = ED_context_get_markers(C); } ac->view_layer = CTX_data_view_layer(C); + ac->depsgraph = CTX_data_depsgraph_pointer(C); ac->obact = (ac->view_layer->basact) ? ac->view_layer->basact->object : NULL; ac->area = area; ac->region = region; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 9cb41e06aa0..8c2f4216aa9 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1113,7 +1113,7 @@ static bool insert_keyframe_value(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, FCurve *fcu, - float cfra, + const AnimationEvalContext *anim_eval_context, float curval, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag) @@ -1130,13 +1130,15 @@ static bool insert_keyframe_value(ReportList *reports, return false; } + float cfra = anim_eval_context->eval_time; + /* adjust frame on which to add keyframe */ if ((flag & INSERTKEY_DRIVER) && (fcu->driver)) { PathResolvedRNA anim_rna; if (RNA_path_resolved_create(ptr, prop, fcu->array_index, &anim_rna)) { /* for making it easier to add corrective drivers... */ - cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra); + cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, anim_eval_context); } else { cfra = 0.0f; @@ -1202,7 +1204,7 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, - float cfra, + const AnimationEvalContext *anim_eval_context, eBezTriple_KeyframeType keytype, struct NlaKeyframingContext *nla_context, eInsertKeyFlags flag) @@ -1274,7 +1276,7 @@ bool insert_keyframe_direct(ReportList *reports, MEM_freeN(values); } - return insert_keyframe_value(reports, &ptr, prop, fcu, cfra, curval, keytype, flag); + return insert_keyframe_value(reports, &ptr, prop, fcu, anim_eval_context, curval, keytype, flag); } /* Find or create the FCurve based on the given path, and insert the specified value into it. */ @@ -1286,7 +1288,7 @@ static bool insert_keyframe_fcurve_value(Main *bmain, const char group[], const char rna_path[], int array_index, - float cfra, + const AnimationEvalContext *anim_eval_context, float curval, eBezTriple_KeyframeType keytype, eInsertKeyFlags flag) @@ -1320,12 +1322,35 @@ static bool insert_keyframe_fcurve_value(Main *bmain, update_autoflags_fcurve_direct(fcu, prop); /* insert keyframe */ - return insert_keyframe_value(reports, ptr, prop, fcu, cfra, curval, keytype, flag); + return insert_keyframe_value( + reports, ptr, prop, fcu, anim_eval_context, curval, keytype, flag); } return false; } +static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval_context, + PointerRNA *id_ptr, + AnimData *adt, + bAction *act, + ListBase *nla_cache, + NlaKeyframingContext **r_nla_context) +{ + if (adt && adt->action == act) { + /* Get NLA context for value remapping. */ + *r_nla_context = BKE_animsys_get_nla_keyframing_context( + nla_cache, id_ptr, adt, anim_eval_context, false); + + /* Apply NLA-mapping to frame. */ + const float remapped_frame = BKE_nla_tweakedit_remap( + adt, anim_eval_context->eval_time, NLATIME_CONVERT_UNMAP); + return BKE_animsys_eval_context_construct_at(anim_eval_context, remapped_frame); + } + + *r_nla_context = NULL; + return *anim_eval_context; +} + /** * Main Keyframing API call * @@ -1346,7 +1371,7 @@ int insert_keyframe(Main *bmain, const char group[], const char rna_path[], int array_index, - float cfra, + const AnimationEvalContext *anim_eval_context, eBezTriple_KeyframeType keytype, ListBase *nla_cache, eInsertKeyFlags flag) @@ -1393,15 +1418,8 @@ int insert_keyframe(Main *bmain, /* apply NLA-mapping to frame to use (if applicable) */ adt = BKE_animdata_from_id(id); - - if (adt && adt->action == act) { - /* Get NLA context for value remapping. */ - nla_context = BKE_animsys_get_nla_keyframing_context( - nla_cache ? nla_cache : &tmp_nla_cache, &id_ptr, adt, cfra, false); - - /* Apply NLA-mapping to frame. */ - cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); - } + const AnimationEvalContext remapped_context = nla_time_remap( + anim_eval_context, &id_ptr, adt, act, nla_cache ? nla_cache : &tmp_nla_cache, &nla_context); /* Obtain values to insert. */ float value_buffer[RNA_MAX_ARRAY_LENGTH]; @@ -1435,7 +1453,7 @@ int insert_keyframe(Main *bmain, group, rna_path, array_index, - cfra, + &remapped_context, values[array_index], keytype, flag)) { @@ -1458,7 +1476,7 @@ int insert_keyframe(Main *bmain, group, rna_path, array_index, - cfra, + &remapped_context, values[array_index], keytype, flag); @@ -1477,7 +1495,7 @@ int insert_keyframe(Main *bmain, group, rna_path, array_index, - cfra, + &remapped_context, values[array_index], keytype, flag); @@ -1495,7 +1513,7 @@ int insert_keyframe(Main *bmain, group, rna_path, array_index, - cfra, + &remapped_context, values[array_index], keytype, flag); @@ -2375,7 +2393,8 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) PropertyRNA *prop = NULL; char *path; uiBut *but; - float cfra = (float)CFRA; + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + CTX_data_depsgraph_pointer(C), (float)CFRA); bool changed = false; int index; const bool all = RNA_boolean_get(op->ptr, "all"); @@ -2401,7 +2420,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) if (fcu) { changed = insert_keyframe_direct( - op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, 0); + op->reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, 0); } else { BKE_report(op->reports, @@ -2417,8 +2436,14 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) fcu = BKE_fcurve_find_by_rna_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special); if (fcu && driven) { - changed = insert_keyframe_direct( - op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, INSERTKEY_DRIVER); + changed = insert_keyframe_direct(op->reports, + ptr, + prop, + fcu, + &anim_eval_context, + ts->keyframe_type, + NULL, + INSERTKEY_DRIVER); } } else { @@ -2461,7 +2486,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) group, path, index, - cfra, + &anim_eval_context, ts->keyframe_type, NULL, flag) != 0); @@ -2769,7 +2794,10 @@ bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter) } /* Returns whether the current value of a given property differs from the interpolated value. */ -bool fcurve_is_changed(PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float frame) +bool fcurve_is_changed(PointerRNA ptr, + PropertyRNA *prop, + FCurve *fcu, + const AnimationEvalContext *anim_eval_context) { PathResolvedRNA anim_rna; anim_rna.ptr = ptr; @@ -2780,7 +2808,7 @@ bool fcurve_is_changed(PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float fra int count, index = fcu->array_index; float *values = setting_get_rna_values(&ptr, prop, buffer, RNA_MAX_ARRAY_LENGTH, &count); - float fcurve_val = calculate_fcurve(&anim_rna, fcu, frame); + float fcurve_val = calculate_fcurve(&anim_rna, fcu, anim_eval_context); float cur_val = (index >= 0 && index < count) ? values[index] : 0.0f; if (values != buffer) { @@ -2987,6 +3015,9 @@ bool ED_autokeyframe_property( bContext *C, Scene *scene, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, float cfra) { Main *bmain = CTX_data_main(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + cfra); ID *id; bAction *action; FCurve *fcu; @@ -3007,7 +3038,8 @@ bool ED_autokeyframe_property( ReportList *reports = CTX_wm_reports(C); ToolSettings *ts = scene->toolsettings; - changed = insert_keyframe_direct(reports, *ptr, prop, fcu, cfra, ts->keyframe_type, NULL, 0); + changed = insert_keyframe_direct( + reports, *ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, 0); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } @@ -3020,7 +3052,7 @@ bool ED_autokeyframe_property( ToolSettings *ts = scene->toolsettings; changed = insert_keyframe_direct( - reports, *ptr, prop, fcu, cfra, ts->keyframe_type, NULL, INSERTKEY_DRIVER); + reports, *ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, INSERTKEY_DRIVER); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } } @@ -3044,7 +3076,7 @@ bool ED_autokeyframe_property( ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, rnaindex, - cfra, + &anim_eval_context, ts->keyframe_type, NULL, flag) != 0; diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 5e4b39d9d81..876740b889a 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -1120,6 +1120,9 @@ int ANIM_apply_keyingset( /* for each possible index, perform operation * - assume that arraylen is greater than index */ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + cfra); for (; i < arraylen; i++) { /* action to take depends on mode */ if (mode == MODIFYKEY_MODE_INSERT) { @@ -1130,7 +1133,7 @@ int ANIM_apply_keyingset( groupname, ksp->rna_path, i, - cfra, + &anim_eval_context, keytype, &nla_cache, kflag2); diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 6ce9ed06f1a..c9d0478270a 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -1023,7 +1023,8 @@ static void poselib_backup_free_data(tPoseLib_PreviewData *pld) * - gets the string to print in the header * - this code is based on the code for extract_pose_from_action in blenkernel/action.c */ -static void poselib_apply_pose(tPoseLib_PreviewData *pld) +static void poselib_apply_pose(tPoseLib_PreviewData *pld, + const AnimationEvalContext *anim_eval_context) { PointerRNA *ptr = &pld->rna_ptr; bArmature *arm = pld->arm; @@ -1049,6 +1050,8 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); ked.f1 = ((float)frame) - 0.5f; ked.f2 = ((float)frame) + 0.5f; + AnimationEvalContext anim_context_at_frame = BKE_animsys_eval_context_construct_at( + anim_eval_context, frame); /* start applying - only those channels which have a key at this point in time! */ for (agrp = act->groups.first; agrp; agrp = agrp->next) { @@ -1075,7 +1078,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) } if (ok) { - animsys_evaluate_action_group(ptr, act, agrp, (float)frame); + animsys_evaluate_action_group(ptr, act, agrp, &anim_context_at_frame); } } } @@ -1150,7 +1153,11 @@ static void poselib_preview_apply(bContext *C, wmOperator *op) /* pose should be the right one to draw (unless we're temporarily not showing it) */ if ((pld->flag & PL_PREVIEW_SHOWORIGINAL) == 0) { RNA_int_set(op->ptr, "pose_index", BLI_findindex(&pld->act->markers, pld->marker)); - poselib_apply_pose(pld); + struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, 0.0f /* poselib_apply_pose() determines its own evaluation time. */); + poselib_apply_pose(pld, &anim_eval_context); } else { RNA_int_set(op->ptr, "pose_index", -2); /* -2 means don't apply any pose */ diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 1d2bf152777..615d59c3154 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -1219,7 +1219,9 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - float cframe = (float)CFRA; + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + (float)CFRA); const bool only_select = RNA_boolean_get(op->ptr, "only_selected"); FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) { @@ -1240,7 +1242,8 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) workob.adt = ob->adt; workob.pose = dummyPose; - BKE_animsys_evaluate_animdata(&workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata( + &workob.id, workob.adt, &anim_eval_context, ADT_RECALC_ANIM, false); /* copy back values, but on selected bones only */ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) { diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index f7d7627b850..21f15575a2f 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -48,6 +48,7 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" +#include "BKE_animsys.h" #include "BKE_collection.h" #include "BKE_context.h" #include "BKE_curve.h" @@ -399,6 +400,7 @@ static void gpencil_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, + Depsgraph *depsgraph, FCurve *fcu, Curve *cu, tGpTimingData *gtd, @@ -453,8 +455,16 @@ static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports, if ((cfra - last_valid_time) < MIN_TIME_DELTA) { cfra = last_valid_time + MIN_TIME_DELTA; } - insert_keyframe_direct( - reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, cfra); + insert_keyframe_direct(reports, + ptr, + prop, + fcu, + &anim_eval_context, + BEZT_KEYTYPE_KEYFRAME, + NULL, + INSERTKEY_FAST); last_valid_time = cfra; } else if (G.debug & G_DEBUG) { @@ -466,8 +476,16 @@ static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports, if ((cfra - last_valid_time) < MIN_TIME_DELTA) { cfra = last_valid_time + MIN_TIME_DELTA; } - insert_keyframe_direct( - reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + cfra); + insert_keyframe_direct(reports, + ptr, + prop, + fcu, + &anim_eval_context, + BEZT_KEYTYPE_KEYFRAME, + NULL, + INSERTKEY_FAST); last_valid_time = cfra; } else { @@ -475,8 +493,16 @@ static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports, * and also far enough from (not yet added!) end_stroke keyframe! */ if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) { - insert_keyframe_direct( - reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_BREAKDOWN, NULL, INSERTKEY_FAST); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, cfra); + insert_keyframe_direct(reports, + ptr, + prop, + fcu, + &anim_eval_context, + BEZT_KEYTYPE_BREAKDOWN, + NULL, + INSERTKEY_FAST); last_valid_time = cfra; } else if (G.debug & G_DEBUG) { @@ -496,6 +522,7 @@ static void gpencil_stroke_path_animation(bContext *C, { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); bAction *act; FCurve *fcu; PointerRNA ptr; @@ -537,8 +564,16 @@ static void gpencil_stroke_path_animation(bContext *C, cu->ctime = 0.0f; cfra = (float)gtd->start_frame; - insert_keyframe_direct( - reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST); + AnimationEvalContext anim_eval_context_start = BKE_animsys_eval_context_construct(depsgraph, + cfra); + insert_keyframe_direct(reports, + ptr, + prop, + fcu, + &anim_eval_context_start, + BEZT_KEYTYPE_KEYFRAME, + NULL, + INSERTKEY_FAST); cu->ctime = cu->pathlen; if (gtd->realtime) { @@ -547,8 +582,16 @@ static void gpencil_stroke_path_animation(bContext *C, else { cfra = (float)gtd->end_frame; } - insert_keyframe_direct( - reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST); + AnimationEvalContext anim_eval_context_end = BKE_animsys_eval_context_construct(depsgraph, + cfra); + insert_keyframe_direct(reports, + ptr, + prop, + fcu, + &anim_eval_context_end, + BEZT_KEYTYPE_KEYFRAME, + NULL, + INSERTKEY_FAST); } else { /* Use actual recorded timing! */ @@ -575,7 +618,7 @@ static void gpencil_stroke_path_animation(bContext *C, } gpencil_stroke_path_animation_add_keyframes( - reports, ptr, prop, fcu, cu, gtd, rng, time_range, nbr_gaps, tot_gaps_time); + reports, ptr, prop, depsgraph, fcu, cu, gtd, rng, time_range, nbr_gaps, tot_gaps_time); BLI_rng_free(rng); } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index bffa11a32f2..9d9f2925c23 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -95,6 +95,8 @@ typedef struct bAnimContext { struct Scene *scene; /** active scene layer */ struct ViewLayer *view_layer; + /** active dependency graph */ + struct Depsgraph *depsgraph; /** active object */ struct Object *obact; /** active set of markers */ diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 5635ef2800a..3fe6407aae7 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -38,6 +38,7 @@ struct Scene; struct KeyingSet; +struct AnimationEvalContext; struct BezTriple; struct FCurve; struct bAction; @@ -118,7 +119,7 @@ bool insert_keyframe_direct(struct ReportList *reports, struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, - float cfra, + const struct AnimationEvalContext *anim_eval_context, eBezTriple_KeyframeType keytype, struct NlaKeyframingContext *nla, eInsertKeyFlags flag); @@ -136,7 +137,7 @@ int insert_keyframe(struct Main *bmain, const char group[], const char rna_path[], int array_index, - float cfra, + const struct AnimationEvalContext *anim_eval_context, eBezTriple_KeyframeType keytype, struct ListBase *nla_cache, eInsertKeyFlags flag); @@ -458,7 +459,7 @@ bool fcurve_frame_has_keyframe(struct FCurve *fcu, float frame, short filter); bool fcurve_is_changed(struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, - float frame); + const struct AnimationEvalContext *anim_eval_context); /** * Main Keyframe Checking API call: diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 28b86674fdd..106145005bd 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -44,6 +44,7 @@ #include "BLI_utildefines.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_idprop.h" #include "BKE_main.h" @@ -1733,6 +1734,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x wmWindow *window = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); ARegion *region = CTX_wm_region(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); uiBut *but; BLI_assert(block->active); @@ -1761,7 +1763,9 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x } } - ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, (scene) ? scene->r.cfra : 0.0f); + ui_but_anim_flag(but, &anim_eval_context); ui_but_override_flag(CTX_data_main(C), but); if (UI_but_is_decorator(but)) { ui_but_anim_decorate_update_from_flag(but); diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 5bf2147aff5..8d12a1dd1ad 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -33,6 +33,7 @@ #include "BLI_string_utf8.h" #include "BLI_utildefines.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_fcurve.h" #include "BKE_fcurve_driver.h" @@ -65,7 +66,7 @@ static FCurve *ui_but_get_fcurve( but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special); } -void ui_but_anim_flag(uiBut *but, float cfra) +void ui_but_anim_flag(uiBut *but, const AnimationEvalContext *anim_eval_context) { AnimData *adt; bAction *act; @@ -95,6 +96,7 @@ void ui_but_anim_flag(uiBut *but, float cfra) * we need to correct the frame number to "look inside" the * remapped action */ + float cfra = anim_eval_context->eval_time; if (adt) { cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); } @@ -105,7 +107,9 @@ void ui_but_anim_flag(uiBut *but, float cfra) /* XXX: this feature is totally broken and useless with NLA */ if (adt == NULL || adt->nla_tracks.first == NULL) { - if (fcurve_is_changed(but->rnapoin, but->rnaprop, fcu, cfra)) { + const AnimationEvalContext remapped_context = BKE_animsys_eval_context_construct_at( + anim_eval_context, cfra); + if (fcurve_is_changed(but->rnapoin, but->rnaprop, fcu, &remapped_context)) { but->drawflag |= UI_BUT_ANIMATED_CHANGED; } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 43c91f1d2eb..988d19e30d3 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -47,6 +47,7 @@ #include "PIL_time.h" +#include "BKE_animsys.h" #include "BKE_blender_undo.h" #include "BKE_brush.h" #include "BKE_colorband.h" @@ -8408,6 +8409,9 @@ void UI_context_update_anim_flag(const bContext *C) { Scene *scene = CTX_data_scene(C); ARegion *region = CTX_wm_region(C); + struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, (scene) ? scene->r.cfra : 0.0f); uiBlock *block; uiBut *but, *activebut; @@ -8417,7 +8421,7 @@ void UI_context_update_anim_flag(const bContext *C) for (block = region->uiblocks.first; block; block = block->next) { for (but = block->buttons.first; but; but = but->next) { - ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f); + ui_but_anim_flag(but, &anim_eval_context); ui_but_override_flag(CTX_data_main(C), but); if (UI_but_is_decorator(but)) { ui_but_anim_decorate_update_from_flag(but); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index a7cbfc23399..249134c6abf 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -32,6 +32,7 @@ #include "UI_interface.h" #include "UI_resources.h" +struct AnimationEvalContext; struct ARegion; struct ID; struct ImBuf; @@ -938,7 +939,7 @@ int ui_but_align_opposite_to_area_align_get(const struct ARegion *region) ATTR_W void ui_block_align_calc(uiBlock *block, const struct ARegion *region); /* interface_anim.c */ -void ui_but_anim_flag(uiBut *but, float cfra); +void ui_but_anim_flag(uiBut *but, const struct AnimationEvalContext *anim_eval_context); void ui_but_anim_copy_driver(struct bContext *C); void ui_but_anim_paste_driver(struct bContext *C); bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index f027a62cbfd..b707aaa0ee9 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -5540,6 +5540,26 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout) } } +static bool ui_layout_has_panel_label(const uiLayout *layout, const PanelType *pt) +{ + LISTBASE_FOREACH (uiItem *, subitem, &layout->items) { + if (subitem->type == ITEM_BUTTON) { + uiButtonItem *bitem = (uiButtonItem *)subitem; + if (!(bitem->but->flag & UI_HIDDEN) && STREQ(bitem->but->str, pt->label)) { + return true; + } + } + else { + uiLayout *litem = (uiLayout *)subitem; + if (ui_layout_has_panel_label(litem, pt)) { + return true; + } + } + } + + return false; +} + static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout, bool show_header) { Panel *panel = MEM_callocN(sizeof(Panel), "popover panel"); @@ -5556,7 +5576,13 @@ static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout, pt->draw_header(C, panel); panel->layout = NULL; } - uiItemL(row, CTX_IFACE_(pt->translation_context, pt->label), ICON_NONE); + + /* draw_header() is often used to add a checkbox to the header. If we add the label like below + * the label is disconnected from the checkbox, adding a weird looking gap. As workaround, let + * the checkbox add the label instead. */ + if (!ui_layout_has_panel_label(row, pt)) { + uiItemL(row, CTX_IFACE_(pt->translation_context, pt->label), ICON_NONE); + } } panel->layout = layout; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 873bdf2a674..347f6806d13 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1564,15 +1564,12 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) void **val_p; float s[2], se1[2], se2[2], sint[2]; float r1[3], r2[3]; - float d, d1, d2, lambda; + float d1, d2, lambda; float vert_tol, vert_tol_sq; float line_tol, line_tol_sq; float face_tol, face_tol_sq; - int isect_kind; uint tot; int i; - const bool use_hit_prev = true; - const bool use_hit_curr = (kcd->is_drag_hold == false); if (kcd->linehits) { MEM_freeN(kcd->linehits); @@ -1703,10 +1700,25 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) val_p = BLI_smallhash_iternext_p(&hiter, (uintptr_t *)&v)) { KnifeEdge *kfe_hit = NULL; - knife_project_v2(kcd, v->cageco, s); - d = dist_squared_to_line_segment_v2(s, s1, s2); - if ((d <= vert_tol_sq) && - (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit)))) { + bool kfv_is_in_cut = false; + if (ELEM(v, kcd->prev.vert, kcd->curr.vert)) { + /* This KnifeVert was captured by the snap system. + * Since the tolerance distance can be different, add this vertex directly. + * Otherwise, the cut may fail or a close cut on a connected edge can be performed. */ + bm_elem_from_knife_vert(v, &kfe_hit); + copy_v2_v2(s, (v == kcd->prev.vert) ? kcd->prev.mval : kcd->curr.mval); + kfv_is_in_cut = true; + } + else { + knife_project_v2(kcd, v->cageco, s); + float d = dist_squared_to_line_segment_v2(s, s1, s2); + if ((d <= vert_tol_sq) && + (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit)))) { + kfv_is_in_cut = true; + } + } + + if (kfv_is_in_cut) { memset(&hit, 0, sizeof(hit)); hit.v = v; @@ -1724,7 +1736,9 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) BLI_array_append(linehits, hit); } else { - /* note that these vertes aren't used */ + /* This vertex isn't used so remove from `kfvs`. + * This is useful to detect KnifeEdges that can be skipped. + * And it optimizes smallhash_iternext a little bit. */ *val_p = NULL; } } @@ -1732,30 +1746,38 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) /* now edge hits; don't add if a vertex at end of edge should have hit */ for (val = BLI_smallhash_iternew(&kfes, &hiter, (uintptr_t *)&kfe); val; val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&kfe)) { - int kfe_verts_in_cut; - /* if we intersect both verts, don't attempt to intersect the edge */ - - kfe_verts_in_cut = (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v1) != NULL) + - (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v2) != NULL); - if (kfe_verts_in_cut == 2) { + /* If we intersect any of the vertices, don't attempt to intersect the edge. */ + if (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v1) || + BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v2)) { continue; } knife_project_v2(kcd, kfe->v1->cageco, se1); knife_project_v2(kcd, kfe->v2->cageco, se2); - isect_kind = (kfe_verts_in_cut) ? -1 : isect_seg_seg_v2_point(s1, s2, se1, se2, sint); - if (isect_kind == -1) { - /* isect_seg_seg_v2_simple doesn't do tolerance test around ends of s1-s2 */ - closest_to_line_segment_v2(sint, s1, se1, se2); - if (len_squared_v2v2(sint, s1) <= line_tol_sq) { - isect_kind = 1; - } - else { - closest_to_line_segment_v2(sint, s2, se1, se2); - if (len_squared_v2v2(sint, s2) <= line_tol_sq) { + int isect_kind = 1; + if (kfe == kcd->prev.edge) { + /* This KnifeEdge was captured by the snap system. */ + copy_v2_v2(sint, kcd->prev.mval); + } + else if (kfe == kcd->curr.edge) { + /* This KnifeEdge was captured by the snap system. */ + copy_v2_v2(sint, kcd->curr.mval); + } + else { + isect_kind = isect_seg_seg_v2_point_ex(s1, s2, se1, se2, 0.0f, sint); + if (isect_kind == -1) { + /* isect_seg_seg_v2_point doesn't do tolerance test around ends of s1-s2 */ + closest_to_line_segment_v2(sint, s1, se1, se2); + if (len_squared_v2v2(sint, s1) <= line_tol_sq) { isect_kind = 1; } + else { + closest_to_line_segment_v2(sint, s2, se1, se2); + if (len_squared_v2v2(sint, s2) <= line_tol_sq) { + isect_kind = 1; + } + } } } if (isect_kind == 1) { @@ -1790,32 +1812,38 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) } } } + /* now face hits; don't add if a vertex or edge in face should have hit */ - for (val = BLI_smallhash_iternew(&faces, &hiter, (uintptr_t *)&f); val; - val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) { - float p[3], p_cage[3]; - - if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) { - if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) { - memset(&hit, 0, sizeof(hit)); - hit.f = f; - copy_v3_v3(hit.hit, p); - copy_v3_v3(hit.cagehit, p_cage); - copy_v2_v2(hit.schit, s1); - set_linehit_depth(kcd, &hit); - BLI_array_append(linehits, hit); + const bool use_hit_prev = (kcd->prev.vert == NULL) && (kcd->prev.edge == NULL); + const bool use_hit_curr = (kcd->curr.vert == NULL) && (kcd->curr.edge == NULL) && + !kcd->is_drag_hold; + if (use_hit_prev || use_hit_curr) { + for (val = BLI_smallhash_iternew(&faces, &hiter, (uintptr_t *)&f); val; + val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) { + float p[3], p_cage[3]; + + if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) { + if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) { + memset(&hit, 0, sizeof(hit)); + hit.f = f; + copy_v3_v3(hit.hit, p); + copy_v3_v3(hit.cagehit, p_cage); + copy_v2_v2(hit.schit, s1); + set_linehit_depth(kcd, &hit); + BLI_array_append(linehits, hit); + } } - } - if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) { - if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) { - memset(&hit, 0, sizeof(hit)); - hit.f = f; - copy_v3_v3(hit.hit, p); - copy_v3_v3(hit.cagehit, p_cage); - copy_v2_v2(hit.schit, s2); - set_linehit_depth(kcd, &hit); - BLI_array_append(linehits, hit); + if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) { + if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) { + memset(&hit, 0, sizeof(hit)); + hit.f = f; + copy_v3_v3(hit.hit, p); + copy_v3_v3(hit.cagehit, p_cage); + copy_v2_v2(hit.schit, s2); + set_linehit_depth(kcd, &hit); + BLI_array_append(linehits, hit); + } } } } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index ff49e0a9c5a..aa9d6234d1f 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1395,7 +1395,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) /* Avoid dependency cycles. */ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer); - while (BKE_collection_find_cycle(active_lc->collection, collection)) { + while (BKE_collection_cycle_find(active_lc->collection, collection)) { active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc); } diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 6f254ea9400..4470269ec23 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -2796,12 +2796,16 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) cfra = scene->r.cfra; /* precalculate time variable before baking */ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); for (f = omd->bakestart; f <= omd->bakeend; f++) { /* For now only simple animation of time value is supported, nothing else. * No drivers or other modifier parameters. */ /* TODO(sergey): This operates on an original data, so no flush is needed. However, baking * usually should happen on an evaluated objects, so this seems to be deeper issue here. */ - BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false); + + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + f); + BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, &anim_eval_context, ADT_RECALC_ANIM, false); och->time[i] = omd->time; i++; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 185066b49ce..af8e0e9d9de 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -724,9 +724,10 @@ static void insert_action_keys(bAnimContext *ac, short mode) flag = ANIM_get_keyframing_flags(scene, true); /* insert keyframes */ + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(ac->depsgraph, + (float)CFRA); for (ale = anim_data.first; ale; ale = ale->next) { FCurve *fcu = (FCurve *)ale->key_data; - float cfra = (float)CFRA; /* Read value from property the F-Curve represents, or from the curve only? * - ale->id != NULL: @@ -745,7 +746,7 @@ static void insert_action_keys(bAnimContext *ac, short mode) ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, - cfra, + &anim_eval_context, ts->keyframe_type, &nla_cache, flag); @@ -754,8 +755,9 @@ static void insert_action_keys(bAnimContext *ac, short mode) AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* adjust current frame for NLA-scaling */ + float cfra = anim_eval_context.eval_time; if (adt) { - cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); + cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); } const float curval = evaluate_fcurve(fcu, cfra); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 1925a3847d6..68fdef54a53 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -681,9 +681,10 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) } } else { + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + ac->depsgraph, (float)CFRA); for (ale = anim_data.first; ale; ale = ale->next) { FCurve *fcu = (FCurve *)ale->key_data; - float cfra = (float)CFRA; /* Read value from property the F-Curve represents, or from the curve only? * @@ -705,7 +706,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, - cfra, + &anim_eval_context, ts->keyframe_type, &nla_cache, flag); @@ -714,6 +715,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) AnimData *adt = ANIM_nla_mapping_get(ac, ale); /* adjust current frame for NLA-mapping */ + float cfra = (float)CFRA; if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS)) { cfra = sipo->cursorTime; } diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 4b012934ab7..0964e0c753e 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -717,7 +717,7 @@ static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op)) GSET_ITER (collections_to_edit_iter, data.collections_to_edit) { Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter); - while (BKE_collection_find_cycle(active_lc->collection, collection)) { + while (BKE_collection_cycle_find(active_lc->collection, collection)) { active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc); } } diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index f721ed0b866..9885c8fc3a6 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -115,7 +115,9 @@ static void autokeyframe_pose( ToolSettings *ts = scene->toolsettings; KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); ListBase nla_cache = {NULL, NULL}; - float cfra = (float)CFRA; + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + (float)CFRA); eInsertKeyFlags flag = 0; /* flag is initialized from UserPref keyframing settings @@ -146,7 +148,8 @@ static void autokeyframe_pose( /* only insert into active keyingset? */ if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) { /* run the active Keying Set on the current datasource */ - ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } /* only insert into available channels? */ else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) { @@ -169,7 +172,7 @@ static void autokeyframe_pose( ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, - cfra, + &anim_eval_context, ts->keyframe_type, &nla_cache, flag); @@ -220,21 +223,25 @@ static void autokeyframe_pose( if (do_loc) { KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } if (do_rot) { KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } if (do_scale) { KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } } /* insert keyframe in all (transform) channels */ else { KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } /* free temp info */ diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 92ed477eb25..2e92b4e5c09 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -794,7 +794,9 @@ static void autokeyframe_object( ToolSettings *ts = scene->toolsettings; KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); ListBase dsources = {NULL, NULL}; - float cfra = (float)CFRA; // xxx this will do for now + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + (float)CFRA); eInsertKeyFlags flag = 0; /* Get flags used for inserting keyframes. */ @@ -808,7 +810,8 @@ static void autokeyframe_object( * NOTE: we assume here that the active Keying Set * does not need to have its iterator overridden. */ - ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) { AnimData *adt = ob->adt; @@ -824,7 +827,7 @@ static void autokeyframe_object( (fcu->grp ? fcu->grp->name : NULL), fcu->rna_path, fcu->array_index, - cfra, + &anim_eval_context, ts->keyframe_type, &nla_cache, flag); @@ -872,21 +875,25 @@ static void autokeyframe_object( /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */ if (do_loc) { KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } if (do_rot) { KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } if (do_scale) { KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } } /* insert keyframe in all (transform) channels */ else { KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + ANIM_apply_keyingset( + C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time); } /* free temp info */ diff --git a/source/blender/functions/FN_array_spans.hh b/source/blender/functions/FN_array_spans.hh index 3f71b36c49c..c362fef3630 100644 --- a/source/blender/functions/FN_array_spans.hh +++ b/source/blender/functions/FN_array_spans.hh @@ -39,17 +39,17 @@ enum class VArraySpanCategory { template<typename T> class VArraySpanBase { protected: - uint virtual_size_; + int64_t virtual_size_; VArraySpanCategory category_; union { struct { const T *start; - uint size; + int64_t size; } single_array; struct { const T *const *starts; - const uint *sizes; + const int64_t *sizes; } starts_and_sizes; } data_; @@ -71,7 +71,7 @@ template<typename T> class VArraySpanBase { return this->virtual_size_ == 0; } - uint size() const + int64_t size() const { return this->virtual_size_; } @@ -99,15 +99,16 @@ template<typename T> class VArraySpan : public VArraySpanBase<T> { this->data_.starts_and_sizes.sizes = nullptr; } - VArraySpan(Span<T> span, uint virtual_size) + VArraySpan(Span<T> span, int64_t virtual_size) { + BLI_assert(virtual_size >= 0); this->virtual_size_ = virtual_size; this->category_ = VArraySpanCategory::SingleArray; this->data_.single_array.start = span.data(); this->data_.single_array.size = span.size(); } - VArraySpan(Span<const T *> starts, Span<uint> sizes) + VArraySpan(Span<const T *> starts, Span<int64_t> sizes) { BLI_assert(starts.size() == sizes.size()); this->virtual_size_ = starts.size(); @@ -116,8 +117,9 @@ template<typename T> class VArraySpan : public VArraySpanBase<T> { this->data_.starts_and_sizes.sizes = sizes.begin(); } - VSpan<T> operator[](uint index) const + VSpan<T> operator[](int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index < this->virtual_size_); switch (this->category_) { case VArraySpanCategory::SingleArray: @@ -151,7 +153,7 @@ class GVArraySpan : public VArraySpanBase<void> { this->data_.starts_and_sizes.sizes = nullptr; } - GVArraySpan(GSpan array, uint virtual_size) + GVArraySpan(GSpan array, int64_t virtual_size) { this->type_ = &array.type(); this->virtual_size_ = virtual_size; @@ -160,7 +162,7 @@ class GVArraySpan : public VArraySpanBase<void> { this->data_.single_array.size = array.size(); } - GVArraySpan(const CPPType &type, Span<const void *> starts, Span<uint> sizes) + GVArraySpan(const CPPType &type, Span<const void *> starts, Span<int64_t> sizes) { BLI_assert(starts.size() == sizes.size()); this->type_ = &type; @@ -187,7 +189,7 @@ class GVArraySpan : public VArraySpanBase<void> { return VArraySpan<T>(*this); } - GVSpan operator[](uint index) const + GVSpan operator[](int64_t index) const { BLI_assert(index < virtual_size_); switch (category_) { diff --git a/source/blender/functions/FN_attributes_ref.hh b/source/blender/functions/FN_attributes_ref.hh index cf5ef2af8a6..ed14676731e 100644 --- a/source/blender/functions/FN_attributes_ref.hh +++ b/source/blender/functions/FN_attributes_ref.hh @@ -65,7 +65,7 @@ class AttributesInfoBuilder : NonCopyable, NonMovable { class AttributesInfo : NonCopyable, NonMovable { private: LinearAllocator<> allocator_; - Map<StringRefNull, uint> index_by_name_; + Map<StringRefNull, int> index_by_name_; Vector<StringRefNull> name_by_index_; Vector<const CPPType *> type_by_index_; Vector<void *> defaults_; @@ -75,7 +75,7 @@ class AttributesInfo : NonCopyable, NonMovable { AttributesInfo(const AttributesInfoBuilder &builder); ~AttributesInfo(); - uint size() const + int size() const { return name_by_index_.size(); } @@ -85,17 +85,17 @@ class AttributesInfo : NonCopyable, NonMovable { return name_by_index_.index_range(); } - StringRefNull name_of(uint index) const + StringRefNull name_of(int index) const { return name_by_index_[index]; } - uint index_of(StringRef name) const + int index_of(StringRef name) const { return index_by_name_.lookup_as(name); } - const void *default_of(uint index) const + const void *default_of(int index) const { return defaults_[index]; } @@ -105,7 +105,7 @@ class AttributesInfo : NonCopyable, NonMovable { return this->default_of(this->index_of(name)); } - template<typename T> const T &default_of(uint index) const + template<typename T> const T &default_of(int index) const { BLI_assert(type_by_index_[index]->is<T>()); return *(T *)defaults_[index]; @@ -116,7 +116,7 @@ class AttributesInfo : NonCopyable, NonMovable { return this->default_of<T>(this->index_of(name)); } - const CPPType &type_of(uint index) const + const CPPType &type_of(int index) const { return *type_by_index_[index]; } @@ -133,7 +133,7 @@ class AttributesInfo : NonCopyable, NonMovable { int try_index_of(StringRef name) const { - return (int)index_by_name_.lookup_default_as(name, -1); + return index_by_name_.lookup_default_as(name, -1); } int try_index_of(StringRef name, const CPPType &type) const @@ -142,7 +142,7 @@ class AttributesInfo : NonCopyable, NonMovable { if (index == -1) { return -1; } - else if (this->type_of((uint)index) == type) { + else if (this->type_of(index) == type) { return index; } else { @@ -164,7 +164,7 @@ class MutableAttributesRef { friend class AttributesRef; public: - MutableAttributesRef(const AttributesInfo &info, Span<void *> buffers, uint size) + MutableAttributesRef(const AttributesInfo &info, Span<void *> buffers, int64_t size) : MutableAttributesRef(info, buffers, IndexRange(size)) { } @@ -174,17 +174,22 @@ class MutableAttributesRef { { } - uint size() const + int64_t size() const { return range_.size(); } + IndexRange index_range() const + { + return IndexRange(this->size()); + } + const AttributesInfo &info() const { return *info_; } - GMutableSpan get(uint index) const + GMutableSpan get(int index) const { const CPPType &type = info_->type_of(index); void *ptr = POINTER_OFFSET(buffers_[index], type.size() * range_.start()); @@ -196,7 +201,7 @@ class MutableAttributesRef { return this->get(info_->index_of(name)); } - template<typename T> MutableSpan<T> get(uint index) const + template<typename T> MutableSpan<T> get(int index) const { BLI_assert(info_->type_of(index).is<T>()); return MutableSpan<T>((T *)buffers_[index] + range_.start(), range_.size()); @@ -214,7 +219,7 @@ class MutableAttributesRef { return {}; } else { - return this->get((uint)index); + return this->get(index); } } @@ -224,8 +229,8 @@ class MutableAttributesRef { if (index == -1) { return {}; } - else if (info_->type_of((uint)index).is<T>()) { - return this->get<T>((uint)index); + else if (info_->type_of(index).is<T>()) { + return this->get<T>(index); } else { return {}; @@ -237,7 +242,7 @@ class MutableAttributesRef { return this->slice(range.start(), range.size()); } - MutableAttributesRef slice(uint start, uint size) const + MutableAttributesRef slice(int64_t start, int64_t size) const { return MutableAttributesRef(*info_, buffers_, range_.slice(start, size)); } @@ -250,7 +255,7 @@ class AttributesRef { IndexRange range_; public: - AttributesRef(const AttributesInfo &info, Span<const void *> buffers, uint size) + AttributesRef(const AttributesInfo &info, Span<const void *> buffers, int64_t size) : AttributesRef(info, buffers, IndexRange(size)) { } @@ -265,7 +270,7 @@ class AttributesRef { { } - uint size() const + int64_t size() const { return range_.size(); } @@ -275,7 +280,7 @@ class AttributesRef { return *info_; } - GSpan get(uint index) const + GSpan get(int index) const { const CPPType &type = info_->type_of(index); const void *ptr = POINTER_OFFSET(buffers_[index], type.size() * range_.start()); @@ -287,7 +292,7 @@ class AttributesRef { return this->get(info_->index_of(name)); } - template<typename T> Span<T> get(uint index) const + template<typename T> Span<T> get(int index) const { BLI_assert(info_->type_of(index).is<T>()); return Span<T>((T *)buffers_[index] + range_.start(), range_.size()); @@ -300,12 +305,12 @@ class AttributesRef { std::optional<GSpan> try_get(StringRef name, const CPPType &type) const { - int index = info_->try_index_of(name, type); + int64_t index = info_->try_index_of(name, type); if (index == -1) { return {}; } else { - return this->get((uint)index); + return this->get(index); } } @@ -315,8 +320,8 @@ class AttributesRef { if (index == -1) { return {}; } - else if (info_->type_of((uint)index).is<T>()) { - return this->get<T>((uint)index); + else if (info_->type_of(index).is<T>()) { + return this->get<T>(index); } else { return {}; @@ -328,7 +333,7 @@ class AttributesRef { return this->slice(range.start(), range.size()); } - AttributesRef slice(uint start, uint size) const + AttributesRef slice(int64_t start, int64_t size) const { return AttributesRef(*info_, buffers_, range_.slice(start, size)); } diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh index ce02bfd05be..594890e353a 100644 --- a/source/blender/functions/FN_cpp_type.hh +++ b/source/blender/functions/FN_cpp_type.hh @@ -38,7 +38,7 @@ * methods come in three variants. Using the construct-default methods as example: * - construct_default(void *ptr): * Constructs a single instance of that type at the given pointer. - * - construct_default_n(void *ptr, uint n): + * - construct_default_n(void *ptr, int64_t n): * Constructs n instances of that type in an array that starts at the given pointer. * - construct_default_indices(void *ptr, IndexMask mask): * Constructs multiple instances of that type in an array that starts at the given pointer. @@ -77,42 +77,42 @@ namespace blender::fn { class CPPType : NonCopyable, NonMovable { public: using ConstructDefaultF = void (*)(void *ptr); - using ConstructDefaultNF = void (*)(void *ptr, uint n); + using ConstructDefaultNF = void (*)(void *ptr, int64_t n); using ConstructDefaultIndicesF = void (*)(void *ptr, IndexMask mask); using DestructF = void (*)(void *ptr); - using DestructNF = void (*)(void *ptr, uint n); + using DestructNF = void (*)(void *ptr, int64_t n); using DestructIndicesF = void (*)(void *ptr, IndexMask mask); using CopyToInitializedF = void (*)(const void *src, void *dst); - using CopyToInitializedNF = void (*)(const void *src, void *dst, uint n); + using CopyToInitializedNF = void (*)(const void *src, void *dst, int64_t n); using CopyToInitializedIndicesF = void (*)(const void *src, void *dst, IndexMask mask); using CopyToUninitializedF = void (*)(const void *src, void *dst); - using CopyToUninitializedNF = void (*)(const void *src, void *dst, uint n); + using CopyToUninitializedNF = void (*)(const void *src, void *dst, int64_t n); using CopyToUninitializedIndicesF = void (*)(const void *src, void *dst, IndexMask mask); using RelocateToInitializedF = void (*)(void *src, void *dst); - using RelocateToInitializedNF = void (*)(void *src, void *dst, uint n); + using RelocateToInitializedNF = void (*)(void *src, void *dst, int64_t n); using RelocateToInitializedIndicesF = void (*)(void *src, void *dst, IndexMask mask); using RelocateToUninitializedF = void (*)(void *src, void *dst); - using RelocateToUninitializedNF = void (*)(void *src, void *dst, uint n); + using RelocateToUninitializedNF = void (*)(void *src, void *dst, int64_t n); using RelocateToUninitializedIndicesF = void (*)(void *src, void *dst, IndexMask mask); - using FillInitializedF = void (*)(const void *value, void *dst, uint n); + using FillInitializedF = void (*)(const void *value, void *dst, int64_t n); using FillInitializedIndicesF = void (*)(const void *value, void *dst, IndexMask mask); - using FillUninitializedF = void (*)(const void *value, void *dst, uint n); + using FillUninitializedF = void (*)(const void *value, void *dst, int64_t n); using FillUninitializedIndicesF = void (*)(const void *value, void *dst, IndexMask mask); using DebugPrintF = void (*)(const void *value, std::stringstream &ss); using IsEqualF = bool (*)(const void *a, const void *b); - using HashF = uint32_t (*)(const void *value); + using HashF = uint64_t (*)(const void *value); private: - uint size_; - uint alignment_; + int64_t size_; + int64_t alignment_; uintptr_t alignment_mask_; bool is_trivially_destructible_; @@ -155,8 +155,8 @@ class CPPType : NonCopyable, NonMovable { public: CPPType(std::string name, - uint size, - uint alignment, + int64_t size, + int64_t alignment, bool is_trivially_destructible, ConstructDefaultF construct_default, ConstructDefaultNF construct_default_n, @@ -250,7 +250,7 @@ class CPPType : NonCopyable, NonMovable { * C++ equivalent: * sizeof(T); */ - uint size() const + int64_t size() const { return size_; } @@ -261,7 +261,7 @@ class CPPType : NonCopyable, NonMovable { * C++ equivalent: * alignof(T); */ - uint alignment() const + int64_t alignment() const { return alignment_; } @@ -306,7 +306,7 @@ class CPPType : NonCopyable, NonMovable { construct_default_(ptr); } - void construct_default_n(void *ptr, uint n) const + void construct_default_n(void *ptr, int64_t n) const { BLI_assert(n == 0 || this->pointer_can_point_to_instance(ptr)); @@ -335,7 +335,7 @@ class CPPType : NonCopyable, NonMovable { destruct_(ptr); } - void destruct_n(void *ptr, uint n) const + void destruct_n(void *ptr, int64_t n) const { BLI_assert(n == 0 || this->pointer_can_point_to_instance(ptr)); @@ -369,7 +369,7 @@ class CPPType : NonCopyable, NonMovable { copy_to_initialized_(src, dst); } - void copy_to_initialized_n(const void *src, void *dst, uint n) const + void copy_to_initialized_n(const void *src, void *dst, int64_t n) const { BLI_assert(src != dst); BLI_assert(n == 0 || this->pointer_can_point_to_instance(src)); @@ -404,7 +404,7 @@ class CPPType : NonCopyable, NonMovable { copy_to_uninitialized_(src, dst); } - void copy_to_uninitialized_n(const void *src, void *dst, uint n) const + void copy_to_uninitialized_n(const void *src, void *dst, int64_t n) const { BLI_assert(src != dst); BLI_assert(n == 0 || this->pointer_can_point_to_instance(src)); @@ -439,7 +439,7 @@ class CPPType : NonCopyable, NonMovable { relocate_to_initialized_(src, dst); } - void relocate_to_initialized_n(void *src, void *dst, uint n) const + void relocate_to_initialized_n(void *src, void *dst, int64_t n) const { BLI_assert(src != dst); BLI_assert(n == 0 || this->pointer_can_point_to_instance(src)); @@ -474,7 +474,7 @@ class CPPType : NonCopyable, NonMovable { relocate_to_uninitialized_(src, dst); } - void relocate_to_uninitialized_n(void *src, void *dst, uint n) const + void relocate_to_uninitialized_n(void *src, void *dst, int64_t n) const { BLI_assert(src != dst); BLI_assert(n == 0 || this->pointer_can_point_to_instance(src)); @@ -497,7 +497,7 @@ class CPPType : NonCopyable, NonMovable { * * Other instances of the same type should live in the array before this method is called. */ - void fill_initialized(const void *value, void *dst, uint n) const + void fill_initialized(const void *value, void *dst, int64_t n) const { BLI_assert(n == 0 || this->pointer_can_point_to_instance(value)); BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst)); @@ -518,7 +518,7 @@ class CPPType : NonCopyable, NonMovable { * * The array should be uninitialized before this method is called. */ - void fill_uninitialized(const void *value, void *dst, uint n) const + void fill_uninitialized(const void *value, void *dst, int64_t n) const { BLI_assert(n == 0 || this->pointer_can_point_to_instance(value)); BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst)); @@ -547,7 +547,7 @@ class CPPType : NonCopyable, NonMovable { return is_equal_(a, b); } - uint32_t hash(const void *value) const + uint64_t hash(const void *value) const { BLI_assert(this->pointer_can_point_to_instance(value)); return hash_(value); @@ -562,7 +562,7 @@ class CPPType : NonCopyable, NonMovable { return default_value_; } - uint32_t hash() const + uint64_t hash() const { return DefaultHash<const CPPType *>{}(this); } @@ -583,39 +583,39 @@ template<typename T> void construct_default_cb(void *ptr) { new (ptr) T; } -template<typename T> void construct_default_n_cb(void *ptr, uint n) +template<typename T> void construct_default_n_cb(void *ptr, int64_t n) { blender::default_construct_n((T *)ptr, n); } template<typename T> void construct_default_indices_cb(void *ptr, IndexMask mask) { - mask.foreach_index([&](uint i) { new ((T *)ptr + i) T; }); + mask.foreach_index([&](int64_t i) { new ((T *)ptr + i) T; }); } template<typename T> void destruct_cb(void *ptr) { ((T *)ptr)->~T(); } -template<typename T> void destruct_n_cb(void *ptr, uint n) +template<typename T> void destruct_n_cb(void *ptr, int64_t n) { blender::destruct_n((T *)ptr, n); } template<typename T> void destruct_indices_cb(void *ptr, IndexMask mask) { T *ptr_ = (T *)ptr; - mask.foreach_index([&](uint i) { ptr_[i].~T(); }); + mask.foreach_index([&](int64_t i) { ptr_[i].~T(); }); } template<typename T> void copy_to_initialized_cb(const void *src, void *dst) { *(T *)dst = *(T *)src; } -template<typename T> void copy_to_initialized_n_cb(const void *src, void *dst, uint n) +template<typename T> void copy_to_initialized_n_cb(const void *src, void *dst, int64_t n) { const T *src_ = (const T *)src; T *dst_ = (T *)dst; - for (uint i = 0; i < n; i++) { + for (int64_t i = 0; i < n; i++) { dst_[i] = src_[i]; } } @@ -625,14 +625,14 @@ void copy_to_initialized_indices_cb(const void *src, void *dst, IndexMask mask) const T *src_ = (const T *)src; T *dst_ = (T *)dst; - mask.foreach_index([&](uint i) { dst_[i] = src_[i]; }); + mask.foreach_index([&](int64_t i) { dst_[i] = src_[i]; }); } template<typename T> void copy_to_uninitialized_cb(const void *src, void *dst) { blender::uninitialized_copy_n((T *)src, 1, (T *)dst); } -template<typename T> void copy_to_uninitialized_n_cb(const void *src, void *dst, uint n) +template<typename T> void copy_to_uninitialized_n_cb(const void *src, void *dst, int64_t n) { blender::uninitialized_copy_n((T *)src, n, (T *)dst); } @@ -642,7 +642,7 @@ void copy_to_uninitialized_indices_cb(const void *src, void *dst, IndexMask mask const T *src_ = (const T *)src; T *dst_ = (T *)dst; - mask.foreach_index([&](uint i) { new (dst_ + i) T(src_[i]); }); + mask.foreach_index([&](int64_t i) { new (dst_ + i) T(src_[i]); }); } template<typename T> void relocate_to_initialized_cb(void *src, void *dst) @@ -653,7 +653,7 @@ template<typename T> void relocate_to_initialized_cb(void *src, void *dst) *dst_ = std::move(*src_); src_->~T(); } -template<typename T> void relocate_to_initialized_n_cb(void *src, void *dst, uint n) +template<typename T> void relocate_to_initialized_n_cb(void *src, void *dst, int64_t n) { blender::initialized_relocate_n((T *)src, n, (T *)dst); } @@ -662,7 +662,7 @@ template<typename T> void relocate_to_initialized_indices_cb(void *src, void *ds T *src_ = (T *)src; T *dst_ = (T *)dst; - mask.foreach_index([&](uint i) { + mask.foreach_index([&](int64_t i) { dst_[i] = std::move(src_[i]); src_[i].~T(); }); @@ -676,7 +676,7 @@ template<typename T> void relocate_to_uninitialized_cb(void *src, void *dst) new (dst_) T(std::move(*src_)); src_->~T(); } -template<typename T> void relocate_to_uninitialized_n_cb(void *src, void *dst, uint n) +template<typename T> void relocate_to_uninitialized_n_cb(void *src, void *dst, int64_t n) { blender::uninitialized_relocate_n((T *)src, n, (T *)dst); } @@ -686,18 +686,18 @@ void relocate_to_uninitialized_indices_cb(void *src, void *dst, IndexMask mask) T *src_ = (T *)src; T *dst_ = (T *)dst; - mask.foreach_index([&](uint i) { + mask.foreach_index([&](int64_t i) { new (dst_ + i) T(std::move(src_[i])); src_[i].~T(); }); } -template<typename T> void fill_initialized_cb(const void *value, void *dst, uint n) +template<typename T> void fill_initialized_cb(const void *value, void *dst, int64_t n) { const T &value_ = *(const T *)value; T *dst_ = (T *)dst; - for (uint i = 0; i < n; i++) { + for (int64_t i = 0; i < n; i++) { dst_[i] = value_; } } @@ -706,15 +706,15 @@ template<typename T> void fill_initialized_indices_cb(const void *value, void *d const T &value_ = *(const T *)value; T *dst_ = (T *)dst; - mask.foreach_index([&](uint i) { dst_[i] = value_; }); + mask.foreach_index([&](int64_t i) { dst_[i] = value_; }); } -template<typename T> void fill_uninitialized_cb(const void *value, void *dst, uint n) +template<typename T> void fill_uninitialized_cb(const void *value, void *dst, int64_t n) { const T &value_ = *(const T *)value; T *dst_ = (T *)dst; - for (uint i = 0; i < n; i++) { + for (int64_t i = 0; i < n; i++) { new (dst_ + i) T(value_); } } @@ -724,7 +724,7 @@ void fill_uninitialized_indices_cb(const void *value, void *dst, IndexMask mask) const T &value_ = *(const T *)value; T *dst_ = (T *)dst; - mask.foreach_index([&](uint i) { new (dst_ + i) T(value_); }); + mask.foreach_index([&](int64_t i) { new (dst_ + i) T(value_); }); } template<typename T> void debug_print_cb(const void *value, std::stringstream &ss) @@ -740,7 +740,7 @@ template<typename T> bool is_equal_cb(const void *a, const void *b) return a_ == b_; } -template<typename T> uint32_t hash_cb(const void *value) +template<typename T> uint64_t hash_cb(const void *value) { const T &value_ = *(const T *)value; return DefaultHash<T>{}(value_); diff --git a/source/blender/functions/FN_generic_vector_array.hh b/source/blender/functions/FN_generic_vector_array.hh index 2672484c184..ee67db000e5 100644 --- a/source/blender/functions/FN_generic_vector_array.hh +++ b/source/blender/functions/FN_generic_vector_array.hh @@ -42,10 +42,10 @@ template<typename T> class GVectorArrayRef; class GVectorArray : NonCopyable, NonMovable { private: const CPPType &type_; - uint element_size_; + int64_t element_size_; Array<void *, 1> starts_; - Array<uint, 1> lengths_; - Array<uint, 1> capacities_; + Array<int64_t, 1> lengths_; + Array<int64_t, 1> capacities_; LinearAllocator<> allocator_; template<typename T> friend class GVectorArrayRef; @@ -53,16 +53,16 @@ class GVectorArray : NonCopyable, NonMovable { public: GVectorArray() = delete; - GVectorArray(const CPPType &type, uint array_size) + GVectorArray(const CPPType &type, int64_t array_size) : type_(type), element_size_(type.size()), starts_(array_size), lengths_(array_size), capacities_(array_size) { - starts_.fill(nullptr); - lengths_.fill(0); - capacities_.fill(0); + starts_.as_mutable_span().fill(nullptr); + lengths_.as_mutable_span().fill(0); + capacities_.as_mutable_span().fill(0); } ~GVectorArray() @@ -71,7 +71,7 @@ class GVectorArray : NonCopyable, NonMovable { return; } - for (uint i : starts_.index_range()) { + for (int64_t i : starts_.index_range()) { type_.destruct_n(starts_[i], lengths_[i]); } } @@ -86,7 +86,7 @@ class GVectorArray : NonCopyable, NonMovable { return starts_.size() == 0; } - uint size() const + int64_t size() const { return starts_.size(); } @@ -101,14 +101,14 @@ class GVectorArray : NonCopyable, NonMovable { return starts_; } - Span<uint> lengths() const + Span<int64_t> lengths() const { return lengths_; } - void append(uint index, const void *src) + void append(int64_t index, const void *src) { - uint old_length = lengths_[index]; + int64_t old_length = lengths_[index]; if (old_length == capacities_[index]) { this->grow_at_least_one(index); } @@ -118,10 +118,10 @@ class GVectorArray : NonCopyable, NonMovable { lengths_[index]++; } - void extend(uint index, GVSpan span) + void extend(int64_t index, GVSpan span) { BLI_assert(type_ == span.type()); - for (uint i = 0; i < span.size(); i++) { + for (int64_t i = 0; i < span.size(); i++) { this->append(index, span[i]); } } @@ -130,12 +130,12 @@ class GVectorArray : NonCopyable, NonMovable { { BLI_assert(type_ == array_span.type()); BLI_assert(mask.min_array_size() <= array_span.size()); - for (uint i : mask) { + for (int64_t i : mask) { this->extend(i, array_span[i]); } } - GMutableSpan operator[](uint index) + GMutableSpan operator[](int64_t index) { BLI_assert(index < starts_.size()); return GMutableSpan(type_, starts_[index], lengths_[index]); @@ -146,10 +146,10 @@ class GVectorArray : NonCopyable, NonMovable { } private: - void grow_at_least_one(uint index) + void grow_at_least_one(int64_t index) { BLI_assert(lengths_[index] == capacities_[index]); - uint new_capacity = lengths_[index] * 2 + 1; + int64_t new_capacity = lengths_[index] * 2 + 1; void *new_buffer = allocator_.allocate(element_size_ * new_capacity, type_.alignment()); type_.relocate_to_uninitialized_n(starts_[index], new_buffer, lengths_[index]); @@ -169,28 +169,28 @@ template<typename T> class GVectorArrayRef { BLI_assert(vector_array.type_.is<T>()); } - void append(uint index, const T &value) + void append(int64_t index, const T &value) { vector_array_->append(index, &value); } - void extend(uint index, Span<T> values) + void extend(int64_t index, Span<T> values) { vector_array_->extend(index, values); } - void extend(uint index, VSpan<T> values) + void extend(int64_t index, VSpan<T> values) { vector_array_->extend(index, GVSpan(values)); } - MutableSpan<T> operator[](uint index) + MutableSpan<T> operator[](int64_t index) { BLI_assert(index < vector_array_->starts_.size()); return MutableSpan<T>((T *)vector_array_->starts_[index], vector_array_->lengths_[index]); } - uint size() const + int64_t size() const { return vector_array_->size(); } diff --git a/source/blender/functions/FN_multi_function.hh b/source/blender/functions/FN_multi_function.hh index 35f144368ac..77ab2749377 100644 --- a/source/blender/functions/FN_multi_function.hh +++ b/source/blender/functions/FN_multi_function.hh @@ -63,7 +63,7 @@ class MultiFunction { virtual void call(IndexMask mask, MFParams params, MFContext context) const = 0; - virtual uint32_t hash() const + virtual uint64_t hash() const { return DefaultHash<const MultiFunction *>{}(this); } @@ -73,7 +73,7 @@ class MultiFunction { return false; } - uint param_amount() const + int param_amount() const { return signature_.param_types.size(); } @@ -83,12 +83,12 @@ class MultiFunction { return signature_.param_types.index_range(); } - MFParamType param_type(uint param_index) const + MFParamType param_type(int param_index) const { return signature_.param_types[param_index]; } - StringRefNull param_name(uint param_index) const + StringRefNull param_name(int param_index) const { return signature_.param_names[param_index]; } @@ -111,7 +111,7 @@ class MultiFunction { } }; -inline MFParamsBuilder::MFParamsBuilder(const class MultiFunction &fn, uint min_array_size) +inline MFParamsBuilder::MFParamsBuilder(const class MultiFunction &fn, int64_t min_array_size) : MFParamsBuilder(fn.signature(), min_array_size) { } diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh index c2c95f7c355..95e216558e7 100644 --- a/source/blender/functions/FN_multi_function_builder.hh +++ b/source/blender/functions/FN_multi_function_builder.hh @@ -59,7 +59,7 @@ template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunctio template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) { return [=](IndexMask mask, VSpan<In1> in1, MutableSpan<Out1> out1) { - mask.foreach_index([&](uint i) { new ((void *)&out1[i]) Out1(element_fn(in1[i])); }); + mask.foreach_index([&](int i) { new ((void *)&out1[i]) Out1(element_fn(in1[i])); }); }; } @@ -101,7 +101,7 @@ class CustomMF_SI_SI_SO : public MultiFunction { template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) { return [=](IndexMask mask, VSpan<In1> in1, VSpan<In2> in2, MutableSpan<Out1> out1) { - mask.foreach_index([&](uint i) { new ((void *)&out1[i]) Out1(element_fn(in1[i], in2[i])); }); + mask.foreach_index([&](int i) { new ((void *)&out1[i]) Out1(element_fn(in1[i], in2[i])); }); }; } @@ -152,7 +152,7 @@ class CustomMF_SI_SI_SI_SO : public MultiFunction { VSpan<In3> in3, MutableSpan<Out1> out1) { mask.foreach_index( - [&](uint i) { new ((void *)&out1[i]) Out1(element_fn(in1[i], in2[i], in3[i])); }); + [&](int i) { new ((void *)&out1[i]) Out1(element_fn(in1[i], in2[i], in3[i])); }); }; } @@ -191,7 +191,7 @@ template<typename Mut1> class CustomMF_SM : public MultiFunction { template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) { return [=](IndexMask mask, MutableSpan<Mut1> mut1) { - mask.foreach_index([&](uint i) { element_fn(mut1[i]); }); + mask.foreach_index([&](int i) { element_fn(mut1[i]); }); }; } @@ -220,7 +220,7 @@ template<typename From, typename To> class CustomMF_Convert : public MultiFuncti VSpan<From> inputs = params.readonly_single_input<From>(0); MutableSpan<To> outputs = params.uninitialized_single_output<To>(1); - for (uint i : mask) { + for (int64_t i : mask) { new ((void *)&outputs[i]) To(inputs[i]); } } @@ -240,7 +240,7 @@ class CustomMF_GenericConstant : public MultiFunction { public: CustomMF_GenericConstant(const CPPType &type, const void *value); void call(IndexMask mask, MFParams params, MFContext context) const override; - uint32_t hash() const override; + uint64_t hash() const override; bool equals(const MultiFunction &other) const override; }; @@ -276,10 +276,10 @@ template<typename T> class CustomMF_Constant : public MultiFunction { void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override { MutableSpan<T> output = params.uninitialized_single_output<T>(0); - mask.foreach_index([&](uint i) { new (&output[i]) T(value_); }); + mask.foreach_index([&](int i) { new (&output[i]) T(value_); }); } - uint32_t hash() const override + uint64_t hash() const override { return DefaultHash<T>{}(value_); } @@ -304,7 +304,7 @@ template<typename T> class CustomMF_Constant : public MultiFunction { class CustomMF_DefaultOutput : public MultiFunction { private: - uint output_amount_; + int output_amount_; public: CustomMF_DefaultOutput(StringRef name, diff --git a/source/blender/functions/FN_multi_function_data_type.hh b/source/blender/functions/FN_multi_function_data_type.hh index 57aea046006..23a1c0e5680 100644 --- a/source/blender/functions/FN_multi_function_data_type.hh +++ b/source/blender/functions/FN_multi_function_data_type.hh @@ -109,9 +109,9 @@ class MFDataType { return ""; } - uint hash() const + uint64_t hash() const { - return DefaultHash<CPPType>{}(*type_) + (uint32_t)category_; + return DefaultHash<CPPType>{}(*type_) + (uint64_t)category_; } }; diff --git a/source/blender/functions/FN_multi_function_network.hh b/source/blender/functions/FN_multi_function_network.hh index 91eb5bb65dc..f6d6c7417e7 100644 --- a/source/blender/functions/FN_multi_function_network.hh +++ b/source/blender/functions/FN_multi_function_network.hh @@ -62,14 +62,14 @@ class MFNode : NonCopyable, NonMovable { Span<MFInputSocket *> inputs_; Span<MFOutputSocket *> outputs_; bool is_dummy_; - uint id_; + int id_; friend MFNetwork; public: StringRefNull name() const; - uint id() const; + int id() const; MFNetwork &network(); const MFNetwork &network() const; @@ -83,11 +83,11 @@ class MFNode : NonCopyable, NonMovable { MFFunctionNode &as_function(); const MFFunctionNode &as_function() const; - MFInputSocket &input(uint index); - const MFInputSocket &input(uint index) const; + MFInputSocket &input(int index); + const MFInputSocket &input(int index) const; - MFOutputSocket &output(uint index); - const MFOutputSocket &output(uint index) const; + MFOutputSocket &output(int index); + const MFOutputSocket &output(int index) const; Span<MFInputSocket *> inputs(); Span<const MFInputSocket *> inputs() const; @@ -104,8 +104,8 @@ class MFNode : NonCopyable, NonMovable { class MFFunctionNode : public MFNode { private: const MultiFunction *function_; - Span<uint> input_param_indices_; - Span<uint> output_param_indices_; + Span<int> input_param_indices_; + Span<int> output_param_indices_; friend MFNetwork; @@ -114,8 +114,8 @@ class MFFunctionNode : public MFNode { const MultiFunction &function() const; - const MFInputSocket &input_for_param(uint param_index) const; - const MFOutputSocket &output_for_param(uint param_index) const; + const MFInputSocket &input_for_param(int param_index) const; + const MFOutputSocket &output_for_param(int param_index) const; }; class MFDummyNode : public MFNode { @@ -137,9 +137,9 @@ class MFSocket : NonCopyable, NonMovable { protected: MFNode *node_; bool is_output_; - uint index_; + int index_; MFDataType data_type_; - uint id_; + int id_; StringRefNull name_; friend MFNetwork; @@ -147,8 +147,8 @@ class MFSocket : NonCopyable, NonMovable { public: StringRefNull name() const; - uint id() const; - uint index() const; + int id() const; + int index() const; const MFDataType &data_type() const; @@ -217,17 +217,17 @@ class MFNetwork : NonCopyable, NonMovable { void remove(MFNode &node); void remove(Span<MFNode *> nodes); - uint socket_id_amount() const; - uint node_id_amount() const; + int socket_id_amount() const; + int node_id_amount() const; Span<MFDummyNode *> dummy_nodes(); Span<MFFunctionNode *> function_nodes(); - MFNode *node_or_null_by_id(uint id); - const MFNode *node_or_null_by_id(uint id) const; + MFNode *node_or_null_by_id(int id); + const MFNode *node_or_null_by_id(int id) const; - MFSocket *socket_or_null_by_id(uint id); - const MFSocket *socket_or_null_by_id(uint id) const; + MFSocket *socket_or_null_by_id(int id); + const MFSocket *socket_or_null_by_id(int id) const; void find_dependencies(Span<const MFInputSocket *> sockets, VectorSet<const MFOutputSocket *> &r_dummy_sockets, @@ -252,7 +252,7 @@ inline StringRefNull MFNode::name() const } } -inline uint MFNode::id() const +inline int MFNode::id() const { return id_; } @@ -301,22 +301,22 @@ inline const MFFunctionNode &MFNode::as_function() const return *(const MFFunctionNode *)this; } -inline MFInputSocket &MFNode::input(uint index) +inline MFInputSocket &MFNode::input(int index) { return *inputs_[index]; } -inline const MFInputSocket &MFNode::input(uint index) const +inline const MFInputSocket &MFNode::input(int index) const { return *inputs_[index]; } -inline MFOutputSocket &MFNode::output(uint index) +inline MFOutputSocket &MFNode::output(int index) { return *outputs_[index]; } -inline const MFOutputSocket &MFNode::output(uint index) const +inline const MFOutputSocket &MFNode::output(int index) const { return *outputs_[index]; } @@ -365,12 +365,12 @@ inline const MultiFunction &MFFunctionNode::function() const return *function_; } -inline const MFInputSocket &MFFunctionNode::input_for_param(uint param_index) const +inline const MFInputSocket &MFFunctionNode::input_for_param(int param_index) const { return this->input(input_param_indices_.first_index(param_index)); } -inline const MFOutputSocket &MFFunctionNode::output_for_param(uint param_index) const +inline const MFOutputSocket &MFFunctionNode::output_for_param(int param_index) const { return this->output(output_param_indices_.first_index(param_index)); } @@ -403,12 +403,12 @@ inline StringRefNull MFSocket::name() const return name_; } -inline uint MFSocket::id() const +inline int MFSocket::id() const { return id_; } -inline uint MFSocket::index() const +inline int MFSocket::index() const { return index_; } @@ -504,32 +504,32 @@ inline Span<MFFunctionNode *> MFNetwork::function_nodes() return function_nodes_; } -inline MFNode *MFNetwork::node_or_null_by_id(uint id) +inline MFNode *MFNetwork::node_or_null_by_id(int id) { return node_or_null_by_id_[id]; } -inline const MFNode *MFNetwork::node_or_null_by_id(uint id) const +inline const MFNode *MFNetwork::node_or_null_by_id(int id) const { return node_or_null_by_id_[id]; } -inline MFSocket *MFNetwork::socket_or_null_by_id(uint id) +inline MFSocket *MFNetwork::socket_or_null_by_id(int id) { return socket_or_null_by_id_[id]; } -inline const MFSocket *MFNetwork::socket_or_null_by_id(uint id) const +inline const MFSocket *MFNetwork::socket_or_null_by_id(int id) const { return socket_or_null_by_id_[id]; } -inline uint MFNetwork::socket_id_amount() const +inline int MFNetwork::socket_id_amount() const { return socket_or_null_by_id_.size(); } -inline uint MFNetwork::node_id_amount() const +inline int MFNetwork::node_id_amount() const { return node_or_null_by_id_.size(); } diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh index e6683693a0a..9cce8bb7401 100644 --- a/source/blender/functions/FN_multi_function_params.hh +++ b/source/blender/functions/FN_multi_function_params.hh @@ -34,7 +34,7 @@ namespace blender::fn { class MFParamsBuilder { private: const MFSignature *signature_; - uint min_array_size_; + int64_t min_array_size_; Vector<GVSpan> virtual_spans_; Vector<GMutableSpan> mutable_spans_; Vector<GVArraySpan> virtual_array_spans_; @@ -43,12 +43,12 @@ class MFParamsBuilder { friend class MFParams; public: - MFParamsBuilder(const MFSignature &signature, uint min_array_size) + MFParamsBuilder(const MFSignature &signature, int64_t min_array_size) : signature_(&signature), min_array_size_(min_array_size) { } - MFParamsBuilder(const class MultiFunction &fn, uint min_array_size); + MFParamsBuilder(const class MultiFunction &fn, int64_t min_array_size); template<typename T> void add_readonly_single_input(const T *value) { @@ -96,21 +96,21 @@ class MFParamsBuilder { vector_arrays_.append(&vector_array); } - GMutableSpan computed_array(uint param_index) + GMutableSpan computed_array(int param_index) { BLI_assert(ELEM(signature_->param_types[param_index].category(), MFParamType::SingleOutput, MFParamType::SingleMutable)); - uint data_index = signature_->data_index(param_index); + int data_index = signature_->data_index(param_index); return mutable_spans_[data_index]; } - GVectorArray &computed_vector_array(uint param_index) + GVectorArray &computed_vector_array(int param_index) { BLI_assert(ELEM(signature_->param_types[param_index].category(), MFParamType::VectorOutput, MFParamType::VectorMutable)); - uint data_index = signature_->data_index(param_index); + int data_index = signature_->data_index(param_index); return *vector_arrays_[data_index]; } @@ -119,13 +119,13 @@ class MFParamsBuilder { { UNUSED_VARS_NDEBUG(param_type); #ifdef DEBUG - uint param_index = this->current_param_index(); + int param_index = this->current_param_index(); MFParamType expected_type = signature_->param_types[param_index]; BLI_assert(expected_type == param_type); #endif } - uint current_param_index() const + int current_param_index() const { return virtual_spans_.size() + mutable_spans_.size() + virtual_array_spans_.size() + vector_arrays_.size(); @@ -141,75 +141,75 @@ class MFParams { { } - template<typename T> VSpan<T> readonly_single_input(uint param_index, StringRef name = "") + template<typename T> VSpan<T> readonly_single_input(int param_index, StringRef name = "") { return this->readonly_single_input(param_index, name).typed<T>(); } - GVSpan readonly_single_input(uint param_index, StringRef name = "") + GVSpan readonly_single_input(int param_index, StringRef name = "") { this->assert_correct_param(param_index, name, MFParamType::SingleInput); - uint data_index = builder_->signature_->data_index(param_index); + int data_index = builder_->signature_->data_index(param_index); return builder_->virtual_spans_[data_index]; } template<typename T> - MutableSpan<T> uninitialized_single_output(uint param_index, StringRef name = "") + MutableSpan<T> uninitialized_single_output(int param_index, StringRef name = "") { return this->uninitialized_single_output(param_index, name).typed<T>(); } - GMutableSpan uninitialized_single_output(uint param_index, StringRef name = "") + GMutableSpan uninitialized_single_output(int param_index, StringRef name = "") { this->assert_correct_param(param_index, name, MFParamType::SingleOutput); - uint data_index = builder_->signature_->data_index(param_index); + int data_index = builder_->signature_->data_index(param_index); return builder_->mutable_spans_[data_index]; } - template<typename T> VArraySpan<T> readonly_vector_input(uint param_index, StringRef name = "") + template<typename T> VArraySpan<T> readonly_vector_input(int param_index, StringRef name = "") { return this->readonly_vector_input(param_index, name).typed<T>(); } - GVArraySpan readonly_vector_input(uint param_index, StringRef name = "") + GVArraySpan readonly_vector_input(int param_index, StringRef name = "") { this->assert_correct_param(param_index, name, MFParamType::VectorInput); - uint data_index = builder_->signature_->data_index(param_index); + int data_index = builder_->signature_->data_index(param_index); return builder_->virtual_array_spans_[data_index]; } - template<typename T> GVectorArrayRef<T> vector_output(uint param_index, StringRef name = "") + template<typename T> GVectorArrayRef<T> vector_output(int param_index, StringRef name = "") { return this->vector_output(param_index, name).typed<T>(); } - GVectorArray &vector_output(uint param_index, StringRef name = "") + GVectorArray &vector_output(int param_index, StringRef name = "") { this->assert_correct_param(param_index, name, MFParamType::VectorOutput); - uint data_index = builder_->signature_->data_index(param_index); + int data_index = builder_->signature_->data_index(param_index); return *builder_->vector_arrays_[data_index]; } - template<typename T> MutableSpan<T> single_mutable(uint param_index, StringRef name = "") + template<typename T> MutableSpan<T> single_mutable(int param_index, StringRef name = "") { return this->single_mutable(param_index, name).typed<T>(); } - GMutableSpan single_mutable(uint param_index, StringRef name = "") + GMutableSpan single_mutable(int param_index, StringRef name = "") { this->assert_correct_param(param_index, name, MFParamType::SingleMutable); - uint data_index = builder_->signature_->data_index(param_index); + int data_index = builder_->signature_->data_index(param_index); return builder_->mutable_spans_[data_index]; } - template<typename T> GVectorArrayRef<T> vector_mutable(uint param_index, StringRef name = "") + template<typename T> GVectorArrayRef<T> vector_mutable(int param_index, StringRef name = "") { return this->vector_mutable(param_index, name).typed<T>(); } - GVectorArray &vector_mutable(uint param_index, StringRef name = "") + GVectorArray &vector_mutable(int param_index, StringRef name = "") { this->assert_correct_param(param_index, name, MFParamType::VectorMutable); - uint data_index = builder_->signature_->data_index(param_index); + int data_index = builder_->signature_->data_index(param_index); return *builder_->vector_arrays_[data_index]; } private: - void assert_correct_param(uint param_index, StringRef name, MFParamType param_type) + void assert_correct_param(int param_index, StringRef name, MFParamType param_type) { UNUSED_VARS_NDEBUG(param_index, name, param_type); #ifdef DEBUG @@ -220,7 +220,7 @@ class MFParams { #endif } - void assert_correct_param(uint param_index, StringRef name, MFParamType::Category category) + void assert_correct_param(int param_index, StringRef name, MFParamType::Category category) { UNUSED_VARS_NDEBUG(param_index, name, category); #ifdef DEBUG diff --git a/source/blender/functions/FN_multi_function_signature.hh b/source/blender/functions/FN_multi_function_signature.hh index e2cf783753e..af5f61fe2ee 100644 --- a/source/blender/functions/FN_multi_function_signature.hh +++ b/source/blender/functions/FN_multi_function_signature.hh @@ -33,11 +33,11 @@ namespace blender::fn { struct MFSignature { std::string function_name; /* Use RawAllocator so that a MultiFunction can have static storage duration. */ - Vector<std::string, 4, RawAllocator> param_names; - Vector<MFParamType, 4, RawAllocator> param_types; - Vector<uint, 4, RawAllocator> param_data_indices; + RawVector<std::string> param_names; + RawVector<MFParamType> param_types; + RawVector<int> param_data_indices; - uint data_index(uint param_index) const + int data_index(int param_index) const { return param_data_indices[param_index]; } @@ -46,10 +46,10 @@ struct MFSignature { class MFSignatureBuilder { private: MFSignature &data_; - uint span_count_ = 0; - uint virtual_span_count_ = 0; - uint virtual_array_span_count_ = 0; - uint vector_array_count_ = 0; + int span_count_ = 0; + int virtual_span_count_ = 0; + int virtual_array_span_count_ = 0; + int vector_array_count_ = 0; public: MFSignatureBuilder(MFSignature &data) : data_(data) diff --git a/source/blender/functions/FN_spans.hh b/source/blender/functions/FN_spans.hh index c8c98d66628..d8b381199cc 100644 --- a/source/blender/functions/FN_spans.hh +++ b/source/blender/functions/FN_spans.hh @@ -52,12 +52,13 @@ class GSpan { private: const CPPType *type_; const void *buffer_; - uint size_; + int64_t size_; public: - GSpan(const CPPType &type, const void *buffer, uint size) + GSpan(const CPPType &type, const void *buffer, int64_t size) : type_(&type), buffer_(buffer), size_(size) { + BLI_assert(size >= 0); BLI_assert(buffer != nullptr || size == 0); BLI_assert(type.pointer_has_valid_alignment(buffer)); } @@ -81,7 +82,7 @@ class GSpan { return size_ == 0; } - uint size() const + int64_t size() const { return size_; } @@ -91,7 +92,7 @@ class GSpan { return buffer_; } - const void *operator[](uint index) const + const void *operator[](int64_t index) const { BLI_assert(index < size_); return POINTER_OFFSET(buffer_, type_->size() * index); @@ -112,12 +113,13 @@ class GMutableSpan { private: const CPPType *type_; void *buffer_; - uint size_; + int64_t size_; public: - GMutableSpan(const CPPType &type, void *buffer, uint size) + GMutableSpan(const CPPType &type, void *buffer, int64_t size) : type_(&type), buffer_(buffer), size_(size) { + BLI_assert(size >= 0); BLI_assert(buffer != nullptr || size == 0); BLI_assert(type.pointer_has_valid_alignment(buffer)); } @@ -147,7 +149,7 @@ class GMutableSpan { return size_ == 0; } - uint size() const + int64_t size() const { return size_; } @@ -157,7 +159,7 @@ class GMutableSpan { return buffer_; } - void *operator[](uint index) + void *operator[](int64_t index) { BLI_assert(index < size_); return POINTER_OFFSET(buffer_, type_->size() * index); @@ -178,7 +180,7 @@ enum class VSpanCategory { template<typename T> struct VSpanBase { protected: - uint virtual_size_; + int64_t virtual_size_; VSpanCategory category_; union { struct { @@ -212,7 +214,7 @@ template<typename T> struct VSpanBase { return this->virtual_size_ == 0; } - uint size() const + int64_t size() const { return this->virtual_size_; } @@ -259,7 +261,7 @@ template<typename T> class VSpan : public VSpanBase<T> { this->data_.full_pointer_array.data = values.begin(); } - static VSpan FromSingle(const T *value, uint virtual_size) + static VSpan FromSingle(const T *value, int64_t virtual_size) { VSpan ref; ref.virtual_size_ = virtual_size; @@ -268,8 +270,9 @@ template<typename T> class VSpan : public VSpanBase<T> { return ref; } - const T &operator[](uint index) const + const T &operator[](int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index < this->virtual_size_); switch (this->category_) { case VSpanCategory::Single: @@ -329,7 +332,7 @@ class GVSpan : public VSpanBase<void> { { } - static GVSpan FromSingle(const CPPType &type, const void *value, uint virtual_size) + static GVSpan FromSingle(const CPPType &type, const void *value, int64_t virtual_size) { GVSpan ref; ref.type_ = &type; @@ -341,7 +344,7 @@ class GVSpan : public VSpanBase<void> { static GVSpan FromSingleWithMaxSize(const CPPType &type, const void *value) { - return GVSpan::FromSingle(type, value, UINT32_MAX); + return GVSpan::FromSingle(type, value, INT64_MAX); } static GVSpan FromDefault(const CPPType &type) @@ -349,7 +352,7 @@ class GVSpan : public VSpanBase<void> { return GVSpan::FromSingleWithMaxSize(type, type.default_value()); } - static GVSpan FromFullPointerArray(const CPPType &type, const void *const *values, uint size) + static GVSpan FromFullPointerArray(const CPPType &type, const void *const *values, int64_t size) { GVSpan ref; ref.type_ = &type; @@ -364,8 +367,9 @@ class GVSpan : public VSpanBase<void> { return *this->type_; } - const void *operator[](uint index) const + const void *operator[](int64_t index) const { + BLI_assert(index >= 0); BLI_assert(index < this->virtual_size_); switch (this->category_) { case VSpanCategory::Single: @@ -400,8 +404,8 @@ class GVSpan : public VSpanBase<void> { { BLI_assert(this->size() >= mask.min_array_size()); - uint element_size = type_->size(); - for (uint i : mask) { + int64_t element_size = type_->size(); + for (int64_t i : mask) { type_->copy_to_uninitialized((*this)[i], POINTER_OFFSET(dst, element_size * i)); } } diff --git a/source/blender/functions/intern/attributes_ref.cc b/source/blender/functions/intern/attributes_ref.cc index f61a9165c47..7bfcc69671a 100644 --- a/source/blender/functions/intern/attributes_ref.cc +++ b/source/blender/functions/intern/attributes_ref.cc @@ -20,7 +20,7 @@ namespace blender::fn { AttributesInfoBuilder::~AttributesInfoBuilder() { - for (uint i : defaults_.index_range()) { + for (int i : defaults_.index_range()) { types_[i]->destruct(defaults_[i]); } } @@ -45,7 +45,7 @@ void AttributesInfoBuilder::add(StringRef name, const CPPType &type, const void AttributesInfo::AttributesInfo(const AttributesInfoBuilder &builder) { - for (uint i : builder.types_.index_range()) { + for (int i : builder.types_.index_range()) { StringRefNull name = allocator_.copy_string(builder.names_[i]); const CPPType &type = *builder.types_[i]; const void *default_value = builder.defaults_[i]; @@ -62,7 +62,7 @@ AttributesInfo::AttributesInfo(const AttributesInfoBuilder &builder) AttributesInfo::~AttributesInfo() { - for (uint i : defaults_.index_range()) { + for (int i : defaults_.index_range()) { type_by_index_[i]->destruct(defaults_[i]); } } diff --git a/source/blender/functions/intern/multi_function_builder.cc b/source/blender/functions/intern/multi_function_builder.cc index 7797c19d563..06084247e66 100644 --- a/source/blender/functions/intern/multi_function_builder.cc +++ b/source/blender/functions/intern/multi_function_builder.cc @@ -37,7 +37,7 @@ void CustomMF_GenericConstant::call(IndexMask mask, type_.fill_uninitialized_indices(value_, output.buffer(), mask); } -uint CustomMF_GenericConstant::hash() const +uint64_t CustomMF_GenericConstant::hash() const { return type_.hash(value_); } @@ -58,8 +58,8 @@ static std::string gspan_to_string(GSpan array) { std::stringstream ss; ss << "["; - uint max_amount = 5; - for (uint i : IndexRange(std::min(max_amount, array.size()))) { + const int64_t max_amount = 5; + for (int64_t i : IndexRange(std::min(max_amount, array.size()))) { array.type().debug_print(array[i], ss); ss << ", "; } @@ -82,7 +82,7 @@ void CustomMF_GenericConstantArray::call(IndexMask mask, MFContext UNUSED(context)) const { GVectorArray &vectors = params.vector_output(0); - for (uint i : mask) { + for (int64_t i : mask) { vectors.extend(i, array_); } } @@ -102,7 +102,7 @@ CustomMF_DefaultOutput::CustomMF_DefaultOutput(StringRef name, } void CustomMF_DefaultOutput::call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const { - for (uint param_index : this->param_indices()) { + for (int param_index : this->param_indices()) { MFParamType param_type = this->param_type(param_index); if (!param_type.is_output()) { continue; diff --git a/source/blender/functions/intern/multi_function_network.cc b/source/blender/functions/intern/multi_function_network.cc index 1d3d3a8b5f2..cd3c38dd09f 100644 --- a/source/blender/functions/intern/multi_function_network.cc +++ b/source/blender/functions/intern/multi_function_network.cc @@ -50,9 +50,9 @@ void MFNode::destruct_sockets() */ MFFunctionNode &MFNetwork::add_function(const MultiFunction &function) { - Vector<uint, 16> input_param_indices, output_param_indices; + Vector<int, 16> input_param_indices, output_param_indices; - for (uint param_index : function.param_indices()) { + for (int param_index : function.param_indices()) { switch (function.param_type(param_index).interface_type()) { case MFParamType::Input: { input_param_indices.append(param_index); @@ -77,16 +77,16 @@ MFFunctionNode &MFNetwork::add_function(const MultiFunction &function) node.is_dummy_ = false; node.id_ = node_or_null_by_id_.append_and_get_index(&node); node.function_ = &function; - node.input_param_indices_ = allocator_.construct_array_copy<uint>(input_param_indices); - node.output_param_indices_ = allocator_.construct_array_copy<uint>(output_param_indices); + node.input_param_indices_ = allocator_.construct_array_copy<int>(input_param_indices); + node.output_param_indices_ = allocator_.construct_array_copy<int>(output_param_indices); node.inputs_ = allocator_.construct_elements_and_pointer_array<MFInputSocket>( input_param_indices.size()); node.outputs_ = allocator_.construct_elements_and_pointer_array<MFOutputSocket>( output_param_indices.size()); - for (uint i : input_param_indices.index_range()) { - uint param_index = input_param_indices[i]; + for (int i : input_param_indices.index_range()) { + int param_index = input_param_indices[i]; MFParamType param = function.param_type(param_index); BLI_assert(param.is_input_or_mutable()); @@ -100,8 +100,8 @@ MFFunctionNode &MFNetwork::add_function(const MultiFunction &function) socket.id_ = socket_or_null_by_id_.append_and_get_index(&socket); } - for (uint i : output_param_indices.index_range()) { - uint param_index = output_param_indices[i]; + for (int i : output_param_indices.index_range()) { + int param_index = output_param_indices[i]; MFParamType param = function.param_type(param_index); BLI_assert(param.is_output_or_mutable()); @@ -145,7 +145,7 @@ MFDummyNode &MFNetwork::add_dummy(StringRef name, node.input_names_ = allocator_.allocate_array<StringRefNull>(input_types.size()); node.output_names_ = allocator_.allocate_array<StringRefNull>(output_types.size()); - for (uint i : input_types.index_range()) { + for (int i : input_types.index_range()) { MFInputSocket &socket = *node.inputs_[i]; socket.data_type_ = input_types[i]; socket.node_ = &node; @@ -156,7 +156,7 @@ MFDummyNode &MFNetwork::add_dummy(StringRef name, node.input_names_[i] = socket.name_; } - for (uint i : output_types.index_range()) { + for (int i : output_types.index_range()) { MFOutputSocket &socket = *node.outputs_[i]; socket.data_type_ = output_types[i]; socket.node_ = &node; diff --git a/source/blender/functions/intern/multi_function_network_evaluation.cc b/source/blender/functions/intern/multi_function_network_evaluation.cc index b59cbc6a1a2..a7e1a2f42af 100644 --- a/source/blender/functions/intern/multi_function_network_evaluation.cc +++ b/source/blender/functions/intern/multi_function_network_evaluation.cc @@ -55,10 +55,10 @@ class MFNetworkEvaluationStorage { LinearAllocator<> allocator_; IndexMask mask_; Array<Value *> value_per_output_id_; - uint min_array_size_; + int64_t min_array_size_; public: - MFNetworkEvaluationStorage(IndexMask mask, uint socket_id_amount); + MFNetworkEvaluationStorage(IndexMask mask, int socket_id_amount); ~MFNetworkEvaluationStorage(); /* Add the values that have been provided by the caller of the multi-function network. */ @@ -155,8 +155,8 @@ void MFNetworkEvaluator::call(IndexMask mask, MFParams params, MFContext context BLI_NOINLINE void MFNetworkEvaluator::copy_inputs_to_storage(MFParams params, Storage &storage) const { - for (uint input_index : inputs_.index_range()) { - uint param_index = input_index + 0; + for (int input_index : inputs_.index_range()) { + int param_index = input_index + 0; const MFOutputSocket &socket = *inputs_[input_index]; switch (socket.data_type().category()) { case MFDataType::Single: { @@ -178,8 +178,8 @@ BLI_NOINLINE void MFNetworkEvaluator::copy_outputs_to_storage( Storage &storage, Vector<const MFInputSocket *> &outputs_to_initialize_in_the_end) const { - for (uint output_index : outputs_.index_range()) { - uint param_index = output_index + inputs_.size(); + for (int output_index : outputs_.index_range()) { + int param_index = output_index + inputs_.size(); const MFInputSocket &socket = *outputs_[output_index]; const MFOutputSocket &origin = *socket.origin(); @@ -263,7 +263,7 @@ BLI_NOINLINE void MFNetworkEvaluator::evaluate_function(MFContext &global_contex * function only on a single element. This can avoid many duplicate computations. */ MFParamsBuilder params{function, 1}; - for (uint param_index : function.param_indices()) { + for (int param_index : function.param_indices()) { MFParamType param_type = function.param_type(param_index); switch (param_type.category()) { case MFParamType::SingleInput: { @@ -312,7 +312,7 @@ BLI_NOINLINE void MFNetworkEvaluator::evaluate_function(MFContext &global_contex else { MFParamsBuilder params{function, storage.mask().min_array_size()}; - for (uint param_index : function.param_indices()) { + for (int param_index : function.param_indices()) { MFParamType param_type = function.param_type(param_index); switch (param_type.category()) { case MFParamType::SingleInput: { @@ -384,7 +384,7 @@ BLI_NOINLINE void MFNetworkEvaluator::initialize_remaining_outputs( MFParams params, Storage &storage, Span<const MFInputSocket *> remaining_outputs) const { for (const MFInputSocket *socket : remaining_outputs) { - uint param_index = inputs_.size() + outputs_.first_index_of(socket); + int param_index = inputs_.size() + outputs_.first_index_of(socket); switch (socket->data_type().category()) { case MFDataType::Single: { @@ -506,7 +506,7 @@ struct OwnVectorValue : public Value { /** \name Storage methods * \{ */ -MFNetworkEvaluationStorage::MFNetworkEvaluationStorage(IndexMask mask, uint socket_id_amount) +MFNetworkEvaluationStorage::MFNetworkEvaluationStorage(IndexMask mask, int socket_id_amount) : mask_(mask), value_per_output_id_(socket_id_amount, nullptr), min_array_size_(mask.min_array_size()) diff --git a/source/blender/functions/intern/multi_function_network_optimization.cc b/source/blender/functions/intern/multi_function_network_optimization.cc index 849b24a318f..e76b2f51a15 100644 --- a/source/blender/functions/intern/multi_function_network_optimization.cc +++ b/source/blender/functions/intern/multi_function_network_optimization.cc @@ -107,7 +107,7 @@ static Vector<MFNode *> find_nodes_based_on_mask(MFNetwork &network, bool mask_value) { Vector<MFNode *> nodes; - for (uint id : id_mask.index_range()) { + for (int id : id_mask.index_range()) { if (id_mask[id] == mask_value) { MFNode *node = network.node_or_null_by_id(id); if (node != nullptr) { @@ -212,7 +212,7 @@ static void prepare_params_for_constant_folding(const MultiFunction &network_fn, MFParamsBuilder ¶ms, ResourceCollector &resources) { - for (uint param_index : network_fn.param_indices()) { + for (int param_index : network_fn.param_indices()) { MFParamType param_type = network_fn.param_type(param_index); MFDataType data_type = param_type.data_type(); @@ -244,7 +244,7 @@ static Array<MFOutputSocket *> add_constant_folded_sockets(const MultiFunction & { Array<MFOutputSocket *> folded_sockets{network_fn.param_indices().size(), nullptr}; - for (uint param_index : network_fn.param_indices()) { + for (int param_index : network_fn.param_indices()) { MFParamType param_type = network_fn.param_type(param_index); MFDataType data_type = param_type.data_type(); @@ -302,7 +302,7 @@ void constant_folding(MFNetwork &network, ResourceCollector &resources) Array<MFOutputSocket *> folded_sockets = compute_constant_sockets_and_add_folded_nodes( network, inputs_to_fold, resources); - for (uint i : inputs_to_fold.index_range()) { + for (int i : inputs_to_fold.index_range()) { MFOutputSocket &original_socket = *inputs_to_fold[i]->origin(); network.relink(original_socket, *folded_sockets[i]); } @@ -317,12 +317,12 @@ void constant_folding(MFNetwork &network, ResourceCollector &resources) * * \{ */ -static uint32_t compute_node_hash(MFFunctionNode &node, RNG *rng, Span<uint32_t> node_hashes) +static uint64_t compute_node_hash(MFFunctionNode &node, RNG *rng, Span<uint64_t> node_hashes) { - uint32_t combined_inputs_hash = 394659347u; + uint64_t combined_inputs_hash = 394659347u; for (MFInputSocket *input_socket : node.inputs()) { MFOutputSocket *origin_socket = input_socket->origin(); - uint32_t input_hash; + uint64_t input_hash; if (origin_socket == nullptr) { input_hash = BLI_rng_get_uint(rng); } @@ -333,8 +333,8 @@ static uint32_t compute_node_hash(MFFunctionNode &node, RNG *rng, Span<uint32_t> combined_inputs_hash = BLI_ghashutil_combine_hash(combined_inputs_hash, input_hash); } - uint32_t function_hash = node.function().hash(); - uint32_t node_hash = BLI_ghashutil_combine_hash(combined_inputs_hash, function_hash); + uint64_t function_hash = node.function().hash(); + uint64_t node_hash = BLI_ghashutil_combine_hash(combined_inputs_hash, function_hash); return node_hash; } @@ -342,15 +342,15 @@ static uint32_t compute_node_hash(MFFunctionNode &node, RNG *rng, Span<uint32_t> * Produces a hash for every node. Two nodes with the same hash should have a high probability of * outputting the same values. */ -static Array<uint32_t> compute_node_hashes(MFNetwork &network) +static Array<uint64_t> compute_node_hashes(MFNetwork &network) { RNG *rng = BLI_rng_new(0); - Array<uint32_t> node_hashes(network.node_id_amount()); + Array<uint64_t> node_hashes(network.node_id_amount()); Array<bool> node_is_hashed(network.node_id_amount(), false); /* No dummy nodes are not assumed to output the same values. */ for (MFDummyNode *node : network.dummy_nodes()) { - uint32_t node_hash = BLI_rng_get_uint(rng); + uint64_t node_hash = BLI_rng_get_uint(rng); node_hashes[node->id()] = node_hash; node_is_hashed[node->id()] = true; } @@ -381,7 +381,7 @@ static Array<uint32_t> compute_node_hashes(MFNetwork &network) continue; } - uint32_t node_hash = compute_node_hash(node, rng, node_hashes); + uint64_t node_hash = compute_node_hash(node, rng, node_hashes); node_hashes[node.id()] = node_hash; node_is_hashed[node.id()] = true; nodes_to_check.pop(); @@ -391,14 +391,14 @@ static Array<uint32_t> compute_node_hashes(MFNetwork &network) return node_hashes; } -static Map<uint32_t, Vector<MFNode *, 1>> group_nodes_by_hash(MFNetwork &network, - Span<uint32_t> node_hashes) +static Map<uint64_t, Vector<MFNode *, 1>> group_nodes_by_hash(MFNetwork &network, + Span<uint64_t> node_hashes) { - Map<uint32_t, Vector<MFNode *, 1>> nodes_by_hash; - for (uint id : IndexRange(network.node_id_amount())) { + Map<uint64_t, Vector<MFNode *, 1>> nodes_by_hash; + for (int id : IndexRange(network.node_id_amount())) { MFNode *node = network.node_or_null_by_id(id); if (node != nullptr) { - uint32_t node_hash = node_hashes[id]; + uint64_t node_hash = node_hashes[id]; nodes_by_hash.lookup_or_add_default(node_hash).append(node); } } @@ -428,7 +428,7 @@ static bool nodes_output_same_values(DisjointSet &cache, const MFNode &a, const if (!functions_are_equal(a.as_function().function(), b.as_function().function())) { return false; } - for (uint i : a.inputs().index_range()) { + for (int i : a.inputs().index_range()) { const MFOutputSocket *origin_a = a.input(i).origin(); const MFOutputSocket *origin_b = b.input(i).origin(); if (origin_a == nullptr || origin_b == nullptr) { @@ -444,7 +444,7 @@ static bool nodes_output_same_values(DisjointSet &cache, const MFNode &a, const } static void relink_duplicate_nodes(MFNetwork &network, - Map<uint32_t, Vector<MFNode *, 1>> &nodes_by_hash) + Map<uint64_t, Vector<MFNode *, 1>> &nodes_by_hash) { DisjointSet same_node_cache{network.node_id_amount()}; @@ -462,7 +462,7 @@ static void relink_duplicate_nodes(MFNetwork &network, /* This is true with fairly high probability, but hash collisions can happen. So we have to * check if the node actually output the same values. */ if (nodes_output_same_values(same_node_cache, deduplicated_node, *node)) { - for (uint i : deduplicated_node.outputs().index_range()) { + for (int i : deduplicated_node.outputs().index_range()) { network.relink(node->output(i), deduplicated_node.output(i)); } } @@ -481,8 +481,8 @@ static void relink_duplicate_nodes(MFNetwork &network, */ void common_subnetwork_elimination(MFNetwork &network) { - Array<uint32_t> node_hashes = compute_node_hashes(network); - Map<uint32_t, Vector<MFNode *, 1>> nodes_by_hash = group_nodes_by_hash(network, node_hashes); + Array<uint64_t> node_hashes = compute_node_hashes(network); + Map<uint64_t, Vector<MFNode *, 1>> nodes_by_hash = group_nodes_by_hash(network, node_hashes); relink_duplicate_nodes(network, nodes_by_hash); } diff --git a/source/blender/gpu/intern/gpu_draw_smoke.c b/source/blender/gpu/intern/gpu_draw_smoke.c index 89261afaebd..e0b94e20574 100644 --- a/source/blender/gpu/intern/gpu_draw_smoke.c +++ b/source/blender/gpu/intern/gpu_draw_smoke.c @@ -196,7 +196,7 @@ static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres) float *data; if (highres) { - data = manta_smoke_turbulence_get_density(fds->fluid); + data = manta_noise_get_density(fds->fluid); } else { data = manta_smoke_get_density(fds->fluid); @@ -212,14 +212,14 @@ static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres) static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres) { - const bool has_color = (highres) ? manta_smoke_turbulence_has_colors(fds->fluid) : + const bool has_color = (highres) ? manta_noise_has_colors(fds->fluid) : manta_smoke_has_colors(fds->fluid); if (!has_color) { return NULL; } - int cell_count = (highres) ? manta_smoke_turbulence_get_cells(fds->fluid) : fds->total_cells; + int cell_count = (highres) ? manta_noise_get_cells(fds->fluid) : fds->total_cells; int *dim = (highres) ? fds->res_noise : fds->res; float *data = MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture"); @@ -228,7 +228,7 @@ static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres) } if (highres) { - manta_smoke_turbulence_get_rgba(fds->fluid, data, 0); + manta_noise_get_rgba(fds->fluid, data, 0); } else { manta_smoke_get_rgba(fds->fluid, data, 0); @@ -245,7 +245,7 @@ static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres) static GPUTexture *create_flame_texture(FluidDomainSettings *fds, int highres) { float *source = NULL; - const bool has_fuel = (highres) ? manta_smoke_turbulence_has_fuel(fds->fluid) : + const bool has_fuel = (highres) ? manta_noise_has_fuel(fds->fluid) : manta_smoke_has_fuel(fds->fluid); int *dim = (highres) ? fds->res_noise : fds->res; @@ -254,7 +254,7 @@ static GPUTexture *create_flame_texture(FluidDomainSettings *fds, int highres) } if (highres) { - source = manta_smoke_turbulence_get_flame(fds->fluid); + source = manta_noise_get_flame(fds->fluid); } else { source = manta_smoke_get_flame(fds->fluid); diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 3387958c2f6..71b8eee9d50 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -718,10 +718,10 @@ static int rna_FluidModifier_grid_get_length(PointerRNA *ptr, int length[RNA_MAX /* high resolution smoke */ int res[3]; - manta_smoke_turbulence_get_res(fds->fluid, res); + manta_noise_get_res(fds->fluid, res); size = res[0] * res[1] * res[2]; - density = manta_smoke_turbulence_get_density(fds->fluid); + density = manta_noise_get_density(fds->fluid); } else if (fds->fluid) { /* regular resolution */ @@ -790,7 +790,7 @@ static void rna_FluidModifier_density_grid_get(PointerRNA *ptr, float *values) BLI_rw_mutex_lock(fds->fluid_mutex, THREAD_LOCK_READ); if (fds->flags & FLUID_DOMAIN_USE_NOISE && fds->fluid) { - density = manta_smoke_turbulence_get_density(fds->fluid); + density = manta_noise_get_density(fds->fluid); } else { density = manta_smoke_get_density(fds->fluid); @@ -837,11 +837,11 @@ static void rna_FluidModifier_color_grid_get(PointerRNA *ptr, float *values) } else { if (fds->flags & FLUID_DOMAIN_USE_NOISE) { - if (manta_smoke_turbulence_has_colors(fds->fluid)) { - manta_smoke_turbulence_get_rgba(fds->fluid, values, 0); + if (manta_noise_has_colors(fds->fluid)) { + manta_noise_get_rgba(fds->fluid, values, 0); } else { - manta_smoke_turbulence_get_rgba_fixed_color(fds->fluid, fds->active_color, values, 0); + manta_noise_get_rgba_fixed_color(fds->fluid, fds->active_color, values, 0); } } else { @@ -867,7 +867,7 @@ static void rna_FluidModifier_flame_grid_get(PointerRNA *ptr, float *values) BLI_rw_mutex_lock(fds->fluid_mutex, THREAD_LOCK_READ); if (fds->flags & FLUID_DOMAIN_USE_NOISE && fds->fluid) { - flame = manta_smoke_turbulence_get_flame(fds->fluid); + flame = manta_noise_get_flame(fds->fluid); } else { flame = manta_smoke_get_flame(fds->fluid); @@ -917,7 +917,7 @@ static void rna_FluidModifier_temperature_grid_get(PointerRNA *ptr, float *value BLI_rw_mutex_lock(fds->fluid_mutex, THREAD_LOCK_READ); if (fds->flags & FLUID_DOMAIN_USE_NOISE && fds->fluid) { - flame = manta_smoke_turbulence_get_flame(fds->fluid); + flame = manta_noise_get_flame(fds->fluid); } else { flame = manta_smoke_get_flame(fds->fluid); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 332108facb3..6f0192bb810 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4448,7 +4448,7 @@ static void def_sh_tex_sky(StructRNA *srna) RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update"); prop = RNA_def_property(srna, "sun_size", PROP_FLOAT, PROP_ANGLE); - RNA_def_property_ui_text(prop, "Sun Size", "Size of sun disc (angular diameter)"); + RNA_def_property_ui_text(prop, "Sun Size", "Size of sun disc"); RNA_def_property_range(prop, 0.0f, M_PI_2); RNA_def_property_float_default(prop, DEG2RADF(0.545)); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -4460,7 +4460,7 @@ static void def_sh_tex_sky(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "sun_elevation", PROP_FLOAT, PROP_ANGLE); - RNA_def_property_ui_text(prop, "Sun Elevation", "Angle between sun and horizon"); + RNA_def_property_ui_text(prop, "Sun Elevation", "Sun angle from horizon"); RNA_def_property_range(prop, -M_PI_2, M_PI_2); RNA_def_property_float_default(prop, M_PI_2); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -4471,25 +4471,25 @@ static void def_sh_tex_sky(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "altitude", PROP_FLOAT, PROP_NONE); - RNA_def_property_ui_text(prop, "Altitude", "Height from sea level in km"); + RNA_def_property_ui_text(prop, "Altitude", "Height from sea level"); RNA_def_property_range(prop, 0.0f, 60.0f); RNA_def_property_float_default(prop, 0.0f); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "air_density", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_ui_text(prop, "Air", "Density of air molecules (Rayleigh scattering)"); + RNA_def_property_ui_text(prop, "Air", "Density of air molecules"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "dust_density", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_ui_text(prop, "Dust", "Density of dust and water molecules (Mie scattering)"); + RNA_def_property_ui_text(prop, "Dust", "Density of dust molecules and water droplets"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "ozone_density", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_ui_text(prop, "Ozone", "Density of Ozone layer (Ozone absorption)"); + RNA_def_property_ui_text(prop, "Ozone", "Density of Ozone layer"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index a41abb1a1dd..5b77632be79 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -27,6 +27,8 @@ #include "BLI_path_util.h" #include "BLI_utildefines.h" +#include "BPY_extern.h" + #include "DEG_depsgraph.h" #include "BKE_image.h" @@ -408,6 +410,19 @@ static PointerRNA rna_RenderEngine_camera_override_get(PointerRNA *ptr) } } +static void rna_RenderEngine_engine_frame_set(RenderEngine *engine, int frame, float subframe) +{ +# ifdef WITH_PYTHON + BPy_BEGIN_ALLOW_THREADS; +# endif + + RE_engine_frame_set(engine, frame, subframe); + +# ifdef WITH_PYTHON + BPy_END_ALLOW_THREADS; +# endif +} + static void rna_RenderResult_views_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { RenderResult *rr = (RenderResult *)ptr->data; @@ -673,7 +688,7 @@ static void rna_def_render_engine(BlenderRNA *brna) parm = RNA_def_string(func, "info", NULL, 0, "Info", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - func = RNA_def_function(srna, "frame_set", "RE_engine_frame_set"); + func = RNA_def_function(srna, "frame_set", "rna_RenderEngine_engine_frame_set"); RNA_def_function_ui_description(func, "Evaluate scene at a different frame (for motion blur)"); parm = RNA_def_int(func, "frame", 0, INT_MIN, INT_MAX, "Frame", "", INT_MIN, INT_MAX); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); @@ -830,6 +845,14 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Eevee Viewport", "Uses Eevee for viewport shading in LookDev shading mode"); + prop = RNA_def_property(srna, "bl_use_gpu_context", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_GPU_CONTEXT); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_ui_text( + prop, + "Use GPU Context", + "Enable OpenGL context for the render method, for engines that render using OpenGL"); + prop = RNA_def_property(srna, "bl_use_shading_nodes_custom", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SHADING_NODES_CUSTOM); RNA_def_property_boolean_default(prop, true); diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh index 84370dcd399..d79bd9031b8 100644 --- a/source/blender/nodes/NOD_derived_node_tree.hh +++ b/source/blender/nodes/NOD_derived_node_tree.hh @@ -46,15 +46,15 @@ class DSocket : NonCopyable, NonMovable { protected: DNode *node_; const SocketRef *socket_ref_; - uint id_; + int id_; friend DerivedNodeTree; public: const DNode &node() const; - uint id() const; - uint index() const; + int id() const; + int index() const; bool is_input() const; bool is_output() const; @@ -105,7 +105,7 @@ class DGroupInput : NonCopyable, NonMovable { const InputSocketRef *socket_ref_; DParentNode *parent_; Vector<DInputSocket *> linked_sockets_; - uint id_; + int id_; friend DerivedNodeTree; @@ -114,7 +114,7 @@ class DGroupInput : NonCopyable, NonMovable { bNodeSocket *bsocket() const; const DParentNode *parent() const; Span<const DInputSocket *> linked_sockets() const; - uint id() const; + int id() const; StringRefNull name() const; }; @@ -126,7 +126,7 @@ class DNode : NonCopyable, NonMovable { Span<DInputSocket *> inputs_; Span<DOutputSocket *> outputs_; - uint id_; + int id_; friend DerivedNodeTree; @@ -137,13 +137,13 @@ class DNode : NonCopyable, NonMovable { Span<const DInputSocket *> inputs() const; Span<const DOutputSocket *> outputs() const; - const DInputSocket &input(uint index) const; - const DOutputSocket &output(uint index) const; + const DInputSocket &input(int index) const; + const DOutputSocket &output(int index) const; - const DInputSocket &input(uint index, StringRef expected_name) const; - const DOutputSocket &output(uint index, StringRef expected_name) const; + const DInputSocket &input(int index, StringRef expected_name) const; + const DOutputSocket &output(int index, StringRef expected_name) const; - uint id() const; + int id() const; PointerRNA *rna() const; StringRefNull idname() const; @@ -157,14 +157,14 @@ class DParentNode : NonCopyable, NonMovable { private: const NodeRef *node_ref_; DParentNode *parent_; - uint id_; + int id_; friend DerivedNodeTree; public: const DParentNode *parent() const; const NodeRef &node_ref() const; - uint id() const; + int id() const; }; using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>; @@ -240,12 +240,12 @@ inline const DNode &DSocket::node() const return *node_; } -inline uint DSocket::id() const +inline int DSocket::id() const { return id_; } -inline uint DSocket::index() const +inline int DSocket::index() const { return socket_ref_->index(); } @@ -367,7 +367,7 @@ inline Span<const DInputSocket *> DGroupInput::linked_sockets() const return linked_sockets_; } -inline uint DGroupInput::id() const +inline int DGroupInput::id() const { return id_; } @@ -401,17 +401,17 @@ inline Span<const DOutputSocket *> DNode::outputs() const return outputs_; } -inline const DInputSocket &DNode::input(uint index) const +inline const DInputSocket &DNode::input(int index) const { return *inputs_[index]; } -inline const DOutputSocket &DNode::output(uint index) const +inline const DOutputSocket &DNode::output(int index) const { return *outputs_[index]; } -inline const DInputSocket &DNode::input(uint index, StringRef expected_name) const +inline const DInputSocket &DNode::input(int index, StringRef expected_name) const { const DInputSocket &socket = *inputs_[index]; BLI_assert(socket.name() == expected_name); @@ -419,7 +419,7 @@ inline const DInputSocket &DNode::input(uint index, StringRef expected_name) con return socket; } -inline const DOutputSocket &DNode::output(uint index, StringRef expected_name) const +inline const DOutputSocket &DNode::output(int index, StringRef expected_name) const { const DOutputSocket &socket = *outputs_[index]; BLI_assert(socket.name() == expected_name); @@ -427,7 +427,7 @@ inline const DOutputSocket &DNode::output(uint index, StringRef expected_name) c return socket; } -inline uint DNode::id() const +inline int DNode::id() const { return id_; } @@ -461,7 +461,7 @@ inline const NodeRef &DParentNode::node_ref() const return *node_ref_; } -inline uint DParentNode::id() const +inline int DParentNode::id() const { return id_; } diff --git a/source/blender/nodes/NOD_node_tree_multi_function.hh b/source/blender/nodes/NOD_node_tree_multi_function.hh index f7a1fbb114d..79c2b3c7ce8 100644 --- a/source/blender/nodes/NOD_node_tree_multi_function.hh +++ b/source/blender/nodes/NOD_node_tree_multi_function.hh @@ -106,7 +106,7 @@ class MFNetworkTreeMap { void add(Span<const DInputSocket *> dsockets, Span<fn::MFInputSocket *> sockets) { assert_same_size(dsockets, sockets); - for (uint i : dsockets.index_range()) { + for (int i : dsockets.index_range()) { this->add(*dsockets[i], *sockets[i]); } } @@ -114,7 +114,7 @@ class MFNetworkTreeMap { void add(Span<const DOutputSocket *> dsockets, Span<fn::MFOutputSocket *> sockets) { assert_same_size(dsockets, sockets); - for (uint i : dsockets.index_range()) { + for (int i : dsockets.index_range()) { this->add(*dsockets[i], *sockets[i]); } } @@ -133,7 +133,7 @@ class MFNetworkTreeMap { void add_try_match(Span<const DSocket *> dsockets, Span<fn::MFSocket *> sockets) { - uint used_sockets = 0; + int used_sockets = 0; for (const DSocket *dsocket : dsockets) { if (!dsocket->is_available()) { continue; diff --git a/source/blender/nodes/NOD_node_tree_ref.hh b/source/blender/nodes/NOD_node_tree_ref.hh index 907184125b8..ebf5709ef50 100644 --- a/source/blender/nodes/NOD_node_tree_ref.hh +++ b/source/blender/nodes/NOD_node_tree_ref.hh @@ -71,8 +71,8 @@ class SocketRef : NonCopyable, NonMovable { NodeRef *node_; bNodeSocket *bsocket_; bool is_input_; - uint id_; - uint index_; + int id_; + int index_; PointerRNA rna_; Vector<SocketRef *> linked_sockets_; Vector<SocketRef *> directly_linked_sockets_; @@ -87,8 +87,8 @@ class SocketRef : NonCopyable, NonMovable { const NodeRef &node() const; const NodeTreeRef &tree() const; - uint id() const; - uint index() const; + int id() const; + int index() const; bool is_input() const; bool is_output() const; @@ -124,7 +124,7 @@ class NodeRef : NonCopyable, NonMovable { NodeTreeRef *tree_; bNode *bnode_; PointerRNA rna_; - uint id_; + int id_; Vector<InputSocketRef *> inputs_; Vector<OutputSocketRef *> outputs_; @@ -136,8 +136,8 @@ class NodeRef : NonCopyable, NonMovable { Span<const InputSocketRef *> inputs() const; Span<const OutputSocketRef *> outputs() const; - const InputSocketRef &input(uint index) const; - const OutputSocketRef &output(uint index) const; + const InputSocketRef &input(int index) const; + const OutputSocketRef &output(int index) const; bNode *bnode() const; bNodeTree *btree() const; @@ -146,7 +146,7 @@ class NodeRef : NonCopyable, NonMovable { StringRefNull idname() const; StringRefNull name() const; - uint id() const; + int id() const; bool is_reroute_node() const; bool is_group_node() const; @@ -220,12 +220,12 @@ inline const NodeTreeRef &SocketRef::tree() const return node_->tree(); } -inline uint SocketRef::id() const +inline int SocketRef::id() const { return id_; } -inline uint SocketRef::index() const +inline int SocketRef::index() const { return index_; } @@ -334,12 +334,12 @@ inline Span<const OutputSocketRef *> NodeRef::outputs() const return outputs_; } -inline const InputSocketRef &NodeRef::input(uint index) const +inline const InputSocketRef &NodeRef::input(int index) const { return *inputs_[index]; } -inline const OutputSocketRef &NodeRef::output(uint index) const +inline const OutputSocketRef &NodeRef::output(int index) const { return *outputs_[index]; } @@ -369,7 +369,7 @@ inline StringRefNull NodeRef::name() const return bnode_->name; } -inline uint NodeRef::id() const +inline int NodeRef::id() const { return id_; } diff --git a/source/blender/nodes/intern/derived_node_tree.cc b/source/blender/nodes/intern/derived_node_tree.cc index daec67b53a9..b7c78cb1499 100644 --- a/source/blender/nodes/intern/derived_node_tree.cc +++ b/source/blender/nodes/intern/derived_node_tree.cc @@ -83,7 +83,7 @@ DNode &DerivedNodeTree::create_node(const NodeRef &node_ref, node.outputs_ = allocator_.construct_elements_and_pointer_array<DOutputSocket>( node_ref.outputs().size()); - for (uint i : node.inputs_.index_range()) { + for (int i : node.inputs_.index_range()) { const InputSocketRef &socket_ref = node_ref.input(i); DInputSocket &socket = *node.inputs_[i]; @@ -94,7 +94,7 @@ DNode &DerivedNodeTree::create_node(const NodeRef &node_ref, r_sockets_map[socket_ref.id()] = &socket; } - for (uint i : node.outputs_.index_range()) { + for (int i : node.outputs_.index_range()) { const OutputSocketRef &socket_ref = node_ref.output(i); DOutputSocket &socket = *node.outputs_[i]; @@ -113,7 +113,7 @@ BLI_NOINLINE void DerivedNodeTree::expand_groups(Vector<DNode *> &all_nodes, Vector<DParentNode *> &all_parent_nodes, NodeTreeRefMap &node_tree_refs) { - for (uint i = 0; i < all_nodes.size(); i++) { + for (int i = 0; i < all_nodes.size(); i++) { DNode &node = *all_nodes[i]; if (node.node_ref_->is_group_node()) { this->expand_group_node(node, all_nodes, all_group_inputs, all_parent_nodes, node_tree_refs); @@ -181,10 +181,10 @@ BLI_NOINLINE void DerivedNodeTree::relink_group_inputs(const NodeTreeRef &group_ const NodeRef &input_node_ref = *node_refs[0]; DNode &input_node = *nodes_by_id[input_node_ref.id()]; - uint input_amount = group_node.inputs().size(); + int input_amount = group_node.inputs().size(); BLI_assert(input_amount == input_node_ref.outputs().size() - 1); - for (uint input_index : IndexRange(input_amount)) { + for (int input_index : IndexRange(input_amount)) { DInputSocket *outside_group = group_node.inputs_[input_index]; DOutputSocket *inside_group = input_node.outputs_[input_index]; @@ -228,10 +228,10 @@ BLI_NOINLINE void DerivedNodeTree::relink_group_outputs(const NodeTreeRef &group const NodeRef &output_node_ref = *node_refs[0]; DNode &output_node = *nodes_by_id[output_node_ref.id()]; - uint output_amount = group_node.outputs().size(); + int output_amount = group_node.outputs().size(); BLI_assert(output_amount == output_node_ref.inputs().size() - 1); - for (uint output_index : IndexRange(output_amount)) { + for (int output_index : IndexRange(output_amount)) { DOutputSocket *outside_group = group_node.outputs_[output_index]; DInputSocket *inside_group = output_node.inputs_[output_index]; @@ -316,7 +316,7 @@ BLI_NOINLINE void DerivedNodeTree::store_in_this_and_init_ids( group_inputs_ = std::move(all_group_inputs); parent_nodes_ = std::move(all_parent_nodes); - for (uint node_index : nodes_by_id_.index_range()) { + for (int node_index : nodes_by_id_.index_range()) { DNode *node = nodes_by_id_[node_index]; node->id_ = node_index; @@ -333,7 +333,7 @@ BLI_NOINLINE void DerivedNodeTree::store_in_this_and_init_ids( } } - for (uint i : group_inputs_.index_range()) { + for (int i : group_inputs_.index_range()) { group_inputs_[i]->id_ = i; } } diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc index f77b19354a4..82842c4ef32 100644 --- a/source/blender/nodes/intern/node_tree_multi_function.cc +++ b/source/blender/nodes/intern/node_tree_multi_function.cc @@ -62,7 +62,7 @@ const fn::MultiFunction &NodeMFNetworkBuilder::get_default_fn(StringRef name) static void insert_dummy_node(CommonMFNetworkBuilderData &common, const DNode &dnode) { - constexpr uint stack_capacity = 10; + constexpr int stack_capacity = 10; Vector<fn::MFDataType, stack_capacity> input_types; Vector<StringRef, stack_capacity> input_names; @@ -159,7 +159,7 @@ static fn::MFOutputSocket *try_find_origin(CommonMFNetworkBuilderData &common, { Span<const DOutputSocket *> from_dsockets = to_dsocket.linked_sockets(); Span<const DGroupInput *> from_group_inputs = to_dsocket.linked_group_inputs(); - uint total_linked_amount = from_dsockets.size() + from_group_inputs.size(); + int total_linked_amount = from_dsockets.size() + from_group_inputs.size(); BLI_assert(total_linked_amount <= 1); if (total_linked_amount == 0) { diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.cc b/source/blender/nodes/shader/nodes/node_shader_map_range.cc index b026499ec4b..4a6c9ec9a4d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_map_range.cc +++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc @@ -115,13 +115,13 @@ class MapRangeFunction : public blender::fn::MultiFunction { blender::fn::VSpan<float> to_max = params.readonly_single_input<float>(4, "To Max"); blender::MutableSpan<float> results = params.uninitialized_single_output<float>(5, "Result"); - for (uint i : mask) { + for (int64_t i : mask) { float factor = safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]); results[i] = to_min[i] + factor * (to_max[i] - to_min[i]); } if (clamp_) { - for (uint i : mask) { + for (int64_t i : mask) { CLAMP(results[i], 0.0f, 1.0f); } } diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc index 4b4b80ea1ad..c1543f791f1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc @@ -80,7 +80,7 @@ class SeparateRGBFunction : public blender::fn::MultiFunction { blender::MutableSpan<float> gs = params.uninitialized_single_output<float>(2, "G"); blender::MutableSpan<float> bs = params.uninitialized_single_output<float>(3, "B"); - for (uint i : mask) { + for (int64_t i : mask) { blender::Color4f color = colors[i]; rs[i] = color.r; gs[i] = color.g; diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc index 03e18acc245..8b23327460f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc @@ -65,7 +65,7 @@ class MF_SeparateXYZ : public blender::fn::MultiFunction { blender::MutableSpan<float> ys = params.uninitialized_single_output<float>(2, "Y"); blender::MutableSpan<float> zs = params.uninitialized_single_output<float>(3, "Z"); - for (uint i : mask) { + for (int64_t i : mask) { blender::float3 xyz = vectors[i]; xs[i] = xyz.x; ys[i] = xyz.y; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c index d2c4413b862..94ffbbe0c55 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c @@ -43,9 +43,9 @@ static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) tex->turbidity = 2.2f; tex->ground_albedo = 0.3f; tex->sun_disc = true; - tex->sun_size = DEG2RADF(0.545); + tex->sun_size = DEG2RADF(0.545f); tex->sun_intensity = 1.0f; - tex->sun_elevation = M_PI_2; + tex->sun_elevation = DEG2RADF(15.0f); tex->sun_rotation = 0.0f; tex->altitude = 0.0f; tex->air_density = 1.0f; diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc b/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc index 21f15bcf6f4..7f712b0db40 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc @@ -148,7 +148,7 @@ class ColorBandFunction : public blender::fn::MultiFunction { params.uninitialized_single_output<blender::Color4f>(1, "Color"); blender::MutableSpan<float> alphas = params.uninitialized_single_output<float>(2, "Alpha"); - for (uint i : mask) { + for (int64_t i : mask) { blender::Color4f color; BKE_colorband_evaluate(&color_band_, values[i], color); colors[i] = color; diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 18d4c7da534..5c6e0b0a308 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -21,6 +21,7 @@ #ifndef __BPY_EXTERN_H__ #define __BPY_EXTERN_H__ +struct AnimationEvalContext; struct ChannelDriver; /* DNA_anim_types.h */ struct ID; /* DNA_ID.h */ struct ListBase; /* DNA_listBase.h */ @@ -117,7 +118,7 @@ void BPY_driver_reset(void); float BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, struct ChannelDriver *driver_orig, - const float evaltime); + const struct AnimationEvalContext *anim_eval_context); void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr); diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 9b191ee5698..3d83eb90da6 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -33,19 +33,22 @@ #include "BLI_math_base.h" #include "BLI_string.h" +#include "BKE_animsys.h" #include "BKE_fcurve_driver.h" #include "BKE_global.h" +#include "RNA_access.h" +#include "RNA_types.h" + #include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ #include "bpy_intern_string.h" #include "bpy_driver.h" +#include "bpy_rna.h" #include "BPY_extern.h" -extern void BPY_update_rna_module(void); - #define USE_RNA_AS_PYOBJECT #define USE_BYTECODE_WHITELIST @@ -377,6 +380,37 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d #endif /* USE_BYTECODE_WHITELIST */ +static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph) +{ + /* This should never happen, but it's probably better to have None in Python + * than a NULL-wrapping Depsgraph py struct. */ + BLI_assert(depsgraph != NULL); + if (depsgraph == NULL) { + Py_RETURN_NONE; + } + + struct PointerRNA depsgraph_ptr; + RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr); + return pyrna_struct_CreatePyObject(&depsgraph_ptr); +} + +/* Adds a variable 'depsgraph' to the driver variables. This can then be used to obtain evaluated + * datablocks, and the current view layer and scene. See T75553. */ +static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars, + struct Depsgraph *depsgraph) +{ + PyObject *py_depsgraph = bpy_pydriver_depsgraph_as_pyobject(depsgraph); + const char *depsgraph_variable_name = "depsgraph"; + + if (PyDict_SetItemString(driver_vars, depsgraph_variable_name, py_depsgraph) == -1) { + fprintf(stderr, + "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", + depsgraph_variable_name); + PyErr_Print(); + PyErr_Clear(); + } +} + /* This evals py driver expressions, 'expr' is a Python expression that * should evaluate to a float number, which is returned. * @@ -396,7 +430,7 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, - const float evaltime) + const AnimationEvalContext *anim_eval_context) { PyObject *driver_vars = NULL; PyObject *retval = NULL; @@ -456,7 +490,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, } /* update global namespace */ - bpy_pydriver_namespace_update_frame(evaltime); + bpy_pydriver_namespace_update_frame(anim_eval_context->eval_time); if (driver_orig->flag & DRIVER_FLAG_USE_SELF) { bpy_pydriver_namespace_update_self(anim_rna); @@ -589,6 +623,8 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, } #endif /* USE_BYTECODE_WHITELIST */ + bpy_pydriver_namespace_add_depsgraph(driver_vars, anim_eval_context->depsgraph); + #if 0 /* slow, with this can avoid all Py_CompileString above. */ /* execute expression to get a value */ retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index 1c84e95672f..8aba2ae8598 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -36,6 +36,7 @@ #include "ED_keyframing.h" #include "BKE_anim_data.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_fcurve.h" #include "BKE_global.h" @@ -332,7 +333,20 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb &options) == -1) { return NULL; } - else if (self->ptr.type == &RNA_NlaStrip) { + + /* This assumes that keyframes are only added on original data & using the active depsgraph. If + * it turns out to be necessary for some reason to insert keyframes on evaluated objects, we can + * revisit this and add an explicit `depsgraph` keyword argument to the function call. + * + * It is unlikely that driver code (which is the reason this depsgraph pointer is obtained) will + * be executed from this function call, as this only happens when `options` has + * `INSERTKEY_DRIVER`, which is not exposed to Python. */ + bContext *C = BPy_GetContext(); + struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + cfra); + + if (self->ptr.type == &RNA_NlaStrip) { /* Handle special properties for NLA Strips, whose F-Curves are stored on the * strips themselves. These are stored separately or else the properties will * not have any effect. @@ -355,8 +369,8 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb if (prop) { NlaStrip *strip = ptr.data; FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index); - - result = insert_keyframe_direct(&reports, ptr, prop, fcu, cfra, keytype, NULL, options); + result = insert_keyframe_direct( + &reports, ptr, prop, fcu, &anim_eval_context, keytype, NULL, options); } else { BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full); @@ -384,7 +398,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb group_name, path_full, index, - cfra, + &anim_eval_context, keytype, NULL, options) != 0); diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 77a60854616..51eb290b0b8 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -60,6 +60,7 @@ struct bNodeTree; #define RE_USE_SHADING_NODES_CUSTOM 64 #define RE_USE_SPHERICAL_STEREO 128 #define RE_USE_STEREO_VIEWPORT 256 +#define RE_USE_GPU_CONTEXT 512 /* RenderEngine.flag */ #define RE_ENGINE_ANIMATION 1 diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 5391775cab8..633b9324d9f 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -624,10 +624,6 @@ void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe) return; } -#ifdef WITH_PYTHON - BPy_BEGIN_ALLOW_THREADS; -#endif - Render *re = engine->re; double cfra = (double)frame + (double)subframe; @@ -636,10 +632,6 @@ void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe) BKE_scene_graph_update_for_newframe(engine->depsgraph, re->main); BKE_scene_camera_switch_update(re->scene); - -#ifdef WITH_PYTHON - BPy_END_ALLOW_THREADS; -#endif } /* Bake */ @@ -871,8 +863,16 @@ int RE_engine_render(Render *re, int do_all) re->draw_lock(re->dlh, 0); } + if (engine->type->flag & RE_USE_GPU_CONTEXT) { + DRW_render_context_enable(engine->re); + } + type->render(engine, engine->depsgraph); + if (engine->type->flag & RE_USE_GPU_CONTEXT) { + DRW_render_context_disable(engine->re); + } + /* Grease pencil render over previous render result. * * NOTE: External engine might have been requested to free its diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index b335862abe0..ade80898131 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2493,7 +2493,9 @@ void RE_RenderAnim(Render *re, { float ctime = BKE_scene_frame_get(scene); AnimData *adt = BKE_animdata_from_id(&scene->id); - BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, ADT_RECALC_ALL, false); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + re->pipeline_depsgraph, ctime); + BKE_animsys_evaluate_animdata(&scene->id, adt, &anim_eval_context, ADT_RECALC_ALL, false); } render_update_depsgraph(re); diff --git a/source/blender/simulation/intern/particle_allocator.cc b/source/blender/simulation/intern/particle_allocator.cc index b65c0197c76..eb1e998e63a 100644 --- a/source/blender/simulation/intern/particle_allocator.cc +++ b/source/blender/simulation/intern/particle_allocator.cc @@ -21,7 +21,7 @@ namespace blender::sim { AttributesAllocator::~AttributesAllocator() { for (std::unique_ptr<AttributesBlock> &block : allocated_blocks_) { - for (uint i : attributes_info_.index_range()) { + for (int i : attributes_info_.index_range()) { const fn::CPPType &type = attributes_info_.type_of(i); type.destruct_n(block->buffers[i], block->size); MEM_freeN(block->buffers[i]); @@ -29,13 +29,13 @@ AttributesAllocator::~AttributesAllocator() } } -fn::MutableAttributesRef AttributesAllocator::allocate_uninitialized(uint size) +fn::MutableAttributesRef AttributesAllocator::allocate_uninitialized(int size) { std::unique_ptr<AttributesBlock> block = std::make_unique<AttributesBlock>(); block->buffers = Array<void *>(attributes_info_.size(), nullptr); block->size = size; - for (uint i : attributes_info_.index_range()) { + for (int i : attributes_info_.index_range()) { const fn::CPPType &type = attributes_info_.type_of(i); void *buffer = MEM_mallocN_aligned(size * type.size(), type.alignment(), AT); block->buffers[i] = buffer; @@ -53,17 +53,17 @@ fn::MutableAttributesRef AttributesAllocator::allocate_uninitialized(uint size) return attributes; } -fn::MutableAttributesRef ParticleAllocator::allocate(uint size) +fn::MutableAttributesRef ParticleAllocator::allocate(int size) { const fn::AttributesInfo &info = attributes_allocator_.attributes_info(); fn::MutableAttributesRef attributes = attributes_allocator_.allocate_uninitialized(size); - for (uint i : info.index_range()) { + for (int i : info.index_range()) { const fn::CPPType &type = info.type_of(i); StringRef name = info.name_of(i); if (name == "ID") { - uint start_id = next_id_.fetch_add(size); + int start_id = next_id_.fetch_add(size); MutableSpan<int> ids = attributes.get<int>("ID"); - for (uint pindex : IndexRange(size)) { + for (int pindex : IndexRange(size)) { ids[pindex] = start_id + pindex; } } diff --git a/source/blender/simulation/intern/particle_allocator.hh b/source/blender/simulation/intern/particle_allocator.hh index f854413c9aa..1e7578a75ed 100644 --- a/source/blender/simulation/intern/particle_allocator.hh +++ b/source/blender/simulation/intern/particle_allocator.hh @@ -31,13 +31,13 @@ class AttributesAllocator : NonCopyable, NonMovable { private: struct AttributesBlock { Array<void *> buffers; - uint size; + int size; }; const fn::AttributesInfo &attributes_info_; Vector<std::unique_ptr<AttributesBlock>> allocated_blocks_; Vector<fn::MutableAttributesRef> allocated_attributes_; - uint total_allocated_ = 0; + int total_allocated_ = 0; std::mutex mutex_; public: @@ -53,7 +53,7 @@ class AttributesAllocator : NonCopyable, NonMovable { return allocated_attributes_; } - uint total_allocated() const + int total_allocated() const { return total_allocated_; } @@ -63,31 +63,36 @@ class AttributesAllocator : NonCopyable, NonMovable { return attributes_info_; } - fn::MutableAttributesRef allocate_uninitialized(uint size); + fn::MutableAttributesRef allocate_uninitialized(int size); }; class ParticleAllocator : NonCopyable, NonMovable { private: AttributesAllocator attributes_allocator_; - std::atomic<uint> next_id_; + std::atomic<int> next_id_; public: - ParticleAllocator(const fn::AttributesInfo &attributes_info, uint next_id) + ParticleAllocator(const fn::AttributesInfo &attributes_info, int next_id) : attributes_allocator_(attributes_info), next_id_(next_id) { } + const fn::AttributesInfo &attributes_info() const + { + return attributes_allocator_.attributes_info(); + } + Span<fn::MutableAttributesRef> get_allocations() const { return attributes_allocator_.get_allocations(); } - uint total_allocated() const + int total_allocated() const { return attributes_allocator_.total_allocated(); } - fn::MutableAttributesRef allocate(uint size); + fn::MutableAttributesRef allocate(int size); }; } // namespace blender::sim diff --git a/source/blender/simulation/intern/particle_function.cc b/source/blender/simulation/intern/particle_function.cc index 3788fd17e36..e0de68d9b29 100644 --- a/source/blender/simulation/intern/particle_function.cc +++ b/source/blender/simulation/intern/particle_function.cc @@ -29,9 +29,9 @@ ParticleFunction::ParticleFunction(const fn::MultiFunction *global_fn, per_particle_inputs_(per_particle_inputs), output_is_global_(output_is_global) { - for (uint i : output_is_global_.index_range()) { + for (int i : output_is_global_.index_range()) { if (output_is_global_[i]) { - uint param_index = global_inputs_.size() + global_output_indices_.size(); + int param_index = global_inputs_.size() + global_output_indices_.size(); fn::MFParamType param_type = global_fn_->param_type(param_index); BLI_assert(param_type.is_output()); output_types_.append(param_type.data_type()); @@ -39,7 +39,7 @@ ParticleFunction::ParticleFunction(const fn::MultiFunction *global_fn, global_output_indices_.append(i); } else { - uint param_index = per_particle_inputs_.size() + per_particle_output_indices_.size(); + int param_index = per_particle_inputs_.size() + per_particle_output_indices_.size(); fn::MFParamType param_type = per_particle_fn_->param_type(param_index); BLI_assert(param_type.is_output()); output_types_.append(param_type.data_type()); @@ -60,7 +60,7 @@ ParticleFunctionEvaluator::ParticleFunctionEvaluator( ParticleFunctionEvaluator::~ParticleFunctionEvaluator() { - for (uint output_index : outputs_.index_range()) { + for (int output_index : outputs_.index_range()) { void *buffer = outputs_[output_index]; fn::MFDataType data_type = particle_fn_.output_types_[output_index]; BLI_assert(data_type.is_single()); /* For now. */ @@ -83,7 +83,7 @@ void ParticleFunctionEvaluator::compute() is_computed_ = true; } -fn::GVSpan ParticleFunctionEvaluator::get(uint output_index, StringRef expected_name) const +fn::GVSpan ParticleFunctionEvaluator::get(int output_index, StringRef expected_name) const { #ifdef DEBUG StringRef real_name = particle_fn_.output_names_[output_index]; @@ -115,7 +115,7 @@ void ParticleFunctionEvaluator::compute_globals() } /* Add output parameters. */ - for (uint output_index : particle_fn_.global_output_indices_) { + for (int output_index : particle_fn_.global_output_indices_) { fn::MFDataType data_type = particle_fn_.output_types_[output_index]; BLI_assert(data_type.is_single()); /* For now. */ @@ -142,7 +142,7 @@ void ParticleFunctionEvaluator::compute_per_particle() } /* Add output parameters. */ - for (uint output_index : particle_fn_.per_particle_output_indices_) { + for (int output_index : particle_fn_.per_particle_output_indices_) { fn::MFDataType data_type = particle_fn_.output_types_[output_index]; BLI_assert(data_type.is_single()); /* For now. */ diff --git a/source/blender/simulation/intern/particle_function.hh b/source/blender/simulation/intern/particle_function.hh index abed9063bae..bbb40efb388 100644 --- a/source/blender/simulation/intern/particle_function.hh +++ b/source/blender/simulation/intern/particle_function.hh @@ -41,8 +41,8 @@ class ParticleFunction { Array<const ParticleFunctionInput *> global_inputs_; Array<const ParticleFunctionInput *> per_particle_inputs_; Array<bool> output_is_global_; - Vector<uint> global_output_indices_; - Vector<uint> per_particle_output_indices_; + Vector<int> global_output_indices_; + Vector<int> per_particle_output_indices_; Vector<fn::MFDataType> output_types_; Vector<StringRefNull> output_names_; @@ -73,9 +73,9 @@ class ParticleFunctionEvaluator { ~ParticleFunctionEvaluator(); void compute(); - fn::GVSpan get(uint output_index, StringRef expected_name) const; + fn::GVSpan get(int output_index, StringRef expected_name) const; - template<typename T> fn::VSpan<T> get(uint output_index, StringRef expected_name) const + template<typename T> fn::VSpan<T> get(int output_index, StringRef expected_name) const { return this->get(output_index, expected_name).typed<T>(); } diff --git a/source/blender/simulation/intern/simulation_collect_influences.cc b/source/blender/simulation/intern/simulation_collect_influences.cc index 98b055802c9..d4161b06a00 100644 --- a/source/blender/simulation/intern/simulation_collect_influences.cc +++ b/source/blender/simulation/intern/simulation_collect_influences.cc @@ -53,7 +53,7 @@ static Span<const nodes::DNode *> get_particle_simulation_nodes(const nodes::Der static std::optional<Array<std::string>> compute_global_string_inputs( nodes::MFNetworkTreeMap &network_map, Span<const fn::MFInputSocket *> sockets) { - uint amount = sockets.size(); + int amount = sockets.size(); if (amount == 0) { return Array<std::string>(); } @@ -67,7 +67,7 @@ static std::optional<Array<std::string>> compute_global_string_inputs( fn::MFParamsBuilder params{network_fn, 1}; Array<std::string> strings(amount, NoInitialization()); - for (uint i : IndexRange(amount)) { + for (int i : IndexRange(amount)) { params.add_uninitialized_single_output( fn::GMutableSpan(fn::CPPType::get<std::string>(), strings.data() + i, 1)); } @@ -101,7 +101,7 @@ static void find_and_deduplicate_particle_attribute_nodes(nodes::MFNetworkTreeMa Map<std::pair<std::string, fn::MFDataType>, Vector<fn::MFNode *>> attribute_nodes_by_name_and_type; - for (uint i : attribute_names->index_range()) { + for (int i : attribute_names->index_range()) { attribute_nodes_by_name_and_type .lookup_or_add_default( {(*attribute_names)[i], name_sockets[i]->node().output(0).data_type()}) @@ -207,7 +207,7 @@ class ParticleFunctionForce : public ParticleForce { evaluator.compute(); fn::VSpan<float3> forces = evaluator.get<float3>(0, "Force"); - for (uint i : mask) { + for (int64_t i : mask) { r_combined_force[i] += forces[i]; } } @@ -273,15 +273,17 @@ class MyBasicEmitter : public ParticleEmitter { } fn::MutableAttributesRef attributes = allocator->allocate(10); - RandomNumberGenerator rng{(uint)context.simulation_time_interval().start() ^ - DefaultHash<std::string>{}(name_)}; + RandomNumberGenerator rng{(uint32_t)context.simulation_time_interval().start() ^ + (uint32_t)DefaultHash<std::string>{}(name_)}; MutableSpan<float3> positions = attributes.get<float3>("Position"); MutableSpan<float3> velocities = attributes.get<float3>("Velocity"); + MutableSpan<float> birth_times = attributes.get<float>("Birth Time"); - for (uint i : IndexRange(attributes.size())) { + for (int i : IndexRange(attributes.size())) { positions[i] = rng.get_unit_float3(); velocities[i] = rng.get_unit_float3(); + birth_times[i] = context.simulation_time_interval().start(); } } }; @@ -307,6 +309,9 @@ static void prepare_particle_attribute_builders(nodes::MFNetworkTreeMap &network builder.add<float3>("Position", {0, 0, 0}); builder.add<float3>("Velocity", {0, 0, 0}); builder.add<int>("ID", 0); + /* TODO: Use bool property, but need to add CD_PROP_BOOL first. */ + builder.add<int>("Dead", 0); + builder.add<float>("Birth Time", 0.0f); r_influences.particle_attributes_builder.add_new(std::move(name), &builder); } } diff --git a/source/blender/simulation/intern/simulation_solver.cc b/source/blender/simulation/intern/simulation_solver.cc index 310261f6c95..f542d6ab2c8 100644 --- a/source/blender/simulation/intern/simulation_solver.cc +++ b/source/blender/simulation/intern/simulation_solver.cc @@ -63,14 +63,14 @@ static const fn::CPPType &custom_to_cpp_data_type(CustomDataType type) class CustomDataAttributesRef { private: Array<void *> buffers_; - uint size_; + int64_t size_; const fn::AttributesInfo &info_; public: - CustomDataAttributesRef(CustomData &custom_data, uint size, const fn::AttributesInfo &info) + CustomDataAttributesRef(CustomData &custom_data, int64_t size, const fn::AttributesInfo &info) : buffers_(info.size(), nullptr), size_(size), info_(info) { - for (uint attribute_index : info.index_range()) { + for (int attribute_index : info.index_range()) { StringRefNull name = info.name_of(attribute_index); const fn::CPPType &cpp_type = info.type_of(attribute_index); CustomDataType custom_type = cpp_to_custom_data_type(cpp_type); @@ -108,7 +108,7 @@ static void ensure_attributes_exist(ParticleSimulationState *state, const fn::At } } while (found_layer_to_remove); - for (uint attribute_index : info.index_range()) { + for (int attribute_index : info.index_range()) { StringRefNull attribute_name = info.name_of(attribute_index); const fn::CPPType &cpp_type = info.type_of(attribute_index); CustomDataType custom_type = cpp_to_custom_data_type(cpp_type); @@ -120,12 +120,129 @@ static void ensure_attributes_exist(ParticleSimulationState *state, const fn::At nullptr, state->tot_particles, attribute_name.c_str()); - cpp_type.fill_uninitialized( - info.default_of(attribute_index), data, (uint)state->tot_particles); + cpp_type.fill_uninitialized(info.default_of(attribute_index), data, state->tot_particles); } } } +BLI_NOINLINE static void simulate_existing_particles(SimulationSolveContext &solve_context, + ParticleSimulationState &state, + const fn::AttributesInfo &attributes_info) +{ + CustomDataAttributesRef custom_data_attributes{ + state.attributes, state.tot_particles, attributes_info}; + fn::MutableAttributesRef attributes = custom_data_attributes; + + Array<float3> force_vectors{state.tot_particles, {0, 0, 0}}; + const Vector<const ParticleForce *> *forces = + solve_context.influences().particle_forces.lookup_ptr(state.head.name); + + if (forces != nullptr) { + ParticleChunkContext particle_chunk_context{IndexMask(state.tot_particles), attributes}; + ParticleForceContext particle_force_context{ + solve_context, particle_chunk_context, force_vectors}; + + for (const ParticleForce *force : *forces) { + force->add_force(particle_force_context); + } + } + + MutableSpan<float3> positions = attributes.get<float3>("Position"); + MutableSpan<float3> velocities = attributes.get<float3>("Velocity"); + MutableSpan<float> birth_times = attributes.get<float>("Birth Time"); + MutableSpan<int> dead_states = attributes.get<int>("Dead"); + float end_time = solve_context.solve_interval().end(); + float time_step = solve_context.solve_interval().duration(); + for (int i : positions.index_range()) { + velocities[i] += force_vectors[i] * time_step; + positions[i] += velocities[i] * time_step; + + if (end_time - birth_times[i] > 2) { + dead_states[i] = true; + } + } +} + +BLI_NOINLINE static void run_emitters(SimulationSolveContext &solve_context, + ParticleAllocators &particle_allocators) +{ + for (const ParticleEmitter *emitter : solve_context.influences().particle_emitters) { + ParticleEmitterContext emitter_context{ + solve_context, particle_allocators, solve_context.solve_interval()}; + emitter->emit(emitter_context); + } +} + +BLI_NOINLINE static int count_particles_after_time_step(ParticleSimulationState &state, + ParticleAllocator &allocator) +{ + CustomDataAttributesRef custom_data_attributes{ + state.attributes, state.tot_particles, allocator.attributes_info()}; + fn::MutableAttributesRef attributes = custom_data_attributes; + int new_particle_amount = attributes.get<int>("Dead").count(0); + + for (fn::MutableAttributesRef emitted_attributes : allocator.get_allocations()) { + new_particle_amount += emitted_attributes.get<int>("Dead").count(0); + } + + return new_particle_amount; +} + +BLI_NOINLINE static void remove_dead_and_add_new_particles(ParticleSimulationState &state, + ParticleAllocator &allocator) +{ + const int new_particle_amount = count_particles_after_time_step(state, allocator); + + CustomDataAttributesRef custom_data_attributes{ + state.attributes, state.tot_particles, allocator.attributes_info()}; + + Vector<fn::MutableAttributesRef> particle_sources; + particle_sources.append(custom_data_attributes); + particle_sources.extend(allocator.get_allocations()); + + CustomDataLayer *dead_layer = nullptr; + + for (CustomDataLayer &layer : MutableSpan(state.attributes.layers, state.attributes.totlayer)) { + StringRefNull name = layer.name; + if (name == "Dead") { + dead_layer = &layer; + continue; + } + const fn::CPPType &cpp_type = custom_to_cpp_data_type((CustomDataType)layer.type); + fn::GMutableSpan new_buffer{ + cpp_type, + MEM_mallocN_aligned(new_particle_amount * cpp_type.size(), cpp_type.alignment(), AT), + new_particle_amount}; + + int current = 0; + for (fn::MutableAttributesRef attributes : particle_sources) { + Span<int> dead_states = attributes.get<int>("Dead"); + fn::GSpan source_buffer = attributes.get(name); + BLI_assert(source_buffer.type() == cpp_type); + for (int i : attributes.index_range()) { + if (dead_states[i] == 0) { + cpp_type.copy_to_uninitialized(source_buffer[i], new_buffer[current]); + current++; + } + } + } + + if (layer.data != nullptr) { + MEM_freeN(layer.data); + } + layer.data = new_buffer.buffer(); + } + + BLI_assert(dead_layer != nullptr); + if (dead_layer->data != nullptr) { + MEM_freeN(dead_layer->data); + } + dead_layer->data = MEM_callocN(sizeof(int) * new_particle_amount, AT); + + state.tot_particles = new_particle_amount; + state.next_particle_id += allocator.total_allocated(); +} + void initialize_simulation_states(Simulation &simulation, Depsgraph &UNUSED(depsgraph), const SimulationInfluences &UNUSED(influences)) @@ -138,89 +255,47 @@ void solve_simulation_time_step(Simulation &simulation, const SimulationInfluences &influences, float time_step) { - SimulationSolveContext solve_context{simulation, depsgraph, influences}; + SimulationSolveContext solve_context{ + simulation, + depsgraph, + influences, + TimeInterval(simulation.current_simulation_time, time_step)}; TimeInterval simulation_time_interval{simulation.current_simulation_time, time_step}; + Vector<SimulationState *> simulation_states{simulation.states}; + Vector<ParticleSimulationState *> particle_simulation_states; + for (SimulationState *state : simulation_states) { + if (state->type == SIM_STATE_TYPE_PARTICLES) { + particle_simulation_states.append((ParticleSimulationState *)state); + } + } + Map<std::string, std::unique_ptr<fn::AttributesInfo>> attribute_infos; - Map<std::string, std::unique_ptr<ParticleAllocator>> particle_allocators; - LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation.states) { + Map<std::string, std::unique_ptr<ParticleAllocator>> particle_allocators_map; + for (ParticleSimulationState *state : particle_simulation_states) { const fn::AttributesInfoBuilder &builder = *influences.particle_attributes_builder.lookup_as( state->head.name); auto info = std::make_unique<fn::AttributesInfo>(builder); ensure_attributes_exist(state, *info); - particle_allocators.add_new( + particle_allocators_map.add_new( state->head.name, std::make_unique<ParticleAllocator>(*info, state->next_particle_id)); attribute_infos.add_new(state->head.name, std::move(info)); } - LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation.states) { - const fn::AttributesInfo &attributes_info = *attribute_infos.lookup_as(state->head.name); - CustomDataAttributesRef custom_data_attributes{ - state->attributes, (uint)state->tot_particles, attributes_info}; - fn::MutableAttributesRef attributes = custom_data_attributes; - - MutableSpan<float3> positions = attributes.get<float3>("Position"); - MutableSpan<float3> velocities = attributes.get<float3>("Velocity"); + ParticleAllocators particle_allocators{particle_allocators_map}; - Array<float3> force_vectors{(uint)state->tot_particles, {0, 0, 0}}; - const Vector<const ParticleForce *> *forces = influences.particle_forces.lookup_ptr( - state->head.name); - - if (forces != nullptr) { - ParticleChunkContext particle_chunk_context{IndexMask((uint)state->tot_particles), - attributes}; - ParticleForceContext particle_force_context{ - solve_context, particle_chunk_context, force_vectors}; - - for (const ParticleForce *force : *forces) { - force->add_force(particle_force_context); - } - } - - for (uint i : positions.index_range()) { - velocities[i] += force_vectors[i] * time_step; - positions[i] += velocities[i] * time_step; - } - } - - for (const ParticleEmitter *emitter : influences.particle_emitters) { - ParticleEmitterContext emitter_context{ - solve_context, particle_allocators, simulation_time_interval}; - emitter->emit(emitter_context); + for (ParticleSimulationState *state : particle_simulation_states) { + const fn::AttributesInfo &attributes_info = *attribute_infos.lookup_as(state->head.name); + simulate_existing_particles(solve_context, *state, attributes_info); } - LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation.states) { - const fn::AttributesInfo &attributes_info = *attribute_infos.lookup_as(state->head.name); - ParticleAllocator &allocator = *particle_allocators.lookup_as(state->head.name); - - const uint emitted_particle_amount = allocator.total_allocated(); - const uint old_particle_amount = state->tot_particles; - const uint new_particle_amount = old_particle_amount + emitted_particle_amount; - - CustomData_realloc(&state->attributes, new_particle_amount); - - CustomDataAttributesRef custom_data_attributes{ - state->attributes, new_particle_amount, attributes_info}; - fn::MutableAttributesRef attributes = custom_data_attributes; - - uint offset = old_particle_amount; - for (fn::MutableAttributesRef emitted_attributes : allocator.get_allocations()) { - fn::MutableAttributesRef dst_attributes = attributes.slice( - IndexRange(offset, emitted_attributes.size())); - for (uint attribute_index : attributes.info().index_range()) { - fn::GMutableSpan emitted_data = emitted_attributes.get(attribute_index); - fn::GMutableSpan dst = dst_attributes.get(attribute_index); - const fn::CPPType &type = dst.type(); - type.copy_to_uninitialized_n( - emitted_data.buffer(), dst.buffer(), emitted_attributes.size()); - } - offset += emitted_attributes.size(); - } + run_emitters(solve_context, particle_allocators); - state->tot_particles = new_particle_amount; - state->next_particle_id += emitted_particle_amount; + for (ParticleSimulationState *state : particle_simulation_states) { + ParticleAllocator &allocator = *particle_allocators.try_get_allocator(state->head.name); + remove_dead_and_add_new_particles(*state, allocator); } simulation.current_simulation_time = simulation_time_interval.end(); diff --git a/source/blender/simulation/intern/simulation_solver.hh b/source/blender/simulation/intern/simulation_solver.hh index 7b37ed0583d..b5e42b53846 100644 --- a/source/blender/simulation/intern/simulation_solver.hh +++ b/source/blender/simulation/intern/simulation_solver.hh @@ -57,14 +57,51 @@ class SimulationSolveContext { Simulation &simulation_; Depsgraph &depsgraph_; const SimulationInfluences &influences_; + TimeInterval solve_interval_; public: SimulationSolveContext(Simulation &simulation, Depsgraph &depsgraph, - const SimulationInfluences &influences) - : simulation_(simulation), depsgraph_(depsgraph), influences_(influences) + const SimulationInfluences &influences, + TimeInterval solve_interval) + : simulation_(simulation), + depsgraph_(depsgraph), + influences_(influences), + solve_interval_(solve_interval) { } + + TimeInterval solve_interval() const + { + return solve_interval_; + } + + const SimulationInfluences &influences() const + { + return influences_; + } +}; + +class ParticleAllocators { + private: + Map<std::string, std::unique_ptr<ParticleAllocator>> &allocators_; + + public: + ParticleAllocators(Map<std::string, std::unique_ptr<ParticleAllocator>> &allocators) + : allocators_(allocators) + { + } + + ParticleAllocator *try_get_allocator(StringRef particle_simulation_name) + { + auto *ptr = allocators_.lookup_ptr_as(particle_simulation_name); + if (ptr != nullptr) { + return ptr->get(); + } + else { + return nullptr; + } + } }; class ParticleChunkContext { @@ -97,12 +134,12 @@ class ParticleChunkContext { class ParticleEmitterContext { private: SimulationSolveContext &solve_context_; - Map<std::string, std::unique_ptr<ParticleAllocator>> &particle_allocators_; + ParticleAllocators &particle_allocators_; TimeInterval simulation_time_interval_; public: ParticleEmitterContext(SimulationSolveContext &solve_context, - Map<std::string, std::unique_ptr<ParticleAllocator>> &particle_allocators, + ParticleAllocators &particle_allocators, TimeInterval simulation_time_interval) : solve_context_(solve_context), particle_allocators_(particle_allocators), @@ -112,13 +149,7 @@ class ParticleEmitterContext { ParticleAllocator *try_get_particle_allocator(StringRef particle_simulation_name) { - auto *ptr = particle_allocators_.lookup_ptr_as(particle_simulation_name); - if (ptr != nullptr) { - return ptr->get(); - } - else { - return nullptr; - } + return particle_allocators_.try_get_allocator(particle_simulation_name); } TimeInterval simulation_time_interval() const diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index f0cd1add48b..d1f65b6271b 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2799,7 +2799,9 @@ static void radial_control_cancel(bContext *C, wmOperator *op) * new value is displayed in sliders/numfields */ WM_event_add_notifier(C, NC_WINDOW, NULL); - GPU_texture_free(rc->texture); + if (rc->texture != NULL) { + GPU_texture_free(rc->texture); + } MEM_freeN(rc); } diff --git a/tests/gtests/blenlib/BLI_array_test.cc b/tests/gtests/blenlib/BLI_array_test.cc index 3ff5baf1d94..c01ba26ffd7 100644 --- a/tests/gtests/blenlib/BLI_array_test.cc +++ b/tests/gtests/blenlib/BLI_array_test.cc @@ -9,21 +9,21 @@ namespace blender { TEST(array, DefaultConstructor) { Array<int> array; - EXPECT_EQ(array.size(), 0u); + EXPECT_EQ(array.size(), 0); EXPECT_TRUE(array.is_empty()); } TEST(array, SizeConstructor) { Array<int> array(5); - EXPECT_EQ(array.size(), 5u); + EXPECT_EQ(array.size(), 5); EXPECT_FALSE(array.is_empty()); } TEST(array, FillConstructor) { Array<int> array(5, 8); - EXPECT_EQ(array.size(), 5u); + EXPECT_EQ(array.size(), 5); EXPECT_EQ(array[0], 8); EXPECT_EQ(array[1], 8); EXPECT_EQ(array[2], 8); @@ -34,7 +34,7 @@ TEST(array, FillConstructor) TEST(array, InitializerListConstructor) { Array<int> array = {4, 5, 6, 7}; - EXPECT_EQ(array.size(), 4u); + EXPECT_EQ(array.size(), 4); EXPECT_EQ(array[0], 4); EXPECT_EQ(array[1], 5); EXPECT_EQ(array[2], 6); @@ -46,7 +46,7 @@ TEST(array, SpanConstructor) int stackarray[4] = {6, 7, 8, 9}; Span<int> span(stackarray, ARRAY_SIZE(stackarray)); Array<int> array(span); - EXPECT_EQ(array.size(), 4u); + EXPECT_EQ(array.size(), 4); EXPECT_EQ(array[0], 6); EXPECT_EQ(array[1], 7); EXPECT_EQ(array[2], 8); @@ -58,8 +58,8 @@ TEST(array, CopyConstructor) Array<int> array = {5, 6, 7, 8}; Array<int> new_array(array); - EXPECT_EQ(array.size(), 4u); - EXPECT_EQ(new_array.size(), 4u); + EXPECT_EQ(array.size(), 4); + EXPECT_EQ(new_array.size(), 4); EXPECT_NE(array.data(), new_array.data()); EXPECT_EQ(new_array[0], 5); EXPECT_EQ(new_array[1], 6); @@ -72,8 +72,8 @@ TEST(array, MoveConstructor) Array<int> array = {5, 6, 7, 8}; Array<int> new_array(std::move(array)); - EXPECT_EQ(array.size(), 0u); - EXPECT_EQ(new_array.size(), 4u); + EXPECT_EQ(array.size(), 0); + EXPECT_EQ(new_array.size(), 4); EXPECT_EQ(new_array[0], 5); EXPECT_EQ(new_array[1], 6); EXPECT_EQ(new_array[2], 7); @@ -84,10 +84,10 @@ TEST(array, CopyAssignment) { Array<int> array = {1, 2, 3}; Array<int> new_array = {4}; - EXPECT_EQ(new_array.size(), 1u); + EXPECT_EQ(new_array.size(), 1); new_array = array; - EXPECT_EQ(new_array.size(), 3u); - EXPECT_EQ(array.size(), 3u); + EXPECT_EQ(new_array.size(), 3); + EXPECT_EQ(array.size(), 3); EXPECT_NE(array.data(), new_array.data()); EXPECT_EQ(new_array[0], 1); EXPECT_EQ(new_array[1], 2); @@ -98,10 +98,10 @@ TEST(array, MoveAssignment) { Array<int> array = {1, 2, 3}; Array<int> new_array = {4}; - EXPECT_EQ(new_array.size(), 1u); + EXPECT_EQ(new_array.size(), 1); new_array = std::move(array); - EXPECT_EQ(new_array.size(), 3u); - EXPECT_EQ(array.size(), 0u); + EXPECT_EQ(new_array.size(), 3); + EXPECT_EQ(array.size(), 0); EXPECT_EQ(new_array[0], 1); EXPECT_EQ(new_array[1], 2); EXPECT_EQ(new_array[2], 3); @@ -144,7 +144,7 @@ TEST(array, NoInitializationSizeConstructor) memset(buffer, 100, sizeof(MyArray)); /* Doing this to avoid some compiler optimization. */ - for (uint i : IndexRange(sizeof(MyArray))) { + for (int64_t i : IndexRange(sizeof(MyArray))) { EXPECT_EQ(((char *)buffer.ptr())[i], 100); } @@ -161,4 +161,16 @@ TEST(array, NoInitializationSizeConstructor) } } +TEST(array, Fill) +{ + Array<int> array(5); + array.fill(3); + EXPECT_EQ(array.size(), 5u); + EXPECT_EQ(array[0], 3); + EXPECT_EQ(array[1], 3); + EXPECT_EQ(array[2], 3); + EXPECT_EQ(array[3], 3); + EXPECT_EQ(array[4], 3); +} + } // namespace blender diff --git a/tests/gtests/blenlib/BLI_disjoint_set_test.cc b/tests/gtests/blenlib/BLI_disjoint_set_test.cc index 30503954c62..22663b936d9 100644 --- a/tests/gtests/blenlib/BLI_disjoint_set_test.cc +++ b/tests/gtests/blenlib/BLI_disjoint_set_test.cc @@ -13,7 +13,7 @@ TEST(disjoint_set, Test) EXPECT_FALSE(disjoint_set.in_same_set(1, 2)); EXPECT_FALSE(disjoint_set.in_same_set(5, 3)); EXPECT_TRUE(disjoint_set.in_same_set(2, 2)); - EXPECT_EQ(disjoint_set.find_root(3), 3u); + EXPECT_EQ(disjoint_set.find_root(3), 3); disjoint_set.join(1, 2); diff --git a/tests/gtests/blenlib/BLI_index_mask_test.cc b/tests/gtests/blenlib/BLI_index_mask_test.cc index 6d9b7c70ab2..bce467cadd9 100644 --- a/tests/gtests/blenlib/BLI_index_mask_test.cc +++ b/tests/gtests/blenlib/BLI_index_mask_test.cc @@ -34,7 +34,7 @@ TEST(index_mask, RangeConstructor) EXPECT_TRUE(mask.is_range()); EXPECT_EQ(mask.as_range().first(), 3); EXPECT_EQ(mask.as_range().last(), 7); - Span<uint> indices = mask.indices(); + Span<int64_t> indices = mask.indices(); EXPECT_EQ(indices[0], 3); EXPECT_EQ(indices[1], 4); EXPECT_EQ(indices[2], 5); diff --git a/tests/gtests/blenlib/BLI_index_range_test.cc b/tests/gtests/blenlib/BLI_index_range_test.cc index 0f4fb7ef03b..1c4d4a1a1f3 100644 --- a/tests/gtests/blenlib/BLI_index_range_test.cc +++ b/tests/gtests/blenlib/BLI_index_range_test.cc @@ -10,42 +10,42 @@ namespace blender { TEST(index_range, DefaultConstructor) { IndexRange range; - EXPECT_EQ(range.size(), 0u); + EXPECT_EQ(range.size(), 0); - Vector<uint> vector; - for (uint value : range) { + Vector<int64_t> vector; + for (int64_t value : range) { vector.append(value); } - EXPECT_EQ(vector.size(), 0u); + EXPECT_EQ(vector.size(), 0); } TEST(index_range, SingleElementRange) { IndexRange range(4, 1); - EXPECT_EQ(range.size(), 1u); - EXPECT_EQ(*range.begin(), 4u); + EXPECT_EQ(range.size(), 1); + EXPECT_EQ(*range.begin(), 4); - Vector<uint> vector; - for (uint value : range) { + Vector<int64_t> vector; + for (int64_t value : range) { vector.append(value); } - EXPECT_EQ(vector.size(), 1u); - EXPECT_EQ(vector[0], 4u); + EXPECT_EQ(vector.size(), 1); + EXPECT_EQ(vector[0], 4); } TEST(index_range, MultipleElementRange) { IndexRange range(6, 4); - EXPECT_EQ(range.size(), 4u); + EXPECT_EQ(range.size(), 4); - Vector<uint> vector; - for (uint value : range) { + Vector<int64_t> vector; + for (int64_t value : range) { vector.append(value); } - EXPECT_EQ(vector.size(), 4u); - for (uint i = 0; i < 4; i++) { + EXPECT_EQ(vector.size(), 4); + for (int i = 0; i < 4; i++) { EXPECT_EQ(vector[i], i + 6); } } @@ -53,28 +53,28 @@ TEST(index_range, MultipleElementRange) TEST(index_range, SubscriptOperator) { IndexRange range(5, 5); - EXPECT_EQ(range[0], 5u); - EXPECT_EQ(range[1], 6u); - EXPECT_EQ(range[2], 7u); + EXPECT_EQ(range[0], 5); + EXPECT_EQ(range[1], 6); + EXPECT_EQ(range[2], 7); } TEST(index_range, Before) { IndexRange range = IndexRange(5, 5).before(3); - EXPECT_EQ(range[0], 2u); - EXPECT_EQ(range[1], 3u); - EXPECT_EQ(range[2], 4u); - EXPECT_EQ(range.size(), 3u); + EXPECT_EQ(range[0], 2); + EXPECT_EQ(range[1], 3); + EXPECT_EQ(range[2], 4); + EXPECT_EQ(range.size(), 3); } TEST(index_range, After) { IndexRange range = IndexRange(5, 5).after(4); - EXPECT_EQ(range[0], 10u); - EXPECT_EQ(range[1], 11u); - EXPECT_EQ(range[2], 12u); - EXPECT_EQ(range[3], 13u); - EXPECT_EQ(range.size(), 4u); + EXPECT_EQ(range[0], 10); + EXPECT_EQ(range[1], 11); + EXPECT_EQ(range[2], 12); + EXPECT_EQ(range[3], 13); + EXPECT_EQ(range.size(), 4); } TEST(index_range, Contains) @@ -90,54 +90,54 @@ TEST(index_range, Contains) TEST(index_range, First) { IndexRange range = IndexRange(5, 3); - EXPECT_EQ(range.first(), 5u); + EXPECT_EQ(range.first(), 5); } TEST(index_range, Last) { IndexRange range = IndexRange(5, 3); - EXPECT_EQ(range.last(), 7u); + EXPECT_EQ(range.last(), 7); } TEST(index_range, OneAfterEnd) { IndexRange range = IndexRange(5, 3); - EXPECT_EQ(range.one_after_last(), 8u); + EXPECT_EQ(range.one_after_last(), 8); } TEST(index_range, Start) { IndexRange range = IndexRange(6, 2); - EXPECT_EQ(range.start(), 6u); + EXPECT_EQ(range.start(), 6); } TEST(index_range, Slice) { IndexRange range = IndexRange(5, 15); IndexRange slice = range.slice(2, 6); - EXPECT_EQ(slice.size(), 6u); - EXPECT_EQ(slice.first(), 7u); - EXPECT_EQ(slice.last(), 12u); + EXPECT_EQ(slice.size(), 6); + EXPECT_EQ(slice.first(), 7); + EXPECT_EQ(slice.last(), 12); } TEST(index_range, SliceRange) { IndexRange range = IndexRange(5, 15); IndexRange slice = range.slice(IndexRange(3, 5)); - EXPECT_EQ(slice.size(), 5u); - EXPECT_EQ(slice.first(), 8u); - EXPECT_EQ(slice.last(), 12u); + EXPECT_EQ(slice.size(), 5); + EXPECT_EQ(slice.first(), 8); + EXPECT_EQ(slice.last(), 12); } TEST(index_range, AsSpan) { IndexRange range = IndexRange(4, 6); - Span<uint> span = range.as_span(); - EXPECT_EQ(span.size(), 6u); - EXPECT_EQ(span[0], 4u); - EXPECT_EQ(span[1], 5u); - EXPECT_EQ(span[2], 6u); - EXPECT_EQ(span[3], 7u); + Span<int64_t> span = range.as_span(); + EXPECT_EQ(span.size(), 6); + EXPECT_EQ(span[0], 4); + EXPECT_EQ(span[1], 5); + EXPECT_EQ(span[2], 6); + EXPECT_EQ(span[3], 7); } } // namespace blender diff --git a/tests/gtests/blenlib/BLI_linear_allocator_test.cc b/tests/gtests/blenlib/BLI_linear_allocator_test.cc index 7ef9d433a4d..9c2dcdc7457 100644 --- a/tests/gtests/blenlib/BLI_linear_allocator_test.cc +++ b/tests/gtests/blenlib/BLI_linear_allocator_test.cc @@ -70,7 +70,7 @@ TEST(linear_allocator, AllocateArray) LinearAllocator<> allocator; MutableSpan<int> span = allocator.allocate_array<int>(5); - EXPECT_EQ(span.size(), 5u); + EXPECT_EQ(span.size(), 5); } TEST(linear_allocator, Construct) @@ -79,7 +79,7 @@ TEST(linear_allocator, Construct) std::array<int, 5> values = {1, 2, 3, 4, 5}; Vector<int> *vector = allocator.construct<Vector<int>>(values); - EXPECT_EQ(vector->size(), 5u); + EXPECT_EQ(vector->size(), 5); EXPECT_EQ((*vector)[3], 4); vector->~Vector(); } @@ -92,8 +92,8 @@ TEST(linear_allocator, ConstructElementsAndPointerArray) Span<Vector<int> *> vectors = allocator.construct_elements_and_pointer_array<Vector<int>>( 5, values); - EXPECT_EQ(vectors.size(), 5u); - EXPECT_EQ(vectors[3]->size(), 7u); + EXPECT_EQ(vectors.size(), 5); + EXPECT_EQ(vectors[3]->size(), 7); EXPECT_EQ((*vectors[2])[5], 6); for (Vector<int> *vector : vectors) { @@ -109,8 +109,8 @@ TEST(linear_allocator, ConstructArrayCopy) MutableSpan<int> span1 = allocator.construct_array_copy(values.as_span()); MutableSpan<int> span2 = allocator.construct_array_copy(values.as_span()); EXPECT_NE(span1.data(), span2.data()); - EXPECT_EQ(span1.size(), 3u); - EXPECT_EQ(span2.size(), 3u); + EXPECT_EQ(span1.size(), 3); + EXPECT_EQ(span2.size(), 3); EXPECT_EQ(span1[1], 2); EXPECT_EQ(span2[2], 3); } diff --git a/tests/gtests/blenlib/BLI_map_test.cc b/tests/gtests/blenlib/BLI_map_test.cc index 4fb97c40e86..cebce218112 100644 --- a/tests/gtests/blenlib/BLI_map_test.cc +++ b/tests/gtests/blenlib/BLI_map_test.cc @@ -13,20 +13,20 @@ namespace blender { TEST(map, DefaultConstructor) { Map<int, float> map; - EXPECT_EQ(map.size(), 0u); + EXPECT_EQ(map.size(), 0); EXPECT_TRUE(map.is_empty()); } TEST(map, AddIncreasesSize) { Map<int, float> map; - EXPECT_EQ(map.size(), 0u); + EXPECT_EQ(map.size(), 0); EXPECT_TRUE(map.is_empty()); map.add(2, 5.0f); - EXPECT_EQ(map.size(), 1u); + EXPECT_EQ(map.size(), 1); EXPECT_FALSE(map.is_empty()); map.add(6, 2.0f); - EXPECT_EQ(map.size(), 2u); + EXPECT_EQ(map.size(), 2); EXPECT_FALSE(map.is_empty()); } @@ -89,16 +89,16 @@ TEST(map, PopTry) Map<int, int> map; map.add(1, 5); map.add(2, 7); - EXPECT_EQ(map.size(), 2u); + EXPECT_EQ(map.size(), 2); std::optional<int> value = map.pop_try(4); - EXPECT_EQ(map.size(), 2u); + EXPECT_EQ(map.size(), 2); EXPECT_FALSE(value.has_value()); value = map.pop_try(2); - EXPECT_EQ(map.size(), 1u); + EXPECT_EQ(map.size(), 1); EXPECT_TRUE(value.has_value()); EXPECT_EQ(*value, 7); EXPECT_EQ(*map.pop_try(1), 5); - EXPECT_EQ(map.size(), 0u); + EXPECT_EQ(map.size(), 0); } TEST(map, PopDefault) @@ -107,17 +107,17 @@ TEST(map, PopDefault) map.add(1, 4); map.add(2, 7); map.add(3, 8); - EXPECT_EQ(map.size(), 3u); + EXPECT_EQ(map.size(), 3); EXPECT_EQ(map.pop_default(4, 10), 10); - EXPECT_EQ(map.size(), 3u); + EXPECT_EQ(map.size(), 3); EXPECT_EQ(map.pop_default(1, 10), 4); - EXPECT_EQ(map.size(), 2u); + EXPECT_EQ(map.size(), 2); EXPECT_EQ(map.pop_default(2, 20), 7); - EXPECT_EQ(map.size(), 1u); + EXPECT_EQ(map.size(), 1); EXPECT_EQ(map.pop_default(2, 20), 20); - EXPECT_EQ(map.size(), 1u); + EXPECT_EQ(map.size(), 1); EXPECT_EQ(map.pop_default(3, 0), 8); - EXPECT_EQ(map.size(), 0u); + EXPECT_EQ(map.size(), 0); } TEST(map, PopItemMany) @@ -143,13 +143,13 @@ TEST(map, ValueIterator) blender::Set<float> values; - uint iterations = 0; + int iterations = 0; for (float value : map.values()) { values.add(value); iterations++; } - EXPECT_EQ(iterations, 3u); + EXPECT_EQ(iterations, 3); EXPECT_TRUE(values.contains(5.0f)); EXPECT_TRUE(values.contains(-2.0f)); EXPECT_TRUE(values.contains(2.0f)); @@ -164,13 +164,13 @@ TEST(map, KeyIterator) blender::Set<int> keys; - uint iterations = 0; + int iterations = 0; for (int key : map.keys()) { keys.add(key); iterations++; } - EXPECT_EQ(iterations, 3u); + EXPECT_EQ(iterations, 3); EXPECT_TRUE(keys.contains(1)); EXPECT_TRUE(keys.contains(2)); EXPECT_TRUE(keys.contains(6)); @@ -186,7 +186,7 @@ TEST(map, ItemIterator) blender::Set<int> keys; blender::Set<float> values; - uint iterations = 0; + int iterations = 0; const Map<int, float> &const_map = map; for (auto item : const_map.items()) { keys.add(item.key); @@ -194,7 +194,7 @@ TEST(map, ItemIterator) iterations++; } - EXPECT_EQ(iterations, 3u); + EXPECT_EQ(iterations, 3); EXPECT_TRUE(keys.contains(5)); EXPECT_TRUE(keys.contains(2)); EXPECT_TRUE(keys.contains(1)); @@ -243,8 +243,8 @@ TEST(map, MutableItemToItemConversion) values.append(item.value); } - EXPECT_EQ(keys.size(), 2u); - EXPECT_EQ(values.size(), 2u); + EXPECT_EQ(keys.size(), 2); + EXPECT_EQ(values.size(), 2); EXPECT_TRUE(keys.contains(3)); EXPECT_TRUE(keys.contains(2)); EXPECT_TRUE(values.contains(6)); @@ -332,10 +332,10 @@ TEST(map, MoveConstructorSmall) map1.add(1, 2.0f); map1.add(4, 1.0f); Map<int, float> map2(std::move(map1)); - EXPECT_EQ(map2.size(), 2u); + EXPECT_EQ(map2.size(), 2); EXPECT_EQ(map2.lookup(1), 2.0f); EXPECT_EQ(map2.lookup(4), 1.0f); - EXPECT_EQ(map1.size(), 0u); + EXPECT_EQ(map1.size(), 0); EXPECT_EQ(map1.lookup_ptr(4), nullptr); } @@ -346,10 +346,10 @@ TEST(map, MoveConstructorLarge) map1.add_new(i, i); } Map<int, int> map2(std::move(map1)); - EXPECT_EQ(map2.size(), 100u); + EXPECT_EQ(map2.size(), 100); EXPECT_EQ(map2.lookup(1), 1); EXPECT_EQ(map2.lookup(4), 4); - EXPECT_EQ(map1.size(), 0u); + EXPECT_EQ(map1.size(), 0); EXPECT_EQ(map1.lookup_ptr(4), nullptr); } @@ -360,10 +360,10 @@ TEST(map, MoveAssignment) map1.add(4, 1.0f); Map<int, float> map2; map2 = std::move(map1); - EXPECT_EQ(map2.size(), 2u); + EXPECT_EQ(map2.size(), 2); EXPECT_EQ(map2.lookup(1), 2.0f); EXPECT_EQ(map2.lookup(4), 1.0f); - EXPECT_EQ(map1.size(), 0u); + EXPECT_EQ(map1.size(), 0); EXPECT_EQ(map1.lookup_ptr(4), nullptr); } @@ -374,10 +374,10 @@ TEST(map, CopyAssignment) map1.add(4, 1.0f); Map<int, float> map2; map2 = map1; - EXPECT_EQ(map2.size(), 2u); + EXPECT_EQ(map2.size(), 2); EXPECT_EQ(map2.lookup(1), 2.0f); EXPECT_EQ(map2.lookup(4), 1.0f); - EXPECT_EQ(map1.size(), 2u); + EXPECT_EQ(map1.size(), 2); EXPECT_EQ(*map1.lookup_ptr(4), 1.0f); } @@ -387,13 +387,13 @@ TEST(map, Clear) map.add(1, 1.0f); map.add(2, 5.0f); - EXPECT_EQ(map.size(), 2u); + EXPECT_EQ(map.size(), 2); EXPECT_TRUE(map.contains(1)); EXPECT_TRUE(map.contains(2)); map.clear(); - EXPECT_EQ(map.size(), 0u); + EXPECT_EQ(map.size(), 0); EXPECT_FALSE(map.contains(1)); EXPECT_FALSE(map.contains(2)); } @@ -425,11 +425,11 @@ TEST(map, Remove) { Map<int, int> map; map.add(2, 4); - EXPECT_EQ(map.size(), 1u); + EXPECT_EQ(map.size(), 1); EXPECT_FALSE(map.remove(3)); - EXPECT_EQ(map.size(), 1u); + EXPECT_EQ(map.size(), 1); EXPECT_TRUE(map.remove(2)); - EXPECT_EQ(map.size(), 0u); + EXPECT_EQ(map.size(), 0); } TEST(map, PointerKeys) @@ -441,7 +441,7 @@ TEST(map, PointerKeys) EXPECT_FALSE(map.add(&a, 4)); map.add_new(&b, 1); map.add_new(&c, 1); - EXPECT_EQ(map.size(), 3u); + EXPECT_EQ(map.size(), 3); EXPECT_TRUE(map.remove(&b)); EXPECT_TRUE(map.add(&b, 8)); EXPECT_FALSE(map.remove(&d)); @@ -473,8 +473,8 @@ TEST(map, ForeachItem) values.append(value); }); - EXPECT_EQ(keys.size(), 2u); - EXPECT_EQ(values.size(), 2u); + EXPECT_EQ(keys.size(), 2); + EXPECT_EQ(values.size(), 2); EXPECT_EQ(keys.first_index_of(3), values.first_index_of(4)); EXPECT_EQ(keys.first_index_of(1), values.first_index_of(8)); } @@ -484,11 +484,11 @@ TEST(map, ForeachItem) */ #if 0 template<typename MapT> -BLI_NOINLINE void benchmark_random_ints(StringRef name, uint amount, uint factor) +BLI_NOINLINE void benchmark_random_ints(StringRef name, int amount, int factor) { RNG *rng = BLI_rng_new(0); Vector<int> values; - for (uint i = 0; i < amount; i++) { + for (int i = 0; i < amount; i++) { values.append(BLI_rng_get_int(rng) * factor); } BLI_rng_free(rng); @@ -520,12 +520,12 @@ BLI_NOINLINE void benchmark_random_ints(StringRef name, uint amount, uint factor TEST(map, Benchmark) { - for (uint i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { benchmark_random_ints<blender::Map<int, int>>("blender::Map ", 1000000, 1); benchmark_random_ints<blender::StdUnorderedMapWrapper<int, int>>("std::unordered_map", 1000000, 1); } std::cout << "\n"; - for (uint i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { uint32_t factor = (3 << 10); benchmark_random_ints<blender::Map<int, int>>("blender::Map ", 1000000, factor); benchmark_random_ints<blender::StdUnorderedMapWrapper<int, int>>( diff --git a/tests/gtests/blenlib/BLI_set_test.cc b/tests/gtests/blenlib/BLI_set_test.cc index 189f0c1b134..fcd958dc2f1 100644 --- a/tests/gtests/blenlib/BLI_set_test.cc +++ b/tests/gtests/blenlib/BLI_set_test.cc @@ -16,7 +16,7 @@ namespace blender { TEST(set, DefaultConstructor) { Set<int> set; - EXPECT_EQ(set.size(), 0u); + EXPECT_EQ(set.size(), 0); EXPECT_TRUE(set.is_empty()); } @@ -54,7 +54,7 @@ TEST(set, AddMany) TEST(set, InitializerListConstructor) { Set<int> set = {4, 5, 6}; - EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set.size(), 3); EXPECT_TRUE(set.contains(4)); EXPECT_TRUE(set.contains(5)); EXPECT_TRUE(set.contains(6)); @@ -79,10 +79,10 @@ TEST(set, CopyConstructor) TEST(set, MoveConstructor) { Set<int> set = {1, 2, 3}; - EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set.size(), 3); Set<int> set2(std::move(set)); - EXPECT_EQ(set.size(), 0u); - EXPECT_EQ(set2.size(), 3u); + EXPECT_EQ(set.size(), 0); + EXPECT_EQ(set2.size(), 3); } TEST(set, CopyAssignment) @@ -103,11 +103,11 @@ TEST(set, CopyAssignment) TEST(set, MoveAssignment) { Set<int> set = {1, 2, 3}; - EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set.size(), 3); Set<int> set2; set2 = std::move(set); - EXPECT_EQ(set.size(), 0u); - EXPECT_EQ(set2.size(), 3u); + EXPECT_EQ(set.size(), 0); + EXPECT_EQ(set2.size(), 3); } TEST(set, RemoveContained) @@ -179,7 +179,7 @@ TEST(set, AddMultiple) a.add_multiple({2, 4, 7}); EXPECT_TRUE(a.contains(4)); EXPECT_TRUE(a.contains(2)); - EXPECT_EQ(a.size(), 4u); + EXPECT_EQ(a.size(), 4); } TEST(set, AddMultipleNew) @@ -197,7 +197,7 @@ TEST(set, Iterator) for (int value : set) { vec.append(value); } - EXPECT_EQ(vec.size(), 5u); + EXPECT_EQ(vec.size(), 5); EXPECT_TRUE(vec.contains(1)); EXPECT_TRUE(vec.contains(3)); EXPECT_TRUE(vec.contains(2)); @@ -210,9 +210,9 @@ TEST(set, OftenAddRemoveContained) Set<int> set; for (int i = 0; i < 100; i++) { set.add(42); - EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set.size(), 1); set.remove_contained(42); - EXPECT_EQ(set.size(), 0u); + EXPECT_EQ(set.size(), 0); } } @@ -224,15 +224,15 @@ TEST(set, UniquePtrValues) set.add_new(std::move(value1)); set.add(std::unique_ptr<int>(new int())); - EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set.size(), 3); } TEST(set, Clear) { Set<int> set = {3, 4, 6, 7}; - EXPECT_EQ(set.size(), 4u); + EXPECT_EQ(set.size(), 4); set.clear(); - EXPECT_EQ(set.size(), 0u); + EXPECT_EQ(set.size(), 0); } TEST(set, StringSet) @@ -240,7 +240,7 @@ TEST(set, StringSet) Set<std::string> set; set.add("hello"); set.add("world"); - EXPECT_EQ(set.size(), 2u); + EXPECT_EQ(set.size(), 2); EXPECT_TRUE(set.contains("hello")); EXPECT_TRUE(set.contains("world")); EXPECT_FALSE(set.contains("world2")); @@ -252,7 +252,7 @@ TEST(set, PointerSet) Set<int *> set; set.add(&a); set.add(&b); - EXPECT_EQ(set.size(), 2u); + EXPECT_EQ(set.size(), 2); EXPECT_TRUE(set.contains(&a)); EXPECT_TRUE(set.contains(&b)); EXPECT_FALSE(set.contains(&c)); @@ -261,14 +261,14 @@ TEST(set, PointerSet) TEST(set, Remove) { Set<int> set = {1, 2, 3, 4, 5, 6}; - EXPECT_EQ(set.size(), 6u); + EXPECT_EQ(set.size(), 6); EXPECT_TRUE(set.remove(2)); - EXPECT_EQ(set.size(), 5u); + EXPECT_EQ(set.size(), 5); EXPECT_FALSE(set.contains(2)); EXPECT_FALSE(set.remove(2)); - EXPECT_EQ(set.size(), 5u); + EXPECT_EQ(set.size(), 5); EXPECT_TRUE(set.remove(5)); - EXPECT_EQ(set.size(), 4u); + EXPECT_EQ(set.size(), 4); } struct Type1 { @@ -363,7 +363,7 @@ template<uint N> struct EqualityIntModN { }; template<uint N> struct HashIntModN { - uint32_t operator()(uint value) const + uint64_t operator()(uint value) const { return value % N; } @@ -409,7 +409,7 @@ struct MyKeyType { uint32_t key; int32_t attached_data; - uint32_t hash() const + uint64_t hash() const { return key; } @@ -455,11 +455,11 @@ TEST(set, LookupKeyPtr) */ #if 0 template<typename SetT> -BLI_NOINLINE void benchmark_random_ints(StringRef name, uint amount, uint factor) +BLI_NOINLINE void benchmark_random_ints(StringRef name, int amount, int factor) { RNG *rng = BLI_rng_new(0); Vector<int> values; - for (uint i = 0; i < amount; i++) { + for (int i = 0; i < amount; i++) { values.append(BLI_rng_get_int(rng) * factor); } BLI_rng_free(rng); @@ -491,12 +491,12 @@ BLI_NOINLINE void benchmark_random_ints(StringRef name, uint amount, uint factor TEST(set, Benchmark) { - for (uint i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { benchmark_random_ints<blender::Set<int>>("blender::Set ", 100000, 1); benchmark_random_ints<blender::StdUnorderedSetWrapper<int>>("std::unordered_set", 100000, 1); } std::cout << "\n"; - for (uint i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { uint32_t factor = (3 << 10); benchmark_random_ints<blender::Set<int>>("blender::Set ", 100000, factor); benchmark_random_ints<blender::StdUnorderedSetWrapper<int>>("std::unordered_set", 100000, factor); diff --git a/tests/gtests/blenlib/BLI_span_test.cc b/tests/gtests/blenlib/BLI_span_test.cc index ccc63fd80eb..9c2e7cf26fb 100644 --- a/tests/gtests/blenlib/BLI_span_test.cc +++ b/tests/gtests/blenlib/BLI_span_test.cc @@ -11,7 +11,7 @@ TEST(span, FromSmallVector) { Vector<int> a = {1, 2, 3}; Span<int> a_span = a; - EXPECT_EQ(a_span.size(), 3u); + EXPECT_EQ(a_span.size(), 3); EXPECT_EQ(a_span[0], 1); EXPECT_EQ(a_span[1], 2); EXPECT_EQ(a_span[2], 3); @@ -23,14 +23,14 @@ TEST(span, AddConstToPointer) std::vector<int *> vec = {&a}; Span<int *> span = vec; Span<const int *> const_span = span; - EXPECT_EQ(const_span.size(), 1u); + EXPECT_EQ(const_span.size(), 1); } TEST(span, IsReferencing) { int array[] = {3, 5, 8}; MutableSpan<int> span(array, ARRAY_SIZE(array)); - EXPECT_EQ(span.size(), 3u); + EXPECT_EQ(span.size(), 3); EXPECT_EQ(span[1], 5); array[1] = 10; EXPECT_EQ(span[1], 10); @@ -40,7 +40,7 @@ TEST(span, DropBack) { Vector<int> a = {4, 5, 6, 7}; auto slice = Span<int>(a).drop_back(2); - EXPECT_EQ(slice.size(), 2u); + EXPECT_EQ(slice.size(), 2); EXPECT_EQ(slice[0], 4); EXPECT_EQ(slice[1], 5); } @@ -49,14 +49,14 @@ TEST(span, DropBackAll) { Vector<int> a = {4, 5, 6, 7}; auto slice = Span<int>(a).drop_back(a.size()); - EXPECT_EQ(slice.size(), 0u); + EXPECT_EQ(slice.size(), 0); } TEST(span, DropFront) { Vector<int> a = {4, 5, 6, 7}; auto slice = Span<int>(a).drop_front(1); - EXPECT_EQ(slice.size(), 3u); + EXPECT_EQ(slice.size(), 3); EXPECT_EQ(slice[0], 5); EXPECT_EQ(slice[1], 6); EXPECT_EQ(slice[2], 7); @@ -66,14 +66,14 @@ TEST(span, DropFrontAll) { Vector<int> a = {4, 5, 6, 7}; auto slice = Span<int>(a).drop_front(a.size()); - EXPECT_EQ(slice.size(), 0u); + EXPECT_EQ(slice.size(), 0); } TEST(span, TakeFront) { Vector<int> a = {4, 5, 6, 7}; auto slice = Span<int>(a).take_front(2); - EXPECT_EQ(slice.size(), 2u); + EXPECT_EQ(slice.size(), 2); EXPECT_EQ(slice[0], 4); EXPECT_EQ(slice[1], 5); } @@ -82,7 +82,7 @@ TEST(span, TakeBack) { Vector<int> a = {5, 6, 7, 8}; auto slice = Span<int>(a).take_back(2); - EXPECT_EQ(slice.size(), 2u); + EXPECT_EQ(slice.size(), 2); EXPECT_EQ(slice[0], 7); EXPECT_EQ(slice[1], 8); } @@ -91,7 +91,7 @@ TEST(span, Slice) { Vector<int> a = {4, 5, 6, 7}; auto slice = Span<int>(a).slice(1, 2); - EXPECT_EQ(slice.size(), 2u); + EXPECT_EQ(slice.size(), 2); EXPECT_EQ(slice[0], 5); EXPECT_EQ(slice[1], 6); } @@ -100,14 +100,14 @@ TEST(span, SliceEmpty) { Vector<int> a = {4, 5, 6, 7}; auto slice = Span<int>(a).slice(2, 0); - EXPECT_EQ(slice.size(), 0u); + EXPECT_EQ(slice.size(), 0); } TEST(span, SliceRange) { Vector<int> a = {1, 2, 3, 4, 5}; auto slice = Span<int>(a).slice(IndexRange(2, 2)); - EXPECT_EQ(slice.size(), 2u); + EXPECT_EQ(slice.size(), 2); EXPECT_EQ(slice[0], 3); EXPECT_EQ(slice[1], 4); } @@ -128,16 +128,16 @@ TEST(span, Count) { Vector<int> a = {2, 3, 4, 3, 3, 2, 2, 2, 2}; Span<int> a_span = a; - EXPECT_EQ(a_span.count(1), 0u); - EXPECT_EQ(a_span.count(2), 5u); - EXPECT_EQ(a_span.count(3), 3u); - EXPECT_EQ(a_span.count(4), 1u); - EXPECT_EQ(a_span.count(5), 0u); + EXPECT_EQ(a_span.count(1), 0); + EXPECT_EQ(a_span.count(2), 5); + EXPECT_EQ(a_span.count(3), 3); + EXPECT_EQ(a_span.count(4), 1); + EXPECT_EQ(a_span.count(5), 0); } static void test_ref_from_initializer_list(Span<int> span) { - EXPECT_EQ(span.size(), 4u); + EXPECT_EQ(span.size(), 4); EXPECT_EQ(span[0], 3); EXPECT_EQ(span[1], 6); EXPECT_EQ(span[2], 8); @@ -153,7 +153,7 @@ TEST(span, FromVector) { std::vector<int> a = {1, 2, 3, 4}; Span<int> a_span(a); - EXPECT_EQ(a_span.size(), 4u); + EXPECT_EQ(a_span.size(), 4); EXPECT_EQ(a_span[0], 1); EXPECT_EQ(a_span[1], 2); EXPECT_EQ(a_span[2], 3); @@ -164,7 +164,7 @@ TEST(span, FromArray) { std::array<int, 2> a = {5, 6}; Span<int> a_span(a); - EXPECT_EQ(a_span.size(), 2u); + EXPECT_EQ(a_span.size(), 2); EXPECT_EQ(a_span[0], 5); EXPECT_EQ(a_span[1], 6); } @@ -197,8 +197,8 @@ TEST(span, SizeInBytes) { std::array<int, 10> a; Span<int> a_span(a); - EXPECT_EQ(a_span.size_in_bytes(), sizeof(a)); - EXPECT_EQ(a_span.size_in_bytes(), 40u); + EXPECT_EQ(a_span.size_in_bytes(), (int64_t)sizeof(a)); + EXPECT_EQ(a_span.size_in_bytes(), 40); } TEST(span, FirstLast) @@ -246,9 +246,9 @@ TEST(span, FirstIndex) std::array<int, 5> a = {4, 5, 4, 2, 5}; Span<int> a_span(a); - EXPECT_EQ(a_span.first_index(4), 0u); - EXPECT_EQ(a_span.first_index(5), 1u); - EXPECT_EQ(a_span.first_index(2), 3u); + EXPECT_EQ(a_span.first_index(4), 0); + EXPECT_EQ(a_span.first_index(5), 1); + EXPECT_EQ(a_span.first_index(2), 3); } TEST(span, CastSameSize) @@ -258,8 +258,8 @@ TEST(span, CastSameSize) Span<int *> a_span = a; Span<float *> new_a_span = a_span.cast<float *>(); - EXPECT_EQ(a_span.size(), 4u); - EXPECT_EQ(new_a_span.size(), 4u); + EXPECT_EQ(a_span.size(), 4); + EXPECT_EQ(new_a_span.size(), 4); EXPECT_EQ(a_span[0], &value); EXPECT_EQ(new_a_span[0], (float *)&value); @@ -271,8 +271,8 @@ TEST(span, CastSmallerSize) Span<uint32_t> a_span = a; Span<uint16_t> new_a_span = a_span.cast<uint16_t>(); - EXPECT_EQ(a_span.size(), 4u); - EXPECT_EQ(new_a_span.size(), 8u); + EXPECT_EQ(a_span.size(), 4); + EXPECT_EQ(new_a_span.size(), 8); } TEST(span, CastLargerSize) @@ -281,8 +281,8 @@ TEST(span, CastLargerSize) Span<uint16_t> a_span = a; Span<uint32_t> new_a_span = a_span.cast<uint32_t>(); - EXPECT_EQ(a_span.size(), 4u); - EXPECT_EQ(new_a_span.size(), 2u); + EXPECT_EQ(a_span.size(), 4); + EXPECT_EQ(new_a_span.size(), 2); } TEST(span, VoidPointerSpan) @@ -291,7 +291,7 @@ TEST(span, VoidPointerSpan) float b; double c; - auto func1 = [](Span<void *> span) { EXPECT_EQ(span.size(), 3u); }; + auto func1 = [](Span<void *> span) { EXPECT_EQ(span.size(), 3); }; func1({&a, &b, &c}); } diff --git a/tests/gtests/blenlib/BLI_stack_cxx_test.cc b/tests/gtests/blenlib/BLI_stack_cxx_test.cc index c8433b4fd87..43b3dd8b3ae 100644 --- a/tests/gtests/blenlib/BLI_stack_cxx_test.cc +++ b/tests/gtests/blenlib/BLI_stack_cxx_test.cc @@ -10,7 +10,7 @@ namespace blender { TEST(stack, DefaultConstructor) { Stack<int> stack; - EXPECT_EQ(stack.size(), 0u); + EXPECT_EQ(stack.size(), 0); EXPECT_TRUE(stack.is_empty()); } @@ -18,7 +18,7 @@ TEST(stack, SpanConstructor) { std::array<int, 3> array = {4, 7, 2}; Stack<int> stack(array); - EXPECT_EQ(stack.size(), 3u); + EXPECT_EQ(stack.size(), 3); EXPECT_EQ(stack.pop(), 2); EXPECT_EQ(stack.pop(), 7); EXPECT_EQ(stack.pop(), 4); @@ -29,8 +29,8 @@ TEST(stack, CopyConstructor) { Stack<int> stack1 = {1, 2, 3, 4, 5, 6, 7}; Stack<int> stack2 = stack1; - EXPECT_EQ(stack1.size(), 7u); - EXPECT_EQ(stack2.size(), 7u); + EXPECT_EQ(stack1.size(), 7); + EXPECT_EQ(stack2.size(), 7); for (int i = 7; i >= 1; i--) { EXPECT_FALSE(stack1.is_empty()); EXPECT_FALSE(stack2.is_empty()); @@ -45,8 +45,8 @@ TEST(stack, MoveConstructor) { Stack<int> stack1 = {1, 2, 3, 4, 5, 6, 7}; Stack<int> stack2 = std::move(stack1); - EXPECT_EQ(stack1.size(), 0u); - EXPECT_EQ(stack2.size(), 7u); + EXPECT_EQ(stack1.size(), 0); + EXPECT_EQ(stack2.size(), 7); for (int i = 7; i >= 1; i--) { EXPECT_EQ(stack2.pop(), i); } @@ -58,8 +58,8 @@ TEST(stack, CopyAssignment) Stack<int> stack2 = {2, 3, 4, 5, 6, 7}; stack2 = stack1; - EXPECT_EQ(stack1.size(), 7u); - EXPECT_EQ(stack2.size(), 7u); + EXPECT_EQ(stack1.size(), 7); + EXPECT_EQ(stack2.size(), 7); for (int i = 7; i >= 1; i--) { EXPECT_FALSE(stack1.is_empty()); EXPECT_FALSE(stack2.is_empty()); @@ -75,8 +75,8 @@ TEST(stack, MoveAssignment) Stack<int> stack1 = {1, 2, 3, 4, 5, 6, 7}; Stack<int> stack2 = {5, 3, 7, 2, 2}; stack2 = std::move(stack1); - EXPECT_EQ(stack1.size(), 0u); - EXPECT_EQ(stack2.size(), 7u); + EXPECT_EQ(stack1.size(), 0); + EXPECT_EQ(stack2.size(), 7); for (int i = 7; i >= 1; i--) { EXPECT_EQ(stack2.pop(), i); } @@ -85,19 +85,19 @@ TEST(stack, MoveAssignment) TEST(stack, Push) { Stack<int> stack; - EXPECT_EQ(stack.size(), 0u); + EXPECT_EQ(stack.size(), 0); stack.push(3); - EXPECT_EQ(stack.size(), 1u); + EXPECT_EQ(stack.size(), 1); stack.push(5); - EXPECT_EQ(stack.size(), 2u); + EXPECT_EQ(stack.size(), 2); } TEST(stack, PushMultiple) { Stack<int> stack; - EXPECT_EQ(stack.size(), 0u); + EXPECT_EQ(stack.size(), 0); stack.push_multiple({1, 2, 3}); - EXPECT_EQ(stack.size(), 3u); + EXPECT_EQ(stack.size(), 3); EXPECT_EQ(stack.pop(), 3); EXPECT_EQ(stack.pop(), 2); EXPECT_EQ(stack.pop(), 1); @@ -139,7 +139,7 @@ TEST(stack, PushMultipleAfterPop) values.append(i); } stack.push_multiple(values); - EXPECT_EQ(stack.size(), 5000u); + EXPECT_EQ(stack.size(), 5000); for (int i = 4999; i >= 0; i--) { EXPECT_EQ(stack.pop(), i); diff --git a/tests/gtests/blenlib/BLI_string_ref_test.cc b/tests/gtests/blenlib/BLI_string_ref_test.cc index 0d1880229c7..83099741c29 100644 --- a/tests/gtests/blenlib/BLI_string_ref_test.cc +++ b/tests/gtests/blenlib/BLI_string_ref_test.cc @@ -10,7 +10,7 @@ namespace blender { TEST(string_ref_null, DefaultConstructor) { StringRefNull ref; - EXPECT_EQ(ref.size(), 0u); + EXPECT_EQ(ref.size(), 0); EXPECT_EQ(ref[0], '\0'); } @@ -18,7 +18,7 @@ TEST(string_ref_null, CStringConstructor) { const char *str = "Hello"; StringRefNull ref(str); - EXPECT_EQ(ref.size(), 5u); + EXPECT_EQ(ref.size(), 5); EXPECT_EQ(ref.data(), str); } @@ -26,21 +26,21 @@ TEST(string_ref_null, CStringLengthConstructor) { const char *str = "Hello"; StringRefNull ref(str, 5); - EXPECT_EQ(ref.size(), 5u); + EXPECT_EQ(ref.size(), 5); EXPECT_EQ(ref.data(), str); } TEST(string_ref, DefaultConstructor) { StringRef ref; - EXPECT_EQ(ref.size(), 0u); + EXPECT_EQ(ref.size(), 0); } TEST(string_ref, StartEndConstructor) { const char *text = "hello world"; StringRef ref(text, text + 5); - EXPECT_EQ(ref.size(), 5u); + EXPECT_EQ(ref.size(), 5); EXPECT_TRUE(ref == "hello"); EXPECT_FALSE(ref == "hello "); } @@ -48,7 +48,7 @@ TEST(string_ref, StartEndConstructor) TEST(string_ref, StartEndConstructorNullptr) { StringRef ref(nullptr, nullptr); - EXPECT_EQ(ref.size(), 0u); + EXPECT_EQ(ref.size(), 0); EXPECT_TRUE(ref == ""); } @@ -56,7 +56,7 @@ TEST(string_ref, StartEndConstructorSame) { const char *text = "hello world"; StringRef ref(text, text); - EXPECT_EQ(ref.size(), 0u); + EXPECT_EQ(ref.size(), 0); EXPECT_TRUE(ref == ""); } @@ -64,7 +64,7 @@ TEST(string_ref, CStringConstructor) { const char *str = "Test"; StringRef ref(str); - EXPECT_EQ(ref.size(), 4u); + EXPECT_EQ(ref.size(), 4); EXPECT_EQ(ref.data(), str); } @@ -72,7 +72,7 @@ TEST(string_ref, PointerWithLengthConstructor) { const char *str = "Test"; StringRef ref(str, 2); - EXPECT_EQ(ref.size(), 2u); + EXPECT_EQ(ref.size(), 2); EXPECT_EQ(ref.data(), str); } @@ -80,14 +80,14 @@ TEST(string_ref, StdStringConstructor) { std::string str = "Test"; StringRef ref(str); - EXPECT_EQ(ref.size(), 4u); + EXPECT_EQ(ref.size(), 4); EXPECT_EQ(ref.data(), str.data()); } TEST(string_ref, SubscriptOperator) { StringRef ref("hello"); - EXPECT_EQ(ref.size(), 5u); + EXPECT_EQ(ref.size(), 5); EXPECT_EQ(ref[0], 'h'); EXPECT_EQ(ref[1], 'e'); EXPECT_EQ(ref[2], 'l'); @@ -99,7 +99,7 @@ TEST(string_ref, ToStdString) { StringRef ref("test"); std::string str = ref; - EXPECT_EQ(str.size(), 4u); + EXPECT_EQ(str.size(), 4); EXPECT_EQ(str, "test"); } @@ -204,7 +204,7 @@ TEST(string_ref, Iterate) for (char c : ref) { chars.append(c); } - EXPECT_EQ(chars.size(), 4u); + EXPECT_EQ(chars.size(), 4); EXPECT_EQ(chars[0], 't'); EXPECT_EQ(chars[1], 'e'); EXPECT_EQ(chars[2], 's'); @@ -240,8 +240,8 @@ TEST(string_ref, DropPrefixN) StringRef ref("test"); StringRef ref2 = ref.drop_prefix(2); StringRef ref3 = ref2.drop_prefix(2); - EXPECT_EQ(ref2.size(), 2u); - EXPECT_EQ(ref3.size(), 0u); + EXPECT_EQ(ref2.size(), 2); + EXPECT_EQ(ref3.size(), 0); EXPECT_EQ(ref2, "st"); EXPECT_EQ(ref3, ""); } @@ -250,7 +250,7 @@ TEST(string_ref, DropPrefix) { StringRef ref("test"); StringRef ref2 = ref.drop_prefix("tes"); - EXPECT_EQ(ref2.size(), 1u); + EXPECT_EQ(ref2.size(), 1); EXPECT_EQ(ref2, "t"); } diff --git a/tests/gtests/blenlib/BLI_vector_set_test.cc b/tests/gtests/blenlib/BLI_vector_set_test.cc index 3c3b4d55959..116c4747c5a 100644 --- a/tests/gtests/blenlib/BLI_vector_set_test.cc +++ b/tests/gtests/blenlib/BLI_vector_set_test.cc @@ -9,14 +9,14 @@ namespace blender { TEST(vector_set, DefaultConstructor) { VectorSet<int> set; - EXPECT_EQ(set.size(), 0u); + EXPECT_EQ(set.size(), 0); EXPECT_TRUE(set.is_empty()); } TEST(vector_set, InitializerListConstructor_WithoutDuplicates) { VectorSet<int> set = {1, 4, 5}; - EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set.size(), 3); EXPECT_EQ(set[0], 1); EXPECT_EQ(set[1], 4); EXPECT_EQ(set[2], 5); @@ -25,7 +25,7 @@ TEST(vector_set, InitializerListConstructor_WithoutDuplicates) TEST(vector_set, InitializerListConstructor_WithDuplicates) { VectorSet<int> set = {1, 3, 3, 2, 1, 5}; - EXPECT_EQ(set.size(), 4u); + EXPECT_EQ(set.size(), 4); EXPECT_EQ(set[0], 1); EXPECT_EQ(set[1], 3); EXPECT_EQ(set[2], 2); @@ -36,10 +36,10 @@ TEST(vector_set, Copy) { VectorSet<int> set1 = {1, 2, 3}; VectorSet<int> set2 = set1; - EXPECT_EQ(set1.size(), 3u); - EXPECT_EQ(set2.size(), 3u); - EXPECT_EQ(set1.index_of(2), 1u); - EXPECT_EQ(set2.index_of(2), 1u); + EXPECT_EQ(set1.size(), 3); + EXPECT_EQ(set2.size(), 3); + EXPECT_EQ(set1.index_of(2), 1); + EXPECT_EQ(set2.index_of(2), 1); } TEST(vector_set, CopyAssignment) @@ -47,18 +47,18 @@ TEST(vector_set, CopyAssignment) VectorSet<int> set1 = {1, 2, 3}; VectorSet<int> set2 = {}; set2 = set1; - EXPECT_EQ(set1.size(), 3u); - EXPECT_EQ(set2.size(), 3u); - EXPECT_EQ(set1.index_of(2), 1u); - EXPECT_EQ(set2.index_of(2), 1u); + EXPECT_EQ(set1.size(), 3); + EXPECT_EQ(set2.size(), 3); + EXPECT_EQ(set1.index_of(2), 1); + EXPECT_EQ(set2.index_of(2), 1); } TEST(vector_set, Move) { VectorSet<int> set1 = {1, 2, 3}; VectorSet<int> set2 = std::move(set1); - EXPECT_EQ(set1.size(), 0u); - EXPECT_EQ(set2.size(), 3u); + EXPECT_EQ(set1.size(), 0); + EXPECT_EQ(set2.size(), 3); } TEST(vector_set, MoveAssignment) @@ -66,36 +66,36 @@ TEST(vector_set, MoveAssignment) VectorSet<int> set1 = {1, 2, 3}; VectorSet<int> set2 = {}; set2 = std::move(set1); - EXPECT_EQ(set1.size(), 0u); - EXPECT_EQ(set2.size(), 3u); + EXPECT_EQ(set1.size(), 0); + EXPECT_EQ(set2.size(), 3); } TEST(vector_set, AddNewIncreasesSize) { VectorSet<int> set; EXPECT_TRUE(set.is_empty()); - EXPECT_EQ(set.size(), 0u); + EXPECT_EQ(set.size(), 0); set.add(5); EXPECT_FALSE(set.is_empty()); - EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set.size(), 1); } TEST(vector_set, AddExistingDoesNotIncreaseSize) { VectorSet<int> set; - EXPECT_EQ(set.size(), 0u); + EXPECT_EQ(set.size(), 0); EXPECT_TRUE(set.add(5)); - EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set.size(), 1); EXPECT_FALSE(set.add(5)); - EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set.size(), 1); } TEST(vector_set, Index) { VectorSet<int> set = {3, 6, 4}; - EXPECT_EQ(set.index_of(6), 1u); - EXPECT_EQ(set.index_of(3), 0u); - EXPECT_EQ(set.index_of(4), 2u); + EXPECT_EQ(set.index_of(6), 1); + EXPECT_EQ(set.index_of(3), 0); + EXPECT_EQ(set.index_of(4), 2); } TEST(vector_set, IndexTry) @@ -110,21 +110,21 @@ TEST(vector_set, IndexTry) TEST(vector_set, RemoveContained) { VectorSet<int> set = {4, 5, 6, 7}; - EXPECT_EQ(set.size(), 4u); + EXPECT_EQ(set.size(), 4); set.remove_contained(5); - EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set.size(), 3); EXPECT_EQ(set[0], 4); EXPECT_EQ(set[1], 7); EXPECT_EQ(set[2], 6); set.remove_contained(6); - EXPECT_EQ(set.size(), 2u); + EXPECT_EQ(set.size(), 2); EXPECT_EQ(set[0], 4); EXPECT_EQ(set[1], 7); set.remove_contained(4); - EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set.size(), 1); EXPECT_EQ(set[0], 7); set.remove_contained(7); - EXPECT_EQ(set.size(), 0u); + EXPECT_EQ(set.size(), 0); } TEST(vector_set, AddMultipleTimes) diff --git a/tests/gtests/blenlib/BLI_vector_test.cc b/tests/gtests/blenlib/BLI_vector_test.cc index 25435739a43..f581626d1ad 100644 --- a/tests/gtests/blenlib/BLI_vector_test.cc +++ b/tests/gtests/blenlib/BLI_vector_test.cc @@ -10,13 +10,13 @@ namespace blender { TEST(vector, DefaultConstructor) { Vector<int> vec; - EXPECT_EQ(vec.size(), 0u); + EXPECT_EQ(vec.size(), 0); } TEST(vector, SizeConstructor) { Vector<int> vec(3); - EXPECT_EQ(vec.size(), 3u); + EXPECT_EQ(vec.size(), 3); } /** @@ -42,7 +42,7 @@ TEST(vector, TrivialTypeSizeConstructor) TEST(vector, SizeValueConstructor) { Vector<int> vec(4, 10); - EXPECT_EQ(vec.size(), 4u); + EXPECT_EQ(vec.size(), 4); EXPECT_EQ(vec[0], 10); EXPECT_EQ(vec[1], 10); EXPECT_EQ(vec[2], 10); @@ -52,7 +52,7 @@ TEST(vector, SizeValueConstructor) TEST(vector, InitializerListConstructor) { Vector<int> vec = {1, 3, 4, 6}; - EXPECT_EQ(vec.size(), 4u); + EXPECT_EQ(vec.size(), 4); EXPECT_EQ(vec[0], 1); EXPECT_EQ(vec[1], 3); EXPECT_EQ(vec[2], 4); @@ -63,7 +63,7 @@ TEST(vector, ConvertingConstructor) { std::array<float, 5> values = {5.4f, 7.3f, -8.1f, 5.0f, 0.0f}; Vector<int> vec = values; - EXPECT_EQ(vec.size(), 5u); + EXPECT_EQ(vec.size(), 5); EXPECT_EQ(vec[0], 5); EXPECT_EQ(vec[1], 7); EXPECT_EQ(vec[2], -8); @@ -88,7 +88,7 @@ TEST(vector, ListBaseConstructor) BLI_addtail(&list, value3); Vector<TestListValue *> vec(list); - EXPECT_EQ(vec.size(), 3u); + EXPECT_EQ(vec.size(), 3); EXPECT_EQ(vec[0]->value, 4); EXPECT_EQ(vec[1]->value, 5); EXPECT_EQ(vec[2]->value, 6); @@ -106,7 +106,7 @@ TEST(vector, ContainerConstructor) list.push_front(5); Vector<int> vec = Vector<int>::FromContainer(list); - EXPECT_EQ(vec.size(), 3u); + EXPECT_EQ(vec.size(), 3); EXPECT_EQ(vec[0], 5); EXPECT_EQ(vec[1], 1); EXPECT_EQ(vec[2], 3); @@ -116,7 +116,7 @@ TEST(vector, CopyConstructor) { Vector<int> vec1 = {1, 2, 3}; Vector<int> vec2(vec1); - EXPECT_EQ(vec2.size(), 3u); + EXPECT_EQ(vec2.size(), 3); EXPECT_EQ(vec2[0], 1); EXPECT_EQ(vec2[1], 2); EXPECT_EQ(vec2[2], 3); @@ -131,8 +131,8 @@ TEST(vector, CopyConstructor2) Vector<int, 2> vec1 = {1, 2, 3, 4}; Vector<int, 3> vec2(vec1); - EXPECT_EQ(vec1.size(), 4u); - EXPECT_EQ(vec2.size(), 4u); + EXPECT_EQ(vec1.size(), 4); + EXPECT_EQ(vec2.size(), 4); EXPECT_NE(vec1.data(), vec2.data()); EXPECT_EQ(vec2[0], 1); EXPECT_EQ(vec2[1], 2); @@ -145,8 +145,8 @@ TEST(vector, CopyConstructor3) Vector<int, 20> vec1 = {1, 2, 3, 4}; Vector<int, 1> vec2(vec1); - EXPECT_EQ(vec1.size(), 4u); - EXPECT_EQ(vec2.size(), 4u); + EXPECT_EQ(vec1.size(), 4); + EXPECT_EQ(vec2.size(), 4); EXPECT_NE(vec1.data(), vec2.data()); EXPECT_EQ(vec2[2], 3); } @@ -156,8 +156,8 @@ TEST(vector, CopyConstructor4) Vector<int, 5> vec1 = {1, 2, 3, 4}; Vector<int, 6> vec2(vec1); - EXPECT_EQ(vec1.size(), 4u); - EXPECT_EQ(vec2.size(), 4u); + EXPECT_EQ(vec1.size(), 4); + EXPECT_EQ(vec2.size(), 4); EXPECT_NE(vec1.data(), vec2.data()); EXPECT_EQ(vec2[3], 4); } @@ -167,8 +167,8 @@ TEST(vector, MoveConstructor) Vector<int> vec1 = {1, 2, 3, 4}; Vector<int> vec2(std::move(vec1)); - EXPECT_EQ(vec1.size(), 0u); - EXPECT_EQ(vec2.size(), 4u); + EXPECT_EQ(vec1.size(), 0); + EXPECT_EQ(vec2.size(), 4); EXPECT_EQ(vec2[0], 1); EXPECT_EQ(vec2[1], 2); EXPECT_EQ(vec2[2], 3); @@ -180,8 +180,8 @@ TEST(vector, MoveConstructor2) Vector<int, 2> vec1 = {1, 2, 3, 4}; Vector<int, 3> vec2(std::move(vec1)); - EXPECT_EQ(vec1.size(), 0u); - EXPECT_EQ(vec2.size(), 4u); + EXPECT_EQ(vec1.size(), 0); + EXPECT_EQ(vec2.size(), 4); EXPECT_EQ(vec2[0], 1); EXPECT_EQ(vec2[1], 2); EXPECT_EQ(vec2[2], 3); @@ -193,8 +193,8 @@ TEST(vector, MoveConstructor3) Vector<int, 20> vec1 = {1, 2, 3, 4}; Vector<int, 1> vec2(std::move(vec1)); - EXPECT_EQ(vec1.size(), 0u); - EXPECT_EQ(vec2.size(), 4u); + EXPECT_EQ(vec1.size(), 0); + EXPECT_EQ(vec2.size(), 4); EXPECT_EQ(vec2[2], 3); } @@ -203,20 +203,20 @@ TEST(vector, MoveConstructor4) Vector<int, 5> vec1 = {1, 2, 3, 4}; Vector<int, 6> vec2(std::move(vec1)); - EXPECT_EQ(vec1.size(), 0u); - EXPECT_EQ(vec2.size(), 4u); + EXPECT_EQ(vec1.size(), 0); + EXPECT_EQ(vec2.size(), 4); EXPECT_EQ(vec2[3], 4); } TEST(vector, MoveAssignment) { Vector<int> vec = {1, 2}; - EXPECT_EQ(vec.size(), 2u); + EXPECT_EQ(vec.size(), 2); EXPECT_EQ(vec[0], 1); EXPECT_EQ(vec[1], 2); vec = Vector<int>({5}); - EXPECT_EQ(vec.size(), 1u); + EXPECT_EQ(vec.size(), 1); EXPECT_EQ(vec[0], 5); } @@ -224,11 +224,11 @@ TEST(vector, CopyAssignment) { Vector<int> vec1 = {1, 2, 3}; Vector<int> vec2 = {4, 5}; - EXPECT_EQ(vec1.size(), 3u); - EXPECT_EQ(vec2.size(), 2u); + EXPECT_EQ(vec1.size(), 3); + EXPECT_EQ(vec2.size(), 2); vec2 = vec1; - EXPECT_EQ(vec2.size(), 3u); + EXPECT_EQ(vec2.size(), 3); vec1[0] = 7; EXPECT_EQ(vec1[0], 7); @@ -241,7 +241,7 @@ TEST(vector, Append) vec.append(3); vec.append(6); vec.append(7); - EXPECT_EQ(vec.size(), 3u); + EXPECT_EQ(vec.size(), 3); EXPECT_EQ(vec[0], 3); EXPECT_EQ(vec[1], 6); EXPECT_EQ(vec[2], 7); @@ -250,56 +250,33 @@ TEST(vector, Append) TEST(vector, AppendAndGetIndex) { Vector<int> vec; - EXPECT_EQ(vec.append_and_get_index(10), 0u); - EXPECT_EQ(vec.append_and_get_index(10), 1u); - EXPECT_EQ(vec.append_and_get_index(10), 2u); + EXPECT_EQ(vec.append_and_get_index(10), 0); + EXPECT_EQ(vec.append_and_get_index(10), 1); + EXPECT_EQ(vec.append_and_get_index(10), 2); vec.append(10); - EXPECT_EQ(vec.append_and_get_index(10), 4u); + EXPECT_EQ(vec.append_and_get_index(10), 4); } TEST(vector, AppendNonDuplicates) { Vector<int> vec; vec.append_non_duplicates(4); - EXPECT_EQ(vec.size(), 1u); + EXPECT_EQ(vec.size(), 1); vec.append_non_duplicates(5); - EXPECT_EQ(vec.size(), 2u); + EXPECT_EQ(vec.size(), 2); vec.append_non_duplicates(4); - EXPECT_EQ(vec.size(), 2u); + EXPECT_EQ(vec.size(), 2); } TEST(vector, ExtendNonDuplicates) { Vector<int> vec; vec.extend_non_duplicates({1, 2}); - EXPECT_EQ(vec.size(), 2u); + EXPECT_EQ(vec.size(), 2); vec.extend_non_duplicates({3, 4}); - EXPECT_EQ(vec.size(), 4u); + EXPECT_EQ(vec.size(), 4); vec.extend_non_duplicates({0, 1, 2, 3}); - EXPECT_EQ(vec.size(), 5u); -} - -TEST(vector, Fill) -{ - Vector<int> vec(5); - vec.fill(3); - EXPECT_EQ(vec.size(), 5u); - EXPECT_EQ(vec[0], 3); - EXPECT_EQ(vec[1], 3); - EXPECT_EQ(vec[2], 3); - EXPECT_EQ(vec[3], 3); - EXPECT_EQ(vec[4], 3); -} - -TEST(vector, FillIndices) -{ - Vector<int> vec(5, 0); - vec.fill_indices({1, 2}, 4); - EXPECT_EQ(vec[0], 0); - EXPECT_EQ(vec[1], 4); - EXPECT_EQ(vec[2], 4); - EXPECT_EQ(vec[3], 0); - EXPECT_EQ(vec[4], 0); + EXPECT_EQ(vec.size(), 5); } TEST(vector, Iterator) @@ -318,8 +295,8 @@ TEST(vector, BecomeLarge) for (int i = 0; i < 100; i++) { vec.append(i * 5); } - EXPECT_EQ(vec.size(), 100u); - for (uint i = 0; i < 100; i++) { + EXPECT_EQ(vec.size(), 100); + for (int i = 0; i < 100; i++) { EXPECT_EQ(vec[i], static_cast<int>(i * 5)); } } @@ -332,7 +309,7 @@ static Vector<int> return_by_value_helper() TEST(vector, ReturnByValue) { Vector<int> vec = return_by_value_helper(); - EXPECT_EQ(vec.size(), 3u); + EXPECT_EQ(vec.size(), 3); EXPECT_EQ(vec[0], 3); EXPECT_EQ(vec[1], 5); EXPECT_EQ(vec[2], 1); @@ -341,39 +318,26 @@ TEST(vector, ReturnByValue) TEST(vector, VectorOfVectors_Append) { Vector<Vector<int>> vec; - EXPECT_EQ(vec.size(), 0u); + EXPECT_EQ(vec.size(), 0); Vector<int> v({1, 2}); vec.append(v); vec.append({7, 8}); - EXPECT_EQ(vec.size(), 2u); + EXPECT_EQ(vec.size(), 2); EXPECT_EQ(vec[0][0], 1); EXPECT_EQ(vec[0][1], 2); EXPECT_EQ(vec[1][0], 7); EXPECT_EQ(vec[1][1], 8); } -TEST(vector, VectorOfVectors_Fill) -{ - Vector<Vector<int>> vec(3); - vec.fill({4, 5}); - - EXPECT_EQ(vec[0][0], 4); - EXPECT_EQ(vec[0][1], 5); - EXPECT_EQ(vec[1][0], 4); - EXPECT_EQ(vec[1][1], 5); - EXPECT_EQ(vec[2][0], 4); - EXPECT_EQ(vec[2][1], 5); -} - TEST(vector, RemoveLast) { Vector<int> vec = {5, 6}; - EXPECT_EQ(vec.size(), 2u); + EXPECT_EQ(vec.size(), 2); vec.remove_last(); - EXPECT_EQ(vec.size(), 1u); + EXPECT_EQ(vec.size(), 1); vec.remove_last(); - EXPECT_EQ(vec.size(), 0u); + EXPECT_EQ(vec.size(), 0); } TEST(vector, IsEmpty) @@ -415,7 +379,7 @@ TEST(vector, RemoveFirstOccurrenceAndReorder) vec.remove_first_occurrence_and_reorder(4); EXPECT_EQ(vec[0], 7); vec.remove_first_occurrence_and_reorder(7); - EXPECT_EQ(vec.size(), 0u); + EXPECT_EQ(vec.size(), 0); } TEST(vector, Remove) @@ -440,7 +404,7 @@ TEST(vector, ExtendSmallVector) Vector<int> a = {2, 3, 4}; Vector<int> b = {11, 12}; b.extend(a); - EXPECT_EQ(b.size(), 5u); + EXPECT_EQ(b.size(), 5); EXPECT_EQ(b[0], 11); EXPECT_EQ(b[1], 12); EXPECT_EQ(b[2], 2); @@ -455,7 +419,7 @@ TEST(vector, ExtendArray) Vector<int> a; a.extend(array, 2); - EXPECT_EQ(a.size(), 2u); + EXPECT_EQ(a.size(), 2); EXPECT_EQ(a[0], 3); EXPECT_EQ(a[1], 4); } @@ -471,7 +435,7 @@ TEST(vector, AppendNTimes) Vector<int> a; a.append_n_times(5, 3); a.append_n_times(2, 2); - EXPECT_EQ(a.size(), 5u); + EXPECT_EQ(a.size(), 5); EXPECT_EQ(a[0], 5); EXPECT_EQ(a[1], 5); EXPECT_EQ(a[2], 5); @@ -486,13 +450,13 @@ TEST(vector, UniquePtrValue) vec.append(std::unique_ptr<int>(new int())); vec.append(std::unique_ptr<int>(new int())); vec.append(std::unique_ptr<int>(new int())); - EXPECT_EQ(vec.size(), 4u); + EXPECT_EQ(vec.size(), 4); std::unique_ptr<int> &a = vec.last(); std::unique_ptr<int> b = vec.pop_last(); vec.remove_and_reorder(0); vec.remove(0); - EXPECT_EQ(vec.size(), 1u); + EXPECT_EQ(vec.size(), 1); UNUSED_VARS(a, b); } @@ -607,29 +571,29 @@ TEST(vector, Resize) { std::string long_string = "012345678901234567890123456789"; Vector<std::string> vec; - EXPECT_EQ(vec.size(), 0u); + EXPECT_EQ(vec.size(), 0); vec.resize(2); - EXPECT_EQ(vec.size(), 2u); + EXPECT_EQ(vec.size(), 2); EXPECT_EQ(vec[0], ""); EXPECT_EQ(vec[1], ""); vec.resize(5, long_string); - EXPECT_EQ(vec.size(), 5u); + EXPECT_EQ(vec.size(), 5); EXPECT_EQ(vec[0], ""); EXPECT_EQ(vec[1], ""); EXPECT_EQ(vec[2], long_string); EXPECT_EQ(vec[3], long_string); EXPECT_EQ(vec[4], long_string); vec.resize(1); - EXPECT_EQ(vec.size(), 1u); + EXPECT_EQ(vec.size(), 1); EXPECT_EQ(vec[0], ""); } TEST(vector, FirstIndexOf) { Vector<int> vec = {2, 3, 5, 7, 5, 9}; - EXPECT_EQ(vec.first_index_of(2), 0u); - EXPECT_EQ(vec.first_index_of(5), 2u); - EXPECT_EQ(vec.first_index_of(9), 5u); + EXPECT_EQ(vec.first_index_of(2), 0); + EXPECT_EQ(vec.first_index_of(5), 2); + EXPECT_EQ(vec.first_index_of(9), 5); } TEST(vector, FirstIndexTryOf) @@ -657,7 +621,19 @@ TEST(vector, ConstructVoidPointerVector) float b; double c; Vector<void *> vec = {&a, &b, &c}; - EXPECT_EQ(vec.size(), 3u); + EXPECT_EQ(vec.size(), 3); +} + +TEST(vector, Fill) +{ + Vector<int> vec(5); + vec.fill(3); + EXPECT_EQ(vec.size(), 5u); + EXPECT_EQ(vec[0], 3); + EXPECT_EQ(vec[1], 3); + EXPECT_EQ(vec[2], 3); + EXPECT_EQ(vec[3], 3); + EXPECT_EQ(vec[4], 3); } } // namespace blender diff --git a/tests/gtests/functions/FN_array_spans_test.cc b/tests/gtests/functions/FN_array_spans_test.cc index 6912a62ff17..6b7bb8429ff 100644 --- a/tests/gtests/functions/FN_array_spans_test.cc +++ b/tests/gtests/functions/FN_array_spans_test.cc @@ -50,7 +50,7 @@ TEST(virtual_array_span, MultipleArrayConstructor) std::array<int, 2> values1 = {6, 7}; std::array<int, 1> values2 = {8}; std::array<const int *, 3> starts = {values0.data(), values1.data(), values2.data()}; - std::array<uint, 3> sizes{values0.size(), values1.size(), values2.size()}; + std::array<int64_t, 3> sizes{values0.size(), values1.size(), values2.size()}; VArraySpan<int> span{starts, sizes}; EXPECT_EQ(span.size(), 3); diff --git a/tests/gtests/functions/FN_attributes_ref_test.cc b/tests/gtests/functions/FN_attributes_ref_test.cc index 0b0afdc210f..9c7cce83493 100644 --- a/tests/gtests/functions/FN_attributes_ref_test.cc +++ b/tests/gtests/functions/FN_attributes_ref_test.cc @@ -58,7 +58,7 @@ TEST(mutable_attributes_ref, ComplexTest) info_builder.add<std::string>("Name", "<no name>"); AttributesInfo info{info_builder}; - uint amount = 5; + int amount = 5; Array<float3> positions(amount); Array<uint> ids(amount, 0); Array<float> sizes(amount); diff --git a/tests/gtests/functions/FN_cpp_type_test.cc b/tests/gtests/functions/FN_cpp_type_test.cc index 78731f9c987..85fc1105c25 100644 --- a/tests/gtests/functions/FN_cpp_type_test.cc +++ b/tests/gtests/functions/FN_cpp_type_test.cc @@ -67,7 +67,7 @@ struct TestType { return false; } - uint32_t hash() const + uint64_t hash() const { return 0; } diff --git a/tests/gtests/functions/FN_multi_function_network_test.cc b/tests/gtests/functions/FN_multi_function_network_test.cc index 35af8300cfa..9f16b71bb10 100644 --- a/tests/gtests/functions/FN_multi_function_network_test.cc +++ b/tests/gtests/functions/FN_multi_function_network_test.cc @@ -78,7 +78,7 @@ class ConcatVectorsFunction : public MultiFunction { GVectorArrayRef<int> a = params.vector_mutable<int>(0); VArraySpan<int> b = params.readonly_vector_input<int>(1); - for (uint i : mask) { + for (int64_t i : mask) { a.extend(i, b[i]); } } @@ -98,7 +98,7 @@ class AppendFunction : public MultiFunction { GVectorArrayRef<int> vectors = params.vector_mutable<int>(0); VSpan<int> values = params.readonly_single_input<int>(1); - for (uint i : mask) { + for (int64_t i : mask) { vectors.append(i, values[i]); } } @@ -118,10 +118,10 @@ class SumVectorFunction : public MultiFunction { VArraySpan<int> vectors = params.readonly_vector_input<int>(0); MutableSpan<int> sums = params.uninitialized_single_output<int>(1); - for (uint i : mask) { + for (int64_t i : mask) { int sum = 0; VSpan<int> vector = vectors[i]; - for (uint j = 0; j < vector.size(); j++) { + for (int j = 0; j < vector.size(); j++) { sum += vector[j]; } sums[i] = sum; @@ -143,7 +143,7 @@ class CreateRangeFunction : public MultiFunction { VSpan<int> sizes = params.readonly_single_input<int>(0, "Size"); GVectorArrayRef<int> ranges = params.vector_output<int>(1, "Range"); - for (int i : mask) { + for (int64_t i : mask) { int size = sizes[i]; for (int j : IndexRange(size)) { ranges.append(i, j); diff --git a/tests/gtests/functions/FN_multi_function_test.cc b/tests/gtests/functions/FN_multi_function_test.cc index 66039e463ed..8b5fb060c36 100644 --- a/tests/gtests/functions/FN_multi_function_test.cc +++ b/tests/gtests/functions/FN_multi_function_test.cc @@ -23,7 +23,7 @@ class AddFunction : public MultiFunction { VSpan<int> b = params.readonly_single_input<int>(1, "B"); MutableSpan<int> result = params.uninitialized_single_output<int>(2, "Result"); - for (uint i : mask) { + for (int64_t i : mask) { result[i] = a[i] + b[i]; } } @@ -65,7 +65,7 @@ class AddPrefixFunction : public MultiFunction { VSpan<std::string> prefixes = params.readonly_single_input<std::string>(0, "Prefix"); MutableSpan<std::string> strings = params.single_mutable<std::string>(1, "Strings"); - for (uint i : mask) { + for (int64_t i : mask) { strings[i] = prefixes[i] + strings[i]; } } @@ -112,7 +112,7 @@ class CreateRangeFunction : public MultiFunction { VSpan<uint> sizes = params.readonly_single_input<uint>(0, "Size"); GVectorArrayRef<uint> ranges = params.vector_output<uint>(1, "Range"); - for (uint i : mask) { + for (int64_t i : mask) { uint size = sizes[i]; for (uint j : IndexRange(size)) { ranges.append(i, j); @@ -164,7 +164,7 @@ class GenericAppendFunction : public MultiFunction { GVectorArray &vectors = params.vector_mutable(0, "Vector"); GVSpan values = params.readonly_single_input(1, "Value"); - for (uint i : mask) { + for (int64_t i : mask) { vectors.append(i, values[i]); } } @@ -355,7 +355,7 @@ TEST(multi_function, CustomMF_GenericConstantArray) EXPECT_EQ(vector_array[1].size(), 4); EXPECT_EQ(vector_array[2].size(), 4); EXPECT_EQ(vector_array[3].size(), 4); - for (uint i = 1; i < 4; i++) { + for (int i = 1; i < 4; i++) { EXPECT_EQ(vector_array[i][0], 3); EXPECT_EQ(vector_array[i][1], 4); EXPECT_EQ(vector_array[i][2], 5); |