more source-level documentation

metadata
Wenzel Jakob 2010-09-15 21:15:42 +02:00
parent 768bacccdc
commit 7a18e43123
12 changed files with 331 additions and 226 deletions

View File

@ -23,7 +23,7 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
/** \brief Console stream /** \brief Interface to the default stdin/stdout console streams
*/ */
class MTS_EXPORT_CORE ConsoleStream : public Stream { class MTS_EXPORT_CORE ConsoleStream : public Stream {
public: public:

View File

@ -38,9 +38,10 @@ MTS_NAMESPACE_BEGIN
class MTS_EXPORT_CORE FileResolver : public Object { class MTS_EXPORT_CORE FileResolver : public Object {
public: public:
/** /**
* Create a new file resolver containing the * \brief Create a new file resolver with the default settings
* current working directory as the initial *
* search path. * Create a new file resolver containing the current working
* directory as the initial search path.
*/ */
FileResolver(); FileResolver();

View File

@ -24,8 +24,7 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
/** /**
* Uniform 3D grid for storing arbitrary quantities, which can * \brief Uniform 3D grid for storing and manipulating arbitrary quantities
* be queried and updated by rasterizing rays to the grid.
*/ */
template <typename ValueType> class Grid { template <typename ValueType> class Grid {
public: public:
@ -98,7 +97,7 @@ public:
inline const ValueType &operator()(int x, int y, int z) const { inline const ValueType &operator()(int x, int y, int z) const {
return m_cells[x + y*m_res.x + z*m_slab]; return m_cells[x + y*m_res.x + z*m_slab];
} }
/// Return the underlying array /// Return a pointer to the underlying array
inline ValueType *getData() const { return m_cells; } inline ValueType *getData() const { return m_cells; }
/// Return a string representation /// Return a string representation
@ -172,7 +171,10 @@ public:
return true; return true;
} }
/// Rasterize a ray to the grid /**
* \brief Rasterize a ray to the grid and apply the functor to
* every traversed cell
*/
template <typename Functor> void rasterize(const Ray &ray, Functor &functor) { template <typename Functor> void rasterize(const Ray &ray, Functor &functor) {
Float mint, maxt, t; Float mint, maxt, t;

View File

@ -25,9 +25,10 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
/** /**
* Templated multiple-reference octree. Based on the excellent * \brief Generic multiple-reference octree.
* implementation in PBRT. Modifications are the addition of a *
* bounding sphere query and support for multithreading. * Based on the excellent implementation in PBRT. Modifications are
* the addition of a bounding sphere query and support for multithreading.
*/ */
template <typename T> class Octree { template <typename T> class Octree {
public: public:

View File

@ -86,12 +86,17 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
/**
* \brief %Random number generator based on Mersenne Twister
* by Takuji Nishimura and Makoto Matsumoto.
*/
class MTS_EXPORT_CORE Random : public SerializableObject { class MTS_EXPORT_CORE Random : public SerializableObject {
public: public:
/** /**
* Construct a new seeded random generator. Uses the default * \brief Construct a new seeded random generator.
* seed on Windows and '/dev/urandom' on OSX and Linux. *
* Uses the default seed on Windows and '/dev/urandom'
* on OSX and Linux.
*/ */
Random(); Random();
@ -123,8 +128,10 @@ public:
Float nextFloat(); Float nextFloat();
/** /**
* Draw a uniformly distributed permutation and permute the given STL container * \brief Draw a uniformly distributed permutation and permute the
* (see Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2) * given STL container.
*
* See Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2.
*/ */
template <typename Iterator> void shuffle(Iterator it1, Iterator it2) { template <typename Iterator> void shuffle(Iterator it1, Iterator it2) {
for (Iterator it = it2 - 1; it > it1; --it) for (Iterator it = it2 - 1; it > it1; --it)

View File

@ -102,7 +102,7 @@ struct Ray {
} }
}; };
/** \brief Ray differential -- enhances the basic ray class with /** \brief %Ray differential -- enhances the basic ray class with
information about the rays of adjacent pixels on the view plane */ information about the rays of adjacent pixels on the view plane */
struct RayDifferential : public Ray { struct RayDifferential : public Ray {
bool hasDifferentials; bool hasDifferentials;
@ -124,11 +124,24 @@ struct RayDifferential : public Ray {
: Ray(ray), hasDifferentials(ray.hasDifferentials), rx(ray.rx), ry(ray.ry) { : Ray(ray), hasDifferentials(ray.hasDifferentials), rx(ray.rx), ry(ray.ry) {
} }
inline void operator=(const Ray &ray) { inline void operator=(const RayDifferential &ray) {
setOrigin(ray.o); o = ray.o;
setDirection(ray.d);
mint = ray.mint; mint = ray.mint;
d = ray.d;
maxt = ray.maxt; maxt = ray.maxt;
dRcp = ray.dRcp;
hasDifferentials = ray.hasDifferentials;
rx = ray.rx;
ry = ray.ry;
}
inline void operator=(const Ray &ray) {
o = ray.o;
mint = ray.mint;
d = ray.d;
maxt = ray.maxt;
dRcp = ray.dRcp;
hasDifferentials = false;
} }
}; };

View File

@ -32,7 +32,7 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
/** /**
* Abstract work unit. Represents a small amount of information * \brief Abstract work unit -- represents a small amount of information
* that encodes part of a larger processing task. * that encodes part of a larger processing task.
*/ */
class MTS_EXPORT_CORE WorkUnit : public Object { class MTS_EXPORT_CORE WorkUnit : public Object {
@ -56,8 +56,8 @@ protected:
}; };
/** /**
* Abstract work result. Represents the information that encodes * \brief Abstract work result -- represents the result of a
* the result of a processed <tt>WorkUnit</tt> instance. * processed <tt>\ref WorkUnit</tt> instance.
*/ */
class MTS_EXPORT_CORE WorkResult : public Object { class MTS_EXPORT_CORE WorkResult : public Object {
public: public:
@ -77,30 +77,28 @@ protected:
}; };
/** /**
* Abstract work processor. Takes work units and turns them into * \brief Abstract work processor -- takes work units and turns them into
* <tt>WorkResult</tt> instances. The class is serializable so that * <tt>WorkResult</tt> instances.
* it can be sent over the network if required. It is possible to *
* keep local state in <tt>WorkProcessor</tt> instances (e.g. scratch * The class is serializable so that it can be sent over the network if
* space for computations), though anything not returned in the form * required. It is possible to keep local state in <tt>WorkProcessor</tt>
* of <tt>WorkResult</tt>s will eventually be lost. Each worker * instances (e.g. scratch space for computations), though anything not
* (both locally and remotely) has its own <tt>WorkProcessor</tt>, * returned in the form of <tt>WorkResult</tt>s will eventually be lost.
* and therefore no form of locking is required. * Each worker (both locally and remotely) has its own <tt>WorkProcessor</tt>,
* and therefore no form of locking is required within instances of this class.
*/ */
class MTS_EXPORT_CORE WorkProcessor : public SerializableObject { class MTS_EXPORT_CORE WorkProcessor : public SerializableObject {
friend class Scheduler; friend class Scheduler;
public: public:
/** /// Create a work unit of the proper type and size.
* Create a work unit of the proper type and size.
*/
virtual ref<WorkUnit> createWorkUnit() const = 0; virtual ref<WorkUnit> createWorkUnit() const = 0;
/** /// Create a work result of the proper type and size
* Create a work result of the proper type and size
*/
virtual ref<WorkResult> createWorkResult() const = 0; virtual ref<WorkResult> createWorkResult() const = 0;
/** /**
* Create a copy of this work processor instance. * \brief Create a copy of this work processor instance.
*
* Note: Before the cloned work processor is used, its * Note: Before the cloned work processor is used, its
* prepare() method will be called - therefore, state * prepare() method will be called - therefore, state
* that is initialized there does not have to be copied. * that is initialized there does not have to be copied.
@ -108,22 +106,23 @@ public:
virtual ref<WorkProcessor> clone() const = 0; virtual ref<WorkProcessor> clone() const = 0;
/** /**
* Called once before processing starts. This is useful for allocating * \brief Called once before processing starts.
* scratch space or resolving references to resource objects. Lengthy *
* computations should be performed in process() instead of here, since * This is useful for allocating scratch space or resolving references
* this this method will be called while the central scheduler lock * to resource objects. Lengthy computations should be performed in
* is held. A thrown exception will lead to the termination of the parallel * process() instead of here, since this this method will be called
* process. * while the central scheduler lock is held. A thrown exception will
* lead to the termination of the parallel process.
*/ */
virtual void prepare() = 0; virtual void prepare() = 0;
/** /**
* Process a work unit and store the computed results. The <tt>active</tt> * \brief Process a work unit and store the computed results.
* parameter can be used to signal a premature stop of the execution flow. *
* In this case, the work result is allowed to be undefined (it will * The <tt>active</tt> parameter can be used to signal a premature
* simply be ignored). * stop of the execution flow. In this case, the work result is allowed
* A thrown exception will lead to the termination of the parallel * to be undefined (it will simply be ignored). A thrown exception will
* process. * lead to the termination of the parallel process.
*/ */
virtual void process(const WorkUnit *workUnit, WorkResult *workResult, virtual void process(const WorkUnit *workUnit, WorkResult *workResult,
const bool &stop) = 0; const bool &stop) = 0;
@ -138,9 +137,10 @@ protected:
: SerializableObject(stream, manager) { } : SerializableObject(stream, manager) { }
/** /**
* Look up a named resource, which has been bound to the associated * \brief Look up a named resource, which has been bound to
* parallel process. Throws an exception if the resource is not * the associated parallel process.
* known / bound. *
* Throws an exception if the resource is not known / bound.
*/ */
SerializableObject *getResource(const std::string &name); SerializableObject *getResource(const std::string &name);
protected: protected:
@ -148,114 +148,143 @@ protected:
}; };
/** /**
* Abstract parallelizable task. Models a larger piece of work that * \brief Abstract parallelizable task.
* can be split into independent `units' and subsequently farmed *
* out over a cluster or processed locally. After the work units have * Models a larger piece of work that can be split into independent
* been completed, the results are pieced back together to a solution of * `units' and subsequently farmed out over a cluster or processed locally.
* the original large-scale problem. This class implements the core logic * After the work units have been completed, the results are pieced back
* running on the central scheduling server, i.e. the part that is * together to a solution of the original large-scale problem. This class
* responsible for generating work units and accepting their results. * implements the core logic running on the central scheduling server,
* The module that performs the actual computation is an instance of * i.e. the part that is responsible for generating work units and
* <tt>WorkProcessor</tt>, which is also specified here. * accepting their results. The module that performs the actual computation
* is an instance of <tt>WorkProcessor</tt>, which is also specified here.
* Finally, the this class references `resources', which denote * Finally, the this class references `resources', which denote
* chunks of globally shared read-only data required during execution. * chunks of globally shared read-only data required during execution.
*/ */
class MTS_EXPORT_CORE ParallelProcess : public Object { class MTS_EXPORT_CORE ParallelProcess : public Object {
friend class Scheduler; friend class Scheduler;
public: public:
/// Binding from local resource names to global resource IDs
typedef std::map<std::string, int> ResourceBindings; typedef std::map<std::string, int> ResourceBindings;
/// Return codes used by generateWork() and getReturnStatus() /// Return codes used by generateWork() and getReturnStatus()
enum EStatus { enum EStatus {
EUnknown, EUnknown, ///< Unknown return status
EPause, EPause, ///< Temporarily, no work units can be created
ESuccess, ESuccess, ///< The process finished / a piece of work was generated
EFailure EFailure ///< The process failed / no more work is available
}; };
/** /**
* Generate a piece of work. Takes a pre-allocated <tt>WorkUnit</tt> * \brief Generate a piece of work.
* instance of the appropriate sub-type and size (as specified by *
* <tt>ParallelProcess::getWorkUnitName</tt>) and fills it with the * Takes a pre-allocated <tt>\ref WorkUnit</tt> instance of
* appropriate content. Returns ESuccess on success and EFailure or EPause * the appropriate sub-type and size (as specified by
* when no more work is left -- in that case, the work unit will * <tt>\ref ParallelProcess::getWorkUnitName()</tt>) and
* be ignored and the process completed (EFailure) or temporarily * fills it with the appropriate content. Returns ESuccess
* paused (EPause). When EPause was used, resubmission via * on success and EFailure or EPause when no more work is
* <tt>Scheduler::schedule()</tt> will be required once more work * left -- in that case, the work unit will be ignored and
* is available. In some cases, it is useful to distribute 'nearby' * the process completed (\ref EFailure) or temporarily
* pieces of work to the same processor -- the <tt>worker</tt> * paused (\ref EPause). When \ref EPause was used,
* parameter can be used to implement this. * resubmission via <tt>\ref Scheduler::schedule()</tt> will
* This function should run as quickly as possible, since it will * be required once more work is available. In some cases, it
* be executed while the scheduler mutex is held. A thrown exception * is useful to distribute 'nearby' pieces of work to the same
* will lead to the termination of the parallel process. * processor -- the <tt>worker</tt> parameter can be used to
* implement this.
* This function should run as quickly as possible, since it
* will be executed while the scheduler mutex is held. A
* thrown exception will lead to the termination of the
* parallel process.
*
* \param unit Work unit data structure to be filled
* \param worker ID of the worker executing this function
*/ */
virtual EStatus generateWork(WorkUnit *unit, int worker) = 0; virtual EStatus generateWork(WorkUnit *unit, int worker) = 0;
/** /**
* Called whenever a work unit has been completed. Note * \brief Called whenever a work unit has been completed.
* that this may be executed by different threads and *
* likely out of order (some sort of locking will * Note that this function may concurrently be executed by
* generally be required when modifying data structures). * multiple threads. Also, processing of work results will
* generally be out of order with respect to the creation
* in \ref generateWork().
*
* When a work unit is only partially completed due to * When a work unit is only partially completed due to
* a call to <tt>Scheduler::cancel</tt>, the second * a call to <tt>Scheduler::cancel</tt>, the second
* parameter is set to true. * parameter is set to true.
* A thrown exception will lead to the termination of * A thrown exception will lead to the termination of
* the parallel process. * the parallel process.
*
* \param result Work result to be processed
* \param cancelled Was the associated work unit not fully completed
*/ */
virtual void processResult(const WorkResult *result, virtual void processResult(const WorkResult *result,
bool cancelled) = 0; bool cancelled) = 0;
/** /**
* Called when the parallel process is canceled * \brief Called when the parallel process is canceled by
* by Scheduler::cancel(). The default implementation * \ref Scheduler::cancel().
* does nothing. *
* The default implementation does nothing.
*/ */
virtual void handleCancellation(); virtual void handleCancellation();
/** /**
* After a process has finished excecution, its return * \brief Query the return status of a process after its
* status can be queried through this method. * execution has finished.
* Returns one of <tt>Success, Failure or Unknown</tt> *
* (EUnknown means that the process is either still running * Returns one of <tt>\ref Success, \ref Failure or \ref Unknown</tt>
* (\ref EUnknown means that the process is either still running
* or has never been scheduled). * or has never been scheduled).
*/ */
inline EStatus getReturnStatus() const { return m_returnStatus; } inline EStatus getReturnStatus() const { return m_returnStatus; }
/** /**
* Create an instance of the algorithm responsible * \brief Create an instance of the algorithm responsible
* for executing the work units of this parallel process. * for executing the work units of this parallel process.
*/ */
virtual ref<WorkProcessor> createWorkProcessor() const = 0; virtual ref<WorkProcessor> createWorkProcessor() const = 0;
/** /**
* Bind a resource to this parallel process. Takes a resource * \brief Bind a resource to this parallel process.
* ID as given by the scheduler and associates it with a name. *
* This name can later be used by the work processor to access * Takes a resource ID as given by the scheduler and associates it
* the resource data. * with a name. This name can later be used by the work processor
* to access the resource data.
*
* \param name Process-specific name of the resource
* \param id Resource ID as returned by \ref Scheduler::registerResource()
* \sa WorkProcessor::getResource
*/ */
virtual void bindResource(const std::string &name, int id); virtual void bindResource(const std::string &name, int id);
/** /**
* Is this process local, i.e. not distributed to remote * \brief Is this process strictly local?
* processing nodes? The default implementation returs false. *
* If a process is marked as local, it shouldn't be distributed
* to remote processing nodes? The default implementation
* returns false.
*/ */
virtual bool isLocal() const; virtual bool isLocal() const;
/** /**
* Return the log level for events associated with this process. * \brief Return the log level for events associated with this process.
*
* By default, this is set to EDebug * By default, this is set to EDebug
*/ */
inline ELogLevel getLogLevel() const { return m_logLevel; } inline ELogLevel getLogLevel() const { return m_logLevel; }
/** /**
* Return a list of the bound resources * \brief Return a list of all bound resources
*/ */
inline const ResourceBindings &getResourceBindings() const { return m_bindings; } inline const ResourceBindings &getResourceBindings() const { return m_bindings; }
/** /**
* Return a list of plugins required by this parallel process. * \brief Return a list of plugins required by this parallel process.
* The default implementation just returns all plugins that are *
* loaded in the current application image. * This is required so that remote machines can load the plugins before
* they accept work from this process. The default implementation just
* returns all plugins that are loaded in the current application.
*/ */
virtual std::vector<std::string> getRequiredPlugins(); virtual std::vector<std::string> getRequiredPlugins();
@ -275,35 +304,40 @@ protected:
class Worker; class Worker;
/** /**
* Centralized task scheduler implementation. Accepts parallelizable * \brief Centralized task scheduler implementation.
* jobs and distributes their computational load both locally and remotely. *
* This is done by associating different types of <tt>Worker</tt>s with * Accepts parallelizable jobs and distributes their computational load
* the scheduler. These try to acquire work units from the scheduler, * both locally and remotely. This is done by associating different types
* which are then executed on the current machine or sent to remote * of <tt>\ref Worker</tt>s with the scheduler. These try to acquire work
* nodes over a network connection. * units from the scheduler, which are then executed on the current machine
* or sent to remote nodes over a network connection.
*/ */
class MTS_EXPORT_CORE Scheduler : public Object { class MTS_EXPORT_CORE Scheduler : public Object {
friend class Worker; friend class Worker;
public: public:
/** /**
* Schedule a parallelizable process for execution. If the * \brief Schedule a parallelizable process for execution.
* scheduler is currently running and idle, its execution *
* will begin immediately. Returns false if the process * If the scheduler is currently running and idle, its execution
* is already scheduled and has not yet terminated. * will begin immediately. Returns \a false if the process
* is already scheduled and has not yet terminated and \a true
* in any other case.
*/ */
bool schedule(ParallelProcess *process); bool schedule(ParallelProcess *process);
/** /**
* Block until the process has successfully been completed * \brief Block until the process has successfully been completed
* or canceled prematurely. Returns false if the process * or canceled prematurely.
* does not exist or has already finished by the time *
* <tt>wait()</tt> is invoked. * Returns false if the process does not exist or has already
* finished by the time <tt>\ref wait()</tt> is invoked.
*/ */
bool wait(const ParallelProcess *process); bool wait(const ParallelProcess *process);
/** /**
* Cancel the execution of a parallelizable process. Upon * \brief Cancel the execution of a parallelizable process.
* return, no more work from this process is running. *
* Upon return, no more work from this process is running.
* Returns false if the process does not exist (anymore). * Returns false if the process does not exist (anymore).
*/ */
inline bool cancel(ParallelProcess *proc) { inline bool cancel(ParallelProcess *proc) {
@ -311,41 +345,48 @@ public:
} }
/** /**
* Register a serializable resource with the scheduler. This should be * \brief Register a serializable resource with the scheduler.
* thought of as a constant state that is shared amongst all processing *
* nodes. Resources can be reused by subsequent parallel processes, and * A resource should be thought of as a constant state that is shared
* consequently do not have to be re-transmitted over the network. Returns * amongst all processing nodes. Resources can be reused by
* a resource ID, which can be used to reference the associated data. * subsequent parallel processes, and consequently do not have to be
* re-transmitted over the network. Returns a resource ID, which can be
* used to reference the associated data.
*/ */
int registerResource(SerializableObject *resource); int registerResource(SerializableObject *resource);
/** /**
* Register a 'manifold' resource with the scheduler. Manifold means that * \brief Register a \a manifold resource with the scheduler.
* in comparison to the previous method, a separate instance is provided * Manifold means that in comparison to the previous method, a separate
* for every core. An example where this is useful is to distribute * instance is provided for every core. An example where this is useful
* random generator state when performing parallel Monte Carlo simulations. * is to distribute random generator state when performing parallel
* <tt>resources</tt> must be a vector whose length is equal * Monte Carlo simulations. <tt>resources</tt> must be a vector whose
* to <tt>getCoreCount()</tt>. * length is equal to <tt>\ref getCoreCount()</tt>.
*/ */
int registerManifoldResource(std::vector<SerializableObject *> &resources); int registerManifoldResource(std::vector<SerializableObject *> &resources);
/** /**
* Increase the reference count of a previously registered resource. * \brief Increase the reference count of a previously registered resource.
*
* The resource must be unregistered an additional time after calling * The resource must be unregistered an additional time after calling
* this function. * this function.
*
* \sa unregisterResource
*/ */
void retainResource(int resourceID); void retainResource(int resourceID);
/** /**
* Unregister a resource from the scheduler (takes the previously * \brief Unregister a resource from the scheduler
* created ID). Note that the resource's won't be removed *
* until all processes using it have terminated) * Note that the resource's won't be removed until all processes using
* it have terminated)
*/ */
void unregisterResource(int id); void unregisterResource(int id);
/** /**
* Return the ID of a registered resource. Throws an exception * \brief Return the ID of a registered resource
* if the resource cannot be found. *
* Throws an exception if the resource cannot be found.
*/ */
int getResourceID(const SerializableObject *resource) const; int getResourceID(const SerializableObject *resource) const;
@ -365,15 +406,15 @@ public:
void start(); void start();
/** /**
* Puase the distribution of work units and shut down all running workers. * \brief Pause the distribution of work units and shut down all
* Any currently scheduled work units are still completed. Processing can * running workers.
* be resumed via <tt>start()</tt>. *
* Any currently scheduled work units are still completed.
* Processing can be resumed via <tt>\ref start()</tt>.
*/ */
void pause(); void pause();
/** /// Cancel all running processes and free memory used by resources
* Cancel all running processes and free memory used by resources
*/
void stop(); void stop();
/// Return the total number of cores exposed through this scheduler /// Return the total number of cores exposed through this scheduler
@ -589,7 +630,7 @@ private:
}; };
/** /**
* Base class of all worker implementations * \brief Base class of all worker implementations
*/ */
class MTS_EXPORT_CORE Worker : public Thread { class MTS_EXPORT_CORE Worker : public Thread {
friend class Scheduler; friend class Scheduler;
@ -615,20 +656,22 @@ protected:
int workerIndex, int coreOffset); int workerIndex, int coreOffset);
/** /**
* Called to inform a worker that a resource is no longer in use. The * \brief Called to inform a worker that a resource is no longer in use.
* remote worker uses this to notify the machine on the other end that *
* The remote worker uses this to notify the machine on the other end that
* the memory used by this resource can now be released. * the memory used by this resource can now be released.
*/ */
virtual void signalResourceExpiration(int id) = 0; virtual void signalResourceExpiration(int id) = 0;
/** /**
* Called to inform a worker that a process has been cancelled * \brief Called to inform a worker that a process has been cancelled
*
* Guaranteed to be called while the Scheduler's main lock is held. * Guaranteed to be called while the Scheduler's main lock is held.
*/ */
virtual void signalProcessCancellation(int id) = 0; virtual void signalProcessCancellation(int id) = 0;
/** /**
* Called to inform a worker that a process has successfully been * \brief Called to inform a worker that a process has successfully been
* completed and any associated resources can be freed. * completed and any associated resources can be freed.
*/ */
virtual void signalProcessTermination(int id) = 0; virtual void signalProcessTermination(int id) = 0;
@ -669,7 +712,7 @@ protected:
}; };
/** /**
* Local worker thread. Acquires work from the scheduler and executes * \brief Acquires work from the scheduler and executes
* it locally. * it locally.
*/ */
class MTS_EXPORT_CORE LocalWorker : public Worker { class MTS_EXPORT_CORE LocalWorker : public Worker {

View File

@ -21,11 +21,11 @@
#include <mitsuba/core/sched.h> #include <mitsuba/core/sched.h>
/* How many work units should be sent to a remote worker /** How many work units should be sent to a remote worker
at a time? This is a multiple of the worker's core count */ at a time? This is a multiple of the worker's core count */
#define BACKLOG_FACTOR 3 #define BACKLOG_FACTOR 3
/* Once the back log factor drops below this value (also a /** Once the back log factor drops below this value (also a
multiple of the core size), the stream processor will multiple of the core size), the stream processor will
continue sending batches of work units */ continue sending batches of work units */
#define CONTINUE_FACTOR 2 #define CONTINUE_FACTOR 2
@ -36,13 +36,16 @@ class RemoteWorkerReader;
class StreamBackend; class StreamBackend;
/** /**
* Remote worker thread. Acquires work from the scheduler and forwards * \brief Acquires work from the scheduler and forwards
* it to a processing node reachable over some form of stream (usually * it to a processing node reachable through a \ref Stream.
* a <tt>SocketStream</tt>).
*/ */
class MTS_EXPORT_CORE RemoteWorker : public Worker { class MTS_EXPORT_CORE RemoteWorker : public Worker {
friend class RemoteWorkerReader; friend class RemoteWorkerReader;
public: public:
/**
* \brief Construct a new remote worker with the given name and
* communication stream
*/
RemoteWorker(const std::string &name, Stream *stream); RemoteWorker(const std::string &name, Stream *stream);
/// Return the name of the node on the other side /// Return the name of the node on the other side
@ -84,8 +87,9 @@ protected:
}; };
/** /**
* Remote worker helper thread - constantly waits for finished * \brief Communication helper thread required by \ref RemoteWorker.
* work units sent by the processing node. *
* Constantly waits for finished work units sent by the processing node.
*/ */
class MTS_EXPORT_CORE RemoteWorkerReader : public Thread { class MTS_EXPORT_CORE RemoteWorkerReader : public Thread {
friend class RemoteWorker; friend class RemoteWorker;
@ -110,11 +114,19 @@ private:
}; };
/** /**
* 'Fake' parallel process used to insert work units from a * \brief Parallel process facade used to insert work units from a
* remote scheduler into the local one. * remote scheduler into the local one.
*/ */
class MTS_EXPORT_CORE RemoteProcess : public ParallelProcess { class MTS_EXPORT_CORE RemoteProcess : public ParallelProcess {
public: public:
/**
* \brief Create a new remote process
*
* \param id Identification number for this process
* \param logLevel Log level for events associated with this process
* \param backend The responsible server-side communication backend
* \param proc Work processor instance for use with this process
*/
RemoteProcess(int id, ELogLevel logLevel, RemoteProcess(int id, ELogLevel logLevel,
StreamBackend *backend, WorkProcessor *proc); StreamBackend *backend, WorkProcessor *proc);
@ -125,6 +137,7 @@ public:
ref<WorkProcessor> createWorkProcessor() const; ref<WorkProcessor> createWorkProcessor() const;
void handleCancellation(); void handleCancellation();
/// Get an empty work unit from the process (or create one)
inline WorkUnit *getEmptyWorkUnit() { inline WorkUnit *getEmptyWorkUnit() {
ref<WorkUnit> wu; ref<WorkUnit> wu;
m_mutex->lock(); m_mutex->lock();
@ -139,12 +152,14 @@ public:
return wu; return wu;
} }
/// Make a full work unit available to the process
inline void putFullWorkUnit(WorkUnit *wu) { inline void putFullWorkUnit(WorkUnit *wu) {
m_mutex->lock(); m_mutex->lock();
m_full.push_back(wu); m_full.push_back(wu);
m_mutex->unlock(); m_mutex->unlock();
} }
/// Mark the process as finished
inline void setDone() { inline void setDone() {
m_mutex->lock(); m_mutex->lock();
m_done = true; m_done = true;
@ -166,9 +181,10 @@ private:
}; };
/** /**
* Stream backend - attaches to the end of a stream, accepts work units * \brief Network processing communication backend
* and forwards them to the local scheduler. Can be used to create *
* remote processing nodes. * Attaches to the end of a stream, accepts work units and forwards
* them to the local scheduler. Can be used to create network processing nodes.
*/ */
class MTS_EXPORT_CORE StreamBackend : public Thread { class MTS_EXPORT_CORE StreamBackend : public Thread {
friend class RemoteProcess; friend class RemoteProcess;
@ -192,7 +208,7 @@ public:
}; };
/** /**
* Create a new stream backend * \brief Create a new stream backend
* *
* @param name * @param name
* Name of the created thread * Name of the created thread

View File

@ -32,10 +32,13 @@ namespace ublas = boost::numeric::ublas;
struct SHVector; struct SHVector;
/* Stores the diagonal blocks of a spherical harmonic rotation matrix */ /**
* \brief Stores the diagonal blocks of a spherical harmonic rotation matrix
*/
struct MTS_EXPORT_CORE SHRotation { struct MTS_EXPORT_CORE SHRotation {
std::vector<ublas::matrix<Float> > blocks; std::vector<ublas::matrix<Float> > blocks;
/// Construct a new rotation storage for the given number of bands
inline SHRotation(int bands) : blocks(bands) { inline SHRotation(int bands) : blocks(bands) {
for (int i=0; i<bands; ++i) { for (int i=0; i<bands; ++i) {
int dim = 2*i+1; int dim = 2*i+1;
@ -44,26 +47,31 @@ struct MTS_EXPORT_CORE SHRotation {
} }
/** /**
* Transform a coefficient vector and store the result into * \brief Transform a coefficient vector and store the result into
* the given target vector. The source and target must have * the given target vector.
* the same number of bands. *
* The source and target must have the same number of bands.
*/ */
void operator()(const SHVector &source, SHVector &target) const; void operator()(const SHVector &source, SHVector &target) const;
}; };
/** /**
* Stores a truncated real spherical harmonics representation of * \brief Stores a truncated real spherical harmonics representation of
* an L2-integrable function. Also provides some other useful * an L2-integrable function.
* functionality, such as evaluation, projection and rotation. *
* Also provides some other useful functionality, such as evaluation,
* projection and rotation.
* *
* The Mathematica equivalent of the basis functions implemented here is: * The Mathematica equivalent of the basis functions implemented here is:
* *
* <pre>
* SphericalHarmonicQ[l_, m_, \[Theta]_, \[Phi]_] := * SphericalHarmonicQ[l_, m_, \[Theta]_, \[Phi]_] :=
* Piecewise[{ * Piecewise[{
* {SphericalHarmonicY[l, m, \[Theta], \[Phi]], m == 0}, * {SphericalHarmonicY[l, m, \[Theta], \[Phi]], m == 0},
* {Sqrt[2]*Re[SphericalHarmonicY[l, m, \[Theta], \[Phi]]], m > 0}, * {Sqrt[2]*Re[SphericalHarmonicY[l, m, \[Theta], \[Phi]]], m > 0},
* {Sqrt[2]*Im[SphericalHarmonicY[l, -m, \[Theta], \[Phi]]], m < 0} * {Sqrt[2]*Im[SphericalHarmonicY[l, -m, \[Theta], \[Phi]]], m < 0}
* }] * }]
* </pre>
*/ */
struct MTS_EXPORT_CORE SHVector { struct MTS_EXPORT_CORE SHVector {
public: public:
@ -169,18 +177,20 @@ public:
/// Evaluate for a direction given in spherical coordinates /// Evaluate for a direction given in spherical coordinates
Float eval(Float theta, Float phi) const; Float eval(Float theta, Float phi) const;
/// Evaluate for a direction given in cartesian coordinates /// Evaluate for a direction given in Cartesian coordinates
Float eval(const Vector &v) const; Float eval(const Vector &v) const;
/** /**
* Evaluate for a direction given in spherical coordinates. * \brief Evaluate for a direction given in spherical coordinates.
*
* This function is much faster but only works for azimuthally * This function is much faster but only works for azimuthally
* invariant functions * invariant functions
*/ */
Float evalAzimuthallyInvariant(Float theta, Float phi) const; Float evalAzimuthallyInvariant(Float theta, Float phi) const;
/** /**
* Evaluate for a direction given in cartesian coordinates. * \brief Evaluate for a direction given in cartesian coordinates.
*
* This function is much faster but only works for azimuthally * This function is much faster but only works for azimuthally
* invariant functions * invariant functions
*/ */
@ -214,8 +224,10 @@ public:
void offset(Float value); void offset(Float value);
/** /**
* Convolve the SH representation with the supplied kernel, * \brief Convolve the SH representation with the supplied kernel.
* which must be rotationally symmetric around the Z-axis. *
* Based on the Funk-Hecke theorem -- the kernel must be rotationally
* symmetric around the Z-axis.
*/ */
void convolve(const SHVector &kernel); void convolve(const SHVector &kernel);
@ -303,7 +315,7 @@ public:
return error/denom; return error/denom;
} }
/* Evaluate an associated Legendre polynomial using the usual recurrence formulae */ /// Evaluate an associated Legendre polynomial using the usual recurrence formulae
static Float legendre(int l, int m, Float x); static Float legendre(int l, int m, Float x);
/// Return a normalization coefficient /// Return a normalization coefficient
@ -315,8 +327,9 @@ public:
} }
/** /**
* Recursively computes rotation matrices for each band of SH coefficients. Based on * \brief Recursively computes rotation matrices for each band of SH coefficients.
* 'Rotation Matrices for Real Spherical Harmonics. Direct Determination by Recursion' *
* Based on 'Rotation Matrices for Real Spherical Harmonics. Direct Determination by Recursion'
* by Ivanic and Ruedenberg. The implemented tables follow the notation in * by Ivanic and Ruedenberg. The implemented tables follow the notation in
* 'Spherical Harmonic Lighting: The Gritty Details' by Robin Green. * 'Spherical Harmonic Lighting: The Gritty Details' by Robin Green.
*/ */
@ -340,22 +353,23 @@ private:
}; };
/** /**
* Implementation of 'Importance Sampling Spherical Harmonics' * \brief Implementation of 'Importance Sampling Spherical Harmonics'
* by W. Jarsz, N. Carr and H. W. Jensen (EUROGRAPHICS 2009) * by W. Jarsz, N. Carr and H. W. Jensen (EUROGRAPHICS 2009)
*/ */
class MTS_EXPORT_CORE SHSampler : public Object { class MTS_EXPORT_CORE SHSampler : public Object {
public: public:
/** /**
* Create a spherical harmonics sampler object for the * \brief Precompute a spherical harmonics sampler object
* specified amount of SH coefficient bands. The 'depth' *
* parameter specifies the number of recursive sample * \param bands Number of SH coefficient bands to support
* warping steps. * \param depth Number of recursive sample warping steps.
*/ */
SHSampler(int bands, int depth); SHSampler(int bands, int depth);
/** /**
* Warp a uniform sample in [0,1]^2 to one that is * \brief Warp a uniform sample in [0,1]^2 to one that is
* approximately proportional to the specified function. * approximately proportional to the specified function.
*
* The resulting sample will have spherical coordinates * The resulting sample will have spherical coordinates
* [0,pi]x[0,2pi] and its actual PDF (which might be * [0,pi]x[0,2pi] and its actual PDF (which might be
* slightly different from the function evaluated at the * slightly different from the function evaluated at the
@ -381,11 +395,11 @@ protected:
return -m_phiMap[depth][phiBlock][P(m)] * m_legendreMap[depth][zBlock][I(l, std::abs(m))]; return -m_phiMap[depth][phiBlock][P(m)] * m_legendreMap[depth][zBlock][I(l, std::abs(m))];
} }
/* Recursively compute assoc. legendre & phi integrals */ /// Recursively compute assoc. legendre & phi integrals
Float *legendreIntegrals(Float a, Float b); Float *legendreIntegrals(Float a, Float b);
Float *phiIntegrals(Float a, Float b); Float *phiIntegrals(Float a, Float b);
/* Integrate a SH expansion over the specified mip-map region */ /// Integrate a SH expansion over the specified mip-map region
Float integrate(int depth, int zBlock, int phiBlock, const SHVector &f) const; Float integrate(int depth, int zBlock, int phiBlock, const SHVector &f) const;
protected: protected:
int m_bands; int m_bands;

View File

@ -24,10 +24,11 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
/** /**
* Stores a 4D function f(wi, wo) (such as a BRDF or phase function) * \brief Stores a 4D function f(wi, wo) (such as a BRDF or phase function)
* using a 2D table of spherical harmonics expansions. Discretizaiton * using a 2D table of spherical harmonics expansions.
* occurs in the 'wi' space. Later lookups interpolate amongst *
* the 4 adjacent samples * Discretizaiton occurs in the 'wi' space. Lookups interpolate amongst
* the 4 adjacent samples.
*/ */
struct SHVector4D { struct SHVector4D {
public: public:

View File

@ -25,14 +25,15 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
/** /**
* Mesh vertex data structure. Stores 3D coordinates, * \brief Mesh vertex data structure. Stores 3D coordinates,
* vertex normals, UV coordinates and a tangent frame * vertex normals, UV coordinates and a tangent frame.
*/ */
struct Vertex { struct Vertex {
Point v; Point v; ///< %Vertex position
Normal n; Normal n; ///< %Vertex normal
Point2 uv; Point2 uv; ///< %Texture coordinates
Vector dpdu, dpdv; Vector dpdu; ///< Partial derivative of the position with respect to \a u.
Vector dpdv; ///< Partial derivative of the position with respect to \a v.
inline bool operator==(const Vertex &vert) const { inline bool operator==(const Vertex &vert) const {
return (v == vert.v && n == vert.n && uv == vert.uv return (v == vert.v && n == vert.n && uv == vert.uv
@ -44,26 +45,29 @@ struct Vertex {
} }
}; };
/** \brief Triangle class including a collection of routines /**
* for analysis and transformation. Triangles are stored as * \brief Simple triangle class including a collection of routines
* indices into a vertex array * for analysis and transformation.
*
* Triangles are stored as indices into a vertex array
*/ */
struct MTS_EXPORT_CORE Triangle { struct MTS_EXPORT_CORE Triangle {
/* Indices into a vertex buffer */ /// Indices into a vertex buffer
unsigned int idx[3]; unsigned int idx[3];
/// Construct an axis-aligned box, which contains the triangle /// Construct an axis-aligned box, which contains the triangle
AABB getAABB(const Vertex *buffer) const; AABB getAABB(const Vertex *buffer) const;
/** /**
* Returns the axis-aligned bounding box of a triangle after it has * \brief Returns the axis-aligned bounding box of a triangle after it has
* clipped to the extends of another, given AABB. This function uses the * clipped to the extends of another, given AABB.
* Sutherland-Hodgman algorithm to calculate the convex polygon, which *
* is created when applying all 6 AABB splitting planes to the triangle. * This function uses the Sutherland-Hodgman algorithm to calculate the
* Afterwards, the AABB of the newly created convex polygon is returned. * convex polygon, which is created when applying all 6 AABB splitting
* This function is an important component for efficiently creating * planes to the triangle. Afterwards, the AABB of the newly created
* 'Perfect Split' KD-trees. For more detail, see * convex polygon is returned. This function is an important component
* "On building fast kd-Trees for Ray Tracing, and on doing * for efficiently creating 'Perfect Split' KD-trees. For more detail,
* see "On building fast kd-Trees for Ray Tracing, and on doing
* that in O(N log N)" by Ingo Wald and Vlastimil Havran * that in O(N log N)" by Ingo Wald and Vlastimil Havran
*/ */
AABB getClippedAABB(const Vertex *buffer, const AABB &aabb) const; AABB getClippedAABB(const Vertex *buffer, const AABB &aabb) const;
@ -73,8 +77,8 @@ struct MTS_EXPORT_CORE Triangle {
* Uses the algorithm presented by Moeller and Trumbore at * Uses the algorithm presented by Moeller and Trumbore at
* http://www.acm.org/jgt/papers/MollerTrumbore97/code.html * http://www.acm.org/jgt/papers/MollerTrumbore97/code.html
* Returns true if an intersection has been detected * Returns true if an intersection has been detected
* On success, pT contains the distance from the ray origin to the * On success, \a t contains the distance from the ray origin to the
* intersection point and pUV contains the intersection point in * intersection point, and \a u and \a v contain the intersection point in
* the local triangle coordinate system * the local triangle coordinate system
*/ */
bool rayIntersect(const Vertex *buffer, const Ray &ray, Float &u, bool rayIntersect(const Vertex *buffer, const Ray &ray, Float &u,

View File

@ -38,19 +38,18 @@
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
class SparseWavelet2D;
class SparseWaveletOctree;
/** /**
* Non-standard 2D Haar wavelet transformation. Based on * \brief Performs non-standard 2D Haar wavelet transformations.
* "Wavelets for computer graphics: A primer, part 1" by *
* Based on "Wavelets for computer graphics: A primer, part 1" by
* Eric J. Stollnitz, Tony D. DeRose, and David H. Salesin * Eric J. Stollnitz, Tony D. DeRose, and David H. Salesin
* (IEEE Computer Graphics and Applications, May 1995) * (IEEE Computer Graphics and Applications, May 1995)
*/ */
class MTS_EXPORT_CORE Wavelet2D : public Object { class MTS_EXPORT_CORE Wavelet2D : public Object {
public: public:
/** /**
* Create a wavelet representation from a given bitmap. * \brief Create a wavelet representation from a given bitmap.
*
* Only one color channel is supported for this encoding, so * Only one color channel is supported for this encoding, so
* the desired channel must be selected using the `colorChannel' * the desired channel must be selected using the `colorChannel'
* parameter. * parameter.
@ -61,7 +60,8 @@ public:
Wavelet2D(const SparseWavelet2D *sw); Wavelet2D(const SparseWavelet2D *sw);
/** /**
* Turn the wavelet representation back into an image. * \brief Turn the wavelet representation back into an image.
*
* Optionally, scale+offset factors can be supplied to * Optionally, scale+offset factors can be supplied to
* map the bitmap to a desired brightness * map the bitmap to a desired brightness
*/ */
@ -71,7 +71,7 @@ public:
void discard(Float fraction); void discard(Float fraction);
/** /**
* Discard components such that the relative L^2-error is below the * \brief Discard components such that the relative L^2-error is below the
* given bound. Returns the achieved compression ratio. * given bound. Returns the achieved compression ratio.
*/ */
Float compress(Float maxError); Float compress(Float maxError);
@ -122,7 +122,8 @@ protected:
}; };
/** /**
* Implements the non-standard 3D wavelet transform using Haar basis functions. * \brief Implements the non-standard 3D wavelet transform using
* Haar basis functions.
*/ */
class MTS_EXPORT_CORE Wavelet3D : public Object { class MTS_EXPORT_CORE Wavelet3D : public Object {
public: public:
@ -134,7 +135,7 @@ public:
Wavelet3D(const float *data, size_t resolution); Wavelet3D(const float *data, size_t resolution);
/** /**
* Turn the wavelet representation back into a dense format * \brief Turn the wavelet representation back into a dense format
*/ */
void decode(float *target); void decode(float *target);
@ -142,7 +143,7 @@ public:
void discard(Float fraction); void discard(Float fraction);
/** /**
* Discard components such that the relative L^2-error is below the * \brief Discard components such that the relative L^2-error is below the
* given bound. Returns the achieved compression ratio. * given bound. Returns the achieved compression ratio.
*/ */
Float compress(Float maxRelError); Float compress(Float maxRelError);
@ -193,7 +194,7 @@ protected:
}; };
/** /**
* Sparse 2D wavelet representation using the Haar basis * \brief Sparse 2D wavelet representation using the Haar basis
*/ */
class MTS_EXPORT_CORE SparseWavelet2D : public SerializableObject { class MTS_EXPORT_CORE SparseWavelet2D : public SerializableObject {
public: public:
@ -302,8 +303,9 @@ public:
Float getPixel(const Point2i &pt) const; Float getPixel(const Point2i &pt) const;
/** /**
* Compute a line integral in 2D wavelet space. Coordinates are * \brief Compute a line integral in 2D wavelet space.
* expected as pixel coordinates in [0,0]-[size,size], *
* Coordinates are expected as pixel coordinates in [0,0]-[size,size],
* but are allowed to be fractional * but are allowed to be fractional
*/ */
Float lineIntegral(Point2 start, Point2 end) const; Float lineIntegral(Point2 start, Point2 end) const;
@ -329,7 +331,8 @@ protected:
}; };
/** /**
* Sparse 3D wavelet representation using the Haar basis and an octree structure * \brief Sparse 3D wavelet representation using the Haar basis and an
* octree structure
*/ */
class MTS_EXPORT_CORE SparseWaveletOctree : public Object { class MTS_EXPORT_CORE SparseWaveletOctree : public Object {
public: public: