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