Patch cache -> heap

This commit is contained in:
Federico Ponchio 2005-02-03 12:35:01 +00:00
parent 85242ce7c8
commit 25f4c94ebf
8 changed files with 184 additions and 56 deletions

View File

@ -50,6 +50,7 @@ void Extraction::Extract(NexusMt *_mt) {
void Extraction::Init() { void Extraction::Init() {
front.clear(); front.clear();
back.clear(); back.clear();
errors.clear();
Cost cost; Cost cost;
@ -69,6 +70,7 @@ void Extraction::Init() {
for(Link::iterator k = link.begin(); k != link.end(); k++) { for(Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch; unsigned int patch = (*k).patch;
Entry &entry = (*mt)[patch]; Entry &entry = (*mt)[patch];
float error = metric->GetError(entry); float error = metric->GetError(entry);
if(error > maxerror) maxerror = error; if(error > maxerror) maxerror = error;
@ -189,11 +191,12 @@ void Extraction::Update(NexusMt *_mt) {
HeapNode hnode = front.back(); HeapNode hnode = front.back();
Node *node = hnode.node; Node *node = hnode.node;
front.pop_back(); front.pop_back();
Node::iterator i; Node::iterator l;
for(i = node->out_begin(); i != node->out_end(); i++) { for(l = node->out_begin(); l != node->out_end(); l++) {
Link &link = (*i); Link &link = (*l);
for(Link::iterator k = link.begin(); k != link.end(); k++) { 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()) { } else if(back.size()) {
@ -201,11 +204,12 @@ void Extraction::Update(NexusMt *_mt) {
HeapNode hnode = back.back(); HeapNode hnode = back.back();
Node *node = hnode.node; Node *node = hnode.node;
back.pop_back(); back.pop_back();
Node::iterator i; Node::iterator l;
for(i = node->in_begin(); i != node->in_end(); i++) { for(l = node->in_begin(); l != node->in_end(); l++) {
Link &link = (*i); Link &link = (*l);
for(Link::iterator k = link.begin(); k != link.end(); k++) { 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; Link &link = *n;
for(Link::iterator k = link.begin(); k != link.end(); k++) { for(Link::iterator k = link.begin(); k != link.end(); k++) {
unsigned int patch = (*k).patch; unsigned int patch = (*k).patch;
selected.push_back(patch); selected.push_back(Item(patch,0));
errors[patch] = 0.0f;
} }
} }
} }

View File

@ -13,6 +13,15 @@ namespace nxs {
class Metric; class Metric;
class NexusMt; 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 { class Extraction {
public: public:
typedef History::Node Node; typedef History::Node Node;
@ -46,10 +55,13 @@ class Extraction {
unsigned int disk_used, disk_max; unsigned int disk_used, disk_max;
std::vector<bool> visited; std::vector<bool> visited;
std::vector<HeapNode> heap; std::map<unsigned int, float> errors;
std::vector<unsigned int> selected;
std::vector<Item> selected;
unsigned int draw_size; //first in selected should be drawn unsigned int draw_size; //first in selected should be drawn
std::vector<HeapNode> heap; //no realtime extraxtion
//nodes that i can expand to //nodes that i can expand to
std::vector<HeapNode> front; std::vector<HeapNode> front;
//nodes that i can contract //nodes that i can contract

View File

@ -43,7 +43,6 @@ class File {
bool IsReadOnly() { return readonly; } bool IsReadOnly() { return readonly; }
static void Delete(const std::string &filename); static void Delete(const std::string &filename);
protected:
#ifdef WIN32 #ifdef WIN32
HANDLE fp; HANDLE fp;

View File

@ -1,3 +1,7 @@
#ifndef WIN32
#include <fcntl.h>
#endif
#include <map> #include <map>
#include <queue> #include <queue>
@ -45,6 +49,15 @@ bool NexusMt::Load(const string &filename) {
if(!Nexus::Load(filename, true)) return false; if(!Nexus::Load(filename, true)) return false;
if(!history.IsQuick() && !history.UpdatesToQuick()) if(!history.IsQuick() && !history.UpdatesToQuick())
return false; 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; return true;
} }
@ -72,6 +85,15 @@ void NexusMt::Render(Extraction &extraction, DrawContest &contest,
Stats *stats) { Stats *stats) {
if(stats) stats->Init(); 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); preload.post(extraction.selected);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
@ -80,10 +102,10 @@ void NexusMt::Render(Extraction &extraction, DrawContest &contest,
if((signature & NXS_NORMALS_SHORT) && (contest.attrs & DrawContest::NORMAL)) if((signature & NXS_NORMALS_SHORT) && (contest.attrs & DrawContest::NORMAL))
glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_NORMAL_ARRAY);
vector<unsigned int> skipped; vector<Item> skipped;
for(unsigned int i = 0; i < extraction.draw_size; i++) { 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); Entry &entry = operator[](patch);
vcg::Sphere3f &sphere = entry.sphere; vcg::Sphere3f &sphere = entry.sphere;
if(extraction.frustum.IsOutside(sphere.Center(), sphere.Radius())) 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(stats) stats->ktri += entry.nface;
if(!entry.patch) { if(!entry.patch) {
skipped.push_back(patch); skipped.push_back(extraction.selected[i]);
continue; continue;
} }
Draw(patch, contest); Draw(patch, contest);
} }
preload.trigger.reset();
preload.lock.enter(); preload.lock.enter();
if(skipped.size()) cerr << "Skipped: " << skipped.size() << endl; if(skipped.size()) cerr << "Skipped: " << skipped.size() << endl;
for(vector<unsigned int>::iterator i = skipped.begin(); for(vector<Item>::iterator i = skipped.begin(); i != skipped.end(); i++) {
i != skipped.end(); i++) { GetPatch((*i).id, (*i).error);
GetPatch(*i); Draw((*i).id, contest);
Draw(*i, contest);
} }
Flush(false); //in case there are no skipped... :P Flush(false); //in case there are no skipped... :P
preload.trigger.post();
preload.lock.leave(); preload.lock.leave();
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_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) { void NexusMt::FlushPatch(unsigned int id) {
Entry &entry = operator[](id); Entry &entry = operator[](id);
if(entry.vbo_element) if(entry.vbo_element)

View File

@ -67,7 +67,12 @@ namespace nxs {
void SetPreload(bool on); void SetPreload(bool on);
void Flush(bool all = true);
Patch &GetPatch(unsigned int patch, float error, bool flush = true);
bool CanAdd(Item &item);
protected: protected:
std::vector<Item> heap;
void FlushPatch(unsigned int id); void FlushPatch(unsigned int id);
void LoadVbo(Entry &entry); void LoadVbo(Entry &entry);
void FlushVbo(Entry &entry); void FlushVbo(Entry &entry);

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $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 Revision 1.30 2005/01/21 17:09:13 ponchio
Porting and debug. Porting and debug.
@ -130,8 +133,11 @@ Created
****************************************************************************/ ****************************************************************************/
#ifdef WIN32
#include <apps/nexus/nexusmt.h> #include <wrap/system/getopt.h>
#else
#include <unistd.h>
#endif
#include <iostream> #include <iostream>
using namespace std; using namespace std;
@ -149,6 +155,7 @@ using namespace std;
#include <wrap/gui/trackball.h> #include <wrap/gui/trackball.h>
#include "watch.h" #include "watch.h"
#include <apps/nexus/nexusmt.h>
using namespace vcg; using namespace vcg;
using namespace nxs; using namespace nxs;
@ -207,8 +214,13 @@ int main(int argc, char *argv[]) {
Trackball track; Trackball track;
if(argc != 2) { if(argc < 2) {
cerr << "Usage: " << argv[0] << " <nexus file>\n"; cerr << "Usage: " << argv[0] << " <nexus file> [options]\n";
cerr << "-e <error>: set initial target error\n"
<< "-m <ram>: max ram used\n"
<< "-x <ram>: max extraction size\n"
<< "-r <ram>: max draw size\n"
<< "-d <ram>: max disk read per frame\n";
return -1; return -1;
} }
@ -228,30 +240,6 @@ int main(int argc, char *argv[]) {
return -1; 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 rotate = false;
bool show_borders = false; bool show_borders = false;
@ -263,6 +251,41 @@ int main(int argc, char *argv[]) {
bool preload = true; bool preload = true;
bool step = 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()) { if(!nexus.InitGL()) {
cerr << "Could not init glew.\n"; cerr << "Could not init glew.\n";
} }

View File

@ -8,17 +8,24 @@ using namespace nxs;
void Preload::execute() { void Preload::execute() {
assert(mt); assert(mt);
while(!get_signaled()) { while(!get_signaled()) {
trigger.wait();
lock.enter(); lock.enter();
while(!queue.size()) { while(!queue.size()) {
trigger.reset();
lock.leave(); lock.leave();
trigger.wait(); trigger.wait();
lock.enter(); lock.enter();
} }
//TODO check we are not loading too much memory! //TODO check we are not loading too much memory!
assert(queue.size()); assert(queue.size());
unsigned int patch = queue.back(); Item &item = queue.back();
mt->GetPatch(patch, false); 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(); queue.pop_back();
} else
queue.clear();
lock.leave(); lock.leave();
} }
} }

View File

@ -7,6 +7,8 @@
#include <ptypes/pasync.h> #include <ptypes/pasync.h>
#include "extraction.h"
namespace nxs { namespace nxs {
class NexusMt; class NexusMt;
@ -19,19 +21,24 @@ class Preload: public pt::thread{
pt::mutex lock; pt::mutex lock;
pt::trigger trigger; pt::trigger trigger;
std::vector<unsigned int> queue; std::vector<Item> queue;
Preload(): thread(false), trigger(true, false) {} Preload(): thread(false), trigger(false, false) {}
~Preload() { ~Preload() {
waitfor(); waitfor();
} }
void execute(); void execute();
void post(std::vector<unsigned int> &patches) { void post(std::vector<Item> &patches) {
trigger.reset();
lock.enter(); lock.enter();
queue.reserve(patches.size());
for(int i = patches.size() -1; i >= 0; i--)
queue.push_back(patches[i]);
trigger.post(); trigger.post();
queue = patches;
lock.leave(); lock.leave();
} }