add VertexArrayBook::save_to_disk()

This commit is contained in:
David Rose 2007-05-24 01:24:39 +00:00
parent 15e0dcd9a0
commit fd13c10bbd
13 changed files with 216 additions and 70 deletions

View File

@ -31,7 +31,6 @@
#include "cycleDataStageReader.h"
#include "cycleDataStageWriter.h"
#include "pipelineCycler.h"
#include "pStatCollector.h"
#include "pmap.h"
#include "reMutex.h"
#include "simpleLru.h"

View File

@ -31,6 +31,17 @@ SimpleAllocator(size_t max_size) :
{
}
////////////////////////////////////////////////////////////////////
// Function: SimpleAllocator::is_empty
// Access: Published
// Description: Returns true if there are no blocks allocated on this
// page, or false if there is at least one.
////////////////////////////////////////////////////////////////////
INLINE bool SimpleAllocator::
is_empty() const {
return (_next == this);
}
////////////////////////////////////////////////////////////////////
// Function: SimpleAllocator::get_total_size
// Access: Published

View File

@ -28,6 +28,7 @@ SimpleAllocator::
// We're shutting down. Force-free everything remaining.
while (_next != (LinkedListNode *)this) {
nassertv(_next != (LinkedListNode *)NULL);
cerr << "force-deleting " << _next << "\n";
((SimpleAllocatorBlock *)_next)->free();
}
}
@ -65,6 +66,8 @@ alloc(size_t size) {
size_t free_size = next->_start - end;
if (size <= free_size) {
SimpleAllocatorBlock *new_block = make_block(end, size);
nassertr(new_block->get_allocator() == this, NULL);
new_block->insert_before(next);
_total_size += size;
return new_block;
@ -82,6 +85,8 @@ alloc(size_t size) {
size_t free_size = _max_size - end;
if (size <= free_size) {
SimpleAllocatorBlock *new_block = make_block(end, size);
nassertr(new_block->get_allocator() == this, NULL);
new_block->insert_before(this);
_total_size += size;
return new_block;

View File

@ -39,6 +39,7 @@ PUBLISHED:
SimpleAllocatorBlock *alloc(size_t size);
INLINE bool is_empty() const;
INLINE size_t get_total_size() const;
INLINE size_t get_max_size() const;
INLINE void set_max_size(size_t max_size);

View File

@ -38,9 +38,11 @@
#include "zStream.h"
#include "indent.h"
#include "cmath.h"
#include "pStatTimer.h"
#include <stddef.h>
PStatCollector Texture::_texture_read_pcollector("*:Texture:Read");
TypeHandle Texture::_type_handle;
////////////////////////////////////////////////////////////////////
@ -1760,6 +1762,8 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath,
int primary_file_num_channels, int alpha_file_channel,
int z, int n, bool read_pages, bool read_mipmaps,
bool header_only, BamCacheRecord *record) {
PStatTimer timer(_texture_read_pcollector);
if (record != (BamCacheRecord *)NULL) {
header_only = false;
}

View File

@ -29,6 +29,7 @@
#include "updateSeq.h"
#include "pmap.h"
#include "config_gobj.h"
#include "pStatCollector.h"
class PNMImage;
class TextureContext;
@ -535,6 +536,8 @@ private:
typedef pmap<string, PT(TypedReferenceCount) > AuxData;
AuxData _aux_data;
static PStatCollector _texture_read_pcollector;
// Datagram stuff
public:
static void register_with_read_factory();

View File

@ -79,21 +79,6 @@ check_resident() const {
nassertv(_size == _uncompressed_size);
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataPage::alloc
// Access: Published
// Description: Allocates a new block. Returns NULL if a block of the
// requested size cannot be allocated.
//
// To free the allocated block, call block->free(), or
// simply delete the block pointer.
////////////////////////////////////////////////////////////////////
INLINE VertexDataBlock *VertexDataPage::
alloc(size_t size) {
check_resident();
return (VertexDataBlock *)SimpleAllocator::alloc(size);
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataPage::get_first_block
// Access: Published
@ -197,6 +182,7 @@ get_page() const {
////////////////////////////////////////////////////////////////////
INLINE unsigned char *VertexDataBlock::
get_pointer() const {
nassertr(get_page() != (VertexDataPage *)NULL, NULL);
return get_page()->get_page_data() + get_start();
}

View File

@ -61,7 +61,6 @@ SimpleLru *VertexDataPage::_global_lru[RC_end_of_list] = {
&VertexDataPage::_resident_lru,
&VertexDataPage::_compressed_lru,
&VertexDataPage::_disk_lru,
&VertexDataPage::_disk_lru,
};
size_t VertexDataPage::_total_page_size = 0;
@ -110,12 +109,13 @@ alloc(size_t size) {
_next_pi = pi;
return block;
}
if (_pages[pi]->get_total_size() == 0) {
if (_pages[pi]->is_empty()) {
// This page is empty, but must have been too small. Create a
// new page in its place.
delete _pages[pi];
_pages[pi] = create_new_page(size);
return _pages[pi]->alloc(size);
VertexDataBlock *block = _pages[pi]->alloc(size);
return block;
}
++pi;
}
@ -129,7 +129,7 @@ alloc(size_t size) {
_next_pi = pi;
return block;
}
if (_pages[pi]->get_total_size() == 0) {
if (_pages[pi]->is_empty()) {
// This page is empty, but must have been too small. Create a
// new page in its place.
delete _pages[pi];
@ -143,7 +143,24 @@ alloc(size_t size) {
// large enough to hold this requested block.
VertexDataPage *page = create_new_page(size);
_pages.push_back(page);
return page->alloc(size);
VertexDataBlock *block = page->alloc(size);
return block;
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataBook::save_to_disk
// Access: Published
// Description: Writes all pages to disk immediately, just in case
// they get evicted later. It makes sense to make this
// call just before taking down a loading screen, to
// minimize chugs from saving pages inadvertently later.
////////////////////////////////////////////////////////////////////
void VertexDataBook::
save_to_disk() {
Pages::iterator pi;
for (pi = _pages.begin(); pi != _pages.end(); ++pi) {
(*pi)->save_to_disk();
}
}
@ -157,7 +174,6 @@ VertexDataPage(size_t page_size) : SimpleAllocator(page_size), SimpleLruPage(pag
_page_data = new unsigned char[get_max_size()];
_size = page_size;
_uncompressed_size = _size;
_saved_block = NULL;
_total_page_size += _size;
get_class_type().inc_memory_usage(TypeHandle::MC_array, _size);
set_ram_class(RC_resident);
@ -176,10 +192,6 @@ VertexDataPage::
if (_page_data != NULL) {
delete[] _page_data;
}
if (_saved_block != (SimpleAllocatorBlock *)NULL) {
delete _saved_block;
}
}
////////////////////////////////////////////////////////////////////
@ -196,7 +208,7 @@ make_resident() {
return;
}
if (_ram_class == RC_disk || _ram_class == RC_compressed_disk) {
if (_ram_class == RC_disk) {
restore_from_disk();
}
@ -249,7 +261,7 @@ make_compressed() {
return;
}
if (_ram_class == RC_disk || _ram_class == RC_compressed_disk) {
if (_ram_class == RC_disk) {
restore_from_disk();
}
@ -306,24 +318,15 @@ make_compressed() {
////////////////////////////////////////////////////////////////////
void VertexDataPage::
make_disk() {
if (_ram_class == RC_disk || _ram_class == RC_compressed_disk) {
// If we're already compressed, just mark the page recently used.
if (_ram_class == RC_disk) {
// If we're already on disk, just mark the page recently used.
mark_used_lru();
return;
}
if (_ram_class == RC_resident || _ram_class == RC_compressed) {
nassertv(_saved_block == (SimpleAllocatorBlock *)NULL);
PStatTimer timer(_vdata_save_pcollector);
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Storing page, " << _size << " bytes, to disk\n";
}
_saved_block = get_save_file()->write_data(_page_data, _size);
if (_saved_block == NULL) {
// Can't write it to disk. Too bad.
if (!save_to_disk()) {
// Can't save it to disk for some reason.
mark_used_lru();
return;
}
@ -335,12 +338,47 @@ make_disk() {
_page_data = NULL;
_size = 0;
if (_ram_class == RC_resident) {
set_ram_class(RC_disk);
set_ram_class(RC_disk);
}
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataPage::save_to_disk
// Access: Published
// Description: Writes the page to disk, but does not evict it from
// memory or affect its LRU status. If it gets evicted
// later without having been modified, it will not need
// to write itself to disk again.
//
// Returns true on success, false on failure.
////////////////////////////////////////////////////////////////////
bool VertexDataPage::
save_to_disk() {
if (_ram_class == RC_resident || _ram_class == RC_compressed) {
PStatTimer timer(_vdata_save_pcollector);
if (_saved_block == (VertexDataSaveBlock *)NULL) {
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Storing page, " << _size << " bytes, to disk\n";
}
bool compressed = (_ram_class == RC_compressed);
_saved_block = get_save_file()->write_data(_page_data, _size, compressed);
if (_saved_block == (VertexDataSaveBlock *)NULL) {
// Can't write it to disk. Too bad.
return false;
}
} else {
set_ram_class(RC_compressed_disk);
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Page already stored: " << _size << " bytes\n";
}
}
}
return true;
}
////////////////////////////////////////////////////////////////////
@ -352,8 +390,8 @@ make_disk() {
////////////////////////////////////////////////////////////////////
void VertexDataPage::
restore_from_disk() {
if (_ram_class == RC_disk || _ram_class == RC_compressed_disk) {
nassertv(_saved_block != (VertexDataBlock *)NULL);
if (_ram_class == RC_disk) {
nassertv(_saved_block != (VertexDataSaveBlock *)NULL);
nassertv(_page_data == (unsigned char *)NULL && _size == 0);
PStatTimer timer(_vdata_restore_pcollector);
@ -375,11 +413,8 @@ restore_from_disk() {
get_class_type().inc_memory_usage(TypeHandle::MC_array, _size);
_total_page_size += _size;
delete _saved_block;
_saved_block = NULL;
set_lru_size(_size);
if (_ram_class == RC_compressed_disk) {
if (_saved_block->get_compressed()) {
set_ram_class(RC_compressed);
} else {
set_ram_class(RC_resident);
@ -387,6 +422,29 @@ restore_from_disk() {
}
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataPage::alloc
// Access: Published
// Description: Allocates a new block. Returns NULL if a block of the
// requested size cannot be allocated.
//
// To free the allocated block, call block->free(), or
// simply delete the block pointer.
////////////////////////////////////////////////////////////////////
VertexDataBlock *VertexDataPage::
alloc(size_t size) {
check_resident();
VertexDataBlock *block = (VertexDataBlock *)SimpleAllocator::alloc(size);
if (block != (VertexDataBlock *)NULL) {
// When we allocate a new block within the page, we have to clear
// the disk cache (since we have just invalidated it).
_saved_block.clear();
}
return block;
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataPage::make_block
// Access: Protected, Virtual
@ -429,7 +487,6 @@ evict_lru() {
break;
case RC_disk:
case RC_compressed_disk:
gobj_cat.warning()
<< "Cannot evict array data from disk.\n";
break;

View File

@ -24,10 +24,10 @@
#include "simpleAllocator.h"
#include "referenceCount.h"
#include "pStatCollector.h"
#include "vertexDataSaveFile.h"
class VertexDataPage;
class VertexDataBlock;
class VertexDataSaveFile;
////////////////////////////////////////////////////////////////////
// Class : VertexDataBook
@ -44,6 +44,8 @@ PUBLISHED:
INLINE int get_num_pages() const;
INLINE VertexDataPage *get_page(int n) const;
void save_to_disk();
private:
INLINE VertexDataPage *create_new_page(size_t size);
@ -73,7 +75,6 @@ PUBLISHED:
RC_resident,
RC_compressed,
RC_disk,
RC_compressed_disk,
RC_end_of_list, // list marker; do not use
};
@ -84,9 +85,10 @@ PUBLISHED:
void make_resident();
void make_compressed();
void make_disk();
bool save_to_disk();
void restore_from_disk();
INLINE VertexDataBlock *alloc(size_t size);
VertexDataBlock *alloc(size_t size);
INLINE VertexDataBlock *get_first_block() const;
INLINE static size_t get_total_page_size();
@ -107,7 +109,7 @@ private:
unsigned char *_page_data;
size_t _size, _uncompressed_size;
RamClass _ram_class;
SimpleAllocatorBlock *_saved_block;
PT(VertexDataSaveBlock) _saved_block;
static SimpleLru _resident_lru;
static SimpleLru _compressed_lru;

View File

@ -91,7 +91,10 @@ page_out(VertexDataBook &book) {
// We only need to allocate a block if we don't have a source
// file.
_block = book.alloc(_size);
memcpy(_block->get_pointer(), _resident_data, _size);
nassertv(_block != (VertexDataBlock *)NULL);
unsigned char *pointer = _block->get_pointer();
nassertv(pointer != (unsigned char *)NULL);
memcpy(pointer, _resident_data, _size);
}
free(_resident_data);

View File

@ -48,6 +48,43 @@ get_total_file_size() const {
////////////////////////////////////////////////////////////////////
INLINE size_t VertexDataSaveFile::
get_used_file_size() const {
return _allocator.get_total_size();
return SimpleAllocator::get_total_size();
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataSaveBlock::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VertexDataSaveBlock::
VertexDataSaveBlock(VertexDataSaveFile *file, size_t start, size_t size) :
SimpleAllocatorBlock(file, start, size)
{
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataSaveBlock::set_compressed
// Access: Public
// Description: Sets the compressed flag. This is true to indicate
// the data is written in zlib-compressed form to the
// save file; false to indicate the data is
// uncompressed.
////////////////////////////////////////////////////////////////////
INLINE void VertexDataSaveBlock::
set_compressed(bool compressed) {
_compressed = compressed;
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataSaveBlock::get_compressed
// Access: Public
// Description: Returns the compressed flag. This is true to
// indicate the data is written in zlib-compressed form
// to the save file; false to indicate the data is
// uncompressed.
////////////////////////////////////////////////////////////////////
INLINE bool VertexDataSaveBlock::
get_compressed() const {
return _compressed;
}

View File

@ -26,7 +26,7 @@
VertexDataSaveFile::
VertexDataSaveFile(const Filename &directory, const string &prefix,
size_t max_size) :
_allocator(max_size)
SimpleAllocator(max_size)
{
Filename dir;
if (directory.empty()) {
@ -168,14 +168,15 @@ VertexDataSaveFile::
// cannot be written (e.g. no remaining space on the
// file).
////////////////////////////////////////////////////////////////////
SimpleAllocatorBlock *VertexDataSaveFile::
write_data(const unsigned char *data, size_t size) {
PT(VertexDataSaveBlock) VertexDataSaveFile::
write_data(const unsigned char *data, size_t size, bool compressed) {
if (!_is_valid) {
return NULL;
}
SimpleAllocatorBlock *block = _allocator.alloc(size);
if (block != (SimpleAllocatorBlock *)NULL) {
PT(VertexDataSaveBlock) block = (VertexDataSaveBlock *)SimpleAllocator::alloc(size);
if (block != (VertexDataSaveBlock *)NULL) {
block->set_compressed(compressed);
#ifdef _WIN32
if (SetFilePointer(_handle, block->get_start(), NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
@ -189,7 +190,6 @@ write_data(const unsigned char *data, size_t size) {
bytes_written != size) {
gobj_cat.error()
<< "Error writing " << size << " bytes to save file. Disk full?\n";
delete block;
return NULL;
}
@ -201,11 +201,10 @@ write_data(const unsigned char *data, size_t size) {
return false;
}
ssize_t result = write(_fd, data, size);
ssize_t result = ::write(_fd, data, size);
if (result != (ssize_t)size) {
gobj_cat.error()
<< "Error writing " << size << " bytes to save file. Disk full?\n";
delete block;
return NULL;
}
#endif // _WIN32
@ -223,7 +222,7 @@ write_data(const unsigned char *data, size_t size) {
// on success, false on failure.
////////////////////////////////////////////////////////////////////
bool VertexDataSaveFile::
read_data(unsigned char *data, size_t size, SimpleAllocatorBlock *block) {
read_data(unsigned char *data, size_t size, VertexDataSaveBlock *block) {
if (!_is_valid) {
return false;
}
@ -263,3 +262,15 @@ read_data(unsigned char *data, size_t size, SimpleAllocatorBlock *block) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: VertexDataSaveFile::make_block
// Access: Protected, Virtual
// Description: Creates a new SimpleAllocatorBlock object. Override
// this function to specialize the block type returned.
////////////////////////////////////////////////////////////////////
SimpleAllocatorBlock *VertexDataSaveFile::
make_block(size_t start, size_t size) {
return new VertexDataSaveBlock(this, start, size);
}

View File

@ -28,6 +28,8 @@
#include <windows.h>
#endif
class VertexDataSaveBlock;
////////////////////////////////////////////////////////////////////
// Class : VertexDataSaveFile
// Description : A temporary file to hold the vertex data that has
@ -35,7 +37,7 @@
// vertex data arrays are written into one large flat
// file.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VertexDataSaveFile {
class EXPCL_PANDA VertexDataSaveFile : public SimpleAllocator {
public:
VertexDataSaveFile(const Filename &directory, const string &prefix,
size_t max_size);
@ -46,12 +48,15 @@ public:
INLINE size_t get_total_file_size() const;
INLINE size_t get_used_file_size() const;
SimpleAllocatorBlock *write_data(const unsigned char *data, size_t size);
PT(VertexDataSaveBlock) write_data(const unsigned char *data, size_t size,
bool compressed);
bool read_data(unsigned char *data, size_t size,
SimpleAllocatorBlock *block);
VertexDataSaveBlock *block);
protected:
virtual SimpleAllocatorBlock *make_block(size_t start, size_t size);
private:
SimpleAllocator _allocator;
Filename _filename;
bool _is_valid;
size_t _total_file_size;
@ -63,6 +68,28 @@ private:
#endif // _WIN32
};
////////////////////////////////////////////////////////////////////
// Class : VertexDataSaveBlock
// Description : A block of bytes on the save file.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VertexDataSaveBlock : public SimpleAllocatorBlock, public ReferenceCount {
protected:
INLINE VertexDataSaveBlock(VertexDataSaveFile *file,
size_t start, size_t size);
public:
INLINE void set_compressed(bool compressed);
INLINE bool get_compressed() const;
private:
bool _compressed;
public:
INLINE unsigned char *get_pointer() const;
friend class VertexDataSaveFile;
};
#include "vertexDataSaveFile.I"
#endif