Refactor: Remove unnecessary curves GPU evaluation caches
Currently we have a cache for all combinations of "strand/strip" and the four subdivision levels. Recomputing this data should be very fast and doesn't require re-uploading data from the CPU. Because they are scene settings, they will be the same for all render engines too, so we won't have a case where we're constantly requesting different values. The extra caches just complicate code, so better to remove them. Now the final evaluated cache remembers the settings it was created with, and it's cleared if they are changed. Pull Request: https://projects.blender.org/blender/blender/pulls/119804
This commit is contained in:
@@ -150,13 +150,11 @@ static void discard_attributes(CurvesEvalCache &eval_cache)
|
||||
GPU_VERTBUF_DISCARD_SAFE(eval_cache.proc_attributes_buf[i]);
|
||||
}
|
||||
|
||||
for (const int i : IndexRange(MAX_HAIR_SUBDIV)) {
|
||||
for (const int j : IndexRange(GPU_MAX_ATTR)) {
|
||||
GPU_VERTBUF_DISCARD_SAFE(eval_cache.final[i].attributes_buf[j]);
|
||||
}
|
||||
|
||||
drw_attributes_clear(&eval_cache.final[i].attr_used);
|
||||
for (const int j : IndexRange(GPU_MAX_ATTR)) {
|
||||
GPU_VERTBUF_DISCARD_SAFE(eval_cache.final.attributes_buf[j]);
|
||||
}
|
||||
|
||||
drw_attributes_clear(&eval_cache.final.attr_used);
|
||||
}
|
||||
|
||||
static void clear_edit_data(CurvesBatchCache *cache)
|
||||
@@ -178,6 +176,15 @@ static void clear_edit_data(CurvesBatchCache *cache)
|
||||
GPU_BATCH_DISCARD_SAFE(cache->edit_curves_lines);
|
||||
}
|
||||
|
||||
static void clear_final_data(CurvesEvalFinalCache &final_cache)
|
||||
{
|
||||
GPU_VERTBUF_DISCARD_SAFE(final_cache.proc_buf);
|
||||
GPU_BATCH_DISCARD_SAFE(final_cache.proc_hairs);
|
||||
for (const int j : IndexRange(GPU_MAX_ATTR)) {
|
||||
GPU_VERTBUF_DISCARD_SAFE(final_cache.attributes_buf[j]);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_eval_data(CurvesEvalCache &eval_cache)
|
||||
{
|
||||
/* TODO: more granular update tagging. */
|
||||
@@ -186,12 +193,7 @@ static void clear_eval_data(CurvesEvalCache &eval_cache)
|
||||
GPU_VERTBUF_DISCARD_SAFE(eval_cache.proc_strand_buf);
|
||||
GPU_VERTBUF_DISCARD_SAFE(eval_cache.proc_strand_seg_buf);
|
||||
|
||||
for (const int i : IndexRange(MAX_HAIR_SUBDIV)) {
|
||||
GPU_VERTBUF_DISCARD_SAFE(eval_cache.final[i].proc_buf);
|
||||
for (const int j : IndexRange(MAX_THICKRES)) {
|
||||
GPU_BATCH_DISCARD_SAFE(eval_cache.final[i].proc_hairs[j]);
|
||||
}
|
||||
}
|
||||
clear_final_data(eval_cache.final);
|
||||
|
||||
discard_attributes(eval_cache);
|
||||
}
|
||||
@@ -504,18 +506,16 @@ static void calc_edit_handles_vbo(const bke::CurvesGeometry &curves,
|
||||
|
||||
static void alloc_final_attribute_vbo(CurvesEvalCache &cache,
|
||||
const GPUVertFormat *format,
|
||||
const int subdiv,
|
||||
const int index,
|
||||
const char * /*name*/)
|
||||
{
|
||||
CurvesEvalFinalCache &final_cache = cache.final[subdiv];
|
||||
final_cache.attributes_buf[index] = GPU_vertbuf_create_with_format_ex(
|
||||
cache.final.attributes_buf[index] = GPU_vertbuf_create_with_format_ex(
|
||||
format, GPU_USAGE_DEVICE_ONLY | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY);
|
||||
|
||||
/* Create a destination buffer for the transform feedback. Sized appropriately */
|
||||
/* Those are points! not line segments. */
|
||||
GPU_vertbuf_data_alloc(final_cache.attributes_buf[index],
|
||||
final_cache.resolution * cache.curves_num);
|
||||
GPU_vertbuf_data_alloc(cache.final.attributes_buf[index],
|
||||
cache.final.resolution * cache.curves_num);
|
||||
}
|
||||
|
||||
static void ensure_control_point_attribute(const Curves &curves,
|
||||
@@ -558,7 +558,6 @@ static void ensure_control_point_attribute(const Curves &curves,
|
||||
static void ensure_final_attribute(const Curves &curves,
|
||||
CurvesEvalCache &cache,
|
||||
const DRW_AttributeRequest &request,
|
||||
const int subdiv,
|
||||
const int index)
|
||||
{
|
||||
char sampler_name[32];
|
||||
@@ -573,11 +572,11 @@ static void ensure_final_attribute(const Curves &curves,
|
||||
|
||||
/* 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]);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache.final.attributes_buf[index]);
|
||||
|
||||
/* Ensure final data for points. */
|
||||
if (request.domain == bke::AttrDomain::Point) {
|
||||
alloc_final_attribute_vbo(cache, &format, subdiv, index, sampler_name);
|
||||
alloc_final_attribute_vbo(cache, &format, index, sampler_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,25 +617,23 @@ static void create_curve_offsets_vbos(const OffsetIndices<int> points_by_curve,
|
||||
fill_curve_offsets_vbos(points_by_curve, data_step, seg_step);
|
||||
}
|
||||
|
||||
static void alloc_final_points_vbo(CurvesEvalCache &cache, int subdiv)
|
||||
static void alloc_final_points_vbo(CurvesEvalCache &cache)
|
||||
{
|
||||
/* Same format as proc_point_buf. */
|
||||
GPUVertFormat format = {0};
|
||||
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
||||
|
||||
cache.final[subdiv].proc_buf = GPU_vertbuf_create_with_format_ex(
|
||||
cache.final.proc_buf = GPU_vertbuf_create_with_format_ex(
|
||||
&format, GPU_USAGE_DEVICE_ONLY | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY);
|
||||
|
||||
/* Create a destination buffer for the transform feedback. Sized appropriately */
|
||||
/* Those are points! not line segments. */
|
||||
GPU_vertbuf_data_alloc(cache.final[subdiv].proc_buf,
|
||||
cache.final[subdiv].resolution * cache.curves_num);
|
||||
GPU_vertbuf_data_alloc(cache.final.proc_buf, cache.final.resolution * cache.curves_num);
|
||||
}
|
||||
|
||||
static void calc_final_indices(const bke::CurvesGeometry &curves,
|
||||
CurvesEvalCache &cache,
|
||||
const int thickness_res,
|
||||
const int subdiv)
|
||||
const int thickness_res)
|
||||
{
|
||||
BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */
|
||||
/* Determine prim type and element count.
|
||||
@@ -647,14 +644,14 @@ static void calc_final_indices(const bke::CurvesGeometry &curves,
|
||||
|
||||
if (use_strip_prims) {
|
||||
/* +1 for primitive restart */
|
||||
verts_per_curve = cache.final[subdiv].resolution * thickness_res;
|
||||
verts_per_curve = cache.final.resolution * thickness_res;
|
||||
prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP;
|
||||
}
|
||||
else {
|
||||
/* Use full primitive type. */
|
||||
prim_type = (thickness_res == 1) ? GPU_PRIM_LINES : GPU_PRIM_TRIS;
|
||||
int verts_per_segment = ((prim_type == GPU_PRIM_LINES) ? 2 : 6);
|
||||
verts_per_curve = (cache.final[subdiv].resolution - 1) * verts_per_segment;
|
||||
verts_per_curve = (cache.final.resolution - 1) * verts_per_segment;
|
||||
}
|
||||
|
||||
static GPUVertFormat format = {0};
|
||||
@@ -672,18 +669,16 @@ static void calc_final_indices(const bke::CurvesGeometry &curves,
|
||||
ibo = GPU_indexbuf_build_curves_on_device(prim_type, curves.curves_num(), verts_per_curve);
|
||||
owns_flag |= GPU_BATCH_OWNS_INDEX;
|
||||
}
|
||||
cache.final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
|
||||
prim_type, vbo, ibo, owns_flag);
|
||||
cache.final.proc_hairs = GPU_batch_create_ex(prim_type, vbo, ibo, owns_flag);
|
||||
}
|
||||
|
||||
static bool ensure_attributes(const Curves &curves,
|
||||
CurvesBatchCache &cache,
|
||||
const GPUMaterial *gpu_material,
|
||||
const int subdiv)
|
||||
const GPUMaterial *gpu_material)
|
||||
{
|
||||
const CustomData *cd_curve = &curves.geometry.curve_data;
|
||||
const CustomData *cd_point = &curves.geometry.point_data;
|
||||
CurvesEvalFinalCache &final_cache = cache.eval_cache.final[subdiv];
|
||||
CurvesEvalFinalCache &final_cache = cache.eval_cache.final;
|
||||
|
||||
if (gpu_material) {
|
||||
DRW_Attributes attrs_needed;
|
||||
@@ -723,7 +718,7 @@ static bool ensure_attributes(const Curves &curves,
|
||||
for (const int i : IndexRange(final_cache.attr_used.num_requests)) {
|
||||
const DRW_AttributeRequest &request = final_cache.attr_used.requests[i];
|
||||
|
||||
if (cache.eval_cache.final[subdiv].attributes_buf[i] != nullptr) {
|
||||
if (cache.eval_cache.final.attributes_buf[i] != nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -731,7 +726,7 @@ static bool ensure_attributes(const Curves &curves,
|
||||
need_tf_update = true;
|
||||
}
|
||||
|
||||
ensure_final_attribute(curves, cache.eval_cache, request, subdiv, i);
|
||||
ensure_final_attribute(curves, cache.eval_cache, request, i);
|
||||
}
|
||||
|
||||
return need_tf_update;
|
||||
@@ -740,10 +735,7 @@ static bool ensure_attributes(const Curves &curves,
|
||||
static void request_attribute(Curves &curves, const char *name)
|
||||
{
|
||||
CurvesBatchCache &cache = get_batch_cache(curves);
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
const Scene *scene = draw_ctx->scene;
|
||||
const int subdiv = scene->r.hair_subdiv;
|
||||
CurvesEvalFinalCache &final_cache = cache.eval_cache.final[subdiv];
|
||||
CurvesEvalFinalCache &final_cache = cache.eval_cache.final;
|
||||
|
||||
DRW_Attributes attributes{};
|
||||
|
||||
@@ -783,11 +775,19 @@ bool curves_ensure_procedural_data(Curves *curves_id,
|
||||
|
||||
CurvesBatchCache &cache = get_batch_cache(*curves_id);
|
||||
CurvesEvalCache &eval_cache = cache.eval_cache;
|
||||
|
||||
if (eval_cache.final.hair_subdiv != subdiv || eval_cache.final.thickres != thickness_res) {
|
||||
/* If the subdivision or indexing settings have changed, the evaluation cache is cleared. */
|
||||
clear_final_data(eval_cache.final);
|
||||
eval_cache.final.hair_subdiv = subdiv;
|
||||
eval_cache.final.thickres = thickness_res;
|
||||
}
|
||||
|
||||
eval_cache.curves_num = curves.curves_num();
|
||||
eval_cache.points_num = curves.points_num();
|
||||
|
||||
const int steps = 3; /* TODO: don't hard-code? */
|
||||
eval_cache.final[subdiv].resolution = 1 << (steps + subdiv);
|
||||
eval_cache.final.resolution = 1 << (steps + subdiv);
|
||||
|
||||
/* Refreshed on combing and simulation. */
|
||||
if (eval_cache.proc_point_buf == nullptr || DRW_vbo_requested(eval_cache.proc_point_buf)) {
|
||||
@@ -801,15 +801,17 @@ bool curves_ensure_procedural_data(Curves *curves_id,
|
||||
}
|
||||
|
||||
/* Refreshed only on subdiv count change. */
|
||||
if (eval_cache.final[subdiv].proc_buf == nullptr) {
|
||||
alloc_final_points_vbo(eval_cache, subdiv);
|
||||
if (eval_cache.final.proc_buf == nullptr) {
|
||||
alloc_final_points_vbo(eval_cache);
|
||||
need_ft_update = true;
|
||||
}
|
||||
if (eval_cache.final[subdiv].proc_hairs[thickness_res - 1] == nullptr) {
|
||||
calc_final_indices(curves, eval_cache, thickness_res, subdiv);
|
||||
}
|
||||
|
||||
need_ft_update |= ensure_attributes(*curves_id, cache, gpu_material, subdiv);
|
||||
if (eval_cache.final.proc_hairs == nullptr) {
|
||||
calc_final_indices(curves, eval_cache, thickness_res);
|
||||
}
|
||||
eval_cache.final.thickres = thickness_res;
|
||||
|
||||
need_ft_update |= ensure_attributes(*curves_id, cache, gpu_material);
|
||||
|
||||
*r_cache = &eval_cache;
|
||||
return need_ft_update;
|
||||
@@ -856,20 +858,18 @@ void DRW_curves_batch_cache_free_old(Curves *curves, int ctime)
|
||||
|
||||
bool do_discard = false;
|
||||
|
||||
for (const int i : IndexRange(MAX_HAIR_SUBDIV)) {
|
||||
CurvesEvalFinalCache &final_cache = cache->eval_cache.final[i];
|
||||
CurvesEvalFinalCache &final_cache = cache->eval_cache.final;
|
||||
|
||||
if (drw_attributes_overlap(&final_cache.attr_used_over_time, &final_cache.attr_used)) {
|
||||
final_cache.last_attr_matching_time = ctime;
|
||||
}
|
||||
|
||||
if (ctime - final_cache.last_attr_matching_time > U.vbotimeout) {
|
||||
do_discard = true;
|
||||
}
|
||||
|
||||
drw_attributes_clear(&final_cache.attr_used_over_time);
|
||||
if (drw_attributes_overlap(&final_cache.attr_used_over_time, &final_cache.attr_used)) {
|
||||
final_cache.last_attr_matching_time = ctime;
|
||||
}
|
||||
|
||||
if (ctime - final_cache.last_attr_matching_time > U.vbotimeout) {
|
||||
do_discard = true;
|
||||
}
|
||||
|
||||
drw_attributes_clear(&final_cache.attr_used_over_time);
|
||||
|
||||
if (do_discard) {
|
||||
discard_attributes(cache->eval_cache);
|
||||
}
|
||||
@@ -915,10 +915,7 @@ GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves,
|
||||
bool *r_is_point_domain)
|
||||
{
|
||||
CurvesBatchCache &cache = get_batch_cache(*curves);
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
const Scene *scene = draw_ctx->scene;
|
||||
const int subdiv = scene->r.hair_subdiv;
|
||||
CurvesEvalFinalCache &final_cache = cache.eval_cache.final[subdiv];
|
||||
CurvesEvalFinalCache &final_cache = cache.eval_cache.final;
|
||||
|
||||
request_attribute(*curves, name);
|
||||
|
||||
|
||||
@@ -114,24 +114,22 @@ void DRW_curves_ubos_pool_free(CurvesUniformBufPool *pool)
|
||||
|
||||
static void drw_curves_cache_shgrp_attach_resources(DRWShadingGroup *shgrp,
|
||||
CurvesEvalCache *cache,
|
||||
GPUVertBuf *point_buf,
|
||||
const int subdiv)
|
||||
GPUVertBuf *point_buf)
|
||||
{
|
||||
DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", point_buf);
|
||||
DRW_shgroup_buffer_texture(shgrp, "hairStrandBuffer", cache->proc_strand_buf);
|
||||
DRW_shgroup_buffer_texture(shgrp, "hairStrandSegBuffer", cache->proc_strand_seg_buf);
|
||||
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final[subdiv].resolution, 1);
|
||||
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final.resolution, 1);
|
||||
}
|
||||
|
||||
static void drw_curves_cache_update_compute(CurvesEvalCache *cache,
|
||||
const int subdiv,
|
||||
const int curves_num,
|
||||
GPUVertBuf *output_buf,
|
||||
GPUVertBuf *input_buf)
|
||||
{
|
||||
GPUShader *shader = DRW_shader_curves_refine_get(CURVES_EVAL_CATMULL_ROM);
|
||||
DRWShadingGroup *shgrp = DRW_shgroup_create(shader, g_tf_pass);
|
||||
drw_curves_cache_shgrp_attach_resources(shgrp, cache, input_buf, subdiv);
|
||||
drw_curves_cache_shgrp_attach_resources(shgrp, cache, input_buf);
|
||||
DRW_shgroup_vertex_buffer(shgrp, "posTime", output_buf);
|
||||
|
||||
const int max_strands_per_call = GPU_max_work_group_count(0);
|
||||
@@ -140,34 +138,30 @@ static void drw_curves_cache_update_compute(CurvesEvalCache *cache,
|
||||
int batch_strands_len = std::min(curves_num - strands_start, max_strands_per_call);
|
||||
DRWShadingGroup *subgroup = DRW_shgroup_create_sub(shgrp);
|
||||
DRW_shgroup_uniform_int_copy(subgroup, "hairStrandOffset", strands_start);
|
||||
DRW_shgroup_call_compute(subgroup, batch_strands_len, cache->final[subdiv].resolution, 1);
|
||||
DRW_shgroup_call_compute(subgroup, batch_strands_len, cache->final.resolution, 1);
|
||||
strands_start += batch_strands_len;
|
||||
}
|
||||
}
|
||||
|
||||
static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int subdiv)
|
||||
static void drw_curves_cache_update_compute(CurvesEvalCache *cache)
|
||||
{
|
||||
const int curves_num = cache->curves_num;
|
||||
const int final_points_len = cache->final[subdiv].resolution * curves_num;
|
||||
const int final_points_len = cache->final.resolution * curves_num;
|
||||
if (final_points_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
drw_curves_cache_update_compute(
|
||||
cache, subdiv, curves_num, cache->final[subdiv].proc_buf, cache->proc_point_buf);
|
||||
drw_curves_cache_update_compute(cache, curves_num, cache->final.proc_buf, cache->proc_point_buf);
|
||||
|
||||
const DRW_Attributes &attrs = cache->final[subdiv].attr_used;
|
||||
const DRW_Attributes &attrs = cache->final.attr_used;
|
||||
for (int i = 0; i < attrs.num_requests; i++) {
|
||||
/* Only refine point attributes. */
|
||||
if (attrs.requests[i].domain == bke::AttrDomain::Curve) {
|
||||
continue;
|
||||
}
|
||||
|
||||
drw_curves_cache_update_compute(cache,
|
||||
subdiv,
|
||||
curves_num,
|
||||
cache->final[subdiv].attributes_buf[i],
|
||||
cache->proc_attributes_buf[i]);
|
||||
drw_curves_cache_update_compute(
|
||||
cache, curves_num, cache->final.attributes_buf[i], cache->proc_attributes_buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +175,7 @@ static CurvesEvalCache *drw_curves_cache_get(Curves &curves,
|
||||
&curves, &cache, gpu_material, subdiv, thickness_res);
|
||||
|
||||
if (update) {
|
||||
drw_curves_cache_update_compute(cache, subdiv);
|
||||
drw_curves_cache_update_compute(cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
@@ -197,7 +191,7 @@ GPUVertBuf *DRW_curves_pos_buffer_get(Object *object)
|
||||
Curves &curves = *static_cast<Curves *>(object->data);
|
||||
CurvesEvalCache *cache = drw_curves_cache_get(curves, nullptr, subdiv, thickness_res);
|
||||
|
||||
return cache->final[subdiv].proc_buf;
|
||||
return cache->final.proc_buf;
|
||||
}
|
||||
|
||||
static int attribute_index_in_material(GPUMaterial *gpu_material, const char *name)
|
||||
@@ -269,12 +263,12 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
|
||||
1.0f);
|
||||
}
|
||||
|
||||
DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", curves_cache->final[subdiv].proc_buf);
|
||||
DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", curves_cache->final.proc_buf);
|
||||
if (curves_cache->proc_length_buf) {
|
||||
DRW_shgroup_buffer_texture(shgrp, "hairLen", curves_cache->proc_length_buf);
|
||||
}
|
||||
|
||||
const DRW_Attributes &attrs = curves_cache->final[subdiv].attr_used;
|
||||
const DRW_Attributes &attrs = curves_cache->final.attr_used;
|
||||
for (int i = 0; i < attrs.num_requests; i++) {
|
||||
const DRW_AttributeRequest &request = attrs.requests[i];
|
||||
|
||||
@@ -289,11 +283,10 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
|
||||
DRW_shgroup_buffer_texture(shgrp, sampler_name, curves_cache->proc_attributes_buf[i]);
|
||||
}
|
||||
else {
|
||||
if (!curves_cache->final[subdiv].attributes_buf[i]) {
|
||||
if (!curves_cache->final.attributes_buf[i]) {
|
||||
continue;
|
||||
}
|
||||
DRW_shgroup_buffer_texture(
|
||||
shgrp, sampler_name, curves_cache->final[subdiv].attributes_buf[i]);
|
||||
DRW_shgroup_buffer_texture(shgrp, sampler_name, curves_cache->final.attributes_buf[i]);
|
||||
}
|
||||
|
||||
/* Some attributes may not be used in the shader anymore and were not garbage collected yet, so
|
||||
@@ -310,7 +303,7 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
|
||||
|
||||
DRW_shgroup_uniform_block(shgrp, "drw_curves", curves_infos);
|
||||
|
||||
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &curves_cache->final[subdiv].resolution, 1);
|
||||
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &curves_cache->final.resolution, 1);
|
||||
DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
|
||||
DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
|
||||
DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->object_to_world().ptr());
|
||||
@@ -324,7 +317,7 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
|
||||
}
|
||||
/* TODO(fclem): Until we have a better way to cull the curves and render with orco, bypass
|
||||
* culling test. */
|
||||
GPUBatch *geom = curves_cache->final[subdiv].proc_hairs[thickness_res - 1];
|
||||
GPUBatch *geom = curves_cache->final.proc_hairs;
|
||||
DRW_shgroup_call_no_cull(shgrp, geom, object);
|
||||
|
||||
return shgrp;
|
||||
@@ -385,7 +378,7 @@ static CurvesEvalCache *curves_cache_get(Curves &curves,
|
||||
}
|
||||
|
||||
const int curves_num = cache->curves_num;
|
||||
const int final_points_len = cache->final[subdiv].resolution * curves_num;
|
||||
const int final_points_len = cache->final.resolution * curves_num;
|
||||
|
||||
auto cache_update = [&](GPUVertBuf *output_buf, GPUVertBuf *input_buf) {
|
||||
PassSimple::Sub &ob_ps = g_pass->sub("Object Pass");
|
||||
@@ -395,7 +388,7 @@ static CurvesEvalCache *curves_cache_get(Curves &curves,
|
||||
ob_ps.bind_texture("hairPointBuffer", input_buf);
|
||||
ob_ps.bind_texture("hairStrandBuffer", cache->proc_strand_buf);
|
||||
ob_ps.bind_texture("hairStrandSegBuffer", cache->proc_strand_seg_buf);
|
||||
ob_ps.push_constant("hairStrandsRes", &cache->final[subdiv].resolution);
|
||||
ob_ps.push_constant("hairStrandsRes", &cache->final.resolution);
|
||||
ob_ps.bind_ssbo("posTime", output_buf);
|
||||
|
||||
const int max_strands_per_call = GPU_max_work_group_count(0);
|
||||
@@ -404,19 +397,19 @@ static CurvesEvalCache *curves_cache_get(Curves &curves,
|
||||
int batch_strands_len = std::min(curves_num - strands_start, max_strands_per_call);
|
||||
PassSimple::Sub &sub_ps = ob_ps.sub("Sub Pass");
|
||||
sub_ps.push_constant("hairStrandOffset", strands_start);
|
||||
sub_ps.dispatch(int3(batch_strands_len, cache->final[subdiv].resolution, 1));
|
||||
sub_ps.dispatch(int3(batch_strands_len, cache->final.resolution, 1));
|
||||
strands_start += batch_strands_len;
|
||||
}
|
||||
};
|
||||
|
||||
if (final_points_len > 0) {
|
||||
cache_update(cache->final[subdiv].proc_buf, cache->proc_point_buf);
|
||||
cache_update(cache->final.proc_buf, cache->proc_point_buf);
|
||||
|
||||
const DRW_Attributes &attrs = cache->final[subdiv].attr_used;
|
||||
const DRW_Attributes &attrs = cache->final.attr_used;
|
||||
for (int i : IndexRange(attrs.num_requests)) {
|
||||
/* Only refine point attributes. */
|
||||
if (attrs.requests[i].domain != bke::AttrDomain::Curve) {
|
||||
cache_update(cache->final[subdiv].attributes_buf[i], cache->proc_attributes_buf[i]);
|
||||
cache_update(cache->final.attributes_buf[i], cache->proc_attributes_buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -432,7 +425,7 @@ GPUVertBuf *curves_pos_buffer_get(Scene *scene, Object *object)
|
||||
Curves &curves = *static_cast<Curves *>(object->data);
|
||||
CurvesEvalCache *cache = curves_cache_get(curves, nullptr, subdiv, thickness_res);
|
||||
|
||||
return cache->final[subdiv].proc_buf;
|
||||
return cache->final.proc_buf;
|
||||
}
|
||||
|
||||
void curves_update(Manager &manager)
|
||||
@@ -497,12 +490,12 @@ GPUBatch *curves_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
1.0f);
|
||||
}
|
||||
|
||||
sub_ps.bind_texture("hairPointBuffer", curves_cache->final[subdiv].proc_buf);
|
||||
sub_ps.bind_texture("hairPointBuffer", curves_cache->final.proc_buf);
|
||||
if (curves_cache->proc_length_buf) {
|
||||
sub_ps.bind_texture("hairLen", curves_cache->proc_length_buf);
|
||||
}
|
||||
|
||||
const DRW_Attributes &attrs = curves_cache->final[subdiv].attr_used;
|
||||
const DRW_Attributes &attrs = curves_cache->final.attr_used;
|
||||
for (int i = 0; i < attrs.num_requests; i++) {
|
||||
const DRW_AttributeRequest &request = attrs.requests[i];
|
||||
|
||||
@@ -516,10 +509,10 @@ GPUBatch *curves_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
sub_ps.bind_texture(sampler_name, curves_cache->proc_attributes_buf[i]);
|
||||
}
|
||||
else {
|
||||
if (!curves_cache->final[subdiv].attributes_buf[i]) {
|
||||
if (!curves_cache->final.attributes_buf[i]) {
|
||||
continue;
|
||||
}
|
||||
sub_ps.bind_texture(sampler_name, curves_cache->final[subdiv].attributes_buf[i]);
|
||||
sub_ps.bind_texture(sampler_name, curves_cache->final.attributes_buf[i]);
|
||||
}
|
||||
|
||||
/* Some attributes may not be used in the shader anymore and were not garbage collected yet, so
|
||||
@@ -536,7 +529,7 @@ GPUBatch *curves_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
|
||||
sub_ps.bind_ubo("drw_curves", curves_infos);
|
||||
|
||||
sub_ps.push_constant("hairStrandsRes", &curves_cache->final[subdiv].resolution, 1);
|
||||
sub_ps.push_constant("hairStrandsRes", &curves_cache->final.resolution, 1);
|
||||
sub_ps.push_constant("hairThicknessRes", thickness_res);
|
||||
sub_ps.push_constant("hairRadShape", hair_rad_shape);
|
||||
sub_ps.push_constant("hairDupliMatrix", ob->object_to_world());
|
||||
@@ -544,7 +537,7 @@ GPUBatch *curves_sub_pass_setup_implementation(PassT &sub_ps,
|
||||
sub_ps.push_constant("hairRadTip", hair_rad_tip);
|
||||
sub_ps.push_constant("hairCloseTip", hair_close_tip);
|
||||
|
||||
return curves_cache->final[subdiv].proc_hairs[thickness_res - 1];
|
||||
return curves_cache->final.proc_hairs;
|
||||
}
|
||||
|
||||
GPUBatch *curves_sub_pass_setup(PassMain::Sub &ps,
|
||||
|
||||
@@ -29,11 +29,16 @@ enum CurvesEvalShader {
|
||||
#define CURVES_EVAL_SHADER_NUM 3
|
||||
|
||||
struct CurvesEvalFinalCache {
|
||||
/** The "additional subdivision" setting from the scene. See #MAX_HAIR_SUBDIV. */
|
||||
int hair_subdiv;
|
||||
/* The "strand or strip" setting from the scene. See #MAX_THICKRES. */
|
||||
int thickres;
|
||||
|
||||
/* Output of the subdivision stage: vertex buffer sized to subdiv level. */
|
||||
GPUVertBuf *proc_buf;
|
||||
|
||||
/** Just contains a huge index buffer used to draw the final curves. */
|
||||
GPUBatch *proc_hairs[MAX_THICKRES];
|
||||
GPUBatch *proc_hairs;
|
||||
|
||||
/** Points per curve, at least 2. */
|
||||
int resolution;
|
||||
@@ -72,7 +77,7 @@ struct CurvesEvalCache {
|
||||
|
||||
GPUVertBuf *proc_strand_seg_buf;
|
||||
|
||||
CurvesEvalFinalCache final[MAX_HAIR_SUBDIV];
|
||||
CurvesEvalFinalCache final;
|
||||
|
||||
/* For point attributes, which need subdivision, these buffers contain the input data.
|
||||
* For curve domain attributes, which do not need subdivision, these are the final data. */
|
||||
|
||||
Reference in New Issue
Block a user