Curves: Port legacy curve viewport drawing to the new data-block
Instead of using `CurveEval` to draw the curve wire edges, use
the new `Curves` data-block, which is already built as part of
an object's evaluated geometry set whenever there is a
`CurveComponent`.
This means that we can remove `Curve`'s temporary ownership
of `CurveEval` for drawing (added in 9ec12c26f1
),
which caused a memory leak as described in T96498.
In my testing this improved performance by around 1.5x during
viewport playback, back to the performance of 3.1 before the
curve data structure transition started.
The next step of using the GPU to do the final curve evaluation
for the viewport is described in T96455, but is unrelated.
Differential Revision: https://developer.blender.org/D14551
This commit is contained in:
parent
edcbf741df
commit
b84255f590
|
@ -123,8 +123,6 @@ static void curve_free_data(ID *id)
|
|||
MEM_SAFE_FREE(curve->str);
|
||||
MEM_SAFE_FREE(curve->strinfo);
|
||||
MEM_SAFE_FREE(curve->tb);
|
||||
|
||||
delete curve->curve_eval;
|
||||
}
|
||||
|
||||
static void curve_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
|
|
|
@ -1494,7 +1494,7 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
|
|||
* the CurveEval data type was introduced, when an evaluated object's curve data was just a
|
||||
* copy of the original curve and everything else ended up in #CurveCache. */
|
||||
CurveComponent &curve_component = geometry.get_component_for_write<CurveComponent>();
|
||||
cow_curve.curve_eval = curves_to_curve_eval(*curve_component.get_for_read()).release();
|
||||
cow_curve.curve_eval = curve_component.get_for_read();
|
||||
BKE_object_eval_assign_data(ob, &cow_curve.id, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ const Curve *CurveComponent::get_curve_for_render() const
|
|||
}
|
||||
|
||||
curve_for_render_ = (Curve *)BKE_id_new_nomain(ID_CU_LEGACY, nullptr);
|
||||
curve_for_render_->curve_eval = curves_to_curve_eval(*curves_).release();
|
||||
curve_for_render_->curve_eval = curves_;
|
||||
|
||||
return curve_for_render_;
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
#include "DNA_curve_types.h"
|
||||
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_displist.h"
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_spline.hh"
|
||||
#include "BKE_vfont.h"
|
||||
|
||||
#include "GPU_batch.h"
|
||||
|
@ -96,18 +96,19 @@ static void curve_render_overlay_verts_edges_len_get(ListBase *lb,
|
|||
}
|
||||
}
|
||||
|
||||
static void curve_eval_render_wire_verts_edges_len_get(const CurveEval &curve_eval,
|
||||
static void curve_eval_render_wire_verts_edges_len_get(const blender::bke::CurvesGeometry &curves,
|
||||
int *r_curve_len,
|
||||
int *r_vert_len,
|
||||
int *r_edge_len)
|
||||
{
|
||||
Span<SplinePtr> splines = curve_eval.splines();
|
||||
*r_curve_len = splines.size();
|
||||
*r_vert_len = 0;
|
||||
*r_curve_len = curves.curves_num();
|
||||
*r_vert_len = curves.evaluated_points_num();
|
||||
|
||||
*r_edge_len = 0;
|
||||
for (const SplinePtr &spline : splines) {
|
||||
*r_vert_len += spline->evaluated_points_size();
|
||||
*r_edge_len += spline->evaluated_edges_size();
|
||||
const blender::VArray<bool> cyclic = curves.cyclic();
|
||||
for (const int i : curves.curves_range()) {
|
||||
const IndexRange points = curves.evaluated_points_for_curve(i);
|
||||
*r_edge_len += blender::bke::curves::curve_segment_size(points.size(), cyclic[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +166,7 @@ struct CurveRenderData {
|
|||
CurveCache *ob_curve_cache;
|
||||
|
||||
/* Owned by the evaluated object's geometry set (#geometry_set_eval). */
|
||||
const CurveEval *curve_eval;
|
||||
const Curves *curve_eval;
|
||||
|
||||
/* borrow from 'Curve' */
|
||||
ListBase *nurbs;
|
||||
|
@ -209,10 +210,11 @@ static CurveRenderData *curve_render_data_create(Curve *cu,
|
|||
|
||||
if (types & CU_DATATYPE_WIRE) {
|
||||
if (rdata->curve_eval != nullptr) {
|
||||
curve_eval_render_wire_verts_edges_len_get(*rdata->curve_eval,
|
||||
&rdata->wire.curve_len,
|
||||
&rdata->wire.vert_len,
|
||||
&rdata->wire.edge_len);
|
||||
curve_eval_render_wire_verts_edges_len_get(
|
||||
blender::bke::CurvesGeometry::wrap(rdata->curve_eval->geometry),
|
||||
&rdata->wire.curve_len,
|
||||
&rdata->wire.vert_len,
|
||||
&rdata->wire.edge_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,18 +468,10 @@ static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curv
|
|||
GPU_vertbuf_init_with_format(vbo_curves_pos, &format);
|
||||
GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len);
|
||||
|
||||
const CurveEval &curve_eval = *rdata->curve_eval;
|
||||
Span<SplinePtr> splines = curve_eval.splines();
|
||||
Array<int> offsets = curve_eval.evaluated_point_offsets();
|
||||
BLI_assert(offsets.last() == vert_len);
|
||||
|
||||
for (const int i_spline : splines.index_range()) {
|
||||
Span<float3> positions = splines[i_spline]->evaluated_positions();
|
||||
for (const int i_point : positions.index_range()) {
|
||||
GPU_vertbuf_attr_set(
|
||||
vbo_curves_pos, attr_id.pos, offsets[i_spline] + i_point, positions[i_point]);
|
||||
}
|
||||
}
|
||||
const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
|
||||
rdata->curve_eval->geometry);
|
||||
const Span<float3> positions = curves.evaluated_positions();
|
||||
GPU_vertbuf_attr_fill(vbo_curves_pos, attr_id.pos, positions.data());
|
||||
}
|
||||
|
||||
static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines)
|
||||
|
@ -495,18 +489,16 @@ static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_c
|
|||
GPUIndexBufBuilder elb;
|
||||
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
|
||||
|
||||
const CurveEval &curve_eval = *rdata->curve_eval;
|
||||
Span<SplinePtr> splines = curve_eval.splines();
|
||||
Array<int> offsets = curve_eval.evaluated_point_offsets();
|
||||
BLI_assert(offsets.last() == vert_len);
|
||||
|
||||
for (const int i_spline : splines.index_range()) {
|
||||
const int eval_size = splines[i_spline]->evaluated_points_size();
|
||||
if (splines[i_spline]->is_cyclic() && splines[i_spline]->evaluated_edges_size() > 1) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + eval_size - 1);
|
||||
const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
|
||||
rdata->curve_eval->geometry);
|
||||
const blender::VArray<bool> cyclic = curves.cyclic();
|
||||
for (const int i : curves.curves_range()) {
|
||||
const IndexRange points = curves.evaluated_points_for_curve(i);
|
||||
if (cyclic[i] && points.size() > 1) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, points.last());
|
||||
}
|
||||
for (const int i_point : IndexRange(eval_size)) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + i_point);
|
||||
for (const int i_point : points) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, i_point);
|
||||
}
|
||||
GPU_indexbuf_add_primitive_restart(&elb);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ extern "C" {
|
|||
#define MAXTEXTBOX 256 /* used in readfile.c and editfont.c */
|
||||
|
||||
struct AnimData;
|
||||
struct CurveEval;
|
||||
struct Curves;
|
||||
struct CurveProfile;
|
||||
struct EditFont;
|
||||
struct GHash;
|
||||
|
@ -291,7 +291,7 @@ typedef struct Curve {
|
|||
* since it also contains the result of geometry nodes evaluation, and isn't just a copy of the
|
||||
* original object data.
|
||||
*/
|
||||
struct CurveEval *curve_eval;
|
||||
const struct Curves *curve_eval;
|
||||
|
||||
void *batch_cache;
|
||||
} Curve;
|
||||
|
|
Loading…
Reference in New Issue