Blender V4.3
scene_fps.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cmath>
12
13#include "BLI_math_base.h"
14
15#include "DNA_scene_types.h"
16
17#include "ED_scene.hh"
18
19#include "MEM_guardedalloc.h"
20
23
29#define FIXED_UNIT FrameSampleT(65535)
30
32// #define USE_DEBUG_REPORT_ERROR_MARGIN
33
36#ifdef USE_DEBUG_REPORT_ERROR_MARGIN
37 double value_db;
38#endif
39};
40
45 double time_curr;
46 double time_prev;
47
48#ifdef USE_DEBUG_REPORT_ERROR_MARGIN
49 double error_sum;
50 int error_samples;
51#endif
52
55
60
64
66
69};
70
72{
73 if (scene->fps_info == nullptr) {
74 return;
75 }
76
77#ifndef NDEBUG
78 /* Assert this value has not somehow become out of sync as this would mean
79 * the reported frame-rate would be wrong. */
80 ScreenFrameRateInfo *fpsi = static_cast<ScreenFrameRateInfo *>(scene->fps_info);
81 FrameSumT times_fps_sum_cmp = 0;
82 for (int i = 0; i < fpsi->times_fps_num_set; i++) {
83 times_fps_sum_cmp += fpsi->times_fps[i].value;
84 }
85 BLI_assert(fpsi->times_fps_sum == times_fps_sum_cmp);
86#endif /* !NDEBUG */
87
88 MEM_freeN(scene->fps_info);
89 scene->fps_info = nullptr;
90}
91
92void ED_scene_fps_average_accumulate(Scene *scene, const short fps_samples, const double ltime)
93{
94 const float fps_target = float(FPS);
95 const int times_fps_num = (fps_samples > 0) ? fps_samples : max_ii(1, int(ceilf(fps_target)));
96
97 ScreenFrameRateInfo *fpsi = static_cast<ScreenFrameRateInfo *>(scene->fps_info);
98 if (fpsi) {
99 /* Reset when the target FPS changes.
100 * Needed redraw times from when a different FPS was set do not contribute
101 * to an average that is over/under the new target. */
102 if ((fpsi->fps_target != fps_target) || (fpsi->times_fps_num != times_fps_num)) {
103 MEM_freeN(fpsi);
104 fpsi = nullptr;
105 scene->fps_info = nullptr;
106 }
107 }
108
109 /* If there isn't any info, initialize it first. */
110 if (fpsi == nullptr) {
111 scene->fps_info = MEM_callocN(
112 sizeof(ScreenFrameRateInfo) + (sizeof(FrameSample) * times_fps_num), __func__);
113 fpsi = static_cast<ScreenFrameRateInfo *>(scene->fps_info);
114 fpsi->fps_target = fps_target;
115 fpsi->times_fps_num = times_fps_num;
116 fpsi->times_fps_num_set = 0;
117
118 /* Use 100 for 2 decimal places (currently used for FPS display), could be configurable. */
119 const double decimal_places = 100.0;
120 fpsi->fps_target_is_fractional = std::round(fps_target) !=
121 (std::round(fps_target * decimal_places) / decimal_places);
122 }
123
124 /* Update the values. */
125 fpsi->time_curr = fpsi->time_prev;
126 fpsi->time_prev = ltime;
127
128 /* Mark as outdated. */
129 fpsi->fps_average = -1.0f;
130}
131
133{
134 ScreenFrameRateInfo *fpsi = static_cast<ScreenFrameRateInfo *>(scene->fps_info);
135 if (fpsi == nullptr) {
136 return false;
137 }
138
139 if (fpsi->time_prev == 0.0 || fpsi->time_curr == 0.0) {
140 /* The user should never see this. */
141 fpsi->fps_average = -1.0f;
142 return false;
143 }
144
145 if (fpsi->fps_average == -1.0) {
146 /* Doing an average for a more robust calculation. */
147 if (fpsi->times_fps_index >= fpsi->times_fps_num) {
148 fpsi->times_fps_index = 0;
149 }
150
151 const double fps_sample = 1.0 / (fpsi->time_prev - fpsi->time_curr);
152
153 {
154 const FrameSampleT fps_prev = (fpsi->times_fps_num_set == fpsi->times_fps_num) ?
155 fpsi->times_fps[fpsi->times_fps_index].value :
156 FrameSampleT(0);
157 const double fps_curr_db = std::round(fps_sample * double(FIXED_UNIT));
158 BLI_assert(fps_curr_db >= 0.0f);
159 const FrameSampleT fps_curr = FrameSampleT(fps_curr_db);
160 fpsi->times_fps[fpsi->times_fps_index].value = fps_curr;
161 fpsi->times_fps_sum -= fps_prev;
162 fpsi->times_fps_sum += fps_curr;
163 }
164#ifdef USE_DEBUG_REPORT_ERROR_MARGIN
165 fpsi->times_fps[fpsi->times_fps_index].value_db = fps_sample;
166#endif
167
168 fpsi->times_fps_index++;
169 if (fpsi->times_fps_index > fpsi->times_fps_num_set) {
171 }
172 BLI_assert(fpsi->times_fps_num_set > 0);
173
174 fpsi->fps_average = float((double(fpsi->times_fps_sum) / double(fpsi->times_fps_num_set)) /
175 FIXED_UNIT);
176
177#ifdef USE_DEBUG_REPORT_ERROR_MARGIN
178 {
179 double fps_average_ref = 0.0f;
180 for (int i = 0; i < fpsi->times_fps_num_set; i++) {
181 fps_average_ref += fpsi->times_fps[i].value_db;
182 }
183 fps_average_ref = float(fps_average_ref / double(fpsi->times_fps_num_set));
184
185 const float error = float(fps_average_ref) - fpsi->fps_average;
186 fpsi->error_sum += error;
187 fpsi->error_samples += 1;
188 if ((fpsi->error_samples % 100) == 0) {
189 printf("%s error: %.16f over %d samples (average %.16f)\n",
190 __func__,
191 fpsi->error_sum,
192 fpsi->error_samples,
193 fpsi->error_sum / double(fpsi->error_samples));
194 }
195 }
196#endif /* USE_DEBUG_REPORT_ERROR_MARGIN */
197 }
198
199 r_state->fps_average = fpsi->fps_average;
200 r_state->fps_target = fpsi->fps_target;
202 return true;
203}
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE int max_ii(int a, int b)
#define FPS
Read Guarded memory(de)allocation.
#define printf
#define ceilf(x)
draw_view in_light_buf[] float
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static void error(const char *str)
void ED_scene_fps_average_clear(Scene *scene)
Definition scene_fps.cc:71
uint32_t FrameSampleT
Definition scene_fps.cc:21
#define FIXED_UNIT
Definition scene_fps.cc:29
bool ED_scene_fps_average_calc(const Scene *scene, SceneFPS_State *r_state)
Definition scene_fps.cc:132
void ED_scene_fps_average_accumulate(Scene *scene, const short fps_samples, const double ltime)
Definition scene_fps.cc:92
uint64_t FrameSumT
Definition scene_fps.cc:22
unsigned int uint32_t
Definition stdint.h:80
unsigned __int64 uint64_t
Definition stdint.h:90
FrameSampleT value
Definition scene_fps.cc:35
bool fps_target_is_fractional
Definition ED_scene.hh:51
float fps_average
Definition ED_scene.hh:49
float fps_target
Definition ED_scene.hh:50
bool fps_target_is_fractional
Definition scene_fps.cc:54
FrameSumT times_fps_sum
Definition scene_fps.cc:65
FrameSample times_fps[0]
Definition scene_fps.cc:68