diff options
author | Jacques Lucke <mail@jlucke.com> | 2019-09-02 18:56:14 +0300 |
---|---|---|
committer | Jacques Lucke <mail@jlucke.com> | 2019-09-02 18:56:14 +0300 |
commit | 0d700d201a11aba45719609a617dc9e13f8f97d4 (patch) | |
tree | 26cd5a643cad6e268f519e84ff454837abac5820 /source/blender | |
parent | d2fe280a6ee8f51cb5eff8420bedd217952309fd (diff) |
remove ParticleSet and ParticleSets abstraction
Diffstat (limited to 'source/blender')
17 files changed, 239 insertions, 317 deletions
diff --git a/source/blender/simulations/bparticles/action_interface.hpp b/source/blender/simulations/bparticles/action_interface.hpp index 96f5782caea..bc3a29c7650 100644 --- a/source/blender/simulations/bparticles/action_interface.hpp +++ b/source/blender/simulations/bparticles/action_interface.hpp @@ -27,7 +27,8 @@ class EmitterActionContext { class ActionInterface { private: ParticleAllocator &m_particle_allocator; - ParticleSet m_particles; + ArrayRef<uint> m_pindices; + AttributeArrays m_attributes; AttributeArrays m_attribute_offsets; ArrayRef<float> m_current_times; ArrayRef<float> m_remaining_durations; @@ -35,7 +36,8 @@ class ActionInterface { public: ActionInterface(ParticleAllocator &particle_allocator, - ParticleSet particles, + ArrayRef<uint> pindices, + AttributeArrays attributes, AttributeArrays attribute_offsets, ArrayRef<float> current_times, ArrayRef<float> remaining_durations, @@ -43,7 +45,8 @@ class ActionInterface { ActionContext &context(); - ParticleSet &particles(); + ArrayRef<uint> pindices(); + AttributeArrays attributes(); AttributeArrays attribute_offsets(); float remaining_time_in_step(uint pindex); ArrayRef<float> remaining_durations(); @@ -58,14 +61,14 @@ class Action { virtual void execute(ActionInterface &interface) = 0; - void execute_from_emitter(ParticleSets &particle_sets, + void execute_from_emitter(NewParticles &new_particles, EmitterInterface &emitter_interface, EmitterActionContext *emitter_action_context = nullptr); void execute_from_event(EventExecuteInterface &event_interface, ActionContext *action_context = nullptr); void execute_for_subset(ArrayRef<uint> pindices, ActionInterface &action_interface); - void execute_for_new_particles(ParticleSets &particle_sets, ActionInterface &action_interface); - void execute_for_new_particles(ParticleSets &particle_sets, + void execute_for_new_particles(NewParticles &new_particles, ActionInterface &action_interface); + void execute_for_new_particles(NewParticles &new_particles, OffsetHandlerInterface &offset_handler_interface); }; @@ -73,13 +76,15 @@ class Action { *******************************************/ inline ActionInterface::ActionInterface(ParticleAllocator &particle_allocator, - ParticleSet particles, + ArrayRef<uint> pindices, + AttributeArrays attributes, AttributeArrays attribute_offsets, ArrayRef<float> current_times, ArrayRef<float> remaining_durations, ActionContext &action_context) : m_particle_allocator(particle_allocator), - m_particles(particles), + m_pindices(pindices), + m_attributes(attributes), m_attribute_offsets(attribute_offsets), m_current_times(current_times), m_remaining_durations(remaining_durations), @@ -96,7 +101,7 @@ class EmptyEmitterActionContext : public EmitterActionContext { } }; -inline void Action::execute_from_emitter(ParticleSets &particle_sets, +inline void Action::execute_from_emitter(NewParticles &new_particles, EmitterInterface &emitter_interface, EmitterActionContext *emitter_action_context) { @@ -109,18 +114,22 @@ inline void Action::execute_from_emitter(ParticleSets &particle_sets, *emitter_action_context; uint offset = 0; - for (ParticleSet particles : particle_sets.sets()) { - used_emitter_context.update(Range<uint>(offset, offset + particles.size())); - offset += particles.size(); - - uint min_array_size = particles.attributes().size(); - AttributeArrays offsets(info, buffers, min_array_size); - TemporaryArray<float> durations(min_array_size); - durations.fill_indices(particles.pindices(), 0); + for (uint i = 0; i < new_particles.range_amount(); i++) { + AttributeArrays attributes = new_particles.segment(i); + uint range_size = attributes.size(); + + used_emitter_context.update(Range<uint>(offset, offset + range_size)); + offset += range_size; + + AttributeArrays offsets(info, buffers, range_size); + TemporaryArray<float> durations(range_size); + durations.fill(0); + ActionInterface action_interface(emitter_interface.particle_allocator(), - particles, + Range<uint>(0, range_size).as_array_ref(), + attributes, offsets, - particles.attributes().get<float>("Birth Time"), + attributes.get<float>("Birth Time"), durations, dynamic_cast<ActionContext &>(used_emitter_context)); this->execute(action_interface); @@ -135,7 +144,8 @@ inline void Action::execute_from_event(EventExecuteInterface &event_interface, *action_context; ActionInterface action_interface(event_interface.particle_allocator(), - event_interface.particles(), + event_interface.pindices(), + event_interface.attributes(), event_interface.attribute_offsets(), event_interface.current_times(), event_interface.remaining_durations(), @@ -146,7 +156,8 @@ inline void Action::execute_from_event(EventExecuteInterface &event_interface, inline void Action::execute_for_subset(ArrayRef<uint> pindices, ActionInterface &action_interface) { ActionInterface sub_interface(action_interface.particle_allocator(), - ParticleSet(action_interface.particles().attributes(), pindices), + pindices, + action_interface.attributes(), action_interface.attribute_offsets(), action_interface.current_times(), action_interface.remaining_durations(), @@ -154,7 +165,7 @@ inline void Action::execute_for_subset(ArrayRef<uint> pindices, ActionInterface this->execute(sub_interface); } -inline void Action::execute_for_new_particles(ParticleSets &particle_sets, +inline void Action::execute_for_new_particles(NewParticles &new_particles, ActionInterface &action_interface) { AttributesInfo info; @@ -163,22 +174,26 @@ inline void Action::execute_for_new_particles(ParticleSets &particle_sets, /* Use empty action context, until there a better solution is implemented. */ EmptyActionContext empty_context; - for (ParticleSet particles : particle_sets.sets()) { - uint min_array_size = particles.attributes().size(); - AttributeArrays offsets(info, buffers, min_array_size); - TemporaryArray<float> durations(min_array_size); - durations.fill_indices(particles.pindices(), 0); + for (uint i = 0; i < new_particles.range_amount(); i++) { + AttributeArrays attributes = new_particles.segment(i); + uint range_size = attributes.size(); + + AttributeArrays offsets(info, buffers, range_size); + TemporaryArray<float> durations(range_size); + durations.fill(0); + ActionInterface new_interface(action_interface.particle_allocator(), - particles, + Range<uint>(0, range_size).as_array_ref(), + attributes, offsets, - particles.attributes().get<float>("Birth Time"), + attributes.get<float>("Birth Time"), durations, empty_context); this->execute(new_interface); } } -inline void Action::execute_for_new_particles(ParticleSets &particle_sets, +inline void Action::execute_for_new_particles(NewParticles &new_particles, OffsetHandlerInterface &offset_handler_interface) { AttributesInfo info; @@ -186,15 +201,19 @@ inline void Action::execute_for_new_particles(ParticleSets &particle_sets, EmptyActionContext empty_context; - for (ParticleSet particles : particle_sets.sets()) { - uint min_array_size = particles.attributes().size(); - AttributeArrays offsets(info, buffers, min_array_size); - TemporaryArray<float> durations(min_array_size); - durations.fill_indices(particles.pindices(), 0); + for (uint i = 0; i < new_particles.range_amount(); i++) { + AttributeArrays attributes = new_particles.segment(i); + uint range_size = attributes.size(); + + AttributeArrays offsets(info, buffers, range_size); + TemporaryArray<float> durations(range_size); + durations.fill(0); + ActionInterface new_interface(offset_handler_interface.particle_allocator(), - particles, + Range<uint>(0, range_size).as_array_ref(), + attributes, offsets, - particles.attributes().get<float>("Birth Time"), + attributes.get<float>("Birth Time"), durations, empty_context); this->execute(new_interface); @@ -206,9 +225,14 @@ inline ActionContext &ActionInterface::context() return m_action_context; } -inline ParticleSet &ActionInterface::particles() +inline ArrayRef<uint> ActionInterface::pindices() +{ + return m_pindices; +} + +inline AttributeArrays ActionInterface::attributes() { - return m_particles; + return m_attributes; } inline AttributeArrays ActionInterface::attribute_offsets() @@ -233,7 +257,7 @@ inline ArrayRef<float> ActionInterface::current_times() inline void ActionInterface::kill(ArrayRef<uint> pindices) { - auto kill_states = m_particles.attributes().get<uint8_t>("Kill State"); + auto kill_states = m_attributes.get<uint8_t>("Kill State"); for (uint pindex : pindices) { kill_states[pindex] = 1; } diff --git a/source/blender/simulations/bparticles/actions.cpp b/source/blender/simulations/bparticles/actions.cpp index 61cb76c91de..716c23ad0f3 100644 --- a/source/blender/simulations/bparticles/actions.cpp +++ b/source/blender/simulations/bparticles/actions.cpp @@ -31,13 +31,14 @@ static float3 random_direction() static void update_position_and_velocity_offsets(ActionInterface &interface) { - ParticleSet particles = interface.particles(); + AttributeArrays attributes = interface.attributes(); AttributeArrays attribute_offsets = interface.attribute_offsets(); - auto velocities = particles.attributes().get<float3>("Velocity"); + + auto velocities = attributes.get<float3>("Velocity"); auto position_offsets = attribute_offsets.try_get<float3>("Position"); auto velocity_offsets = attribute_offsets.try_get<float3>("Velocity"); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { float3 velocity = velocities[pindex]; if (position_offsets.has_value()) { @@ -51,12 +52,11 @@ static void update_position_and_velocity_offsets(ActionInterface &interface) void SetVelocityAction::execute(ActionInterface &interface) { - ParticleSet particles = interface.particles(); - auto velocities = particles.attributes().get<float3>("Velocity"); + auto velocities = interface.attributes().get<float3>("Velocity"); auto inputs = m_compute_inputs->compute(interface); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { float3 velocity = inputs->get<float3>("Velocity", 0, pindex); velocities[pindex] = velocity; } @@ -66,12 +66,11 @@ void SetVelocityAction::execute(ActionInterface &interface) void RandomizeVelocityAction::execute(ActionInterface &interface) { - ParticleSet particles = interface.particles(); - auto velocities = particles.attributes().get<float3>("Velocity"); + auto velocities = interface.attributes().get<float3>("Velocity"); auto inputs = m_compute_inputs->compute(interface); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { float randomness = inputs->get<float>("Randomness", 0, pindex); float3 old_velocity = velocities[pindex]; float old_speed = old_velocity.length(); @@ -85,11 +84,10 @@ void RandomizeVelocityAction::execute(ActionInterface &interface) void ChangeColorAction::execute(ActionInterface &interface) { - ParticleSet particles = interface.particles(); - auto colors = particles.attributes().get<rgba_f>("Color"); + auto colors = interface.attributes().get<rgba_f>("Color"); auto inputs = m_compute_inputs->compute(interface); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { rgba_f color = inputs->get<rgba_f>("Color", 0, pindex); colors[pindex] = color; } @@ -97,14 +95,12 @@ void ChangeColorAction::execute(ActionInterface &interface) void KillAction::execute(ActionInterface &interface) { - interface.kill(interface.particles().pindices()); + interface.kill(interface.pindices()); } void ExplodeAction::execute(ActionInterface &interface) { - ParticleSet &particles = interface.particles(); - - auto positions = particles.attributes().get<float3>("Position"); + auto positions = interface.attributes().get<float3>("Position"); Vector<float3> new_positions; Vector<float3> new_velocities; @@ -112,7 +108,7 @@ void ExplodeAction::execute(ActionInterface &interface) auto inputs = m_compute_inputs->compute(interface); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { uint parts_amount = std::max(0, inputs->get<int>("Amount", 0, pindex)); float speed = inputs->get<float>("Speed", 1, pindex); @@ -137,12 +133,10 @@ void ExplodeAction::execute(ActionInterface &interface) void ConditionAction::execute(ActionInterface &interface) { - ParticleSet particles = interface.particles(); - auto inputs = m_compute_inputs->compute(interface); Vector<uint> true_pindices, false_pindices; - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { if (inputs->get<bool>("Condition", 0, pindex)) { true_pindices.append(pindex); } diff --git a/source/blender/simulations/bparticles/events.cpp b/source/blender/simulations/bparticles/events.cpp index eedab18a9ed..1ec1037401b 100644 --- a/source/blender/simulations/bparticles/events.cpp +++ b/source/blender/simulations/bparticles/events.cpp @@ -14,15 +14,15 @@ void AgeReachedEvent::attributes(AttributesDeclaration &builder) void AgeReachedEvent::filter(EventFilterInterface &interface) { - ParticleSet particles = interface.particles(); - auto birth_times = particles.attributes().get<float>("Birth Time"); - auto was_activated_before = particles.attributes().get<uint8_t>(m_identifier); + AttributeArrays attributes = interface.attributes(); + auto birth_times = attributes.get<float>("Birth Time"); + auto was_activated_before = attributes.get<uint8_t>(m_identifier); float end_time = interface.step_end_time(); auto inputs = m_compute_inputs->compute(interface); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { if (was_activated_before[pindex]) { continue; } @@ -50,10 +50,8 @@ void AgeReachedEvent::filter(EventFilterInterface &interface) void AgeReachedEvent::execute(EventExecuteInterface &interface) { - ParticleSet particles = interface.particles(); - - auto was_activated_before = particles.attributes().get<uint8_t>(m_identifier); - for (uint pindex : particles.pindices()) { + auto was_activated_before = interface.attributes().get<uint8_t>(m_identifier); + for (uint pindex : interface.pindices()) { was_activated_before[pindex] = true; } @@ -75,12 +73,12 @@ uint MeshCollisionEvent::storage_size() void MeshCollisionEvent::filter(EventFilterInterface &interface) { - ParticleSet particles = interface.particles(); - auto positions = particles.attributes().get<float3>("Position"); - auto last_collision_times = particles.attributes().get<float>(m_identifier); + AttributeArrays attributes = interface.attributes(); + auto positions = attributes.get<float3>("Position"); + auto last_collision_times = attributes.get<float>(m_identifier); auto position_offsets = interface.attribute_offsets().get<float3>("Position"); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { float3 ray_start = m_world_to_local.transform_position(positions[pindex]); float3 ray_direction = m_world_to_local.transform_direction(position_offsets[pindex]); float length = ray_direction.normalize_and_get_length(); @@ -123,8 +121,6 @@ MeshCollisionEvent::RayCastResult MeshCollisionEvent::ray_cast(float3 start, void MeshCollisionEvent::execute(EventExecuteInterface &interface) { - ParticleSet particles = interface.particles(); - uint array_size = interface.array_size(); TemporaryArray<float3> local_positions(array_size); TemporaryArray<float3> local_normals(array_size); @@ -132,9 +128,9 @@ void MeshCollisionEvent::execute(EventExecuteInterface &interface) TemporaryArray<float4x4> world_transforms(array_size); TemporaryArray<float3> world_normals(array_size); - auto last_collision_times = particles.attributes().get<float>(m_identifier); + auto last_collision_times = interface.attributes().get<float>(m_identifier); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { auto storage = interface.get_storage<EventStorage>(pindex); looptri_indices[pindex] = storage.looptri_index; local_positions[pindex] = storage.local_position; diff --git a/source/blender/simulations/bparticles/force_interface.hpp b/source/blender/simulations/bparticles/force_interface.hpp index 5ce7e37b22a..0490a39df35 100644 --- a/source/blender/simulations/bparticles/force_interface.hpp +++ b/source/blender/simulations/bparticles/force_interface.hpp @@ -17,9 +17,9 @@ class ForceInterface : public BlockStepDataAccess { { } - ParticleSet particles() + ArrayRef<uint> pindices() { - return ParticleSet(this->attributes(), m_pindices); + return m_pindices; } MutableArrayRef<float3> combined_destination() diff --git a/source/blender/simulations/bparticles/forces.cpp b/source/blender/simulations/bparticles/forces.cpp index c7efe2395be..1f3f5e98162 100644 --- a/source/blender/simulations/bparticles/forces.cpp +++ b/source/blender/simulations/bparticles/forces.cpp @@ -10,12 +10,11 @@ Force::~Force() void GravityForce::add_force(ForceInterface &interface) { - ParticleSet particles = interface.particles(); MutableArrayRef<float3> destination = interface.combined_destination(); auto inputs = m_compute_inputs->compute(interface); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { float3 acceleration = inputs->get<float3>("Direction", 0, pindex); destination[pindex] += acceleration; } @@ -23,14 +22,12 @@ void GravityForce::add_force(ForceInterface &interface) void TurbulenceForce::add_force(ForceInterface &interface) { - ParticleSet particles = interface.particles(); MutableArrayRef<float3> destination = interface.combined_destination(); - - auto positions = particles.attributes().get<float3>("Position"); + auto positions = interface.attributes().get<float3>("Position"); auto inputs = m_compute_inputs->compute(interface); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { float3 pos = positions[pindex]; float3 strength = inputs->get<float3>("Strength", 0, pindex); float x = (BLI_gNoise(0.5f, pos.x, pos.y, pos.z + 1000.0f, false, 1) - 0.5f) * strength.x; diff --git a/source/blender/simulations/bparticles/integrator.cpp b/source/blender/simulations/bparticles/integrator.cpp index 8a5de745657..c073bbda1b9 100644 --- a/source/blender/simulations/bparticles/integrator.cpp +++ b/source/blender/simulations/bparticles/integrator.cpp @@ -16,12 +16,11 @@ AttributesInfo &ConstantVelocityIntegrator::offset_attributes_info() void ConstantVelocityIntegrator::integrate(IntegratorInterface &interface) { - ParticleSet particles = interface.particles(); - auto velocities = particles.attributes().get<float3>("Velocity"); + auto velocities = interface.attributes().get<float3>("Velocity"); auto position_offsets = interface.attribute_offsets().get<float3>("Position"); auto durations = interface.remaining_durations(); - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { position_offsets[pindex] = velocities[pindex] * durations[pindex]; } } @@ -67,7 +66,7 @@ BLI_NOINLINE void EulerIntegrator::compute_combined_force(IntegratorInterface &i { r_force.fill({0, 0, 0}); - ForceInterface force_interface(interface.step_data(), interface.particles().pindices(), r_force); + ForceInterface force_interface(interface.step_data(), interface.pindices(), r_force); for (Force *force : m_forces) { force->add_force(force_interface); diff --git a/source/blender/simulations/bparticles/offset_handlers.cpp b/source/blender/simulations/bparticles/offset_handlers.cpp index 400a8a1d63f..a99a743890f 100644 --- a/source/blender/simulations/bparticles/offset_handlers.cpp +++ b/source/blender/simulations/bparticles/offset_handlers.cpp @@ -4,15 +4,14 @@ namespace BParticles { void CreateTrailHandler::execute(OffsetHandlerInterface &interface) { - ParticleSet particles = interface.particles(); - auto positions = particles.attributes().get<float3>("Position"); + auto positions = interface.attributes().get<float3>("Position"); auto position_offsets = interface.attribute_offsets().get<float3>("Position"); auto inputs = m_compute_inputs->compute(interface); Vector<float3> new_positions; Vector<float> new_birth_times; - for (uint pindex : particles.pindices()) { + for (uint pindex : interface.pindices()) { float rate = inputs->get<float>("Rate", 0, pindex); if (rate <= 0.0f) { continue; diff --git a/source/blender/simulations/bparticles/particle_allocator.cpp b/source/blender/simulations/bparticles/particle_allocator.cpp index 8bcc22a4edd..04af3c5def3 100644 --- a/source/blender/simulations/bparticles/particle_allocator.cpp +++ b/source/blender/simulations/bparticles/particle_allocator.cpp @@ -71,7 +71,7 @@ AttributesInfo &ParticleAllocator::attributes_info(StringRef particle_type_name) return m_state.particle_container(particle_type_name).attributes_info(); } -ParticleSets ParticleAllocator::request(StringRef particle_type_name, uint size) +NewParticles ParticleAllocator::request(StringRef particle_type_name, uint size) { Vector<ParticlesBlock *> blocks; Vector<Range<uint>> ranges; @@ -79,12 +79,12 @@ ParticleSets ParticleAllocator::request(StringRef particle_type_name, uint size) AttributesInfo &attributes_info = this->attributes_info(particle_type_name); - Vector<ParticleSet> sets; + Vector<ArrayRef<void *>> buffers; for (uint i = 0; i < blocks.size(); i++) { - sets.append(ParticleSet(blocks[i]->attributes(), ranges[i].as_array_ref())); + buffers.append(blocks[i]->attribute_buffers()); } - return ParticleSets(attributes_info, sets); + return NewParticles(attributes_info, std::move(buffers), std::move(ranges)); } } // namespace BParticles diff --git a/source/blender/simulations/bparticles/particle_allocator.hpp b/source/blender/simulations/bparticles/particle_allocator.hpp index 33a06a02863..b7244748cbe 100644 --- a/source/blender/simulations/bparticles/particle_allocator.hpp +++ b/source/blender/simulations/bparticles/particle_allocator.hpp @@ -27,7 +27,7 @@ class ParticleAllocator { */ ArrayRef<ParticlesBlock *> allocated_blocks(); - ParticleSets request(StringRef particle_type_name, uint size); + NewParticles request(StringRef particle_type_name, uint size); ParticlesState &particles_state(); diff --git a/source/blender/simulations/bparticles/particle_function.cpp b/source/blender/simulations/bparticles/particle_function.cpp index 9e13c42cfc9..adfea55ca0c 100644 --- a/source/blender/simulations/bparticles/particle_function.cpp +++ b/source/blender/simulations/bparticles/particle_function.cpp @@ -49,7 +49,8 @@ ParticleFunction::~ParticleFunction() std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute(ActionInterface &interface) { - return this->compute(interface.particles(), + return this->compute(interface.pindices(), + interface.attributes(), ParticleTimes::FromCurrentTimes(interface.current_times()), &interface.context()); } @@ -57,7 +58,8 @@ std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute(ActionInterfac std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute( OffsetHandlerInterface &interface) { - return this->compute(interface.particles(), + return this->compute(interface.pindices(), + interface.attributes(), ParticleTimes::FromDurationsAndEnd(interface.remaining_durations(), interface.step_end_time()), nullptr); @@ -65,7 +67,8 @@ std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute( std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute(ForceInterface &interface) { - return this->compute(interface.particles(), + return this->compute(interface.pindices(), + interface.attributes(), ParticleTimes::FromDurationsAndEnd(interface.remaining_durations(), interface.step_end_time()), nullptr); @@ -73,13 +76,15 @@ std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute(ForceInterface std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute(EventFilterInterface &interface) { - return this->compute(interface.particles(), + return this->compute(interface.pindices(), + interface.attributes(), ParticleTimes::FromDurationsAndEnd(interface.remaining_durations(), interface.step_end_time()), nullptr); } -std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute(ParticleSet particles, +std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute(ArrayRef<uint> pindices, + AttributeArrays attributes, ParticleTimes particle_times, ActionContext *action_context) { @@ -94,7 +99,7 @@ std::unique_ptr<ParticleFunctionResult> ParticleFunction::compute(ParticleSet pa result->m_output_indices = m_output_indices; this->init_without_deps(result); - this->init_with_deps(result, particles, particle_times, action_context); + this->init_with_deps(result, pindices, attributes, particle_times, action_context); return std::unique_ptr<ParticleFunctionResult>(result); } @@ -130,7 +135,8 @@ void ParticleFunction::init_without_deps(ParticleFunctionResult *result) } void ParticleFunction::init_with_deps(ParticleFunctionResult *result, - ParticleSet particles, + ArrayRef<uint> pindices, + AttributeArrays attributes, ParticleTimes particle_times, ActionContext *action_context) { @@ -146,7 +152,7 @@ void ParticleFunction::init_with_deps(ParticleFunctionResult *result, for (uint i = 0; i < m_fn_with_deps->input_amount(); i++) { auto *provider = m_input_providers[i]; - InputProviderInterface interface(particles, particle_times, action_context); + InputProviderInterface interface(pindices, attributes, particle_times, action_context); auto array = provider->get(interface); BLI_assert(array.buffer != nullptr); BLI_assert(array.stride > 0); @@ -170,7 +176,7 @@ void ParticleFunction::init_with_deps(ParticleFunctionResult *result, CPPTypeInfo &type_info = m_fn_with_deps->output_type(output_index)->extension<CPPTypeInfo>(); uint output_stride = type_info.size(); - void *output_buffer = BLI_temporary_allocate(output_stride * particles.size()); + void *output_buffer = BLI_temporary_allocate(output_stride * attributes.size()); result->m_buffers[parameter_index] = output_buffer; result->m_strides[parameter_index] = output_stride; @@ -184,7 +190,7 @@ void ParticleFunction::init_with_deps(ParticleFunctionResult *result, ExecutionContext execution_context(stack); FN::TextStackFrame stack_frame("Particle Function"); stack.push(&stack_frame); - m_array_execution->call(particles.pindices(), input_buffers, output_buffers, execution_context); + m_array_execution->call(pindices, input_buffers, output_buffers, execution_context); stack.pop(); for (uint i : inputs_to_free) { diff --git a/source/blender/simulations/bparticles/particle_function.hpp b/source/blender/simulations/bparticles/particle_function.hpp index b6257abfe31..8f2e90bc3f7 100644 --- a/source/blender/simulations/bparticles/particle_function.hpp +++ b/source/blender/simulations/bparticles/particle_function.hpp @@ -150,21 +150,31 @@ struct ParticleTimes { class InputProviderInterface { private: - ParticleSet m_particles; + ArrayRef<uint> m_pindices; + AttributeArrays m_attributes; ParticleTimes m_particle_times; ActionContext *m_action_context; public: - InputProviderInterface(ParticleSet particles, + InputProviderInterface(ArrayRef<uint> pindices, + AttributeArrays attributes, ParticleTimes particle_times, ActionContext *action_context) - : m_particles(particles), m_particle_times(particle_times), m_action_context(action_context) + : m_pindices(pindices), + m_attributes(attributes), + m_particle_times(particle_times), + m_action_context(action_context) { } - ParticleSet particles() + ArrayRef<uint> pindices() { - return m_particles; + return m_pindices; + } + + AttributeArrays attributes() + { + return m_attributes; } ParticleTimes &particle_times() @@ -231,14 +241,16 @@ class ParticleFunction { std::unique_ptr<ParticleFunctionResult> compute(EventFilterInterface &interface); private: - std::unique_ptr<ParticleFunctionResult> compute(ParticleSet particles, + std::unique_ptr<ParticleFunctionResult> compute(ArrayRef<uint> pindices, + AttributeArrays attributes, ParticleTimes particle_times, ActionContext *action_context); void init_without_deps(ParticleFunctionResult *result); void init_with_deps(ParticleFunctionResult *result, - ParticleSet particles, + ArrayRef<uint> pindices, + AttributeArrays attributes, ParticleTimes particle_times, ActionContext *action_context); }; diff --git a/source/blender/simulations/bparticles/particle_function_builder.cpp b/source/blender/simulations/bparticles/particle_function_builder.cpp index b248c2bebbe..d477c920c93 100644 --- a/source/blender/simulations/bparticles/particle_function_builder.cpp +++ b/source/blender/simulations/bparticles/particle_function_builder.cpp @@ -66,7 +66,7 @@ class AttributeInputProvider : public ParticleFunctionInputProvider { ParticleFunctionInputArray get(InputProviderInterface &interface) override { - AttributeArrays attributes = interface.particles().attributes(); + AttributeArrays attributes = interface.attributes(); uint attribute_index = attributes.attribute_index(m_name); uint stride = attributes.attribute_stride(attribute_index); void *buffer = attributes.get_ptr(attribute_index); @@ -88,21 +88,21 @@ class CollisionNormalInputProvider : public ParticleFunctionInputProvider { class AgeInputProvider : public ParticleFunctionInputProvider { ParticleFunctionInputArray get(InputProviderInterface &interface) override { - auto birth_times = interface.particles().attributes().get<float>("Birth Time"); + auto birth_times = interface.attributes().get<float>("Birth Time"); float *ages_buffer = (float *)BLI_temporary_allocate(sizeof(float) * birth_times.size()); MutableArrayRef<float> ages(ages_buffer, birth_times.size()); ParticleTimes × = interface.particle_times(); if (times.type() == ParticleTimes::Type::Current) { auto current_times = times.current_times(); - for (uint pindex : interface.particles().pindices()) { + for (uint pindex : interface.pindices()) { ages[pindex] = current_times[pindex] - birth_times[pindex]; } } else if (times.type() == ParticleTimes::Type::DurationAndEnd) { auto remaining_durations = times.remaining_durations(); float end_time = times.end_time(); - for (uint pindex : interface.particles().pindices()) { + for (uint pindex : interface.pindices()) { ages[pindex] = end_time - remaining_durations[pindex] - birth_times[pindex]; } } @@ -158,7 +158,7 @@ class SurfaceImageInputProvider : public ParticleFunctionInputProvider { local_positions.size()); MutableArrayRef<rgba_f> colors{colors_buffer, local_positions.size()}; - for (uint pindex : interface.particles().pindices()) { + for (uint pindex : interface.pindices()) { float3 local_position = local_positions[pindex]; uint triangle_index = surface_info->looptri_indices()[pindex]; diff --git a/source/blender/simulations/bparticles/particle_set.cpp b/source/blender/simulations/bparticles/particle_set.cpp index cc1570d4a3f..55eb0fc4766 100644 --- a/source/blender/simulations/bparticles/particle_set.cpp +++ b/source/blender/simulations/bparticles/particle_set.cpp @@ -2,38 +2,43 @@ namespace BParticles { -ParticleSets::ParticleSets(AttributesInfo &attributes_info, ArrayRef<ParticleSet> sets) - : m_attributes_info(attributes_info), m_sets(sets) +NewParticles::NewParticles(AttributesInfo &attributes_info, + Vector<ArrayRef<void *>> buffers, + Vector<Range<uint>> ranges) + : m_attributes_info(&attributes_info), + m_buffers(std::move(buffers)), + m_ranges(std::move(ranges)) { + BLI_assert(buffers.size() == ranges.size()); m_size = 0; - for (auto &set : sets) { - m_size += set.size(); + for (Range<uint> range : m_ranges) { + m_size += range.size(); } } -void ParticleSets::set_elements(uint index, void *data) +void NewParticles::set_elements(uint index, void *data) { - AttributeType type = m_attributes_info.type_of(index); + AttributeType type = m_attributes_info->type_of(index); uint element_size = size_of_attribute_type(type); void *remaining_data = data; - for (ParticleSet particles : m_sets) { - AttributeArrays attributes = particles.attributes(); + for (uint i = 0; i < this->range_amount(); i++) { + AttributeArrays attributes = this->segment(i); void *dst = attributes.get_ptr(index); - for (uint i = 0; i < particles.size(); i++) { - uint pindex = particles.pindices()[i]; + uint range_size = m_ranges[i].size(); + for (uint pindex = 0; pindex < range_size; pindex++) { memcpy(POINTER_OFFSET(dst, element_size * pindex), - POINTER_OFFSET(remaining_data, element_size * i), + POINTER_OFFSET(remaining_data, element_size * pindex), element_size); } - remaining_data = POINTER_OFFSET(remaining_data, particles.size() * element_size); + remaining_data = POINTER_OFFSET(remaining_data, range_size * element_size); } } -void ParticleSets::set_repeated_elements(uint index, +void NewParticles::set_repeated_elements(uint index, void *data, uint data_element_amount, void *default_value) @@ -43,13 +48,16 @@ void ParticleSets::set_repeated_elements(uint index, return; } - AttributeType type = m_attributes_info.type_of(index); + AttributeType type = m_attributes_info->type_of(index); uint element_size = size_of_attribute_type(type); + uint offset = 0; - for (ParticleSet particles : m_sets) { - AttributeArrays attributes = particles.attributes(); + for (uint i = 0; i < this->range_amount(); i++) { + AttributeArrays attributes = this->segment(i); void *dst = attributes.get_ptr(index); - for (uint pindex : particles.pindices()) { + + uint range_size = m_ranges[i].size(); + for (uint pindex = 0; pindex < range_size; pindex++) { memcpy(POINTER_OFFSET(dst, element_size * pindex), POINTER_OFFSET(data, element_size * offset), element_size); @@ -61,16 +69,17 @@ void ParticleSets::set_repeated_elements(uint index, } } -void ParticleSets::fill_elements(uint index, void *value) +void NewParticles::fill_elements(uint index, void *value) { - AttributeType type = m_attributes_info.type_of(index); + AttributeType type = m_attributes_info->type_of(index); uint element_size = size_of_attribute_type(type); - for (ParticleSet particles : m_sets) { - AttributeArrays attributes = particles.attributes(); + for (uint i = 0; i < this->range_amount(); i++) { + AttributeArrays attributes = this->segment(i); void *dst = attributes.get_ptr(index); - for (uint pindex : particles.pindices()) { + uint range_size = m_ranges[i].size(); + for (uint pindex = 0; pindex < range_size; pindex++) { memcpy(POINTER_OFFSET(dst, element_size * pindex), value, element_size); } } diff --git a/source/blender/simulations/bparticles/particle_set.hpp b/source/blender/simulations/bparticles/particle_set.hpp index e2a930cb22d..5bd4174833a 100644 --- a/source/blender/simulations/bparticles/particle_set.hpp +++ b/source/blender/simulations/bparticles/particle_set.hpp @@ -4,96 +4,75 @@ namespace BParticles { -/** - * A set of particles all of which are in the same block. - */ -struct ParticleSet { +class NewParticles { private: - AttributeArrays m_attributes; - - /* Indices into the attribute arrays. - * Invariants: - * - Every index must exist at most once. - * - The indices must be sorted. */ - ArrayRef<uint> m_pindices; - - public: - ParticleSet(AttributeArrays attributes, ArrayRef<uint> pindices); - - /** - * Access the attributes of particles in the block on this set. - */ - AttributeArrays attributes(); - - /** - * Access particle indices in the block that are part of the set. - * Every value in this array is an index into the attribute arrays. - */ - ArrayRef<uint> pindices(); - - /** - * Number of particles in this set. - */ - uint size() const; - - /** - * Returns true when pindices()[i] == i for all i, otherwise false. - */ - bool pindices_are_trivial(); - - Range<uint> trivial_pindices(); -}; - -class ParticleSets { - private: - AttributesInfo &m_attributes_info; - Vector<ParticleSet> m_sets; + AttributesInfo *m_attributes_info; + Vector<ArrayRef<void *>> m_buffers; + Vector<Range<uint>> m_ranges; uint m_size; public: - ParticleSets(AttributesInfo &attributes_info, ArrayRef<ParticleSet> sets); - - ArrayRef<ParticleSet> sets(); + NewParticles(AttributesInfo &attributes_info, + Vector<ArrayRef<void *>> buffers, + Vector<Range<uint>> ranges); template<typename T> void set(uint index, ArrayRef<T> data) { BLI_assert(data.size() == m_size); - BLI_assert(m_attributes_info.type_of(index) == attribute_type_by_type<T>::value); + BLI_assert(m_attributes_info->type_of(index) == attribute_type_by_type<T>::value); this->set_elements(index, (void *)data.begin()); } template<typename T> void set(StringRef name, ArrayRef<T> data) { - uint index = m_attributes_info.attribute_index(name); + uint index = m_attributes_info->attribute_index(name); this->set<T>(index, data); } template<typename T> void set_repeated(uint index, ArrayRef<T> data) { - BLI_assert(m_attributes_info.type_of(index) == attribute_type_by_type<T>::value); + BLI_assert(m_attributes_info->type_of(index) == attribute_type_by_type<T>::value); this->set_repeated_elements( - index, (void *)data.begin(), data.size(), m_attributes_info.default_value_ptr(index)); + index, (void *)data.begin(), data.size(), m_attributes_info->default_value_ptr(index)); } template<typename T> void set_repeated(StringRef name, ArrayRef<T> data) { - uint index = m_attributes_info.attribute_index(name); + uint index = m_attributes_info->attribute_index(name); this->set_repeated<T>(index, data); } template<typename T> void fill(uint index, T value) { - BLI_assert(m_attributes_info.type_of(index) == attribute_type_by_type<T>::value); + BLI_assert(m_attributes_info->type_of(index) == attribute_type_by_type<T>::value); this->fill_elements(index, (void *)&value); } template<typename T> void fill(StringRef name, T value) { - uint index = m_attributes_info.attribute_index(name); + uint index = m_attributes_info->attribute_index(name); this->fill<T>(index, value); } - AttributesInfo &attributes_info(); + AttributeArrays segment(uint i) + { + return AttributeArrays(*m_attributes_info, m_buffers[i], m_ranges[i]); + } + + AttributesInfo &attributes_info() + { + return *m_attributes_info; + } + + uint range_amount() const + { + return m_buffers.size(); + } + + Range<uint> range(uint i) const + { + return m_ranges[i]; + } private: void set_elements(uint index, void *data); @@ -104,62 +83,4 @@ class ParticleSets { void fill_elements(uint index, void *value); }; -/* ParticleSet inline functions - *******************************************/ - -inline ParticleSet::ParticleSet(AttributeArrays attributes, ArrayRef<uint> pindices) - : m_attributes(attributes), m_pindices(pindices) -{ -} - -inline AttributeArrays ParticleSet::attributes() -{ - return m_attributes; -} - -inline ArrayRef<uint> ParticleSet::pindices() -{ - return m_pindices; -} - -inline uint ParticleSet::size() const -{ - return m_pindices.size(); -} - -inline bool ParticleSet::pindices_are_trivial() -{ - if (m_pindices.size() == 0) { - return true; - } - else { - /* This works due to the invariants mentioned above. */ - return m_pindices.first() == 0 && m_pindices.last() == m_pindices.size() - 1; - } -} - -inline Range<uint> ParticleSet::trivial_pindices() -{ - BLI_assert(this->pindices_are_trivial()); - if (m_pindices.size() == 0) { - return Range<uint>(0, 0); - } - else { - return Range<uint>(m_pindices.first(), m_pindices.last() + 1); - } -} - -/* ParticleSets inline functions - ********************************************/ - -inline ArrayRef<ParticleSet> ParticleSets::sets() -{ - return m_sets; -} - -inline AttributesInfo &ParticleSets::attributes_info() -{ - return m_attributes_info; -} - } // namespace BParticles diff --git a/source/blender/simulations/bparticles/particles_container.hpp b/source/blender/simulations/bparticles/particles_container.hpp index 6f21d7ef231..075b5c7cdef 100644 --- a/source/blender/simulations/bparticles/particles_container.hpp +++ b/source/blender/simulations/bparticles/particles_container.hpp @@ -181,6 +181,8 @@ class ParticlesBlock { AttributeArrays attributes_slice(uint start, uint length); AttributeArrays attributes_slice(Range<uint> range); + ArrayRef<void *> attribute_buffers(); + /** * Copy the attributes of one particle to another index in the same block. */ @@ -320,4 +322,9 @@ inline AttributeArrays ParticlesBlock::attributes() return this->attributes_slice(Range<uint>(0, m_active_amount)); } +inline ArrayRef<void *> ParticlesBlock::attribute_buffers() +{ + return m_attribute_buffers; +} + } // namespace BParticles diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp index ec26525daf6..b0fd6c3ea02 100644 --- a/source/blender/simulations/bparticles/simulate.cpp +++ b/source/blender/simulations/bparticles/simulate.cpp @@ -79,27 +79,18 @@ BLI_NOINLINE static void forward_particles_to_next_event_or_end( handler->execute(interface); } - ParticleSet particles(step_data.attributes, pindices); - + auto attributes = step_data.attributes; auto attribute_offsets = step_data.attribute_offsets; for (uint attribute_index : attribute_offsets.info().attribute_indices()) { StringRef name = attribute_offsets.info().name_of(attribute_index); /* Only vectors can be integrated for now. */ - auto values = particles.attributes().get<float3>(name); + auto values = attributes.get<float3>(name); auto offsets = attribute_offsets.get<float3>(attribute_index); - if (particles.pindices_are_trivial()) { - for (uint pindex : particles.trivial_pindices()) { - float time_factor = time_factors_to_next_event[pindex]; - values[pindex] += time_factor * offsets[pindex]; - } - } - else { - for (uint pindex : particles.pindices()) { - float time_factor = time_factors_to_next_event[pindex]; - values[pindex] += time_factor * offsets[pindex]; - } + for (uint pindex : pindices) { + float time_factor = time_factors_to_next_event[pindex]; + values[pindex] += time_factor * offsets[pindex]; } } } @@ -266,34 +257,6 @@ BLI_NOINLINE static void simulate_with_max_n_events(BlockStepData &step_data, } } -BLI_NOINLINE static void add_float3_arrays(ArrayRef<float3> base, ArrayRef<float3> values) -{ - /* I'm just testing the impact of vectorization here. - * This should eventually be moved to another place. */ - BLI_assert(base.size() == values.size()); - BLI_assert(POINTER_AS_UINT(base.begin()) % 16 == 0); - BLI_assert(POINTER_AS_UINT(values.begin()) % 16 == 0); - - float *base_start = (float *)base.begin(); - float *values_start = (float *)values.begin(); - uint total_size = base.size() * 3; - uint overshoot = total_size % 4; - uint vectorized_size = total_size - overshoot; - - /* Twice as fast in my test than the normal loop. - * The compiler did not vectorize it, maybe for compatibility? */ - for (uint i = 0; i < vectorized_size; i += 4) { - __m128 a = _mm_load_ps(base_start + i); - __m128 b = _mm_load_ps(values_start + i); - __m128 result = _mm_add_ps(a, b); - _mm_store_ps(base_start + i, result); - } - - for (uint i = vectorized_size; i < total_size; i++) { - base_start[i] += values_start[i]; - } -} - BLI_NOINLINE static void apply_remaining_offsets(BlockStepData &step_data, ArrayRef<OffsetHandler *> offset_handlers, ArrayRef<uint> pindices) @@ -308,23 +271,18 @@ BLI_NOINLINE static void apply_remaining_offsets(BlockStepData &step_data, } } + auto attributes = step_data.attributes; auto attribute_offsets = step_data.attribute_offsets; - ParticleSet particles(step_data.attributes, pindices); for (uint attribute_index : attribute_offsets.info().attribute_indices()) { StringRef name = attribute_offsets.info().name_of(attribute_index); /* Only vectors can be integrated for now. */ - auto values = particles.attributes().get<float3>(name); + auto values = attributes.get<float3>(name); auto offsets = attribute_offsets.get<float3>(attribute_index); - if (particles.pindices_are_trivial()) { - add_float3_arrays(values.take_front(particles.size()), offsets.take_front(particles.size())); - } - else { - for (uint pindex : particles.pindices()) { - values[pindex] += offsets[pindex]; - } + for (uint pindex : pindices) { + values[pindex] += offsets[pindex]; } } } diff --git a/source/blender/simulations/bparticles/step_description_interfaces.hpp b/source/blender/simulations/bparticles/step_description_interfaces.hpp index a866f4fa735..ee3f8d49c60 100644 --- a/source/blender/simulations/bparticles/step_description_interfaces.hpp +++ b/source/blender/simulations/bparticles/step_description_interfaces.hpp @@ -142,9 +142,9 @@ class EventFilterInterface : public BlockStepDataAccess { Vector<float> &r_filtered_time_factors); /** - * Return the particle set that should be checked. + * Return the indices that should be checked. */ - ParticleSet particles(); + ArrayRef<uint> pindices(); /** * Mark a particle as triggered by the event at a specific point in time. @@ -178,9 +178,9 @@ class EventExecuteInterface : public BlockStepDataAccess { ~EventExecuteInterface() = default; /** - * Access the set of particles that should be modified by this event. + * Access the indices that should be modified by this event. */ - ParticleSet particles(); + ArrayRef<uint> pindices(); /** * Get the time at which every particle is modified by this event. @@ -208,7 +208,7 @@ class IntegratorInterface : public BlockStepDataAccess { public: IntegratorInterface(BlockStepData &step_data, ArrayRef<uint> pindices); - ParticleSet particles(); + ArrayRef<uint> pindices(); }; class OffsetHandlerInterface : public BlockStepDataAccess { @@ -221,7 +221,7 @@ class OffsetHandlerInterface : public BlockStepDataAccess { ArrayRef<uint> pindices, ArrayRef<float> time_factors); - ParticleSet particles(); + ArrayRef<uint> pindices(); ArrayRef<float> time_factors(); }; @@ -273,9 +273,9 @@ inline uint EventStorage::max_element_size() const /* EventFilterInterface inline functions **********************************************/ -inline ParticleSet EventFilterInterface::particles() +inline ArrayRef<uint> EventFilterInterface::pindices() { - return ParticleSet(m_step_data.attributes, m_pindices); + return m_pindices; } inline void EventFilterInterface::trigger_particle(uint pindex, float time_factor) @@ -312,9 +312,9 @@ inline EventStorage &EventExecuteInterface::event_storage() return m_event_storage; } -inline ParticleSet EventExecuteInterface::particles() +inline ArrayRef<uint> EventExecuteInterface::pindices() { - return ParticleSet(m_step_data.attributes, m_pindices); + return m_pindices; } inline ArrayRef<float> EventExecuteInterface::current_times() @@ -332,9 +332,9 @@ template<typename T> inline T &EventExecuteInterface::get_storage(uint pindex) /* OffsetHandlerInterface inline functions **********************************************/ -inline ParticleSet OffsetHandlerInterface::particles() +inline ArrayRef<uint> OffsetHandlerInterface::pindices() { - return ParticleSet(m_step_data.attributes, m_pindices); + return m_pindices; } inline ArrayRef<float> OffsetHandlerInterface::time_factors() @@ -345,9 +345,9 @@ inline ArrayRef<float> OffsetHandlerInterface::time_factors() /* IntegratorInterface inline functions **********************************************/ -inline ParticleSet IntegratorInterface::particles() +inline ArrayRef<uint> IntegratorInterface::pindices() { - return ParticleSet(m_step_data.attributes, m_pindices); + return m_pindices; } } // namespace BParticles |