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
{
return isARBPixelBufferObjectUsable() && supportsAsyncInstanceUpload();
return isARBPixelBufferObjectUsable() && isARBBufferStorageUsable();
}
#endif // !SERVER_ONLY

View File

@ -24,11 +24,11 @@
#include "utils/string_utils.hpp"
#include "utils/log.hpp"
#include <algorithm>
#include <thread>
// ----------------------------------------------------------------------------
STKTexManager::STKTexManager() : m_pbo(0), m_pbo_ptr(NULL), m_pbo_size(0),
m_thread_size(0), m_tlt_added(0)
STKTexManager::STKTexManager() : m_pbo(0), m_thread_size(0), m_tlt_added(0)
{
#ifndef SERVER_ONLY
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,"
" each capacity %d MB", m_thread_size,
each_capacity / 1024 / 1024);
GLuint pbo;
uint8_t* pbo_ptr;
glGenBuffers(1, &m_pbo);
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++)
{
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,
pbo, pbo_ptr));
offset, pbo_ptr + offset));
offset += each_capacity;
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
@ -285,6 +287,7 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
// ----------------------------------------------------------------------------
void STKTexManager::reset()
{
m_tlt_added = 0;
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
if (!CVS->isAZDOEnabled()) return;
for (auto p : m_all_textures)
@ -321,10 +324,36 @@ void STKTexManager::uploadBatch()
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
if (!CVS->supportsThreadedTextureLoading()) return;
bool uploaded = false;
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
{
if (ttl->finishedLoading())
{
if (!uploaded)
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
uploaded = true;
}
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
} // uploadBatch

View File

@ -21,12 +21,9 @@
#include "graphics/gl_headers.hpp"
#include "utils/no_copy.hpp"
#include "utils/singleton.hpp"
#include "utils/synchronised.hpp"
#include "irrString.h"
#include <algorithm>
#include <cassert>
#include <string>
#include <unordered_map>
#include <vector>
@ -47,15 +44,11 @@ private:
* This is used to specify details like: "while loading kart '...'" */
std::string m_texture_error_message;
Synchronised<std::vector<STKTexture*> > m_threaded_loading_textures;
std::vector<ThreadedTexLoader*> m_all_tex_loaders;
GLuint m_pbo;
uint8_t* m_pbo_ptr;
unsigned m_pbo_size, m_thread_size, m_tlt_added;
unsigned m_thread_size, m_tlt_added;
// ------------------------------------------------------------------------
STKTexture* findTextureInFileSystem(const std::string& filename,
@ -143,35 +136,6 @@ public:
} // getTexture
// ------------------------------------------------------------------------
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

View File

@ -86,8 +86,7 @@ void ThreadedTexLoader::handleCompletedTextures()
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
m_completed_textures.lock();
glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
m_locked = true;
size_t offset = 0;
for (STKTexture* stkt : m_completed_textures.getData())
{
@ -95,26 +94,11 @@ void ThreadedTexLoader::handleCompletedTextures()
glBindTexture(GL_TEXTURE_2D, stkt->getOpenGLTextureName());
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stkt->getSize().Width,
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())
glGenerateMipmap(GL_TEXTURE_2D);
offset += stkt->getTextureSize();
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
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
} // handleCompletedTextures

View File

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