| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <AnKi/Scene/Components/ParticleEmitter2Component.h>
- #include <AnKi/Scene/Components/MeshComponent.h>
- #include <AnKi/Resource/ParticleEmitterResource2.h>
- #include <AnKi/Resource/ResourceManager.h>
- #include <AnKi/GpuMemory/RebarTransientMemoryPool.h>
- namespace anki {
- // Contains some shared geometry data and it's a singleton because we don't want to be wasting time and memory for every emitter
- class ParticleEmitter2Component::ParticleEmitterQuadGeometry : public MakeSingleton<ParticleEmitterQuadGeometry>
- {
- public:
- UnifiedGeometryBufferAllocation m_quadPositions;
- UnifiedGeometryBufferAllocation m_quadUvs;
- UnifiedGeometryBufferAllocation m_quadIndices;
- U32 m_userCount = 0;
- SpinLock m_mtx;
- void init()
- {
- // Allocate and populate a quad
- const U32 vertCount = 4;
- const U32 indexCount = 6;
- m_quadPositions = UnifiedGeometryBuffer::getSingleton().allocateFormat(kMeshRelatedVertexStreamFormats[VertexStreamId::kPosition], vertCount);
- m_quadUvs = UnifiedGeometryBuffer::getSingleton().allocateFormat(kMeshRelatedVertexStreamFormats[VertexStreamId::kUv], vertCount);
- m_quadIndices = UnifiedGeometryBuffer::getSingleton().allocateFormat(Format::kR16_Uint, indexCount);
- static_assert(kMeshRelatedVertexStreamFormats[VertexStreamId::kPosition] == Format::kR16G16B16A16_Unorm);
- WeakArray<U16Vec4> transientPositions;
- const BufferView positionsAlloc = RebarTransientMemoryPool::getSingleton().allocateCopyBuffer(vertCount, transientPositions);
- transientPositions[0] = U16Vec4(0, 0, 0, 0);
- transientPositions[1] = U16Vec4(kMaxU16, 0, 0, 0);
- transientPositions[2] = U16Vec4(kMaxU16, kMaxU16, 0, 0);
- transientPositions[3] = U16Vec4(0, kMaxU16, 0, 0);
- static_assert(kMeshRelatedVertexStreamFormats[VertexStreamId::kUv] == Format::kR32G32_Sfloat);
- WeakArray<Vec2> transientUvs;
- const BufferView uvsAlloc = RebarTransientMemoryPool::getSingleton().allocateCopyBuffer(vertCount, transientUvs);
- transientUvs[0] = Vec2(0.0f);
- transientUvs[1] = Vec2(1.0f, 0.0f);
- transientUvs[2] = Vec2(1.0f, 1.0f);
- transientUvs[3] = Vec2(0.0f, 1.0f);
- WeakArray<U16> transientIndices;
- const BufferView indicesAlloc = RebarTransientMemoryPool::getSingleton().allocateCopyBuffer(indexCount, transientIndices);
- transientIndices[0] = 0;
- transientIndices[1] = 1;
- transientIndices[2] = 3;
- transientIndices[3] = 1;
- transientIndices[4] = 2;
- transientIndices[5] = 3;
- CommandBufferInitInfo cmdbInit("Particle quad upload");
- cmdbInit.m_flags |= CommandBufferFlag::kSmallBatch;
- CommandBufferPtr cmdb = GrManager::getSingleton().newCommandBuffer(cmdbInit);
- Buffer* dstBuff = &UnifiedGeometryBuffer::getSingleton().getBuffer();
- cmdb->copyBufferToBuffer(positionsAlloc, m_quadPositions);
- cmdb->copyBufferToBuffer(uvsAlloc, m_quadUvs);
- cmdb->copyBufferToBuffer(indicesAlloc, m_quadIndices);
- BufferBarrierInfo barrier;
- barrier.m_bufferView = BufferView(dstBuff);
- barrier.m_previousUsage = BufferUsageBit::kCopyDestination;
- barrier.m_nextUsage = dstBuff->getBufferUsage();
- cmdb->setPipelineBarrier({}, {&barrier, 1}, {});
- cmdb->endRecording();
- GrManager::getSingleton().submit(cmdb.get());
- }
- void deinit()
- {
- UnifiedGeometryBuffer::getSingleton().deferredFree(m_quadPositions);
- UnifiedGeometryBuffer::getSingleton().deferredFree(m_quadUvs);
- UnifiedGeometryBuffer::getSingleton().deferredFree(m_quadIndices);
- }
- void addUser()
- {
- LockGuard lock(m_mtx);
- if(m_userCount == 0)
- {
- init();
- }
- ++m_userCount;
- }
- void removeUser()
- {
- LockGuard lock(m_mtx);
- ANKI_ASSERT(m_userCount > 0);
- if(m_userCount == 1)
- {
- deinit();
- }
- --m_userCount;
- }
- };
- ParticleEmitter2Component::ParticleEmitter2Component(SceneNode* node)
- : SceneComponent(node, kClassType)
- {
- ParticleEmitterQuadGeometry::getSingleton().addUser();
- }
- ParticleEmitter2Component::~ParticleEmitter2Component()
- {
- ParticleEmitterQuadGeometry::getSingleton().removeUser();
- }
- ParticleEmitter2Component& ParticleEmitter2Component::setParticleEmitterFilename(CString fname)
- {
- ParticleEmitterResource2Ptr newRsrc;
- const Error err = ResourceManager::getSingleton().loadResource(fname, newRsrc);
- if(err)
- {
- ANKI_SCENE_LOGE("Failed to load resource: %s", fname.cstr());
- }
- else
- {
- m_particleEmitterResource = std::move(newRsrc);
- m_resourceDirty = true;
- }
- return *this;
- }
- CString ParticleEmitter2Component::getParticleEmitterFilename() const
- {
- if(m_particleEmitterResource)
- {
- return m_particleEmitterResource->getFilename();
- }
- else
- {
- return "*Error*";
- }
- }
- void ParticleEmitter2Component::onOtherComponentRemovedOrAdded(SceneComponent* other, Bool added)
- {
- ANKI_ASSERT(other);
- if(other->getType() == SceneComponentType::kMesh)
- {
- bookkeepComponent(m_meshComponents, other, added, m_meshComponentDirty);
- }
- }
- void ParticleEmitter2Component::update(SceneComponentUpdateInfo& info, Bool& updated)
- {
- if(!isValid())
- {
- return;
- }
- if(!m_resourceDirty && !m_geomTypeDirty && !m_meshComponentDirty) [[likely]]
- {
- return;
- }
- // From now on it's dirty and needs some kind of update
- updated = true;
- // Streams
- if(m_resourceDirty)
- {
- for(ParticleProperty prop : EnumIterable<ParticleProperty>())
- {
- GpuSceneBuffer::getSingleton().deferredFree(m_gpuScene.m_particleStreams[prop]);
- m_gpuScene.m_particleStreams[prop] = GpuSceneBuffer::getSingleton().allocate(kParticlePropertySize[prop], alignof(U32));
- }
- }
- // Alive particles index buffer
- if(m_resourceDirty)
- {
- const ParticleEmitterResourceCommonProperties& commonProps = m_particleEmitterResource->getCommonProperties();
- GpuSceneBuffer::getSingleton().deferredFree(m_gpuScene.m_aliveParticleIndices);
- m_gpuScene.m_aliveParticleIndices = GpuSceneBuffer::getSingleton().allocate(commonProps.m_particleCount * sizeof(U32), alignof(U32));
- }
- // AnKiParticleEmitterProperties
- if(m_resourceDirty)
- {
- GpuSceneBuffer::getSingleton().deferredFree(m_gpuScene.m_anKiParticleEmitterProperties);
- ConstWeakArray<U8> prefilled = m_particleEmitterResource->getPrefilledAnKiParticleEmitterProperties();
- m_gpuScene.m_anKiParticleEmitterProperties = GpuSceneBuffer::getSingleton().allocate(prefilled.getSizeInBytes(), alignof(U32));
- GpuSceneMicroPatcher::getSingleton().newCopy(*info.m_framePool, m_gpuScene.m_anKiParticleEmitterProperties, prefilled);
- }
- // GpuSceneParticleEmitter2
- const Bool updateGpuSceneEmitter = m_resourceDirty || m_meshComponentDirty || m_geomTypeDirty;
- if(updateGpuSceneEmitter)
- {
- if(!m_gpuScene.m_gpuSceneParticleEmitter)
- {
- m_gpuScene.m_gpuSceneParticleEmitter.allocate();
- }
- const ParticleEmitterResourceCommonProperties& commonProps = m_particleEmitterResource->getCommonProperties();
- GpuSceneParticleEmitter2 emitter;
- zeroMemory(emitter);
- for(ParticleProperty prop : EnumIterable<ParticleProperty>())
- {
- emitter.m_particleStateSteamOffsets[U32(prop)] = m_gpuScene.m_particleStreams[prop].getOffset();
- }
- emitter.m_aliveParticleIndicesOffset = m_gpuScene.m_aliveParticleIndices.getOffset();
- emitter.m_particleCount = commonProps.m_particleCount;
- emitter.m_emissionPeriod = commonProps.m_emissionPeriod;
- emitter.m_particlesPerEmission = commonProps.m_particlesPerEmission;
- emitter.m_particleEmitterPropertiesOffset = m_gpuScene.m_anKiParticleEmitterProperties.getOffset();
- // TODO
- }
- }
- } // end namespace anki
|