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