Text archives Help
- From: boulos@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [Manta] r1724 - in trunk: Core Core/Util Engine/Control Interface Model/Groups Model/Groups/private Model/Instances Model/MiscObjects SCIRun/Core include scenes tests
- Date: Sat, 15 Sep 2007 10:30:44 -0600 (MDT)
Author: boulos
Date: Sat Sep 15 10:29:34 2007
New Revision: 1724
Added:
trunk/Core/Util/SpinLock.h
trunk/Core/Util/UpdateGraph.h
trunk/Interface/Task.cc
trunk/Interface/Task.h
trunk/Interface/TaskQueue.cc
trunk/Interface/TaskQueue.h
trunk/include/MachineParameters.h.CmakeTemplate
trunk/tests/atomic_counter.cc
Modified:
trunk/Core/CMakeLists.txt
trunk/Engine/Control/RTRT.cc
trunk/Engine/Control/RTRT.h
trunk/Interface/AccelerationStructure.h
trunk/Interface/CMakeLists.txt
trunk/Interface/Callback.h
trunk/Interface/CallbackHelpers.h
trunk/Interface/Context.cc
trunk/Interface/Context.h
trunk/Interface/MantaInterface.h
trunk/Interface/Object.cc
trunk/Interface/Object.h
trunk/Interface/Transaction.h
trunk/Model/Groups/DynBVH.cc
trunk/Model/Groups/DynBVH.h
trunk/Model/Groups/Group.cc
trunk/Model/Groups/Group.h
trunk/Model/Groups/Mesh.cc
trunk/Model/Groups/Mesh.h
trunk/Model/Groups/private/CGT.cc
trunk/Model/Groups/private/CGT.h
trunk/Model/Instances/Instance.cc
trunk/Model/Instances/Instance.h
trunk/Model/MiscObjects/KeyFrameAnimation.cc
trunk/Model/MiscObjects/KeyFrameAnimation.h
trunk/SCIRun/Core/CMakeLists.txt
trunk/include/CMakeLists.txt
trunk/scenes/primtest.cc
trunk/tests/CMakeLists.txt
Log:
Core/CMakeLists.txt
Core/Util/UpdateGraph.h
Adding a new UpdateGraph that is templated on KeyType to allow
people to use it for any purpose they'd like.
Core/Util/SpinLock.h
Adding an efficient x86 spin lock. If you're not on x86 this will
spin on a standard SCIRun::Mutex and be super slow. So we should add
more implementations for say PPC and maybe IA64.
Engine/Control/RTRT.cc
Engine/Control/RTRT.h
Interface/MantaInterface.h
Adding support for callbacks "labeled" as update callbacks. When
performing a transaction that modifies an object (and would require
its bounds to change in any way that requires an update to
acceleration structures) simply use one of these new transactions
and the doUpdates in RTRT will handle it.
Interface/Callback.h
Interface/CallbackHelpers.h
Adding Callback_1Data_2Arg (for BVH task based update)
Interface/Context.cc
Interface/Context.h
Adding an UpdateContext. Eventually this might replace the
preprocess context, but for now simply helps to provide info to the
new task based update scheme.
Interface/AccelerationStructure.h
Interface/CMakeLists.txt
Interface/Object.cc
Interface/Object.h
Interface/Task.cc
Interface/Task.h
Interface/TaskQueue.cc
Interface/TaskQueue.h
Interface/Transaction.h
Model/Groups/DynBVH.cc
Model/Groups/DynBVH.h
Model/Groups/Group.cc
Model/Groups/Group.h
Model/Groups/Mesh.cc
Model/Groups/Mesh.h
Model/Groups/private/CGT.cc
Model/Groups/private/CGT.h
Model/Instances/Instance.cc
Model/Instances/Instance.h
Model/MiscObjects/KeyFrameAnimation.cc
Model/MiscObjects/KeyFrameAnimation.h
Adding support for updates through a task based model. Objects are
queried before frame0 to see if they'd like to join the
UpdateGraph. If an update transaction is fired for an object in the
graph, it will be marked for updates and those updates will be
processed in parallel by traversing the update graph. The update
graph also allows us to avoid "re-updating" a parent object more
than once if multiple nodes lead into it (such as a top level
acceleration structure over thousands of objects).
As a proof of concept, the BVH contains it's own task based update
but it is very inefficient as it creates two subtasks unless the
node is a leaf (so essentially it goes all the way down and is
mostly just locking overhead).
SCIRun/Core/CMakeLists.txt
SCIRun/Core/Thread/AtomicCounter.h
SCIRun/Core/Thread/AtomicCounter_x86.cc
SCIRun/Core/Thread/Thread_pthreads.cc
Adding an efficient x86 implementation of AtomicCounter. This
should provide benefits to even general rendering as a lot of things
rely on AtomicCounter (including the WorkQueue load balancer).
include/CMakeLists.txt
include/MachineParameters.h.CmakeTemplate
Adding a CMakeTemplate for "machine parameters" like x86 or not,
64-bit or not, etc. For now this just detects whether or not the
system is an x86 based machine.
scenes/primtest.cc
Adding the ability to load a single mesh that isn't a keyframed
animation of one frame.
tests/CMakeLists.txt
tests/atomic_counter.cc
Adding an atomic_counter correctness test. It was useful in making
AtomicCounter_x86 and will probably be useful for adding the same
things for the refactor of the ia64 version and perhaps a PPC
version.
Modified: trunk/Core/CMakeLists.txt
==============================================================================
--- trunk/Core/CMakeLists.txt (original)
+++ trunk/Core/CMakeLists.txt Sat Sep 15 10:29:34 2007
@@ -77,6 +77,7 @@
Util/StaticCheck.h
Util/ThreadStorage.h
Util/ThreadStorage.cc
+ Util/UpdateGraph.h
)
ADD_LIBRARY (Manta_Core ${CORE_SOURCES})
Added: trunk/Core/Util/SpinLock.h
==============================================================================
--- (empty file)
+++ trunk/Core/Util/SpinLock.h Sat Sep 15 10:29:34 2007
@@ -0,0 +1,87 @@
+#ifndef MANTA_CORE_UTIL_SPINLOCK_H_
+#define MANTA_CORE_UTIL_SPINLOCK_H_
+
+#include <MachineParameters.h>
+
+#if !(MANTA_X86)
+#include <SCIRun/Core/Thread/Mutex.h>
+#endif
+
+namespace Manta {
+#if MANTA_X86
+ class SpinLock {
+ public:
+ SpinLock() : value(0) {
+ }
+ int value;
+
+ inline void unlock() {
+ volatile int return_val;
+ do {
+ return_val = 0;
+ __asm__ __volatile__(
+ "lock;\n"
+ "xchg %1, %0;\n" :
+ "=m" (value), "=r"(return_val) :
+ "m" (value) , "r" (return_val) :
+ /* no unknown clobbers */
+ );
+ // Check that we unlocked the lock (meaning that return_val = 1)
+ } while (return_val == 0);
+
+ return;
+ }
+
+
+ inline void lock() {
+ volatile int return_val;
+
+ do {
+ return_val = 1;
+ __asm__ __volatile__(
+ "lock;\n"
+ "xchg %1, %0;\n" :
+ "=m" (value), "=r"(return_val) :
+ "m" (value) , "r" (return_val) :
+ /* no unknown clobbers */
+ );
+ // Check that we got the lock, so return_val == 0 to exit
+ } while (return_val == 1);
+ return;
+ }
+
+ inline bool tryLock() {
+ volatile int return_val = 1;
+
+ __asm__ __volatile__(
+ "lock;\n"
+ "xchg %1, %0;\n" :
+ "=m" (value), "=r"(return_val) :
+ "m" (value) , "r" (return_val) :
+ /* no unknown clobbers */
+ );
+ return return_val == 0;
+ }
+ };
+#else
+ class SpinLock {
+ public:
+ SpinLock() : spin_mutex("SpinLock") {
+ }
+
+ void lock() {
+ while (!(spin_mutex.tryLock())) {
+ }
+ }
+ void unlock() {
+ spin_mutex.unlock();
+ }
+ bool tryLock() {
+ return spin_mutex.tryLock();
+ }
+
+ SCIRun::Mutex spin_mutex;
+ };
+#endif // MANTA_X86
+}
+#endif // MANTA_CORE_UTIL_SPINLOCK_H_
Added: trunk/Core/Util/UpdateGraph.h
==============================================================================
--- (empty file)
+++ trunk/Core/Util/UpdateGraph.h Sat Sep 15 10:29:34 2007
@@ -0,0 +1,156 @@
+#ifndef _MANTA_CORE_UTIL_UPDATE_GRAPH_H_
+#define _MANTA_CORE_UTIL_UPDATE_GRAPH_H_
+
+
+#include <map>
+#include <set>
+#include <vector>
+#include <Core/Exceptions/InternalError.h>
+#include <Core/Thread/AtomicCounter.h>
+#include <Core/Thread/Mutex.h>
+#include <iostream>
+#include <string>
+
+namespace Manta {
+
+ template<class KeyType>
+ class UpdateGraphNode {
+ public:
+ UpdateGraphNode(KeyType key, UpdateGraphNode* parent) :
+ key(key),
+ parent(parent),
+ needs_update(false),
+ counter("UpdateGraph Counter", 0),
+ active_edges(0) {
+ }
+
+ void addChild(UpdateGraphNode* child) {
+ children.push_back(child);
+ }
+
+ void print() {
+ std::cout << "Node (" << this << ") has " << children.size() << "
children, needs_update = " << needs_update << ", active_edges = " <<
active_edges << ", counter = " << counter;
+ }
+
+ KeyType key;
+ UpdateGraphNode* parent;
+ std::vector<UpdateGraphNode*> children;
+ bool needs_update;
+ SCIRun::AtomicCounter counter;
+ int active_edges; // NOTE(boulos): We could also increment the
+ // atomic counter and decrement it back to 0
+ // to determine child completion
+ };
+
+ template<class KeyType>
+ class UpdateGraph {
+ public:
+ typedef UpdateGraphNode<KeyType> Node;
+ typedef typename std::map<KeyType, Node*>::iterator node_map_iterator;
+ typedef typename std::set<Node*>::iterator leaf_iterator;
+
+ UpdateGraph() :
+ root_node(0),
+ graph_mutex("Update Graph Mutex") {
+ }
+
+ Node* getNode(KeyType key) {
+ node_map_iterator it = node_map.find(key);
+ if (it == node_map.end()) {
+ throw SCIRun::InternalError("Asked to mark an object not in the node
map",
+ __FILE__, __LINE__);
+ }
+
+ return it->second;
+ }
+
+ void lock() {
+ graph_mutex.lock();
+ }
+ void unlock() {
+ graph_mutex.unlock();
+ }
+
+ Node* finishUpdate(KeyType key) {
+ Node* node = getNode(key);
+ Node* parent = node->parent;
+ // Reset the node for future frames
+ node->active_edges = 0;
+ node->needs_update = false;
+ node->counter.set(0);
+
+ if (parent) {
+ int new_val = ++parent->counter;
+ if (new_val == parent->active_edges) {
+ return parent;
+ }
+ }
+ return 0;
+ }
+
+ void markObject(KeyType key) {
+ Node* node = getNode(key);
+ leaf_nodes.insert(node);
+
+ while (node && !node->needs_update) {
+ node->needs_update = true;
+ Node* parent = node->parent;
+ if (parent) {
+ parent->active_edges++;
+ }
+ leaf_nodes.erase(parent); // Set will remove it if it's there
+ node = parent;
+ }
+ }
+
+ // Insert a new Key into the UpdateGraph. For the root of the
+ // graph, pass parent as NULL and this will automatically work
+ // correctly. Note that there is no current way to get the root
+ // of the tree, and there may not be one single root (in case many
+ // people have no parent somehow)
+ Node* insert(KeyType key, Node* parent) {
+ Node* new_node = new Node(key, parent);
+ if (parent) {
+ parent->addChild(new_node);
+ } else {
+ root_node = new_node;
+ }
+ node_map[key] = new_node;
+ return new_node;
+ }
+
+ void print(KeyType key) {
+ Node* node = getNode(key);
+ printNode(node, "");
+
+ leaf_iterator leaf_it = leaf_nodes.begin();
+ while (leaf_it != leaf_nodes.end()) {
+ std::cout << "Leaf Node: " << *leaf_it << std::endl;
+ leaf_it++;
+ }
+ }
+ void printNode(Node* node, std::string indent) {
+ std::cout << indent;
+ node->print();
+ std::cout << std::endl;
+ indent += " ";
+ for (size_t i = 0; i < node->children.size(); i++) {
+ printNode(node->children[i], indent);
+ }
+ }
+
+ bool finished() {
+ if (root_node)
+ return root_node->needs_update == false;
+ return true;
+ }
+
+ std::map<KeyType, Node*> node_map;
+ std::set<Node*> leaf_nodes;
+ Node* root_node;
+ SCIRun::Mutex graph_mutex;
+ };
+
+} // end namespace Manta
+
+#endif // _MANTA_CORE_UTIL_UPDATE_GRAPH_H_
Modified: trunk/Engine/Control/RTRT.cc
==============================================================================
--- trunk/Engine/Control/RTRT.cc (original)
+++ trunk/Engine/Control/RTRT.cc Sat Sep 15 10:29:34 2007
@@ -46,6 +46,8 @@
#include <Interface/Renderer.h>
#include <Interface/Scene.h>
#include <Interface/SetupCallback.h>
+#include <Interface/Task.h>
+#include <Interface/TaskQueue.h>
#include <Interface/UserInterface.h>
#include <Interface/ShadowAlgorithm.h>
#include <Core/Exceptions/IllegalValue.h>
@@ -57,6 +59,9 @@
#include <Core/Thread/Time.h>
#include <Core/Util/Assert.h>
#include <Core/Util/NotFinished.h>
+#include <Core/Util/Preprocessor.h>
+#include <Core/Util/SpinLock.h>
+#include <Core/Util/UpdateGraph.h>
#include <MantaSSE.h>
#include <sgi_stl_warnings_off.h>
@@ -70,6 +75,8 @@
#include <Core/Math/CheapRNG.h>
#include <Core/Math/MT_RNG.h>
+#include <queue>
+
using namespace Manta;
using namespace std;
using SCIRun::IllegalValue;
@@ -108,6 +115,7 @@
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Default Constructor.
@@ -131,7 +139,9 @@
preprocess_barrier("Barrier for preprocessing"),
transaction_lock("RTRT transaction lock"),
thread_storage( 0 ),
- channel_create_lock("RTRT channel creation lock")
+ channel_create_lock("RTRT channel creation lock"),
+ update_graph(new ObjectUpdateGraph()),
+ update_work_queue(new TaskQueue())
{
workersWanted=0;
workersRendering=0;
@@ -478,6 +488,71 @@
}
}
+void RTRT::finishUpdates(Object* which_object,
+ const UpdateContext& context) {
+ // Pass this along to the update graph, so that the node is marked
+ // as done. If the parent of the node is now ready to be processed,
+ // next_node will be non-null.
+ //cerr << MANTA_FUNC << " object = " << which_object << endl;
+ ObjectUpdateGraphNode* next_node =
update_graph->finishUpdate(which_object);
+ if (next_node) {
+ // Follow this guy immediately
+ Object* next_object = next_node->key;
+ next_object->performUpdate(context);
+ }
+}
+
+void RTRT::insertWork(TaskList* new_work) {
+ update_work_queue->insert(new_work);
+}
+
+void RTRT::doUpdates(bool& changed, int proc, int numProcs) {
+ // While the update_graph isn't done, we should keep checking for
+ // work
+ double start_time = Time::currentSeconds();
+ bool had_update = false;
+ UpdateContext context(this, proc, numProcs);
+ while (!update_graph->finished()) {
+ // Some update actually happened, let the pipeline know
+ had_update = true;
+
+ // Ask the work queue for a task to run
+ Task* work = update_work_queue->grabWork();
+
+ if (work) {
+ work->run();
+ } else {
+ // Lock the update graph and see if a leaf node can be expanded
+ // into more work
+ //cerr << "Work queue failed to give out work
(update_work_queue.size() = " << update_work_queue->tasks.size() << std::endl;
+
+ Object* object = NULL;
+ update_graph->lock();
+ ObjectUpdateGraph::leaf_iterator leaf_it =
update_graph->leaf_nodes.begin();
+ if (leaf_it != update_graph->leaf_nodes.end()) {
+
+ ObjectUpdateGraphNode* node = *leaf_it;
+ object = node->key;
+ // Remove the leaf from the set of active leaf_nodes
+ update_graph->leaf_nodes.erase(leaf_it);
+ }
+ update_graph->unlock();
+
+ if (object) {
+ // We found a leaf object, start running the update
+ object->performUpdate(context);
+ }
+ }
+ // We now loop back to find more work.
+ }
+ if (had_update) {
+ changed = true;
+ if (proc == 0) {
+ double end_time = Time::currentSeconds();
+ cerr << "Finished some updates (in " << end_time - start_time << "
seconds)\n";
+ }
+ }
+}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// MAIN RENDERING LOOP
@@ -517,8 +592,11 @@
// scene. For now, only thread 0 will do this and pretend there is
// only a single thread to emulate the old behavior until we can
// ensure everything is thread-safe throughout the tree.
- if (proc == 0)
+ if (proc == 0) {
doPreprocess(proc, 1);
+ scene->getObject()->addToUpdateGraph(update_graph, NULL);
+ //update_graph->print(scene->getObject());
+ }
for(;;){
// P0 update frame number, time, etc.
@@ -556,8 +634,15 @@
if(proc == 0)
postTransactions(changed);
+ barrier1.wait(workersRendering);
+
+#if 0
doSerialAnimationCallbacks(changed, proc, workersAnimAndImage);
doParallelAnimationCallbacks(changed, proc, workersAnimAndImage);
+#else
+ doUpdates(changed, proc, workersAnimAndImage);
+ barrier1.wait(workersRendering);
+#endif
if(!firstFrame){
for(size_t index = 0;index < channels.size();index++){
@@ -856,6 +941,7 @@
///////////////////////////////////////////////////////////////////////////////
void RTRT::postTransactions(bool& changed)
{
+ bool updated_graph = false;
if(transactions.size() > 0){
// Lock the queue.
@@ -871,6 +957,12 @@
transaction->apply();
int flag = transaction->getFlag();
+ UpdateTransaction* update =
dynamic_cast<UpdateTransaction*>(transaction);
+ if (update) {
+ update_graph->markObject(update->getObject());
+ updated_graph = true;
+ }
+
// Delete the transaction.
delete transaction;
@@ -889,6 +981,9 @@
}
}
+ if (updated_graph) {
+ //update_graph->print(getScene()->getObject());
+ }
// Unlock the queue.
transaction_lock.unlock();
}
Modified: trunk/Engine/Control/RTRT.h
==============================================================================
--- trunk/Engine/Control/RTRT.h (original)
+++ trunk/Engine/Control/RTRT.h Sat Sep 15 10:29:34 2007
@@ -31,6 +31,7 @@
#include <Interface/MantaInterface.h>
#include <Interface/FrameState.h>
+#include <Interface/Object.h>
#include <Interface/Parameters.h>
#include <Core/Thread/AtomicCounter.h>
#include <Core/Thread/Barrier.h>
@@ -56,6 +57,7 @@
class Image;
class Scene;
class RandomNumberGenerator;
+ class TaskQueue;
class RTRT : public MantaInterface {
public:
@@ -152,6 +154,11 @@
// Transactions
virtual void addTransaction(TransactionBase* );
+ // The object has finished it's updating, let someone know
+ virtual void finishUpdates(Object* which_object, const UpdateContext&
context);
+ // There is new work to be done for this Object
+ virtual void insertWork(TaskList* new_work);
+
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Callbacks.
@@ -179,8 +186,8 @@
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
- // Debug:
- virtual void shootOneRay( Color &result_color, RayPacket
&result_rays, Real image_x, Real image_y, int channel_index );
+ // Debug:
+ virtual void shootOneRay( Color &result_color, RayPacket &result_rays,
Real image_x, Real image_y, int channel_index );
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
@@ -263,6 +270,7 @@
void doPreprocess(int proc, int numProcs);
void doParallelPreRenderCallbacks(int proc, int numProcs);
void doSerialPreRenderCallbacks(int proc, int numProcs);
+ void doUpdates(bool& changed, int proc, int numProcs);
void doIdleModeCallbacks(bool changed, bool firstFrame, bool&
pipelineNeedsSetup, int proc, int numProcs);
void doTerminationCallbacks();
@@ -354,6 +362,9 @@
Scene* scene;
SCIRun::Mutex channel_create_lock;
+
+ ObjectUpdateGraph* update_graph;
+ TaskQueue* update_work_queue;
};
}
Modified: trunk/Interface/AccelerationStructure.h
==============================================================================
--- trunk/Interface/AccelerationStructure.h (original)
+++ trunk/Interface/AccelerationStructure.h Sat Sep 15 10:29:34 2007
@@ -31,6 +31,9 @@
// rebuild the data structure over the current group.
virtual void rebuild(int proc=0, int numProcs=1) = 0;
+
+ virtual void addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent) = 0;
};
}
#endif //Manta_Interface_AccelerationStructure_h
Modified: trunk/Interface/CMakeLists.txt
==============================================================================
--- trunk/Interface/CMakeLists.txt (original)
+++ trunk/Interface/CMakeLists.txt Sat Sep 15 10:29:34 2007
@@ -54,6 +54,10 @@
SetupCallback.h
ShadowAlgorithm.cc
ShadowAlgorithm.h
+ Task.h
+ Task.cc
+ TaskQueue.h
+ TaskQueue.cc
TexCoordMapper.cc
TexCoordMapper.h
Texture.h
@@ -64,4 +68,4 @@
XWindow.h
)
-TARGET_LINK_LIBRARIES(Manta_Interface Manta_Core SCIRun_Core )
+TARGET_LINK_LIBRARIES(Manta_Interface Manta_Core SCIRun_Core)
Modified: trunk/Interface/Callback.h
==============================================================================
--- trunk/Interface/Callback.h (original)
+++ trunk/Interface/Callback.h Sat Sep 15 10:29:34 2007
@@ -109,7 +109,7 @@
Arg1 arg1, Arg2 arg2) {
return new Callback_Static_4Data_2Arg<Data1, Data2, Data3, Data4,
Arg1, Arg2>(pmf, arg1, arg2);
}
-
+
///////////////////////////////////////////////////////////
// Class member functions
@@ -122,7 +122,7 @@
}
#ifndef SWIG // For now these const versions won't compile in swig
- template<class T> static
+ template<class T> static
CallbackBase_0Data*
create(T* ptr, void (T::*pmf)() const) {
return new Callback_0Data_0Arg_const<T>(ptr, pmf);
@@ -134,9 +134,9 @@
create(T* ptr, void (T::*pmf)(Arg1), Arg1 arg1) {
return new Callback_0Data_1Arg<T, Arg1>(ptr, pmf, arg1);
}
-
+
#ifndef SWIG // For now these const versions won't compile in swig
- template<class T, typename Arg1> static
+ template<class T, typename Arg1> static
CallbackBase_0Data*
create(T* ptr, void (T::*pmf)(Arg1) const, Arg1 arg1) {
return new Callback_0Data_1Arg_const<T, Arg1>(ptr, pmf, arg1);
@@ -148,9 +148,9 @@
create(T* ptr, void (T::*pmf)(Arg1, Arg2), Arg1 arg1, Arg2 arg2) {
return new Callback_0Data_2Arg<T, Arg1, Arg2>(ptr, pmf, arg1, arg2);
}
-
+
#ifndef SWIG // For now these const versions won't compile in swig
- template<class T, typename Arg1, typename Arg2> static
+ template<class T, typename Arg1, typename Arg2> static
CallbackBase_0Data*
create(T* ptr, void (T::*pmf)(Arg1, Arg2) const, Arg1 arg1, Arg2 arg2) {
return new Callback_0Data_2Arg_const<T, Arg1, Arg2>(ptr, pmf, arg1,
arg2);
@@ -180,6 +180,12 @@
return new Callback_1Data_1Arg<T, Data1, Arg1>(ptr, pmf, arg1);
}
+ template<class T, typename Data1, typename Arg1, typename Arg2> static
+ CallbackBase_1Data<Data1>*
+ create(T* ptr, void (T::*pmf)(Data1, Arg1, Arg2), Arg1 arg1, Arg2 arg2) {
+ return new Callback_1Data_2Arg<T, Data1, Arg1, Arg2>(ptr, pmf, arg1,
arg2);
+ }
+
// 2 Data elements
template<class T, typename Data1, typename Data2> static
CallbackBase_2Data<Data1, Data2>*
@@ -240,7 +246,7 @@
create(T* ptr, void (T::*pmf)(Data1, Data2, Data3, Data4, Arg1, Arg2),
Arg1 arg1, Arg2 arg2) {
return new Callback_4Data_2Arg<T, Data1, Data2, Data3, Data4, Arg1,
Arg2>(ptr, pmf, arg1, arg2);
}
-
+
// 5 data elements
template<class T, typename Data1, typename Data2, typename Data3,
typename Data4, typename Data5> static
CallbackBase_5Data<Data1, Data2, Data3, Data4, Data5>*
Modified: trunk/Interface/CallbackHelpers.h
==============================================================================
--- trunk/Interface/CallbackHelpers.h (original)
+++ trunk/Interface/CallbackHelpers.h Sat Sep 15 10:29:34 2007
@@ -9,7 +9,7 @@
////////////////////////////////////////////////////////////
// Base classes that can be used by both the static and non-static
// Callback classes.
- //
+ //
// 0 Data
class CallbackBase_0Data : public CallbackHandle {
@@ -130,7 +130,7 @@
//////////////////////////////////////////////////////////
// Global functin or static class member functions
- //
+ //
// 0 Data
class Callback_Static_0Data_0Arg : public CallbackBase_0Data {
@@ -168,7 +168,7 @@
void (*pmf)(Arg1);
Arg1 arg1;
};
-
+
template<typename Arg1, typename Arg2>
class Callback_Static_0Data_2Arg : public CallbackBase_0Data {
public:
@@ -188,7 +188,7 @@
Arg1 arg1;
Arg2 arg2;
};
-
+
// 1 Data
template<typename Data1>
class Callback_Static_1Data_0Arg : public CallbackBase_1Data<Data1> {
@@ -358,10 +358,10 @@
Arg1 arg1;
Arg2 arg2;
};
-
+
///////////////////////////////////////////////////////////
// Class member functions
-
+
// 0 Data
template<class T>
class Callback_0Data_0Arg : public CallbackBase_0Data {
@@ -424,25 +424,25 @@
};
#ifndef SWIG // For now these const versions won't compile in swig
- template<class T, typename Arg1>
- class Callback_0Data_1Arg_const : public CallbackBase_0Data {
- public:
- Callback_0Data_1Arg_const(T* ptr, void (T::*pmf)(Arg1) const,
Arg1 arg1)
+ template<class T, typename Arg1>
+ class Callback_0Data_1Arg_const : public CallbackBase_0Data {
+ public:
+ Callback_0Data_1Arg_const(T* ptr, void (T::*pmf)(Arg1)
const, Arg1 arg1)
: ptr(ptr), pmf(pmf), arg1(arg1)
{
}
- virtual ~Callback_0Data_1Arg_const()
+ virtual ~Callback_0Data_1Arg_const()
{
}
- virtual void call()
+ virtual void call()
{
- (ptr->*pmf)(arg1);
+ (ptr->*pmf)(arg1);
}
- private:
- T* ptr;
- void (T::*pmf)(Arg1) const;
- Arg1 arg1;
- };
+ private:
+ T* ptr;
+ void (T::*pmf)(Arg1) const;
+ Arg1 arg1;
+ };
#endif
template<class T, typename Arg1, typename Arg2>
@@ -467,26 +467,26 @@
};
#ifndef SWIG // For now these const versions won't compile in swig
- template<class T, typename Arg1, typename Arg2>
- class Callback_0Data_2Arg_const : public CallbackBase_0Data {
- public:
- Callback_0Data_2Arg_const(T* ptr, void (T::*pmf)(Arg1, Arg2)
const, Arg1 arg1, Arg2 arg2)
+ template<class T, typename Arg1, typename Arg2>
+ class Callback_0Data_2Arg_const : public CallbackBase_0Data {
+ public:
+ Callback_0Data_2Arg_const(T* ptr, void (T::*pmf)(Arg1, Arg2)
const, Arg1 arg1, Arg2 arg2)
: ptr(ptr), pmf(pmf), arg1(arg1), arg2(arg2)
{
}
- virtual ~Callback_0Data_2Arg_const()
+ virtual ~Callback_0Data_2Arg_const()
{
}
- virtual void call()
+ virtual void call()
{
- (ptr->*pmf)(arg1, arg2);
+ (ptr->*pmf)(arg1, arg2);
}
- private:
- T* ptr;
- void (T::*pmf)(Arg1, Arg2) const;
- Arg1 arg1;
- Arg2 arg2;
- };
+ private:
+ T* ptr;
+ void (T::*pmf)(Arg1, Arg2) const;
+ Arg1 arg1;
+ Arg2 arg2;
+ };
#endif
template<class T, typename Arg1, typename Arg2, typename Arg3>
@@ -512,28 +512,28 @@
};
- template<class T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4 >
- class Callback_0Data_4Arg : public CallbackBase_0Data {
- public:
- Callback_0Data_4Arg(T* ptr, void (T::*pmf)(Arg1,
Arg2, Arg2, Arg4), Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ template<class T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4 >
+ class Callback_0Data_4Arg : public CallbackBase_0Data {
+ public:
+ Callback_0Data_4Arg(T* ptr, void (T::*pmf)(Arg1,
Arg2, Arg2, Arg4), Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
: ptr(ptr), pmf(pmf), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4)
{
}
- virtual ~Callback_0Data_4Arg()
+ virtual ~Callback_0Data_4Arg()
{
}
- virtual void call()
+ virtual void call()
{
- (ptr->*pmf)(arg1, arg2, arg3, arg4);
+ (ptr->*pmf)(arg1, arg2, arg3, arg4);
}
- private:
- T* ptr;
- void (T::*pmf)(Arg1, Arg2, Arg3, Arg4);
- Arg1 arg1;
- Arg2 arg2;
- Arg3 arg3;
- Arg4 arg4;
- };
+ private:
+ T* ptr;
+ void (T::*pmf)(Arg1, Arg2, Arg3, Arg4);
+ Arg1 arg1;
+ Arg2 arg2;
+ Arg3 arg3;
+ Arg4 arg4;
+ };
// 1 Data
template<class T, typename Data1>
@@ -575,6 +575,27 @@
Arg1 arg1;
};
+ template<class T, typename Data1, typename Arg1, typename Arg2>
+ class Callback_1Data_2Arg : public CallbackBase_1Data<Data1> {
+ public:
+ Callback_1Data_2Arg(T* ptr, void (T::*pmf)(Data1, Arg1, Arg2), Arg1
arg1, Arg2 arg2)
+ : ptr(ptr), pmf(pmf), arg1(arg1), arg2(arg2)
+ {
+ }
+ virtual ~Callback_1Data_2Arg()
+ {
+ }
+ virtual void call(Data1 data1)
+ {
+ (ptr->*pmf)(data1, arg1, arg2);
+ }
+ private:
+ T* ptr;
+ void (T::*pmf)(Data1, Arg1, Arg2);
+ Arg1 arg1;
+ Arg2 arg2;
+ };
+
// 2 Data
template<class T, typename Data1, typename Data2>
class Callback_2Data_0Arg : public CallbackBase_2Data<Data1, Data2> {
@@ -761,7 +782,7 @@
void (T::*pmf)(Data1, Data2, Data3, Data4, Arg1, Arg2);
Arg1 arg1;
Arg2 arg2;
- };
+ };
// 5 Data
template<class T, typename Data1, typename Data2, typename Data3, typename
Data4, typename Data5>
Modified: trunk/Interface/Context.cc
==============================================================================
--- trunk/Interface/Context.cc (original)
+++ trunk/Interface/Context.cc Sat Sep 15 10:29:34 2007
@@ -43,4 +43,18 @@
}
+UpdateContext::UpdateContext(MantaInterface* manta_interface,
+ unsigned int proc,
+ unsigned int num_procs) :
+ manta_interface(manta_interface),
+ proc(proc),
+ num_procs(num_procs) {
+}
+void UpdateContext::finish(Object* which_object) const {
+ const UpdateContext& context = *this;
+ manta_interface->finishUpdates(which_object, context);
+}
+void UpdateContext::insertWork(TaskList* new_work) const {
+ manta_interface->insertWork(new_work);
+}
Modified: trunk/Interface/Context.h
==============================================================================
--- trunk/Interface/Context.h (original)
+++ trunk/Interface/Context.h Sat Sep 15 10:29:34 2007
@@ -11,12 +11,14 @@
class FrameState;
class LightSet;
class LoadBalancer;
+ class Object;
class PixelSampler;
class ReadContext;
class Renderer;
class MantaInterface;
class Scene;
class ShadowAlgorithm;
+ class TaskList;
class XWindow;
class ThreadStorage;
class RandomNumberGenerator;
@@ -203,7 +205,7 @@
// the constructor that takes a manta_interface. It returns the
// old barrier.
SCIRun::Barrier* setBarrier(SCIRun::Barrier* barrier);
-
+
// Call this when you're done changing your state values during a
// preprocess call. It ensures that all the threads finish
// together.
@@ -218,6 +220,22 @@
PreprocessContext(const PreprocessContext&);
PreprocessContext& operator=(const PreprocessContext&);
+ };
+
+ class UpdateContext {
+ public:
+ UpdateContext(MantaInterface* manta_interface,
+ unsigned int proc,
+ unsigned int num_procs);
+
+ void finish(Object* which_object) const;
+ void insertWork(TaskList* new_work) const;
+
+ MantaInterface* manta_interface;
+ unsigned int proc;
+ unsigned int num_procs;
+ private:
+ UpdateContext();
};
}
Modified: trunk/Interface/MantaInterface.h
==============================================================================
--- trunk/Interface/MantaInterface.h (original)
+++ trunk/Interface/MantaInterface.h Sat Sep 15 10:29:34 2007
@@ -56,6 +56,7 @@
class ImageDisplay;
class ImageTraverser;
class LoadBalancer;
+ class Object;
class PixelSampler;
class RandomNumberGenerator;
class RayPacket;
@@ -63,6 +64,8 @@
class Scene;
class SetupCallback;
class ShadowAlgorithm;
+ class TaskList;
+ class UpdateContext;
class UserInterface;
class MantaInterface {
@@ -75,14 +78,14 @@
// Pipeline Components.
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-
+
// Image Displays (opengl, file, mpeg, etc.)
-
+
// Create a channel given a pointer to the ImageDisplay for the channel.
virtual int createChannel( ImageDisplay *image_display, Camera *camera,
bool stereo, int xres, int yres) = 0;
virtual ImageDisplay *getImageDisplay( int channel ) = 0;
virtual void setImageDisplay( int channel, ImageDisplay *display ) = 0;
-
+
virtual Camera* getCamera(int channel) const = 0;
virtual void setCamera(int channel, Camera *camera ) = 0;
virtual void getResolution(int channel, bool& stereo, int& xres, int&
yres) = 0;
@@ -96,7 +99,7 @@
typedef unsigned int IdleModeHandle;
virtual IdleModeHandle addIdleMode( IdleMode* idle_mode_ ) = 0;
virtual IdleMode* getIdleMode( IdleModeHandle i ) const = 0;
-
+
/*
* Render Stack Components.
*/
@@ -106,7 +109,7 @@
virtual ImageTraverser* getImageTraverser() const = 0;
// Image Types (rgb, rgba, float, etc.)
- typedef CallbackBase_4Data<bool,int,int,Image*&> CreateImageCallback;
+ typedef CallbackBase_4Data<bool,int,int,Image*&> CreateImageCallback;
virtual void setCreateImageCallback( CreateImageCallback* const callback
) = 0;
virtual CreateImageCallback* getCreateImageCallback() const = 0;
@@ -119,11 +122,11 @@
// Load Balancers
virtual void setLoadBalancer( LoadBalancer* load_balancer_ ) = 0;
virtual LoadBalancer* getLoadBalancer() const = 0;
-
+
// PixelSamplers
- virtual void setPixelSampler( PixelSampler* sampler_ ) = 0;
+ virtual void setPixelSampler( PixelSampler* sampler_ ) = 0;
virtual PixelSampler* getPixelSampler() const = 0;
-
+
// Renderers
virtual void setRenderer( Renderer* renderer_ ) = 0;
virtual Renderer* getRenderer() const = 0;
@@ -141,7 +144,7 @@
// Time Mode
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-
+
enum TimeMode {
RealTime,
FixedRate,
@@ -151,13 +154,13 @@
// Query functions
virtual int getCurrentFrame() const = 0;
-
+
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Control
///////////////////////////////////////////////////////////////////////////
-
///////////////////////////////////////////////////////////////////////////
-
+
///////////////////////////////////////////////////////////////////////////
+
// Parallel processing
virtual void changeNumWorkers(int) = 0;
virtual TValue<int>& numWorkers() = 0;
@@ -175,30 +178,39 @@
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
virtual void addTransaction(TransactionBase*) = 0;
-
+
template<class T, class Op>
void addTransaction(const char* name, TValue<T>& value, Op op, int flag
= TransactionBase::DEFAULT ) {
- addTransaction(new Transaction<T, Op>(name, value, op, flag ));
+ addTransaction(new Transaction<T, Op>(name, value, op, flag));
}
-
+
void addTransaction(const char* name, CallbackBase_0Data* callback, int
flag = TransactionBase::DEFAULT ) {
- addTransaction(new CallbackTransaction(name, callback, flag ));
+ addTransaction(new CallbackTransaction(name, callback, flag));
+ }
+
+ void addUpdateTransaction(const char* name, CallbackBase_0Data*
callback, Object* object, int flag = TransactionBase::DEFAULT ) {
+ addTransaction(new UpdateTransaction(name, callback, object, flag));
}
+ // The object has finished it's updating, let someone know
+ virtual void finishUpdates(Object* which_object, const UpdateContext&
context) = 0;
+ // There is new work to be done for this Object
+ virtual void insertWork(TaskList* new_work) = 0;
+
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Callbacks.
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-
+
typedef unsigned long FrameNumber;
-
+
enum OneShotTime {
// Callbacks
Absolute,
Relative
};
-
+
virtual void addOneShotCallback(OneShotTime whence, FrameNumber frame,
CallbackBase_2Data<int, int>* callback) = 0;
virtual void addParallelOneShotCallback(OneShotTime whence, FrameNumber
frame, CallbackBase_2Data<int, int>* callback) = 0;
@@ -212,16 +224,16 @@
//
virtual SCIRun::Barrier* getPreprocessBarrier() = 0;
-
+
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Debug
///////////////////////////////////////////////////////////////////////////
-
///////////////////////////////////////////////////////////////////////////
+
///////////////////////////////////////////////////////////////////////////
// This should only be called from within a transaction called function.
- virtual void shootOneRay( Color &result_color, RayPacket
&result_rays, Real image_x, Real image_y, int channel_index ) = 0;
-
+ virtual void shootOneRay( Color &result_color, RayPacket &result_rays,
Real image_x, Real image_y, int channel_index ) = 0;
+
protected:
MantaInterface();
Modified: trunk/Interface/Object.cc
==============================================================================
--- trunk/Interface/Object.cc (original)
+++ trunk/Interface/Object.cc Sat Sep 15 10:29:34 2007
@@ -1,5 +1,6 @@
#include <Interface/Object.h>
+#include <Interface/Context.h>
using namespace Manta;
@@ -9,4 +10,9 @@
Object::~Object()
{
+}
+
+void Object::performUpdate(const UpdateContext& context) {
+ // By default, claim we're done already
+ context.finish(this);
}
Modified: trunk/Interface/Object.h
==============================================================================
--- trunk/Interface/Object.h (original)
+++ trunk/Interface/Object.h Sat Sep 15 10:29:34 2007
@@ -7,9 +7,17 @@
namespace Manta {
class BBox;
+ class Object;
class PreprocessContext;
class RayPacket;
class RenderContext;
+ class UpdateContext;
+
+ template<class KeyType> class UpdateGraph;
+ template<class KeyType> class UpdateGraphNode;
+ typedef UpdateGraph<Object*> ObjectUpdateGraph;
+ typedef UpdateGraphNode<Object*> ObjectUpdateGraphNode;
+
class Object : public Interpolable {
public:
@@ -21,8 +29,14 @@
// consistency for when you have multiple threads calling
// preprocess.
virtual void preprocess(const PreprocessContext& context) {};
+ virtual void performUpdate(const UpdateContext& context);
virtual void computeBounds(const PreprocessContext& context, BBox& bbox)
const = 0;
virtual void intersect(const RenderContext& context, RayPacket& rays)
const = 0;
+ // If you'd like to be included in the update graph (so that you
+ // can possibly be updated), simply add yourself in. By default,
+ // nobody is inserted.
+ virtual void addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent) { }
private:
// Object(const Object&);
// Object& operator=(const Object&);
Added: trunk/Interface/Task.cc
==============================================================================
--- (empty file)
+++ trunk/Interface/Task.cc Sat Sep 15 10:29:34 2007
@@ -0,0 +1,48 @@
+#include <Interface/Task.h>
+
+using namespace Manta;
+
+Task::Task(TaskCallback* task_function) :
+ task_list(0),
+ task_function(task_function) {
+}
+
+void Task::finished() {
+ task_list->finishTask(task_id);
+}
+
+void Task::run() {
+ task_function->call(this);
+}
+
+TaskList::TaskList() :
+ reduction_function(0),
+ num_assigned("TaskList Assignment Count", 0),
+ num_remaining("TaskList Remaining Count", 0) {
+ tasks.reserve(2);
+}
+
+void TaskList::push_back(Task* task) {
+ task->task_list = this;
+ task->task_id = static_cast<unsigned int>(tasks.size());
+
+ tasks.push_back(task);
+ num_remaining++;
+}
+
+unsigned int TaskList::pop() {
+ return num_assigned++;
+}
+
+void TaskList::finishTask(unsigned int task_id) {
+ unsigned int num_left = --num_remaining;
+ if (num_left == 0) {
+ // Call the reduction function
+ if (reduction_function)
+ reduction_function->call();
+ }
+}
+
+void TaskList::setReduction(CallbackBase_0Data* new_reduction) {
+ reduction_function = new_reduction;
+}
Added: trunk/Interface/Task.h
==============================================================================
--- (empty file)
+++ trunk/Interface/Task.h Sat Sep 15 10:29:34 2007
@@ -0,0 +1,54 @@
+#ifndef MANTA_INTERFACE_TASK_H_
+#define MANTA_INTERFACE_TASK_H_
+
+// NOTE(boulos): Because Task and TaskList rely on Callback, they have
+// to be part of Interface to avoid a cyclic dependency.
+
+#include <vector>
+#include <Core/Thread/AtomicCounter.h>
+#include <Interface/Callback.h>
+
+namespace Manta {
+ class TaskList;
+
+ class Task {
+ public:
+ typedef CallbackBase_1Data<Task*> TaskCallback;
+ Task(TaskCallback* task_function);
+
+ static const unsigned int MaxScratchpadSize = 128;
+
+ unsigned int task_id;
+ TaskList* task_list;
+ char scratchpad_data[Task::MaxScratchpadSize];
+
+ // The function the task actually runs (always appends Task* to the end)
+ TaskCallback* task_function;
+ void finished();
+ void run();
+ };
+
+ class TaskList {
+ public:
+ TaskList();
+
+ // NOTE(boulos): push_back will modify your task to point to this
+ // TaskList and assign it an id.
+ void push_back(Task* task);
+ unsigned int pop();
+
+ void finishTask(unsigned int task_id);
+
+ void setReduction(CallbackBase_0Data* new_reduction);
+ // After finishing all the tasks, the reduction is called by the
+ // finishing thread
+ CallbackBase_0Data* reduction_function;
+
+ std::vector<Task*> tasks;
+ SCIRun::AtomicCounter num_assigned;
+ // Need to keep track of how many tasks are left unfinished
+ SCIRun::AtomicCounter num_remaining;
+ };
+} // end namespace Manta
+
+#endif // MANTA_CORE_UTIL_TASK_H_
Added: trunk/Interface/TaskQueue.cc
==============================================================================
--- (empty file)
+++ trunk/Interface/TaskQueue.cc Sat Sep 15 10:29:34 2007
@@ -0,0 +1,74 @@
+#include <Interface/TaskQueue.h>
+
+#define WQ_USE_STL 0
+using namespace Manta;
+
+TaskQueue::TaskQueue() {
+#if !(WQ_USE_STL)
+ tasks.resize(8, NULL);
+ read_index = write_index = 0;
+#endif
+}
+
+void TaskQueue::lock() {
+ queue_mutex.lock();
+}
+void TaskQueue::unlock() {
+ queue_mutex.unlock();
+}
+
+void TaskQueue::insert(TaskList* new_work) {
+#if WQ_USE_STL
+ lock();
+ tasks.push(new_work);
+ unlock();
+#else
+ lock();
+ tasks[write_index] = new_work;
+ write_index++;
+ size_t cur_size = tasks.size();
+ write_index &= (cur_size-1);
+ if (write_index == read_index) {
+ // Just hit the loop around point, so we need a bigger queue
+ tasks.resize(2 * cur_size, NULL);
+ // Set us to be the end of the old circular buffer
+ write_index = cur_size;
+ read_index = 0;
+ }
+ unlock();
+#endif
+}
+
+Task* TaskQueue::grabWork() {
+ Task* result = 0;
+ lock();
+#if WQ_USE_STL
+ if (tasks.size() > 0) {
+ TaskList* top_list = tasks.front();
+ unsigned int idx = top_list->pop();
+ result = top_list->tasks[idx];
+ // If we grabbed the last one, remove the TaskList
+ if (top_list->tasks.size() - 1 == idx) {
+ //std::cerr << "Finished TaskList " << result << std::endl;
+ tasks.pop();
+ }
+ }
+#else
+ // Queue is only empty (or over-full if write_index == read_index)
+ if (write_index != read_index) {
+ TaskList* top_list = tasks[read_index];
+ unsigned int idx = top_list->pop();
+ result = top_list->tasks[idx];
+ // If we grabbed the last one, remove the TaskList
+ if (top_list->tasks.size() - 1 == idx) {
+ //std::cerr << "Finished TaskList " << result << std::endl;
+ read_index++;
+ read_index &= (tasks.size() - 1);
+ } else {
+ //std::cerr << "Returning standard work " << result << "(was index "
<< idx << " of " << top_list->tasks.size() << ")\n";
+ }
+ }
+#endif
+ unlock();
+ return result;
+}
Added: trunk/Interface/TaskQueue.h
==============================================================================
--- (empty file)
+++ trunk/Interface/TaskQueue.h Sat Sep 15 10:29:34 2007
@@ -0,0 +1,38 @@
+#ifndef MANTA_INTERFACE_TASK_QUEUE_H_
+#define MANTA_INTERFACE_TASK_QUEUE_H_
+
+#include <Core/Util/SpinLock.h>
+#include <Interface/Task.h>
+
+#include <queue>
+#include <vector>
+
+namespace Manta {
+ class TaskQueue {
+ public:
+ TaskQueue();
+ /// Insert a new TaskList into the queue.
+ /// \param[in] new_work The task list to be inserted.
+ void insert(TaskList* new_work);
+
+ /// Attempt to grab work from the TaskQueue.
+ /// \return Returns NULL if no work is available or a valid Task*
otherwise.
+ Task* grabWork();
+ private:
+ void lock();
+ void unlock();
+
+#if WQ_USE_STL
+ std::queue<TaskList*> tasks;
+#else
+ std::vector<TaskList*> tasks;
+ size_t read_index;
+ size_t write_index;
+#endif
+
+ SpinLock queue_mutex;
+ };
+} // end namespace Manta
+
+
+#endif // MANTA_CORE_UTIL_TASK_QUEUE_H_
Modified: trunk/Interface/Transaction.h
==============================================================================
--- trunk/Interface/Transaction.h (original)
+++ trunk/Interface/Transaction.h Sat Sep 15 10:29:34 2007
@@ -9,6 +9,7 @@
namespace Manta {
class MantaInterface;
+ class Object;
class TransactionBase {
public:
@@ -20,7 +21,7 @@
// (Other transactions processed following the next
frame.)
PURGE // Process this transaction and then purge all remaining
from the queue.
};
-
+
virtual void apply() = 0;
virtual void printValue(std::ostream&) = 0;
virtual void printOp(std::ostream&) = 0;
@@ -28,7 +29,7 @@
const char* getName() const { return name; }
int getFlag() const { return flag; };
-
+
protected:
TransactionBase(const char* name, int flag_=TransactionBase::DEFAULT );
private:
@@ -49,7 +50,7 @@
{
value = op(value);
}
-
+
virtual void printValue(std::ostream& stream)
{
stream << value.value;
@@ -98,6 +99,39 @@
CallbackTransaction& operator=(const CallbackTransaction&);
CallbackBase_0Data* callback;
+ };
+
+ class UpdateTransaction : public TransactionBase {
+ public:
+ UpdateTransaction(const char* name, CallbackBase_0Data* callback,
Object* object, int flag)
+ : TransactionBase(name,flag), callback(callback), object(object)
+ { }
+
+ virtual void apply()
+ {
+ callback->call();
+ delete callback;
+ }
+
+ virtual void printValue(std::ostream& stream)
+ {
+ stream << "(n/a)";
+ }
+
+ virtual void printOp(std::ostream& stream)
+ {
+ stream << typeid(*callback).name();
+ }
+
+ virtual Object* getObject() const {
+ return object;
+ }
+ private:
+ UpdateTransaction(const UpdateTransaction&);
+ UpdateTransaction& operator=(const UpdateTransaction&);
+
+ CallbackBase_0Data* callback;
+ Object* object;
};
}
Modified: trunk/Model/Groups/DynBVH.cc
==============================================================================
--- trunk/Model/Groups/DynBVH.cc (original)
+++ trunk/Model/Groups/DynBVH.cc Sat Sep 15 10:29:34 2007
@@ -1,5 +1,6 @@
#include <Model/Groups/DynBVH.h>
#include <Core/Util/Preprocessor.h>
+#include <Core/Util/UpdateGraph.h>
#include <DynBVH_Parameters.h>
#include <stdio.h>
#include <stdlib.h>
@@ -8,6 +9,7 @@
#include <iostream>
#include <SCIRun/Core/Thread/Time.h>
#include <Interface/Context.h>
+#include <Interface/Task.h>
using namespace Manta;
using std::cerr;
@@ -435,6 +437,12 @@
return currGroup;
}
+void DynBVH::addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent) {
+ ObjectUpdateGraphNode* node = graph->insert(this, parent);
+ getGroup()->addToUpdateGraph(graph, node);
+}
+
void DynBVH::preprocess(const PreprocessContext& context)
{
//cerr << MANTA_FUNC << endl;
@@ -450,6 +458,156 @@
// that you're not required to call preprocess in order to do an
// update/rebuild.
}
+}
+
+typedef Callback_1Data_2Arg<DynBVH, Task*, int, UpdateContext> bvhtask_type;
+
+void DynBVH::performUpdate(const UpdateContext& context) {
+ //cerr << "Asking for BVH update" << endl;
+ // preallocate task list memory
+ tasklist_memory = new char[(num_nodes+1) * sizeof(TaskList)];
+ cur_tasklist = 0;
+ task_memory = new char[2 * (num_nodes+1) * sizeof(Task)];
+ cur_task = 0;
+ callback_memory = new char[3 * (num_nodes+1) * sizeof(bvhtask_type)];
+ cur_callback = 0;
+
+ TaskList* new_list = new (tasklist_memory + sizeof(TaskList)*cur_tasklist)
TaskList();
+
+ Task* update_tree =
+ new (task_memory + sizeof(Task) * cur_task) Task(
+ new (callback_memory) Callback_1Data_2Arg<DynBVH, Task*, int,
UpdateContext>
+ (this,
+ &DynBVH::parallelTopDownUpdate,
+ 0,
+ context));
+
+ cur_task++;
+ cur_tasklist++;
+ cur_callback++;
+
+ new_list->push_back(update_tree);
+ new_list->setReduction(
+ Callback::create(this,
+ &DynBVH::finishUpdate,
+ context));
+
+ // Ask the work queue to update my BVH
+ context.insertWork(new_list);
+}
+
+void DynBVH::finishUpdate(UpdateContext context) {
+ cur_tasklist = 0;
+ cur_task = 0;
+ cur_callback = 0;
+ delete[] tasklist_memory;
+ delete[] task_memory;
+ delete[] callback_memory;
+ context.finish(this);
+}
+
+void DynBVH::parallelTopDownUpdate(Task* task, int node_id, UpdateContext
context) {
+ // If node is a leaf update bounds and exit
+ //cerr << MANTA_FUNC << "(node_id = " << node_id << ")\n";
+ BVHNode& node = nodes[node_id];
+ if (node.isLeaf()) {
+ PreprocessContext preprocess_context(context.manta_interface,
+ context.proc,
+ context.num_procs,
+ NULL);
+ node.bounds.reset();
+ for (int i = 0; i < node.children; i++) {
+ BBox temp;
+ int obj_id = object_ids[node.child + i];
+ currGroup->get(obj_id)->computeBounds(preprocess_context, temp);
+ node.bounds.extendByBox(temp);
+ }
+ task->finished();
+ //cerr << MANTA_FUNC << "(node_id = " << node_id << ") finishing at a
leaf\n";
+ } else {
+ int left_son = node.child;
+ int right_son = left_son + 1;
+ // Recurse into two subtrees
+#if 1
+ taskpool_mutex.lock();
+
+ size_t tasklist_id = cur_tasklist;
+ size_t left_task_id = cur_task;
+ size_t right_task_id = cur_task + 1;
+ size_t callback_id = cur_callback;
+
+ cur_tasklist++;
+ cur_task += 2;
+ cur_callback += 3;
+
+ taskpool_mutex.unlock();
+#endif
+
+ TaskList* children = new (tasklist_memory + sizeof(TaskList) *
tasklist_id) TaskList();
+ Task* left_child = new (task_memory + sizeof(Task) * left_task_id) Task(
+ new (callback_memory + callback_id * sizeof(bvhtask_type)
)Callback_1Data_2Arg<DynBVH, Task*, int, UpdateContext>
+ (this,
+ &DynBVH::parallelTopDownUpdate,
+ left_son,
+ context));
+/*
+ Callback::create(this,
+ &DynBVH::parallelTopDownUpdate,
+ left_son,
+ context));
+*/
+ children->push_back(left_child);
+
+ Task* right_child = new (task_memory + sizeof(Task) * right_task_id)
Task(
+ new (callback_memory + (callback_id+1)*sizeof(bvhtask_type))
Callback_1Data_2Arg<DynBVH, Task*, int, UpdateContext>
+ (this,
+ &DynBVH::parallelTopDownUpdate,
+ right_son,
+ context));
+/*
+ Callback::create(this,
+ &DynBVH::parallelTopDownUpdate,
+ right_son,
+ context));
+*/
+
+ children->push_back(right_child);
+
+
+ // When the children finish, call reduction
+ children->setReduction(
+ new (callback_memory + (callback_id+2) * sizeof(bvhtask_type))
Callback_0Data_2Arg<DynBVH, int, Task*>(this,
+
&DynBVH::updateBoundsReduction,
+ node_id,
+ task));
+
+/*
+ Callback::create(this,
+ &DynBVH::updateBoundsReduction,
+ node_id,
+ task));
+*/
+
+ // Insert new TaskList for the BVH Object* in UpdateGraph
+ context.insertWork(children);
+ }
+}
+
+void DynBVH::updateBoundsReduction(int node_id, Task* task) {
+ //cerr << MANTA_FUNC << "(node_id = " << node_id << ")\n";
+ BVHNode& node = nodes[node_id];
+
+ // Check that node isn't a leaf
+ node.bounds.reset();
+ int left_son = node.child;
+ int right_son = left_son + 1;
+ const BVHNode& left_node = nodes[left_son];
+ const BVHNode& right_node = nodes[right_son];
+
+ node.bounds.extendByBox(left_node.bounds);
+ node.bounds.extendByBox(right_node.bounds);
+ task->finished();
+ //cerr << MANTA_FUNC << "(node_id = " << node_id << ") after
task->finished()\n";
}
void DynBVH::update(int proc, int numProcs) {
Modified: trunk/Model/Groups/DynBVH.h
==============================================================================
--- trunk/Model/Groups/DynBVH.h (original)
+++ trunk/Model/Groups/DynBVH.h Sat Sep 15 10:29:34 2007
@@ -6,10 +6,12 @@
#include <Interface/RayPacket.h>
#include <Interface/AccelerationStructure.h>
#include <Core/Thread/Barrier.h>
-#include <SCIRun/Core/Thread/Mutex.h>
+#include <Core/Util/SpinLock.h>
namespace Manta
{
+ class Task;
+
class DynBVH : public AccelerationStructure
{
protected:
@@ -62,10 +64,18 @@
Group* currGroup;
bool group_changed;
SCIRun::Barrier barrier;
+ SpinLock taskpool_mutex;
vector<BBox> obj_bounds;
vector<Vector> obj_centroids;
+ char* tasklist_memory;
+ size_t cur_tasklist;
+ char* task_memory;
+ size_t cur_task;
+
+ char* callback_memory;
+ size_t cur_callback;
public:
DynBVH() : currGroup(NULL), group_changed(false), barrier("DynBVH
barrier")
@@ -73,6 +83,15 @@
void setGroup(Group* new_group);
Group* getGroup() const;
+
+ virtual void addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent);
+
+ void performUpdate(const UpdateContext& context);
+ void finishUpdate(UpdateContext context);
+
+ void parallelTopDownUpdate(Task* task, int node_id, UpdateContext
context);
+ void updateBoundsReduction(int node_id, Task* task);
void preprocess(const PreprocessContext&);
void intersect(const RenderContext& context, RayPacket& rays) const;
Modified: trunk/Model/Groups/Group.cc
==============================================================================
--- trunk/Model/Groups/Group.cc (original)
+++ trunk/Model/Groups/Group.cc Sat Sep 15 10:29:34 2007
@@ -1,5 +1,6 @@
#include <Core/Util/Preprocessor.h>
+#include <Core/Util/UpdateGraph.h>
#include <Interface/Context.h>
#include <Model/Groups/Group.h>
#include <SCIRun/Core/Util/Assert.h>
@@ -216,4 +217,14 @@
{
for(vector<Object*>::const_iterator iter = objs.begin(); iter !=
objs.end(); ++iter)
(*iter)->intersect(context, rays);
+}
+
+void Group::addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent) {
+ // Insert myself underneath my parent
+ ObjectUpdateGraphNode* node = graph->insert(this, parent);
+ // Ask the underlying objects to insert themselves underneath me if they
want
+ for (size_t i = 0; i < objs.size(); i++) {
+ objs[i]->addToUpdateGraph(graph, node);
+ }
}
Modified: trunk/Model/Groups/Group.h
==============================================================================
--- trunk/Model/Groups/Group.h (original)
+++ trunk/Model/Groups/Group.h Sat Sep 15 10:29:34 2007
@@ -62,7 +62,7 @@
Object* get( size_t i );
const Object* get( size_t i ) const;
const vector<Object*> &getVectorOfObjects() const { return objs; };
-
+
//whether the group has been modified (is dirty) and needs state,
//such as the bounding box, to be updated.
bool isDirty() const;
@@ -83,6 +83,9 @@
int proc, int numProcs) const;
static Group* create(const vector<string>& args);
+
+ virtual void addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent);
protected:
vector<Object*> objs;
Modified: trunk/Model/Groups/Mesh.cc
==============================================================================
--- trunk/Model/Groups/Mesh.cc (original)
+++ trunk/Model/Groups/Mesh.cc Sat Sep 15 10:29:34 2007
@@ -1,5 +1,6 @@
#include <Model/Groups/Mesh.h>
#include <Core/Util/Preprocessor.h>
+#include <Core/Util/UpdateGraph.h>
#include <SCIRun/Core/Exceptions/InternalError.h>
#include <Interface/MeshTriangle.h>
@@ -196,6 +197,17 @@
for (unsigned int i=0; i < materials.size(); ++i)
materials[i]->preprocess(context);
Group::preprocess(context);
+}
+
+void Mesh::addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent) {
+ // Insert myself underneath my parent
+ /*ObjectUpdateGraphNode* node = */graph->insert(this, parent);
+ // NOTE(boulos): Not currently adding the children (for
+ // WaldTriangle this is incorrect). Worse yet, without having
+ // information even for KenslerShirley about which Primitives
+ // have changed the BVH update won't be able to update only the
+ // sections that changed.
}
void Mesh::interpolateNormals()
Modified: trunk/Model/Groups/Mesh.h
==============================================================================
--- trunk/Model/Groups/Mesh.h (original)
+++ trunk/Model/Groups/Mesh.h Sat Sep 15 10:29:34 2007
@@ -78,6 +78,9 @@
virtual void preprocess(const PreprocessContext& context);
+ virtual void addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent);
+
//removes degenerate triangles from mesh.
void removeDegenerateTriangles();
};
Modified: trunk/Model/Groups/private/CGT.cc
==============================================================================
--- trunk/Model/Groups/private/CGT.cc (original)
+++ trunk/Model/Groups/private/CGT.cc Sat Sep 15 10:29:34 2007
@@ -1,8 +1,10 @@
#include <Model/Groups/private/CGT.h>
#include <SCIRun/Core/Thread/Time.h>
#include <Core/Geometry/BBox.h>
+#include <Core/Util/UpdateGraph.h>
#include <Interface/MantaInterface.h>
+
using namespace Manta;
#define DISPLAY_BUILD_TIMES true
@@ -19,6 +21,12 @@
Group* Grid::getGroup() const {
return currGroup;
+}
+
+void Grid::addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent) {
+ ObjectUpdateGraphNode* node = graph->insert(this, parent);
+ getGroup()->addToUpdateGraph(graph, node);
}
void Grid::preprocess(const PreprocessContext& context)
Modified: trunk/Model/Groups/private/CGT.h
==============================================================================
--- trunk/Model/Groups/private/CGT.h (original)
+++ trunk/Model/Groups/private/CGT.h Sat Sep 15 10:29:34 2007
@@ -170,6 +170,9 @@
void setGroup(Group* new_group);
Group* getGroup() const;
+ virtual void addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent);
+
void preprocess(const PreprocessContext&);
void build(int proc, int numProcs, bool &);
void preFrameSetup(int proc, int numProcs);
Modified: trunk/Model/Instances/Instance.cc
==============================================================================
--- trunk/Model/Instances/Instance.cc (original)
+++ trunk/Model/Instances/Instance.cc Sat Sep 15 10:29:34 2007
@@ -35,6 +35,7 @@
#include <Core/Geometry/BBox.h>
#include <Core/Math/MiscMath.h>
#include <Core/Util/Preprocessor.h>
+#include <Core/Util/UpdateGraph.h>
#include <iostream>
#include <sgi_stl_warnings_off.h>
@@ -66,12 +67,22 @@
transform_inv = transform.inverse();
}
+Object* Instance::getInstance() {
+ return instance;
+}
+
void Instance::preprocess(const PreprocessContext& context)
{
//cerr << MANTA_FUNC << endl;
//cerr << " Before instance->preprocess (thread " << context.proc << " of
" << context.numProcs << ")\n";
instance->preprocess(context);
//cerr << " After instance->preprocess (thread " << context.proc << " of "
<< context.numProcs << ")\n";
+}
+
+void Instance::addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent) {
+ ObjectUpdateGraphNode* node = graph->insert(this, parent);
+ instance->addToUpdateGraph(graph, node);
}
void Instance::computeBounds(const PreprocessContext& context, BBox& bbox)
const
Modified: trunk/Model/Instances/Instance.h
==============================================================================
--- trunk/Model/Instances/Instance.h (original)
+++ trunk/Model/Instances/Instance.h Sat Sep 15 10:29:34 2007
@@ -47,6 +47,8 @@
// Functions for callbacks (must be pass by value)
void setTransform(AffineTransform new_transform);
+ Object* getInstance();
+
// Generic
virtual void preprocess(const PreprocessContext&);
virtual void computeBounds(const PreprocessContext& context,
@@ -62,6 +64,9 @@
RayPacket& rays) const;
virtual void computeTexCoords3(const RenderContext& context,
RayPacket& rays) const;
+
+ virtual void addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent);
private:
Object* instance;
Modified: trunk/Model/MiscObjects/KeyFrameAnimation.cc
==============================================================================
--- trunk/Model/MiscObjects/KeyFrameAnimation.cc (original)
+++ trunk/Model/MiscObjects/KeyFrameAnimation.cc Sat Sep 15 10:29:34
2007
@@ -1,7 +1,8 @@
-#include "KeyFrameAnimation.h"
+#include <Model/MiscObjects/KeyFrameAnimation.h>
#include <Interface/Context.h>
#include <Interface/MantaInterface.h>
#include <SCIRun/Core/Thread/Time.h>
+#include <Core/Util/UpdateGraph.h>
#include <assert.h>
#include <cmath>
@@ -76,7 +77,7 @@
void KeyFrameAnimation::update(Temp_Callback context)
{
if (frames.empty())
- return;
+ return;
//only one thread can do serial code
if (context.proc == 0) {
if (updateToCurrTime) {
@@ -130,7 +131,7 @@
if (context.proc == 0) {
currGroup = frames[(int) frame];
// TODO(boulos): Who should check for identical pointers?
- if (as)
+ if (as)
as->setGroup(currGroup);
}
//make sure the as->setGroup has occured before all the threads
@@ -243,4 +244,14 @@
as = _as;
as->setGroup(currGroup);
//XXX need to do some more stuff to make sure the switch happens cleanly...
+}
+
+void KeyFrameAnimation::addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent) {
+ // Insert myself underneath my parent
+ ObjectUpdateGraphNode* node = graph->insert(this, parent);
+ // Ask the underlying objects to insert themselves underneath me if they
want
+ for (size_t i = 0; i < frames.size(); i++) {
+ frames[i]->addToUpdateGraph(graph, node);
+ }
}
Modified: trunk/Model/MiscObjects/KeyFrameAnimation.h
==============================================================================
--- trunk/Model/MiscObjects/KeyFrameAnimation.h (original)
+++ trunk/Model/MiscObjects/KeyFrameAnimation.h Sat Sep 15 10:29:34 2007
@@ -18,7 +18,7 @@
//add a keyframe
void push_back(Group *objects);
-
+
//number of seconds the animation takes from start to end
void setDuration(float time) { duration = time; };
@@ -54,10 +54,12 @@
//TODO: should we instead have a collection of acceleration structures?
void useAccelerationStructure(AccelerationStructure* as);
+ virtual void addToUpdateGraph(ObjectUpdateGraph* graph,
+ ObjectUpdateGraphNode* parent);
AccelerationStructure *as;
private:
-
+
float wrapTime(float time) const;
InterpolationMode interpolation;
Modified: trunk/SCIRun/Core/CMakeLists.txt
==============================================================================
--- trunk/SCIRun/Core/CMakeLists.txt (original)
+++ trunk/SCIRun/Core/CMakeLists.txt Sat Sep 15 10:29:34 2007
@@ -65,6 +65,19 @@
)
+# If we are on X86 define SCIRUN_X86
+IF (CMAKE_SYSTEM_PROCESSOR MATCHES "i686" OR
+ CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
+ ADD_DEFINITIONS(-DSCIRUN_X86)
+ENDIF(CMAKE_SYSTEM_PROCESSOR MATCHES "i686" OR
+ CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
+
+# This takes advantage of the previously run
+# Manta/CMake/ConfigArchitecture.cmake
+IF(APPLE_X86)
+ ADD_DEFINITIONS(-DSCIRUN_X86)
+ENDIF(APPLE_X86)
+
# If we are using SPROC on IRIX then add these files
IF (CMAKE_USE_SPROC_INIT)
# MESSAGE("Using sproc threads")
Modified: trunk/include/CMakeLists.txt
==============================================================================
--- trunk/include/CMakeLists.txt (original)
+++ trunk/include/CMakeLists.txt Sat Sep 15 10:29:34 2007
@@ -106,4 +106,26 @@
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/DynBVH_Parameters.h.CMakeTemplate
${CMAKE_BINARY_DIR}/include/DynBVH_Parameters.h
+ )
+
+# Configure the MachineParameters.h
+
+# Default to off
+SET(MANTA_X86_DEF "0")
+
+IF (CMAKE_SYSTEM_PROCESSOR MATCHES "i686" OR
+ CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
+ SET(MANTA_X86_DEF "1")
+ENDIF(CMAKE_SYSTEM_PROCESSOR MATCHES "i686" OR
+ CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
+
+# This takes advantage of the previously run
+# Manta/CMake/ConfigArchitecture.cmake
+IF(APPLE_X86)
+ SET(MANTA_X86_DEF "1")
+ENDIF(APPLE_X86)
+
+CONFIGURE_FILE(
+ ${CMAKE_CURRENT_SOURCE_DIR}/MachineParameters.h.CmakeTemplate
+ ${CMAKE_BINARY_DIR}/include/MachineParameters.h
)
Added: trunk/include/MachineParameters.h.CmakeTemplate
==============================================================================
--- (empty file)
+++ trunk/include/MachineParameters.h.CmakeTemplate Sat Sep 15 10:29:34
2007
@@ -0,0 +1,34 @@
+/*
+ For more information, please see:
http://software.sci.utah.edu
+
+ The MIT License
+
+ Copyright (c) 2005-2006
+ Scientific Computing and Imaging Institute, University of Utah
+
+ License for the specific language governing rights and limitations under
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MANTA_INCLUDE_MACHINE_PARAMETERS_H_
+#define MANTA_INCLUDE_MACHINE_PARAMETERS_H_
+
+#define MANTA_X86 ${MANTA_X86_DEF}
+
+#endif
Modified: trunk/scenes/primtest.cc
==============================================================================
--- trunk/scenes/primtest.cc (original)
+++ trunk/scenes/primtest.cc Sat Sep 15 10:29:34 2007
@@ -353,6 +353,16 @@
if ( mapr )
prim->setTexCoordMapper( mapr );
spinprim = prim;
+ } else if(primtype == "mesh") {
+ AccelerationStructure *as= new DynBVH();
+ Mesh* mesh = new Mesh();
+ if (!strncmp(modelName.c_str()+modelName.length()-4, ".obj", 4)) {
+ mesh = new ObjGroup(modelName.c_str());
+ } else {
+ throw SCIRun::InternalError("No OBJ model found", __FILE__, __LINE__);
+ }
+ as->setGroup(mesh);
+ spinprim = as;
} else if(primtype == "ply"){
#ifdef USE_PRIVATE_CODE
bgpoly = false;
Modified: trunk/tests/CMakeLists.txt
==============================================================================
--- trunk/tests/CMakeLists.txt (original)
+++ trunk/tests/CMakeLists.txt Sat Sep 15 10:29:34 2007
@@ -1,3 +1,5 @@
SUBDIRS( perftest )
+ADD_EXECUTABLE(atomic_counter atomic_counter.cc)
+TARGET_LINK_LIBRARIES(atomic_counter ${MANTA_TARGET_LINK_LIBRARIES})
Added: trunk/tests/atomic_counter.cc
==============================================================================
--- (empty file)
+++ trunk/tests/atomic_counter.cc Sat Sep 15 10:29:34 2007
@@ -0,0 +1,106 @@
+/*
+ For more information, please see:
http://software.sci.utah.edu
+
+ The MIT License
+
+ Copyright (c) 2004 Scientific Computing and Imaging Institute,
+ University of Utah.
+
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+*/
+
+
+
+#include <Core/Thread/Thread.h>
+#include <Core/Thread/Barrier.h>
+#include <Core/Thread/Runnable.h>
+#include <Core/Thread/ThreadGroup.h>
+#include <Core/Thread/Mutex.h>
+#include <Core/Thread/Time.h>
+#include <Core/Thread/AtomicCounter.h>
+#include <iostream>
+using std::cerr;
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+
+using namespace SCIRun;
+
+class AtomicCountTest : public Runnable {
+ AtomicCounter* counter;
+ int count;
+ int proc;
+ int np;
+public:
+ AtomicCountTest(AtomicCounter* barrier, int count, int proc, int np);
+ virtual void run();
+};
+
+void usage(char* progname)
+{
+ cerr << "usage: " << progname << " nprocessors count\n";
+ exit(1);
+}
+
+int main(int argc, char* argv[])
+{
+ int np=0;
+ int count=0;
+ if(argc != 3){
+ usage(argv[0]);
+ }
+ np=atoi(argv[1]);
+ count=atoi(argv[2]);
+ AtomicCounter* counter=new AtomicCounter("test counter", 0);
+ ThreadGroup* group=new ThreadGroup("test group");
+ for(int i=0;i<np;i++){
+ char buf[100];
+ sprintf(buf, "worker %d", i);
+ new Thread(new AtomicCountTest(counter, count, i, np), strdup(buf),
group);
+ }
+ group->join();
+ AtomicCounter& counter_ref = *counter;
+ int result = counter_ref;
+ printf("adding result = %d\n", result);
+ if (result != np * count) {
+ return -1;
+ }
+ return 0;
+}
+
+AtomicCountTest::AtomicCountTest(AtomicCounter* counter,
+ int count, int proc, int np)
+ : counter(counter), count(count), proc(proc), np(np)
+{
+}
+
+void AtomicCountTest::run()
+{
+ for(int i=0;i<count;i++){
+ AtomicCounter& ref_counter = *counter;
+ ref_counter++;
+ }
+}
+
+
- [Manta] r1724 - in trunk: Core Core/Util Engine/Control Interface Model/Groups Model/Groups/private Model/Instances Model/MiscObjects SCIRun/Core include scenes tests, boulos, 09/15/2007
Archive powered by MHonArc 2.6.16.