diff options
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_curves.cc')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_curves.cc | 184 |
1 files changed, 88 insertions, 96 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc index 3bca17d9c56..0322d048fa5 100644 --- a/source/blender/draw/intern/draw_cache_impl_curves.cc +++ b/source/blender/draw/intern/draw_cache_impl_curves.cc @@ -14,9 +14,9 @@ #include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_math_vec_types.hh" -#include "BLI_math_vector.h" #include "BLI_math_vector.hh" #include "BLI_span.hh" +#include "BLI_task.hh" #include "BLI_utildefines.h" #include "DNA_curves_types.h" @@ -60,7 +60,7 @@ struct CurvesBatchCache { * some locking would be necessary because multiple objects can use the same curves data with * different materials, etc. This is a placeholder to make multi-threading easier in the future. */ - ThreadMutex render_mutex; + std::mutex render_mutex; }; static bool curves_batch_cache_valid(const Curves &curves) @@ -74,15 +74,13 @@ static void curves_batch_cache_init(Curves &curves) CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves.batch_cache); if (!cache) { - cache = MEM_cnew<CurvesBatchCache>(__func__); + cache = MEM_new<CurvesBatchCache>(__func__); curves.batch_cache = cache; } else { - memset(cache, 0, sizeof(*cache)); + cache->curves_cache = {}; } - BLI_mutex_init(&cache->render_mutex); - cache->is_dirty = false; } @@ -90,13 +88,11 @@ static void curves_discard_attributes(CurvesEvalCache &curves_cache) { for (const int i : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_attributes_buf[i]); - DRW_TEXTURE_FREE_SAFE(curves_cache.proc_attributes_tex[i]); } for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { for (const int j : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].attributes_buf[j]); - DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].attributes_tex[j]); } drw_attributes_clear(&curves_cache.final[i].attr_used); @@ -108,17 +104,13 @@ static void curves_batch_cache_clear_data(CurvesEvalCache &curves_cache) /* TODO: more granular update tagging. */ GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_point_buf); GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_length_buf); - DRW_TEXTURE_FREE_SAFE(curves_cache.point_tex); - DRW_TEXTURE_FREE_SAFE(curves_cache.length_tex); + GPU_VERTBUF_DISCARD_SAFE(curves_cache.data_edit_points); GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_strand_buf); GPU_VERTBUF_DISCARD_SAFE(curves_cache.proc_strand_seg_buf); - DRW_TEXTURE_FREE_SAFE(curves_cache.strand_tex); - DRW_TEXTURE_FREE_SAFE(curves_cache.strand_seg_tex); for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { GPU_VERTBUF_DISCARD_SAFE(curves_cache.final[i].proc_buf); - DRW_TEXTURE_FREE_SAFE(curves_cache.final[i].proc_tex); for (const int j : IndexRange(MAX_THICKRES)) { GPU_BATCH_DISCARD_SAFE(curves_cache.final[i].proc_hairs[j]); } @@ -171,9 +163,8 @@ void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode) void DRW_curves_batch_cache_free(Curves *curves) { curves_batch_cache_clear(*curves); - CurvesBatchCache *cache = static_cast<CurvesBatchCache *>(curves->batch_cache); - BLI_mutex_end(&cache->render_mutex); - MEM_SAFE_FREE(curves->batch_cache); + MEM_delete(static_cast<CurvesBatchCache *>(curves->batch_cache)); + curves->batch_cache = nullptr; } void DRW_curves_batch_cache_free_old(Curves *curves, int ctime) @@ -225,43 +216,43 @@ static void curves_batch_cache_fill_segments_proc_pos( MutableSpan<PositionAndParameter> posTime_data, MutableSpan<float> hairLength_data) { + using namespace blender; /* TODO: use hair radius layer if available. */ - const int curve_num = curves_id.geometry.curve_num; - const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap( - curves_id.geometry); - Span<float3> positions = curves.positions(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + const Span<float3> positions = curves.positions(); - for (const int i_curve : IndexRange(curve_num)) { - const IndexRange points = curves.points_for_curve(i_curve); + threading::parallel_for(curves.curves_range(), 1024, [&](const IndexRange range) { + for (const int i_curve : range) { + const IndexRange points = curves.points_for_curve(i_curve); - Span<float3> curve_positions = positions.slice(points); - MutableSpan<PositionAndParameter> curve_posTime_data = posTime_data.slice(points); + Span<float3> curve_positions = positions.slice(points); + MutableSpan<PositionAndParameter> curve_posTime_data = posTime_data.slice(points); - float total_len = 0.0f; - for (const int i_point : curve_positions.index_range()) { - if (i_point > 0) { - total_len += blender::math::distance(curve_positions[i_point - 1], - curve_positions[i_point]); - } - curve_posTime_data[i_point].position = curve_positions[i_point]; - curve_posTime_data[i_point].parameter = total_len; - } - hairLength_data[i_curve] = total_len; - - /* Assign length value. */ - if (total_len > 0.0f) { - const float factor = 1.0f / total_len; - /* Divide by total length to have a [0-1] number. */ + float total_len = 0.0f; for (const int i_point : curve_positions.index_range()) { - curve_posTime_data[i_point].parameter *= factor; + if (i_point > 0) { + total_len += math::distance(curve_positions[i_point - 1], curve_positions[i_point]); + } + curve_posTime_data[i_point].position = curve_positions[i_point]; + curve_posTime_data[i_point].parameter = total_len; + } + hairLength_data[i_curve] = total_len; + + /* Assign length value. */ + if (total_len > 0.0f) { + const float factor = 1.0f / total_len; + /* Divide by total length to have a [0-1] number. */ + for (const int i_point : curve_positions.index_range()) { + curve_posTime_data[i_point].parameter *= factor; + } } } - } + }); } static void curves_batch_cache_ensure_procedural_pos(const Curves &curves, CurvesEvalCache &cache, - GPUMaterial *gpu_material) + GPUMaterial *UNUSED(gpu_material)) { if (cache.proc_point_buf == nullptr || DRW_vbo_requested(cache.proc_point_buf)) { /* Initialize vertex format. */ @@ -274,7 +265,7 @@ static void curves_batch_cache_ensure_procedural_pos(const Curves &curves, GPU_vertbuf_data_alloc(cache.proc_point_buf, cache.point_len); MutableSpan posTime_data{ - reinterpret_cast<PositionAndParameter *>(GPU_vertbuf_get_data(cache.proc_point_buf)), + static_cast<PositionAndParameter *>(GPU_vertbuf_get_data(cache.proc_point_buf)), cache.point_len}; GPUVertFormat length_format = {0}; @@ -284,25 +275,47 @@ static void curves_batch_cache_ensure_procedural_pos(const Curves &curves, &length_format, GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY); GPU_vertbuf_data_alloc(cache.proc_length_buf, cache.strands_len); - MutableSpan hairLength_data{ - reinterpret_cast<float *>(GPU_vertbuf_get_data(cache.proc_length_buf)), cache.strands_len}; + MutableSpan hairLength_data{static_cast<float *>(GPU_vertbuf_get_data(cache.proc_length_buf)), + cache.strands_len}; curves_batch_cache_fill_segments_proc_pos(curves, posTime_data, hairLength_data); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache.proc_point_buf); - cache.point_tex = GPU_texture_create_from_vertbuf("hair_point", cache.proc_point_buf); } +} - if (gpu_material && cache.proc_length_buf != nullptr && cache.length_tex) { - ListBase gpu_attrs = GPU_material_attributes(gpu_material); - LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &gpu_attrs) { - if (attr->type == CD_HAIRLENGTH) { - GPU_vertbuf_use(cache.proc_length_buf); - cache.length_tex = GPU_texture_create_from_vertbuf("hair_length", cache.proc_length_buf); - break; +static void curves_batch_cache_ensure_data_edit_points(const Curves &curves_id, + CurvesEvalCache &cache) +{ + using namespace blender; + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + + static GPUVertFormat format_data = {0}; + uint data = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U8, 1, GPU_FETCH_INT); + GPU_vertbuf_init_with_format(cache.data_edit_points, &format_data); + GPU_vertbuf_data_alloc(cache.data_edit_points, curves.points_num()); + + VArray<float> selection; + switch (curves_id.selection_domain) { + case ATTR_DOMAIN_POINT: + selection = curves.selection_point_float(); + for (const int point_i : selection.index_range()) { + uint8_t vflag = 0; + const float point_selection = selection[point_i]; + SET_FLAG_FROM_TEST(vflag, (point_selection > 0.0f), VFLAG_VERT_SELECTED); + GPU_vertbuf_attr_set(cache.data_edit_points, data, point_i, &vflag); } - } + break; + case ATTR_DOMAIN_CURVE: + selection = curves.selection_curve_float(); + for (const int curve_i : curves.curves_range()) { + uint8_t vflag = 0; + const float curve_selection = selection[curve_i]; + SET_FLAG_FROM_TEST(vflag, (curve_selection > 0.0f), VFLAG_VERT_SELECTED); + const IndexRange points = curves.points_for_curve(curve_i); + for (const int point_i : points) { + GPU_vertbuf_attr_set(cache.data_edit_points, data, point_i, &vflag); + } + } + break; } } @@ -318,7 +331,7 @@ static void curves_batch_cache_ensure_procedural_final_attr(CurvesEvalCache &cac const GPUVertFormat *format, const int subdiv, const int index, - const char *name) + const char *UNUSED(name)) { CurvesEvalFinalCache &final_cache = cache.final[subdiv]; final_cache.attributes_buf[index] = GPU_vertbuf_create_with_format_ex( @@ -328,12 +341,6 @@ static void curves_batch_cache_ensure_procedural_final_attr(CurvesEvalCache &cac /* Those are points! not line segments. */ GPU_vertbuf_data_alloc(final_cache.attributes_buf[index], final_cache.strands_res * cache.strands_len); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(final_cache.attributes_buf[index]); - - final_cache.attributes_tex[index] = GPU_texture_create_from_vertbuf( - name, final_cache.attributes_buf[index]); } static void curves_batch_ensure_attribute(const Curves &curves, @@ -342,8 +349,8 @@ static void curves_batch_ensure_attribute(const Curves &curves, const int subdiv, const int index) { + using namespace blender; GPU_VERTBUF_DISCARD_SAFE(cache.proc_attributes_buf[index]); - DRW_TEXTURE_FREE_SAFE(cache.proc_attributes_tex[index]); char sampler_name[32]; drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name); @@ -361,15 +368,15 @@ static void curves_batch_ensure_attribute(const Curves &curves, request.domain == ATTR_DOMAIN_POINT ? curves.geometry.point_num : curves.geometry.curve_num); - const blender::bke::AttributeAccessor attributes = - blender::bke::CurvesGeometry::wrap(curves.geometry).attributes(); + const bke::AttributeAccessor attributes = + bke::CurvesGeometry::wrap(curves.geometry).attributes(); /* TODO(@kevindietrich): float4 is used for scalar attributes as the implicit conversion done * by OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following * the Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a * similar texture state swizzle to map the attribute correctly as for volume attributes, so we * can control the conversion ourselves. */ - blender::VArray<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>( + VArray<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>( request.attribute_name, request.domain, {0.0f, 0.0f, 0.0f, 1.0f}); MutableSpan<ColorGeometry4f> vbo_span{ @@ -378,13 +385,9 @@ static void curves_batch_ensure_attribute(const Curves &curves, attribute.materialize(vbo_span); - GPU_vertbuf_use(attr_vbo); - cache.proc_attributes_tex[index] = GPU_texture_create_from_vertbuf(sampler_name, attr_vbo); - /* Existing final data may have been for a different attribute (with a different name or domain), * free the data. */ GPU_VERTBUF_DISCARD_SAFE(cache.final[subdiv].attributes_buf[index]); - DRW_TEXTURE_FREE_SAFE(cache.final[subdiv].attributes_tex[index]); /* Ensure final data for points. */ if (request.domain == ATTR_DOMAIN_POINT) { @@ -430,19 +433,11 @@ static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves, GPU_vertbuf_attr_get_raw_data(cache.proc_strand_seg_buf, seg_id, &seg_step); curves_batch_cache_fill_strands_data(curves, data_step, seg_step); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache.proc_strand_buf); - cache.strand_tex = GPU_texture_create_from_vertbuf("curves_strand", cache.proc_strand_buf); - - GPU_vertbuf_use(cache.proc_strand_seg_buf); - cache.strand_seg_tex = GPU_texture_create_from_vertbuf("curves_strand_seg", - cache.proc_strand_seg_buf); } static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &cache, int subdiv) { - /* Same format as point_tex. */ + /* Same format as proc_point_buf. */ GPUVertFormat format = {0}; GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); @@ -453,12 +448,6 @@ static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &c /* Those are points! not line segments. */ GPU_vertbuf_data_alloc(cache.final[subdiv].proc_buf, cache.final[subdiv].strands_res * cache.strands_len); - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache.final[subdiv].proc_buf); - - cache.final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("hair_proc", - cache.final[subdiv].proc_buf); } static void curves_batch_cache_fill_segments_indices(const Curves &curves, @@ -516,7 +505,6 @@ static bool curves_ensure_attributes(const Curves &curves, GPUMaterial *gpu_material, int subdiv) { - ThreadMutex *render_mutex = &cache.render_mutex; const CustomData *cd_curve = &curves.geometry.curve_data; const CustomData *cd_point = &curves.geometry.point_data; CurvesEvalFinalCache &final_cache = cache.curves_cache.final[subdiv]; @@ -548,11 +536,10 @@ static bool curves_ensure_attributes(const Curves &curves, /* Some new attributes have been added, free all and start over. */ for (const int i : IndexRange(GPU_MAX_ATTR)) { GPU_VERTBUF_DISCARD_SAFE(cache.curves_cache.proc_attributes_buf[i]); - DRW_TEXTURE_FREE_SAFE(cache.curves_cache.proc_attributes_tex[i]); } - drw_attributes_merge(&final_cache.attr_used, &attrs_needed, render_mutex); + drw_attributes_merge(&final_cache.attr_used, &attrs_needed, cache.render_mutex); } - drw_attributes_merge(&final_cache.attr_used_over_time, &attrs_needed, render_mutex); + drw_attributes_merge(&final_cache.attr_used_over_time, &attrs_needed, cache.render_mutex); } bool need_tf_update = false; @@ -596,7 +583,7 @@ bool curves_ensure_procedural_data(Curves *curves, } /* Refreshed if active layer or custom data changes. */ - if ((*r_hair_cache)->strand_tex == nullptr) { + if ((*r_hair_cache)->proc_strand_buf == nullptr) { curves_batch_cache_ensure_procedural_strand_data(*curves, cache.curves_cache); } @@ -651,10 +638,10 @@ static void request_attribute(Curves &curves, const char *name) drw_attributes_add_request( &attributes, name, type, CustomData_get_named_layer(&custom_data, type, name), domain); - drw_attributes_merge(&final_cache.attr_used, &attributes, &cache.render_mutex); + drw_attributes_merge(&final_cache.attr_used, &attributes, cache.render_mutex); } -GPUTexture **DRW_curves_texture_for_evaluated_attribute(Curves *curves, +GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves, const char *name, bool *r_is_point_domain) { @@ -680,10 +667,10 @@ GPUTexture **DRW_curves_texture_for_evaluated_attribute(Curves *curves, switch (final_cache.attr_used.requests[request_i].domain) { case ATTR_DOMAIN_POINT: *r_is_point_domain = true; - return &final_cache.attributes_tex[request_i]; + return &final_cache.attributes_buf[request_i]; case ATTR_DOMAIN_CURVE: *r_is_point_domain = false; - return &cache.curves_cache.proc_attributes_tex[request_i]; + return &cache.curves_cache.proc_attributes_buf[request_i]; default: BLI_assert_unreachable(); return nullptr; @@ -697,9 +684,14 @@ void DRW_curves_batch_cache_create_requested(Object *ob) if (DRW_batch_requested(cache.edit_points, GPU_PRIM_POINTS)) { DRW_vbo_request(cache.edit_points, &cache.curves_cache.proc_point_buf); + DRW_vbo_request(cache.edit_points, &cache.curves_cache.data_edit_points); } if (DRW_vbo_requested(cache.curves_cache.proc_point_buf)) { curves_batch_cache_ensure_procedural_pos(*curves, cache.curves_cache, nullptr); } + + if (DRW_vbo_requested(cache.curves_cache.data_edit_points)) { + curves_batch_cache_ensure_data_edit_points(*curves, cache.curves_cache); + } } |