Improved ResourceListeners
Former-commit-id: 8016c23cb75aab94762a1e2838dbbcac2093119b
This commit is contained in:
parent
4b1a6cc09e
commit
d4cff9946e
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <atomic>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
|
|
@ -19,23 +19,6 @@
|
|||
|
||||
class NzResourceListener;
|
||||
|
||||
struct NzResourceEntry
|
||||
{
|
||||
NzResourceEntry(NzResourceListener* resourceListener, int i = 0) :
|
||||
listener(resourceListener),
|
||||
index(i)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const NzResourceEntry& rhs) const
|
||||
{
|
||||
return listener < rhs.listener;
|
||||
}
|
||||
|
||||
NzResourceListener* listener;
|
||||
int index;
|
||||
};
|
||||
|
||||
class NAZARA_API NzResource
|
||||
{
|
||||
public:
|
||||
|
|
@ -59,16 +42,13 @@ class NAZARA_API NzResource
|
|||
void NotifyDestroy();
|
||||
|
||||
private:
|
||||
void EnsureResourceListenerUpdate() const;
|
||||
|
||||
NazaraMutexAttrib(m_mutex, mutable)
|
||||
|
||||
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms
|
||||
mutable std::set<NzResourceEntry> m_resourceListeners;
|
||||
mutable std::set<NzResourceEntry> m_resourceListenersCache;
|
||||
mutable bool m_resourceListenerUpdated;
|
||||
mutable std::unordered_map<NzResourceListener*, int> m_resourceListeners;
|
||||
std::atomic_bool m_resourcePersistent;
|
||||
mutable std::atomic_uint m_resourceReferenceCount;
|
||||
bool m_resourceListenersLocked;
|
||||
};
|
||||
|
||||
#endif // NAZARA_RESOURCE_HPP
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ class NAZARA_API NzResourceListener
|
|||
NzResourceListener() = default;
|
||||
virtual ~NzResourceListener();
|
||||
|
||||
virtual void OnResourceCreated(const NzResource* resource, int index);
|
||||
virtual void OnResourceDestroy(const NzResource* resource, int index);
|
||||
virtual bool OnResourceCreated(const NzResource* resource, int index);
|
||||
virtual bool OnResourceDestroy(const NzResource* resource, int index);
|
||||
virtual void OnResourceReleased(const NzResource* resource, int index);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
|
|||
void Sort(const NzCamera& camera);
|
||||
|
||||
private:
|
||||
void OnResourceDestroy(const NzResource* resource, int index);
|
||||
bool OnResourceDestroy(const NzResource* resource, int index) override;
|
||||
|
||||
struct ModelMaterialComparator
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class NAZARA_API NzRenderTexture : public NzRenderTarget, NzResourceListener, Nz
|
|||
void Desactivate() const override;
|
||||
|
||||
private:
|
||||
void OnResourceDestroy(const NzResource* resource, int index) override;
|
||||
bool OnResourceDestroy(const NzResource* resource, int index) override;
|
||||
|
||||
NzRenderTextureImpl* m_impl = nullptr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,15 +12,16 @@
|
|||
|
||||
NzResource::NzResource(bool persistent) :
|
||||
m_resourcePersistent(persistent),
|
||||
m_resourceReferenceCount(0)
|
||||
m_resourceReferenceCount(0),
|
||||
m_resourceListenersLocked(false)
|
||||
{
|
||||
}
|
||||
|
||||
NzResource::~NzResource()
|
||||
{
|
||||
EnsureResourceListenerUpdate();
|
||||
for (const NzResourceEntry& entry : m_resourceListenersCache)
|
||||
entry.listener->OnResourceReleased(this, entry.index);
|
||||
m_resourceListenersLocked = true;
|
||||
for (auto& pair : m_resourceListeners)
|
||||
pair.first->OnResourceReleased(this, pair.second);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_resourceReferenceCount > 0)
|
||||
|
|
@ -30,10 +31,11 @@ NzResource::~NzResource()
|
|||
|
||||
void NzResource::AddResourceListener(NzResourceListener* listener, int index) const
|
||||
{
|
||||
///DOC: Est ignoré si appelé depuis un évènement
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_resourceListeners.insert(NzResourceEntry(listener, index)).second)
|
||||
m_resourceListenerUpdated = false;
|
||||
if (!m_resourceListenersLocked)
|
||||
m_resourceListeners.insert(std::make_pair(listener, index));
|
||||
}
|
||||
|
||||
void NzResource::AddResourceReference() const
|
||||
|
|
@ -53,10 +55,11 @@ bool NzResource::IsPersistent() const
|
|||
|
||||
void NzResource::RemoveResourceListener(NzResourceListener* listener) const
|
||||
{
|
||||
NazaraMutexLock(m_mutex);
|
||||
///DOC: Est ignoré si appelé depuis un évènement
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (m_resourceListeners.erase(listener) != 0)
|
||||
m_resourceListenerUpdated = false;
|
||||
if (!m_resourceListenersLocked)
|
||||
m_resourceListeners.erase(listener);
|
||||
}
|
||||
|
||||
bool NzResource::RemoveResourceReference() const
|
||||
|
|
@ -97,26 +100,34 @@ void NzResource::NotifyCreated()
|
|||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
EnsureResourceListenerUpdate();
|
||||
for (const NzResourceEntry& entry : m_resourceListenersCache)
|
||||
entry.listener->OnResourceCreated(this, entry.index);
|
||||
m_resourceListenersLocked = true;
|
||||
|
||||
auto it = m_resourceListeners.begin();
|
||||
while (it != m_resourceListeners.end())
|
||||
{
|
||||
if (!it->first->OnResourceCreated(this, it->second))
|
||||
m_resourceListeners.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
m_resourceListenersLocked = false;
|
||||
}
|
||||
|
||||
void NzResource::NotifyDestroy()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
EnsureResourceListenerUpdate();
|
||||
for (const NzResourceEntry& entry : m_resourceListenersCache)
|
||||
entry.listener->OnResourceDestroy(this, entry.index);
|
||||
}
|
||||
m_resourceListenersLocked = true;
|
||||
|
||||
void NzResource::EnsureResourceListenerUpdate() const
|
||||
{
|
||||
// Déjà bloqué par une mutex
|
||||
if (!m_resourceListenerUpdated)
|
||||
auto it = m_resourceListeners.begin();
|
||||
while (it != m_resourceListeners.end())
|
||||
{
|
||||
m_resourceListenersCache = m_resourceListeners;
|
||||
m_resourceListenerUpdated = true;
|
||||
if (!it->first->OnResourceDestroy(this, it->second))
|
||||
m_resourceListeners.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
m_resourceListenersLocked = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,16 +7,20 @@
|
|||
|
||||
NzResourceListener::~NzResourceListener() = default;
|
||||
|
||||
void NzResourceListener::OnResourceCreated(const NzResource* resource, int index)
|
||||
bool NzResourceListener::OnResourceCreated(const NzResource* resource, int index)
|
||||
{
|
||||
NazaraUnused(resource);
|
||||
NazaraUnused(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzResourceListener::OnResourceDestroy(const NzResource* resource, int index)
|
||||
bool NzResourceListener::OnResourceDestroy(const NzResource* resource, int index)
|
||||
{
|
||||
NazaraUnused(resource);
|
||||
NazaraUnused(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzResourceListener::OnResourceReleased(const NzResource* resource, int index)
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ void NzForwardRenderQueue::Sort(const NzCamera& camera)
|
|||
std::sort(transparentsModels.begin(), transparentsModels.end(), comparator);
|
||||
}
|
||||
|
||||
void NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int index)
|
||||
bool NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
|
|
@ -231,7 +231,7 @@ void NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int ind
|
|||
}
|
||||
}
|
||||
|
||||
resource->RemoveResourceListener(this);
|
||||
return false; // Nous ne voulons plus recevoir d'évènement de cette ressource
|
||||
}
|
||||
|
||||
bool NzForwardRenderQueue::SkeletalMeshComparator::operator()(const NzSkeletalMesh* subMesh1, const NzSkeletalMesh* subMesh2)
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ bool NzGLSLProgram::SendVector(int location, const NzVector4f& vector)
|
|||
return true;
|
||||
}
|
||||
|
||||
void NzGLSLProgram::OnResourceCreated(const NzResource* resource, int index)
|
||||
bool NzGLSLProgram::OnResourceCreated(const NzResource* resource, int index)
|
||||
{
|
||||
NazaraUnused(resource);
|
||||
|
||||
|
|
@ -530,7 +530,7 @@ void NzGLSLProgram::OnResourceCreated(const NzResource* resource, int index)
|
|||
if (it == m_textures.end())
|
||||
{
|
||||
NazaraInternalError("Invalid index (" + NzString::Number(index) + ')');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -540,15 +540,17 @@ void NzGLSLProgram::OnResourceCreated(const NzResource* resource, int index)
|
|||
if (slot.texture != resource)
|
||||
{
|
||||
NazaraInternalError("Wrong texture at location #" + NzString::Number(index));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
slot.enabled = true;
|
||||
slot.updated = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzGLSLProgram::OnResourceDestroy(const NzResource* resource, int index)
|
||||
bool NzGLSLProgram::OnResourceDestroy(const NzResource* resource, int index)
|
||||
{
|
||||
NazaraUnused(resource);
|
||||
|
||||
|
|
@ -558,7 +560,7 @@ void NzGLSLProgram::OnResourceDestroy(const NzResource* resource, int index)
|
|||
if (it == m_textures.end())
|
||||
{
|
||||
NazaraInternalError("Invalid index (" + NzString::Number(index) + ')');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -568,19 +570,19 @@ void NzGLSLProgram::OnResourceDestroy(const NzResource* resource, int index)
|
|||
if (slot.texture != resource)
|
||||
{
|
||||
NazaraInternalError("Wrong texture at location #" + NzString::Number(index));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
slot.enabled = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzGLSLProgram::OnResourceReleased(const NzResource* resource, int index)
|
||||
{
|
||||
if (m_textures.erase(index) == 0)
|
||||
NazaraInternalError("Texture " + NzString::Pointer(resource) + " not found");
|
||||
|
||||
resource->RemoveResourceListener(this);
|
||||
}
|
||||
|
||||
void NzGLSLProgram::PreLinkage()
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ class NzGLSLProgram : public NzAbstractShaderProgram, NzResourceListener
|
|||
bool SendVector(int location, const NzVector4f& vector);
|
||||
|
||||
private:
|
||||
void OnResourceCreated(const NzResource* resource, int index) override;
|
||||
void OnResourceDestroy(const NzResource* resource, int index) override;
|
||||
bool OnResourceCreated(const NzResource* resource, int index) override;
|
||||
bool OnResourceDestroy(const NzResource* resource, int index) override;
|
||||
void OnResourceReleased(const NzResource* resource, int index) override;
|
||||
void PreLinkage();
|
||||
bool PostLinkage();
|
||||
|
|
|
|||
|
|
@ -324,11 +324,12 @@ void NzRenderTexture::Destroy()
|
|||
{
|
||||
if (m_impl)
|
||||
{
|
||||
bool canFreeFBO = true;
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (NzContext::GetCurrent() != m_impl->context)
|
||||
{
|
||||
NazaraError("RenderTexture can only be used with it's creation context");
|
||||
return;
|
||||
NazaraWarning("RenderTexture should be destroyed by it's creation context, this will cause leaks");
|
||||
canFreeFBO = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -339,7 +340,7 @@ void NzRenderTexture::Destroy()
|
|||
if (attachment.isUsed)
|
||||
{
|
||||
if (attachment.isBuffer)
|
||||
glDeleteRenderbuffers(1, &attachment.buffer);
|
||||
glDeleteRenderbuffers(1, &attachment.buffer); // Les Renderbuffers sont partagés entre les contextes: Ne posera pas de problème
|
||||
else
|
||||
{
|
||||
attachment.texture->SetRenderTexture(nullptr);
|
||||
|
|
@ -348,7 +349,8 @@ void NzRenderTexture::Destroy()
|
|||
}
|
||||
}
|
||||
|
||||
glDeleteFramebuffers(1, &m_impl->fbo);
|
||||
if (canFreeFBO)
|
||||
glDeleteFramebuffers(1, &m_impl->fbo);
|
||||
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
|
@ -636,11 +638,15 @@ void NzRenderTexture::Desactivate() const
|
|||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void NzRenderTexture::OnResourceDestroy(const NzResource* resource, int index)
|
||||
bool NzRenderTexture::OnResourceDestroy(const NzResource* resource, int index)
|
||||
{
|
||||
if (resource == m_impl->context)
|
||||
// Notre context a été détruit, libérons la RenderTexture pour éviter un leak
|
||||
{
|
||||
// Notre contexte va être détruit, libérons la RenderTexture pour éviter un leak
|
||||
Destroy();
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sinon, c'est une texture
|
||||
|
|
@ -652,5 +658,7 @@ void NzRenderTexture::OnResourceDestroy(const NzResource* resource, int index)
|
|||
|
||||
m_impl->checked = false;
|
||||
m_impl->drawBuffersUpdated = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,6 +128,4 @@ void NzStaticMesh::OnResourceReleased(const NzResource* resource, int index)
|
|||
m_vertexBuffer = nullptr;
|
||||
else
|
||||
NazaraInternalError("Not listening to " + NzString::Pointer(resource));
|
||||
|
||||
resource->RemoveResourceListener(this);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue