[iOS] Fixed OGL context initiailization race

This commit is contained in:
r.kuznetsov 2017-10-31 17:02:16 +03:00
parent 820487db2f
commit 568c2f21e1
6 changed files with 41 additions and 18 deletions

View file

@ -41,9 +41,9 @@ OGLContext * ThreadSafeFactory::CreateContext(TCreateCtxFn const & createFn, TIs
return ctx;
}
void ThreadSafeFactory::waitForInitialization()
void ThreadSafeFactory::waitForInitialization(dp::OGLContext * context)
{
m_factory->waitForInitialization();
m_factory->waitForInitialization(context);
}
} // namespace dp

View file

@ -18,7 +18,7 @@ public:
virtual OGLContext * getResourcesUploadContext() = 0;
virtual bool isDrawContextCreated() const { return false; }
virtual bool isUploadContextCreated() const { return false; }
virtual void waitForInitialization() {}
virtual void waitForInitialization(dp::OGLContext * context) {}
};
class ThreadSafeFactory : public OGLContextFactory
@ -36,7 +36,7 @@ public:
return static_cast<T *>(m_factory);
}
void waitForInitialization() override;
void waitForInitialization(dp::OGLContext * context) override;
protected:
typedef function<OGLContext * ()> TCreateCtxFn;

View file

@ -520,8 +520,9 @@ void BackendRenderer::ReleaseResources()
void BackendRenderer::OnContextCreate()
{
LOG(LINFO, ("On context create."));
m_contextFactory->waitForInitialization();
m_contextFactory->getResourcesUploadContext()->makeCurrent();
dp::OGLContext * context = m_contextFactory->getResourcesUploadContext();
m_contextFactory->waitForInitialization(context);
context->makeCurrent();
GLFunctions::Init(m_apiVersion);

View file

@ -1763,9 +1763,9 @@ void FrontendRenderer::OnContextCreate()
{
LOG(LINFO, ("On context create."));
m_contextFactory->waitForInitialization();
dp::OGLContext * context = m_contextFactory->getDrawContext();
m_contextFactory->waitForInitialization(context);
context->makeCurrent();
GLFunctions::Init(m_apiVersion);

View file

@ -20,7 +20,7 @@ public:
bool isDrawContextCreated() const override;
bool isUploadContextCreated() const override;
void waitForInitialization() override;
void waitForInitialization(dp::OGLContext * context) override;
void setPresentAvailable(bool available);
@ -31,6 +31,8 @@ private:
iosOGLContext * m_uploadContext;
bool m_isInitialized;
size_t m_initializationCounter;
bool m_presentAvailable;
condition_variable m_initializationCondition;
mutex m_initializationMutex;
};

View file

@ -1,11 +1,15 @@
#import "iosOGLContextFactory.h"
size_t constexpr kGLThreadsCount = 2;
iosOGLContextFactory::iosOGLContextFactory(CAEAGLLayer * layer, dp::ApiVersion apiVersion)
: m_layer(layer)
, m_apiVersion(apiVersion)
, m_drawContext(nullptr)
, m_uploadContext(nullptr)
, m_isInitialized(false)
, m_initializationCounter(0)
, m_presentAvailable(false)
{}
iosOGLContextFactory::~iosOGLContextFactory()
@ -40,20 +44,36 @@ bool iosOGLContextFactory::isUploadContextCreated() const
void iosOGLContextFactory::setPresentAvailable(bool available)
{
lock_guard<mutex> lock(m_initializationMutex);
m_presentAvailable = available;
if (m_isInitialized)
{
lock_guard<mutex> lock(m_initializationMutex);
if (!m_isInitialized && available)
m_drawContext->setPresentAvailable(m_presentAvailable);
}
else if (m_initializationCounter >= kGLThreadsCount && m_presentAvailable)
{
m_isInitialized = true;
m_initializationCondition.notify_all();
}
}
void iosOGLContextFactory::waitForInitialization(dp::OGLContext * context)
{
unique_lock<mutex> lock(m_initializationMutex);
if (!m_isInitialized)
{
m_initializationCounter++;
if (m_initializationCounter >= kGLThreadsCount && m_presentAvailable)
{
m_isInitialized = true;
m_initializationCondition.notify_all();
}
else
{
m_initializationCondition.wait(lock, [this] { return m_isInitialized; });
}
}
if (m_drawContext != nullptr)
m_drawContext->setPresentAvailable(available);
}
void iosOGLContextFactory::waitForInitialization()
{
unique_lock<mutex> lock(m_initializationMutex);
m_initializationCondition.wait(lock, [this] { return m_isInitialized; });
if (m_drawContext == context)
m_drawContext->setPresentAvailable(m_presentAvailable);
}