Fixed crash when resources in use by the Renderer are released
Former-commit-id: 98eedb556f0387f0a5c1cafde2fc74645d1d0457
This commit is contained in:
parent
f1dc7b98e5
commit
72a57fbf4c
|
|
@ -42,10 +42,14 @@ class NAZARA_API NzResource
|
||||||
void NotifyDestroy();
|
void NotifyDestroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
typedef std::unordered_map<NzResourceListener*, std::pair<int, unsigned int>> ResourceListenerMap;
|
||||||
|
|
||||||
|
void RemoveResourceListenerIterator(ResourceListenerMap::iterator iterator) 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::unordered_map<NzResourceListener*, int> m_resourceListeners;
|
mutable ResourceListenerMap m_resourceListeners;
|
||||||
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;
|
bool m_resourceListenersLocked;
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,13 @@ class NAZARA_API NzContext : public NzResource
|
||||||
|
|
||||||
const NzContextParameters& GetParameters() const;
|
const NzContextParameters& GetParameters() const;
|
||||||
bool IsActive() const;
|
bool IsActive() const;
|
||||||
bool SetActive(bool active);
|
bool SetActive(bool active) const;
|
||||||
void SwapBuffers();
|
void SwapBuffers();
|
||||||
|
|
||||||
static bool EnsureContext();
|
static bool EnsureContext();
|
||||||
static NzContext* GetCurrent();
|
static const NzContext* GetCurrent();
|
||||||
static NzContext* GetReference();
|
static const NzContext* GetReference();
|
||||||
static NzContext* GetThreadContext();
|
static const NzContext* GetThreadContext();
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,8 +133,8 @@ class NAZARA_API NzOpenGL
|
||||||
static GLenum TextureTargetProxy[nzImageType_Max+1];
|
static GLenum TextureTargetProxy[nzImageType_Max+1];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void OnContextDestruction(NzContext* context);
|
static void OnContextDestruction(const NzContext* context);
|
||||||
static void OnContextChange(NzContext* newContext);
|
static void OnContextChange(const NzContext* newContext);
|
||||||
};
|
};
|
||||||
|
|
||||||
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;
|
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,14 @@ class NzIndexBuffer;
|
||||||
class NzMaterial;
|
class NzMaterial;
|
||||||
class NzRenderTarget;
|
class NzRenderTarget;
|
||||||
class NzShaderProgram;
|
class NzShaderProgram;
|
||||||
|
class NzTexture;
|
||||||
class NzVertexBuffer;
|
class NzVertexBuffer;
|
||||||
|
|
||||||
class NAZARA_API NzRenderer
|
class NAZARA_API NzRenderer
|
||||||
{
|
{
|
||||||
|
friend NzShaderProgram;
|
||||||
|
friend NzTexture;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NzRenderer() = delete;
|
NzRenderer() = delete;
|
||||||
~NzRenderer() = delete;
|
~NzRenderer() = delete;
|
||||||
|
|
@ -96,6 +100,8 @@ class NAZARA_API NzRenderer
|
||||||
private:
|
private:
|
||||||
static void EnableInstancing(bool instancing);
|
static void EnableInstancing(bool instancing);
|
||||||
static bool EnsureStateUpdate();
|
static bool EnsureStateUpdate();
|
||||||
|
static void OnProgramReleased(const NzShaderProgram* program);
|
||||||
|
static void OnTextureReleased(const NzTexture* texture);
|
||||||
static void UpdateMatrix(nzMatrixType type);
|
static void UpdateMatrix(nzMatrixType type);
|
||||||
|
|
||||||
static unsigned int s_moduleReferenceCounter;
|
static unsigned int s_moduleReferenceCounter;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <Nazara/Core/Config.hpp>
|
#include <Nazara/Core/Config.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/ResourceListener.hpp>
|
#include <Nazara/Core/ResourceListener.hpp>
|
||||||
|
#include <Nazara/Utility/StaticMesh.hpp>
|
||||||
#include <Nazara/Utility/VertexDeclaration.hpp>
|
#include <Nazara/Utility/VertexDeclaration.hpp>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <Nazara/Core/Debug.hpp>
|
#include <Nazara/Core/Debug.hpp>
|
||||||
|
|
@ -21,7 +22,7 @@ NzResource::~NzResource()
|
||||||
{
|
{
|
||||||
m_resourceListenersLocked = true;
|
m_resourceListenersLocked = true;
|
||||||
for (auto& pair : m_resourceListeners)
|
for (auto& pair : m_resourceListeners)
|
||||||
pair.first->OnResourceReleased(this, pair.second);
|
pair.first->OnResourceReleased(this, pair.second.first);
|
||||||
|
|
||||||
#if NAZARA_CORE_SAFE
|
#if NAZARA_CORE_SAFE
|
||||||
if (m_resourceReferenceCount > 0)
|
if (m_resourceReferenceCount > 0)
|
||||||
|
|
@ -35,7 +36,11 @@ void NzResource::AddResourceListener(NzResourceListener* listener, int index) co
|
||||||
NazaraLock(m_mutex)
|
NazaraLock(m_mutex)
|
||||||
|
|
||||||
if (!m_resourceListenersLocked)
|
if (!m_resourceListenersLocked)
|
||||||
m_resourceListeners.insert(std::make_pair(listener, index));
|
{
|
||||||
|
auto pair = m_resourceListeners.insert(std::make_pair(listener, std::make_pair(index, 1U)));
|
||||||
|
if (!pair.second)
|
||||||
|
pair.first->second.second++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzResource::AddResourceReference() const
|
void NzResource::AddResourceReference() const
|
||||||
|
|
@ -59,7 +64,11 @@ void NzResource::RemoveResourceListener(NzResourceListener* listener) const
|
||||||
NazaraLock(m_mutex);
|
NazaraLock(m_mutex);
|
||||||
|
|
||||||
if (!m_resourceListenersLocked)
|
if (!m_resourceListenersLocked)
|
||||||
m_resourceListeners.erase(listener);
|
{
|
||||||
|
ResourceListenerMap::iterator it = m_resourceListeners.find(listener);
|
||||||
|
if (it != m_resourceListeners.end())
|
||||||
|
RemoveResourceListenerIterator(it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzResource::RemoveResourceReference() const
|
bool NzResource::RemoveResourceReference() const
|
||||||
|
|
@ -105,8 +114,9 @@ void NzResource::NotifyCreated()
|
||||||
auto it = m_resourceListeners.begin();
|
auto it = m_resourceListeners.begin();
|
||||||
while (it != m_resourceListeners.end())
|
while (it != m_resourceListeners.end())
|
||||||
{
|
{
|
||||||
if (!it->first->OnResourceCreated(this, it->second))
|
ResourceListenerMap::iterator iterator = it++;
|
||||||
m_resourceListeners.erase(it++);
|
if (!it->first->OnResourceCreated(this, it->second.first))
|
||||||
|
RemoveResourceListenerIterator(it++);
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
@ -123,11 +133,20 @@ void NzResource::NotifyDestroy()
|
||||||
auto it = m_resourceListeners.begin();
|
auto it = m_resourceListeners.begin();
|
||||||
while (it != m_resourceListeners.end())
|
while (it != m_resourceListeners.end())
|
||||||
{
|
{
|
||||||
if (!it->first->OnResourceDestroy(this, it->second))
|
if (!it->first->OnResourceDestroy(this, it->second.first))
|
||||||
m_resourceListeners.erase(it++);
|
RemoveResourceListenerIterator(it++);
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_resourceListenersLocked = false;
|
m_resourceListenersLocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzResource::RemoveResourceListenerIterator(ResourceListenerMap::iterator iterator) const
|
||||||
|
{
|
||||||
|
unsigned int& referenceCount = iterator->second.second;
|
||||||
|
if (referenceCount == 1)
|
||||||
|
m_resourceListeners.erase(iterator);
|
||||||
|
else
|
||||||
|
referenceCount--;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
thread_local NzContext* currentContext = nullptr;
|
thread_local const NzContext* currentContext = nullptr;
|
||||||
thread_local NzContext* threadContext = nullptr;
|
thread_local const NzContext* threadContext = nullptr;
|
||||||
|
|
||||||
std::vector<NzContext*> contexts;
|
std::vector<NzContext*> contexts;
|
||||||
|
|
||||||
|
|
@ -219,7 +219,7 @@ bool NzContext::IsActive() const
|
||||||
return currentContext == this;
|
return currentContext == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzContext::SetActive(bool active)
|
bool NzContext::SetActive(bool active) const
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_RENDERER_SAFE
|
#ifdef NAZARA_RENDERER_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -302,17 +302,17 @@ bool NzContext::EnsureContext()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzContext* NzContext::GetCurrent()
|
const NzContext* NzContext::GetCurrent()
|
||||||
{
|
{
|
||||||
return currentContext;
|
return currentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzContext* NzContext::GetReference()
|
const NzContext* NzContext::GetReference()
|
||||||
{
|
{
|
||||||
return s_reference;
|
return s_reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzContext* NzContext::GetThreadContext()
|
const NzContext* NzContext::GetThreadContext()
|
||||||
{
|
{
|
||||||
EnsureContext();
|
EnsureContext();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ namespace
|
||||||
};
|
};
|
||||||
|
|
||||||
std::set<NzString> s_openGLextensionSet;
|
std::set<NzString> s_openGLextensionSet;
|
||||||
std::unordered_map<NzContext*, ContextStates> s_contexts;
|
std::unordered_map<const NzContext*, ContextStates> s_contexts;
|
||||||
thread_local ContextStates* s_contextStates = nullptr;
|
thread_local ContextStates* s_contextStates = nullptr;
|
||||||
NzString s_rendererName;
|
NzString s_rendererName;
|
||||||
NzString s_vendorName;
|
NzString s_vendorName;
|
||||||
|
|
@ -1305,12 +1305,12 @@ void NzOpenGL::Uninitialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzOpenGL::OnContextDestruction(NzContext* context)
|
void NzOpenGL::OnContextDestruction(const NzContext* context)
|
||||||
{
|
{
|
||||||
s_contexts.erase(context);
|
s_contexts.erase(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzOpenGL::OnContextChange(NzContext* newContext)
|
void NzOpenGL::OnContextChange(const NzContext* newContext)
|
||||||
{
|
{
|
||||||
s_contextStates = (newContext) ? &s_contexts[newContext] : nullptr;
|
s_contextStates = (newContext) ? &s_contexts[newContext] : nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ bool NzRenderWindow::CopyToImage(NzImage* image) const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NzContext* currentContext = NzContext::GetCurrent();
|
const NzContext* currentContext = NzContext::GetCurrent();
|
||||||
if (m_context != currentContext)
|
if (m_context != currentContext)
|
||||||
{
|
{
|
||||||
if (!m_context->SetActive(true))
|
if (!m_context->SetActive(true))
|
||||||
|
|
@ -112,7 +112,7 @@ bool NzRenderWindow::CopyToTexture(NzTexture* texture) const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NzContext* currentContext = NzContext::GetCurrent();
|
const NzContext* currentContext = NzContext::GetCurrent();
|
||||||
if (m_context != currentContext)
|
if (m_context != currentContext)
|
||||||
{
|
{
|
||||||
if (!m_context->SetActive(true))
|
if (!m_context->SetActive(true))
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,14 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
enum ResourceType
|
||||||
|
{
|
||||||
|
ResourceType_Context,
|
||||||
|
ResourceType_IndexBuffer,
|
||||||
|
ResourceType_VertexBuffer,
|
||||||
|
ResourceType_VertexDeclaration
|
||||||
|
};
|
||||||
|
|
||||||
enum UpdateFlags
|
enum UpdateFlags
|
||||||
{
|
{
|
||||||
Update_None = 0,
|
Update_None = 0,
|
||||||
|
|
@ -64,8 +72,9 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
using VAO_Key = std::tuple<const NzIndexBuffer*, const NzVertexBuffer*, const NzVertexDeclaration*, const NzVertexDeclaration*>;
|
using VAO_Key = std::tuple<const NzIndexBuffer*, const NzVertexBuffer*, const NzVertexDeclaration*, const NzVertexDeclaration*>;
|
||||||
|
using VAO_Map = std::unordered_map<const NzContext*, std::map<VAO_Key, unsigned int>>;
|
||||||
|
|
||||||
std::unordered_map<NzContext*, std::map<VAO_Key, unsigned int>> s_vaos;
|
VAO_Map s_vaos;
|
||||||
std::set<unsigned int> s_dirtyTextureUnits;
|
std::set<unsigned int> s_dirtyTextureUnits;
|
||||||
std::vector<TextureUnit> s_textureUnits;
|
std::vector<TextureUnit> s_textureUnits;
|
||||||
GLuint s_currentVAO = 0;
|
GLuint s_currentVAO = 0;
|
||||||
|
|
@ -89,6 +98,90 @@ namespace
|
||||||
unsigned int s_maxRenderTarget;
|
unsigned int s_maxRenderTarget;
|
||||||
unsigned int s_maxTextureUnit;
|
unsigned int s_maxTextureUnit;
|
||||||
unsigned int s_maxVertexAttribs;
|
unsigned int s_maxVertexAttribs;
|
||||||
|
|
||||||
|
class ResourceListener : public NzResourceListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void OnResourceReleased(const NzResource* resource, int index) override
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case ResourceType_Context:
|
||||||
|
{
|
||||||
|
const NzContext* context = static_cast<const NzContext*>(resource);
|
||||||
|
s_vaos.erase(context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ResourceType_IndexBuffer:
|
||||||
|
{
|
||||||
|
const NzIndexBuffer* indexBuffer = static_cast<const NzIndexBuffer*>(resource);
|
||||||
|
for (auto& pair : s_vaos)
|
||||||
|
{
|
||||||
|
auto it = pair.second.begin();
|
||||||
|
while (it != pair.second.end())
|
||||||
|
{
|
||||||
|
const VAO_Key& key = it->first;
|
||||||
|
const NzIndexBuffer* vaoIndexBuffer = std::get<0>(key);
|
||||||
|
|
||||||
|
if (vaoIndexBuffer == indexBuffer)
|
||||||
|
pair.second.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ResourceType_VertexBuffer:
|
||||||
|
{
|
||||||
|
const NzVertexBuffer* vertexBuffer = static_cast<const NzVertexBuffer*>(resource);
|
||||||
|
for (auto& pair : s_vaos)
|
||||||
|
{
|
||||||
|
auto it = pair.second.begin();
|
||||||
|
while (it != pair.second.end())
|
||||||
|
{
|
||||||
|
const VAO_Key& key = it->first;
|
||||||
|
const NzVertexBuffer* vaoVertexBuffer = std::get<1>(key);
|
||||||
|
|
||||||
|
if (vaoVertexBuffer == vertexBuffer)
|
||||||
|
pair.second.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ResourceType_VertexDeclaration:
|
||||||
|
{
|
||||||
|
const NzVertexDeclaration* vertexDeclaration = static_cast<const NzVertexDeclaration*>(resource);
|
||||||
|
for (auto& pair : s_vaos)
|
||||||
|
{
|
||||||
|
auto it = pair.second.begin();
|
||||||
|
while (it != pair.second.end())
|
||||||
|
{
|
||||||
|
const VAO_Key& key = it->first;
|
||||||
|
const NzVertexDeclaration* vaoVertexDeclaration = std::get<2>(key);
|
||||||
|
const NzVertexDeclaration* vaoInstancingDeclaration = std::get<3>(key);
|
||||||
|
|
||||||
|
if (vaoVertexDeclaration == vertexDeclaration || vaoInstancingDeclaration == vertexDeclaration)
|
||||||
|
pair.second.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
NazaraInternalError("Unknown resource type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ResourceListener s_listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzRenderer::Clear(nzUInt32 flags)
|
void NzRenderer::Clear(nzUInt32 flags)
|
||||||
|
|
@ -1164,12 +1257,33 @@ void NzRenderer::Uninitialize()
|
||||||
// Libération des VAOs
|
// Libération des VAOs
|
||||||
for (auto& pair : s_vaos)
|
for (auto& pair : s_vaos)
|
||||||
{
|
{
|
||||||
|
const NzContext* context = pair.first;
|
||||||
|
context->SetActive(true);
|
||||||
|
|
||||||
for (auto& pair2 : pair.second)
|
for (auto& pair2 : pair.second)
|
||||||
{
|
{
|
||||||
|
const VAO_Key& key = pair2.first;
|
||||||
|
const NzIndexBuffer* indexBuffer = std::get<0>(key);
|
||||||
|
const NzVertexBuffer* vertexBuffer = std::get<1>(key);
|
||||||
|
const NzVertexDeclaration* vertexDeclaration = std::get<2>(key);
|
||||||
|
const NzVertexDeclaration* instancingDeclaration = std::get<3>(key);
|
||||||
|
|
||||||
|
if (indexBuffer)
|
||||||
|
indexBuffer->RemoveResourceListener(&s_listener);
|
||||||
|
|
||||||
|
vertexBuffer->RemoveResourceListener(&s_listener);
|
||||||
|
vertexDeclaration->RemoveResourceListener(&s_listener);
|
||||||
|
|
||||||
|
if (instancingDeclaration)
|
||||||
|
instancingDeclaration->RemoveResourceListener(&s_listener);
|
||||||
|
|
||||||
GLuint vao = static_cast<GLuint>(pair2.second);
|
GLuint vao = static_cast<GLuint>(pair2.second);
|
||||||
glDeleteVertexArrays(1, &vao);
|
glDeleteVertexArrays(1, &vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context->SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_vaos.clear();
|
s_vaos.clear();
|
||||||
|
|
||||||
NzOpenGL::Uninitialize();
|
NzOpenGL::Uninitialize();
|
||||||
|
|
@ -1256,18 +1370,21 @@ bool NzRenderer::EnsureStateUpdate()
|
||||||
{
|
{
|
||||||
TextureUnit& unit = s_textureUnits[i];
|
TextureUnit& unit = s_textureUnits[i];
|
||||||
|
|
||||||
if (!unit.textureUpdated)
|
if (unit.texture)
|
||||||
{
|
{
|
||||||
NzOpenGL::BindTextureUnit(i);
|
if (!unit.textureUpdated)
|
||||||
unit.texture->Bind();
|
{
|
||||||
|
NzOpenGL::BindTextureUnit(i);
|
||||||
|
unit.texture->Bind();
|
||||||
|
|
||||||
unit.textureUpdated = true;
|
unit.textureUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!unit.samplerUpdated)
|
if (!unit.samplerUpdated)
|
||||||
{
|
{
|
||||||
unit.sampler.Bind(i);
|
unit.sampler.Bind(i);
|
||||||
unit.samplerUpdated = true;
|
unit.samplerUpdated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1277,13 +1394,16 @@ bool NzRenderer::EnsureStateUpdate()
|
||||||
{
|
{
|
||||||
TextureUnit& unit = s_textureUnits[i];
|
TextureUnit& unit = s_textureUnits[i];
|
||||||
|
|
||||||
NzOpenGL::BindTextureUnit(i);
|
if (unit.texture)
|
||||||
|
{
|
||||||
|
NzOpenGL::BindTextureUnit(i);
|
||||||
|
|
||||||
unit.texture->Bind();
|
unit.texture->Bind();
|
||||||
unit.textureUpdated = true;
|
unit.textureUpdated = true;
|
||||||
|
|
||||||
unit.sampler.Apply(unit.texture);
|
unit.sampler.Apply(unit.texture);
|
||||||
unit.samplerUpdated = true;
|
unit.samplerUpdated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1324,10 +1444,18 @@ bool NzRenderer::EnsureStateUpdate()
|
||||||
if (s_useVertexArrayObjects)
|
if (s_useVertexArrayObjects)
|
||||||
{
|
{
|
||||||
// Note: Les VAOs ne sont pas partagés entre les contextes, nous avons donc un tableau de VAOs par contexte
|
// Note: Les VAOs ne sont pas partagés entre les contextes, nous avons donc un tableau de VAOs par contexte
|
||||||
auto& vaos = s_vaos[NzContext::GetCurrent()];
|
const NzContext* context = NzContext::GetCurrent();
|
||||||
|
|
||||||
|
auto pair = s_vaos.insert(std::make_pair(context, VAO_Map::mapped_type()));
|
||||||
|
if (pair.second)
|
||||||
|
context->AddResourceListener(&s_listener, ResourceType_Context);
|
||||||
|
|
||||||
|
auto& vaos = pair.first->second;
|
||||||
|
|
||||||
// Notre clé est composée de ce qui définit un VAO
|
// Notre clé est composée de ce qui définit un VAO
|
||||||
VAO_Key key(s_indexBuffer, s_vertexBuffer, s_vertexBuffer->GetVertexDeclaration(), (s_instancing) ? s_instancingDeclaration : nullptr);
|
const NzVertexDeclaration* vertexDeclaration = s_vertexBuffer->GetVertexDeclaration();
|
||||||
|
const NzVertexDeclaration* instancingDeclaration = (s_instancing) ? s_instancingDeclaration : nullptr;
|
||||||
|
VAO_Key key(s_indexBuffer, s_vertexBuffer, vertexDeclaration, instancingDeclaration);
|
||||||
|
|
||||||
// On recherche un VAO existant avec notre configuration
|
// On recherche un VAO existant avec notre configuration
|
||||||
auto it = vaos.find(key);
|
auto it = vaos.find(key);
|
||||||
|
|
@ -1339,6 +1467,14 @@ bool NzRenderer::EnsureStateUpdate()
|
||||||
|
|
||||||
// On l'ajoute à notre liste
|
// On l'ajoute à notre liste
|
||||||
vaos.insert(std::make_pair(key, static_cast<unsigned int>(s_currentVAO)));
|
vaos.insert(std::make_pair(key, static_cast<unsigned int>(s_currentVAO)));
|
||||||
|
if (s_indexBuffer)
|
||||||
|
s_indexBuffer->AddResourceListener(&s_listener, ResourceType_IndexBuffer);
|
||||||
|
|
||||||
|
s_vertexBuffer->AddResourceListener(&s_listener, ResourceType_VertexBuffer);
|
||||||
|
vertexDeclaration->AddResourceListener(&s_listener, ResourceType_VertexDeclaration);
|
||||||
|
|
||||||
|
if (instancingDeclaration)
|
||||||
|
instancingDeclaration->AddResourceListener(&s_listener, ResourceType_VertexDeclaration);
|
||||||
|
|
||||||
// Et on indique qu'on veut le programmer
|
// Et on indique qu'on veut le programmer
|
||||||
update = true;
|
update = true;
|
||||||
|
|
@ -1474,6 +1610,25 @@ bool NzRenderer::EnsureStateUpdate()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzRenderer::OnProgramReleased(const NzShaderProgram* program)
|
||||||
|
{
|
||||||
|
if (s_program == program)
|
||||||
|
{
|
||||||
|
s_program = nullptr;
|
||||||
|
s_updateFlags |= Update_Program;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzRenderer::OnTextureReleased(const NzTexture* texture)
|
||||||
|
{
|
||||||
|
for (TextureUnit& unit : s_textureUnits)
|
||||||
|
{
|
||||||
|
if (unit.texture == texture)
|
||||||
|
unit.texture = nullptr;
|
||||||
|
// Inutile de changer le flag pour une texture désactivée
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NzRenderer::UpdateMatrix(nzMatrixType type)
|
void NzRenderer::UpdateMatrix(nzMatrixType type)
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ m_compiled(program.m_compiled)
|
||||||
NzShaderProgram::~NzShaderProgram()
|
NzShaderProgram::~NzShaderProgram()
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
NzRenderer::OnProgramReleased(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzShaderProgram::Create(nzShaderLanguage language)
|
bool NzShaderProgram::Create(nzShaderLanguage language)
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,7 @@ NzTexture::NzTexture(const NzImage& image)
|
||||||
NzTexture::~NzTexture()
|
NzTexture::~NzTexture()
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
NzRenderer::OnTextureReleased(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount)
|
bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue