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