Blender  V3.3
buffers.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include <stdlib.h>
5 
6 #include "device/device.h"
7 #include "session/buffers.h"
8 
9 #include "util/foreach.h"
10 #include "util/hash.h"
11 #include "util/math.h"
12 #include "util/time.h"
13 #include "util/types.h"
14 
16 
17 /* --------------------------------------------------------------------
18  * Convert part information to an index of `BufferParams::pass_offset_`.
19  */
20 
21 static int pass_type_mode_to_index(PassType pass_type, PassMode mode)
22 {
23  int index = static_cast<int>(pass_type) * 2;
24 
25  if (mode == PassMode::DENOISED) {
26  ++index;
27  }
28 
29  return index;
30 }
31 
32 static int pass_to_index(const BufferPass &pass)
33 {
34  return pass_type_mode_to_index(pass.type, pass.mode);
35 }
36 
37 /* --------------------------------------------------------------------
38  * Buffer pass.
39  */
40 
42 {
43  NodeType *type = NodeType::add("buffer_pass", create);
44 
45  const NodeEnum *pass_type_enum = Pass::get_type_enum();
46  const NodeEnum *pass_mode_enum = Pass::get_mode_enum();
47 
48  SOCKET_ENUM(type, "Type", *pass_type_enum, PASS_COMBINED);
49  SOCKET_ENUM(mode, "Mode", *pass_mode_enum, static_cast<int>(PassMode::DENOISED));
50  SOCKET_STRING(name, "Name", ustring());
51  SOCKET_BOOLEAN(include_albedo, "Include Albedo", false);
52  SOCKET_STRING(lightgroup, "Light Group", ustring());
53 
54  SOCKET_INT(offset, "Offset", -1);
55 
56  return type;
57 }
58 
59 BufferPass::BufferPass() : Node(get_node_type())
60 {
61 }
62 
63 BufferPass::BufferPass(const Pass *scene_pass)
64  : Node(get_node_type()),
65  type(scene_pass->get_type()),
66  mode(scene_pass->get_mode()),
67  name(scene_pass->get_name()),
68  include_albedo(scene_pass->get_include_albedo()),
69  lightgroup(scene_pass->get_lightgroup())
70 {
71 }
72 
74 {
75  return Pass::get_info(type, include_albedo, !lightgroup.empty());
76 }
77 
78 /* --------------------------------------------------------------------
79  * Buffer Params.
80  */
81 
83 {
84  NodeType *type = NodeType::add("buffer_params", create);
85 
86  SOCKET_INT(width, "Width", 0);
87  SOCKET_INT(height, "Height", 0);
88 
89  SOCKET_INT(window_x, "Window X", 0);
90  SOCKET_INT(window_y, "Window Y", 0);
91  SOCKET_INT(window_width, "Window Width", 0);
92  SOCKET_INT(window_height, "Window Height", 0);
93 
94  SOCKET_INT(full_x, "Full X", 0);
95  SOCKET_INT(full_y, "Full Y", 0);
96  SOCKET_INT(full_width, "Full Width", 0);
97  SOCKET_INT(full_height, "Full Height", 0);
98 
99  SOCKET_STRING(layer, "Layer", ustring());
100  SOCKET_STRING(view, "View", ustring());
101  SOCKET_INT(samples, "Samples", 0);
102  SOCKET_FLOAT(exposure, "Exposure", 1.0f);
103  SOCKET_BOOLEAN(use_approximate_shadow_catcher, "Use Approximate Shadow Catcher", false);
104  SOCKET_BOOLEAN(use_transparent_background, "Transparent Background", false);
105 
106  /* Notes:
107  * - Skip passes since they do not follow typical container socket definition.
108  * Might look into covering those as a socket in the future.
109  *
110  * - Skip offset, stride, and pass stride since those can be delivered from the passes and
111  * rest of the sockets. */
112 
113  return type;
114 }
115 
116 BufferParams::BufferParams() : Node(get_node_type())
117 {
119 }
120 
122 {
125 
126  pass_stride = 0;
127  for (const BufferPass &pass : passes) {
128  if (pass.offset != PASS_UNUSED) {
129  const int index = pass_to_index(pass);
130  if (pass_offset_[index] == PASS_UNUSED) {
131  pass_offset_[index] = pass_stride;
132  }
133 
134  pass_stride += pass.get_info().num_components;
135  }
136  }
137 }
138 
140 {
141  passes.clear();
142 
143  pass_stride = 0;
144  for (const Pass *scene_pass : scene_passes) {
145  BufferPass buffer_pass(scene_pass);
146 
147  if (scene_pass->is_written()) {
148  buffer_pass.offset = pass_stride;
149  pass_stride += scene_pass->get_info().num_components;
150  }
151  else {
152  buffer_pass.offset = PASS_UNUSED;
153  }
154 
155  passes.emplace_back(std::move(buffer_pass));
156  }
157 
158  update_passes();
159 }
160 
162 {
163  for (int i = 0; i < kNumPassOffsets; ++i) {
165  }
166 }
167 
169 {
170  if (pass_type == PASS_NONE) {
171  return PASS_UNUSED;
172  }
173 
174  const int index = pass_type_mode_to_index(pass_type, mode);
175  return pass_offset_[index];
176 }
177 
178 const BufferPass *BufferParams::find_pass(string_view name) const
179 {
180  for (const BufferPass &pass : passes) {
181  if (pass.name == name) {
182  return &pass;
183  }
184  }
185 
186  return nullptr;
187 }
188 
190 {
191  for (const BufferPass &pass : passes) {
192  if (pass.type == type && pass.mode == mode) {
193  return &pass;
194  }
195  }
196 
197  return nullptr;
198 }
199 
201 {
202  const BufferPass *pass = find_pass(type, mode);
203  return get_actual_display_pass(pass);
204 }
205 
207 {
208  if (!pass) {
209  return nullptr;
210  }
211 
212  if (pass->type == PASS_COMBINED && pass->lightgroup.empty()) {
213  const BufferPass *shadow_catcher_matte_pass = find_pass(PASS_SHADOW_CATCHER_MATTE, pass->mode);
214  if (shadow_catcher_matte_pass) {
215  pass = shadow_catcher_matte_pass;
216  }
217  }
218 
219  return pass;
220 }
221 
223 {
224  offset = -(full_x + full_y * width);
225  stride = width;
226 }
227 
228 bool BufferParams::modified(const BufferParams &other) const
229 {
230  if (width != other.width || height != other.height) {
231  return true;
232  }
233 
234  if (full_x != other.full_x || full_y != other.full_y || full_width != other.full_width ||
235  full_height != other.full_height) {
236  return true;
237  }
238 
239  if (window_x != other.window_x || window_y != other.window_y ||
240  window_width != other.window_width || window_height != other.window_height) {
241  return true;
242  }
243 
244  if (offset != other.offset || stride != other.stride || pass_stride != other.pass_stride) {
245  return true;
246  }
247 
248  if (layer != other.layer || view != other.view) {
249  return true;
250  }
251 
252  if (exposure != other.exposure ||
255  return true;
256  }
257 
258  return !(passes == other.passes);
259 }
260 
261 /* --------------------------------------------------------------------
262  * Render Buffers.
263  */
264 
265 RenderBuffers::RenderBuffers(Device *device) : buffer(device, "RenderBuffers", MEM_READ_WRITE)
266 {
267 }
268 
270 {
271  buffer.free();
272 }
273 
274 void RenderBuffers::reset(const BufferParams &params_)
275 {
276  DCHECK(params_.pass_stride != -1);
277 
278  params = params_;
279 
280  /* re-allocate buffer */
282 }
283 
285 {
287 }
288 
290 {
291  DCHECK(params.pass_stride != -1);
292 
293  if (!buffer.device_pointer)
294  return false;
295 
297 
298  return true;
299 }
300 
302 {
304 }
305 
307  const BufferParams &dst_params,
308  const RenderBuffers *src,
309  const BufferParams &src_params,
310  const size_t src_offset)
311 {
312  DCHECK_EQ(dst_params.width, src_params.width);
313  /* TODO(sergey): More sanity checks to avoid buffer overrun. */
314 
315  /* Create a map of pass offsets to be copied.
316  * Assume offsets are different to allow copying passes between buffers with different set of
317  * passes. */
318 
319  struct {
320  int dst_offset;
321  int src_offset;
322  } pass_offsets[PASS_NUM];
323 
324  int num_passes = 0;
325 
326  for (int i = 0; i < PASS_NUM; ++i) {
327  const PassType pass_type = static_cast<PassType>(i);
328 
329  const int dst_pass_offset = dst_params.get_pass_offset(pass_type, PassMode::DENOISED);
330  if (dst_pass_offset == PASS_UNUSED) {
331  continue;
332  }
333 
334  const int src_pass_offset = src_params.get_pass_offset(pass_type, PassMode::DENOISED);
335  if (src_pass_offset == PASS_UNUSED) {
336  continue;
337  }
338 
339  pass_offsets[num_passes].dst_offset = dst_pass_offset;
340  pass_offsets[num_passes].src_offset = src_pass_offset;
341  ++num_passes;
342  }
343 
344  /* Copy passes. */
345  /* TODO(sergey): Make it more reusable, allowing implement copy of noisy passes. */
346 
347  const int64_t dst_width = dst_params.width;
348  const int64_t dst_height = dst_params.height;
349  const int64_t dst_pass_stride = dst_params.pass_stride;
350  const int64_t dst_num_pixels = dst_width * dst_height;
351 
352  const int64_t src_pass_stride = src_params.pass_stride;
353  const int64_t src_offset_in_floats = src_offset * src_pass_stride;
354 
355  const float *src_pixel = src->buffer.data() + src_offset_in_floats;
356  float *dst_pixel = dst->buffer.data();
357 
358  for (int i = 0; i < dst_num_pixels;
359  ++i, src_pixel += src_pass_stride, dst_pixel += dst_pass_stride) {
360  for (int pass_offset_idx = 0; pass_offset_idx < num_passes; ++pass_offset_idx) {
361  const int dst_pass_offset = pass_offsets[pass_offset_idx].dst_offset;
362  const int src_pass_offset = pass_offsets[pass_offset_idx].src_offset;
363 
364  /* TODO(sergey): Support non-RGBA passes. */
365  dst_pixel[dst_pass_offset + 0] = src_pixel[src_pass_offset + 0];
366  dst_pixel[dst_pass_offset + 1] = src_pixel[src_pass_offset + 1];
367  dst_pixel[dst_pass_offset + 2] = src_pixel[src_pass_offset + 2];
368  dst_pixel[dst_pass_offset + 3] = src_pixel[src_pass_offset + 3];
369  }
370  }
371 }
372 
static AppView * view
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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 type
_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 GLsizei width
static CCL_NAMESPACE_BEGIN int pass_type_mode_to_index(PassType pass_type, PassMode mode)
Definition: buffers.cpp:21
void render_buffers_host_copy_denoised(RenderBuffers *dst, const BufferParams &dst_params, const RenderBuffers *src, const BufferParams &src_params, const size_t src_offset)
Definition: buffers.cpp:306
static int pass_to_index(const BufferPass &pass)
Definition: buffers.cpp:32
NODE_DEFINE(BufferPass)
Definition: buffers.cpp:41
ustring view
Definition: buffers.h:98
int pass_stride
Definition: buffers.h:93
ustring layer
Definition: buffers.h:97
int offset
Definition: buffers.h:90
int full_x
Definition: buffers.h:84
int full_width
Definition: buffers.h:86
int pass_offset_[kNumPassOffsets]
Definition: buffers.h:148
bool use_approximate_shadow_catcher
Definition: buffers.h:101
int stride
Definition: buffers.h:90
vector< BufferPass > passes
Definition: buffers.h:96
int height
Definition: buffers.h:72
static constexpr int kNumPassOffsets
Definition: buffers.h:143
int get_pass_offset(PassType type, PassMode mode=PassMode::NOISY) const
Definition: buffers.cpp:168
float exposure
Definition: buffers.h:100
int window_y
Definition: buffers.h:79
void update_offset_stride()
Definition: buffers.cpp:222
bool modified(const BufferParams &other) const
Definition: buffers.cpp:228
int full_height
Definition: buffers.h:87
int window_height
Definition: buffers.h:81
int window_width
Definition: buffers.h:80
void reset_pass_offset()
Definition: buffers.cpp:161
NODE_DECLARE int width
Definition: buffers.h:71
const BufferPass * find_pass(string_view name) const
Definition: buffers.cpp:178
const BufferPass * get_actual_display_pass(PassType type, PassMode mode=PassMode::NOISY) const
Definition: buffers.cpp:200
int window_x
Definition: buffers.h:78
bool use_transparent_background
Definition: buffers.h:102
int full_y
Definition: buffers.h:85
void update_passes()
Definition: buffers.cpp:121
BufferPass()
Definition: buffers.cpp:59
int offset
Definition: buffers.h:35
bool include_albedo
Definition: buffers.h:32
PassInfo get_info() const
Definition: buffers.cpp:73
NODE_DECLARE PassType type
Definition: buffers.h:29
ustring lightgroup
Definition: buffers.h:33
PassMode mode
Definition: buffers.h:30
Definition: pass.h:48
PassInfo get_info() const
Definition: pass.cpp:136
static const NodeEnum * get_type_enum()
Definition: pass.cpp:44
static const NodeEnum * get_mode_enum()
Definition: pass.cpp:104
device_vector< float > buffer
Definition: buffers.h:159
void zero()
Definition: buffers.cpp:284
BufferParams params
Definition: buffers.h:156
bool copy_from_device()
Definition: buffers.cpp:289
void copy_to_device()
Definition: buffers.cpp:301
void reset(const BufferParams &params)
Definition: buffers.cpp:274
RenderBuffers(Device *device)
Definition: buffers.cpp:265
device_ptr device_pointer
T * alloc(size_t width, size_t height=0, size_t depth=0)
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
@ MEM_READ_WRITE
SyclQueue void void * src
ccl_gpu_kernel_postfix ccl_global float int full_x
ccl_global float * buffer
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_gpu_kernel_postfix ccl_global float int int full_y
#define PASS_UNUSED
Definition: kernel/types.h:44
PassType
Definition: kernel/types.h:334
@ PASS_SHADOW_CATCHER_MATTE
Definition: kernel/types.h:394
@ PASS_COMBINED
Definition: kernel/types.h:338
@ PASS_NUM
Definition: kernel/types.h:402
@ PASS_NONE
Definition: kernel/types.h:335
#define DCHECK(expression)
Definition: log.h:55
#define DCHECK_EQ(a, b)
Definition: log.h:64
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
#define SOCKET_FLOAT(name, ui_name, default_value,...)
Definition: node_type.h:191
#define SOCKET_INT(name, ui_name, default_value,...)
Definition: node_type.h:187
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
Definition: node_type.h:185
#define SOCKET_STRING(name, ui_name, default_value,...)
Definition: node_type.h:203
#define SOCKET_ENUM(name, ui_name, values, default_value,...)
Definition: node_type.h:207
PassMode
Definition: pass.h:19
__int64 int64_t
Definition: stdint.h:89
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
const NodeType * type
Definition: graph/node.h:175
ustring name
Definition: graph/node.h:174
Definition: pass.h:26