Merge branch 'blender-v5.2-release'

This commit is contained in:
Brecht Van Lommel 2026-06-09 20:36:44 +02:00
commit 80c05b2640
14 changed files with 90 additions and 91 deletions

View file

@ -28,30 +28,18 @@
CCL_NAMESPACE_BEGIN
#ifdef _WIN32
double time_dt()
{
__int64 frequency, counter;
QueryPerformanceFrequency((LARGE_INTEGER *)&frequency);
QueryPerformanceCounter((LARGE_INTEGER *)&counter);
return (double)counter / (double)frequency;
return std::chrono::duration<double>(std::chrono::steady_clock::now().time_since_epoch())
.count();
}
#ifdef _WIN32
void time_sleep(const double t)
{
Sleep((int)(t * 1000));
}
#else
double time_dt()
{
struct timeval now;
gettimeofday(&now, nullptr);
return now.tv_sec + now.tv_usec * 1e-6;
}
/* sleep t seconds */
void time_sleep(double t)
{

View file

@ -81,7 +81,7 @@ struct ImageRuntime {
short gpu_layer = IMAGE_GPU_LAYER_NONE;
short gpu_view = IMAGE_GPU_VIEW_NONE;
int lastused = 0;
int64_t lastused = 0;
/** Register containing partial updates. */
PartialUpdateRegister *partial_update_register = nullptr;

View file

@ -632,8 +632,8 @@ void BKE_image_free_anim_gputextures(Main *bmain)
void BKE_image_free_old_gputextures(Main *bmain)
{
static int lasttime = 0;
int ctime = int(BLI_time_now_seconds());
static int64_t lasttime = 0;
int64_t ctime = BLI_time_now_seconds_i();
/*
* Run garbage collector once for every collecting period of time

View file

@ -9,16 +9,18 @@
#pragma once
#include <cstdint>
namespace blender {
/**
* Return an indication of time, expressed as seconds since some fixed point.
* Successive calls are guaranteed to generate values greater than or equal to the last call.
*/
extern double BLI_time_now_seconds();
double BLI_time_now_seconds();
/** `int` version of #BLI_time_now_seconds. */
extern long int BLI_time_now_seconds_i();
/** Integer version of #BLI_time_now_seconds. */
int64_t BLI_time_now_seconds_i();
/**
* Platform-independent sleep function.

View file

@ -8,58 +8,40 @@
#include "BLI_time.h"
#include <chrono>
#ifdef WIN32
# include <cmath>
# include <cstdio>
# include <windows.h>
/* timeapi.h needs to be included after windows.h. */
# include <timeapi.h>
#else
# include <thread>
# include <unistd.h>
#endif
namespace blender {
double BLI_time_now_seconds()
{
static int hasperfcounter = -1; /* (-1 == unknown) */
static double perffreq;
if (hasperfcounter == -1) {
__int64 ifreq;
hasperfcounter = QueryPerformanceFrequency((LARGE_INTEGER *)&ifreq);
perffreq = double(ifreq);
}
if (hasperfcounter) {
__int64 count;
QueryPerformanceCounter((LARGE_INTEGER *)&count);
return count / perffreq;
}
else {
static double accum = 0.0;
static int ltick = 0;
int ntick = GetTickCount();
if (ntick < ltick) {
accum += (0xFFFFFFFF - ltick + ntick) / 1000.0;
}
else {
accum += (ntick - ltick) / 1000.0;
}
ltick = ntick;
return accum;
}
return std::chrono::duration<double>(std::chrono::steady_clock::now().time_since_epoch())
.count();
}
long int BLI_time_now_seconds_i()
int64_t BLI_time_now_seconds_i()
{
return (long int)BLI_time_now_seconds();
return std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
}
#ifdef WIN32
void BLI_time_sleep_ms(int ms)
{
Sleep(ms);
@ -104,32 +86,8 @@ void BLI_time_sleep_precise_us(int us)
CloseHandle(timerHandle);
}
} // namespace blender
#else
# include <chrono>
# include <thread>
# include <unistd.h>
namespace blender {
double BLI_time_now_seconds()
{
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return double(ts.tv_sec) + (ts.tv_nsec / 1000000000.0);
}
long int BLI_time_now_seconds_i()
{
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
/* `tv_nsec` is in [0, 999999999], always less than one second, so it never carries. */
return ts.tv_sec;
}
void BLI_time_sleep_ms(int ms)
{
if (ms >= 1000) {
@ -145,6 +103,6 @@ void BLI_time_sleep_precise_us(int us)
std::this_thread::sleep_for(std::chrono::microseconds(us));
}
} // namespace blender
#endif
} // namespace blender

View file

@ -621,7 +621,7 @@ inline char but_pointer_bit_max_index(ButPointerType pointer_type)
/** Deduce the #ButPointerType matching \a T. */
template<typename T> constexpr ButPointerType but_pointer_type_for()
{
constexpr ButPointerType ptr_type = (std::is_floating_point_v<T>) ?
constexpr ButPointerType ptr_type = (std::is_same_v<T, float>) ?
ButPointerType::Float :
(std::is_integral_v<T> || std::is_enum_v<T>) ?
(sizeof(T) == 1) ? ButPointerType::Char :

View file

@ -27,6 +27,7 @@
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
#include "BKE_callbacks.hh"
#include "BKE_colortools.hh"
#include "BKE_compositor.hh"
#include "BKE_context.hh"
@ -528,6 +529,8 @@ static void image_renderinfo_cb(void *rjv, RenderStats *rs)
RE_ReleaseResult(rj->re);
BKE_callback_exec_string(G_MAIN, rs->infostr, BKE_CB_EVT_RENDER_STATS);
/* make jobs timer to send notifier */
*(rj->do_update) = true;
}

View file

@ -1095,8 +1095,12 @@ void transform_convert_mesh_connectivity_distance(BMesh *bm,
* - Edge itself is loose
* - Edge has vertex that was originally selected
* In all these cases a direct distance along the edge is accurate and
* required to make sure we visit all edges. Other edges are handled by
* propagation across edges below. */
* required to make sure we visit all edges.
*
* Additionally re-add edges whose other vertex already has a known
* distance, so that propagation across their adjacent faces can happen
* now that this vertex distance is known too. Other edges are handled
* by propagation across edges below. */
const bool need_direct_distance = BM_elem_flag_test(e, tag_loose) ||
BM_elem_flag_test(v1, BM_ELEM_SELECT) ||
BM_elem_flag_test(v2, BM_ELEM_SELECT);
@ -1105,7 +1109,8 @@ void transform_convert_mesh_connectivity_distance(BMesh *bm,
BM_ITER_ELEM (e_other, &eiter, v2, BM_EDGES_OF_VERT) {
if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 &&
!BM_elem_flag_test(e_other, BM_ELEM_HIDDEN) &&
(need_direct_distance || BM_elem_flag_test(e_other, tag_loose)))
(need_direct_distance || BM_elem_flag_test(e_other, tag_loose) ||
dists[BM_elem_index_get(BM_edge_other_vert(e_other, v2))] != FLT_MAX))
{
BM_elem_flag_enable(e_other, tag_queued);
BLI_LINKSTACK_PUSH(queue_next, e_other);

View file

@ -290,7 +290,9 @@ void IMB_ensure_host_buffer(ImBuf *ibuf)
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
float *output_buffer = static_cast<float *>(
GPU_texture_read(ibuf->gpu.texture, GPU_DATA_FLOAT, 0));
const ColorSpace *float_colorspace = ibuf->float_buffer.colorspace;
ibuf->assign_float_data(output_buffer);
ibuf->float_buffer.colorspace = float_colorspace;
if (need_secondary_context) {
IMB_deactivate_gpu_context();

View file

@ -474,12 +474,17 @@ void IMB_crop(ImBuf *ibuf, const int2 &rect_pos, const int2 &rect_size)
return;
}
const ColorSpace *byte_colorspace = ibuf->byte_buffer.colorspace;
const ColorSpace *float_colorspace = ibuf->float_buffer.colorspace;
if (const uchar *byte_data = ibuf->byte_data()) {
ibuf->assign_byte_data(create_cropped_buffer(byte_data, src_size, rect_pos, rect_size));
ibuf->byte_buffer.colorspace = byte_colorspace;
}
if (const float *float_data = ibuf->float_data()) {
ibuf->assign_float_data(
create_cropped_buffer(float_data, src_size, ibuf->channels, rect_pos, rect_size));
ibuf->float_buffer.colorspace = float_colorspace;
}
ibuf->x = rect_size.x;

View file

@ -66,6 +66,9 @@ bool IMB_rotate_orthogonal(ImBuf *ibuf, int degrees)
const int size_x = ibuf->x;
const int size_y = ibuf->y;
const ColorSpace *float_colorspace = ibuf->float_buffer.colorspace;
const ColorSpace *byte_colorspace = ibuf->byte_buffer.colorspace;
if (ELEM(degrees, 90, 270)) {
std::swap(ibuf->x, ibuf->y);
}
@ -76,6 +79,7 @@ bool IMB_rotate_orthogonal(ImBuf *ibuf, int degrees)
size_t(channels) * size_t(size_x) * size_t(size_y), __func__);
rotate_pixels<float>(degrees, size_x, size_y, src_pixels, dst_pixels, ibuf->channels);
ibuf->assign_float_data(dst_pixels);
ibuf->float_buffer.colorspace = float_colorspace;
if (ibuf->byte_data()) {
IMB_byte_from_float(ibuf);
}
@ -86,6 +90,7 @@ bool IMB_rotate_orthogonal(ImBuf *ibuf, int degrees)
__func__);
rotate_pixels<uchar>(degrees, size_x, size_y, src_pixels, dst_pixels, 4);
ibuf->assign_byte_data(dst_pixels);
ibuf->byte_buffer.colorspace = byte_colorspace;
}
return true;

View file

@ -460,6 +460,9 @@ bool IMB_scale(ImBuf *ibuf, const int2 new_size, IMBScaleFilter filter, bool thr
return false;
}
const ColorSpace *float_colorspace = ibuf->float_buffer.colorspace;
const ColorSpace *byte_colorspace = ibuf->byte_buffer.colorspace;
switch (filter) {
case IMBScaleFilter::Nearest: {
if (const float *src = ibuf->float_data()) {
@ -507,6 +510,8 @@ bool IMB_scale(ImBuf *ibuf, const int2 new_size, IMBScaleFilter filter, bool thr
break;
}
}
ibuf->float_buffer.colorspace = float_colorspace;
ibuf->byte_buffer.colorspace = byte_colorspace;
ibuf->x = new_size.x;
ibuf->y = new_size.y;
return true;

View file

@ -310,10 +310,28 @@ static int rna_find_parsed_struct_index(const StringRef structname)
return -1;
}
static const void *rna_default_data(const int struct_idx,
const int member_idx,
const void *base_default_data)
{
const void *member_default_data = DNA_member_default_table[struct_idx][member_idx];
if (base_default_data) {
/* For a nested member, offset into the parent struct's default instance. */
const void *struct_default_base = DNA_member_default_table[struct_idx][0];
return POINTER_OFFSET(base_default_data,
static_cast<const char *>(member_default_data) -
static_cast<const char *>(struct_default_base));
}
return member_default_data;
}
/** Find DNA type info, recursively following `.` and `->`. */
static bool rna_find_sdna_member(const StringRef structname,
const StringRef path,
PropertyDefRNA *r_dp = nullptr)
PropertyDefRNA *r_dp = nullptr,
const void *base_default_data = nullptr)
{
const int struct_idx = rna_find_parsed_struct_index(structname);
if (struct_idx == -1) {
@ -341,7 +359,7 @@ static bool rna_find_sdna_member(const StringRef structname,
for (int b = 0; pm.member_name[b] == '*'; b++) {
r_dp->dnapointerlevel++;
}
r_dp->dnadefaultdata = DNA_member_default_table[struct_idx][member_idx];
r_dp->dnadefaultdata = rna_default_data(struct_idx, member_idx, base_default_data);
}
return true;
}
@ -357,7 +375,12 @@ static bool rna_find_sdna_member(const StringRef structname,
continue;
}
rna_find_sdna_member(pm.type_name, remainder, r_dp);
/* The return value for nested structs is ignored, to allow recursing into
* runtime structs not covered by DNA. */
rna_find_sdna_member(pm.type_name,
remainder,
r_dp,
rna_default_data(struct_idx, member_idx, base_default_data));
return true;
}

View file

@ -190,12 +190,14 @@ static bool default_break(void * /*arg*/)
return G.is_break == true;
}
static void stats_update(void * /*arg*/, RenderStats *rs)
static void stats_update(void *arg, RenderStats *rs)
{
if (rs->infostr == nullptr) {
return;
}
Render *re = static_cast<Render *>(arg);
/* Compositor calls this from multiple threads, mutex lock to ensure we don't
* get garbled output. */
static Mutex mutex;
@ -212,7 +214,7 @@ static void stats_update(void * /*arg*/, RenderStats *rs)
/* NOTE: using G_MAIN seems valid here???
* Not sure it's actually even used anyway, we could as well pass nullptr? */
BKE_callback_exec_string(G_MAIN, rs->infostr, BKE_CB_EVT_RENDER_STATS);
render_callback_exec_string(re, G_MAIN, BKE_CB_EVT_RENDER_STATS, rs->infostr);
if (show_info) {
fflush(stdout);
@ -944,6 +946,7 @@ void RE_display_init(Render *re)
re->display->progress_cb = float_nothing;
re->display->test_break_cb = default_break;
re->display->stats_draw_cb = stats_update;
re->display->sdh = re;
}
void RE_display_ensure_gpu_context(Render *re)