From 25f4c94ebfcbdc16818df1e9881b3336ac883f71 Mon Sep 17 00:00:00 2001 From: ponchio Date: Thu, 3 Feb 2005 12:35:01 +0000 Subject: [PATCH] Patch cache -> heap --- apps/nexus/extraction.cpp | 23 +++++++---- apps/nexus/extraction.h | 16 +++++++- apps/nexus/file.h | 1 - apps/nexus/nexusmt.cpp | 86 +++++++++++++++++++++++++++++++++++---- apps/nexus/nexusmt.h | 7 +++- apps/nexus/nexusview.cpp | 79 ++++++++++++++++++++++------------- apps/nexus/preload.cpp | 13 ++++-- apps/nexus/preload.h | 15 +++++-- 8 files changed, 184 insertions(+), 56 deletions(-) diff --git a/apps/nexus/extraction.cpp b/apps/nexus/extraction.cpp index b723dba0..96d6131b 100644 --- a/apps/nexus/extraction.cpp +++ b/apps/nexus/extraction.cpp @@ -50,6 +50,7 @@ void Extraction::Extract(NexusMt *_mt) { void Extraction::Init() { front.clear(); back.clear(); + errors.clear(); Cost cost; @@ -69,6 +70,7 @@ void Extraction::Init() { for(Link::iterator k = link.begin(); k != link.end(); k++) { unsigned int patch = (*k).patch; Entry &entry = (*mt)[patch]; + float error = metric->GetError(entry); if(error > maxerror) maxerror = error; @@ -189,11 +191,12 @@ void Extraction::Update(NexusMt *_mt) { HeapNode hnode = front.back(); Node *node = hnode.node; front.pop_back(); - Node::iterator i; - for(i = node->out_begin(); i != node->out_end(); i++) { - Link &link = (*i); + Node::iterator l; + for(l = node->out_begin(); l != node->out_end(); l++) { + Link &link = (*l); for(Link::iterator k = link.begin(); k != link.end(); k++) { - selected.push_back((*k).patch); + selected.push_back(Item((*k).patch, i)); + errors[(*k).patch] = i; } } } else if(back.size()) { @@ -201,11 +204,12 @@ void Extraction::Update(NexusMt *_mt) { HeapNode hnode = back.back(); Node *node = hnode.node; back.pop_back(); - Node::iterator i; - for(i = node->in_begin(); i != node->in_end(); i++) { - Link &link = (*i); + Node::iterator l; + for(l = node->in_begin(); l != node->in_end(); l++) { + Link &link = (*l); for(Link::iterator k = link.begin(); k != link.end(); k++) { - selected.push_back((*k).patch); + selected.push_back(Item((*k).patch, i)); + errors[(*k).patch] = i; } } } @@ -344,7 +348,8 @@ void Extraction::Select() { Link &link = *n; for(Link::iterator k = link.begin(); k != link.end(); k++) { unsigned int patch = (*k).patch; - selected.push_back(patch); + selected.push_back(Item(patch,0)); + errors[patch] = 0.0f; } } } diff --git a/apps/nexus/extraction.h b/apps/nexus/extraction.h index a5cfa846..9919c48c 100644 --- a/apps/nexus/extraction.h +++ b/apps/nexus/extraction.h @@ -13,6 +13,15 @@ namespace nxs { class Metric; class NexusMt; +struct Item { + float error; + unsigned int id; + Item(unsigned int i = 0, float e = 0): id(i), error(e) {} + bool operator<(const Item &item) const { + return error < item.error; + } +}; + class Extraction { public: typedef History::Node Node; @@ -46,10 +55,13 @@ class Extraction { unsigned int disk_used, disk_max; std::vector visited; - std::vector heap; - std::vector selected; + std::map errors; + + std::vector selected; unsigned int draw_size; //first in selected should be drawn + std::vector heap; //no realtime extraxtion + //nodes that i can expand to std::vector front; //nodes that i can contract diff --git a/apps/nexus/file.h b/apps/nexus/file.h index c654ecbd..e13a3a00 100644 --- a/apps/nexus/file.h +++ b/apps/nexus/file.h @@ -43,7 +43,6 @@ class File { bool IsReadOnly() { return readonly; } static void Delete(const std::string &filename); - protected: #ifdef WIN32 HANDLE fp; diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index d15914cf..699f0b6b 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -1,3 +1,7 @@ +#ifndef WIN32 +#include +#endif + #include #include @@ -45,6 +49,15 @@ bool NexusMt::Load(const string &filename) { if(!Nexus::Load(filename, true)) return false; if(!history.IsQuick() && !history.UpdatesToQuick()) return false; + +#ifndef WIN32 + //i will read data only once usually. + // for(unsigned int i = 0; i < files.size(); i++) { + // int fd = fileno(files[i]->fp); + // posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE); + // } + +#endif return true; } @@ -72,6 +85,15 @@ void NexusMt::Render(Extraction &extraction, DrawContest &contest, Stats *stats) { if(stats) stats->Init(); + for(unsigned int i = 0; i < heap.size(); i++) { + Item &item = heap[i]; + if(!extraction.errors.count(item.id)) { + item.error = 1e20; + } else + item.error = extraction.errors[item.id]; + } + make_heap(heap.begin(), heap.end()); + preload.post(extraction.selected); glEnableClientState(GL_VERTEX_ARRAY); @@ -80,10 +102,10 @@ void NexusMt::Render(Extraction &extraction, DrawContest &contest, if((signature & NXS_NORMALS_SHORT) && (contest.attrs & DrawContest::NORMAL)) glEnableClientState(GL_NORMAL_ARRAY); - vector skipped; + vector skipped; for(unsigned int i = 0; i < extraction.draw_size; i++) { - unsigned int patch = extraction.selected[i]; + unsigned int patch = extraction.selected[i].id; Entry &entry = operator[](patch); vcg::Sphere3f &sphere = entry.sphere; if(extraction.frustum.IsOutside(sphere.Center(), sphere.Radius())) @@ -92,23 +114,28 @@ void NexusMt::Render(Extraction &extraction, DrawContest &contest, if(stats) stats->ktri += entry.nface; if(!entry.patch) { - skipped.push_back(patch); + skipped.push_back(extraction.selected[i]); continue; } - Draw(patch, contest); } + + preload.trigger.reset(); preload.lock.enter(); + if(skipped.size()) cerr << "Skipped: " << skipped.size() << endl; - for(vector::iterator i = skipped.begin(); - i != skipped.end(); i++) { - GetPatch(*i); - Draw(*i, contest); + for(vector::iterator i = skipped.begin(); i != skipped.end(); i++) { + GetPatch((*i).id, (*i).error); + Draw((*i).id, contest); } Flush(false); //in case there are no skipped... :P + + preload.trigger.post(); preload.lock.leave(); + + glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); @@ -192,6 +219,49 @@ void NexusMt::Draw(unsigned int cell, DrawContest &contest) { } } +Patch &NexusMt::GetPatch(unsigned int patch, float error, bool flush) { + Entry &entry = operator[](patch); + if(entry.patch) return *(entry.patch); + + while(flush && ram_used > ram_max) { + if(heap[0].error == 0) break; + unsigned int to_flush = heap[0].id; + pop_heap(heap.begin(), heap.end()); + heap.pop_back(); + FlushPatch(to_flush); + } + entry.patch = LoadPatch(patch); + heap.push_back(Item(patch, error)); + push_heap(heap.begin(), heap.end()); + return *(entry.patch); +} + +void NexusMt::Flush(bool all) { + if(all) { + for(unsigned int i = 0; i < heap.size(); i++) { + unsigned int patch = heap[i].id; + FlushPatch(patch); + } + heap.clear(); + } else { + while(heap.size() && ram_used > ram_max) { + if(heap[0].error == 0) break; + unsigned int to_flush = heap[0].id; + pop_heap(heap.begin(), heap.end()); + heap.pop_back(); + FlushPatch(to_flush); + } + } +} + +bool NexusMt::CanAdd(Item &item) { + if(!heap.size()) return true; + Entry &entry = operator[](item.id); + if(ram_used + entry.ram_size < ram_max) + return true; + return heap[0].error > item.error; +} + void NexusMt::FlushPatch(unsigned int id) { Entry &entry = operator[](id); if(entry.vbo_element) diff --git a/apps/nexus/nexusmt.h b/apps/nexus/nexusmt.h index a04e48c9..73889860 100644 --- a/apps/nexus/nexusmt.h +++ b/apps/nexus/nexusmt.h @@ -42,7 +42,7 @@ namespace nxs { Stats(): count(0) {} void Init(); }; - + class NexusMt: public Nexus { public: bool use_vbo; @@ -67,7 +67,12 @@ namespace nxs { void SetPreload(bool on); + void Flush(bool all = true); + Patch &GetPatch(unsigned int patch, float error, bool flush = true); + bool CanAdd(Item &item); protected: + std::vector heap; + void FlushPatch(unsigned int id); void LoadVbo(Entry &entry); void FlushVbo(Entry &entry); diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index 37868f0a..e1cd6094 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.31 2005/02/01 16:42:30 ponchio +Trigger + Revision 1.30 2005/01/21 17:09:13 ponchio Porting and debug. @@ -130,8 +133,11 @@ Created ****************************************************************************/ - -#include +#ifdef WIN32 +#include +#else +#include +#endif #include using namespace std; @@ -149,6 +155,7 @@ using namespace std; #include #include "watch.h" +#include using namespace vcg; using namespace nxs; @@ -207,8 +214,13 @@ int main(int argc, char *argv[]) { Trackball track; - if(argc != 2) { - cerr << "Usage: " << argv[0] << " \n"; + if(argc < 2) { + cerr << "Usage: " << argv[0] << " [options]\n"; + cerr << "-e : set initial target error\n" + << "-m : max ram used\n" + << "-x : max extraction size\n" + << "-r : max draw size\n" + << "-d : max disk read per frame\n"; return -1; } @@ -227,32 +239,8 @@ int main(int argc, char *argv[]) { cerr << "Could not init SDL window\n"; return -1; } - - // FrustumPolicy frustum_policy; - cerr << "Commands: \n" - " q: quit\n" - " s: screen error extraction\n" - " g: geometry error extraction\n" - - " t: show statistics\n" - " b: increase memory buffer\n" - " B: decrease memory buffer\n" - - " d: debug mode (show patches colored)\n" - " f: flas shading mode\n" - " m: smooth mode\n" - " p: draw points\n" - - " c: show colors\n" - " n: show normals\n" - " u: rotate model\n" - " -: decrease error\n" - " +: increase error (= too)\n"; - - Watch watch; - bool rotate = false; bool show_borders = false; bool show_colors = true; @@ -263,6 +251,41 @@ int main(int argc, char *argv[]) { bool preload = true; bool step = true; + int option; + while((option = getopt(argc, argv, "e:m:x:r:d:")) != EOF) { + switch(option) { + case 'e': extraction.target_error = atof(optarg); break; + case 'm': nexus.MaxRam() = atoi(optarg); break; + case 'x': extraction.extr_max = atoi(optarg); break; + case 'r': extraction.draw_max = atoi(optarg); break; + case 'd': extraction.disk_max = atoi(optarg); break; + default: + cerr << "Unknow option.\n"; break; + } + } + + + // FrustumPolicy frustum_policy; + + cerr << "Commands: \n" + " q: quit\n" + " t: toggle statistics\n" + " b: increase memory buffer\n" + " B: decrease memory buffer\n" + + " d: debug mode (show patches colored)\n" + " f: flat shading mode\n" + " m: smooth mode\n" + " p: draw points\n" + + " c: show colors\n" + " n: show normals\n" + " r: rotate model\n" + " -: decrease error\n" + " +: increase error (= too)\n"; + + Watch watch; + if(!nexus.InitGL()) { cerr << "Could not init glew.\n"; } diff --git a/apps/nexus/preload.cpp b/apps/nexus/preload.cpp index d8b6c49c..036fac82 100644 --- a/apps/nexus/preload.cpp +++ b/apps/nexus/preload.cpp @@ -8,17 +8,24 @@ using namespace nxs; void Preload::execute() { assert(mt); while(!get_signaled()) { + trigger.wait(); lock.enter(); while(!queue.size()) { + trigger.reset(); lock.leave(); trigger.wait(); lock.enter(); } //TODO check we are not loading too much memory! assert(queue.size()); - unsigned int patch = queue.back(); - mt->GetPatch(patch, false); - queue.pop_back(); + Item &item = queue.back(); + if(item.error == 0 || mt->CanAdd(item)) { + //we cannot flush since we are not in the openGL thread + //and flushing includes VBO buffer flushing also. + mt->GetPatch(item.id, item.error, false); + queue.pop_back(); + } else + queue.clear(); lock.leave(); } } diff --git a/apps/nexus/preload.h b/apps/nexus/preload.h index f4be85ba..31c1d1af 100644 --- a/apps/nexus/preload.h +++ b/apps/nexus/preload.h @@ -7,6 +7,8 @@ #include +#include "extraction.h" + namespace nxs { class NexusMt; @@ -19,19 +21,24 @@ class Preload: public pt::thread{ pt::mutex lock; pt::trigger trigger; - std::vector queue; + std::vector queue; - Preload(): thread(false), trigger(true, false) {} + Preload(): thread(false), trigger(false, false) {} ~Preload() { waitfor(); } void execute(); - void post(std::vector &patches) { + void post(std::vector &patches) { + trigger.reset(); lock.enter(); + + queue.reserve(patches.size()); + for(int i = patches.size() -1; i >= 0; i--) + queue.push_back(patches[i]); + trigger.post(); - queue = patches; lock.leave(); }