Asynchronous streaming and memory management improvements in progress.

--HG--
branch : async_streaming
This commit is contained in:
2013-11-01 23:17:04 -07:00
parent 63503393a4
commit ab808fc3e1
13 changed files with 133 additions and 47 deletions

View File

@@ -37,6 +37,7 @@ KRDataBlock::KRDataBlock() {
m_data_size = 0;
m_data_offset = 0;
m_fdPackFile = 0;
m_fileName = "";
m_mmapData = NULL;
m_fileOwnerDataBlock = NULL;
m_bMalloced = false;
@@ -68,6 +69,7 @@ void KRDataBlock::unload()
m_data_size = 0;
m_data_offset = 0;
m_fdPackFile = 0;
m_fileName = "";
m_mmapData = NULL;
m_fileOwnerDataBlock = NULL;
m_bReadOnly = false;
@@ -95,6 +97,7 @@ bool KRDataBlock::load(const std::string &path)
m_fdPackFile = open(path.c_str(), O_RDONLY);
if(m_fdPackFile >= 0) {
m_fileOwnerDataBlock = this;
m_fileName = path;
if(fstat(m_fdPackFile, &statbuf) >= 0) {
m_data_size = statbuf.st_size;
m_data_offset = 0;
@@ -117,9 +120,9 @@ KRDataBlock *KRDataBlock::getSubBlock(int start, int length)
if(m_fdPackFile) {
new_block->m_fdPackFile = m_fdPackFile;
new_block->m_fileOwnerDataBlock = m_fileOwnerDataBlock;
new_block->m_data_offset = start;
new_block->m_data_offset = start + m_data_offset;
} else if(m_bMalloced) {
new_block->m_data = (unsigned char *)m_data + start;
new_block->m_data = (unsigned char *)m_data + start + m_data_offset;
}
new_block->m_bReadOnly = true;
return new_block;
@@ -189,16 +192,20 @@ void KRDataBlock::append(void *data, size_t size) {
// Copy the entire data block to the destination pointer
void KRDataBlock::copy(void *dest) {
lock();
memcpy((unsigned char *)dest, m_data, m_data_size);
unlock();
copy(dest, 0, m_data_size);
}
// Copy a range of data to the destination pointer
void KRDataBlock::copy(void *dest, int start, int count) {
lock();
memcpy((unsigned char *)dest, (unsigned char *)m_data + start, count);
unlock();
if(m_lockCount == 0 && m_fdPackFile != 0) {
// Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer
ssize_t r = pread(m_fdPackFile, dest, count, start + m_data_offset);
assert(r != -1);
} else {
lock();
memcpy((unsigned char *)dest, (unsigned char *)m_data + start, count);
unlock();
}
}
// Append data to the end of the block, increasing the size of the block and making it read-write.
@@ -249,25 +256,26 @@ bool KRDataBlock::save(const std::string& path) {
// Get contents as a string
std::string KRDataBlock::getString()
{
lock();
KRDataBlock b;
b.append(*this);
b.append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
b.lock();
std::string ret = std::string((char *)b.getStart());
b.unlock();
unlock();
return ret;
}
// Lock the memory, forcing it to be loaded into a contiguous block of address space
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);
// 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) {
@@ -290,6 +298,8 @@ 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);
munmap(m_mmapData, m_data_size);
m_data = NULL;
m_mmapData = NULL;

View File

@@ -97,6 +97,7 @@ private:
// For memory mapped objects:
int m_fdPackFile;
std::string m_fileName;
KRDataBlock *m_fileOwnerDataBlock;
void *m_mmapData;
@@ -111,6 +112,7 @@ private:
// Assert if not locked
void assertLocked();
};
#endif

View File

@@ -425,7 +425,7 @@ void kraken::set_debug_text(const std::string &print_text)
[self getAmbientIntensity],
[self getSunTemperature],
[self getSunIntensity],
_settings.dof_quality,
static_cast<float>(_settings.dof_quality),
_settings.dof_depth,
_settings.dof_falloff,
_settings.bEnableFlash ? 1.0f : 0.0f,
@@ -445,26 +445,26 @@ void kraken::set_debug_text(const std::string &print_text)
_settings.bEnableDeferredLighting ? 1.0f : 0.0f,
_settings.getPerspectiveNearZ(),
_settings.getPerspectiveFarZ(),
_settings.volumetric_environment_enable,
5 - _settings.volumetric_environment_downsample,
static_cast<float>(_settings.volumetric_environment_enable),
static_cast<float>(5 - _settings.volumetric_environment_downsample),
_settings.volumetric_environment_max_distance,
_settings.volumetric_environment_quality,
_settings.volumetric_environment_intensity,
_settings.fog_type,
static_cast<float>(_settings.fog_type),
_settings.fog_near,
_settings.fog_far,
_settings.fog_density,
_settings.fog_color.x,
_settings.fog_color.y,
_settings.fog_color.z,
_settings.dust_particle_enable,
static_cast<float>(_settings.dust_particle_enable),
_settings.dust_particle_intensity,
_settings.getLODBias(),
_settings.getEnableRealtimeOcclusion(),
static_cast<float>(_settings.getEnableRealtimeOcclusion()),
_settings.debug_display,
_settings.siren_enable,
_settings.siren_enable_reverb,
_settings.siren_enable_hrtf,
static_cast<float>(_settings.siren_enable),
static_cast<float>(_settings.siren_enable_reverb),
static_cast<float>(_settings.siren_enable_hrtf),
_settings.siren_reverb_max_length,
_settings.max_anisotropy
};

View File

@@ -11,7 +11,6 @@
#include "KRResource.h"
#include "KRNode.h"
#include "KRTexture.h"
class KRLODGroup : public KRNode {
public:

View File

@@ -0,0 +1,35 @@
//
// KRLODSet.cpp
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KRLODSet.h"
#include "KRContext.h"
KRLODSet::KRLODSet(KRScene &scene, std::string name) : KRNode(scene, name)
{
}
KRLODSet::~KRLODSet()
{
}
std::string KRLODSet::getElementName() {
return "lod_set";
}
tinyxml2::XMLElement *KRLODSet::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
return e;
}
void KRLODSet::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
}

View File

@@ -0,0 +1,26 @@
//
// KRLODSet
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRLODSET_H
#define KRLODSET_H
#include "KRResource.h"
#include "KRNode.h"
class KRLODSet : public KRNode {
public:
KRLODSet(KRScene &scene, std::string name);
virtual ~KRLODSet();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
};
#endif

View File

@@ -11,7 +11,7 @@
KRLocator::KRLocator(KRScene &scene, std::string name) : KRNode(scene, name)
{
setScaleCompensation(true);
}
KRLocator::~KRLocator()

View File

@@ -404,11 +404,10 @@ bool KRScene::save(KRDataBlock &data) {
KRScene *KRScene::Load(KRContext &context, const std::string &name, KRDataBlock *data)
{
data->append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
std::string xml_string = data->getString();
delete data;
tinyxml2::XMLDocument doc;
data->lock();
doc.Parse((char *)data->getStart());
data->unlock();
doc.Parse(xml_string.c_str());
KRScene *new_scene = new KRScene(context, name);
tinyxml2::XMLElement *scene_element = doc.RootElement();
@@ -420,7 +419,7 @@ KRScene *KRScene::Load(KRContext &context, const std::string &name, KRDataBlock
new_scene->getRootNode()->addChild(n);
}
delete data;
return new_scene;
}

View File

@@ -36,11 +36,9 @@
KRTexture2D::KRTexture2D(KRContext &context, KRDataBlock *data, std::string name) : KRTexture(context, name) {
m_current_lod_max_dim = 0;
m_pData = data;
m_pData->lock();
}
KRTexture2D::~KRTexture2D() {
m_pData->unlock();
delete m_pData;
}

View File

@@ -87,7 +87,7 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
m_iHeight = header->height;
m_bHasAlpha = header->bitmaskAlpha;
uint8_t *bytes = ((uint8_t *)m_pData->getStart()) + sizeof(PVRTexHeader);
uint32_t dataStart = sizeof(PVRTexHeader);
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;
@@ -116,7 +116,7 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8);
dataBlockStruct newBlock;
newBlock.start = bytes+dataOffset;
newBlock.start = dataStart + dataOffset;
newBlock.length = dataSize;
m_blocks.push_back(newBlock);
@@ -245,16 +245,20 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
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));
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
}
#else
m_pData->lock();
#if GL_EXT_texture_storage
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block.length, block.start));
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block.length, (char *)m_pData->getStart() + block.start));
#else
GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block.length, block.start));
GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block.length, (char *)m_pData->getStart() + block.start));
#endif
m_pData->unlock();
memoryTransferred += block.length; // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
#endif
memoryRequired += block.length;

View File

@@ -30,7 +30,7 @@ protected:
bool m_bHasAlpha;
struct dataBlockStruct {
void *start;
uint32_t start;
uint32_t length;
};

View File

@@ -42,11 +42,13 @@ KRTextureTGA::~KRTextureTGA()
}
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle)
{
{
m_pData->lock();
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);
if(pHeader->colourmaptype != 0) {
m_pData->unlock();
return false; // Mapped colors not supported
}
@@ -78,6 +80,7 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
free(converted_image);
err = glGetError();
if (err != GL_NO_ERROR) {
m_pData->unlock();
return false;
}
int memAllocated = pHeader->width * pHeader->height * 4;
@@ -92,6 +95,7 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
glTexImage2D(target, 0, GL_RGBA, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData);
err = glGetError();
if (err != GL_NO_ERROR) {
m_pData->unlock();
return false;
}
int memAllocated = pHeader->width * pHeader->height * 4;
@@ -102,13 +106,16 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
}
break;
default:
m_pData->unlock();
return false; // 16-bit images not yet supported
}
break;
default:
m_pData->unlock();
return false; // Image type not yet supported
}
m_pData->unlock();
return true;
}