Blender V4.3
draw_manager.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BKE_global.hh"
10#include "GPU_compute.hh"
11
12#include "draw_debug.hh"
13#include "draw_defines.hh"
14#include "draw_manager.hh"
15#include "draw_manager_c.hh"
16#include "draw_pass.hh"
17#include "draw_shader.hh"
18
19namespace blender::draw {
20
22{
23 for (GPUTexture *texture : acquired_textures) {
24 /* Decrease refcount and free if 0. */
25 GPU_texture_free(texture);
26 }
27}
28
30{
31 matrix_buf.swap();
32 bounds_buf.swap();
33 infos_buf.swap();
34
35 matrix_buf.current().trim_to_next_power_of_2(resource_len_);
36 bounds_buf.current().trim_to_next_power_of_2(resource_len_);
37 infos_buf.current().trim_to_next_power_of_2(resource_len_);
39
40 /* TODO: This means the reference is kept until further redraw or manager tear-down. Instead,
41 * they should be released after each draw loop. But for now, mimics old DRW behavior. */
42 for (GPUTexture *texture : acquired_textures) {
43 /* Decrease refcount and free if 0. */
44 GPU_texture_free(texture);
45 }
46
49
50/* For some reason, if this uninitialized data pattern was enabled (ie release asserts enabled),
51 * The viewport just gives up rendering objects on ARM64 devices. Possibly Mesa GLOn12-related. */
52#if !defined(NDEBUG) && !defined(_M_ARM64)
53 /* Detect uninitialized data. */
54 memset(matrix_buf.current().data(),
55 0xF0,
56 matrix_buf.current().size() * sizeof(*matrix_buf.current().data()));
57 memset(bounds_buf.current().data(),
58 0xF0,
59 matrix_buf.current().size() * sizeof(*bounds_buf.current().data()));
60 memset(infos_buf.current().data(),
61 0xF0,
62 matrix_buf.current().size() * sizeof(*infos_buf.current().data()));
63#endif
64 resource_len_ = 0;
65 attribute_len_ = 0;
66 /* TODO(fclem): Resize buffers if too big, but with an hysteresis threshold. */
67
68 object_active = DST.draw_ctx.obact;
69
70 /* Init the 0 resource. */
72}
73
74void Manager::sync_layer_attributes()
75{
76 /* Sort the attribute IDs - the shaders use binary search. */
77 Vector<uint32_t> id_list;
78
79 id_list.reserve(layer_attributes.size());
80
81 for (uint32_t id : layer_attributes.keys()) {
82 id_list.append(id);
83 }
84
85 std::sort(id_list.begin(), id_list.end());
86
87 /* Look up the attributes. */
89
90 for (uint32_t id : id_list) {
93 {
94 /* Check if the buffer is full. */
95 if (++count == size) {
96 break;
97 }
98 }
99 }
100
101 layer_attributes_buf[0].buffer_length = count;
102}
103
105{
106 GPU_debug_group_begin("Manager.end_sync");
107
108 sync_layer_attributes();
109
110 matrix_buf.current().push_update();
111 bounds_buf.current().push_update();
112 infos_buf.current().push_update();
116
117 /* Useful for debugging the following resource finalize. But will trigger the drawing of the GPU
118 * debug draw/print buffers for every frame. Not nice for performance. */
119 // debug_bind();
120
121 /* Dispatch compute to finalize the resources on GPU. Save a bit of CPU time. */
122 uint thread_groups = divide_ceil_u(resource_len_, DRW_FINALIZE_GROUP_SIZE);
124 GPU_shader_bind(shader);
125 GPU_shader_uniform_1i(shader, "resource_len", resource_len_);
126 GPU_storagebuf_bind(matrix_buf.current(), GPU_shader_get_ssbo_binding(shader, "matrix_buf"));
127 GPU_storagebuf_bind(bounds_buf.current(), GPU_shader_get_ssbo_binding(shader, "bounds_buf"));
128 GPU_storagebuf_bind(infos_buf.current(), GPU_shader_get_ssbo_binding(shader, "infos_buf"));
129 GPU_compute_dispatch(shader, thread_groups, 1, 1);
131
133}
134
136{
137#ifdef _DEBUG
138 if (DST.debug == nullptr) {
139 return;
140 }
143# ifndef DISABLE_DEBUG_SHADER_PRINT_BARRIER
144 /* Add a barrier to allow multiple shader writing to the same buffer. */
146# endif
147#endif
148}
149
151{
156 /* 2 is the hardcoded location of the uniform attr UBO. */
157 /* TODO(@fclem): Remove this workaround. */
159}
160
162{
163 view.bind();
164
165 debug_bind();
166
168 state.inverted_view = view.is_inverted();
169
170 pass.draw_commands_buf_.bind(state, pass.headers_, pass.commands_, pass.sub_passes_);
171
173
174 pass.submit(state);
175
176 state.cleanup();
177}
178
179void Manager::submit(PassMain &pass, View &view)
180{
181 view.bind();
182
183 debug_bind();
184
185 bool freeze_culling = (U.experimental.use_viewport_debug && DST.draw_ctx.v3d &&
187
188 view.compute_visibility(
189 bounds_buf.current(), infos_buf.current(), resource_len_, freeze_culling);
190
192 state.inverted_view = view.is_inverted();
193
194 pass.draw_commands_buf_.bind(state,
195 pass.headers_,
196 pass.commands_,
197 view.get_visibility_buffer(),
198 view.visibility_word_per_draw(),
199 view.view_len_,
200 pass.use_custom_ids);
201
203
204 pass.submit(state);
205
206 state.cleanup();
207}
208
210{
211 pass.sort();
212
213 this->submit(static_cast<PassMain &>(pass), view);
214}
215
217{
218 debug_bind();
219
221
222 pass.draw_commands_buf_.bind(state, pass.headers_, pass.commands_, pass.sub_passes_);
223
225
226 pass.submit(state);
227
228 state.cleanup();
229}
230
232{
233 submit(pass, view);
234
235 pass.draw_commands_buf_.resource_id_buf_.read();
236
238 output.resource_id = {pass.draw_commands_buf_.resource_id_buf_.data(),
239 pass.draw_commands_buf_.resource_id_count_};
240 /* There is no visibility data for PassSimple. */
241 output.visibility = {(uint *)view.get_visibility_buffer().data(), 0};
242 return output;
243}
244
246{
247 submit(pass, view);
248
250
251 pass.draw_commands_buf_.resource_id_buf_.read();
252 view.get_visibility_buffer().read();
253
255 output.resource_id = {pass.draw_commands_buf_.resource_id_buf_.data(),
256 pass.draw_commands_buf_.resource_id_count_};
257 output.visibility = {(uint *)view.get_visibility_buffer().data(),
258 divide_ceil_u(resource_len_, 32)};
259 return output;
260}
261
263{
264 matrix_buf.current().read();
265 bounds_buf.current().read();
266 infos_buf.current().read();
267
269 output.matrices = {matrix_buf.current().data(), resource_len_};
270 output.bounds = {bounds_buf.current().data(), resource_len_};
271 output.infos = {infos_buf.current().data(), resource_len_};
272 return output;
273}
274
275} // namespace blender::draw
MINLINE uint divide_ceil_u(uint a, uint b)
unsigned int uint
@ V3D_DEBUG_FREEZE_CULLING
void GPU_compute_dispatch(GPUShader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len)
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
int GPU_shader_get_ssbo_binding(GPUShader *shader, const char *name)
void GPU_shader_bind(GPUShader *shader)
void GPU_memory_barrier(eGPUBarrier barrier)
Definition gpu_state.cc:374
@ GPU_BARRIER_SHADER_STORAGE
Definition GPU_state.hh:48
@ GPU_BARRIER_BUFFER_UPDATE
Definition GPU_state.hh:56
void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot)
void GPU_texture_free(GPUTexture *texture)
void GPU_uniformbuf_bind(GPUUniformBuf *ubo, int slot)
struct GPUShader GPUShader
unsigned int U
Definition btGjkEpa3.h:78
#define output
void clear()
Definition BLI_map.hh:989
const Value & lookup(const Key &key) const
Definition BLI_map.hh:506
int64_t size() const
Definition BLI_map.hh:927
constexpr const T * data() const
Definition BLI_span.hh:216
void append(const T &value)
void reserve(const int64_t min_capacity)
LayerAttributeBuf layer_attributes_buf
SwapChain< ObjectBoundsBuf, 2 > bounds_buf
SubmitDebugOutput submit_debug(PassSimple &pass, View &view)
SwapChain< ObjectInfosBuf, 2 > infos_buf
ObjectAttributeBuf attributes_buf
Map< uint32_t, GPULayerAttr > layer_attributes
Vector< GPUTexture * > acquired_textures
SwapChain< ObjectMatricesBuf, 2 > matrix_buf
void submit(PassSimple &pass, View &view)
ResourceHandle resource_handle(const ObjectRef &ref, float inflate_bounds=0.0f)
ObjectAttributeLegacyBuf attributes_buf_legacy
DataDebugOutput data_debug()
void trim_to_next_power_of_2(int64_t required_size)
GPUStorageBuf * drw_debug_gpu_print_buf_get()
GPUStorageBuf * drw_debug_gpu_draw_buf_get()
Simple API to draw debug shapes and log in the viewport.
#define DRW_FINALIZE_GROUP_SIZE
#define DRW_DEBUG_DRAW_SLOT
#define DRW_DEBUG_PRINT_SLOT
#define DRW_OBJ_INFOS_SLOT
#define DRW_OBJ_ATTR_SLOT
#define DRW_OBJ_MAT_SLOT
#define DRW_LAYER_ATTR_UBO_SLOT
DRWManager DST
GPUShader * DRW_shader_draw_resource_finalize_get()
int count
static ulong state[N]
unsigned int uint32_t
Definition stdint.h:80
ViewLayer * view_layer
DRWContextState draw_ctx
DRWDebugModule * debug
short debug_flag