Optimizing realtime vis.

This commit is contained in:
Federico Ponchio 2004-12-15 08:46:16 +00:00
parent 7fb2c4b831
commit e8c748d159
9 changed files with 421 additions and 238 deletions

View File

@ -57,14 +57,17 @@ float FrustumMetric::GetError(unsigned int cell) {
if(dist < 0) return 1e20f; if(dist < 0) return 1e20f;
float error = entry.error/frustum.Resolution(dist); float error = entry.error/frustum.Resolution(dist);
if(frustum.IsOutside(sphere.Center(), sphere.Radius())) if(frustum.IsOutside(sphere.Center(), sphere.Radius()))
error /= 256; error /= 32;
return error; return error;
} }
bool NexusMt::Expand(TNode &node) { bool NexusMt::Expand(TNode &tnode) {
//expand if node error > target error //expand if node error > target error
if(extraction_used >= extraction_max) return false; if(extraction_used >= extraction_max) return false;
return node.error > target_error; if(draw_used >= draw_max) return false;
if(disk_used >= disk_max) return false;
return tnode.error > target_error;
} }
void NexusMt::NodeVisited(Node *node) { void NexusMt::NodeVisited(Node *node) {
@ -75,8 +78,15 @@ void NexusMt::NodeVisited(Node *node) {
assert(!(node->out[i]->visited)); assert(!(node->out[i]->visited));
Frag &frag = node->frags[i]; Frag &frag = node->frags[i];
for(unsigned int k = 0; k < frag.size(); k++) { for(unsigned int k = 0; k < frag.size(); k++) {
PServer::Entry &entry = patches.entries[frag[k]]; unsigned int patch = frag[k];
extraction_used += entry.ram_size; PServer::Entry &entry = patches.entries[patch];
unsigned int ram_size = entry.ram_size;
extraction_used += ram_size;
PatchInfo &info = index[patch];
if(!frustum.IsOutside(info.sphere.Center(), info.sphere.Radius()))
draw_used += ram_size;
if(!patches.entries[patch].patch)
disk_used += ram_size;
} }
} }
@ -88,8 +98,14 @@ void NexusMt::NodeVisited(Node *node) {
if((*from)->out[i] == node) { if((*from)->out[i] == node) {
vector<unsigned int> &frag = frags[i]; vector<unsigned int> &frag = frags[i];
for(unsigned int k = 0; k < frag.size(); k++) { for(unsigned int k = 0; k < frag.size(); k++) {
PServer::Entry &entry = patches.entries[frag[k]]; unsigned int patch = frag[k];
extraction_used -= entry.ram_size; PServer::Entry &entry = patches.entries[patch];
extraction_used -= entry.ram_size;
PatchInfo &info = index[patch];
if(!frustum.IsOutside(info.sphere.Center(), info.sphere.Radius()))
draw_used -= entry.ram_size;
if(!patches.entries[patch].patch)
disk_used -= entry.ram_size;
} }
} }
} }
@ -101,7 +117,10 @@ NexusMt::NexusMt(): vbo_mode(VBO_AUTO),
metric = new FrustumMetric(); metric = new FrustumMetric();
metric->index = &index; metric->index = &index;
target_error = 4.0f; target_error = 4.0f;
extraction_max = 640000000; extraction_max = 64000000000;
draw_max = 12000; //1M triangles (ZSN)
disk_max = 300;
} }
NexusMt::~NexusMt() { NexusMt::~NexusMt() {
@ -180,7 +199,7 @@ bool NexusMt::Load(const string &filename) {
SetPrefetchSize(patches.ram_max/2); SetPrefetchSize(patches.ram_max/2);
cerr << "Start!\n"; cerr << "Start!\n";
prefetch.start();
cerr << "Started\n"; cerr << "Started\n";
return true; return true;
} }
@ -199,6 +218,8 @@ bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) {
patches.vbo_max = vbosize / chunk_size; patches.vbo_max = vbosize / chunk_size;
if(vbo_mode == VBO_OFF) if(vbo_mode == VBO_OFF)
patches.vbo_max = 0; patches.vbo_max = 0;
prefetch.start();
return true; return true;
} }
@ -212,13 +233,23 @@ void NexusMt::Render() {
} }
void NexusMt::Draw(vector<unsigned int> &cells) { void NexusMt::Draw(vector<unsigned int> &cells) {
prefetch.init(this, cells, visited);
tri_total = 0; tri_total = 0;
tri_rendered = 0; tri_rendered = 0;
Frustumf frustum;
frustum.GetView(); frustum.GetView();
vector<unsigned int> draw;
for(unsigned int i = 0; i < cells.size(); i++) {
PatchInfo &entry = index[cells[i]];
tri_total += entry.nface;
if(!frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius())) {
draw.push_back(cells[i]);
tri_rendered += entry.nface;
}
}
prefetch.init(this, draw, visited);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
if(use_colors) if(use_colors)
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
@ -226,37 +257,36 @@ void NexusMt::Draw(vector<unsigned int> &cells) {
glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_NORMAL_ARRAY);
//TODO textures and data. //TODO textures and data.
unsigned int count = cells.size(); unsigned int count = draw.size();
while(count) { while(count > 0 || prefetch.draw.get_count()) {
// cerr << "Getting message: " << count << endl; if(todraw.size()) {
pt::message *msg = patches.queue.getmessage(); QueuePServer::Data *data = todraw.back();
QueuePServer::Data *data = (QueuePServer::Data *)(msg->param); todraw.pop_back();
if(msg->id == QueuePServer::FLUSH) { Draw((unsigned int)(data->patch), *data);
// cerr << "Flush...\n"; } else {
if(data->vbo_element) { // cerr << "Getting message: " << count << endl;
glDeleteBuffersARB(1, &(data->vbo_element)); pt::message *msg = prefetch.draw.getmessage();
glDeleteBuffersARB(1, &(data->vbo_array)); QueuePServer::Data *data = (QueuePServer::Data *)(msg->param);
if(msg->id == QueuePServer::FLUSH) {
if(data->vbo_element) {
glDeleteBuffersARB(1, &(data->vbo_element));
glDeleteBuffersARB(1, &(data->vbo_array));
}
delete data;
delete msg;
continue;
} }
delete data;
if(msg->id != QueuePServer::DRAW) {
cerr << "Unknown message!\n";
continue;
}
unsigned int cell = msg->result;
Draw(cell, *data);
delete msg; delete msg;
continue;
} }
if(msg->id != QueuePServer::DRAW) {
cerr << "Unknown message!\n";
continue;
}
unsigned int cell = msg->result;
PatchInfo &entry = index[cell];
tri_total += entry.nface;
//frustum culling
if(!frustum.IsOutside(entry.sphere.Center(), entry.sphere.Radius())) {
tri_rendered += entry.nface;
Draw(cell, *data);
}
delete msg;
count--; count--;
} }
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
@ -455,7 +485,7 @@ void NexusMt::LoadHistory() {
Node &oldnode = nodes[floor_node]; Node &oldnode = nodes[floor_node];
oldnode.frags.push_back(fr); oldnode.frags.push_back(fr);
if(node.error < max_err) if(node.error < max_err)
node.error = max_err; node.error = max_err;
//Update in and out of the nodes. //Update in and out of the nodes.
node.in.push_back(&oldnode); node.in.push_back(&oldnode);
@ -502,18 +532,24 @@ void NexusMt::ClearHistory() {
void NexusMt::Extract(std::vector<unsigned int> &selected) { void NexusMt::Extract(std::vector<unsigned int> &selected) {
extraction_used = 0; extraction_used = 0;
draw_used = 0;
disk_used = 0;
visited.clear(); visited.clear();
float bestcost = -1;
int best = -1;
float cost = 0;
std::vector<Node>::iterator n; std::vector<Node>::iterator n;
for(n = nodes.begin(); n != nodes.end(); n++) { for(n = nodes.begin(); n != nodes.end(); n++)
(*n).visited = false; (*n).visited = false;
// (*n).pushed = false;
}
std::vector<TNode> heap; std::vector<TNode> heap;
Node *root = &nodes[0]; Node *root = &nodes[0];
VisitNode(root, heap); VisitNode(root, heap);
sequence.clear();
//vector<Node *> sequence;
while(heap.size()) { while(heap.size()) {
pop_heap(heap.begin(), heap.end()); pop_heap(heap.begin(), heap.end());
TNode tnode = heap.back(); TNode tnode = heap.back();
@ -524,9 +560,40 @@ void NexusMt::Extract(std::vector<unsigned int> &selected) {
bool expand = Expand(tnode); bool expand = Expand(tnode);
if(expand) if(expand) //{
VisitNode(node, heap); VisitNode(node, heap);
/* float cost = disk_used * 100;
if(draw_used > draw_max)
cost += 1 * (draw_used - draw_max);
if(tnode.error > target_error)
cost += 1000 * (tnode.error - target_error) * (tnode.error - target_error);
if(best == -1 || cost < bestcost) {
bestcost = cost;
best = sequence.size();
}
} */
} }
//cerr << "best: " << best << " tot: " << sequence.size() << endl;
/*for(n = nodes.begin(); n != nodes.end(); n++)
(*n).visited = false;
for(unsigned int i = 0; i < best; i++) {
Node *node = sequence[i];
node->visited = true;
for(unsigned int n = 0; n < node->out.size(); n++) {
Node *outnode = node->out[n];
for(unsigned int k = 0; k < outnode->frags.size(); k++) {
for(unsigned int j = 0; j < outnode->frags[k].size(); j++) {
unsigned int patch = outnode->frags[k][j];
float error = metric->GetError(patch);
visited.push_back(PServer::Item(patch, fabs(error - target_error)));
}
}
}
} */
Select(selected); Select(selected);
} }
@ -556,7 +623,7 @@ void NexusMt::Extract(std::vector<unsigned int> &selected) {
} }
} }
Select(selected); Select(selected);
}*/ } */
void NexusMt::Select(vector<unsigned int> &selected) { void NexusMt::Select(vector<unsigned int> &selected) {
selected.clear(); selected.clear();
@ -579,18 +646,38 @@ void NexusMt::Select(vector<unsigned int> &selected) {
} }
} }
} }
/*bool NexusMt::TestCurrent(Node *node) {
if(!visited) return;
for(unsigned int i = 0; i < node->out.size(); i++)
if(!node->out[k].visited) {
node->current = true;
return true;
}
node->current = false;
return false;
} */
void NexusMt::VisitNode(Node *node, vector<TNode> &heap) { void NexusMt::VisitNode(Node *node, vector<TNode> &heap) {
if(node->visited) return; //TestCurrent(*i);
if(node->visited) return;
node->visited = true;
vector<Node *>::iterator i; vector<Node *>::iterator i;
for(i = node->in.begin(); i != node->in.end(); i++) for(i = node->in.begin(); i != node->in.end(); i++) {
VisitNode(*i, heap); VisitNode(*i, heap);
}
for(unsigned int k = 0; k < node->out.size(); k++) { for(unsigned int k = 0; k < node->out.size(); k++) {
Node *outnode = node->out[k]; Node *outnode = node->out[k];
float max_error = 0; float max_error = metric->GetError(outnode);
/* for(unsigned int j = 0; j < node->frags[k].size(); j++) {
unsigned int patch = node->frags[k][j];
PServer::Entry &entry = patches.entries[patch];
if(!entry.patch)
max_error /= 2;
}*/
for(unsigned int j = 0; j < node->frags[k].size(); j++) { for(unsigned int j = 0; j < node->frags[k].size(); j++) {
unsigned int patch = node->frags[k][j]; unsigned int patch = node->frags[k][j];
@ -598,13 +685,23 @@ void NexusMt::VisitNode(Node *node, vector<TNode> &heap) {
if(max_error < error) max_error = error; if(max_error < error) max_error = error;
visited.push_back(PServer::Item(patch, fabs(error - target_error))); visited.push_back(PServer::Item(patch, fabs(error - target_error)));
// push_heap(visited.begin(), visited.end()); // push_heap(visited.begin(), visited.end());
} }
heap.push_back(TNode(outnode, max_error)); heap.push_back(TNode(outnode, max_error));
push_heap(heap.begin(), heap.end()); push_heap(heap.begin(), heap.end());
} }
node->visited = true; sequence.push_back(node);
NodeVisited(node); NodeVisited(node);
} }
/*void NexusMt::UnvisitNode(Node *node, vector<TNode> &heap) {
node->current = false;
vector<Node *>::iterator i;
for(i = node->in.begin(); i != node->in.end(); i++)
if(TestCurrent(*i)) {
float error = metric->GetError(*i);
heap.push_back(TNode(*i, error));
push_heap(heap.begin(), heap.end());
}
} */

View File

@ -19,7 +19,8 @@ namespace nxs {
std::vector<Node *> out; std::vector<Node *> out;
std::vector<Frag> frags; std::vector<Frag> frags;
float error; float error;
bool visited; bool visited;
bool current;
// bool pushed; // bool pushed;
}; };
@ -102,9 +103,15 @@ class NexusMt: public NexusBase {
Metric *metric; Metric *metric;
float target_error; float target_error;
int extraction_max; vcg::Frustumf frustum;
int extraction_used;
unsigned int extraction_max; //total extraxtion (even culled parts)
unsigned int extraction_used;
unsigned int draw_max; //only visible parts
unsigned int draw_used;
unsigned int disk_max; //max not in ram loadable size
unsigned int disk_used;
Mode mode; Mode mode;
@ -119,7 +126,9 @@ class NexusMt: public NexusBase {
unsigned int tri_rendered; unsigned int tri_rendered;
unsigned int tri_total; unsigned int tri_total;
vector<QueuePServer::Data *> todraw;
std::vector<PServer::Item> visited; std::vector<PServer::Item> visited;
std::vector<Node *> sequence;
QueuePServer patches; QueuePServer patches;
BorderServer borders; BorderServer borders;
@ -160,6 +169,7 @@ class NexusMt: public NexusBase {
void LoadHistory(); void LoadHistory();
void ClearHistory(); void ClearHistory();
void VisitNode(Node *node, std::vector<TNode> &heap); void VisitNode(Node *node, std::vector<TNode> &heap);
void UnvisitNode(Node *node, std::vector<TNode> &heap);
void Select(std::vector<unsigned int> &selected); void Select(std::vector<unsigned int> &selected);
Patch &LoadPatch(unsigned int p); Patch &LoadPatch(unsigned int p);
}; };

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.24 2004/12/13 00:44:48 ponchio
Lotsa changes...
Revision 1.23 2004/12/01 18:46:21 ponchio Revision 1.23 2004/12/01 18:46:21 ponchio
Microchanges. Microchanges.
@ -209,14 +212,17 @@ int main(int argc, char *argv[]) {
" q: quit\n" " q: quit\n"
" s: screen error extraction\n" " s: screen error extraction\n"
" g: geometry error extraction\n" " g: geometry error extraction\n"
" p: draw points\n"
" t: show statistics\n" " t: show statistics\n"
" r: toggle realtime mode (TODO)\n"
" b: increase memory buffer\n" " b: increase memory buffer\n"
" B: decrease memory buffer\n" " B: decrease memory buffer\n"
" d: debug mode (show patches colored)\n" " d: debug mode (show patches colored)\n"
" f: flas shading mode\n" " f: flas shading mode\n"
" m: smooth mode\n" " m: smooth mode\n"
" p: draw points\n"
" c: show colors\n" " c: show colors\n"
" n: show normals\n" " n: show normals\n"
" u: rotate model\n" " u: rotate model\n"
@ -233,11 +239,9 @@ int main(int argc, char *argv[]) {
bool extract = true; bool extract = true;
NexusMt::MetricKind metric; NexusMt::MetricKind metric;
NexusMt::Mode mode = NexusMt::SMOOTH; NexusMt::Mode mode = NexusMt::SMOOTH;
unsigned int ram_size = 640000;
nexus.SetError(error); nexus.SetError(error);
nexus.SetExtractionSize(ram_size);
nexus.SetMetric(NexusMt::FRUSTUM); nexus.SetMetric(NexusMt::FRUSTUM);
if(!nexus.InitGL()) { if(!nexus.InitGL()) {
cerr << "Could not init glew.\n"; cerr << "Could not init glew.\n";
@ -256,100 +260,99 @@ int main(int argc, char *argv[]) {
bool redraw = false; bool redraw = false;
float fps = 0; float fps = 0;
float tframe = 0; float tframe = 0;
bool keepdrawing = true;
while( !quit ) { while( !quit ) {
bool first = true; unsigned int anything = SDL_PollEvent(&event);
SDL_WaitEvent(&event); if(!anything && !keepdrawing) {
while( first || SDL_PollEvent( &event ) ){ SDL_WaitEvent(&event);
first = false; anything = true;
switch( event.type ) { }
case SDL_QUIT: quit = 1; break; if(anything) {
case SDL_KEYDOWN: switch( event.type ) {
switch(event.key.keysym.sym) { case SDL_QUIT: quit = 1; break;
case SDLK_RCTRL: case SDL_KEYDOWN:
case SDLK_LCTRL: switch(event.key.keysym.sym) {
track.ButtonDown(Trackball::KEY_CTRL); break; case SDLK_RCTRL:
case SDLK_q: exit(0); break; case SDLK_LCTRL: track.ButtonDown(Trackball::KEY_CTRL); break;
case SDLK_b: show_borders = !show_borders; break; case SDLK_q: exit(0); break;
case SDLK_e: extract = !extract; break; case SDLK_k: keepdrawing = !keepdrawing; break;
case SDLK_c: show_colors = !show_colors; break; case SDLK_e: extract = !extract; break;
case SDLK_n: show_normals = !show_normals; break; case SDLK_c: show_colors = !show_colors; break;
// case SDLK_9: nexus.patches->ram_size *= 0.8f; break; case SDLK_n: show_normals = !show_normals; break;
// case SDLK_0: nexus.patches->ram_size *= 1.2f; break;
case SDLK_LEFT: nexus.extraction_max *= 0.7; break;
case SDLK_LEFT: case SDLK_RIGHT: nexus.extraction_max *= 1.5; break;
ram_size *= 0.7; case SDLK_UP: nexus.draw_max *= 1.5; break;
nexus.SetExtractionSize(ram_size); case SDLK_DOWN: nexus.draw_max *= 0.7; break;
cerr << "Max extraction ram size: " << ram_size << endl; break; case SDLK_PAGEUP: nexus.disk_max *= 1.5; break;
case SDLK_RIGHT: case SDLK_PAGEDOWN: nexus.disk_max *= 0.7; break;
ram_size *= 1.5;
nexus.SetExtractionSize(ram_size);
cerr << "Max extraction ram size: " << ram_size << endl; break;
case SDLK_s: metric = NexusMt::FRUSTUM; break; case SDLK_s: metric = NexusMt::FRUSTUM; break;
case SDLK_p: mode = NexusMt::POINTS; nexus.SetMode(mode); break; case SDLK_p: mode = NexusMt::POINTS; nexus.SetMode(mode); break;
case SDLK_d: mode = NexusMt::PATCHES; nexus.SetMode(mode); break; case SDLK_d: mode = NexusMt::PATCHES; nexus.SetMode(mode); break;
case SDLK_f: mode = NexusMt::FLAT; nexus.SetMode(mode); break; case SDLK_f: mode = NexusMt::FLAT; nexus.SetMode(mode); break;
case SDLK_m: mode = NexusMt::SMOOTH; nexus.SetMode(mode); break; case SDLK_m: mode = NexusMt::SMOOTH; nexus.SetMode(mode); break;
case SDLK_r: case SDLK_r:
case SDLK_SPACE: rotate = !rotate; break; case SDLK_SPACE: rotate = !rotate; break;
case SDLK_MINUS: case SDLK_MINUS:
error *= 0.9f; error *= 0.9f;
nexus.SetError(error); nexus.SetError(error);
cerr << "Error: " << error << endl; break; cerr << "Error: " << error << endl; break;
case SDLK_EQUALS: case SDLK_EQUALS:
case SDLK_PLUS: case SDLK_PLUS:
error *= 1.1f; error *= 1.1f;
nexus.SetError(error); nexus.SetError(error);
cerr << "Error: " << error << endl; break; cerr << "Error: " << error << endl; break;
} }
break; break;
case SDL_KEYUP: case SDL_KEYUP:
switch(event.key.keysym.sym) { switch(event.key.keysym.sym) {
case SDLK_RCTRL: case SDLK_RCTRL:
case SDLK_LCTRL: case SDLK_LCTRL:
track.ButtonUp(Trackball::KEY_CTRL); break; track.ButtonUp(Trackball::KEY_CTRL); break;
} }
break; break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
x = event.button.x; x = event.button.x;
y = height - event.button.y; y = height - event.button.y;
#ifdef SDL_BUTTON_WHEELUP #ifdef SDL_BUTTON_WHEELUP
if(event.button.button == SDL_BUTTON_WHEELUP) if(event.button.button == SDL_BUTTON_WHEELUP)
track.MouseWheel(1); track.MouseWheel(1);
else if(event.button.button == SDL_BUTTON_WHEELDOWN) else if(event.button.button == SDL_BUTTON_WHEELDOWN)
track.MouseWheel(-1); track.MouseWheel(-1);
else else
#endif #endif
if(event.button.button == SDL_BUTTON_LEFT) if(event.button.button == SDL_BUTTON_LEFT)
track.MouseDown(x, y, Trackball::BUTTON_LEFT); track.MouseDown(x, y, Trackball::BUTTON_LEFT);
else if(event.button.button == SDL_BUTTON_RIGHT) else if(event.button.button == SDL_BUTTON_RIGHT)
track.MouseDown(x, y, Trackball::BUTTON_RIGHT); track.MouseDown(x, y, Trackball::BUTTON_RIGHT);
break; break;
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
x = event.button.x; x = event.button.x;
y = height - event.button.y; y = height - event.button.y;
if(event.button.button == SDL_BUTTON_LEFT) if(event.button.button == SDL_BUTTON_LEFT)
track.MouseUp(x, y, Trackball::BUTTON_LEFT); track.MouseUp(x, y, Trackball::BUTTON_LEFT);
else if(event.button.button == SDL_BUTTON_RIGHT) else if(event.button.button == SDL_BUTTON_RIGHT)
track.MouseUp(x, y, Trackball::BUTTON_RIGHT); track.MouseUp(x, y, Trackball::BUTTON_RIGHT);
break; break;
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)); while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK));
x = event.motion.x; x = event.motion.x;
y = height - event.motion.y; y = height - event.motion.y;
track.MouseMove(x, y); track.MouseMove(x, y);
break; break;
case SDL_VIDEOEXPOSE: case SDL_VIDEOEXPOSE:
default: break; default: break;
}
} }
redraw = true; redraw = true;
}
if(!redraw) continue; //if(!redraw && !keepdrawing) continue;
redraw = false; redraw = false;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@ -363,9 +366,11 @@ int main(int argc, char *argv[]) {
if(rotate) { if(rotate) {
alpha++; alpha++;
if(alpha > 360) alpha = 0; if(alpha > 360) alpha = 0;
SDL_Event redraw; if(!keepdrawing) {
redraw.type = SDL_VIDEOEXPOSE; SDL_Event redraw;
SDL_PushEvent(&redraw); redraw.type = SDL_VIDEOEXPOSE;
SDL_PushEvent(&redraw);
}
} }
@ -440,8 +445,8 @@ int main(int argc, char *argv[]) {
gl_print(0.03, 0.12, buffer);*/ gl_print(0.03, 0.12, buffer);*/
sprintf(buffer, "Extr size: %.3fMb(max) %.3fMb(cur)", sprintf(buffer, "Extr size: %.3fMb(max) %.3fMb(cur)",
nexus.extraction_max * nexus.chunk_size/(float)(1<<20), nexus.patches.ram_max * nexus.chunk_size/(float)(1<<20),
nexus.extraction_used * nexus.chunk_size/(float)(1<<20)); nexus.patches.ram_used * nexus.chunk_size/(float)(1<<20));
gl_print(0.03, 0.09, buffer); gl_print(0.03, 0.09, buffer);
sprintf(buffer, "Vbo size : %.3fMb(max) %.3fMb(cur)", sprintf(buffer, "Vbo size : %.3fMb(max) %.3fMb(cur)",
@ -455,12 +460,7 @@ int main(int argc, char *argv[]) {
nexus.tri_rendered/(float)(1<<10), nexus.tri_rendered/(float)(1<<10),
tframe, 1/tframe); tframe, 1/tframe);
gl_print(0.03, 0.03, buffer); gl_print(0.03, 0.03, buffer);
/* cerr << "Ram flushed: " << nexus.patches.ram_flushed << endl;
cerr << "Ram readed: " << nexus.patches.ram_readed << endl;*/
nexus.patches.ram_flushed = 0;
nexus.patches.ram_readed = 0;
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glPopMatrix(); glPopMatrix();

View File

@ -1,3 +1,5 @@
#include <set>
#include "prefetch.h" #include "prefetch.h"
#include "nexusmt.h" #include "nexusmt.h"
@ -13,18 +15,30 @@ void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected,
safety.lock(); safety.lock();
mt = m; mt = m;
missing.clear(); missing.clear();
mt->todraw.clear();
unsigned int notloaded = 0; unsigned int notloaded = 0;
std::map<unsigned int, float> tmp; set<unsigned int> tmp;
//std::map<unsigned int, float> tmp;
vector<QueuePServer::Data> flush;
for(unsigned int i = 0; i < selected.size(); i++) { for(unsigned int i = 0; i < selected.size(); i++) {
unsigned int patch = selected[i]; unsigned int patch = selected[i];
tmp[patch] = 0.0f; tmp.insert(patch);
if(!mt->patches.IsLoaded(patch)) //tmp[patch] = 0.0f;
notloaded++; if(!mt->patches.entries[patch].patch) {
// if(mt->patches.IsLoaded(patch)) //cerr << "miss: " << patch << endl;
// mt->todraw.push_back(make_pair(patch, (Patch *)NULL)); load.post(patch);
// else notloaded++;
missing.push_back(PServer::Item(patch, 0.0f)); } else {
PatchInfo &info = mt->index[patch];
QueuePServer::Data &data = mt->patches.Lookup(patch, info.nvert, info.nface, 0.0f, flush);
if(flush.size() != 0) {
cerr << "Flushing!\n";
exit(0);
}
mt->todraw.push_back(&data);
}
//missing.push_back(PServer::Item(patch, 0.0f));
} }
if(notloaded) if(notloaded)
cerr << "Patches to load: " << notloaded << endl; cerr << "Patches to load: " << notloaded << endl;
@ -32,52 +46,84 @@ void Prefetch::init(NexusMt *m, std::vector<unsigned int> &selected,
for(unsigned int i = 0; i < visited.size(); i++) { for(unsigned int i = 0; i < visited.size(); i++) {
PServer::Item &item = visited[i]; PServer::Item &item = visited[i];
if(tmp.count(item.patch)) continue; if(tmp.count(item.patch)) continue;
if(mt->patches.IsLoaded(item.patch)) // if(mt->patches.entries[item.patch].patch)
tmp[item.patch] = item.priority; // tmp[item.patch] = item.priority;
if(item.priority != 0.0f)
missing.push_back(item); missing.push_back(item);
} }
QueuePServer &ps = mt->patches; QueuePServer &ps = mt->patches;
for(unsigned int i = 0; i < ps.heap.size(); i++) { for(unsigned int i = 0; i < ps.heap.size(); i++) {
PServer::Item &item = ps.heap[i]; PServer::Item &item = ps.heap[i];
if(tmp.count(item.patch)) if(tmp.count(item.patch))
item.priority = 0;
else {
if(item.priority == 0)
item.priority = 1;
item.priority *= 1.1;
}
/*if(tmp.count(item.patch))
item.priority = tmp[item.patch]; item.priority = tmp[item.patch];
else else
item.priority = 1e40; item.priority = 1e30;*/
} }
make_heap(ps.heap.begin(), ps.heap.end()); make_heap(ps.heap.begin(), ps.heap.end());
sort(missing.begin(), missing.end()); //CRITICAL reverse pero'! sort(missing.begin(), missing.end()); //CRITICAL reverse pero'!
reverse(missing.begin(), missing.end()); reverse(missing.begin(), missing.end());
load.post(0xffffffff);
safety.unlock(); safety.unlock();
} }
void Prefetch::execute() { void Prefetch::execute() {
while(1) {
if(get_signaled()) return;
while(1) { while(1) {
safety.lock(); if(get_signaled()) return;
if(missing.size() == 0) { vector<QueuePServer::Data> flush;
safety.unlock();
break;
}
PServer::Item item = missing.back();
missing.pop_back();
if(item.priority > 0 &&
mt->patches.ram_used > mt->patches.ram_max &&
item.priority >= mt->patches.MaxPriority()) {
safety.unlock();
break;
}
PatchInfo &info = mt->index[item.patch];
// cerr << "prefetching: " << item.patch << endl; if(load.get_count() || missing.size() == 0) {
mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority); pt::message *msg = load.getmessage();
if(msg->id != 0xffffffff) {
safety.lock();
PatchInfo &info = mt->index[msg->id];
safety.unlock(); //posting draw message
} QueuePServer::Data &data = mt->patches.Lookup(msg->id, info.nvert, info.nface, 0.0f, flush);
relax(5); pt::message *msg = new pt::message(QueuePServer::DRAW, (unsigned int)&data);
} msg->result = msg->id;
draw.post(msg);
//p;osting flush messages
for(unsigned int i = 0; i < flush.size(); i++) {
QueuePServer::Data *data = new QueuePServer::Data;
*data = flush[i];
draw.post(QueuePServer::FLUSH, (unsigned int)data);
}
safety.unlock();
}
delete msg;
} else {
safety.lock();
if(missing.size() != 0) {
PServer::Item item = missing.back();
missing.pop_back();
if(item.priority > mt->patches.MaxPriority()) {
missing.clear();
} else {
PatchInfo &info = mt->index[item.patch];
//cerr << "prefetching: " << item.patch << endl;
mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority, flush);
for(unsigned int i = 0; i < flush.size(); i++) {
QueuePServer::Data *data = new QueuePServer::Data;
*data = flush[i];
draw.post(QueuePServer::FLUSH, (unsigned int)data);
}
}
}
safety.unlock();
}
}
} }

View File

@ -17,14 +17,15 @@ class Prefetch: public pt::thread{
public: public:
pt::mutex safety; pt::mutex safety;
unsigned int ram_max; //unsigned int ram_max;
unsigned int ram_used; //unsigned int ram_used;
NexusMt *mt; NexusMt *mt;
std::vector<PServer::Item> missing; std::vector<PServer::Item> missing;
pt::jobqueue draw;
pt::jobqueue load;
Prefetch(): thread(false), draw(20000), load(64000) {}
Prefetch(): thread(false) {}
~Prefetch() { ~Prefetch() {
waitfor(); waitfor();
} }

View File

@ -15,9 +15,6 @@ bool PServer::Create(const std::string &filename,
ram_max = rsize/chunk_size + 1; ram_max = rsize/chunk_size + 1;
ram_used = 0; ram_used = 0;
ram_readed = 0;
ram_flushed = 0;
return MFile::Create(filename); return MFile::Create(filename);
} }
@ -31,9 +28,6 @@ bool PServer::Load(const std::string &filename, Signature sig,
ram_max = rsize/chunk_size + 1; ram_max = rsize/chunk_size + 1;
ram_used = 0; ram_used = 0;
ram_readed = 0;
ram_flushed = 0;
return MFile::Load(filename, readonly); return MFile::Load(filename, readonly);
} }
@ -51,6 +45,7 @@ bool PServer::ReadEntries(FILE *fp) {
fread(&(entries[i].patch_start), 1, sizeof(unsigned int), fp); fread(&(entries[i].patch_start), 1, sizeof(unsigned int), fp);
fread(&(entries[i].ram_size), 1, sizeof(unsigned short), fp); fread(&(entries[i].ram_size), 1, sizeof(unsigned short), fp);
fread(&(entries[i].disk_size), 1, sizeof(unsigned short), fp); fread(&(entries[i].disk_size), 1, sizeof(unsigned short), fp);
entries[i].patch = NULL;
} }
return true; return true;
} }
@ -81,6 +76,7 @@ Patch *PServer::LoadPatch(unsigned int idx,
assert(idx < entries.size()); assert(idx < entries.size());
Entry &entry = entries[idx]; Entry &entry = entries[idx];
if(entry.patch) return entry.patch;
char *ram = new char[entry.ram_size * chunk_size]; char *ram = new char[entry.ram_size * chunk_size];
#ifdef CONTROLS #ifdef CONTROLS
@ -108,15 +104,17 @@ Patch *PServer::LoadPatch(unsigned int idx,
delete []disk; delete []disk;
} }
} }
ram_used += entry.ram_size; ram_used += entry.ram_size;
ram_readed += entry.ram_size; entry.patch = patch;
return patch; return patch;
} }
void PServer::FlushPatch(unsigned int id, Patch *patch) { void PServer::FlushPatch(unsigned int id, Patch *patch) {
//TODO move this into an assert!!!!
if(!patch) return;
Entry &entry = entries[id]; Entry &entry = entries[id];
assert(entry.patch == patch);
entry.patch = NULL;
if(!readonly) { //write back patch if(!readonly) { //write back patch
if((signature & NXS_COMPRESSED)) { if((signature & NXS_COMPRESSED)) {
@ -147,10 +145,8 @@ void PServer::FlushPatch(unsigned int id, Patch *patch) {
} }
delete [](patch->start); delete [](patch->start);
delete patch; delete patch;
ram_used -= entry.ram_size;
ram_used -= entry.ram_size;
ram_flushed += entry.ram_size;
} }
void PServer::MaxRamBuffer(unsigned int r_buffer) { void PServer::MaxRamBuffer(unsigned int r_buffer) {

View File

@ -16,6 +16,7 @@ class PServer: public MFile {
unsigned int patch_start; //granularita' Chunk unsigned int patch_start; //granularita' Chunk
unsigned short ram_size; //in chunks unsigned short ram_size; //in chunks
unsigned short disk_size; // in chunks (used when compressed) unsigned short disk_size; // in chunks (used when compressed)
Patch *patch;
}; };
/* struct Data { /* struct Data {
@ -42,17 +43,8 @@ class PServer: public MFile {
unsigned int ram_max; unsigned int ram_max;
unsigned int ram_used; unsigned int ram_used;
//statistics:
unsigned int ram_readed;
unsigned int ram_flushed;
//pt::rwlock ramlock; //read only thread safety...
//pt::rwlock disklock; //read only thread safety...
std::vector<Entry> entries;
std::vector<Entry> entries;
PServer(): chunk_size(1024), PServer(): chunk_size(1024),
ram_max(128000000), ram_max(128000000),

View File

@ -7,6 +7,42 @@ using namespace nxs;
using namespace pt; using namespace pt;
QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
unsigned short nv, unsigned short nf,
float priority,
vector<QueuePServer::Data> &flush) {
flush.clear();
if(index.count(patch)) {
return index[patch];
} else {
while(ram_used > ram_max) {
if(MaxPriority() == 0) break;
pop_heap(heap.begin(), heap.end());
Item item = heap.back();
heap.pop_back();
assert(item.priority != 0);
Data &data = index[item.patch];
flush.push_back(data);
FlushPatch(item.patch, data.patch);
index.erase(item.patch);
}
Item item(patch, priority);
heap.push_back(item);
push_heap(heap.begin(), heap.end());
Data &data = index[patch];
// cerr << "Loading: " << patch << endl;
data.patch = LoadPatch(patch, nv, nf);
/*if(priority == 0) {
message *msg = new message(DRAW, (unsigned int)&data);
msg->result = patch;
queue.post(msg);
} */
return data;
}
}
/*
QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
unsigned short nv, unsigned short nf, unsigned short nv, unsigned short nf,
float priority) { float priority) {
@ -48,8 +84,8 @@ QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
return data; return data;
} }
} }
*/
QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, /*QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
Patch *mem, Patch *mem,
float priority) { float priority) {
if(index.count(patch)) { if(index.count(patch)) {
@ -75,7 +111,7 @@ QueuePServer::Data &QueuePServer::Lookup(unsigned int patch,
LoadVbo(data); LoadVbo(data);
return data; return data;
} }
} } */
bool QueuePServer::IsLoaded(unsigned int patch) { bool QueuePServer::IsLoaded(unsigned int patch) {
return index.count(patch); return index.count(patch);

View File

@ -2,6 +2,7 @@
#define NXS_QUEUE_PSERVER_H #define NXS_QUEUE_PSERVER_H
#include <map> #include <map>
#include <hash_map>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
@ -29,11 +30,15 @@ class QueuePServer: public PServer {
std::map<unsigned int, Data> index; std::map<unsigned int, Data> index;
std::vector<Item> heap; std::vector<Item> heap;
Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf,
float priority = 0.0f);
Data &Lookup(unsigned int patch, Patch *mem, float priority = 0.0f); QueuePServer(): queue(64000) {}
//Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf,
// float priority = 0.0f);
//return flushing too.
Data &Lookup(unsigned int patch, unsigned short nv, unsigned short nf, float priority,
std::vector<QueuePServer::Data> &data);
bool IsLoaded(unsigned int patch); bool IsLoaded(unsigned int patch);
float MaxPriority(); float MaxPriority();