Patch cache -> heap
This commit is contained in:
parent
85242ce7c8
commit
25f4c94ebf
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue