From 9bb65dd0c37704b023e40f33e01b59c26b22d62e Mon Sep 17 00:00:00 2001 From: ponchio Date: Mon, 13 Dec 2004 00:44:48 +0000 Subject: [PATCH] Lotsa changes... --- apps/nexus/lrupserver.h | 64 ++++++++++ apps/nexus/nexus.cpp | 145 +++++------------------ apps/nexus/nexus.h | 77 +++--------- apps/nexus/nexusbase.h | 63 ++++++++++ apps/nexus/nexusmt.cpp | 229 ++++++++++++++++++++---------------- apps/nexus/nexusmt.h | 63 +++++----- apps/nexus/nexusview.cpp | 39 +++--- apps/nexus/nxsbuilder.cpp | 20 ++-- apps/nexus/nxsedit.cpp | 8 +- apps/nexus/nxstest.cpp | 8 +- apps/nexus/prefetch.cpp | 56 +++++++++ apps/nexus/prefetch.h | 41 +++++++ apps/nexus/pserver.cpp | 158 +++++++++++++++++++++++++ apps/nexus/pserver.h | 93 +++++++++++++++ apps/nexus/queuepserver.cpp | 85 +++++++++++++ apps/nexus/queuepserver.h | 42 +++++++ 16 files changed, 852 insertions(+), 339 deletions(-) create mode 100644 apps/nexus/lrupserver.h create mode 100644 apps/nexus/nexusbase.h create mode 100644 apps/nexus/prefetch.cpp create mode 100644 apps/nexus/prefetch.h create mode 100644 apps/nexus/pserver.cpp create mode 100644 apps/nexus/pserver.h create mode 100644 apps/nexus/queuepserver.cpp create mode 100644 apps/nexus/queuepserver.h diff --git a/apps/nexus/lrupserver.h b/apps/nexus/lrupserver.h new file mode 100644 index 00000000..3cfa4fe7 --- /dev/null +++ b/apps/nexus/lrupserver.h @@ -0,0 +1,64 @@ +#ifndef NXS_LRU_PSERVER_H +#define NXS_LRU_PSERVER_H + +#include +#include +#include "pserver.h" + +namespace nxs { + +class LruPServer: public PServer { + public: + //TODO change name to Item + typedef std::pair Item; + std::list items; + typedef std::list Items; + std::map index; + + ~LruPServer() { + Flush(); + } + + Patch &Lookup(unsigned int patch, unsigned short nv, unsigned short nf) { + if(index.count(patch)) { + Items::iterator &i = index[patch]; + Item item = *i; + items.erase(i); + items.push_front(item); + i = items.begin(); + return *((*i).second); + } else { + while(ram_used > ram_max) { + index.erase(items.back().first); + FlushPatch(patch, items.back().second); + items.pop_back(); + } + Item item; + item.first = patch; + item.second = LoadPatch(patch, nv, nf); + items.push_front(item); + Items::iterator i = items.begin(); + index[patch] = i; + return *((*i).second); + } + } + + bool IsLoaded(unsigned int patch) { + return index.count(patch); + } + void Flush() { + std::cerr << "Lru flulshing\n"; + std::map::iterator i; + for(i = index.begin(); i != index.end(); i++) { + Item &item = *((*i).second); + FlushPatch((*i).first, item.second); + } + + items.clear(); + index.clear(); + } +}; + +}//namespace + +#endif diff --git a/apps/nexus/nexus.cpp b/apps/nexus/nexus.cpp index bcc8c601..5c6eb227 100644 --- a/apps/nexus/nexus.cpp +++ b/apps/nexus/nexus.cpp @@ -1,12 +1,16 @@ -#include #include + +#include +#include + #include "nexus.h" +#include "lrupserver.h" +#include "queuepserver.h" using namespace std; using namespace vcg; using namespace nxs; -Nexus::Nexus(): index_file(NULL) {} Nexus::~Nexus() { Close(); } @@ -17,7 +21,7 @@ bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) { cerr << "Could not create file: " << file << ".nxs\n"; return false; } - + signature = sig; totvert = 0; totface = 0; @@ -27,6 +31,8 @@ bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) { chunk_size = c_size; + history.clear(); + if(!patches.Create(file + ".nxp", signature, chunk_size)) { cerr << "Could not create file: " << file << ".nxp" << endl; return false; @@ -40,7 +46,10 @@ bool Nexus::Create(const string &file, Signature sig, unsigned int c_size) { return true; } -bool Nexus::Load(const string &file, bool readonly) { + +bool Nexus::Load(const string &file, bool rdonly) { + readonly = rdonly; + index_file = fopen((file + ".nxs").c_str(), "rb+"); if(!index_file) return false; @@ -63,6 +72,7 @@ bool Nexus::Load(const string &file, bool readonly) { index.resize(size); readed = fread(&index[0], sizeof(PatchInfo), size, index_file); if(readed != size) return false; + patches.ReadEntries(index_file); borders.ReadEntries(index_file); @@ -88,20 +98,26 @@ bool Nexus::Load(const string &file, bool readonly) { history[i].created[e] = buffer[pos++]; } + if(readonly) { + fclose(index_file); + index_file = NULL; + } + //TODO support readonly if(!patches.Load(file + ".nxp", signature, chunk_size, readonly)) return false; - if(!borders.Load(file + ".nxb", readonly, 1, 500)) return false; + if(!borders.Load(file + ".nxb", readonly, 1, 500)) + return false; return true; } void Nexus::Close() { patches.Close(); borders.Close(); - if(!index_file) return; + rewind(index_file); - + fwrite(&signature, sizeof(unsigned int), 1, index_file); fwrite(&totvert, sizeof(unsigned int), 1, index_file); fwrite(&totface, sizeof(unsigned int), 1, index_file); @@ -112,9 +128,11 @@ void Nexus::Close() { fwrite(&size, sizeof(unsigned int), 1, index_file); fwrite(&(index[0]), sizeof(PatchInfo), size, index_file); + //TODO this should be moved to the end... + //BUT it will break compatibility with existing models. patches.WriteEntries(index_file); borders.WriteEntries(index_file); - + vector buffer; buffer.push_back(history.size()); for(unsigned int i = 0; i < history.size(); i++) { @@ -126,12 +144,11 @@ void Nexus::Close() { for(unsigned int e = 0; e < update.created.size(); e++) buffer.push_back(update.created[e]); } - + size = buffer.size(); fwrite(&size, sizeof(unsigned int), 1, index_file); fwrite(&(buffer[0]), sizeof(unsigned int), size, index_file); - - + fclose(index_file); index_file = NULL; } @@ -139,7 +156,7 @@ void Nexus::Close() { Patch &Nexus::GetPatch(unsigned int patch, bool flush) { assert(patch < index.size()); PatchInfo &info = index[patch]; - return patches.GetPatch(patch, info.nvert, info.nface, flush); + return patches.Lookup(patch, info.nvert, info.nface); } Border Nexus::GetBorder(unsigned int patch, bool flush) { @@ -180,111 +197,13 @@ unsigned int Nexus::AddPatch(unsigned int nvert, unsigned int nface, return index.size() -1; } -void Nexus::SetRamBufferSize(unsigned int r_size) { - patches.SetRamBufferSize(r_size); +void Nexus::MaxRamBuffer(unsigned int r_size) { + patches.MaxRamBuffer(r_size); + //TODO do the same with borders } -/*void Nexus::Join(const std::set &patches, - std::vector &newvert, - std::vector &newface, - std::vector &newbord) { - - map > remap; - set newborders; - set erased; - for(unsigned int u = 0; u < history.size(); u++) - for(unsigned int e = 0; e < history[u].erased.size(); e++) - erased.insert(history[u].erased[e]); - - set::const_iterator patch_idx; - for(patch_idx = patches.begin(); patch_idx != patches.end(); patch_idx++) { - unsigned int patch = *patch_idx; - PatchInfo &entry = index[patch]; - remap[patch].resize(entry.nvert, 0xffffffff); - } - - unsigned int vcount = 0; - unsigned int fcount = 0; - unsigned int bcount = 0; - for(patch_idx = patches.begin(); patch_idx != patches.end(); patch_idx++) { - unsigned int patch = *patch_idx; - vector &vmap = remap[patch]; - - PatchInfo &entry = index[patch]; - fcount += entry.nface; - for(unsigned int k = 0; k < entry.nvert; k++) { - if(vmap[k] == 0xffffffff) { //first time - vmap[k] = vcount++; - } - } - - Border border = GetBorder(patch); - for(unsigned int k = 0; k < border.Size(); k++) { - Link link = border[k]; - if(link.IsNull()) continue; - - assert(link.start_vert < entry.nvert); - assert(vmap[link.start_vert] != 0xffffffff); - - if(!remap.count(link.end_patch)) { //external - //test if erased in history... in wich case we do not add border - if(!erased.count(link.end_patch)) { - link.start_vert = vmap[link.start_vert]; - newborders.insert(link); - } - continue; - } - //internal - //TODO unsigned int &rmpv = remap[link.end_patch][link.end_vert]; - if(remap[link.end_patch][link.end_vert] == 0xffffffff) { //first time - remap[link.end_patch][link.end_vert] = vmap[link.start_vert]; - } - } - } - - - - newvert.resize(vcount); - newface.resize(fcount*3); - newbord.resize(0); - - fcount = 0; - for(patch_idx = patches.begin(); patch_idx != patches.end(); patch_idx++) { - Patch patch = GetPatch(*patch_idx); - - vector &vmap = remap[*patch_idx]; - assert(vmap.size() == patch.nv); - - for(unsigned int i = 0; i < vmap.size(); i++) { - assert(vmap[i] < vcount); - newvert[vmap[i]] = patch.Vert(i); - } - - for(unsigned int i = 0; i < patch.nf; i++) - for(int k = 0; k < 3; k++) { - //TODO remove this check. - if(patch.Face(i)[k] >= vmap.size()) { - cerr << "Face overflow: " << patch.Face(i)[k] << endl; - exit(0); - } - assert(patch.Face(i)[k] < vmap.size()); - newface[fcount++] = vmap[patch.Face(i)[k]]; - } - } - - assert(fcount == newface.size()); - - set::iterator b; - for(b = newborders.begin(); b != newborders.end(); b++) - newbord.push_back(*b); - - return; - }*/ - - void Nexus::Unify(float threshold) { //TODO what if colors or normals or strips? - //TODO update totvert unsigned int duplicated = 0; unsigned int degenerate = 0; diff --git a/apps/nexus/nexus.h b/apps/nexus/nexus.h index e157e402..eda64a5b 100644 --- a/apps/nexus/nexus.h +++ b/apps/nexus/nexus.h @@ -3,57 +3,23 @@ #include #include -#include -#include -#include "patchserver.h" +#include "nexusbase.h" +#include "lrupserver.h" #include "borderserver.h" namespace nxs { - -struct PatchInfo { - unsigned short nvert; - unsigned short nface; - - vcg::Sphere3f sphere; - float error; -}; - - - -class Nexus { +class Nexus: public NexusBase { public: - struct BorderEntry { - unsigned int border_start; //granuralita' Link - unsigned short border_size; //in Links - unsigned short border_used; //in Links - }; + Nexus() {} + ~Nexus(); - struct PatchInfo { - unsigned short nvert; - unsigned short nface; - - vcg::Sphere3f sphere; - float error; - }; - - - //TODO optimize to be vector with offset. - struct Update { - std::vector erased; - std::vector created; - }; - - - Nexus(); - virtual ~Nexus(); - bool Create(const std::string &filename, Signature signature, unsigned int chunk_size = 1024); - virtual bool Load(const std::string &filename, bool readonly = false); - virtual void Close(); + bool Load(const std::string &filename, bool readonly = false); + void Close(); unsigned int AddPatch(unsigned int nv, unsigned int nf, unsigned int nb); Patch &GetPatch(unsigned int patch, bool flush = true); @@ -67,12 +33,7 @@ class Nexus { bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; } bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; } - void SetRamBufferSize(unsigned int ram_size); - - /* void Join(const std::set &patches, - std::vector &vert, - std::vector &faces, - std::vector &links);*/ + void MaxRamBuffer(unsigned int ram_size); //move to nxsalgo! void Unify(float threshold = 0.0f); @@ -82,24 +43,24 @@ class Nexus { //BE CAREFUL: this 2 members get replicated into patchserver //TODO fix this nasty thing it is dangerous as it is. - Signature signature; - unsigned int chunk_size; + // Signature signature; + // unsigned int chunk_size; - unsigned int totvert; - unsigned int totface; - vcg::Sphere3f sphere; + // unsigned int totvert; + // unsigned int totface; + // vcg::Sphere3f sphere; - std::vector index; + // std::vector index; - PatchServer patches; + LruPServer patches; BorderServer borders; - std::vector history; + // std::vector history; - bool readonly; + // bool readonly; - private: - FILE *index_file; + // private: + // FILE *index_file; }; } diff --git a/apps/nexus/nexusbase.h b/apps/nexus/nexusbase.h new file mode 100644 index 00000000..0559aac9 --- /dev/null +++ b/apps/nexus/nexusbase.h @@ -0,0 +1,63 @@ +#ifndef NXS_NEXUS_BASE_H +#define NXS_NEXUS_BASE_H + +#include +#include + +#include "pserver.h" + +namespace nxs { + +struct PatchInfo { + unsigned short nvert; + unsigned short nface; + + vcg::Sphere3f sphere; + float error; +}; + + +class NexusBase { + public: + + //TODO optimize to be vector with offset. + struct Update { + std::vector erased; + std::vector created; + }; + + NexusBase(): index_file(NULL) {} + + // bool Create(const std::string &filename, Signature signature, + // unsigned int chunk_size = 1024); + // bool Load(const std::string &filename, bool readonly = false); + // void Close(); + + bool IsCompressed() { return (signature & NXS_COMPRESSED) != 0; } + bool HasStrips() { return (signature & NXS_STRIP) != 0; } + bool HasColors() { return (signature & NXS_COLORS) != 0; } + bool HasNormalsShort() { return (signature & NXS_NORMALS_SHORT) != 0; } + bool HasNormalsFloat() { return (signature & NXS_NORMALS_FLOAT) != 0; } + + + //BE CAREFUL: this 2 members get replicated into patchserver + //TODO fix this nasty thing it is dangerous as it is. + Signature signature; + unsigned int chunk_size; + + unsigned int totvert; + unsigned int totface; + vcg::Sphere3f sphere; + + std::vector index; + std::vector history; + + bool readonly; + + protected: + FILE *index_file; +}; + +} + +#endif diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index cd5deffe..0379ed66 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -48,28 +48,23 @@ float Metric::GetError(Frag &frag) { float FrustumMetric::GetError(unsigned int cell) { float max_error = 0; - Nexus::PatchInfo &entry = (*index)[cell]; + PatchInfo &entry = (*index)[cell]; Sphere3f &sphere = entry.sphere; float dist = Distance(sphere, frustum.ViewPoint()); if(dist < 0) return 1e20f; float error = entry.error/frustum.Resolution(dist); if(frustum.IsOutside(sphere.Center(), sphere.Radius())) - error /= 4; + error /= 256; return error; } -void Policy::Init() { - ram_used = 0; -} - -bool Policy::Expand(TNode &node) { +bool NexusMt::Expand(TNode &node) { //expand if node error > target error - if(ram_used >= ram_size) return false; - //cerr << "Error: " << error << " node.error: " << node.error << endl; - return node.error > error; + if(extraction_used >= extraction_max) return false; + return node.error > target_error; } -void Policy::NodeVisited(Node *node) { +void NexusMt::NodeVisited(Node *node) { //TODO write this a bit more elegant. //first we process arcs removed: @@ -77,11 +72,11 @@ void Policy::NodeVisited(Node *node) { assert(!(node->out[i]->visited)); Frag &frag = node->frags[i]; for(unsigned int k = 0; k < frag.size(); k++) { - PatchEntry &entry = (*entries)[frag[k]]; - ram_used += entry.ram_size; + PServer::Entry &entry = patches.entries[frag[k]]; + extraction_used += entry.ram_size; } } - + vector::iterator from; for(from = node->in.begin(); from != node->in.end(); from++) { assert((*from)->visited); @@ -90,59 +85,84 @@ void Policy::NodeVisited(Node *node) { if((*from)->out[i] == node) { vector &frag = frags[i]; for(unsigned int k = 0; k < frag.size(); k++) { - PatchEntry &entry = (*entries)[frag[k]]; - ram_used -= entry.ram_size; + PServer::Entry &entry = patches.entries[frag[k]]; + extraction_used -= entry.ram_size; } } } } } -Prefetch::Prefetch(): thread(true), nexus(NULL) {} - -Prefetch::~Prefetch() { signal(); waitfor(); } - -void Prefetch::execute() { - assert(nexus != NULL); - while(1) { - if(get_signaled()) return; - if(cells.size() == 0 || - nexus->patches.ram_used > nexus->patches.ram_size) { - relax(100); - continue; - } - cells_mx.lock(); - - pop_heap(cells.begin(), cells.end()); - unsigned int cell = cells.back(); - cells.pop_back(); - - patch_mx.lock(); - Patch &patch = nexus->GetPatch(cell, false); - patch_mx.unlock(); - - cells_mx.unlock(); - } -} - NexusMt::NexusMt(): vbo_mode(VBO_AUTO), - metric(NULL), mode(SMOOTH), prefetching(true) { + metric(NULL), mode(SMOOTH) { metric = new FrustumMetric(); metric->index = &index; - policy.error = 4; - policy.ram_size = 64000000; - - prefetch.nexus = this; + target_error = 4.0f; + extraction_max = 640000000; } -NexusMt::~NexusMt() {} +NexusMt::~NexusMt() { + if(metric) + delete metric; +} -bool NexusMt::Load(const string &filename, bool readonly) { - if(!Nexus::Load(filename, readonly)) return false; +bool NexusMt::Load(const string &filename) { + index_file = fopen((filename + ".nxs").c_str(), "rb+"); + if(!index_file) return false; + + unsigned int readed; + readed = fread(&signature, sizeof(unsigned int), 1, index_file); + if(!readed) return false; + readed = fread(&totvert, sizeof(unsigned int), 1, index_file); + if(!readed) return false; + readed = fread(&totface, sizeof(unsigned int), 1, index_file); + if(!readed) return false; + readed = fread(&sphere, sizeof(Sphere3f), 1, index_file); + if(!readed) return false; + readed = fread(&chunk_size, sizeof(unsigned int), 1, index_file); + if(!readed) return false; + + unsigned int size; //size of index + readed = fread(&size, sizeof(unsigned int), 1, index_file); + if(!readed) return false; + + index.resize(size); + readed = fread(&index[0], sizeof(PatchInfo), size, index_file); + if(readed != size) return false; + + patches.ReadEntries(index_file); + borders.ReadEntries(index_file); + + //history size; + fread(&size, sizeof(unsigned int), 1, index_file); + vector buffer; + buffer.resize(size); + fread(&(buffer[0]), sizeof(unsigned int), size, index_file); + + //number of history updates + size = buffer[0]; + history.resize(size); + + unsigned int pos = 1; + for(unsigned int i = 0; i < size; i++) { + unsigned int erased = buffer[pos++]; + unsigned int created = buffer[pos++]; + history[i].erased.resize(erased); + history[i].created.resize(created); + for(unsigned int e = 0; e < erased; e++) + history[i].erased[e] = buffer[pos++]; + for(unsigned int e = 0; e < created; e++) + history[i].created[e] = buffer[pos++]; + } + + fclose(index_file); + index_file = NULL; + + if(!patches.Load(filename + ".nxp", signature, chunk_size, true)) + return false; + LoadHistory(); - - policy.entries = &patches.patches; - + use_colors = false; use_normals = false; use_textures = false; @@ -153,10 +173,14 @@ bool NexusMt::Load(const string &filename, bool readonly) { SetComponent(TEXTURE, true); SetComponent(DATA, true); - SetPrefetching(prefetching); + SetPrefetchSize(patches.ram_max/2); return true; } +void NexusMt::Close() { + patches.Close(); +} + bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) { GLenum ret = glewInit(); if(ret != GLEW_OK) return false; @@ -164,26 +188,26 @@ bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) { cerr << "No vbo available!" << endl; vbo_mode = VBO_OFF; } - patches.vbo_size = vbosize / patches.chunk_size; - if(vbo_mode == VBO_OFF) - patches.vbo_size = 0; + patches.vbo_max = vbosize / chunk_size; + if(vbo_mode == VBO_OFF) + patches.vbo_max = 0; return true; } void NexusMt::Render() { - patches.Flush(); vector cells; metric->GetView(); - policy.Init(); - tri_total = 0; - tri_rendered = 0; - + Extract(cells); Draw(cells); } void NexusMt::Draw(vector &cells) { + + tri_total = 0; + tri_rendered = 0; + Frustumf frustum; frustum.GetView(); @@ -196,7 +220,7 @@ void NexusMt::Draw(vector &cells) { for(unsigned int i = 0; i < cells.size(); i++) { unsigned int cell = cells[i]; - Nexus::PatchInfo &entry = index[cell]; + PatchInfo &entry = index[cell]; tri_total += entry.nface; //frustum culling if(frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius())) @@ -204,21 +228,22 @@ void NexusMt::Draw(vector &cells) { tri_rendered += entry.nface; - Patch &patch = GetPatch(cell, false); + QueuePServer::Data &data = patches.Lookup(cell,entry.nvert,entry.nface, 0); + Patch &patch = *data.patch; char *fstart; char *vstart; char *cstart; char *nstart; if(vbo_mode != VBO_OFF) { - unsigned int vbo_array; - unsigned int vbo_element; - patches.GetVbo(cell, vbo_element, vbo_array); - assert(vbo_element); - assert(vbo_array); + // unsigned int vbo_array; + // unsigned int vbo_element; + // patches.GetVbo(cell, vbo_element, vbo_array); + assert(data.vbo_element); + assert(data.vbo_array); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_array); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo_element); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.vbo_element); fstart = NULL; vstart = NULL; @@ -281,8 +306,8 @@ void NexusMt::Draw(vector &cells) { glDisableClientState(GL_NORMAL_ARRAY); } -void NexusMt::SetRamExtractionSize(unsigned int r_size) { - policy.ram_size = r_size/patches.chunk_size; +void NexusMt::SetExtractionSize(unsigned int r_size) { + extraction_max = r_size/patches.chunk_size; } void NexusMt::SetMetric(NexusMt::MetricKind kind) { @@ -291,24 +316,15 @@ void NexusMt::SetMetric(NexusMt::MetricKind kind) { } void NexusMt::SetError(float error) { - policy.error = error; + target_error = error; } -void NexusMt::SetVboSize(unsigned int _vbo_size) { - patches.vbo_size = _vbo_size; +void NexusMt::SetVboSize(unsigned int _vbo_max) { + patches.vbo_max = _vbo_max; } -void NexusMt::SetPrefetching(bool on) { - if(on && prefetch.Running()) return; - if(!on && !prefetch.Running()) return; - if(on) { - prefetch.cells.clear(); - prefetch.start(); - } else { - prefetch.signal(); - prefetch.waitfor(); - } - prefetching = on; +void NexusMt::SetPrefetchSize(unsigned int size) { + //TODO do something reasonable with this. } bool NexusMt::SetMode(Mode _mode) { @@ -370,8 +386,8 @@ void NexusMt::LoadHistory() { for(unsigned int i = 0; i < (*u).created.size(); i++) { unsigned int cell = (*u).created[i]; if(index[cell].error > node.error) - node.error = index[cell].error; - + node.error = index[cell].error; + cell_node[cell] = current_node; } @@ -397,18 +413,18 @@ void NexusMt::LoadHistory() { vector &cells = (*e).second; vector::iterator k; for(k = cells.begin(); k != cells.end(); k++) { - unsigned int cell = (*k); + unsigned int cell = (*k); assert(cell < index.size()); - fr.push_back(cell); - if(index[cell].error > max_err) - max_err = index[cell].error; + fr.push_back(cell); + if(index[cell].error > max_err) + max_err = index[cell].error; } //Add the new Frag to the node. unsigned int floor_node = (*e).first; Node &oldnode = nodes[floor_node]; oldnode.frags.push_back(fr); if(node.error < max_err) - node.error = max_err; + node.error = max_err; //Update in and out of the nodes. node.in.push_back(&oldnode); @@ -454,10 +470,12 @@ void NexusMt::ClearHistory() { } */ void NexusMt::Extract(std::vector &selected) { + extraction_used = 0; + std::vector::iterator n; for(n = nodes.begin(); n != nodes.end(); n++) { (*n).visited = false; - (*n).pushed = false; + // (*n).pushed = false; } std::vector heap; @@ -472,7 +490,7 @@ void NexusMt::Extract(std::vector &selected) { Node *node = tnode.node; if(node->visited) continue; - bool expand = policy.Expand(tnode); + bool expand = Expand(tnode); if(expand) VisitNode(node, heap); @@ -539,13 +557,22 @@ void NexusMt::VisitNode(Node *node, vector &heap) { for(unsigned int k = 0; k < node->out.size(); k++) { Node *outnode = node->out[k]; - float error = metric->GetError(node->frags[k]); - // if(node->pushed) continue - heap.push_back(TNode(outnode, error)); + float max_error = 0; + + + for(unsigned int j = 0; j < node->frags[k].size(); j++) { + unsigned int patch = node->frags[k][j]; + float error = metric->GetError(patch); + if(max_error < error) max_error = error; + visited.push_back(PServer::Item(patch, fabs(error - target_error))); + // push_heap(visited.begin(), visited.end()); + } + + heap.push_back(TNode(outnode, max_error)); push_heap(heap.begin(), heap.end()); } node->visited = true; - policy.NodeVisited(node); + NodeVisited(node); } diff --git a/apps/nexus/nexusmt.h b/apps/nexus/nexusmt.h index fe17995e..316ac6bb 100644 --- a/apps/nexus/nexusmt.h +++ b/apps/nexus/nexusmt.h @@ -1,13 +1,15 @@ #ifndef NXS_NEXUS_MT_H #define NXS_NEXUS_MT_H - -#include "nexus.h" #include #include #include #include +#include "nexusbase.h" +#include "queuepserver.h" +#include "borderserver.h" +#include "prefetch.h" namespace nxs { @@ -19,7 +21,7 @@ namespace nxs { std::vector frags; float error; bool visited; - bool pushed; + // bool pushed; }; struct TNode { @@ -31,7 +33,7 @@ namespace nxs { class Metric { public: - vector *index; + std::vector *index; float GetError(Node *node); float GetError(Frag &frag); @@ -60,7 +62,7 @@ namespace nxs { float GetError(unsigned int cell); }; - class Policy { + /* class Policy { public: float error; int ram_used; @@ -71,27 +73,9 @@ namespace nxs { void Init(); bool Expand(TNode &node); void NodeVisited(Node *node); - }; + };*/ -class Prefetch: public pt::thread { - public: - Prefetch(); - ~Prefetch(); - void execute(); - void cleanup() {} - - bool Running() { return get_running(); } - - std::vector cells; - pt::mutex cells_mx; - pt::mutex patch_mx; - Nexus *nexus; -}; - -class NexusMt: public Nexus { - private: - std::vector nodes; - Prefetch prefetch; +class NexusMt: public NexusBase { public: //Vertex buffer object mode enum Vbo { VBO_AUTO, //autodetect best size @@ -118,10 +102,13 @@ class NexusMt: public Nexus { Vbo vbo_mode; Metric *metric; - Policy policy; + float target_error; + int extraction_max; + int extraction_used; + + Mode mode; - bool prefetching; unsigned int components; bool use_normals; @@ -132,31 +119,41 @@ class NexusMt: public Nexus { //statistics: unsigned int tri_rendered; unsigned int tri_total; - + + std::vector visited; + QueuePServer patches; + BorderServer borders; + NexusMt(); ~NexusMt(); - bool Load(const std::string &filename, bool readonly = true); - bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 0); + bool Load(const std::string &filename); + void Close(); + + bool InitGL(Vbo mode = VBO_AUTO, unsigned int vbo_size = 64000000); void Render(); void SetMetric(MetricKind kind); void SetError(float error); - void SetRamExtractionSize(unsigned int ram_size); + void SetExtractionSize(unsigned int ram_size); + void SetPrefetchSize(unsigned int size); void SetVboSize(unsigned int vbo_size); - void SetPrefetching(bool on); bool SetMode(Mode mode); bool SetComponent(Component c, bool on); bool SetComponents(unsigned int mask); - void Draw(std::vector &selected); void Extract(std::vector &selected); protected: + std::vector nodes; + + bool Expand(TNode &node); + void NodeVisited(Node *node); + void LoadHistory(); void ClearHistory(); void VisitNode(Node *node, std::vector &heap); diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index 0fa02ab8..e54e2bba 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.23 2004/12/01 18:46:21 ponchio +Microchanges. + Revision 1.22 2004/11/28 04:16:19 ponchio *** empty log message *** @@ -234,7 +237,7 @@ int main(int argc, char *argv[]) { unsigned int ram_size = 640000; nexus.SetError(error); - nexus.SetRamExtractionSize(ram_size); + nexus.SetExtractionSize(ram_size); nexus.SetMetric(NexusMt::FRUSTUM); if(!nexus.InitGL()) { cerr << "Could not init glew.\n"; @@ -271,16 +274,16 @@ int main(int argc, char *argv[]) { case SDLK_e: extract = !extract; break; case SDLK_c: show_colors = !show_colors; break; case SDLK_n: show_normals = !show_normals; break; - case SDLK_9: nexus.patches.ram_size *= 0.8f; break; - case SDLK_0: nexus.patches.ram_size *= 1.2f; break; + // case SDLK_9: nexus.patches->ram_size *= 0.8f; break; + // case SDLK_0: nexus.patches->ram_size *= 1.2f; break; case SDLK_LEFT: ram_size *= 0.7; - nexus.SetRamExtractionSize(ram_size); + nexus.SetExtractionSize(ram_size); cerr << "Max extraction ram size: " << ram_size << endl; break; case SDLK_RIGHT: ram_size *= 1.5; - nexus.SetRamExtractionSize(ram_size); + nexus.SetExtractionSize(ram_size); cerr << "Max extraction ram size: " << ram_size << endl; break; case SDLK_s: metric = NexusMt::FRUSTUM; break; @@ -388,17 +391,17 @@ int main(int argc, char *argv[]) { static vector cells; watch.Start(); if(extract) { - nexus.patches.Flush(); + // nexus.patches.Flush(); nexus.metric->GetView(); - nexus.policy.Init(); + // nexus.policy.Init(); nexus.tri_total = 0; nexus.tri_rendered = 0; nexus.Extract(cells); } nexus.Draw(cells); - if(show_borders) { + /* if(show_borders) { for(unsigned int i = 0; i < cells.size(); i++) { Border border = nexus.GetBorder(cells[i]); Patch &patch = nexus.GetPatch(cells[i]); @@ -413,7 +416,7 @@ int main(int argc, char *argv[]) { glEnd(); glPointSize(1); } - } + }*/ //cerr Do some reporting: if(show_statistics) { @@ -431,19 +434,19 @@ int main(int argc, char *argv[]) { char buffer[1024]; glColor3f(1.0f, 1.0f, 1.0f); - sprintf(buffer, "Ram size : %.3fMb (max) %.3fMb (cur)", - nexus.patches.ram_size * nexus.chunk_size/(float)(1<<20), - nexus.patches.ram_used * nexus.chunk_size/(float)(1<<20)); - gl_print(0.03, 0.12, buffer); + /* sprintf(buffer, "Ram size : %.3fMb (max) %.3fMb (cur)", + nexus.patches->ram_size * nexus.chunk_size/(float)(1<<20), + nexus.patches->ram_used * nexus.chunk_size/(float)(1<<20)); + gl_print(0.03, 0.12, buffer);*/ sprintf(buffer, "Extr size: %.3fMb(max) %.3fMb(cur)", - nexus.policy.ram_size * nexus.chunk_size/(float)(1<<20), - nexus.policy.ram_used * nexus.chunk_size/(float)(1<<20)); + nexus.extraction_max * nexus.chunk_size/(float)(1<<20), + nexus.extraction_used * nexus.chunk_size/(float)(1<<20)); gl_print(0.03, 0.09, buffer); - + sprintf(buffer, "Vbo size : %.3fMb(max) %.3fMb(cur)", - nexus.patches.vbo_size * nexus.chunk_size/(float)(1<<20), - nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20)); + nexus.patches.vbo_max * nexus.chunk_size/(float)(1<<20), + nexus.patches.vbo_used * nexus.chunk_size/(float)(1<<20)); gl_print(0.03, 0.06, buffer); sprintf(buffer, "Triangles: %.2fK (tot) %.2fK (vis) " diff --git a/apps/nexus/nxsbuilder.cpp b/apps/nexus/nxsbuilder.cpp index 2ee4edf0..caa6946e 100644 --- a/apps/nexus/nxsbuilder.cpp +++ b/apps/nexus/nxsbuilder.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.10 2004/12/09 22:33:28 ponchio +Different splitting optimization. + Revision 1.9 2004/12/04 13:22:55 ponchio *** empty log message *** @@ -282,7 +285,7 @@ void ThirdStep(const string &crudefile, const string &output, Nexus nexus; //TODO here i really need no ram_buffer..... - nexus.patches.SetRamBufferSize(0); + nexus.MaxRamBuffer(0); if(!nexus.Create(output, NXS_FACES, chunk_size)) { cerr << "Could not create nexus output: " << output << endl; getchar(); @@ -384,6 +387,7 @@ void ThirdStep(const string &crudefile, const string &output, cerr << "Could not save: " << output << ".rvi\n"; exit(0); } + nexus.Close(); } void FourthStep(const string &crudefile, const string &output, @@ -393,7 +397,7 @@ void FourthStep(const string &crudefile, const string &output, cerr << "Could not load nexus " << output << endl; exit(0); } - nexus.patches.SetRamBufferSize(ram_buffer); + nexus.MaxRamBuffer(ram_buffer); //TODO Clear borders in case of failure! VFile vert_remap; @@ -411,7 +415,7 @@ void FourthStep(const string &crudefile, const string &output, for(int start = 0; start < nexus.index.size(); start++) { report.Step(start); - Nexus::PatchInfo &s_entry = nexus.index[start]; + PatchInfo &s_entry = nexus.index[start]; vector links; #ifdef WIN32 @@ -427,7 +431,7 @@ void FourthStep(const string &crudefile, const string &output, for(int end = 0; end < nexus.index.size(); end++) { if(start == end) continue; - Nexus::PatchInfo &e_entry = nexus.index[end]; + PatchInfo &e_entry = nexus.index[end]; float dist = Distance(s_entry.sphere, e_entry.sphere); if(dist > s_entry.sphere.Radius() + e_entry.sphere.Radius()) { @@ -467,7 +471,7 @@ void FifthStep(const string &crudefile, const string &output, cerr << "Could not load nexus " << output << endl; exit(0); } - nexus.patches.SetRamBufferSize(ram_buffer); + nexus.MaxRamBuffer(ram_buffer); VChain vchain; if(!vchain.Load(output + ".vchain")) { @@ -482,7 +486,7 @@ void FifthStep(const string &crudefile, const string &output, } nexus.history.push_back(update); nexus.Unify(); - nexus.patches.FlushAll(); + nexus.patches.Flush(); Dispatcher dispatcher(&nexus, &vchain); @@ -752,7 +756,7 @@ void SaveFragment(Nexus &nexus, VChain &chain, patch.face.size()/3, bordsize); patch_levels.push_back(current_level); - Nexus::PatchInfo &entry = nexus.index[patch_idx]; + PatchInfo &entry = nexus.index[patch_idx]; entry.error = fragout.error; patch_remap[i] = patch_idx; @@ -780,7 +784,7 @@ void SaveFragment(Nexus &nexus, VChain &chain, memcpy(patch.VertBegin(), &outpatch.vert[0], outpatch.vert.size() * sizeof(Point3f)); - Nexus::PatchInfo &entry = nexus.index[patch_idx]; + PatchInfo &entry = nexus.index[patch_idx]; for(unsigned int v = 0; v < outpatch.vert.size(); v++) { entry.sphere.Add(outpatch.vert[v]); nexus.sphere.Add(outpatch.vert[v]); diff --git a/apps/nexus/nxsedit.cpp b/apps/nexus/nxsedit.cpp index fc0c04b2..435a6881 100644 --- a/apps/nexus/nxsedit.cpp +++ b/apps/nexus/nxsedit.cpp @@ -211,7 +211,7 @@ int main(int argc, char *argv[]) { Nexus nexus; - nexus.patches.SetRamBufferSize(ram_size); + nexus.MaxRamBuffer(ram_size); if(!nexus.Load(input, true)) { cerr << "Could not open nexus file: " << input << "\n"; return -1; @@ -312,7 +312,7 @@ int main(int argc, char *argv[]) { cout << "Writing to nexus: " << output << endl; Nexus out; - out.patches.SetRamBufferSize(ram_size); + out.MaxRamBuffer(ram_size); if(!chunk_size) chunk_size = nexus.patches.chunk_size; @@ -327,7 +327,7 @@ int main(int argc, char *argv[]) { cout << "Copying and allocating...\n"; for(unsigned int patch = 0; patch < nexus.index.size(); patch++) { report.Step(patch); - Nexus::PatchInfo &src_entry = nexus.index[patch]; + PatchInfo &src_entry = nexus.index[patch]; Patch src_patch = nexus.GetPatch(patch); Border src_border = nexus.GetBorder(patch); @@ -341,7 +341,7 @@ int main(int argc, char *argv[]) { out.AddPatch(src_entry.nvert, src_entry.nface, src_border.Available()); - Nexus::PatchInfo &dst_entry = out.index[patch]; + PatchInfo &dst_entry = out.index[patch]; Patch dst_patch = out.GetPatch(patch); diff --git a/apps/nexus/nxstest.cpp b/apps/nexus/nxstest.cpp index 0f693709..4ed759f7 100644 --- a/apps/nexus/nxstest.cpp +++ b/apps/nexus/nxstest.cpp @@ -20,7 +20,7 @@ int main(int argc, char *argv[]) { Report report(nexus.index.size()); for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) { report.Step(patchid); - Nexus::PatchInfo &info = nexus.index[patchid]; + PatchInfo &info = nexus.index[patchid]; Patch &patch = nexus.GetPatch(patchid); for(int f = 0; f < patch.nf; f++) { unsigned short *face = patch.Face(f); @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) { cerr << "Testing borders\n"; for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) { - Nexus::PatchInfo &info = nexus.index[patchid]; + PatchInfo &info = nexus.index[patchid]; Border border = nexus.GetBorder(patchid); for(unsigned int i = 0; i < border.Size(); i++) { Link &link = border[i]; @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) { cerr << "Reciprocity borders test\n"; for(unsigned int patchid = 0; patchid < nexus.index.size(); patchid++) { - Nexus::PatchInfo &info = nexus.index[patchid]; + PatchInfo &info = nexus.index[patchid]; Border border = nexus.GetBorder(patchid); vector links; links.resize(border.Size()); @@ -125,4 +125,4 @@ int main(int argc, char *argv[]) { } return 0; -} \ No newline at end of file +} diff --git a/apps/nexus/prefetch.cpp b/apps/nexus/prefetch.cpp new file mode 100644 index 00000000..fa390fd1 --- /dev/null +++ b/apps/nexus/prefetch.cpp @@ -0,0 +1,56 @@ +#include "prefetch.h" + +using namespace std; +using namespace nxs; + + +void Prefetch::init(NexusMt *m, std::vector &selected, + std::vector &visited) { + safety.lock(); + mt = m; + missing.clear(); + + std::map tmp; + for(unsigned int i = 0; i < selected.size(); i++) { + unsigned int patch = selected[i]; + tmp[patch] = 0.0f; + missing.push_back(PServer::Item(patch, 0.0f)); + } + for(unsigned int i = 0; i < visited.size(); i++) { + PServer::Item &item = visited[i]; + if(tmp.count(item.patch)) continue; + if(mt->patches.IsLoaded(item.patch)) + tmp[item.patch] = item.priority; + else + missing.push_back(item); + } + + QueuePServer &ps = mt->patches; + for(unsigned int i = 0; i < ps.heap.size(); i++) { + PServer::Item &item = ps.heap[i]; + if(tmp.count(item.patch)) + item.priority = tmp[item.patch]; + else + item.priority = 1e40; + } + make_heap(ps.heap.begin(), ps.heap.end()); + sort(missing.begin(), missing.end()); //CRITICAL reverse pero'! + reverse(missing.begin(), missing.end()); + safety.unlock(); +} + +void Prefetch::execute() { + while(1) { + if(get_signaled()) return; + while(1) { + safety.lock(); + if(missing.size() == 0) break; + PServer::Item item = missing.back(); + missing.pop_back(); + PatchInfo &info = mt->index[item.patch]; + mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority); + safety.unlock(); + } + relax(50); + } +} diff --git a/apps/nexus/prefetch.h b/apps/nexus/prefetch.h new file mode 100644 index 00000000..da51e4fe --- /dev/null +++ b/apps/nexus/prefetch.h @@ -0,0 +1,41 @@ +#ifndef NXS_PREFETCH_H +#define NXS_PREFETCH_H + +#include +#include +#include + +#include + +#include "nexusmt.h" +#include "queuepserver.h" + +namespace nxs { + +class NexusMt; + +class Prefetch: public pt::thread{ + public: + + pt::mutex safety; + unsigned int ram_max; + unsigned int ram_used; + + NexusMt *mt; + std::vector missing; + + + Prefetch(): thread(false) {} + ~Prefetch() { + waitfor(); + } + + void init(NexusMt *m, + std::vector &selected, + std::vector &visited); + void execute(); + void cleanup() {} +}; + +} +#endif diff --git a/apps/nexus/pserver.cpp b/apps/nexus/pserver.cpp new file mode 100644 index 00000000..b0003b0f --- /dev/null +++ b/apps/nexus/pserver.cpp @@ -0,0 +1,158 @@ +#include +#include "pserver.h" + +using namespace std; +using namespace nxs; + + +bool PServer::Create(const std::string &filename, + Signature sig, + unsigned int csize, + unsigned int rsize) { + signature = sig; + chunk_size = csize; + + ram_max = rsize/chunk_size + 1; + ram_used = 0; + + ram_readed = 0; + ram_flushed = 0; + + return MFile::Create(filename); +} + +bool PServer::Load(const std::string &filename, Signature sig, + unsigned int csize, bool readonly, + unsigned int rsize) { + + signature = sig; + chunk_size = csize; + + ram_max = rsize/chunk_size + 1; + ram_used = 0; + + ram_readed = 0; + ram_flushed = 0; + + return MFile::Load(filename, readonly); +} + +void PServer::Close() { + Flush(); + MFile::Close(); +} + +//TODO add error checking. +bool PServer::ReadEntries(FILE *fp) { + unsigned int n; + fread(&n, 1, sizeof(int), fp); + entries.resize(n); + for(unsigned int i = 0; i < n; i++) { + fread(&(entries[i].patch_start), 1, sizeof(unsigned int), fp); + fread(&(entries[i].ram_size), 1, sizeof(unsigned short), fp); + fread(&(entries[i].disk_size), 1, sizeof(unsigned short), fp); + } + return true; +} + +bool PServer::WriteEntries(FILE *fp) { + unsigned int n = entries.size(); + fwrite(&n, 1, sizeof(int), fp); + for(unsigned int i = 0; i < entries.size(); i++) { + fwrite(&(entries[i].patch_start), 1, sizeof(unsigned int), fp); + fwrite(&(entries[i].ram_size), 1, sizeof(unsigned short), fp); + fwrite(&(entries[i].disk_size), 1, sizeof(unsigned short), fp); + } + return true; +} + +void PServer::AddPatch(unsigned short nvert, unsigned short nface) { + Entry entry; + entry.patch_start = 0xffffffff; + entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size); + entry.disk_size = 0xffff; + entries.push_back(entry); +} + +Patch *PServer::LoadPatch(unsigned int idx, + unsigned short nvert, unsigned short nface) { + + // ramlock.rdlock(); + + assert(idx < entries.size()); + Entry &entry = entries[idx]; + + char *ram = new char[entry.ram_size * chunk_size]; +#ifdef CONTROLS + if(!ram) { + cerr << "COuld not allocate ram!\n"; + exit(0); + } +#endif + + Patch *patch = new Patch(signature, ram, nvert, nface); + + if(entry.patch_start != 0xffffffff) { //was allocated. + assert(entry.disk_size != 0xffff); + + SetPosition((int64)entry.patch_start * (int64)chunk_size); + + if((signature & NXS_COMPRESSED) == 0) { //not compressed + ReadBuffer(ram, entry.disk_size * chunk_size); + } else { + unsigned char *disk = new unsigned char[entry.disk_size * chunk_size]; + ReadBuffer(disk, entry.disk_size * chunk_size); + + patch->Decompress(entry.ram_size * chunk_size, + disk, entry.disk_size * chunk_size); + delete []disk; + } + } + ram_used += entry.ram_size; + ram_readed += entry.ram_size; + + return patch; +} + +void PServer::FlushPatch(unsigned int id, Patch *patch) { + + Entry &entry = entries[id]; + + if(!readonly) { //write back patch + if((signature & NXS_COMPRESSED)) { + unsigned int compressed_size; + char *compressed = patch->Compress(entry.ram_size * chunk_size, + compressed_size); + if(entry.disk_size == 0xffff) {//allocate space + assert(entry.patch_start == 0xffffffff); + entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1; + entry.patch_start = (unsigned int)(Length()/chunk_size); + Redim(Length() + entry.disk_size * chunk_size); + } else { + //cerr << "OOOOPSPPPS not supported!" << endl; + exit(-1); + } + SetPosition((int64)entry.patch_start * (int64)chunk_size); + WriteBuffer(compressed, entry.disk_size * chunk_size); + delete []compressed; + } else { + if(entry.disk_size == 0xffff) { + entry.disk_size = entry.ram_size; + entry.patch_start = (unsigned int)(Length()/chunk_size); + Redim(Length() + entry.disk_size * chunk_size); + } + SetPosition((int64)entry.patch_start * (int64)chunk_size); + WriteBuffer(patch->start, entry.disk_size * chunk_size); + } + } + + delete [](patch->start); + delete patch; + + ram_used -= entry.ram_size; + ram_flushed += entry.ram_size; +} + +void PServer::MaxRamBuffer(unsigned int r_buffer) { + ram_max = (unsigned int)(r_buffer/chunk_size) + 1; +} diff --git a/apps/nexus/pserver.h b/apps/nexus/pserver.h new file mode 100644 index 00000000..329840b6 --- /dev/null +++ b/apps/nexus/pserver.h @@ -0,0 +1,93 @@ +#ifndef NXS_PSERVER_H +#define NXS_PSERVER_H + +#include +#include +#include +#include "patch.h" +#include "mfile.h" + +namespace nxs { + +class PServer: public MFile { + public: + + struct Entry { + unsigned int patch_start; //granularita' Chunk + unsigned short ram_size; //in chunks + unsigned short disk_size; // in chunks (used when compressed) + }; + + /* struct Data { + // unsigned int npatch; + Patch *patch; + unsigned int vbo_array; + unsigned int vbo_element; + Data(): patch(NULL), vbo_array(0), vbo_element(0) {} + };*/ + + struct Item { //used by lru and pqueue. + unsigned int patch; + float priority; + Item(unsigned int p, float f): patch(p), priority(f) {} + bool operator<(const Item &i) const { + return priority < i.priority; + } + }; + + + + Signature signature; + unsigned int chunk_size; + + unsigned int ram_max; + unsigned int ram_used; + + //statistics: + unsigned int ram_readed; + unsigned int ram_flushed; + + //pt::rwlock ramlock; //read only thread safety... + //pt::rwlock disklock; //read only thread safety... + + std::vector entries; + + + + PServer(): chunk_size(1024), + ram_max(128000000), + ram_used(0) {} + virtual ~PServer() { + std::cerr << "Closing pserver" << std::endl; + MFile::Close(); + } + + bool Create(const std::string &filename, Signature signature, + unsigned int chunk_size, unsigned int ram_max = 128000000); + bool Load(const std::string &filename, Signature sig, + unsigned int chunk_size, bool readonly, + unsigned int ram_max = 128000000); + + bool ReadEntries(FILE *fp); + bool WriteEntries(FILE *fp); + virtual void Close(); + + void AddPatch(unsigned short nvert, unsigned short nface); + Patch *LoadPatch(unsigned int id, unsigned short nv, unsigned short nf); + void FlushPatch(unsigned int id, Patch *patch); + + virtual bool IsLoaded(unsigned int patch) = 0; + // virtual Patch &Lookup(unsigned int patch, + // unsigned short nv, unsigned short nf) = 0; + virtual void Flush() = 0; + + void MaxRamBuffer(unsigned int ram_buffer); + + //void GetVbo(unsigned int patch, unsigned int &elem, unsigned int &array); + //bool FlushVbo(unsigned int patch, Data &data); + //void MaxVboBuffer(unsigned int ram_buffer); +}; + + +}//namespace +#endif diff --git a/apps/nexus/queuepserver.cpp b/apps/nexus/queuepserver.cpp new file mode 100644 index 00000000..65f7f2a4 --- /dev/null +++ b/apps/nexus/queuepserver.cpp @@ -0,0 +1,85 @@ +#include + +#include "queuepserver.h" + +using namespace std; +using namespace nxs; + + +QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, + unsigned short nv, unsigned short nf, + float priority) { + if(index.count(patch)) { + return index[patch]; + } else { + while(ram_used > ram_max) { + pop_heap(heap.begin(), heap.end()); + Item item = heap.back(); + if(item.priority == 0) break; //no deleting needed patches. + Data &data = index[patch]; + FlushVbo(data); + FlushPatch(patch, data.patch); + index.erase(patch); + } + Item item(patch, priority); + heap.push_back(item); + push_heap(heap.begin(), heap.end()); + Data &data = index[patch]; + data.patch = LoadPatch(patch, nv, nf); + LoadVbo(data); + return data; + } +} + +bool QueuePServer::IsLoaded(unsigned int patch) { + return index.count(patch); +} +void QueuePServer::Flush() { + std::map::iterator i; + for(i = index.begin(); i != index.end(); i++) { + FlushVbo((*i).second); + FlushPatch((*i).first, (*i).second.patch); + } +} + +void QueuePServer::LoadVbo(Data &data) { + if(!vbo_max) return; + Patch &patch = *data.patch; + glGenBuffersARB(1, &data.vbo_element); + assert(data.vbo_element); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, data.vbo_element); + + unsigned int size = patch.nf * sizeof(unsigned short); + if((signature & NXS_FACES) != 0) size *= 3; + + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, patch.FaceBegin(), + GL_STATIC_DRAW_ARB); + vbo_used += size; + + //TODO fix this when we allow data :p + size = sizeof(float) * patch.dstart; + + glGenBuffersARB(1, &data.vbo_array); + assert(data.vbo_array); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, data.vbo_array); + + glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(), + GL_STATIC_DRAW_ARB); + + vbo_used += size; +} +void QueuePServer::FlushVbo(Data &data) { + if(!vbo_max) return; + assert(data.vbo_element); + assert(data.vbo_array); + glDeleteBuffersARB(1, &data.vbo_element); + glDeleteBuffersARB(1, &data.vbo_array); + data.vbo_element = 0; + data.vbo_array = 0; + + Patch &patch = *data.patch; + vbo_used -= patch.nf * sizeof(unsigned short); + vbo_used -= sizeof(float) * patch.dstart; +} + + diff --git a/apps/nexus/queuepserver.h b/apps/nexus/queuepserver.h new file mode 100644 index 00000000..e9b262fa --- /dev/null +++ b/apps/nexus/queuepserver.h @@ -0,0 +1,42 @@ +#ifndef NXS_QUEUE_PSERVER_H +#define NXS_QUEUE_PSERVER_H + +#include +#include +#include + +#include "pserver.h" + +namespace nxs { + +class QueuePServer: public PServer { + public: + + struct Data { + Patch *patch; + unsigned int vbo_array; + unsigned int vbo_element; + Data(): patch(NULL), vbo_array(0), vbo_element(0) {} + }; + + unsigned int vbo_used; + unsigned int vbo_max; + + std::map index; + std::vector heap; + + Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf, + float priority = 0.0f); + + bool IsLoaded(unsigned int patch); + void Flush(); + + protected: + + void LoadVbo(Data &data); + void FlushVbo(Data &data); +}; + +} + +#endif