Blender V4.3
draw_manager.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
17#include "BKE_paint.hh"
18#include "BKE_pbvh_api.hh"
19
20#include "BLI_map.hh"
21#include "BLI_sys_types.h"
22
23#include "GPU_material.hh"
24
25#include "draw_resource.hh"
26#include "draw_sculpt.hh"
27#include "draw_view.hh"
28
29#include <string>
30
31namespace blender::draw {
32
33/* Forward declarations. */
34
35namespace detail {
36template<typename T> class Pass;
37} // namespace detail
38
39namespace command {
40class DrawCommandBuf;
41class DrawMultiBuf;
42} // namespace command
43
46class PassSortable;
47
48class Manager {
59
60 public:
67
76
84
95
100
105
111
112 private:
114 uint resource_len_ = 0;
116 uint attribute_len_ = 0;
117
118 Object *object_active = nullptr;
119
120 public:
122 ~Manager();
123
132 /* WORKAROUND: Instead of breaking const correctness everywhere, we only break it for this. */
133 ResourceHandle resource_handle(const ObjectRef &ref, float inflate_bounds = 0.0f);
139 const float4x4 *model_matrix,
140 const float3 *bounds_center,
141 const float3 *bounds_half_extent);
146 ResourceHandle resource_handle(const float4x4 &model_matrix);
152 ResourceHandle resource_handle(const float4x4 &model_matrix,
153 const float3 &bounds_center,
154 const float3 &bounds_half_extent);
159 ResourceHandle resource_handle_for_psys(const ObjectRef &ref, const float4x4 &model_matrix);
160
162 {
163 /* TODO(fclem): Deduplicate with other engine. */
165 const float3 center = math::midpoint(bounds.min, bounds.max);
166 const float3 half_extent = bounds.max - center;
167 return resource_handle(ref, nullptr, &center, &half_extent);
168 }
169
172 const ObjectRef &ref,
173 float inflate_bounds = 0.0f);
176 const float3 &bounds_center,
177 const float3 &bounds_half_extent);
178
184 const ObjectRef &ref,
185 const GPUMaterial *material);
187 const ObjectRef &ref,
188 Span<GPUMaterial *> materials);
189
194
199 void submit(PassSimple &pass, View &view);
200 void submit(PassMain &pass, View &view);
201 void submit(PassSortable &pass, View &view);
205 void submit(PassSimple &pass);
206
210 SubmitDebugOutput submit_debug(PassSimple &pass, View &view);
211 SubmitDebugOutput submit_debug(PassMain &pass, View &view);
212
216 DataDebugOutput data_debug();
217
222 void acquire_texture(GPUTexture *texture)
223 {
224 GPU_texture_ref(texture);
225 acquired_textures.append(texture);
226 }
227
232 {
233 return resource_len_;
234 }
235
237 void begin_sync();
238 void end_sync();
239
240 void debug_bind();
241 void resource_bind();
242
243 private:
244 void sync_layer_attributes();
245};
246
248{
249 if (ref.handle.raw == 0) {
250 /* WORKAROUND: Instead of breaking const correctness everywhere, we only break it for this. */
251 const_cast<ObjectRef &>(ref).handle = resource_handle(ref);
252 }
253 return ref.handle;
254}
255
256inline ResourceHandle Manager::resource_handle(const ObjectRef &ref, float inflate_bounds)
257{
258 bool is_active_object = (ref.dupli_object ? ref.dupli_parent : ref.object) == object_active;
259 matrix_buf.current().get_or_resize(resource_len_).sync(*ref.object);
260 bounds_buf.current().get_or_resize(resource_len_).sync(*ref.object, inflate_bounds);
261 infos_buf.current().get_or_resize(resource_len_).sync(ref, is_active_object);
262 return ResourceHandle(resource_len_++, (ref.object->transflag & OB_NEG_SCALE) != 0);
263}
264
266 const float4x4 *model_matrix,
267 const float3 *bounds_center,
268 const float3 *bounds_half_extent)
269{
270 bool is_active_object = (ref.dupli_object ? ref.dupli_parent : ref.object) == object_active;
271 if (model_matrix) {
272 matrix_buf.current().get_or_resize(resource_len_).sync(*model_matrix);
273 }
274 else {
275 matrix_buf.current().get_or_resize(resource_len_).sync(*ref.object);
276 }
277 if (bounds_center && bounds_half_extent) {
278 bounds_buf.current().get_or_resize(resource_len_).sync(*bounds_center, *bounds_half_extent);
279 }
280 else {
281 bounds_buf.current().get_or_resize(resource_len_).sync(*ref.object);
282 }
283 infos_buf.current().get_or_resize(resource_len_).sync(ref, is_active_object);
284 return ResourceHandle(resource_len_++, (ref.object->transflag & OB_NEG_SCALE) != 0);
285}
286
288{
289 matrix_buf.current().get_or_resize(resource_len_).sync(model_matrix);
290 bounds_buf.current().get_or_resize(resource_len_).sync();
291 infos_buf.current().get_or_resize(resource_len_).sync();
292 return ResourceHandle(resource_len_++, false);
293}
294
296 const float3 &bounds_center,
297 const float3 &bounds_half_extent)
298{
299 matrix_buf.current().get_or_resize(resource_len_).sync(model_matrix);
300 bounds_buf.current().get_or_resize(resource_len_).sync(bounds_center, bounds_half_extent);
301 infos_buf.current().get_or_resize(resource_len_).sync();
302 return ResourceHandle(resource_len_++, false);
303}
304
306 const float4x4 &model_matrix)
307{
308 bool is_active_object = (ref.dupli_object ? ref.dupli_parent : ref.object) == object_active;
309 matrix_buf.current().get_or_resize(resource_len_).sync(model_matrix);
310 bounds_buf.current().get_or_resize(resource_len_).sync();
311 infos_buf.current().get_or_resize(resource_len_).sync(ref, is_active_object);
312 return ResourceHandle(resource_len_++, (ref.object->transflag & OB_NEG_SCALE) != 0);
313}
314
316 const ObjectRef &ref,
317 float inflate_bounds)
318{
319 bounds_buf.current()[handle.resource_index()].sync(*ref.object, inflate_bounds);
320}
321
323 const float3 &bounds_center,
324 const float3 &bounds_half_extent)
325{
326 bounds_buf.current()[handle.resource_index()].sync(bounds_center, bounds_half_extent);
327}
328
330 const ObjectRef &ref,
331 const GPUMaterial *material)
332{
333 ObjectInfos &infos = infos_buf.current().get_or_resize(handle.resource_index());
334 infos.object_attrs_offset = attribute_len_;
335
336 const GPUUniformAttrList *attr_list = GPU_material_uniform_attributes(material);
337 if (attr_list == nullptr) {
338 return;
339 }
340
341 LISTBASE_FOREACH (const GPUUniformAttr *, attr, &attr_list->list) {
342 if (attributes_buf.get_or_resize(attribute_len_).sync(ref, *attr)) {
343 infos.object_attrs_len++;
344 attribute_len_++;
345 }
346 }
347}
348
350 const ObjectRef &ref,
351 Span<GPUMaterial *> materials)
352{
353 ObjectInfos &infos = infos_buf.current().get_or_resize(handle.resource_index());
354 infos.object_attrs_offset = attribute_len_;
355
356 /* Simple cache solution to avoid duplicates. */
357 Vector<uint32_t, 4> hash_cache;
358
359 for (const GPUMaterial *mat : materials) {
361 if (attr_list == nullptr) {
362 continue;
363 }
364
365 LISTBASE_FOREACH (const GPUUniformAttr *, attr, &attr_list->list) {
367 if ((mat != materials.first()) && (hash_cache.first_index_of_try(attr->hash_code) != -1)) {
368 /* Attribute has already been added to the attribute buffer by another material. */
369 continue;
370 }
371 hash_cache.append(attr->hash_code);
372 if (attributes_buf.get_or_resize(attribute_len_).sync(ref, *attr)) {
373 infos.object_attrs_len++;
374 attribute_len_++;
375 }
376 }
377 }
378}
379
381{
382 const ListBase *attr_list = GPU_material_layer_attributes(material);
383
384 if (attr_list != nullptr) {
385 LISTBASE_FOREACH (const GPULayerAttr *, attr, attr_list) {
388 layer_attributes.add(attr->hash_code, *attr);
389 }
390 }
391}
392
393} // namespace blender::draw
394
395/* TODO(@fclem): This is for testing. The manager should be passed to the engine through the
396 * callbacks. */
A BVH for high poly meshes.
#define LISTBASE_FOREACH(type, var, list)
unsigned int uint
@ OB_NEG_SCALE
const ListBase * GPU_material_layer_attributes(const GPUMaterial *material)
const GPUUniformAttrList * GPU_material_uniform_attributes(const GPUMaterial *material)
void GPU_texture_ref(GPUTexture *texture)
Definition pass.h:49
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
void append(const T &value)
int64_t first_index_of_try(const T &value) const
LayerAttributeBuf layer_attributes_buf
void acquire_texture(GPUTexture *texture)
ResourceHandle unique_handle(const ObjectRef &ref)
void register_layer_attributes(GPUMaterial *material)
SwapChain< ObjectBoundsBuf, 2 > bounds_buf
ResourceHandle resource_handle_for_sculpt(const ObjectRef &ref)
SubmitDebugOutput submit_debug(PassSimple &pass, View &view)
ResourceHandle resource_handle_for_psys(const ObjectRef &ref, const float4x4 &model_matrix)
void extract_object_attributes(ResourceHandle handle, const ObjectRef &ref, const GPUMaterial *material)
SwapChain< ObjectInfosBuf, 2 > infos_buf
ObjectAttributeBuf attributes_buf
Map< uint32_t, GPULayerAttr > layer_attributes
uint resource_handle_count() const
Vector< GPUTexture * > acquired_textures
void update_handle_bounds(ResourceHandle handle, const ObjectRef &ref, float inflate_bounds=0.0f)
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()
blender::draw::Manager * DRW_manager_get()
blender::draw::ObjectRef DRW_object_ref_get(Object *object)
Bounds< float3 > bounds_get(const Tree &pbvh)
Definition pbvh.cc:1480
T midpoint(const T &a, const T &b)
short transflag
struct SculptSession * sculpt
std::unique_ptr< blender::bke::pbvh::Tree > pbvh
Definition BKE_paint.hh:408
DupliObject * dupli_object