Asynchronous streaming and memory management improvements in progress.

--HG--
branch : async_streaming
This commit is contained in:
2013-11-13 23:52:17 -08:00
parent 05626214d4
commit cf732a6721
9 changed files with 82 additions and 16 deletions

View File

@@ -27,6 +27,7 @@ const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = {
};
KRContext::KRContext() {
m_streamingEnabled = false;
mach_timebase_info(&m_timebase_info);
m_bDetectedExtensions = false;
@@ -43,7 +44,7 @@ KRContext::KRContext() {
m_pAnimationCurveManager = new KRAnimationCurveManager(*this);
m_pSoundManager = new KRAudioManager(*this);
m_pUnknownManager = new KRUnknownManager(*this);
m_streamingEnabled = true;
}
KRContext::~KRContext() {
@@ -271,3 +272,12 @@ long KRContext::getAbsoluteTimeMilliseconds()
return (long)(mach_absolute_time() / 1000 * m_timebase_info.numer / m_timebase_info.denom); // Division done first to avoid potential overflow
}
bool KRContext::getStreamingEnabled()
{
return m_streamingEnabled;
}
void KRContext::setStreamingEnabled(bool enable)
{
m_streamingEnabled = enable;
}

View File

@@ -73,6 +73,8 @@ public:
long getAbsoluteTimeMilliseconds();
std::vector<KRResource *> getResources();
bool getStreamingEnabled();
void setStreamingEnabled(bool enable);
private:
KRBundleManager *m_pBundleManager;
@@ -93,6 +95,8 @@ private:
float m_absolute_time;
mach_timebase_info_data_t m_timebase_info;
std::atomic<bool> m_streamingEnabled;
};
#endif

View File

@@ -14,6 +14,7 @@
float const PI = 3.141592653589793f;
float const D2R = PI * 2 / 360;
#include <stdint.h>
#include <vector>
#include <string>

View File

@@ -9,6 +9,7 @@
#include "KRMeshStreamer.h"
#include "KREngine-common.h"
#include "KRContext.h"
#include <chrono>
@@ -36,6 +37,9 @@ void KRMeshStreamer::run()
while(!m_stop)
{
if(m_context.getStreamingEnabled()) {
}
std::this_thread::sleep_for( sleep_duration );
}
}

View File

@@ -52,13 +52,14 @@ long KRTexture::getReferencedMemSize() {
void KRTexture::resize(int max_dim)
{
assert(m_iHandle == m_iNewHandle); // Only allow one resize() per frame
if(m_iHandle != m_iNewHandle) return; // Only allow one resize() per frame
if(max_dim == 0) {
m_iNewHandle = 0;
} else {
int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
/*
int requiredMemoryTransfer = getThroughputRequiredForResize(target_dim);
int requiredMemoryDelta = getMemRequiredForSize(target_dim) - getMemSize() - getReferencedMemSize();
@@ -74,13 +75,13 @@ void KRTexture::resize(int max_dim)
// Exceeding total memory allocated to textures; can't resize now
return;
}
*/
if(m_current_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) {
if(!createGLTexture(target_dim)) {
assert(false);
}
}
}
// }
}
}

View File

@@ -215,13 +215,20 @@ long KRTextureManager::getMemActive() {
void KRTextureManager::startFrame(float deltaTime)
{
m_streamer.startStreamer();
_clearGLState();
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) {
KRTexture *activeTexture = *itr;
activeTexture->_swapHandles();
}
// TODO - Implement proper double-buffering to reduce copy operations
m_streamerFenceMutex.lock();
m_activeTextures_streamer_copy = m_activeTextures;
m_poolTextures_streamer_copy = m_poolTextures;
m_streamerFenceMutex.unlock();
m_memoryTransferredThisFrame = 0;
balanceTextureMemory();
rotateBuffers();
}
@@ -234,15 +241,25 @@ void KRTextureManager::endFrame(float deltaTime)
}
}
void KRTextureManager::doStreaming()
{
// TODO - Implement proper double-buffering to reduce copy operations
m_streamerFenceMutex.lock();
m_activeTextures_streamer = m_activeTextures_streamer_copy;
m_poolTextures_streamer = m_poolTextures_streamer_copy;
m_streamerFenceMutex.unlock();
balanceTextureMemory();
}
void KRTextureManager::balanceTextureMemory()
{
return;
// Balance texture memory by reducing and increasing the maximum mip-map level of both active and inactive textures
// Favour performance over maximum texture resolution when memory is insufficient for textures at full resolution.
// Determine the additional amount of memory required in order to resize all active textures to the maximum size
long wantedTextureMem = 0;
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) {
for(std::set<KRTexture *>::iterator itr=m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end(); itr++) {
KRTexture *activeTexture = *itr;
wantedTextureMem = activeTexture->getMemRequiredForSize(getContext().KRENGINE_MAX_TEXTURE_DIM) - activeTexture->getMemSize();
@@ -259,7 +276,7 @@ void KRTextureManager::balanceTextureMemory()
maxDimInactive = maxDimInactive >> 1;
potentialMemorySaving = 0;
for(std::set<KRTexture *>::iterator itr=m_poolTextures.begin(); itr != m_poolTextures.end(); itr++) {
for(std::set<KRTexture *>::iterator itr=m_poolTextures_streamer.begin(); itr != m_poolTextures_streamer.end(); itr++) {
KRTexture *poolTexture = *itr;
long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize();
if(potentialMemoryDelta < 0) {
@@ -270,7 +287,7 @@ void KRTextureManager::balanceTextureMemory()
// Strip off mipmap levels of inactive textures to free up memory
long inactive_texture_mem_used_target = 0;
for(std::set<KRTexture *>::iterator itr=m_poolTextures.begin(); itr != m_poolTextures.end(); itr++) {
for(std::set<KRTexture *>::iterator itr=m_poolTextures_streamer.begin(); itr != m_poolTextures_streamer.end(); itr++) {
KRTexture *poolTexture = *itr;
long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize();
if(potentialMemoryDelta < 0) {
@@ -286,7 +303,7 @@ void KRTextureManager::balanceTextureMemory()
long maxDimActive = getContext().KRENGINE_MAX_TEXTURE_DIM;
while(memory_available <= 0 && maxDimActive >= getContext().KRENGINE_MIN_TEXTURE_DIM) {
memory_available = getContext().KRENGINE_MAX_TEXTURE_MEM - inactive_texture_mem_used_target;
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end() && memory_available > 0; itr++) {
for(std::set<KRTexture *>::iterator itr=m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end() && memory_available > 0; itr++) {
KRTexture *activeTexture = *itr;
memory_available -= activeTexture->getMemRequiredForSize(maxDimActive);
}
@@ -297,7 +314,7 @@ void KRTextureManager::balanceTextureMemory()
}
// Resize active textures to balance the memory usage and mipmap levels
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end() && memory_available > 0; itr++) {
for(std::set<KRTexture *>::iterator itr=m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end() && memory_available > 0; itr++) {
KRTexture *activeTexture = *itr;
activeTexture->resize(maxDimActive);
}

View File

@@ -78,6 +78,8 @@ public:
void _clearGLState();
void setMaxAnisotropy(float max_anisotropy);
void doStreaming();
private:
int m_iActiveTexture;
@@ -89,15 +91,24 @@ private:
GLuint m_wrapModeS[KRENGINE_MAX_TEXTURE_UNITS];
GLuint m_wrapModeT[KRENGINE_MAX_TEXTURE_UNITS];
float m_maxAnisotropy[KRENGINE_MAX_TEXTURE_UNITS];
std::set<KRTexture *> m_activeTextures;
std::set<KRTexture *> m_poolTextures;
std::set<KRTexture *> m_activeTextures_streamer;
std::set<KRTexture *> m_poolTextures_streamer;
std::set<KRTexture *> m_activeTextures_streamer_copy;
std::set<KRTexture *> m_poolTextures_streamer_copy;
long m_textureMemUsed;
void rotateBuffers();
void balanceTextureMemory();
KRTextureStreamer m_streamer;
std::mutex m_streamerFenceMutex;
};
#endif

View File

@@ -45,13 +45,17 @@ public:
KRTextureStreamer(KRContext &context);
~KRTextureStreamer();
void startStreamer();
private:
KRContext &m_context;
std::thread m_thread;
std::atomic<bool> m_stop;
std::atomic<bool> m_running;
void run();
};
#endif /* defined(KRTEXTURESTREAMER_H) */

View File

@@ -9,16 +9,25 @@
#include "KREngine-common.h"
#include "KRTextureStreamer.h"
#include "KRContext.h"
#include <chrono>
EAGLContext *gTextureStreamerContext;
EAGLContext *gTextureStreamerContext = nil;
KRTextureStreamer::KRTextureStreamer(KRContext &context) : m_context(context)
{
gTextureStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup];
m_running = false;
m_stop = false;
m_thread = std::thread(&KRTextureStreamer::run, this);
}
void KRTextureStreamer::startStreamer()
{
if(!m_running) {
m_running = true;
gTextureStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup];
m_thread = std::thread(&KRTextureStreamer::run, this);
}
}
KRTextureStreamer::~KRTextureStreamer()
@@ -36,6 +45,11 @@ void KRTextureStreamer::run()
while(!m_stop)
{
if(m_context.getStreamingEnabled()) {
m_context.getTextureManager()->doStreaming();
}
std::this_thread::sleep_for( sleep_duration );
}
m_running = false;
}