Blender V4.3
path_trace_display.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
6
7#include "session/buffers.h"
8
9#include "util/log.h"
10
12
13PathTraceDisplay::PathTraceDisplay(unique_ptr<DisplayDriver> driver) : driver_(std::move(driver))
14{
15}
16
17void PathTraceDisplay::reset(const BufferParams &buffer_params, const bool reset_rendering)
18{
20
21 params_.full_offset = make_int2(buffer_params.full_x + buffer_params.window_x,
22 buffer_params.full_y + buffer_params.window_y);
23 params_.full_size = make_int2(buffer_params.full_width, buffer_params.full_height);
24 params_.size = make_int2(buffer_params.window_width, buffer_params.window_height);
25
26 texture_state_.is_outdated = true;
27
28 if (!reset_rendering) {
29 driver_->next_tile_begin();
30 }
31}
32
33void PathTraceDisplay::mark_texture_updated()
34{
35 texture_state_.is_outdated = false;
36}
37
38/* --------------------------------------------------------------------
39 * Update procedure.
40 */
41
42bool PathTraceDisplay::update_begin(int texture_width, int texture_height)
43{
44 DCHECK(!update_state_.is_active);
45
46 if (update_state_.is_active) {
47 LOG(ERROR) << "Attempt to re-activate update process.";
48 return false;
49 }
50
51 /* Get parameters within a mutex lock, to avoid reset() modifying them at the same time.
52 * The update itself is non-blocking however, for better performance and to avoid
53 * potential deadlocks due to locks held by the subclass. */
55 {
57 params = params_;
58 texture_state_.size = make_int2(texture_width, texture_height);
59 }
60
61 if (!driver_->update_begin(params, texture_width, texture_height)) {
62 LOG(ERROR) << "PathTraceDisplay implementation could not begin update.";
63 return false;
64 }
65
66 update_state_.is_active = true;
67
68 return true;
69}
70
72{
73 DCHECK(update_state_.is_active);
74
75 if (!update_state_.is_active) {
76 LOG(ERROR) << "Attempt to deactivate inactive update process.";
77 return;
78 }
79
80 driver_->update_end();
81
82 update_state_.is_active = false;
83}
84
86{
87 return texture_state_.size;
88}
89
90/* --------------------------------------------------------------------
91 * Texture update from CPU buffer.
92 */
93
95 const half4 *rgba_pixels, int texture_x, int texture_y, int pixels_width, int pixels_height)
96{
97 DCHECK(update_state_.is_active);
98
99 if (!update_state_.is_active) {
100 LOG(ERROR) << "Attempt to copy pixels data outside of PathTraceDisplay update.";
101 return;
102 }
103
104 mark_texture_updated();
105
106 /* This call copies pixels to a mapped texture buffer which is typically much cheaper from CPU
107 * time point of view than to copy data directly to a texture.
108 *
109 * The possible downside of this approach is that it might require a higher peak memory when
110 * doing partial updates of the texture (although, in practice even partial updates might peak
111 * with a full-frame buffer stored on the CPU if the GPU is currently occupied). */
112 half4 *mapped_rgba_pixels = map_texture_buffer();
113 if (!mapped_rgba_pixels) {
114 return;
115 }
116
117 const int texture_width = texture_state_.size.x;
118 const int texture_height = texture_state_.size.y;
119
120 if (texture_x == 0 && texture_y == 0 && pixels_width == texture_width &&
121 pixels_height == texture_height)
122 {
123 const size_t size_in_bytes = sizeof(half4) * texture_width * texture_height;
124 memcpy(mapped_rgba_pixels, rgba_pixels, size_in_bytes);
125 }
126 else {
127 const half4 *rgba_row = rgba_pixels;
128 half4 *mapped_rgba_row = mapped_rgba_pixels + texture_y * texture_width + texture_x;
129 for (int y = 0; y < pixels_height;
130 ++y, rgba_row += pixels_width, mapped_rgba_row += texture_width)
131 {
132 memcpy(mapped_rgba_row, rgba_row, sizeof(half4) * pixels_width);
133 }
134 }
135
137}
138
139/* --------------------------------------------------------------------
140 * Texture buffer mapping.
141 */
142
144{
145 DCHECK(!texture_buffer_state_.is_mapped);
146 DCHECK(update_state_.is_active);
147
148 if (texture_buffer_state_.is_mapped) {
149 LOG(ERROR) << "Attempt to re-map an already mapped texture buffer.";
150 return nullptr;
151 }
152
153 if (!update_state_.is_active) {
154 LOG(ERROR) << "Attempt to copy pixels data outside of PathTraceDisplay update.";
155 return nullptr;
156 }
157
158 half4 *mapped_rgba_pixels = driver_->map_texture_buffer();
159
160 if (mapped_rgba_pixels) {
161 texture_buffer_state_.is_mapped = true;
162 }
163
164 return mapped_rgba_pixels;
165}
166
168{
169 DCHECK(texture_buffer_state_.is_mapped);
170
171 if (!texture_buffer_state_.is_mapped) {
172 LOG(ERROR) << "Attempt to unmap non-mapped texture buffer.";
173 return;
174 }
175
176 texture_buffer_state_.is_mapped = false;
177
178 mark_texture_updated();
179 driver_->unmap_texture_buffer();
180}
181
182/* --------------------------------------------------------------------
183 * Graphics interoperability.
184 */
185
187{
188 DCHECK(!texture_buffer_state_.is_mapped);
189 DCHECK(update_state_.is_active);
190
191 if (texture_buffer_state_.is_mapped) {
192 LOG(ERROR)
193 << "Attempt to use graphics interoperability mode while the texture buffer is mapped.";
195 }
196
197 if (!update_state_.is_active) {
198 LOG(ERROR) << "Attempt to use graphics interoperability outside of PathTraceDisplay update.";
200 }
201
202 /* Assume that interop will write new values to the texture. */
203 mark_texture_updated();
204
205 return driver_->graphics_interop_get();
206}
207
209{
210 driver_->graphics_interop_activate();
211}
212
214{
215 driver_->graphics_interop_deactivate();
216}
217
218/* --------------------------------------------------------------------
219 * Drawing.
220 */
221
223{
224 driver_->clear();
225}
226
228{
229 /* Get parameters within a mutex lock, to avoid reset() modifying them at the same time.
230 * The drawing itself is non-blocking however, for better performance and to avoid
231 * potential deadlocks due to locks held by the subclass. */
233 bool is_outdated;
234
235 {
236 thread_scoped_lock lock(mutex_);
237 params = params_;
238 is_outdated = texture_state_.is_outdated;
239 }
240
241 driver_->draw(params);
242
243 return !is_outdated;
244}
245
247{
248 driver_->flush();
249}
250
volatile int lock
int full_width
Definition buffers.h:87
int window_y
Definition buffers.h:80
int full_height
Definition buffers.h:88
int window_height
Definition buffers.h:82
int window_width
Definition buffers.h:81
int window_x
Definition buffers.h:79
void reset(const BufferParams &buffer_params, bool reset_rendering)
int2 get_texture_size() const
PathTraceDisplay(unique_ptr< DisplayDriver > driver)
DisplayDriver::GraphicsInterop graphics_interop_get()
bool update_begin(int texture_width, int texture_height)
void copy_pixels_to_texture(const half4 *rgba_pixels, int texture_x, int texture_y, int pixels_width, int pixels_height)
#define CCL_NAMESPACE_END
ccl_device_forceinline int2 make_int2(const int x, const int y)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define DCHECK(expression)
Definition log.h:51
#define LOG(severity)
Definition log.h:33
Definition half.h:61
std::unique_lock< std::mutex > thread_scoped_lock
Definition thread.h:30