The initial goal of this PR is to avoid creating vertex and index buffers as part of the "request" phase of the drawing loop. Conflating requesting and creating index buffers might not sound so bad, but it ends up significantly complicating the whole process. It is also incompatible with a future buffer cache that would allow avoiding re-uploading mesh buffers. Specifically, this means removing the use of `DRW_vbo_request` and `DRW_ibo_request` from the mesh batch extraction process. Instead, a list of buffer types is gathered based on the requested batches. Then that list is filtered to find the batches that haven't been requested yet. Overall I find the new process much easier to understand. A few examples of simplifications this allows are avoiding allocating `MeshRenderData` on the heap, and the removal of its `use_final_mesh` member. That's just replaced by passing the necessary information through the call stack. Another notable difference is that for meshes, EEVEE's velocity module now requests a batch that contains the buffer rather than just requesting the buffer itself. This is just simpler to get working since it doesn't require a separate code path. The task graph argument for extraction is unused after this change. It wasn't used effectively anyway; a simpler method of multithreading extractions is used in this PR. I didn't remove it completely because it will probably be repurposed in the next step of this project. The next step in this project is to replace `MeshBufferList` with a global cache that's keyed based on the mesh data that compromises each batch, when possible (i.e. for non edit-mode meshes). This changes above should be applied to other object types too. Pull Request: https://projects.blender.org/blender/blender/pulls/135699
673 lines
20 KiB
C++
673 lines
20 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup draw
|
|
*/
|
|
|
|
#include "DNA_curve_types.h"
|
|
#include "DNA_curves_types.h"
|
|
#include "DNA_grease_pencil_types.h"
|
|
#include "DNA_lattice_types.h"
|
|
#include "DNA_mesh_types.h"
|
|
#include "DNA_modifier_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_particle_types.h"
|
|
#include "DNA_pointcloud_types.h"
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_volume_types.h"
|
|
|
|
#include "BLI_ghash.h"
|
|
#include "BLI_listbase.h"
|
|
#include "BLI_string.h"
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "BKE_context.hh"
|
|
#include "BKE_mesh_wrapper.hh"
|
|
#include "BKE_object.hh"
|
|
#include "BKE_subdiv_modifier.hh"
|
|
|
|
#include "DRW_render.hh"
|
|
#include "GPU_batch.hh"
|
|
#include "GPU_batch_utils.hh"
|
|
#include "GPU_capabilities.hh"
|
|
|
|
#include "draw_cache.hh"
|
|
#include "draw_cache_impl.hh"
|
|
#include "draw_context_private.hh"
|
|
|
|
using blender::Span;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Internal Defines
|
|
* \{ */
|
|
|
|
#define VCLASS_LIGHT_AREA_SHAPE (1 << 0)
|
|
#define VCLASS_LIGHT_SPOT_SHAPE (1 << 1)
|
|
#define VCLASS_LIGHT_SPOT_BLEND (1 << 2)
|
|
#define VCLASS_LIGHT_SPOT_CONE (1 << 3)
|
|
#define VCLASS_LIGHT_DIST (1 << 4)
|
|
|
|
#define VCLASS_CAMERA_FRAME (1 << 5)
|
|
#define VCLASS_CAMERA_DIST (1 << 6)
|
|
#define VCLASS_CAMERA_VOLUME (1 << 7)
|
|
|
|
#define VCLASS_SCREENSPACE (1 << 8)
|
|
#define VCLASS_SCREENALIGNED (1 << 9)
|
|
|
|
#define VCLASS_EMPTY_SCALED (1 << 10)
|
|
#define VCLASS_EMPTY_AXES (1 << 11)
|
|
#define VCLASS_EMPTY_AXES_NAME (1 << 12)
|
|
#define VCLASS_EMPTY_AXES_SHADOW (1 << 13)
|
|
#define VCLASS_EMPTY_SIZE (1 << 14)
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Common
|
|
* \{ */
|
|
|
|
namespace blender::draw {
|
|
|
|
void DRW_vertbuf_create_wiredata(blender::gpu::VertBuf *vbo, const int vert_len)
|
|
{
|
|
static struct {
|
|
uint wd;
|
|
} attr_id;
|
|
|
|
static const GPUVertFormat format = [&]() {
|
|
GPUVertFormat format{};
|
|
/* initialize vertex format */
|
|
if (!GPU_crappy_amd_driver()) {
|
|
/* Some AMD drivers strangely crash with a vbo with this format. */
|
|
attr_id.wd = GPU_vertformat_attr_add(
|
|
&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
|
|
}
|
|
else {
|
|
attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
|
}
|
|
return format;
|
|
}();
|
|
|
|
GPU_vertbuf_init_with_format(*vbo, format);
|
|
GPU_vertbuf_data_alloc(*vbo, vert_len);
|
|
|
|
if (GPU_vertbuf_get_format(vbo)->stride == 1) {
|
|
memset(vbo->data<uint8_t>().data(), 0xFF, size_t(vert_len));
|
|
}
|
|
else {
|
|
GPUVertBufRaw wd_step;
|
|
GPU_vertbuf_attr_get_raw_data(vbo, attr_id.wd, &wd_step);
|
|
for (int i = 0; i < vert_len; i++) {
|
|
*((float *)GPU_vertbuf_raw_step(&wd_step)) = 1.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace blender::draw
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Common Object API
|
|
*
|
|
* \note Curve and text objects evaluate to the evaluated geometry set's mesh component if
|
|
* they have a surface, so curve objects themselves do not have a surface (the mesh component
|
|
* is presented to render engines as a separate object).
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_object_all_edges_get(Object *ob)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_all_edges_get(ob);
|
|
/* TODO: should match #DRW_cache_object_surface_get. */
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_edge_detection_get(ob, r_is_manifold);
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_object_face_wireframe_get(const Scene *scene, Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_face_wireframe_get(ob);
|
|
case OB_POINTCLOUD:
|
|
return DRW_pointcloud_batch_cache_get_dots(ob);
|
|
case OB_VOLUME:
|
|
return DRW_cache_volume_face_wireframe_get(ob);
|
|
case OB_GREASE_PENCIL:
|
|
return DRW_cache_grease_pencil_face_wireframe_get(scene, ob);
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_object_loose_edges_get(Object *ob)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_loose_edges_get(ob);
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_object_surface_get(Object *ob)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_surface_get(ob);
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
Span<blender::gpu::Batch *> DRW_cache_object_surface_material_get(
|
|
Object *ob, const Span<const GPUMaterial *> materials)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
return DRW_cache_mesh_surface_shaded_get(ob, materials);
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Meshes
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_all_verts_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_all_verts(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_all_edges_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_all_edges(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_loose_edges_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_loose_edges(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_edge_detection(DRW_object_get_data_for_drawing<Mesh>(*ob),
|
|
r_is_manifold);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_edges_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_edges(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
Span<blender::gpu::Batch *> DRW_cache_mesh_surface_shaded_get(
|
|
Object *ob, const blender::Span<const GPUMaterial *> materials)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_shaded(
|
|
*ob, DRW_object_get_data_for_drawing<Mesh>(*ob), materials);
|
|
}
|
|
|
|
Span<blender::gpu::Batch *> DRW_cache_mesh_surface_texpaint_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_texpaint(*ob,
|
|
DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_texpaint_single(
|
|
*ob, DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_vertpaint_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_vertpaint(*ob,
|
|
DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_sculptcolors_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_sculpt(*ob, DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_weights_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_weights(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_face_wireframe_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_wireframes_face(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_edit_mesh_analysis(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_mesh_surface_viewer_attribute_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_MESH);
|
|
return DRW_mesh_batch_cache_get_surface_viewer_attribute(
|
|
DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Curve
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_edge_wire_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_CURVES_LEGACY);
|
|
Curve &cu = DRW_object_get_data_for_drawing<Curve>(*ob);
|
|
return DRW_curve_batch_cache_get_wire_edge(&cu);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_edge_wire_viewer_attribute_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_CURVES_LEGACY);
|
|
Curve &cu = DRW_object_get_data_for_drawing<Curve>(*ob);
|
|
return DRW_curve_batch_cache_get_wire_edge_viewer_attribute(&cu);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_edge_normal_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_CURVES_LEGACY);
|
|
Curve &cu = DRW_object_get_data_for_drawing<Curve>(*ob);
|
|
return DRW_curve_batch_cache_get_normal_edge(&cu);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_edge_overlay_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF));
|
|
|
|
Curve &cu = DRW_object_get_data_for_drawing<Curve>(*ob);
|
|
return DRW_curve_batch_cache_get_edit_edges(&cu);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_curve_vert_overlay_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF));
|
|
|
|
Curve &cu = DRW_object_get_data_for_drawing<Curve>(*ob);
|
|
return DRW_curve_batch_cache_get_edit_verts(&cu);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Font
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_text_edge_wire_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_FONT);
|
|
Curve &cu = DRW_object_get_data_for_drawing<Curve>(*ob);
|
|
return DRW_curve_batch_cache_get_wire_edge(&cu);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Surface
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_surf_edge_wire_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_SURF);
|
|
Curve &cu = DRW_object_get_data_for_drawing<Curve>(*ob);
|
|
return DRW_curve_batch_cache_get_wire_edge(&cu);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Lattice
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_lattice_verts_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_LATTICE);
|
|
|
|
Lattice < = DRW_object_get_data_for_drawing<Lattice>(*ob);
|
|
return DRW_lattice_batch_cache_get_all_verts(<);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_LATTICE);
|
|
|
|
Lattice < = DRW_object_get_data_for_drawing<Lattice>(*ob);
|
|
int actdef = -1;
|
|
|
|
if (use_weight && !BLI_listbase_is_empty(<.vertex_group_names) && lt.editlatt->latt->dvert) {
|
|
actdef = lt.vertex_group_active_index - 1;
|
|
}
|
|
|
|
return DRW_lattice_batch_cache_get_all_edges(<, use_weight, actdef);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_lattice_vert_overlay_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_LATTICE);
|
|
|
|
Lattice < = DRW_object_get_data_for_drawing<Lattice>(*ob);
|
|
return DRW_lattice_batch_cache_get_edit_verts(<);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name PointCloud
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_pointcloud_vert_overlay_get(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
BLI_assert(ob->type == OB_POINTCLOUD);
|
|
|
|
PointCloud &pointcloud = DRW_object_get_data_for_drawing<PointCloud>(*ob);
|
|
return DRW_pointcloud_batch_cache_get_edit_dots(&pointcloud);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Volume
|
|
* \{ */
|
|
|
|
namespace blender::draw {
|
|
|
|
blender::gpu::Batch *DRW_cache_volume_face_wireframe_get(Object *ob)
|
|
{
|
|
BLI_assert(ob->type == OB_VOLUME);
|
|
return DRW_volume_batch_cache_get_wireframes_face(&DRW_object_get_data_for_drawing<Volume>(*ob));
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_volume_selection_surface_get(Object *ob)
|
|
{
|
|
BLI_assert(ob->type == OB_VOLUME);
|
|
return DRW_volume_batch_cache_get_selection_surface(
|
|
&DRW_object_get_data_for_drawing<Volume>(*ob));
|
|
}
|
|
|
|
} // namespace blender::draw
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Particles
|
|
* \{ */
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_hair(Object *object,
|
|
ParticleSystem *psys,
|
|
ModifierData *md)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_hair(object, psys, md);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_dots(Object *object, ParticleSystem *psys)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_dots(object, psys);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_edit_strands(Object *object,
|
|
ParticleSystem *psys,
|
|
PTCacheEdit *edit,
|
|
bool use_weight)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_edit_strands(object, psys, edit, use_weight);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_edit_inner_points(Object *object,
|
|
ParticleSystem *psys,
|
|
PTCacheEdit *edit)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_edit_inner_points(object, psys, edit);
|
|
}
|
|
|
|
blender::gpu::Batch *DRW_cache_particles_get_edit_tip_points(Object *object,
|
|
ParticleSystem *psys,
|
|
PTCacheEdit *edit)
|
|
{
|
|
using namespace blender::draw;
|
|
return DRW_particles_batch_cache_get_edit_tip_points(object, psys, edit);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Batch Cache Implementation (common)
|
|
* \{ */
|
|
|
|
void drw_batch_cache_validate(Object *ob)
|
|
{
|
|
using namespace blender::draw;
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
DRW_mesh_batch_cache_validate(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
|
break;
|
|
case OB_CURVES_LEGACY:
|
|
case OB_FONT:
|
|
case OB_SURF:
|
|
DRW_curve_batch_cache_validate(&DRW_object_get_data_for_drawing<Curve>(*ob));
|
|
break;
|
|
case OB_LATTICE:
|
|
DRW_lattice_batch_cache_validate(&DRW_object_get_data_for_drawing<Lattice>(*ob));
|
|
break;
|
|
case OB_CURVES:
|
|
DRW_curves_batch_cache_validate(&DRW_object_get_data_for_drawing<Curves>(*ob));
|
|
break;
|
|
case OB_POINTCLOUD:
|
|
DRW_pointcloud_batch_cache_validate(&DRW_object_get_data_for_drawing<PointCloud>(*ob));
|
|
break;
|
|
case OB_VOLUME:
|
|
DRW_volume_batch_cache_validate(&DRW_object_get_data_for_drawing<Volume>(*ob));
|
|
break;
|
|
case OB_GREASE_PENCIL:
|
|
DRW_grease_pencil_batch_cache_validate(&DRW_object_get_data_for_drawing<GreasePencil>(*ob));
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void drw_batch_cache_generate_requested(Object *ob, TaskGraph &task_graph)
|
|
{
|
|
using namespace blender::draw;
|
|
const DRWContext *draw_ctx = DRW_context_get();
|
|
const Scene *scene = draw_ctx->scene;
|
|
const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
|
|
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
|
|
const bool is_paint_mode = ELEM(
|
|
mode, CTX_MODE_SCULPT, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_WEIGHT);
|
|
|
|
const bool use_hide = ((ob->type == OB_MESH) &&
|
|
((is_paint_mode && (ob == draw_ctx->obact) &&
|
|
DRW_object_use_hide_faces(ob)) ||
|
|
((mode == CTX_MODE_EDIT_MESH) && (ob->mode == OB_MODE_EDIT))));
|
|
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
DRW_mesh_batch_cache_create_requested(task_graph,
|
|
*ob,
|
|
DRW_object_get_data_for_drawing<Mesh>(*ob),
|
|
*scene,
|
|
is_paint_mode,
|
|
use_hide);
|
|
break;
|
|
case OB_CURVES_LEGACY:
|
|
case OB_FONT:
|
|
case OB_SURF:
|
|
DRW_curve_batch_cache_create_requested(ob, scene);
|
|
break;
|
|
case OB_CURVES:
|
|
DRW_curves_batch_cache_create_requested(ob);
|
|
break;
|
|
case OB_POINTCLOUD:
|
|
DRW_pointcloud_batch_cache_create_requested(ob);
|
|
break;
|
|
/* TODO: all cases. */
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void drw_batch_cache_generate_requested_evaluated_mesh_or_curve(Object *ob, TaskGraph &task_graph)
|
|
{
|
|
using namespace blender::draw;
|
|
/* NOTE: Logic here is duplicated from #drw_batch_cache_generate_requested. */
|
|
|
|
const DRWContext *draw_ctx = DRW_context_get();
|
|
const Scene *scene = draw_ctx->scene;
|
|
const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
|
|
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
|
|
const bool is_paint_mode = ELEM(
|
|
mode, CTX_MODE_SCULPT, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_WEIGHT);
|
|
|
|
const bool use_hide = ((ob->type == OB_MESH) &&
|
|
((is_paint_mode && (ob == draw_ctx->obact) &&
|
|
DRW_object_use_hide_faces(ob)) ||
|
|
((mode == CTX_MODE_EDIT_MESH) && (ob->mode == OB_MODE_EDIT))));
|
|
|
|
Mesh *mesh = BKE_object_get_evaluated_mesh_no_subsurf_unchecked(ob);
|
|
/* Try getting the mesh first and if that fails, try getting the curve data.
|
|
* If the curves are surfaces or have certain modifiers applied to them, the will have mesh data
|
|
* of the final result.
|
|
*/
|
|
if (mesh != nullptr) {
|
|
DRW_mesh_batch_cache_create_requested(task_graph, *ob, *mesh, *scene, is_paint_mode, use_hide);
|
|
}
|
|
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_FONT, OB_SURF)) {
|
|
DRW_curve_batch_cache_create_requested(ob, scene);
|
|
}
|
|
}
|
|
|
|
void drw_batch_cache_generate_requested_delayed(Object *ob)
|
|
{
|
|
DRWContext &draw_ctx = drw_get();
|
|
if (draw_ctx.delayed_extraction == nullptr) {
|
|
draw_ctx.delayed_extraction = BLI_gset_ptr_new(__func__);
|
|
}
|
|
BLI_gset_add(draw_ctx.delayed_extraction, ob);
|
|
}
|
|
|
|
namespace blender::draw {
|
|
void DRW_batch_cache_free_old(Object *ob, int ctime)
|
|
{
|
|
switch (ob->type) {
|
|
case OB_MESH:
|
|
DRW_mesh_batch_cache_free_old(&DRW_object_get_data_for_drawing<Mesh>(*ob), ctime);
|
|
break;
|
|
case OB_CURVES:
|
|
DRW_curves_batch_cache_free_old(&DRW_object_get_data_for_drawing<Curves>(*ob), ctime);
|
|
break;
|
|
case OB_POINTCLOUD:
|
|
DRW_pointcloud_batch_cache_free_old(&DRW_object_get_data_for_drawing<PointCloud>(*ob),
|
|
ctime);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} // namespace blender::draw
|
|
|
|
/** \} */
|
|
|
|
void DRW_cdlayer_attr_aliases_add(GPUVertFormat *format,
|
|
const char *base_name,
|
|
const int data_type,
|
|
const char *layer_name,
|
|
bool is_active_render,
|
|
bool is_active_layer)
|
|
{
|
|
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
|
|
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
|
|
|
|
/* Attribute layer name. */
|
|
SNPRINTF(attr_name, "%s%s", base_name, attr_safe_name);
|
|
GPU_vertformat_alias_add(format, attr_name);
|
|
|
|
/* Auto layer name. */
|
|
SNPRINTF(attr_name, "a%s", attr_safe_name);
|
|
GPU_vertformat_alias_add(format, attr_name);
|
|
|
|
/* Active render layer name. */
|
|
if (is_active_render) {
|
|
GPU_vertformat_alias_add(format, data_type == CD_PROP_FLOAT2 ? "a" : base_name);
|
|
}
|
|
|
|
/* Active display layer name. */
|
|
if (is_active_layer) {
|
|
SNPRINTF(attr_name, "a%s", base_name);
|
|
GPU_vertformat_alias_add(format, attr_name);
|
|
}
|
|
}
|