Asynchronous streaming and memory management improvements in progress.
--HG-- branch : async_streaming
This commit is contained in:
@@ -297,3 +297,31 @@ void KRAnimation::deleteCurves()
|
||||
}
|
||||
}
|
||||
|
||||
void KRAnimation::_lockData()
|
||||
{
|
||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
|
||||
KRAnimationLayer *layer = (*layer_itr).second;
|
||||
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
|
||||
KRAnimationAttribute *attribute = *attribute_itr;
|
||||
KRAnimationCurve *curve = attribute->getCurve();
|
||||
if(curve) {
|
||||
curve->_lockData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRAnimation::_unlockData()
|
||||
{
|
||||
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
|
||||
KRAnimationLayer *layer = (*layer_itr).second;
|
||||
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
|
||||
KRAnimationAttribute *attribute = *attribute_itr;
|
||||
KRAnimationCurve *curve = attribute->getCurve();
|
||||
if(curve) {
|
||||
curve->_unlockData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,9 @@ public:
|
||||
KRAnimation *split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes = true, bool clone_curves = true);
|
||||
void deleteCurves();
|
||||
|
||||
void _lockData();
|
||||
void _unlockData();
|
||||
|
||||
private:
|
||||
unordered_map<std::string, KRAnimationLayer *> m_layers;
|
||||
bool m_auto_play;
|
||||
|
||||
@@ -228,3 +228,13 @@ KRAnimationCurve *KRAnimationCurve::split(const std::string &name, int start_fra
|
||||
getContext().getAnimationCurveManager()->addAnimationCurve(new_curve);
|
||||
return new_curve;
|
||||
}
|
||||
|
||||
void KRAnimationCurve::_lockData()
|
||||
{
|
||||
m_pData->lock();
|
||||
}
|
||||
|
||||
void KRAnimationCurve::_unlockData()
|
||||
{
|
||||
m_pData->unlock();
|
||||
}
|
||||
|
||||
@@ -67,6 +67,9 @@ public:
|
||||
KRAnimationCurve *split(const std::string &name, float start_time, float duration);
|
||||
KRAnimationCurve *split(const std::string &name, int start_frame, int frame_count);
|
||||
|
||||
void _lockData();
|
||||
void _unlockData();
|
||||
|
||||
private:
|
||||
KRDataBlock *m_pData;
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@ KRAnimationManager::KRAnimationManager(KRContext &context) : KRContextObject(con
|
||||
}
|
||||
|
||||
KRAnimationManager::~KRAnimationManager() {
|
||||
for(std::set<KRAnimation *>::iterator itr = m_activeAnimations.begin(); itr != m_activeAnimations.end(); itr++) {
|
||||
KRAnimation *animation = *itr;
|
||||
animation->_unlockData();
|
||||
}
|
||||
|
||||
for(unordered_map<std::string, KRAnimation *>::iterator itr = m_animations.begin(); itr != m_animations.end(); ++itr){
|
||||
delete (*itr).second;
|
||||
}
|
||||
@@ -52,11 +57,13 @@ void KRAnimationManager::startFrame(float deltaTime)
|
||||
// Add playing animations to the active animations list
|
||||
if(active_animations_itr == m_activeAnimations.end()) {
|
||||
m_activeAnimations.insert(animation);
|
||||
animation->_lockData();
|
||||
}
|
||||
} else {
|
||||
// Remove stopped animations from the active animations list
|
||||
if(active_animations_itr != m_activeAnimations.end()) {
|
||||
m_activeAnimations.erase(active_animations_itr);
|
||||
animation->_unlockData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ int KRContext::KRENGINE_MAX_SHADER_HANDLES;
|
||||
int KRContext::KRENGINE_MAX_TEXTURE_HANDLES;
|
||||
int KRContext::KRENGINE_MAX_TEXTURE_MEM;
|
||||
int KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX;
|
||||
int KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN;
|
||||
int KRContext::KRENGINE_MAX_TEXTURE_DIM;
|
||||
int KRContext::KRENGINE_MIN_TEXTURE_DIM;
|
||||
int KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT;
|
||||
@@ -281,3 +280,26 @@ void KRContext::setStreamingEnabled(bool enable)
|
||||
{
|
||||
m_streamingEnabled = enable;
|
||||
}
|
||||
|
||||
void KRContext::getMemoryStats(long &free_memory)
|
||||
{
|
||||
free_memory = 0;
|
||||
#if TARGET_OS_IPHONE
|
||||
mach_port_t host_port = mach_host_self();
|
||||
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
|
||||
vm_size_t pagesize = 0;
|
||||
vm_statistics_data_t vm_stat;
|
||||
int total_ram = 256 * 1024 * 1024;
|
||||
if(host_page_size(host_port, &pagesize) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: Could not get VM page size.\n");
|
||||
} else if(host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: Could not get VM stats.\n");
|
||||
} else {
|
||||
total_ram = (vm_stat.wire_count + vm_stat.active_count + vm_stat.inactive_count + vm_stat.free_count) * pagesize;
|
||||
|
||||
free_memory = vm_stat.free_count * pagesize;
|
||||
}
|
||||
#else
|
||||
#error Unsupported Platform
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ public:
|
||||
static int KRENGINE_MAX_TEXTURE_HANDLES;
|
||||
static int KRENGINE_MAX_TEXTURE_MEM;
|
||||
static int KRENGINE_TARGET_TEXTURE_MEM_MAX;
|
||||
static int KRENGINE_TARGET_TEXTURE_MEM_MIN;
|
||||
static int KRENGINE_MAX_TEXTURE_DIM;
|
||||
static int KRENGINE_MIN_TEXTURE_DIM;
|
||||
static int KRENGINE_MAX_TEXTURE_THROUGHPUT;
|
||||
@@ -76,6 +75,8 @@ public:
|
||||
bool getStreamingEnabled();
|
||||
void setStreamingEnabled(bool enable);
|
||||
|
||||
void getMemoryStats(long &free_memory);
|
||||
|
||||
private:
|
||||
KRBundleManager *m_pBundleManager;
|
||||
KRSceneManager *m_pSceneManager;
|
||||
|
||||
@@ -146,6 +146,7 @@ KRDataBlock *KRDataBlock::getSubBlock(int start, int length)
|
||||
new_block->m_data = (unsigned char *)m_data + start + m_data_offset;
|
||||
}
|
||||
new_block->m_bReadOnly = true;
|
||||
|
||||
return new_block;
|
||||
}
|
||||
|
||||
@@ -289,55 +290,58 @@ std::string KRDataBlock::getString()
|
||||
// Lock the memory, forcing it to be loaded into a contiguous block of address space
|
||||
void KRDataBlock::lock()
|
||||
{
|
||||
|
||||
m_lockCount++;
|
||||
|
||||
if(m_lockCount == 1) {
|
||||
if(m_lockCount == 0) {
|
||||
|
||||
// Memory mapped file; ensure data is mapped to ram
|
||||
if(m_fdPackFile) {
|
||||
//fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
|
||||
|
||||
// Round m_data_offset down to the next memory page, as required by mmap
|
||||
size_t alignment_offset = m_data_offset & (KRAKEN_MEM_PAGE_SIZE - 1);
|
||||
if ((m_mmapData = mmap(0, m_data_size + alignment_offset, m_bReadOnly ? PROT_READ : PROT_WRITE, MAP_SHARED, m_fdPackFile, m_data_offset - alignment_offset)) == (caddr_t) -1) {
|
||||
int iError = errno;
|
||||
switch(iError) {
|
||||
case EACCES:
|
||||
fprintf(stderr, "mmap failed with EACCES\n");
|
||||
break;
|
||||
case EBADF:
|
||||
fprintf(stderr, "mmap failed with EBADF\n");
|
||||
break;
|
||||
case EMFILE:
|
||||
fprintf(stderr, "mmap failed with EMFILE\n");
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "mmap failed with EINVAL\n");
|
||||
break;
|
||||
case ENOMEM:
|
||||
fprintf(stderr, "mmap failed with ENOMEM\n");
|
||||
break;
|
||||
case ENXIO:
|
||||
fprintf(stderr, "mmap failed with ENXIO\n");
|
||||
break;
|
||||
case EOVERFLOW:
|
||||
fprintf(stderr, "mmap failed with EOVERFLOW\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "mmap failed with errno: %i\n", iError);
|
||||
break;
|
||||
if(m_data_size < KRENGINE_MIN_MMAP) {
|
||||
m_data = malloc(m_data_size);
|
||||
assert(m_data != NULL);
|
||||
copy(m_data);
|
||||
} else {
|
||||
//fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
|
||||
|
||||
// Round m_data_offset down to the next memory page, as required by mmap
|
||||
size_t alignment_offset = m_data_offset & (KRAKEN_MEM_PAGE_SIZE - 1);
|
||||
if ((m_mmapData = mmap(0, m_data_size + alignment_offset, m_bReadOnly ? PROT_READ : PROT_WRITE, MAP_SHARED, m_fdPackFile, m_data_offset - alignment_offset)) == (caddr_t) -1) {
|
||||
int iError = errno;
|
||||
switch(iError) {
|
||||
case EACCES:
|
||||
fprintf(stderr, "mmap failed with EACCES\n");
|
||||
break;
|
||||
case EBADF:
|
||||
fprintf(stderr, "mmap failed with EBADF\n");
|
||||
break;
|
||||
case EMFILE:
|
||||
fprintf(stderr, "mmap failed with EMFILE\n");
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "mmap failed with EINVAL\n");
|
||||
break;
|
||||
case ENOMEM:
|
||||
fprintf(stderr, "mmap failed with ENOMEM\n");
|
||||
break;
|
||||
case ENXIO:
|
||||
fprintf(stderr, "mmap failed with ENXIO\n");
|
||||
break;
|
||||
case EOVERFLOW:
|
||||
fprintf(stderr, "mmap failed with EOVERFLOW\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "mmap failed with errno: %i\n", iError);
|
||||
break;
|
||||
}
|
||||
assert(false); // mmap() failed.
|
||||
}
|
||||
assert(false); // mmap() failed.
|
||||
m_mapCount++;
|
||||
m_mapSize += m_data_size;
|
||||
m_mapOverhead += alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
|
||||
fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
|
||||
m_data = (unsigned char *)m_mmapData + alignment_offset;
|
||||
}
|
||||
m_mapCount++;
|
||||
m_mapSize += m_data_size;
|
||||
m_mapOverhead += alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
|
||||
fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
|
||||
m_data = (unsigned char *)m_mmapData + alignment_offset;
|
||||
}
|
||||
|
||||
}
|
||||
m_lockCount++;
|
||||
}
|
||||
|
||||
// Unlock the memory, releasing the address space for use by other allocations
|
||||
@@ -346,24 +350,29 @@ void KRDataBlock::unlock()
|
||||
// We expect that the data block was previously locked
|
||||
assertLocked();
|
||||
|
||||
m_lockCount--;
|
||||
if(m_lockCount == 0) {
|
||||
|
||||
if(m_lockCount == 1) {
|
||||
|
||||
// Memory mapped file; ensure data is unmapped from ram
|
||||
if(m_fdPackFile) {
|
||||
//fprintf(stderr, "KRDataBlock::unlock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
|
||||
|
||||
munmap(m_mmapData, m_data_size);
|
||||
m_data = NULL;
|
||||
m_mmapData = NULL;
|
||||
m_mapCount--;
|
||||
m_mapSize -= m_data_size;
|
||||
size_t alignment_offset = m_data_offset & (KRAKEN_MEM_PAGE_SIZE - 1);
|
||||
m_mapOverhead -= alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
|
||||
fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
|
||||
if(m_data_size < KRENGINE_MIN_MMAP) {
|
||||
free(m_data);
|
||||
m_data = NULL;
|
||||
} else {
|
||||
//fprintf(stderr, "KRDataBlock::unlock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
|
||||
|
||||
munmap(m_mmapData, m_data_size);
|
||||
m_data = NULL;
|
||||
m_mmapData = NULL;
|
||||
m_mapCount--;
|
||||
m_mapSize -= m_data_size;
|
||||
size_t alignment_offset = m_data_offset & (KRAKEN_MEM_PAGE_SIZE - 1);
|
||||
m_mapOverhead -= alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
|
||||
fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
m_lockCount--;
|
||||
}
|
||||
|
||||
// Assert if not locked
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#define KRENGINE_MIN_MMAP 327680000
|
||||
|
||||
class KRDataBlock {
|
||||
public:
|
||||
KRDataBlock();
|
||||
|
||||
@@ -101,7 +101,6 @@ void kraken::set_debug_text(const std::string &print_text)
|
||||
KRContext::KRENGINE_MAX_VBO_MEM = total_ram * 2 / 4;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_MEM = total_ram * 1 / 8;
|
||||
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX = KRContext::KRENGINE_MAX_TEXTURE_MEM * 3 / 4;
|
||||
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = KRContext::KRENGINE_MAX_TEXTURE_MEM / 2;
|
||||
|
||||
|
||||
|
||||
@@ -115,7 +114,6 @@ void kraken::set_debug_text(const std::string &print_text)
|
||||
KRContext::KRENGINE_MAX_TEXTURE_HANDLES = 10000;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_MEM = 64000000 * 2;
|
||||
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX = 48000000 * 2;
|
||||
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = 32000000 * 2;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 32000000;
|
||||
@@ -126,7 +124,6 @@ void kraken::set_debug_text(const std::string &print_text)
|
||||
KRContext::KRENGINE_MAX_TEXTURE_HANDLES = 10000;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_MEM = 64000000;
|
||||
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX = 48000000;
|
||||
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = 32000000;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 32000000;
|
||||
@@ -139,7 +136,6 @@ void kraken::set_debug_text(const std::string &print_text)
|
||||
KRContext::KRENGINE_MAX_TEXTURE_HANDLES = 10000;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_MEM = 512000000;
|
||||
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX = 384000000;
|
||||
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = 256000000;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 128000000;
|
||||
|
||||
@@ -32,6 +32,8 @@ KRMeshStreamer::~KRMeshStreamer()
|
||||
|
||||
void KRMeshStreamer::run()
|
||||
{
|
||||
pthread_setname_np("Kraken - Mesh Streamer");
|
||||
|
||||
std::chrono::microseconds sleep_duration( 100 );
|
||||
[EAGLContext setCurrentContext: gMeshStreamerContext];
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ KRTexture::~KRTexture()
|
||||
}
|
||||
|
||||
void KRTexture::releaseHandles() {
|
||||
long mem_size = getMemSize();
|
||||
|
||||
if(m_iNewHandle != 0) {
|
||||
GLDEBUG(glDeleteTextures(1, &m_iNewHandle));
|
||||
m_iNewHandle = 0;
|
||||
@@ -35,10 +37,10 @@ void KRTexture::releaseHandles() {
|
||||
}
|
||||
if(m_iHandle != 0) {
|
||||
GLDEBUG(glDeleteTextures(1, &m_iHandle));
|
||||
getContext().getTextureManager()->memoryChanged(-getMemSize());
|
||||
m_iHandle = 0;
|
||||
m_textureMemUsed = 0;
|
||||
}
|
||||
getContext().getTextureManager()->memoryChanged(-mem_size);
|
||||
}
|
||||
|
||||
long KRTexture::getMemSize() {
|
||||
@@ -52,45 +54,36 @@ long KRTexture::getReferencedMemSize() {
|
||||
|
||||
void KRTexture::resize(int max_dim)
|
||||
{
|
||||
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();
|
||||
if(m_handle_lock.test_and_set())
|
||||
{
|
||||
if(m_iHandle == m_iNewHandle) {
|
||||
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;
|
||||
|
||||
if(requiredMemoryDelta) {
|
||||
// Only resize / regenerate the texture if it actually changes the size of the texture (Assumption: textures of different sizes will always consume different amounts of memory)
|
||||
|
||||
if(getContext().getTextureManager()->getMemoryTransferedThisFrame() + requiredMemoryTransfer > getContext().KRENGINE_MAX_TEXTURE_THROUGHPUT) {
|
||||
// Exceeding per-frame transfer throughput; can't resize now
|
||||
return;
|
||||
}
|
||||
|
||||
if(getContext().getTextureManager()->getMemUsed() + requiredMemoryDelta > getContext().KRENGINE_MAX_TEXTURE_MEM) {
|
||||
// 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);
|
||||
if(m_current_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) {
|
||||
assert(m_newTextureMemUsed == 0);
|
||||
m_newTextureMemUsed = getMemRequiredForSize(target_dim);
|
||||
|
||||
getContext().getTextureManager()->memoryChanged(m_newTextureMemUsed);
|
||||
getContext().getTextureManager()->addMemoryTransferredThisFrame(m_newTextureMemUsed);
|
||||
|
||||
if(!createGLTexture(target_dim)) {
|
||||
getContext().getTextureManager()->memoryChanged(-m_newTextureMemUsed);
|
||||
m_newTextureMemUsed = 0;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
m_handle_lock.clear();
|
||||
}
|
||||
}
|
||||
|
||||
GLuint KRTexture::getHandle() {
|
||||
/*
|
||||
if(m_iHandle == 0 && m_iNewHandle == 0) {
|
||||
resize(m_min_lod_max_dim);
|
||||
}
|
||||
*/
|
||||
resetPoolExpiry();
|
||||
return m_iHandle;
|
||||
}
|
||||
@@ -100,34 +93,6 @@ void KRTexture::resetPoolExpiry()
|
||||
m_last_frame_used = getContext().getCurrentFrame();
|
||||
}
|
||||
|
||||
long KRTexture::getThroughputRequiredForResize(int max_dim)
|
||||
{
|
||||
// Calculate the throughput required for GPU texture upload if the texture is resized to max_dim.
|
||||
// This default behaviour assumes that the texture will need to be deleted and regenerated to change the maximum mip-map level.
|
||||
// If an OpenGL extension is present that allows a texture to be resized incrementally, then this method should be overridden
|
||||
|
||||
if(max_dim == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
int target_dim = max_dim;
|
||||
if(target_dim < m_min_lod_max_dim) target_dim = target_dim;
|
||||
|
||||
|
||||
if(target_dim != m_current_lod_max_dim) {
|
||||
int requiredMemory = getMemRequiredForSize(target_dim);
|
||||
int requiredMemoryDelta = requiredMemory - getMemSize() - getReferencedMemSize();
|
||||
|
||||
if(requiredMemoryDelta == 0) {
|
||||
// Only resize / regenerate the texture if it actually changes the size of the texture (Assumption: textures of different sizes will always consume different amounts of memory)
|
||||
return 0;
|
||||
}
|
||||
return requiredMemory;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long KRTexture::getLastFrameUsed()
|
||||
{
|
||||
return m_last_frame_used;
|
||||
@@ -169,14 +134,18 @@ bool KRTexture::canStreamOut() const {
|
||||
|
||||
void KRTexture::_swapHandles()
|
||||
{
|
||||
if(m_iNewHandle != m_iHandle) {
|
||||
if(m_iHandle != 0) {
|
||||
GLDEBUG(glDeleteTextures(1, &m_iHandle));
|
||||
getContext().getTextureManager()->memoryChanged(m_newTextureMemUsed - m_textureMemUsed);
|
||||
m_textureMemUsed = m_newTextureMemUsed;
|
||||
if(m_handle_lock.test_and_set())
|
||||
{
|
||||
if(m_iHandle != m_iNewHandle) {
|
||||
if(m_iHandle != 0) {
|
||||
GLDEBUG(glDeleteTextures(1, &m_iHandle));
|
||||
getContext().getTextureManager()->memoryChanged(-m_textureMemUsed);
|
||||
}
|
||||
m_textureMemUsed = (long)m_newTextureMemUsed;
|
||||
m_newTextureMemUsed = 0;
|
||||
m_iHandle = m_iNewHandle;
|
||||
}
|
||||
m_iHandle = m_iNewHandle;
|
||||
m_handle_lock.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ public:
|
||||
virtual long getReferencedMemSize();
|
||||
|
||||
virtual long getMemRequiredForSize(int max_dim) = 0;
|
||||
virtual long getThroughputRequiredForResize(int max_dim);
|
||||
virtual void resize(int max_dim);
|
||||
|
||||
long getLastFrameUsed();
|
||||
@@ -74,10 +73,9 @@ protected:
|
||||
GLuint getHandle();
|
||||
|
||||
|
||||
GLuint m_iHandle;
|
||||
GLuint m_iHandle;
|
||||
GLuint m_iNewHandle;
|
||||
long m_textureMemUsed;
|
||||
long m_newTextureMemUsed;
|
||||
std::atomic_flag m_handle_lock;
|
||||
|
||||
int m_current_lod_max_dim;
|
||||
|
||||
@@ -86,6 +84,10 @@ protected:
|
||||
|
||||
long m_last_frame_used;
|
||||
long m_last_frame_bound;
|
||||
|
||||
private:
|
||||
std::atomic<long> m_textureMemUsed;
|
||||
std::atomic<long> m_newTextureMemUsed;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -49,12 +49,9 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) {
|
||||
|
||||
bool success = true;
|
||||
int prev_lod_max_dim = 0;
|
||||
long prev_mem_size = 0;
|
||||
#if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage
|
||||
|
||||
if(m_iHandle != 0) {
|
||||
prev_mem_size = getMemSize();
|
||||
m_textureMemUsed = 0;
|
||||
prev_lod_max_dim = m_current_lod_max_dim;
|
||||
}
|
||||
#endif
|
||||
@@ -74,10 +71,8 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) {
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
}
|
||||
|
||||
if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, m_newTextureMemUsed, prev_lod_max_dim)) {
|
||||
if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, prev_lod_max_dim)) {
|
||||
GLDEBUG(glDeleteTextures(1, &m_iNewHandle));
|
||||
getContext().getTextureManager()->memoryChanged(-m_newTextureMemUsed);
|
||||
m_newTextureMemUsed = 0;
|
||||
m_iNewHandle = m_iHandle;
|
||||
m_current_lod_max_dim = prev_lod_max_dim;
|
||||
success = false;
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
virtual bool save(const std::string& path);
|
||||
virtual bool save(KRDataBlock &data);
|
||||
|
||||
virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim) = 0;
|
||||
virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim) = 0;
|
||||
virtual void bind(GLuint texture_unit);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -68,37 +68,31 @@ bool KRTextureCube::createGLTexture(int lod_max_dim)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
m_iNewHandle = 0;
|
||||
GLDEBUG(glGenTextures(1, &m_iNewHandle));
|
||||
if(m_iNewHandle == 0) {
|
||||
m_iNewHandle = m_iHandle;
|
||||
success = false;
|
||||
} else {
|
||||
m_current_lod_max_dim = 0;
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iNewHandle));
|
||||
|
||||
bool bMipMaps = false;
|
||||
assert(m_iNewHandle != 0);
|
||||
|
||||
m_current_lod_max_dim = 0;
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iNewHandle));
|
||||
|
||||
bool bMipMaps = false;
|
||||
|
||||
for(int i=0; i<6; i++) {
|
||||
std::string faceName = getName() + SUFFIXES[i];
|
||||
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
|
||||
if(faceTexture) {
|
||||
if(faceTexture->hasMipmaps()) bMipMaps = true;
|
||||
faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, m_newTextureMemUsed, prev_lod_max_dim);
|
||||
}
|
||||
}
|
||||
|
||||
if(bMipMaps) {
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
|
||||
} else {
|
||||
// GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
|
||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_CUBE_MAP));
|
||||
for(int i=0; i<6; i++) {
|
||||
std::string faceName = getName() + SUFFIXES[i];
|
||||
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
|
||||
if(faceTexture) {
|
||||
if(faceTexture->hasMipmaps()) bMipMaps = true;
|
||||
faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, prev_lod_max_dim);
|
||||
}
|
||||
}
|
||||
|
||||
if(bMipMaps) {
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
|
||||
} else {
|
||||
// GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
|
||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_CUBE_MAP));
|
||||
}
|
||||
|
||||
|
||||
return success;
|
||||
|
||||
@@ -266,7 +266,7 @@ void KRTextureManager::balanceTextureMemory()
|
||||
}
|
||||
|
||||
// Determine how much memory we need to free up
|
||||
long memoryDeficit = wantedTextureMem - (getContext().KRENGINE_MAX_TEXTURE_MEM - getMemUsed());
|
||||
long memoryDeficit = wantedTextureMem - (getContext().KRENGINE_TARGET_TEXTURE_MEM_MAX - getMemUsed());
|
||||
|
||||
|
||||
// Determine how many mip map levels we need to strip off of inactive textures to free the memory we need
|
||||
@@ -289,10 +289,17 @@ void KRTextureManager::balanceTextureMemory()
|
||||
long inactive_texture_mem_used_target = 0;
|
||||
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();
|
||||
long mem_required = poolTexture->getMemRequiredForSize(maxDimInactive);
|
||||
long potentialMemoryDelta = mem_required - poolTexture->getMemSize();
|
||||
if(potentialMemoryDelta < 0) {
|
||||
poolTexture->resize(maxDimInactive);
|
||||
inactive_texture_mem_used_target += poolTexture->getMemRequiredForSize(maxDimInactive);
|
||||
if(mem_required * 2 + getMemUsed() < KRContext::KRENGINE_MAX_TEXTURE_MEM) {
|
||||
long mem_free;
|
||||
m_pContext->getMemoryStats(mem_free);
|
||||
if(mem_required * 2 < mem_free - 10000000) {
|
||||
poolTexture->resize(maxDimInactive);
|
||||
}
|
||||
}
|
||||
inactive_texture_mem_used_target += mem_required;
|
||||
} else {
|
||||
inactive_texture_mem_used_target += poolTexture->getMemSize();
|
||||
}
|
||||
@@ -302,7 +309,7 @@ void KRTextureManager::balanceTextureMemory()
|
||||
long memory_available = 0;
|
||||
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;
|
||||
memory_available = getContext().KRENGINE_TARGET_TEXTURE_MEM_MAX - inactive_texture_mem_used_target;
|
||||
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);
|
||||
@@ -316,7 +323,14 @@ void KRTextureManager::balanceTextureMemory()
|
||||
// Resize active textures to balance the memory usage and mipmap levels
|
||||
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);
|
||||
long mem_required = activeTexture->getMemRequiredForSize(maxDimActive);
|
||||
if(mem_required * 2 + getMemUsed() < KRContext::KRENGINE_MAX_TEXTURE_MEM) {
|
||||
long mem_free;
|
||||
m_pContext->getMemoryStats(mem_free);
|
||||
if(mem_required * 2 < mem_free - 10000000) {
|
||||
activeTexture->resize(maxDimActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//fprintf(stderr, "Active mipmap size: %i Inactive mapmap size: %i\n", (int)maxDimActive, (int)maxDimInactive);
|
||||
@@ -358,6 +372,7 @@ void KRTextureManager::addMemoryTransferredThisFrame(long memoryTransferred)
|
||||
void KRTextureManager::memoryChanged(long memoryDelta)
|
||||
{
|
||||
m_textureMemUsed += memoryDelta;
|
||||
//fprintf(stderr, "Texture Memory: %ld / %i\n", (long)m_textureMemUsed, KRContext::KRENGINE_MAX_TEXTURE_MEM);
|
||||
}
|
||||
|
||||
unordered_map<std::string, KRTexture *> &KRTextureManager::getTextures()
|
||||
|
||||
@@ -101,7 +101,7 @@ private:
|
||||
std::set<KRTexture *> m_activeTextures_streamer_copy;
|
||||
std::set<KRTexture *> m_poolTextures_streamer_copy;
|
||||
|
||||
long m_textureMemUsed;
|
||||
std::atomic<long> m_textureMemUsed;
|
||||
|
||||
void rotateBuffers();
|
||||
void balanceTextureMemory();
|
||||
|
||||
@@ -64,9 +64,11 @@ typedef struct _PVRTexHeader
|
||||
|
||||
KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name) {
|
||||
#if TARGET_OS_IPHONE
|
||||
m_pData->lock();
|
||||
PVRTexHeader *header = (PVRTexHeader *)m_pData->getStart();
|
||||
uint32_t formatFlags = header->flags & PVR_TEXTURE_FLAG_TYPE_MASK;
|
||||
|
||||
PVRTexHeader header;
|
||||
m_pData->copy(&header, 0, sizeof(PVRTexHeader));
|
||||
|
||||
uint32_t formatFlags = header.flags & PVR_TEXTURE_FLAG_TYPE_MASK;
|
||||
if (formatFlags == kPVRTextureFlagTypePVRTC_4) {
|
||||
m_internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
|
||||
} else if(formatFlags == kPVRTextureFlagTypePVRTC_2) {
|
||||
@@ -75,7 +77,7 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
|
||||
assert(false);
|
||||
}
|
||||
|
||||
uint32_t pvrTag = header->pvrTag;
|
||||
uint32_t pvrTag = header.pvrTag;
|
||||
if (gPVRTexIdentifier[0] != ((pvrTag >> 0) & 0xff) ||
|
||||
gPVRTexIdentifier[1] != ((pvrTag >> 8) & 0xff) ||
|
||||
gPVRTexIdentifier[2] != ((pvrTag >> 16) & 0xff) ||
|
||||
@@ -83,12 +85,12 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
|
||||
assert(false);
|
||||
}
|
||||
|
||||
m_iWidth = header->width; // Note: call __builtin_bswap32 when needed to switch endianness
|
||||
m_iHeight = header->height;
|
||||
m_bHasAlpha = header->bitmaskAlpha;
|
||||
m_iWidth = header.width; // Note: call __builtin_bswap32 when needed to switch endianness
|
||||
m_iHeight = header.height;
|
||||
m_bHasAlpha = header.bitmaskAlpha;
|
||||
|
||||
uint32_t dataStart = sizeof(PVRTexHeader);
|
||||
uint32_t dataLength = header->dataLength, dataOffset = 0, dataSize = 0;
|
||||
uint32_t dataLength = header.dataLength, dataOffset = 0, dataSize = 0;
|
||||
uint32_t width = m_iWidth, height = m_iHeight, bpp = 4;
|
||||
uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0;
|
||||
|
||||
@@ -115,11 +117,7 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
|
||||
}
|
||||
dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8);
|
||||
|
||||
dataBlockStruct newBlock;
|
||||
newBlock.start = dataStart + dataOffset;
|
||||
newBlock.length = dataSize;
|
||||
|
||||
m_blocks.push_back(newBlock);
|
||||
m_blocks.push_back(m_pData->getSubBlock(dataStart + dataOffset, dataSize));
|
||||
|
||||
dataOffset += dataSize;
|
||||
|
||||
@@ -135,13 +133,15 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
|
||||
|
||||
m_max_lod_max_dim = m_iWidth > m_iHeight ? m_iWidth : m_iHeight;
|
||||
m_min_lod_max_dim = width > height ? width : height;
|
||||
|
||||
m_pData->unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
KRTexturePVR::~KRTexturePVR() {
|
||||
|
||||
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
|
||||
KRDataBlock *block = *itr;
|
||||
delete block;
|
||||
}
|
||||
m_blocks.clear();
|
||||
}
|
||||
|
||||
long KRTexturePVR::getMemRequiredForSize(int max_dim)
|
||||
@@ -154,10 +154,10 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
|
||||
int height = m_iHeight;
|
||||
long memoryRequired = 0;
|
||||
|
||||
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
|
||||
dataBlockStruct block = *itr;
|
||||
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
|
||||
KRDataBlock *block = *itr;
|
||||
if(width <= target_dim && height <= target_dim) {
|
||||
memoryRequired += block.length;
|
||||
memoryRequired += block->getSize();
|
||||
}
|
||||
|
||||
width = width >> 1;
|
||||
@@ -173,7 +173,7 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
|
||||
return memoryRequired;
|
||||
}
|
||||
|
||||
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim)
|
||||
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim)
|
||||
{
|
||||
int target_dim = lod_max_dim;
|
||||
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
|
||||
@@ -196,7 +196,7 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
int level_count=0;
|
||||
int max_lod_width=0;
|
||||
int max_lod_height=0;
|
||||
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
|
||||
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
|
||||
if(width <= target_dim && height <= target_dim) {
|
||||
if(max_lod_width == 0) {
|
||||
max_lod_width = width;
|
||||
@@ -229,8 +229,8 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
// Upload texture data
|
||||
int destination_level=0;
|
||||
int source_level = 0;
|
||||
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
|
||||
dataBlockStruct block = *itr;
|
||||
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
|
||||
KRDataBlock *block = *itr;
|
||||
if(width <= target_dim && height <= target_dim) {
|
||||
|
||||
if(width > current_lod_max_dim) {
|
||||
@@ -245,24 +245,23 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
// GLDEBUG(glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
|
||||
GLDEBUG(glCopyTextureLevelsAPPLE(m_iNewHandle, m_iHandle, source_level, 1));
|
||||
} else {
|
||||
// glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
|
||||
m_pData->lock();
|
||||
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block.length, (char *)m_pData->getStart() + block.start));
|
||||
m_pData->unlock();
|
||||
// GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block.length, block.start));
|
||||
memoryTransferred += block.length; // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
|
||||
block->lock();
|
||||
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, (GLsizei)block->getSize(), block->getStart()));
|
||||
block->unlock();
|
||||
|
||||
memoryTransferred += block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
|
||||
}
|
||||
#else
|
||||
m_pData->lock();
|
||||
block->lock();
|
||||
#if GL_EXT_texture_storage
|
||||
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block.length, (char *)m_pData->getStart() + block.start));
|
||||
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block->getSize(), block->getStart()));
|
||||
#else
|
||||
GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block.length, (char *)m_pData->getStart() + block.start));
|
||||
GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block->getSize(), block->getStart()));
|
||||
#endif
|
||||
m_pData->unlock();
|
||||
memoryTransferred += block.length; // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
|
||||
block->unlock();
|
||||
memoryTransferred += block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
|
||||
#endif
|
||||
memoryRequired += block.length;
|
||||
memoryRequired += block->getSize();
|
||||
//
|
||||
// err = glGetError();
|
||||
// if (err != GL_NO_ERROR) {
|
||||
@@ -288,10 +287,6 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
}
|
||||
}
|
||||
|
||||
textureMemUsed += memoryRequired;
|
||||
getContext().getTextureManager()->memoryChanged(memoryRequired);
|
||||
getContext().getTextureManager()->addMemoryTransferredThisFrame(memoryTransferred);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
virtual ~KRTexturePVR();
|
||||
virtual std::string getExtension();
|
||||
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim);
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim);
|
||||
|
||||
virtual long getMemRequiredForSize(int max_dim);
|
||||
|
||||
@@ -29,12 +29,7 @@ protected:
|
||||
GLenum m_internalFormat;
|
||||
bool m_bHasAlpha;
|
||||
|
||||
struct dataBlockStruct {
|
||||
uint32_t start;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
std::list<dataBlockStruct> m_blocks;
|
||||
std::list<KRDataBlock *> m_blocks;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,6 +40,8 @@ KRTextureStreamer::~KRTextureStreamer()
|
||||
|
||||
void KRTextureStreamer::run()
|
||||
{
|
||||
pthread_setname_np("Kraken - Texture Streamer");
|
||||
|
||||
std::chrono::microseconds sleep_duration( 100 );
|
||||
[EAGLContext setCurrentContext: gTextureStreamerContext];
|
||||
|
||||
|
||||
@@ -33,6 +33,34 @@ KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string na
|
||||
|
||||
m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height;
|
||||
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data->unlock();
|
||||
}
|
||||
|
||||
@@ -41,7 +69,7 @@ KRTextureTGA::~KRTextureTGA()
|
||||
|
||||
}
|
||||
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim)
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim)
|
||||
{
|
||||
m_pData->lock();
|
||||
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
|
||||
@@ -83,10 +111,6 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
m_pData->unlock();
|
||||
return false;
|
||||
}
|
||||
int memAllocated = pHeader->width * pHeader->height * 4;
|
||||
textureMemUsed += memAllocated;
|
||||
getContext().getTextureManager()->memoryChanged(memAllocated);
|
||||
getContext().getTextureManager()->addMemoryTransferredThisFrame(memAllocated);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
@@ -98,10 +122,6 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
m_pData->unlock();
|
||||
return false;
|
||||
}
|
||||
int memAllocated = pHeader->width * pHeader->height * 4;
|
||||
textureMemUsed += memAllocated;
|
||||
getContext().getTextureManager()->memoryChanged(memAllocated);
|
||||
getContext().getTextureManager()->addMemoryTransferredThisFrame(memAllocated);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
@@ -121,25 +141,7 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
|
||||
long KRTextureTGA::getMemRequiredForSize(int max_dim)
|
||||
{
|
||||
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
return pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
return pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return m_imageSize;
|
||||
}
|
||||
|
||||
std::string KRTextureTGA::getExtension()
|
||||
|
||||
@@ -18,9 +18,11 @@ public:
|
||||
virtual ~KRTextureTGA();
|
||||
virtual std::string getExtension();
|
||||
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim);
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, int prev_lod_max_dim);
|
||||
|
||||
virtual long getMemRequiredForSize(int max_dim);
|
||||
private:
|
||||
long m_imageSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user