Avoid unnecessary sync

This commit is contained in:
Benau 2017-03-10 14:16:23 +08:00
parent 68e36268aa
commit 553c483bf4
5 changed files with 59 additions and 74 deletions

View File

@ -490,7 +490,7 @@ bool CentralVideoSettings::isARBPixelBufferObjectUsable() const
bool CentralVideoSettings::supportsThreadedTextureLoading() const bool CentralVideoSettings::supportsThreadedTextureLoading() const
{ {
return isARBPixelBufferObjectUsable() && supportsAsyncInstanceUpload(); return isARBPixelBufferObjectUsable() && isARBBufferStorageUsable();
} }
#endif // !SERVER_ONLY #endif // !SERVER_ONLY

View File

@ -24,11 +24,11 @@
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
#include <algorithm>
#include <thread> #include <thread>
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
STKTexManager::STKTexManager() : m_pbo(0), m_pbo_ptr(NULL), m_pbo_size(0), STKTexManager::STKTexManager() : m_pbo(0), m_thread_size(0), m_tlt_added(0)
m_thread_size(0), m_tlt_added(0)
{ {
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
if (CVS->supportsThreadedTextureLoading()) if (CVS->supportsThreadedTextureLoading())
@ -40,18 +40,20 @@ STKTexManager::STKTexManager() : m_pbo(0), m_pbo_ptr(NULL), m_pbo_size(0),
Log::info("STKTexManager", "%d thread(s) for texture loading," Log::info("STKTexManager", "%d thread(s) for texture loading,"
" each capacity %d MB", m_thread_size, " each capacity %d MB", m_thread_size,
each_capacity / 1024 / 1024); each_capacity / 1024 / 1024);
GLuint pbo; glGenBuffers(1, &m_pbo);
uint8_t* pbo_ptr; glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, max_pbo_size, NULL,
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT |
GL_MAP_COHERENT_BIT);
uint8_t* pbo_ptr = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER,
0, max_pbo_size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT |
GL_MAP_COHERENT_BIT);
size_t offset = 0;
for (unsigned i = 0; i < m_thread_size; i++) for (unsigned i = 0; i < m_thread_size; i++)
{ {
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, each_capacity, NULL,
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
pbo_ptr = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0,
each_capacity, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);
m_all_tex_loaders.push_back(new ThreadedTexLoader(each_capacity, m_all_tex_loaders.push_back(new ThreadedTexLoader(each_capacity,
pbo, pbo_ptr)); offset, pbo_ptr + offset));
offset += each_capacity;
} }
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} }
@ -285,6 +287,7 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void STKTexManager::reset() void STKTexManager::reset()
{ {
m_tlt_added = 0;
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(USE_GLES2))
if (!CVS->isAZDOEnabled()) return; if (!CVS->isAZDOEnabled()) return;
for (auto p : m_all_textures) for (auto p : m_all_textures)
@ -321,10 +324,36 @@ void STKTexManager::uploadBatch()
{ {
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(USE_GLES2))
if (!CVS->supportsThreadedTextureLoading()) return; if (!CVS->supportsThreadedTextureLoading()) return;
bool uploaded = false;
for (ThreadedTexLoader* ttl : m_all_tex_loaders) for (ThreadedTexLoader* ttl : m_all_tex_loaders)
{ {
if (ttl->finishedLoading()) if (ttl->finishedLoading())
{
if (!uploaded)
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
uploaded = true;
}
ttl->handleCompletedTextures(); ttl->handleCompletedTextures();
}
}
if (uploaded)
{
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
GLenum reason = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
if (reason != GL_ALREADY_SIGNALED)
{
do
{
reason = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT,
1000000);
}
while (reason == GL_TIMEOUT_EXPIRED);
}
glDeleteSync(sync);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
ttl->unlockCompletedTextures();
} }
#endif #endif
} // uploadBatch } // uploadBatch

View File

@ -21,12 +21,9 @@
#include "graphics/gl_headers.hpp" #include "graphics/gl_headers.hpp"
#include "utils/no_copy.hpp" #include "utils/no_copy.hpp"
#include "utils/singleton.hpp" #include "utils/singleton.hpp"
#include "utils/synchronised.hpp"
#include "irrString.h" #include "irrString.h"
#include <algorithm>
#include <cassert>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -47,15 +44,11 @@ private:
* This is used to specify details like: "while loading kart '...'" */ * This is used to specify details like: "while loading kart '...'" */
std::string m_texture_error_message; std::string m_texture_error_message;
Synchronised<std::vector<STKTexture*> > m_threaded_loading_textures;
std::vector<ThreadedTexLoader*> m_all_tex_loaders; std::vector<ThreadedTexLoader*> m_all_tex_loaders;
GLuint m_pbo; GLuint m_pbo;
uint8_t* m_pbo_ptr; unsigned m_thread_size, m_tlt_added;
unsigned m_pbo_size, m_thread_size, m_tlt_added;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
STKTexture* findTextureInFileSystem(const std::string& filename, STKTexture* findTextureInFileSystem(const std::string& filename,
@ -143,35 +136,6 @@ public:
} // getTexture } // getTexture
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void uploadBatch(); void uploadBatch();
// ------------------------------------------------------------------------
const unsigned getThreadedLoadingTextureNum() const
{
m_threaded_loading_textures.lock();
const unsigned num = m_threaded_loading_textures.getData().size();
m_threaded_loading_textures.unlock();
return num;
}
// ------------------------------------------------------------------------
STKTexture* getThreadedLoadingTexture(unsigned num) const
{
m_threaded_loading_textures.lock();
assert(num < m_threaded_loading_textures.getData().size());
STKTexture* t = m_threaded_loading_textures.getData()[num];
m_threaded_loading_textures.unlock();
return t;
}
// ------------------------------------------------------------------------
const bool isThreadedLoaderEmpty() const
{
m_threaded_loading_textures.lock();
const bool empty = m_threaded_loading_textures.getData().empty();
m_threaded_loading_textures.unlock();
return empty;
}
// ------------------------------------------------------------------------
uint8_t* getPBOPtr() { return m_pbo_ptr; }
// ------------------------------------------------------------------------
unsigned getNumLoadingThread() const { return m_thread_size; }
}; // STKTexManager }; // STKTexManager

View File

@ -86,8 +86,7 @@ void ThreadedTexLoader::handleCompletedTextures()
{ {
#if !(defined(SERVER_ONLY) || defined(USE_GLES2)) #if !(defined(SERVER_ONLY) || defined(USE_GLES2))
m_completed_textures.lock(); m_completed_textures.lock();
glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); m_locked = true;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
size_t offset = 0; size_t offset = 0;
for (STKTexture* stkt : m_completed_textures.getData()) for (STKTexture* stkt : m_completed_textures.getData())
{ {
@ -95,26 +94,11 @@ void ThreadedTexLoader::handleCompletedTextures()
glBindTexture(GL_TEXTURE_2D, stkt->getOpenGLTextureName()); glBindTexture(GL_TEXTURE_2D, stkt->getOpenGLTextureName());
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stkt->getSize().Width, glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stkt->getSize().Width,
stkt->getSize().Height, stkt->isSingleChannel() ? GL_RED : GL_BGRA, stkt->getSize().Height, stkt->isSingleChannel() ? GL_RED : GL_BGRA,
GL_UNSIGNED_BYTE, (const void*)offset); GL_UNSIGNED_BYTE, (const void*)(m_pbo_offset + offset));
if (stkt->hasMipMaps()) if (stkt->hasMipMaps())
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
offset += stkt->getTextureSize(); offset += stkt->getTextureSize();
} }
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
m_completed_textures.getData().clear(); m_completed_textures.getData().clear();
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
GLenum reason = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
if (reason != GL_ALREADY_SIGNALED)
{
do
{
reason =
glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000);
}
while (reason == GL_TIMEOUT_EXPIRED);
}
glDeleteSync(sync);
m_finished_loading.setAtomic(false);
m_completed_textures.unlock();
#endif #endif
} // handleCompletedTextures } // handleCompletedTextures

View File

@ -18,7 +18,6 @@
#ifndef HEADER_THREADED_TEX_LOADER_HPP #ifndef HEADER_THREADED_TEX_LOADER_HPP
#define HEADER_THREADED_TEX_LOADER_HPP #define HEADER_THREADED_TEX_LOADER_HPP
#include "graphics/gl_headers.hpp"
#include "utils/no_copy.hpp" #include "utils/no_copy.hpp"
#include "utils/synchronised.hpp" #include "utils/synchronised.hpp"
#include "utils/types.hpp" #include "utils/types.hpp"
@ -33,7 +32,7 @@ class ThreadedTexLoader : public NoCopy
private: private:
const unsigned m_tex_capacity; const unsigned m_tex_capacity;
GLuint m_pbo; const size_t m_pbo_offset;
uint8_t* m_pbo_ptr; uint8_t* m_pbo_ptr;
@ -45,7 +44,7 @@ private:
Synchronised<bool> m_finished_loading; Synchronised<bool> m_finished_loading;
bool m_destroy; bool m_destroy, m_locked;
Synchronised<std::vector<STKTexture*> > Synchronised<std::vector<STKTexture*> >
m_threaded_loading_textures, m_completed_textures; m_threaded_loading_textures, m_completed_textures;
@ -54,10 +53,11 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
static void* startRoutine(void *obj); static void* startRoutine(void *obj);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
ThreadedTexLoader(unsigned capacity, GLuint pbo, uint8_t* pbo_ptr) ThreadedTexLoader(unsigned capacity, size_t offset, uint8_t* pbo_ptr)
: m_tex_capacity(capacity), m_pbo(pbo), m_pbo_ptr(pbo_ptr), : m_tex_capacity(capacity), m_pbo_offset(offset),
m_tex_size_loaded(0), m_waiting_timeout(0), m_pbo_ptr(pbo_ptr), m_tex_size_loaded(0),
m_finished_loading(false), m_destroy(false) m_waiting_timeout(0), m_finished_loading(false),
m_destroy(false), m_locked(false)
{ {
pthread_cond_init(&m_cond_request, NULL); pthread_cond_init(&m_cond_request, NULL);
pthread_create(&m_thread, NULL, &startRoutine, this); pthread_create(&m_thread, NULL, &startRoutine, this);
@ -81,6 +81,14 @@ public:
bool finishedLoading() const { return m_finished_loading.getAtomic(); } bool finishedLoading() const { return m_finished_loading.getAtomic(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void handleCompletedTextures(); void handleCompletedTextures();
// ------------------------------------------------------------------------
void unlockCompletedTextures()
{
if (!m_locked) return;
m_locked = false;
m_finished_loading.setAtomic(false);
m_completed_textures.unlock();
}
}; // ThreadedTexLoader }; // ThreadedTexLoader