diff --git a/apps/nexus/nexusmt.cpp b/apps/nexus/nexusmt.cpp index 78c38e8e..e7943960 100644 --- a/apps/nexus/nexusmt.cpp +++ b/apps/nexus/nexusmt.cpp @@ -57,14 +57,17 @@ float FrustumMetric::GetError(unsigned int cell) { if(dist < 0) return 1e20f; float error = entry.error/frustum.Resolution(dist); if(frustum.IsOutside(sphere.Center(), sphere.Radius())) - error /= 256; + error /= 32; return error; } -bool NexusMt::Expand(TNode &node) { +bool NexusMt::Expand(TNode &tnode) { //expand if node error > target error - if(extraction_used >= extraction_max) return false; - return node.error > target_error; + if(extraction_used >= extraction_max) return false; + if(draw_used >= draw_max) return false; + if(disk_used >= disk_max) return false; + + return tnode.error > target_error; } void NexusMt::NodeVisited(Node *node) { @@ -75,8 +78,15 @@ void NexusMt::NodeVisited(Node *node) { assert(!(node->out[i]->visited)); Frag &frag = node->frags[i]; for(unsigned int k = 0; k < frag.size(); k++) { - PServer::Entry &entry = patches.entries[frag[k]]; - extraction_used += entry.ram_size; + unsigned int patch = frag[k]; + 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) { vector &frag = frags[i]; for(unsigned int k = 0; k < frag.size(); k++) { - PServer::Entry &entry = patches.entries[frag[k]]; - extraction_used -= entry.ram_size; + unsigned int patch = frag[k]; + 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->index = &index; target_error = 4.0f; - extraction_max = 640000000; + extraction_max = 64000000000; + draw_max = 12000; //1M triangles (ZSN) + disk_max = 300; + } NexusMt::~NexusMt() { @@ -180,7 +199,7 @@ bool NexusMt::Load(const string &filename) { SetPrefetchSize(patches.ram_max/2); cerr << "Start!\n"; - prefetch.start(); + cerr << "Started\n"; return true; } @@ -199,6 +218,8 @@ bool NexusMt::InitGL(Vbo mode, unsigned int vbosize) { patches.vbo_max = vbosize / chunk_size; if(vbo_mode == VBO_OFF) patches.vbo_max = 0; + + prefetch.start(); return true; } @@ -212,13 +233,23 @@ void NexusMt::Render() { } void NexusMt::Draw(vector &cells) { - prefetch.init(this, cells, visited); tri_total = 0; tri_rendered = 0; - Frustumf frustum; frustum.GetView(); + vector 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); if(use_colors) glEnableClientState(GL_COLOR_ARRAY); @@ -226,37 +257,36 @@ void NexusMt::Draw(vector &cells) { glEnableClientState(GL_NORMAL_ARRAY); //TODO textures and data. - unsigned int count = cells.size(); - while(count) { - // cerr << "Getting message: " << count << endl; - pt::message *msg = patches.queue.getmessage(); - QueuePServer::Data *data = (QueuePServer::Data *)(msg->param); - if(msg->id == QueuePServer::FLUSH) { - // cerr << "Flush...\n"; - if(data->vbo_element) { - glDeleteBuffersARB(1, &(data->vbo_element)); - glDeleteBuffersARB(1, &(data->vbo_array)); + unsigned int count = draw.size(); + while(count > 0 || prefetch.draw.get_count()) { + if(todraw.size()) { + QueuePServer::Data *data = todraw.back(); + todraw.pop_back(); + Draw((unsigned int)(data->patch), *data); + } else { + // cerr << "Getting message: " << count << endl; + pt::message *msg = prefetch.draw.getmessage(); + 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; - 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--; } glDisableClientState(GL_VERTEX_ARRAY); @@ -455,7 +485,7 @@ void NexusMt::LoadHistory() { Node &oldnode = nodes[floor_node]; oldnode.frags.push_back(fr); if(node.error < max_err) - node.error = max_err; + node.error = max_err; //Update in and out of the nodes. node.in.push_back(&oldnode); @@ -502,18 +532,24 @@ void NexusMt::ClearHistory() { void NexusMt::Extract(std::vector &selected) { extraction_used = 0; + draw_used = 0; + disk_used = 0; visited.clear(); + float bestcost = -1; + int best = -1; + float cost = 0; + std::vector::iterator n; - for(n = nodes.begin(); n != nodes.end(); n++) { - (*n).visited = false; - // (*n).pushed = false; - } - + for(n = nodes.begin(); n != nodes.end(); n++) + (*n).visited = false; + std::vector heap; Node *root = &nodes[0]; VisitNode(root, heap); - + + sequence.clear(); + //vector sequence; while(heap.size()) { pop_heap(heap.begin(), heap.end()); TNode tnode = heap.back(); @@ -524,9 +560,40 @@ void NexusMt::Extract(std::vector &selected) { bool expand = Expand(tnode); - if(expand) - VisitNode(node, heap); + if(expand) //{ + 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); } @@ -556,7 +623,7 @@ void NexusMt::Extract(std::vector &selected) { } } Select(selected); -}*/ +} */ void NexusMt::Select(vector &selected) { selected.clear(); @@ -579,18 +646,38 @@ void NexusMt::Select(vector &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 &heap) { - if(node->visited) return; - + //TestCurrent(*i); + + if(node->visited) return; + node->visited = true; + + vector::iterator i; - for(i = node->in.begin(); i != node->in.end(); i++) - VisitNode(*i, heap); + for(i = node->in.begin(); i != node->in.end(); i++) { + VisitNode(*i, heap); + } for(unsigned int k = 0; k < node->out.size(); 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++) { unsigned int patch = node->frags[k][j]; @@ -598,13 +685,23 @@ void NexusMt::VisitNode(Node *node, vector &heap) { if(max_error < error) max_error = error; visited.push_back(PServer::Item(patch, fabs(error - target_error))); // push_heap(visited.begin(), visited.end()); - } + } heap.push_back(TNode(outnode, max_error)); push_heap(heap.begin(), heap.end()); } - node->visited = true; + sequence.push_back(node); NodeVisited(node); } +/*void NexusMt::UnvisitNode(Node *node, vector &heap) { + node->current = false; + vector::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()); + } +} */ \ No newline at end of file diff --git a/apps/nexus/nexusmt.h b/apps/nexus/nexusmt.h index 8beab69d..3234235a 100644 --- a/apps/nexus/nexusmt.h +++ b/apps/nexus/nexusmt.h @@ -19,7 +19,8 @@ namespace nxs { std::vector out; std::vector frags; float error; - bool visited; + bool visited; + bool current; // bool pushed; }; @@ -102,9 +103,15 @@ class NexusMt: public NexusBase { Metric *metric; float target_error; - - int extraction_max; - int extraction_used; + + vcg::Frustumf frustum; + + 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; @@ -119,7 +126,9 @@ class NexusMt: public NexusBase { unsigned int tri_rendered; unsigned int tri_total; + vector todraw; std::vector visited; + std::vector sequence; QueuePServer patches; BorderServer borders; @@ -160,6 +169,7 @@ class NexusMt: public NexusBase { void LoadHistory(); void ClearHistory(); void VisitNode(Node *node, std::vector &heap); + void UnvisitNode(Node *node, std::vector &heap); void Select(std::vector &selected); Patch &LoadPatch(unsigned int p); }; diff --git a/apps/nexus/nexusview.cpp b/apps/nexus/nexusview.cpp index e54e2bba..04b59ff9 100644 --- a/apps/nexus/nexusview.cpp +++ b/apps/nexus/nexusview.cpp @@ -24,6 +24,9 @@ History $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 Microchanges. @@ -209,14 +212,17 @@ int main(int argc, char *argv[]) { " q: quit\n" " s: screen error extraction\n" " g: geometry error extraction\n" - " p: draw points\n" + " t: show statistics\n" - " r: toggle realtime mode (TODO)\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" @@ -233,11 +239,9 @@ int main(int argc, char *argv[]) { bool extract = true; NexusMt::MetricKind metric; - NexusMt::Mode mode = NexusMt::SMOOTH; - unsigned int ram_size = 640000; + NexusMt::Mode mode = NexusMt::SMOOTH; - nexus.SetError(error); - nexus.SetExtractionSize(ram_size); + nexus.SetError(error); nexus.SetMetric(NexusMt::FRUSTUM); if(!nexus.InitGL()) { cerr << "Could not init glew.\n"; @@ -256,100 +260,99 @@ int main(int argc, char *argv[]) { bool redraw = false; float fps = 0; float tframe = 0; + bool keepdrawing = true; - while( !quit ) { - bool first = true; - SDL_WaitEvent(&event); - while( first || SDL_PollEvent( &event ) ){ - first = false; - switch( event.type ) { - case SDL_QUIT: quit = 1; break; - case SDL_KEYDOWN: - switch(event.key.keysym.sym) { - case SDLK_RCTRL: - case SDLK_LCTRL: - track.ButtonDown(Trackball::KEY_CTRL); break; - case SDLK_q: exit(0); break; - case SDLK_b: show_borders = !show_borders; break; - case SDLK_e: extract = !extract; break; - case SDLK_c: show_colors = !show_colors; break; - case SDLK_n: show_normals = !show_normals; break; - // case SDLK_9: nexus.patches->ram_size *= 0.8f; break; - // case SDLK_0: nexus.patches->ram_size *= 1.2f; break; - - case SDLK_LEFT: - ram_size *= 0.7; - nexus.SetExtractionSize(ram_size); - cerr << "Max extraction ram size: " << ram_size << endl; break; - case SDLK_RIGHT: - ram_size *= 1.5; - nexus.SetExtractionSize(ram_size); - cerr << "Max extraction ram size: " << ram_size << endl; break; + while( !quit ) { + unsigned int anything = SDL_PollEvent(&event); + if(!anything && !keepdrawing) { + SDL_WaitEvent(&event); + anything = true; + } + if(anything) { + switch( event.type ) { + case SDL_QUIT: quit = 1; break; + case SDL_KEYDOWN: + switch(event.key.keysym.sym) { + case SDLK_RCTRL: + case SDLK_LCTRL: track.ButtonDown(Trackball::KEY_CTRL); break; + case SDLK_q: exit(0); break; + case SDLK_k: keepdrawing = !keepdrawing; break; + case SDLK_e: extract = !extract; break; + case SDLK_c: show_colors = !show_colors; break; + case SDLK_n: show_normals = !show_normals; break; + + case SDLK_LEFT: nexus.extraction_max *= 0.7; break; + case SDLK_RIGHT: nexus.extraction_max *= 1.5; break; + case SDLK_UP: nexus.draw_max *= 1.5; break; + case SDLK_DOWN: nexus.draw_max *= 0.7; break; + case SDLK_PAGEUP: nexus.disk_max *= 1.5; break; + case SDLK_PAGEDOWN: nexus.disk_max *= 0.7; break; - case SDLK_s: metric = NexusMt::FRUSTUM; break; - case SDLK_p: mode = NexusMt::POINTS; 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_m: mode = NexusMt::SMOOTH; nexus.SetMode(mode); break; + case SDLK_s: metric = NexusMt::FRUSTUM; break; + case SDLK_p: mode = NexusMt::POINTS; 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_m: mode = NexusMt::SMOOTH; nexus.SetMode(mode); break; - case SDLK_r: - case SDLK_SPACE: rotate = !rotate; break; + case SDLK_r: + case SDLK_SPACE: rotate = !rotate; break; - case SDLK_MINUS: - error *= 0.9f; - nexus.SetError(error); - cerr << "Error: " << error << endl; break; + case SDLK_MINUS: + error *= 0.9f; + nexus.SetError(error); + cerr << "Error: " << error << endl; break; - case SDLK_EQUALS: - case SDLK_PLUS: - error *= 1.1f; - nexus.SetError(error); - cerr << "Error: " << error << endl; break; - } - break; - case SDL_KEYUP: - switch(event.key.keysym.sym) { - case SDLK_RCTRL: - case SDLK_LCTRL: - track.ButtonUp(Trackball::KEY_CTRL); break; - } - break; - case SDL_MOUSEBUTTONDOWN: - x = event.button.x; - y = height - event.button.y; -#ifdef SDL_BUTTON_WHEELUP - if(event.button.button == SDL_BUTTON_WHEELUP) - track.MouseWheel(1); - else if(event.button.button == SDL_BUTTON_WHEELDOWN) - track.MouseWheel(-1); - else - #endif - if(event.button.button == SDL_BUTTON_LEFT) - track.MouseDown(x, y, Trackball::BUTTON_LEFT); - else if(event.button.button == SDL_BUTTON_RIGHT) - track.MouseDown(x, y, Trackball::BUTTON_RIGHT); - break; - case SDL_MOUSEBUTTONUP: - x = event.button.x; - y = height - event.button.y; - if(event.button.button == SDL_BUTTON_LEFT) - track.MouseUp(x, y, Trackball::BUTTON_LEFT); - else if(event.button.button == SDL_BUTTON_RIGHT) - track.MouseUp(x, y, Trackball::BUTTON_RIGHT); - break; - case SDL_MOUSEMOTION: - while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)); - x = event.motion.x; - y = height - event.motion.y; - track.MouseMove(x, y); - break; - case SDL_VIDEOEXPOSE: - default: break; + case SDLK_EQUALS: + case SDLK_PLUS: + error *= 1.1f; + nexus.SetError(error); + cerr << "Error: " << error << endl; break; + } + break; + case SDL_KEYUP: + switch(event.key.keysym.sym) { + case SDLK_RCTRL: + case SDLK_LCTRL: + track.ButtonUp(Trackball::KEY_CTRL); break; + } + break; + case SDL_MOUSEBUTTONDOWN: + x = event.button.x; + y = height - event.button.y; + #ifdef SDL_BUTTON_WHEELUP + if(event.button.button == SDL_BUTTON_WHEELUP) + track.MouseWheel(1); + else if(event.button.button == SDL_BUTTON_WHEELDOWN) + track.MouseWheel(-1); + else + #endif + if(event.button.button == SDL_BUTTON_LEFT) + track.MouseDown(x, y, Trackball::BUTTON_LEFT); + else if(event.button.button == SDL_BUTTON_RIGHT) + track.MouseDown(x, y, Trackball::BUTTON_RIGHT); + break; + case SDL_MOUSEBUTTONUP: + x = event.button.x; + y = height - event.button.y; + if(event.button.button == SDL_BUTTON_LEFT) + track.MouseUp(x, y, Trackball::BUTTON_LEFT); + else if(event.button.button == SDL_BUTTON_RIGHT) + track.MouseUp(x, y, Trackball::BUTTON_RIGHT); + break; + case SDL_MOUSEMOTION: + while(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK)); + x = event.motion.x; + y = height - event.motion.y; + track.MouseMove(x, y); + break; + case SDL_VIDEOEXPOSE: + default: break; + } } redraw = true; - } + - if(!redraw) continue; + //if(!redraw && !keepdrawing) continue; redraw = false; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); @@ -363,9 +366,11 @@ int main(int argc, char *argv[]) { if(rotate) { alpha++; if(alpha > 360) alpha = 0; - SDL_Event redraw; - redraw.type = SDL_VIDEOEXPOSE; - SDL_PushEvent(&redraw); + if(!keepdrawing) { + SDL_Event 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);*/ sprintf(buffer, "Extr size: %.3fMb(max) %.3fMb(cur)", - nexus.extraction_max * nexus.chunk_size/(float)(1<<20), - nexus.extraction_used * nexus.chunk_size/(float)(1<<20)); + nexus.patches.ram_max * nexus.chunk_size/(float)(1<<20), + nexus.patches.ram_used * nexus.chunk_size/(float)(1<<20)); gl_print(0.03, 0.09, buffer); sprintf(buffer, "Vbo size : %.3fMb(max) %.3fMb(cur)", @@ -455,12 +460,7 @@ int main(int argc, char *argv[]) { nexus.tri_rendered/(float)(1<<10), tframe, 1/tframe); 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_LIGHTING); glPopMatrix(); diff --git a/apps/nexus/prefetch.cpp b/apps/nexus/prefetch.cpp index ed405160..b9396833 100644 --- a/apps/nexus/prefetch.cpp +++ b/apps/nexus/prefetch.cpp @@ -1,3 +1,5 @@ +#include + #include "prefetch.h" #include "nexusmt.h" @@ -13,18 +15,30 @@ void Prefetch::init(NexusMt *m, std::vector &selected, safety.lock(); mt = m; missing.clear(); + mt->todraw.clear(); unsigned int notloaded = 0; - std::map tmp; + set tmp; + //std::map tmp; + vector flush; for(unsigned int i = 0; i < selected.size(); i++) { unsigned int patch = selected[i]; - tmp[patch] = 0.0f; - if(!mt->patches.IsLoaded(patch)) - notloaded++; - // if(mt->patches.IsLoaded(patch)) - // mt->todraw.push_back(make_pair(patch, (Patch *)NULL)); - // else - missing.push_back(PServer::Item(patch, 0.0f)); + tmp.insert(patch); + //tmp[patch] = 0.0f; + if(!mt->patches.entries[patch].patch) { + //cerr << "miss: " << patch << endl; + load.post(patch); + notloaded++; + } 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) cerr << "Patches to load: " << notloaded << endl; @@ -32,52 +46,84 @@ void Prefetch::init(NexusMt *m, std::vector &selected, for(unsigned int i = 0; i < visited.size(); i++) { PServer::Item &item = visited[i]; if(tmp.count(item.patch)) continue; - if(mt->patches.IsLoaded(item.patch)) - tmp[item.patch] = item.priority; - - missing.push_back(item); +// if(mt->patches.entries[item.patch].patch) +// tmp[item.patch] = item.priority; + if(item.priority != 0.0f) + missing.push_back(item); } QueuePServer &ps = mt->patches; for(unsigned int i = 0; i < ps.heap.size(); i++) { PServer::Item &item = ps.heap[i]; 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]; else - item.priority = 1e40; + item.priority = 1e30;*/ } make_heap(ps.heap.begin(), ps.heap.end()); sort(missing.begin(), missing.end()); //CRITICAL reverse pero'! - reverse(missing.begin(), missing.end()); + reverse(missing.begin(), missing.end()); + load.post(0xffffffff); + safety.unlock(); } -void Prefetch::execute() { - while(1) { - if(get_signaled()) return; +void Prefetch::execute() { while(1) { - safety.lock(); - if(missing.size() == 0) { - 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]; + if(get_signaled()) return; + vector flush; - // cerr << "prefetching: " << item.patch << endl; - mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority); + if(load.get_count() || missing.size() == 0) { + pt::message *msg = load.getmessage(); + if(msg->id != 0xffffffff) { + safety.lock(); + PatchInfo &info = mt->index[msg->id]; - safety.unlock(); - } - relax(5); - } + //posting draw message + QueuePServer::Data &data = mt->patches.Lookup(msg->id, info.nvert, info.nface, 0.0f, flush); + 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(); + } + } } diff --git a/apps/nexus/prefetch.h b/apps/nexus/prefetch.h index a2e6a012..defcdad1 100644 --- a/apps/nexus/prefetch.h +++ b/apps/nexus/prefetch.h @@ -17,14 +17,15 @@ class Prefetch: public pt::thread{ public: pt::mutex safety; - unsigned int ram_max; - unsigned int ram_used; + //unsigned int ram_max; + //unsigned int ram_used; NexusMt *mt; std::vector missing; + pt::jobqueue draw; + pt::jobqueue load; - - Prefetch(): thread(false) {} + Prefetch(): thread(false), draw(20000), load(64000) {} ~Prefetch() { waitfor(); } diff --git a/apps/nexus/pserver.cpp b/apps/nexus/pserver.cpp index b0003b0f..91f14d91 100644 --- a/apps/nexus/pserver.cpp +++ b/apps/nexus/pserver.cpp @@ -15,9 +15,6 @@ bool PServer::Create(const std::string &filename, ram_max = rsize/chunk_size + 1; ram_used = 0; - ram_readed = 0; - ram_flushed = 0; - return MFile::Create(filename); } @@ -31,9 +28,6 @@ bool PServer::Load(const std::string &filename, Signature sig, ram_max = rsize/chunk_size + 1; ram_used = 0; - ram_readed = 0; - ram_flushed = 0; - 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].ram_size), 1, sizeof(unsigned short), fp); fread(&(entries[i].disk_size), 1, sizeof(unsigned short), fp); + entries[i].patch = NULL; } return true; } @@ -81,6 +76,7 @@ Patch *PServer::LoadPatch(unsigned int idx, assert(idx < entries.size()); Entry &entry = entries[idx]; + if(entry.patch) return entry.patch; char *ram = new char[entry.ram_size * chunk_size]; #ifdef CONTROLS @@ -108,15 +104,17 @@ Patch *PServer::LoadPatch(unsigned int idx, delete []disk; } } - ram_used += entry.ram_size; - ram_readed += entry.ram_size; - + ram_used += entry.ram_size; + entry.patch = patch; return patch; } void PServer::FlushPatch(unsigned int id, Patch *patch) { - + //TODO move this into an assert!!!! + if(!patch) return; Entry &entry = entries[id]; + assert(entry.patch == patch); + entry.patch = NULL; if(!readonly) { //write back patch if((signature & NXS_COMPRESSED)) { @@ -147,10 +145,8 @@ void PServer::FlushPatch(unsigned int id, Patch *patch) { } delete [](patch->start); - delete patch; - - ram_used -= entry.ram_size; - ram_flushed += entry.ram_size; + delete patch; + ram_used -= entry.ram_size; } void PServer::MaxRamBuffer(unsigned int r_buffer) { diff --git a/apps/nexus/pserver.h b/apps/nexus/pserver.h index 329840b6..f87f9581 100644 --- a/apps/nexus/pserver.h +++ b/apps/nexus/pserver.h @@ -16,6 +16,7 @@ class PServer: public MFile { unsigned int patch_start; //granularita' Chunk unsigned short ram_size; //in chunks unsigned short disk_size; // in chunks (used when compressed) + Patch *patch; }; /* struct Data { @@ -42,17 +43,8 @@ class PServer: public MFile { unsigned int ram_max; 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 entries; - + std::vector entries; PServer(): chunk_size(1024), ram_max(128000000), diff --git a/apps/nexus/queuepserver.cpp b/apps/nexus/queuepserver.cpp index c8e6315c..61a7095e 100644 --- a/apps/nexus/queuepserver.cpp +++ b/apps/nexus/queuepserver.cpp @@ -7,6 +7,42 @@ using namespace nxs; using namespace pt; +QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, + unsigned short nv, unsigned short nf, + float priority, + vector &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, unsigned short nv, unsigned short nf, float priority) { @@ -48,8 +84,8 @@ QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, return data; } } - -QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, +*/ +/*QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, Patch *mem, float priority) { if(index.count(patch)) { @@ -75,7 +111,7 @@ QueuePServer::Data &QueuePServer::Lookup(unsigned int patch, LoadVbo(data); return data; } -} +} */ bool QueuePServer::IsLoaded(unsigned int patch) { return index.count(patch); diff --git a/apps/nexus/queuepserver.h b/apps/nexus/queuepserver.h index e5bc8a73..e40e2a8a 100644 --- a/apps/nexus/queuepserver.h +++ b/apps/nexus/queuepserver.h @@ -2,6 +2,7 @@ #define NXS_QUEUE_PSERVER_H #include +#include #include #include @@ -29,11 +30,15 @@ class QueuePServer: public PServer { std::map index; std::vector 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 &data); bool IsLoaded(unsigned int patch); float MaxPriority();