Texture streaming has improved performance by taking advantage of the APPLE_copy_texture_levels and EXT_texture_storage extensions.
This commit is contained in:
@@ -90,7 +90,7 @@ void kraken::set_parameter(const std::string ¶meter_name, float parameter_va
|
||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||
|
||||
KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 32000000;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 4000000;
|
||||
|
||||
|
||||
KRContext::KRENGINE_MAX_VBO_MEM = total_ram * 2 / 4;
|
||||
|
||||
@@ -66,9 +66,6 @@ void KRTexture::resize(int max_dim)
|
||||
}
|
||||
|
||||
if(m_current_lod_max_dim != target_dim || m_iHandle == 0) {
|
||||
releaseHandle();
|
||||
}
|
||||
if(m_iHandle == 0) {
|
||||
if(!createGLTexture(target_dim)) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -43,28 +43,52 @@ KRTexture2D::~KRTexture2D() {
|
||||
}
|
||||
|
||||
bool KRTexture2D::createGLTexture(int lod_max_dim) {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iHandle));
|
||||
if (hasMipmaps()) {
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
|
||||
success = false;
|
||||
} else {
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iHandle));
|
||||
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;
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, m_textureMemUsed)) {
|
||||
GLDEBUG(glDeleteTextures(1, &m_iHandle));
|
||||
m_iHandle = 0;
|
||||
m_current_lod_max_dim = 0;
|
||||
return false;
|
||||
if(prev_handle != 0) {
|
||||
getContext().getTextureManager()->memoryChanged(-prev_mem_size);
|
||||
GLDEBUG(glDeleteTextures(1, &prev_handle));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
void KRTexture2D::bind(GLuint texture_unit) {
|
||||
|
||||
@@ -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) = 0;
|
||||
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 void bind(GLuint texture_unit);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -55,6 +55,8 @@ KRTextureCube::~KRTextureCube()
|
||||
|
||||
bool KRTextureCube::createGLTexture(int lod_max_dim)
|
||||
{
|
||||
releaseHandle();
|
||||
|
||||
m_current_lod_max_dim = 0;
|
||||
GLDEBUG(glGenTextures(1, &m_iHandle));
|
||||
if(m_iHandle == 0) {
|
||||
@@ -70,7 +72,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);
|
||||
faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, m_textureMemUsed, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,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)
|
||||
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle)
|
||||
{
|
||||
int target_dim = lod_max_dim;
|
||||
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
|
||||
@@ -186,29 +186,93 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
int width = m_iWidth;
|
||||
int height = m_iHeight;
|
||||
long memoryRequired = 0;
|
||||
long memoryTransferred = 0;
|
||||
|
||||
|
||||
// Upload texture data
|
||||
int i=0;
|
||||
#if GL_EXT_texture_storage
|
||||
//void TexStorage2DEXT(enum target, sizei levels, enum internalformat, sizei width, sizei height);
|
||||
//TexStorage2DEXT(target, )
|
||||
|
||||
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++) {
|
||||
dataBlockStruct block = *itr;
|
||||
if(width <= target_dim && height <= target_dim) {
|
||||
memoryRequired += block.length;
|
||||
if(max_lod_width == 0) {
|
||||
max_lod_width = width;
|
||||
max_lod_height = height;
|
||||
}
|
||||
if(width > current_lod_max_dim) {
|
||||
current_lod_max_dim = width;
|
||||
}
|
||||
if(height > current_lod_max_dim) {
|
||||
current_lod_max_dim = height;
|
||||
}
|
||||
glCompressedTexImage2D(target, i, m_internalFormat, width, height, 0, block.length, block.start);
|
||||
err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
assert(false);
|
||||
return false;
|
||||
|
||||
level_count++;
|
||||
}
|
||||
|
||||
width = width >> 1;
|
||||
if(width < 1) {
|
||||
width = 1;
|
||||
}
|
||||
height = height >> 1;
|
||||
if(height < 1) {
|
||||
height = 1;
|
||||
}
|
||||
}
|
||||
width = m_iWidth;
|
||||
height = m_iHeight;
|
||||
|
||||
glTexStorage2DEXT(target, level_count, m_internalFormat, max_lod_width, max_lod_height);
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
if(width <= target_dim && height <= target_dim) {
|
||||
|
||||
if(width > current_lod_max_dim) {
|
||||
current_lod_max_dim = width;
|
||||
}
|
||||
if(height > current_lod_max_dim) {
|
||||
current_lod_max_dim = height;
|
||||
}
|
||||
#if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage
|
||||
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));
|
||||
} else {
|
||||
// glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
|
||||
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block.length, block.start));
|
||||
// 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
|
||||
}
|
||||
#else
|
||||
#if GL_EXT_texture_storage
|
||||
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block.length, block.start));
|
||||
#else
|
||||
GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block.length, block.start));
|
||||
#endif
|
||||
memoryTransferred += block.length; // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
|
||||
#endif
|
||||
memoryRequired += block.length;
|
||||
//
|
||||
// err = glGetError();
|
||||
// if (err != GL_NO_ERROR) {
|
||||
// assert(false);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
|
||||
destination_level++;
|
||||
}
|
||||
|
||||
i++;
|
||||
if(width <= prev_lod_max_dim && height <= prev_lod_max_dim) {
|
||||
source_level++;
|
||||
}
|
||||
|
||||
width = width >> 1;
|
||||
@@ -222,8 +286,8 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
}
|
||||
|
||||
textureMemUsed += memoryRequired;
|
||||
getContext().getTextureManager()->memoryChanged(memoryRequired);
|
||||
getContext().getTextureManager()->addMemoryTransferredThisFrame(memoryRequired);
|
||||
getContext().getTextureManager()->memoryChanged(memoryTransferred);
|
||||
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);
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle);
|
||||
|
||||
virtual long getMemRequiredForSize(int max_dim);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ KRTextureTGA::~KRTextureTGA()
|
||||
|
||||
}
|
||||
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed)
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle)
|
||||
{
|
||||
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
|
||||
unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER);
|
||||
|
||||
@@ -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);
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle);
|
||||
|
||||
virtual long getMemRequiredForSize(int max_dim);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user