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() {
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;
}
}
}

View File

@ -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

View File

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

View File

@ -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)

View File

@ -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);

View File

@ -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";
}

View File

@ -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();
}
}

View File

@ -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();
}