Blender  V3.3
id_passes.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2018-2022 Blender Foundation */
3 
4 #pragma once
5 
7 
8 /* Element of ID pass stored in the render buffers.
9  * It is `float2` semantically, but it must be unaligned since the offset of ID passes in the
10  * render buffers might not meet expected by compiler alignment. */
11 typedef struct IDPassBufferElement {
12  float x;
13  float y;
15 
17  int num_slots,
18  float id,
19  float weight)
20 {
21  kernel_assert(id != ID_NONE);
22  if (weight == 0.0f) {
23  return;
24  }
25 
26  for (int slot = 0; slot < num_slots; slot++) {
28 #ifdef __ATOMIC_PASS_WRITE__
29  /* If the loop reaches an empty slot, the ID isn't in any slot yet - so add it! */
30  if (id_buffer[slot].x == ID_NONE) {
31  /* Use an atomic to claim this slot.
32  * If a different thread got here first, try again from this slot on. */
33  float old_id = atomic_compare_and_swap_float(buffer + slot * 2, ID_NONE, id);
34  if (old_id != ID_NONE && old_id != id) {
35  continue;
36  }
37  atomic_add_and_fetch_float(buffer + slot * 2 + 1, weight);
38  break;
39  }
40  /* If there already is a slot for that ID, add the weight.
41  * If no slot was found, add it to the last. */
42  else if (id_buffer[slot].x == id || slot == num_slots - 1) {
43  atomic_add_and_fetch_float(buffer + slot * 2 + 1, weight);
44  break;
45  }
46 #else /* __ATOMIC_PASS_WRITE__ */
47  /* If the loop reaches an empty slot, the ID isn't in any slot yet - so add it! */
48  if (id_buffer[slot].x == ID_NONE) {
49  id_buffer[slot].x = id;
50  id_buffer[slot].y = weight;
51  break;
52  }
53  /* If there already is a slot for that ID, add the weight.
54  * If no slot was found, add it to the last. */
55  else if (id_buffer[slot].x == id || slot == num_slots - 1) {
56  id_buffer[slot].y += weight;
57  break;
58  }
59 #endif /* __ATOMIC_PASS_WRITE__ */
60  }
61 }
62 
64 {
66  for (int slot = 1; slot < num_slots; ++slot) {
67  if (id_buffer[slot].x == ID_NONE) {
68  return;
69  }
70  /* Since we're dealing with a tiny number of elements, insertion sort should be fine. */
71  int i = slot;
72  while (i > 0 && id_buffer[i].y > id_buffer[i - 1].y) {
73  const IDPassBufferElement swap = id_buffer[i];
74  id_buffer[i] = id_buffer[i - 1];
75  id_buffer[i - 1] = swap;
76  --i;
77  }
78  }
79 }
80 
81 /* post-sorting for Cryptomatte */
84  int pixel_index)
85 {
86  const int pass_stride = kernel_data.film.pass_stride;
87  const uint64_t render_buffer_offset = (uint64_t)pixel_index * pass_stride;
88  ccl_global float *cryptomatte_buffer = render_buffer + render_buffer_offset +
89  kernel_data.film.pass_cryptomatte;
90  kernel_sort_id_slots(cryptomatte_buffer, 2 * kernel_data.film.cryptomatte_depth);
91 }
92 
void swap(T &a, T &b)
Definition: Common.h:19
_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
#define atomic_compare_and_swap_float(p, old_val, new_val)
Definition: atomic.h:13
#define atomic_add_and_fetch_float(p, x)
Definition: atomic.h:12
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_device_inline
Definition: cuda/compat.h:34
#define ccl_global
Definition: cuda/compat.h:43
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
ccl_device_inline void kernel_cryptomatte_post(KernelGlobals kg, ccl_global float *render_buffer, int pixel_index)
Definition: id_passes.h:82
ccl_device_inline void kernel_sort_id_slots(ccl_global float *buffer, int num_slots)
Definition: id_passes.h:63
CCL_NAMESPACE_BEGIN struct IDPassBufferElement IDPassBufferElement
ccl_device_inline void kernel_write_id_slots(ccl_global float *buffer, int num_slots, float id, float weight)
Definition: id_passes.h:16
ccl_global float * buffer
ccl_gpu_kernel_postfix ccl_global KernelWorkTile const int ccl_global float * render_buffer
ccl_gpu_kernel_postfix ccl_global float int int int int int int int pass_stride
#define ID_NONE
Definition: kernel/types.h:43
unsigned __int64 uint64_t
Definition: stdint.h:90