Blender V4.5
draw_debug.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "BKE_object.hh"
12#include "BLI_math_bits.h"
13#include "BLI_math_matrix.h"
14#include "BLI_math_matrix.hh"
15#include "GPU_batch.hh"
16#include "GPU_debug.hh"
17
19#include "draw_debug.hh"
20#include "draw_shader.hh"
21#include "draw_shader_shared.hh"
22
23namespace blender::draw {
24
25/* -------------------------------------------------------------------- */
28
30{
31 for (int i = 0; i < 2; i++) {
32 vertex_len_.store(0);
33
34 if (cpu_draw_buf_.current() == nullptr) {
35 cpu_draw_buf_.current() = MEM_new<DebugDrawBuf>("DebugDrawBuf-CPU", "DebugDrawBuf-CPU");
36 gpu_draw_buf_.current() = MEM_new<DebugDrawBuf>("DebugDrawBuf-GPU", "DebugDrawBuf-GPU");
37 }
38
39 cpu_draw_buf_.current()->command.vertex_len = 0;
40 cpu_draw_buf_.current()->command.vertex_first = 0;
41 cpu_draw_buf_.current()->command.instance_len = 1;
42 cpu_draw_buf_.current()->command.instance_first_array = 0;
43
44 gpu_draw_buf_.current()->command.vertex_len = 0;
45 gpu_draw_buf_.current()->command.vertex_first = 0;
46 gpu_draw_buf_.current()->command.instance_len = 1;
47 gpu_draw_buf_.current()->command.instance_first_array = 0;
48 gpu_draw_buf_.current()->push_update();
49
50 cpu_draw_buf_.swap();
51 gpu_draw_buf_.swap();
52 }
53
54 gpu_draw_buf_used = false;
55}
56
58{
59#ifdef WITH_DRAW_DEBUG
60 gpu_draw_buf_used = true;
61 return *gpu_draw_buf_.current();
62#else
63 return nullptr;
64#endif
65}
66
67void DebugDraw::clear_gpu_data()
68{
69 for (int i = 0; i < 2; i++) {
70 MEM_SAFE_DELETE(cpu_draw_buf_.current());
71 MEM_SAFE_DELETE(gpu_draw_buf_.current());
72
73 cpu_draw_buf_.swap();
74 gpu_draw_buf_.swap();
75 }
76}
77
79{
81}
82
84
85/* -------------------------------------------------------------------- */
88
89void drw_debug_line(const float3 v1, const float3 v2, const float4 color, const uint lifetime)
90{
92 dd.draw_line(v1, v2, debug_color_pack(color), lifetime);
93}
94
95void drw_debug_polygon(Span<float3> face_verts, const float4 color, const uint lifetime)
96{
97 BLI_assert(!face_verts.is_empty());
100 float3 v0 = face_verts.last();
101 for (auto vert : face_verts) {
102 float3 v1 = vert;
103 dd.draw_line(v0, v1, col, lifetime);
104 v0 = v1;
105 }
106}
107
108void drw_debug_bbox(const BoundBox &bbox, const float4 color, const uint lifetime)
109{
112 dd.draw_line(bbox.vec[0], bbox.vec[1], col, lifetime);
113 dd.draw_line(bbox.vec[1], bbox.vec[2], col, lifetime);
114 dd.draw_line(bbox.vec[2], bbox.vec[3], col, lifetime);
115 dd.draw_line(bbox.vec[3], bbox.vec[0], col, lifetime);
116
117 dd.draw_line(bbox.vec[4], bbox.vec[5], col, lifetime);
118 dd.draw_line(bbox.vec[5], bbox.vec[6], col, lifetime);
119 dd.draw_line(bbox.vec[6], bbox.vec[7], col, lifetime);
120 dd.draw_line(bbox.vec[7], bbox.vec[4], col, lifetime);
121
122 dd.draw_line(bbox.vec[0], bbox.vec[4], col, lifetime);
123 dd.draw_line(bbox.vec[1], bbox.vec[5], col, lifetime);
124 dd.draw_line(bbox.vec[2], bbox.vec[6], col, lifetime);
125 dd.draw_line(bbox.vec[3], bbox.vec[7], col, lifetime);
126}
127
128static Vector<float3> precompute_sphere_points(int circle_resolution)
129{
131 for (auto axis : IndexRange(3)) {
132 for (auto edge : IndexRange(circle_resolution)) {
133 for (auto vert : IndexRange(2)) {
134 const float angle = (2 * M_PI) * (edge + vert) / float(circle_resolution);
135 const float point[3] = {cosf(angle), sinf(angle), 0.0f};
136 result.append(float3(point[(0 + axis) % 3], point[(1 + axis) % 3], point[(2 + axis) % 3]));
137 }
138 }
139 }
140 return result;
141}
142
143void drw_debug_sphere(const float3 center, float radius, const float4 color, const uint lifetime)
144{
146 static Vector<float3> sphere_verts = precompute_sphere_points(16);
147
150 for (auto i : IndexRange(sphere_verts.size() / 2)) {
151 float3 v0 = sphere_verts[i * 2] * radius + center;
152 float3 v1 = sphere_verts[i * 2 + 1] * radius + center;
153 dd.draw_line(v0, v1, col, lifetime);
154 }
155}
156
157void drw_debug_point(const float3 pos, float rad, const float4 col, const uint lifetime)
158{
159 static Vector<float3> point_verts = precompute_sphere_points(4);
160
163 for (auto i : IndexRange(point_verts.size() / 2)) {
164 float3 v0 = point_verts[i * 2] * rad + pos;
165 float3 v1 = point_verts[i * 2 + 1] * rad + pos;
166 dd.draw_line(v0, v1, color, lifetime);
167 }
168}
169
170void drw_debug_matrix(const float4x4 &m4, const uint lifetime)
171{
172 float3 v0 = math::transform_point(m4, float3(0.0f, 0.0f, 0.0f));
173 float3 v1 = math::transform_point(m4, float3(1.0f, 0.0f, 0.0f));
174 float3 v2 = math::transform_point(m4, float3(0.0f, 1.0f, 0.0f));
175 float3 v3 = math::transform_point(m4, float3(0.0f, 0.0f, 1.0f));
176
178 dd.draw_line(v0, v1, debug_color_pack(float4(1.0f, 0.0f, 0.0f, 1.0f)), lifetime);
179 dd.draw_line(v0, v2, debug_color_pack(float4(0.0f, 1.0f, 0.0f, 1.0f)), lifetime);
180 dd.draw_line(v0, v3, debug_color_pack(float4(0.0f, 0.0f, 1.0f, 1.0f)), lifetime);
181}
182
183void drw_debug_matrix_as_bbox(const float4x4 &mat, const float4 color, const uint lifetime)
184{
185 BoundBox bb;
186 const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
188 for (auto i : IndexRange(8)) {
189 mul_project_m4_v3(mat.ptr(), bb.vec[i]);
190 }
191 drw_debug_bbox(bb, color, lifetime);
192}
193
195
196/* -------------------------------------------------------------------- */
200
202{
203 DebugDrawBuf &buf = *cpu_draw_buf_.current();
204 uint index = vertex_len_.fetch_add(2);
205 if (index + 2 < DRW_DEBUG_DRAW_VERT_MAX) {
206 buf.verts[index / 2] = debug_line_make(float_as_uint(v1.x),
207 float_as_uint(v1.y),
208 float_as_uint(v1.z),
209 float_as_uint(v2.x),
210 float_as_uint(v2.y),
211 float_as_uint(v2.z),
212 color,
213 lifetime);
214 buf.command.vertex_len += 2;
215 }
216}
217
219
220/* -------------------------------------------------------------------- */
223
224void DebugDraw::display_lines(View &view)
225{
226 const bool cpu_draw_buf_used = vertex_len_.load() != 0;
227
228 if (!cpu_draw_buf_used && !gpu_draw_buf_used) {
229 return;
230 }
231
233
234 float viewport_size[4];
235 GPU_viewport_size_get_f(viewport_size);
236
238 GPUShader *shader = DRW_shader_debug_draw_display_get();
240 GPU_shader_uniform_mat4(shader, "persmat", view.persmat().ptr());
241 GPU_shader_uniform_2f(shader, "size_viewport", viewport_size[2], viewport_size[3]);
242
243 if (gpu_draw_buf_used) {
245 /* Reset buffer. */
246 gpu_draw_buf_.next()->command.vertex_len = 0;
247 gpu_draw_buf_.next()->push_update();
248
249 GPU_storagebuf_bind(*gpu_draw_buf_.current(), DRW_DEBUG_DRAW_SLOT);
251 GPU_batch_draw_indirect(batch, *gpu_draw_buf_.current(), 0);
252 GPU_storagebuf_unbind(*gpu_draw_buf_.current());
253 GPU_storagebuf_unbind(*gpu_draw_buf_.next());
255 }
256
257 {
259 /* We might have race condition here (a writer thread might still be outputting vertices).
260 * But that is ok. At worse, we will be missing some vertex data and show 1 corrupted line. */
261 cpu_draw_buf_.current()->command.vertex_len = vertex_len_.load();
262 cpu_draw_buf_.current()->push_update();
263 /* Reset buffer. */
264 cpu_draw_buf_.next()->command.vertex_len = 0;
265 cpu_draw_buf_.next()->push_update();
266
267 GPU_storagebuf_bind(*cpu_draw_buf_.current(), DRW_DEBUG_DRAW_SLOT);
269 GPU_batch_draw_indirect(batch, *cpu_draw_buf_.current(), 0);
270 GPU_storagebuf_unbind(*cpu_draw_buf_.current());
271 GPU_storagebuf_unbind(*cpu_draw_buf_.next());
272
273 /* Read result of lifetime management. */
274 cpu_draw_buf_.next()->read();
275 vertex_len_.store(min_ii(DRW_DEBUG_DRAW_VERT_MAX, cpu_draw_buf_.next()->command.vertex_len));
277 }
278
279 gpu_draw_buf_.swap();
280 cpu_draw_buf_.swap();
281}
282
284{
285 /* Display only on the main thread. Avoid concurrent usage of the resource. */
287
288 GPU_debug_group_begin("DebugDraw");
289
290 display_lines(view);
291
293}
294
296
297} // namespace blender::draw
General operations, lookup, etc. for blender objects.
void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float max[3])
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE int min_ii(int a, int b)
MINLINE unsigned int float_as_uint(float f)
#define M_PI
void mul_project_m4_v3(const float mat[4][4], float vec[3])
unsigned int uint
int BLI_thread_is_main(void)
Definition threads.cc:179
static AppView * view
blender::gpu::Batch * GPU_batch_procedural_lines_get()
Definition gpu_batch.cc:538
void GPU_batch_draw_indirect(blender::gpu::Batch *batch, GPUStorageBuf *indirect_buf, intptr_t offset)
void GPU_batch_set_shader(blender::gpu::Batch *batch, GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
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_2f(GPUShader *sh, const char *name, float x, float y)
void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4])
void GPU_viewport_size_get_f(float coords[4])
Definition gpu_state.cc:273
void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot)
void GPU_storagebuf_unbind(GPUStorageBuf *ssbo)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
ATTR_WARN_UNUSED_RESULT const BMVert * v2
constexpr const T & last(const int64_t n=0) const
Definition BLI_span.hh:325
constexpr bool is_empty() const
Definition BLI_span.hh:260
int64_t size() const
void display_to_view(View &view)
static DebugDraw & get()
GPUStorageBuf * gpu_draw_buf_get()
Definition draw_debug.cc:57
void draw_line(float3 v1, float3 v2, uint color, uint lifetime=1)
#define sinf(x)
#define cosf(x)
Simple API to draw debug shapes and log in the viewport.
#define DRW_DEBUG_DRAW_SLOT
#define DRW_DEBUG_DRAW_FEEDBACK_SLOT
GPUShader * DRW_shader_debug_draw_display_get()
DRWDebugVertPair debug_line_make(uint in_pos1_x, uint in_pos1_y, uint in_pos1_z, uint in_pos2_x, uint in_pos2_y, uint in_pos2_z, uint in_vert_color, uint in_lifetime)
uint debug_color_pack(float4 v_color)
#define DRW_DEBUG_DRAW_VERT_MAX
@ DRW_STATE_DEPTH_LESS
Definition draw_state.hh:37
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
uint pos
struct @242053044010324116347033273112253060004051364061::@051143074301336237271216303350234260141112266062 batch
uint col
void drw_debug_bbox(const BoundBox &bbox, const float4 color, const uint lifetime)
void drw_debug_matrix_as_bbox(const float4x4 &mat, const float4 color, const uint lifetime)
void drw_debug_sphere(const float3 center, float radius, const float4 color, const uint lifetime)
void drw_debug_matrix(const float4x4 &m4, const uint lifetime)
void drw_debug_line(const float3 v1, const float3 v2, const float4 color, const uint lifetime)
Definition draw_debug.cc:89
static Vector< float3 > precompute_sphere_points(int circle_resolution)
void drw_debug_polygon(Span< float3 > face_verts, const float4 color, const uint lifetime)
Definition draw_debug.cc:95
void drw_debug_clear()
Definition draw_debug.cc:78
void drw_debug_point(const float3 pos, float rad, const float4 col, const uint lifetime)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< float, 3 > float3
float vec[8][3]
DRWDebugVertPair verts[DRW_DEBUG_DRAW_VERT_MAX]
const c_style_mat & ptr() const
static void set(DRWState state=DRW_STATE_DEFAULT)
i
Definition text_draw.cc:230