Asynchronous streaming and memory management improvements in progress.
--HG-- branch : async_streaming
This commit is contained in:
@@ -27,6 +27,7 @@ const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
KRContext::KRContext() {
|
KRContext::KRContext() {
|
||||||
|
m_streamingEnabled = false;
|
||||||
mach_timebase_info(&m_timebase_info);
|
mach_timebase_info(&m_timebase_info);
|
||||||
|
|
||||||
m_bDetectedExtensions = false;
|
m_bDetectedExtensions = false;
|
||||||
@@ -43,7 +44,7 @@ KRContext::KRContext() {
|
|||||||
m_pAnimationCurveManager = new KRAnimationCurveManager(*this);
|
m_pAnimationCurveManager = new KRAnimationCurveManager(*this);
|
||||||
m_pSoundManager = new KRAudioManager(*this);
|
m_pSoundManager = new KRAudioManager(*this);
|
||||||
m_pUnknownManager = new KRUnknownManager(*this);
|
m_pUnknownManager = new KRUnknownManager(*this);
|
||||||
|
m_streamingEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRContext::~KRContext() {
|
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
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ public:
|
|||||||
long getAbsoluteTimeMilliseconds();
|
long getAbsoluteTimeMilliseconds();
|
||||||
|
|
||||||
std::vector<KRResource *> getResources();
|
std::vector<KRResource *> getResources();
|
||||||
|
bool getStreamingEnabled();
|
||||||
|
void setStreamingEnabled(bool enable);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KRBundleManager *m_pBundleManager;
|
KRBundleManager *m_pBundleManager;
|
||||||
@@ -93,6 +95,8 @@ private:
|
|||||||
float m_absolute_time;
|
float m_absolute_time;
|
||||||
|
|
||||||
mach_timebase_info_data_t m_timebase_info;
|
mach_timebase_info_data_t m_timebase_info;
|
||||||
|
|
||||||
|
std::atomic<bool> m_streamingEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
float const PI = 3.141592653589793f;
|
float const PI = 3.141592653589793f;
|
||||||
float const D2R = PI * 2 / 360;
|
float const D2R = PI * 2 / 360;
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "KRMeshStreamer.h"
|
#include "KRMeshStreamer.h"
|
||||||
|
|
||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
#include "KRContext.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@@ -36,6 +37,9 @@ void KRMeshStreamer::run()
|
|||||||
|
|
||||||
while(!m_stop)
|
while(!m_stop)
|
||||||
{
|
{
|
||||||
|
if(m_context.getStreamingEnabled()) {
|
||||||
|
|
||||||
|
}
|
||||||
std::this_thread::sleep_for( sleep_duration );
|
std::this_thread::sleep_for( sleep_duration );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,13 +52,14 @@ long KRTexture::getReferencedMemSize() {
|
|||||||
|
|
||||||
void KRTexture::resize(int max_dim)
|
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) {
|
if(max_dim == 0) {
|
||||||
m_iNewHandle = 0;
|
m_iNewHandle = 0;
|
||||||
} else {
|
} else {
|
||||||
int target_dim = max_dim;
|
int target_dim = max_dim;
|
||||||
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
|
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
|
||||||
|
/*
|
||||||
int requiredMemoryTransfer = getThroughputRequiredForResize(target_dim);
|
int requiredMemoryTransfer = getThroughputRequiredForResize(target_dim);
|
||||||
int requiredMemoryDelta = getMemRequiredForSize(target_dim) - getMemSize() - getReferencedMemSize();
|
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
|
// Exceeding total memory allocated to textures; can't resize now
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if(m_current_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) {
|
if(m_current_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) {
|
||||||
if(!createGLTexture(target_dim)) {
|
if(!createGLTexture(target_dim)) {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -215,13 +215,20 @@ long KRTextureManager::getMemActive() {
|
|||||||
|
|
||||||
void KRTextureManager::startFrame(float deltaTime)
|
void KRTextureManager::startFrame(float deltaTime)
|
||||||
{
|
{
|
||||||
|
m_streamer.startStreamer();
|
||||||
_clearGLState();
|
_clearGLState();
|
||||||
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) {
|
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) {
|
||||||
KRTexture *activeTexture = *itr;
|
KRTexture *activeTexture = *itr;
|
||||||
activeTexture->_swapHandles();
|
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;
|
m_memoryTransferredThisFrame = 0;
|
||||||
balanceTextureMemory();
|
|
||||||
rotateBuffers();
|
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()
|
void KRTextureManager::balanceTextureMemory()
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
// Balance texture memory by reducing and increasing the maximum mip-map level of both active and inactive textures
|
// 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.
|
// 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
|
// Determine the additional amount of memory required in order to resize all active textures to the maximum size
|
||||||
long wantedTextureMem = 0;
|
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;
|
KRTexture *activeTexture = *itr;
|
||||||
|
|
||||||
wantedTextureMem = activeTexture->getMemRequiredForSize(getContext().KRENGINE_MAX_TEXTURE_DIM) - activeTexture->getMemSize();
|
wantedTextureMem = activeTexture->getMemRequiredForSize(getContext().KRENGINE_MAX_TEXTURE_DIM) - activeTexture->getMemSize();
|
||||||
@@ -259,7 +276,7 @@ void KRTextureManager::balanceTextureMemory()
|
|||||||
maxDimInactive = maxDimInactive >> 1;
|
maxDimInactive = maxDimInactive >> 1;
|
||||||
potentialMemorySaving = 0;
|
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;
|
KRTexture *poolTexture = *itr;
|
||||||
long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize();
|
long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize();
|
||||||
if(potentialMemoryDelta < 0) {
|
if(potentialMemoryDelta < 0) {
|
||||||
@@ -270,7 +287,7 @@ void KRTextureManager::balanceTextureMemory()
|
|||||||
|
|
||||||
// Strip off mipmap levels of inactive textures to free up memory
|
// Strip off mipmap levels of inactive textures to free up memory
|
||||||
long inactive_texture_mem_used_target = 0;
|
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;
|
KRTexture *poolTexture = *itr;
|
||||||
long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize();
|
long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize();
|
||||||
if(potentialMemoryDelta < 0) {
|
if(potentialMemoryDelta < 0) {
|
||||||
@@ -286,7 +303,7 @@ void KRTextureManager::balanceTextureMemory()
|
|||||||
long maxDimActive = getContext().KRENGINE_MAX_TEXTURE_DIM;
|
long maxDimActive = getContext().KRENGINE_MAX_TEXTURE_DIM;
|
||||||
while(memory_available <= 0 && maxDimActive >= getContext().KRENGINE_MIN_TEXTURE_DIM) {
|
while(memory_available <= 0 && maxDimActive >= getContext().KRENGINE_MIN_TEXTURE_DIM) {
|
||||||
memory_available = getContext().KRENGINE_MAX_TEXTURE_MEM - inactive_texture_mem_used_target;
|
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;
|
KRTexture *activeTexture = *itr;
|
||||||
memory_available -= activeTexture->getMemRequiredForSize(maxDimActive);
|
memory_available -= activeTexture->getMemRequiredForSize(maxDimActive);
|
||||||
}
|
}
|
||||||
@@ -297,7 +314,7 @@ void KRTextureManager::balanceTextureMemory()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resize active textures to balance the memory usage and mipmap levels
|
// 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;
|
KRTexture *activeTexture = *itr;
|
||||||
activeTexture->resize(maxDimActive);
|
activeTexture->resize(maxDimActive);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ public:
|
|||||||
void _clearGLState();
|
void _clearGLState();
|
||||||
void setMaxAnisotropy(float max_anisotropy);
|
void setMaxAnisotropy(float max_anisotropy);
|
||||||
|
|
||||||
|
void doStreaming();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_iActiveTexture;
|
int m_iActiveTexture;
|
||||||
|
|
||||||
@@ -89,15 +91,24 @@ private:
|
|||||||
GLuint m_wrapModeS[KRENGINE_MAX_TEXTURE_UNITS];
|
GLuint m_wrapModeS[KRENGINE_MAX_TEXTURE_UNITS];
|
||||||
GLuint m_wrapModeT[KRENGINE_MAX_TEXTURE_UNITS];
|
GLuint m_wrapModeT[KRENGINE_MAX_TEXTURE_UNITS];
|
||||||
float m_maxAnisotropy[KRENGINE_MAX_TEXTURE_UNITS];
|
float m_maxAnisotropy[KRENGINE_MAX_TEXTURE_UNITS];
|
||||||
|
|
||||||
|
|
||||||
std::set<KRTexture *> m_activeTextures;
|
std::set<KRTexture *> m_activeTextures;
|
||||||
std::set<KRTexture *> m_poolTextures;
|
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;
|
long m_textureMemUsed;
|
||||||
|
|
||||||
void rotateBuffers();
|
void rotateBuffers();
|
||||||
void balanceTextureMemory();
|
void balanceTextureMemory();
|
||||||
|
|
||||||
KRTextureStreamer m_streamer;
|
KRTextureStreamer m_streamer;
|
||||||
|
|
||||||
|
std::mutex m_streamerFenceMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -45,13 +45,17 @@ public:
|
|||||||
KRTextureStreamer(KRContext &context);
|
KRTextureStreamer(KRContext &context);
|
||||||
~KRTextureStreamer();
|
~KRTextureStreamer();
|
||||||
|
|
||||||
|
void startStreamer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KRContext &m_context;
|
KRContext &m_context;
|
||||||
|
|
||||||
std::thread m_thread;
|
std::thread m_thread;
|
||||||
std::atomic<bool> m_stop;
|
std::atomic<bool> m_stop;
|
||||||
|
std::atomic<bool> m_running;
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(KRTEXTURESTREAMER_H) */
|
#endif /* defined(KRTEXTURESTREAMER_H) */
|
||||||
|
|||||||
@@ -9,16 +9,25 @@
|
|||||||
#include "KREngine-common.h"
|
#include "KREngine-common.h"
|
||||||
|
|
||||||
#include "KRTextureStreamer.h"
|
#include "KRTextureStreamer.h"
|
||||||
|
#include "KRContext.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
EAGLContext *gTextureStreamerContext;
|
EAGLContext *gTextureStreamerContext = nil;
|
||||||
|
|
||||||
KRTextureStreamer::KRTextureStreamer(KRContext &context) : m_context(context)
|
KRTextureStreamer::KRTextureStreamer(KRContext &context) : m_context(context)
|
||||||
{
|
{
|
||||||
gTextureStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup];
|
m_running = false;
|
||||||
m_stop = 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()
|
KRTextureStreamer::~KRTextureStreamer()
|
||||||
@@ -36,6 +45,11 @@ void KRTextureStreamer::run()
|
|||||||
|
|
||||||
while(!m_stop)
|
while(!m_stop)
|
||||||
{
|
{
|
||||||
|
if(m_context.getStreamingEnabled()) {
|
||||||
|
m_context.getTextureManager()->doStreaming();
|
||||||
|
}
|
||||||
std::this_thread::sleep_for( sleep_duration );
|
std::this_thread::sleep_for( sleep_duration );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user