Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_curves.cc')
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curves.cc184
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);
+ }
}