Patch cache -> heap
This commit is contained in:
parent
85242ce7c8
commit
25f4c94ebf
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<bool> visited;
|
||||
std::vector<HeapNode> heap;
|
||||
std::vector<unsigned int> selected;
|
||||
std::map<unsigned int, float> errors;
|
||||
|
||||
std::vector<Item> selected;
|
||||
unsigned int draw_size; //first in selected should be drawn
|
||||
|
||||
std::vector<HeapNode> heap; //no realtime extraxtion
|
||||
|
||||
//nodes that i can expand to
|
||||
std::vector<HeapNode> front;
|
||||
//nodes that i can contract
|
||||
|
|
|
@ -43,7 +43,6 @@ class File {
|
|||
bool IsReadOnly() { return readonly; }
|
||||
|
||||
static void Delete(const std::string &filename);
|
||||
protected:
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE fp;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#ifndef WIN32
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
|
@ -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<unsigned int> skipped;
|
||||
vector<Item> 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<unsigned int>::iterator i = skipped.begin();
|
||||
i != skipped.end(); i++) {
|
||||
GetPatch(*i);
|
||||
Draw(*i, contest);
|
||||
for(vector<Item>::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)
|
||||
|
|
|
@ -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<Item> heap;
|
||||
|
||||
void FlushPatch(unsigned int id);
|
||||
void LoadVbo(Entry &entry);
|
||||
void FlushVbo(Entry &entry);
|
||||
|
|
|
@ -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 <apps/nexus/nexusmt.h>
|
||||
#ifdef WIN32
|
||||
#include <wrap/system/getopt.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
@ -149,6 +155,7 @@ using namespace std;
|
|||
#include <wrap/gui/trackball.h>
|
||||
#include "watch.h"
|
||||
|
||||
#include <apps/nexus/nexusmt.h>
|
||||
|
||||
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] << " <nexus file>\n";
|
||||
if(argc < 2) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <ptypes/pasync.h>
|
||||
|
||||
#include "extraction.h"
|
||||
|
||||
namespace nxs {
|
||||
|
||||
class NexusMt;
|
||||
|
@ -19,19 +21,24 @@ class Preload: public pt::thread{
|
|||
pt::mutex lock;
|
||||
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() {
|
||||
waitfor();
|
||||
}
|
||||
|
||||
void execute();
|
||||
|
||||
void post(std::vector<unsigned int> &patches) {
|
||||
void post(std::vector<Item> &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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue