diff --git a/KREngine/Kraken.xcodeproj/project.pbxproj b/KREngine/Kraken.xcodeproj/project.pbxproj index eaf6e96..b3554fb 100644 --- a/KREngine/Kraken.xcodeproj/project.pbxproj +++ b/KREngine/Kraken.xcodeproj/project.pbxproj @@ -77,12 +77,12 @@ E43F70DD181B20E400136169 /* KRLODSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43F70DA181B20E300136169 /* KRLODSet.cpp */; }; E43F70DE181B20E400136169 /* KRLODSet.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70DB181B20E400136169 /* KRLODSet.h */; }; E43F70DF181B20E400136169 /* KRLODSet.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70DB181B20E400136169 /* KRLODSet.h */; }; - E43F70E51824D9AB00136169 /* KRTextureStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43F70E31824D9AB00136169 /* KRTextureStreamer.cpp */; }; - E43F70E61824D9AB00136169 /* KRTextureStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43F70E31824D9AB00136169 /* KRTextureStreamer.cpp */; }; + E43F70E51824D9AB00136169 /* KRTextureStreamer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */; }; + E43F70E61824D9AB00136169 /* KRTextureStreamer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */; }; E43F70E71824D9AB00136169 /* KRTextureStreamer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70E41824D9AB00136169 /* KRTextureStreamer.h */; }; E43F70E81824D9AB00136169 /* KRTextureStreamer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70E41824D9AB00136169 /* KRTextureStreamer.h */; }; - E43F70FF1824E73100136169 /* KRMeshStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43F70FD1824E73100136169 /* KRMeshStreamer.cpp */; }; - E43F71001824E73100136169 /* KRMeshStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43F70FD1824E73100136169 /* KRMeshStreamer.cpp */; }; + E43F70FF1824E73100136169 /* KRMeshStreamer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E43F70FD1824E73100136169 /* KRMeshStreamer.mm */; }; + E43F71001824E73100136169 /* KRMeshStreamer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E43F70FD1824E73100136169 /* KRMeshStreamer.mm */; }; E43F71011824E73100136169 /* KRMeshStreamer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70FE1824E73100136169 /* KRMeshStreamer.h */; }; E43F71021824E73100136169 /* KRMeshStreamer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70FE1824E73100136169 /* KRMeshStreamer.h */; }; E4409D2916FA748700310F76 /* font.tga in Resources */ = {isa = PBXBuildFile; fileRef = E41AE1DD16B124CA00980428 /* font.tga */; }; @@ -437,9 +437,9 @@ E43B0AD515DDCA0D00A5CB9F /* KRContextObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRContextObject.h; sourceTree = ""; }; E43F70DA181B20E300136169 /* KRLODSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRLODSet.cpp; sourceTree = ""; }; E43F70DB181B20E400136169 /* KRLODSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRLODSet.h; sourceTree = ""; }; - E43F70E31824D9AB00136169 /* KRTextureStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRTextureStreamer.cpp; sourceTree = ""; }; + E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KRTextureStreamer.mm; sourceTree = ""; }; E43F70E41824D9AB00136169 /* KRTextureStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRTextureStreamer.h; sourceTree = ""; }; - E43F70FD1824E73100136169 /* KRMeshStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRMeshStreamer.cpp; sourceTree = ""; }; + E43F70FD1824E73100136169 /* KRMeshStreamer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KRMeshStreamer.mm; sourceTree = ""; }; E43F70FE1824E73100136169 /* KRMeshStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRMeshStreamer.h; sourceTree = ""; }; E44F38231683B22C00399B5D /* KRRenderSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRRenderSettings.h; sourceTree = ""; }; E44F38271683B24400399B5D /* KRRenderSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRRenderSettings.cpp; sourceTree = ""; }; @@ -902,7 +902,7 @@ E4CA10EE1637BD58005D9400 /* KRTextureTGA.cpp */, E460292516681CFE00261BB9 /* KRTextureAnimated.h */, E460292716681D1000261BB9 /* KRTextureAnimated.cpp */, - E43F70E31824D9AB00136169 /* KRTextureStreamer.cpp */, + E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */, E43F70E41824D9AB00136169 /* KRTextureStreamer.h */, ); name = Texture; @@ -919,7 +919,7 @@ E4C454AE167BB8FC003586CD /* KRMeshCube.cpp */, E4C454B1167BC04B003586CD /* KRMeshSphere.h */, E4C454B4167BC05C003586CD /* KRMeshSphere.cpp */, - E43F70FD1824E73100136169 /* KRMeshStreamer.cpp */, + E43F70FD1824E73100136169 /* KRMeshStreamer.mm */, E43F70FE1824E73100136169 /* KRMeshStreamer.h */, ); name = Mesh; @@ -1583,7 +1583,7 @@ E497B946151BA99500D3DC67 /* KRVector2.cpp in Sources */, E497B94D151BCF2500D3DC67 /* KRResource.cpp in Sources */, E497B950151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */, - E43F70FF1824E73100136169 /* KRMeshStreamer.cpp in Sources */, + E43F70FF1824E73100136169 /* KRMeshStreamer.mm in Sources */, E461A156152E54F800F2044A /* KRLight.cpp in Sources */, E461A159152E557E00F2044A /* KRPointLight.cpp in Sources */, E468447F17FFDF51001F1FA1 /* KRLocator.cpp in Sources */, @@ -1609,7 +1609,7 @@ E4324BA816444C230043185B /* KRParticleSystem.cpp in Sources */, E4324BAE16444E120043185B /* KRParticleSystemNewtonian.cpp in Sources */, E460292816681D1000261BB9 /* KRTextureAnimated.cpp in Sources */, - E43F70E51824D9AB00136169 /* KRTextureStreamer.cpp in Sources */, + E43F70E51824D9AB00136169 /* KRTextureStreamer.mm in Sources */, E428C2F51669611600A16EDF /* KRAnimationManager.cpp in Sources */, E428C2FB1669613200A16EDF /* KRAnimation.cpp in Sources */, E428C3071669628A00A16EDF /* KRAnimationCurve.cpp in Sources */, @@ -1682,7 +1682,7 @@ E488399515F928CA00BD66D5 /* KRBundle.cpp in Sources */, E488399D15F92BE000BD66D5 /* KRBundleManager.cpp in Sources */, E43F70DD181B20E400136169 /* KRLODSet.cpp in Sources */, - E43F71001824E73100136169 /* KRMeshStreamer.cpp in Sources */, + E43F71001824E73100136169 /* KRMeshStreamer.mm in Sources */, E4B175AD161F5A1000B8FB80 /* KRTexture.cpp in Sources */, E4B175B3161F5FAF00B8FB80 /* KRTextureCube.cpp in Sources */, E4CA10EA1637BD2B005D9400 /* KRTexturePVR.cpp in Sources */, @@ -1698,7 +1698,7 @@ E428C31A1669A25D00A16EDF /* KRAnimationAttribute.cpp in Sources */, E416AA9D1671375C000F6786 /* KRAnimationCurveManager.cpp in Sources */, E480BE6D1671C653004EC8AD /* KRBone.cpp in Sources */, - E43F70E61824D9AB00136169 /* KRTextureStreamer.cpp in Sources */, + E43F70E61824D9AB00136169 /* KRTextureStreamer.mm in Sources */, E4C454B0167BB8FC003586CD /* KRMeshCube.cpp in Sources */, E4C454B6167BC05C003586CD /* KRMeshSphere.cpp in Sources */, E4C454BC167BD248003586CD /* KRHitInfo.cpp in Sources */, diff --git a/KREngine/kraken/KRAudioSample.cpp b/KREngine/kraken/KRAudioSample.cpp index b9bd250..b115711 100644 --- a/KREngine/kraken/KRAudioSample.cpp +++ b/KREngine/kraken/KRAudioSample.cpp @@ -40,7 +40,6 @@ KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension) : KRResource(context, name) { m_pData = new KRDataBlock(); - m_pData->lock(); m_extension = extension; m_audio_file_id = 0; @@ -56,7 +55,6 @@ KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string e KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name) { m_pData = data; - m_pData->lock(); m_extension = extension; m_audio_file_id = 0; @@ -73,7 +71,6 @@ KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string e KRAudioSample::~KRAudioSample() { closeFile(); - m_pData->unlock(); delete m_pData; } @@ -202,7 +199,6 @@ OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc UInt32 max_count = sound->m_pData->getSize() - inPosition; *actualCount = requestCount < max_count ? requestCount : max_count; sound->m_pData->copy(buffer, inPosition, *actualCount); - //memcpy(buffer, (unsigned char *)sound->m_pData->getStart() + inPosition, *actualCount); return noErr; } diff --git a/KREngine/kraken/KRDataBlock.cpp b/KREngine/kraken/KRDataBlock.cpp index c420a50..33050ad 100644 --- a/KREngine/kraken/KRDataBlock.cpp +++ b/KREngine/kraken/KRDataBlock.cpp @@ -33,6 +33,12 @@ #include "KREngine-common.h" #include "KRResource.h" +#include + +int m_mapCount = 0; +size_t m_mapSize = 0; +size_t m_mapOverhead = 0; + KRDataBlock::KRDataBlock() { m_data = NULL; m_data_size = 0; @@ -271,17 +277,49 @@ void KRDataBlock::lock() { m_lockCount++; + if(m_lockCount == 1) { // 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); + //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. } + 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; } @@ -299,11 +337,16 @@ void KRDataBlock::unlock() // 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); + //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); } } diff --git a/KREngine/kraken/KREngine-common.h b/KREngine/kraken/KREngine-common.h index 8ad0ac6..fbde9bc 100644 --- a/KREngine/kraken/KREngine-common.h +++ b/KREngine/kraken/KREngine-common.h @@ -72,7 +72,8 @@ using std::queue; int KRAKEN_MEM_PAGE_SIZE = getpagesize(); -#define KRAKEN_MEM_ROUND_DOWN_PAGE(x) (x & ~(KRAKEN_MEM_PAGE_SIZE - 1)) +#define KRAKEN_MEM_ROUND_DOWN_PAGE(x) ((x) & ~(KRAKEN_MEM_PAGE_SIZE - 1)) +#define KRAKEN_MEM_ROUND_UP_PAGE(x) ((((x) - 1) & ~(KRAKEN_MEM_PAGE_SIZE - 1)) + KRAKEN_MEM_PAGE_SIZE) #define KRENGINE_MAX_TEXTURE_UNITS 8 diff --git a/KREngine/kraken/KRMeshManager.h b/KREngine/kraken/KRMeshManager.h index 3d8910c..f1782b4 100644 --- a/KREngine/kraken/KRMeshManager.h +++ b/KREngine/kraken/KRMeshManager.h @@ -110,7 +110,6 @@ public: void log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count); std::vector getDrawCalls(); - private: unordered_multimap m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model diff --git a/KREngine/kraken/KRMeshStreamer.cpp b/KREngine/kraken/KRMeshStreamer.mm similarity index 66% rename from KREngine/kraken/KRMeshStreamer.cpp rename to KREngine/kraken/KRMeshStreamer.mm index 51b1902..b2aa5de 100644 --- a/KREngine/kraken/KRMeshStreamer.cpp +++ b/KREngine/kraken/KRMeshStreamer.mm @@ -8,10 +8,15 @@ #include "KRMeshStreamer.h" +#include "KREngine-common.h" + #include +EAGLContext *gMeshStreamerContext; + KRMeshStreamer::KRMeshStreamer(KRContext &context) : m_context(context) { + gMeshStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup]; m_stop = false; m_thread = std::thread(&KRMeshStreamer::run, this); } @@ -20,11 +25,14 @@ KRMeshStreamer::~KRMeshStreamer() { m_stop = true; m_thread.join(); + + [gMeshStreamerContext release]; } void KRMeshStreamer::run() { std::chrono::microseconds sleep_duration( 100 ); + [EAGLContext setCurrentContext: gMeshStreamerContext]; while(!m_stop) { diff --git a/KREngine/kraken/KRTexture.cpp b/KREngine/kraken/KRTexture.cpp index 24aee65..5c0830c 100644 --- a/KREngine/kraken/KRTexture.cpp +++ b/KREngine/kraken/KRTexture.cpp @@ -15,16 +15,24 @@ KRTexture::KRTexture(KRContext &context, std::string name) : KRResource(context, name) { m_iHandle = 0; + m_iNewHandle = 0; m_textureMemUsed = 0; + m_newTextureMemUsed = 0; m_last_frame_used = 0; + m_last_frame_bound = 0; } KRTexture::~KRTexture() { - releaseHandle(); + releaseHandles(); } -void KRTexture::releaseHandle() { +void KRTexture::releaseHandles() { + if(m_iNewHandle != 0) { + GLDEBUG(glDeleteTextures(1, &m_iNewHandle)); + m_iNewHandle = 0; + m_newTextureMemUsed = 0; + } if(m_iHandle != 0) { GLDEBUG(glDeleteTextures(1, &m_iHandle)); getContext().getTextureManager()->memoryChanged(-getMemSize()); @@ -34,7 +42,7 @@ void KRTexture::releaseHandle() { } long KRTexture::getMemSize() { - return m_textureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory + return m_textureMemUsed + m_newTextureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory } long KRTexture::getReferencedMemSize() { @@ -44,8 +52,10 @@ long KRTexture::getReferencedMemSize() { void KRTexture::resize(int max_dim) { + assert(m_iHandle == m_iNewHandle); // Only allow one resize() per frame + if(max_dim == 0) { - releaseHandle(); + m_iNewHandle = 0; } else { int target_dim = max_dim; if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; @@ -65,7 +75,7 @@ void KRTexture::resize(int max_dim) return; } - if(m_current_lod_max_dim != target_dim || m_iHandle == 0) { + if(m_current_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) { if(!createGLTexture(target_dim)) { assert(false); } @@ -74,12 +84,12 @@ void KRTexture::resize(int max_dim) } } - GLuint KRTexture::getHandle() { - if(m_iHandle == 0) { - //resize(getContext().KRENGINE_MIN_TEXTURE_DIM); + /* + if(m_iHandle == 0 && m_iNewHandle == 0) { resize(m_min_lod_max_dim); } + */ resetPoolExpiry(); return m_iHandle; } @@ -147,3 +157,25 @@ int KRTexture::getMinMipMap() { bool KRTexture::hasMipmaps() { return m_max_lod_max_dim != m_min_lod_max_dim; } + +void KRTexture::bind(GLuint texture_unit) { + m_last_frame_bound = getContext().getCurrentFrame(); +} + +bool KRTexture::canStreamOut() const { + return (m_last_frame_bound + 2 > getContext().getCurrentFrame()); +} + +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; + m_newTextureMemUsed = 0; + } + m_iHandle = m_iNewHandle; + } +} + diff --git a/KREngine/kraken/KRTexture.h b/KREngine/kraken/KRTexture.h index 1a38e4f..8ecd169 100644 --- a/KREngine/kraken/KRTexture.h +++ b/KREngine/kraken/KRTexture.h @@ -46,8 +46,8 @@ public: KRTexture(KRContext &context, std::string name); virtual ~KRTexture(); - virtual void bind(GLuint texture_unit) = 0; - void releaseHandle(); + virtual void bind(GLuint texture_unit); + void releaseHandles(); long getMemSize(); virtual long getReferencedMemSize(); @@ -66,13 +66,18 @@ public: int getMinMipMap(); bool hasMipmaps(); + bool canStreamOut() const; + + void _swapHandles(); protected: virtual bool createGLTexture(int lod_max_dim) = 0; GLuint getHandle(); GLuint m_iHandle; + GLuint m_iNewHandle; long m_textureMemUsed; + long m_newTextureMemUsed; int m_current_lod_max_dim; @@ -80,6 +85,7 @@ protected: uint32_t m_min_lod_max_dim; long m_last_frame_used; + long m_last_frame_bound; }; diff --git a/KREngine/kraken/KRTexture2D.cpp b/KREngine/kraken/KRTexture2D.cpp index da79d62..e5d6138 100644 --- a/KREngine/kraken/KRTexture2D.cpp +++ b/KREngine/kraken/KRTexture2D.cpp @@ -43,54 +43,52 @@ KRTexture2D::~KRTexture2D() { } bool KRTexture2D::createGLTexture(int lod_max_dim) { + if(m_iHandle != m_iNewHandle) { + return true; + } + bool success = true; - GLuint prev_handle = 0; 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_handle = m_iHandle; prev_mem_size = getMemSize(); - m_iHandle = 0; m_textureMemUsed = 0; prev_lod_max_dim = m_current_lod_max_dim; } -#else - releaseHandle(); #endif + m_iNewHandle = 0; m_current_lod_max_dim = 0; - GLDEBUG(glGenTextures(1, &m_iHandle)); + GLDEBUG(glGenTextures(1, &m_iNewHandle)); - if(m_iHandle == 0) { + if(m_iNewHandle == 0) { success = false; } else { - GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iHandle)); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iNewHandle)); if (hasMipmaps()) { GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)); } else { 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_textureMemUsed, prev_lod_max_dim, prev_handle)) { - GLDEBUG(glDeleteTextures(1, &m_iHandle)); - m_iHandle = 0; - m_current_lod_max_dim = 0; + if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, m_newTextureMemUsed, 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; } } - if(prev_handle != 0) { - getContext().getTextureManager()->memoryChanged(-prev_mem_size); - GLDEBUG(glDeleteTextures(1, &prev_handle)); - } - return success; } void KRTexture2D::bind(GLuint texture_unit) { + KRTexture::bind(texture_unit); GLuint handle = getHandle(); GLDEBUG(glBindTexture(GL_TEXTURE_2D, handle)); @@ -101,7 +99,6 @@ void KRTexture2D::bind(GLuint texture_unit) { } } - bool KRTexture2D::save(const std::string& path) { if(m_pData) { diff --git a/KREngine/kraken/KRTexture2D.h b/KREngine/kraken/KRTexture2D.h index f3e8684..87efc8f 100644 --- a/KREngine/kraken/KRTexture2D.h +++ b/KREngine/kraken/KRTexture2D.h @@ -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, GLuint prev_handle) = 0; + virtual bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim) = 0; virtual void bind(GLuint texture_unit); protected: diff --git a/KREngine/kraken/KRTextureAnimated.cpp b/KREngine/kraken/KRTextureAnimated.cpp index c3b5669..a38d970 100644 --- a/KREngine/kraken/KRTextureAnimated.cpp +++ b/KREngine/kraken/KRTextureAnimated.cpp @@ -114,6 +114,7 @@ void KRTextureAnimated::resetPoolExpiry() void KRTextureAnimated::bind(GLuint texture_unit) { + KRTexture::bind(texture_unit); int frame_number = (int)floor(fmodf(getContext().getAbsoluteTime() * m_frame_rate,m_frame_count)); KRTexture2D *frame_texture = textureForFrame(frame_number); if(frame_texture) { diff --git a/KREngine/kraken/KRTextureCube.cpp b/KREngine/kraken/KRTextureCube.cpp index a9e532d..710aef0 100644 --- a/KREngine/kraken/KRTextureCube.cpp +++ b/KREngine/kraken/KRTextureCube.cpp @@ -55,32 +55,30 @@ KRTextureCube::~KRTextureCube() bool KRTextureCube::createGLTexture(int lod_max_dim) { + assert(m_iNewHandle == m_iHandle); // Only allow one resize per frame + bool success = true; - GLuint prev_handle = 0; 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_handle = m_iHandle; - prev_mem_size = getMemSize(); - m_iHandle = 0; - m_textureMemUsed = 0; prev_lod_max_dim = m_current_lod_max_dim; } -#else - releaseHandle(); #endif - m_current_lod_max_dim = 0; - GLDEBUG(glGenTextures(1, &m_iHandle)); - if(m_iHandle == 0) { + + + + m_iNewHandle = 0; + GLDEBUG(glGenTextures(1, &m_iNewHandle)); + if(m_iNewHandle == 0) { + m_iNewHandle = m_iHandle; success = false; } else { - - GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iHandle)); + m_current_lod_max_dim = 0; + GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iNewHandle)); bool bMipMaps = false; @@ -89,7 +87,7 @@ bool KRTextureCube::createGLTexture(int lod_max_dim) 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_textureMemUsed, prev_lod_max_dim, prev_handle); + faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, m_newTextureMemUsed, prev_lod_max_dim); } } @@ -101,11 +99,7 @@ bool KRTextureCube::createGLTexture(int lod_max_dim) GLDEBUG(glGenerateMipmap(GL_TEXTURE_CUBE_MAP)); } } - - if(prev_handle != 0) { - getContext().getTextureManager()->memoryChanged(-prev_mem_size); - GLDEBUG(glDeleteTextures(1, &prev_handle)); - } + return success; } @@ -141,6 +135,7 @@ void KRTextureCube::resetPoolExpiry() void KRTextureCube::bind(GLuint texture_unit) { + KRTexture::bind(texture_unit); GLuint handle = getHandle(); GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, handle)); if(handle) { diff --git a/KREngine/kraken/KRTextureManager.cpp b/KREngine/kraken/KRTextureManager.cpp index 643a7f3..e258841 100644 --- a/KREngine/kraken/KRTextureManager.cpp +++ b/KREngine/kraken/KRTextureManager.cpp @@ -216,6 +216,10 @@ long KRTextureManager::getMemActive() { void KRTextureManager::startFrame(float deltaTime) { _clearGLState(); + for(std::set::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) { + KRTexture *activeTexture = *itr; + activeTexture->_swapHandles(); + } m_memoryTransferredThisFrame = 0; balanceTextureMemory(); rotateBuffers(); @@ -310,7 +314,7 @@ void KRTextureManager::rotateBuffers() KRTexture *poolTexture = *itr; if(poolTexture->getLastFrameUsed() + KRENGINE_TEXTURE_EXPIRY_FRAMES < getContext().getCurrentFrame()) { expiredTextures.insert(poolTexture); - poolTexture->releaseHandle(); + poolTexture->releaseHandles(); } } for(std::set::iterator itr=expiredTextures.begin(); itr != expiredTextures.end(); itr++) { @@ -318,6 +322,7 @@ void KRTextureManager::rotateBuffers() } // ----====---- Swap the buffers ----====---- + m_poolTextures.insert(m_activeTextures.begin(), m_activeTextures.end()); m_activeTextures.clear(); } diff --git a/KREngine/kraken/KRTexturePVR.cpp b/KREngine/kraken/KRTexturePVR.cpp index 44d0b07..4765597 100644 --- a/KREngine/kraken/KRTexturePVR.cpp +++ b/KREngine/kraken/KRTexturePVR.cpp @@ -135,6 +135,7 @@ 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 } @@ -172,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, GLuint prev_handle) +bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, 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; @@ -242,7 +243,7 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo if(target == GL_TEXTURE_2D && width <= prev_lod_max_dim && height <= prev_lod_max_dim) { //GLDEBUG(glCompressedTexImage2D(target, i, m_internalFormat, width, height, 0, block.length, NULL)); // Allocate, but don't copy // GLDEBUG(glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); - GLDEBUG(glCopyTextureLevelsAPPLE(m_iHandle, prev_handle, source_level, 1)); + 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(); @@ -288,7 +289,7 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo } textureMemUsed += memoryRequired; - getContext().getTextureManager()->memoryChanged(memoryTransferred); + getContext().getTextureManager()->memoryChanged(memoryRequired); getContext().getTextureManager()->addMemoryTransferredThisFrame(memoryTransferred); return true; diff --git a/KREngine/kraken/KRTexturePVR.h b/KREngine/kraken/KRTexturePVR.h index 515387b..97c6505 100644 --- a/KREngine/kraken/KRTexturePVR.h +++ b/KREngine/kraken/KRTexturePVR.h @@ -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, GLuint prev_handle); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim); virtual long getMemRequiredForSize(int max_dim); diff --git a/KREngine/kraken/KRTextureStreamer.cpp b/KREngine/kraken/KRTextureStreamer.mm similarity index 66% rename from KREngine/kraken/KRTextureStreamer.cpp rename to KREngine/kraken/KRTextureStreamer.mm index a968cc0..004b2d9 100644 --- a/KREngine/kraken/KRTextureStreamer.cpp +++ b/KREngine/kraken/KRTextureStreamer.mm @@ -6,12 +6,17 @@ // Copyright (c) 2013 Kearwood Software. All rights reserved. // +#include "KREngine-common.h" + #include "KRTextureStreamer.h" #include +EAGLContext *gTextureStreamerContext; + KRTextureStreamer::KRTextureStreamer(KRContext &context) : m_context(context) { + gTextureStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup]; m_stop = false; m_thread = std::thread(&KRTextureStreamer::run, this); } @@ -20,11 +25,14 @@ KRTextureStreamer::~KRTextureStreamer() { m_stop = true; m_thread.join(); + + [gTextureStreamerContext release]; } void KRTextureStreamer::run() { std::chrono::microseconds sleep_duration( 100 ); + [EAGLContext setCurrentContext: gTextureStreamerContext]; while(!m_stop) { diff --git a/KREngine/kraken/KRTextureTGA.cpp b/KREngine/kraken/KRTextureTGA.cpp index e04d5a7..b5fd7fa 100644 --- a/KREngine/kraken/KRTextureTGA.cpp +++ b/KREngine/kraken/KRTextureTGA.cpp @@ -41,7 +41,7 @@ KRTextureTGA::~KRTextureTGA() } -bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle) +bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim) { m_pData->lock(); TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart(); diff --git a/KREngine/kraken/KRTextureTGA.h b/KREngine/kraken/KRTextureTGA.h index 458ca3a..1624341 100644 --- a/KREngine/kraken/KRTextureTGA.h +++ b/KREngine/kraken/KRTextureTGA.h @@ -18,7 +18,7 @@ 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, GLuint prev_handle); + bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim); virtual long getMemRequiredForSize(int max_dim); };