Patch by Tom Kazimiers: automatically cancel photon gathering if few or no photons are being generated

metadata
Wenzel Jakob 2011-07-15 10:15:57 +02:00
parent 5a714c3bc6
commit 5f27a96432
5 changed files with 51 additions and 9 deletions

View File

@ -53,12 +53,15 @@ public:
* \param isLocal
* Should the parallel process only be executed locally? (sending
* photons over the network may be unnecessary and wasteful)
* \param autoCancel
* Indicates if the gathering process should be canceled if there
* are not enough photons generated
* \param progressReporterPayload
* Custom pointer payload to be delivered with progress messages
*/
GatherPhotonProcess(EGatherType type, size_t photonCount,
size_t granularity, int maxDepth, int rrDepth, bool isLocal,
const void *progressReporterPayload);
bool autoCancel, const void *progressReporterPayload);
/**
* Once the process has finished, this returns a reference
@ -89,6 +92,7 @@ public:
bool isLocal() const;
ref<WorkProcessor> createWorkProcessor() const;
void processResult(const WorkResult *wr, bool cancelled);
EStatus generateWork(WorkUnit *unit, int worker);
/// @}
// ======================================================================
@ -97,12 +101,23 @@ public:
protected:
/// Virtual destructor
virtual ~GatherPhotonProcess() { }
/**
* \brief Checks if the configuration of needed, generated and shot
* photons indicates an unsuccessful progress of the gathering. This
* check is taken from PBRT.
*/
inline bool unsuccessful(size_t needed, size_t gen, size_t shot) {
return (gen < needed && (gen == 0 || gen < shot/1024));
}
protected:
EGatherType m_type;
ref<PhotonMap> m_photonMap;
size_t m_photonCount;
int m_maxDepth;
int m_rrDepth;
bool m_isLocal;
bool m_autoCancel;
size_t m_excess, m_numShot;
};

View File

@ -60,6 +60,8 @@ public:
m_volumeLookupSize = props.getInteger("volumeLookupSize", 120);
/* Should photon gathering steps exclusively run on the local machine? */
m_gatherLocally = props.getBoolean("gatherLocally", true);
/* Indicates if the gathering steps should be canceled if not enough photons are generated. */
m_autoCancelGathering = props.getBoolean("autoCancelGathering", true);
}
/// Unserialize from a binary data stream
@ -77,6 +79,7 @@ public:
m_causticLookupSize = stream->readInt();
m_volumeLookupSize = stream->readInt();
m_gatherLocally = stream->readBool();
m_autoCancelGathering = stream->readBool();
}
void serialize(Stream *stream, InstanceManager *manager) const {
@ -93,6 +96,7 @@ public:
stream->writeInt(m_causticLookupSize);
stream->writeInt(m_volumeLookupSize);
stream->writeBool(m_gatherLocally);
stream->writeBool(m_autoCancelGathering);
}
/// Configure the sampler for a specified amount of direct illumination samples
@ -142,7 +146,8 @@ public:
/* Generate the global photon map */
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
GatherPhotonProcess::ESurfacePhotons, m_globalPhotons,
m_granularity, m_maxDepth, m_rrDepth, m_gatherLocally, job);
m_granularity, m_maxDepth, m_rrDepth, m_gatherLocally,
m_autoCancelGathering, job);
proc->bindResource("scene", sceneResID);
proc->bindResource("camera", cameraResID);
@ -172,7 +177,8 @@ public:
/* Generate the caustic photon map */
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
GatherPhotonProcess::ECausticPhotons, m_causticPhotons,
m_granularity, 2, m_rrDepth, m_gatherLocally, job);
m_granularity, 2, m_rrDepth, m_gatherLocally,
m_autoCancelGathering, job);
proc->bindResource("scene", sceneResID);
proc->bindResource("camera", cameraResID);
@ -199,7 +205,8 @@ public:
/* Generate the volume photon map */
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
GatherPhotonProcess::EVolumePhotons, m_volumePhotons,
m_granularity, m_maxDepth, m_rrDepth, m_gatherLocally, job);
m_granularity, m_maxDepth, m_rrDepth, m_gatherLocally,
m_autoCancelGathering, job);
proc->bindResource("scene", sceneResID);
proc->bindResource("camera", cameraResID);
@ -426,6 +433,7 @@ private:
int m_rrDepth;
int m_maxDepth, m_maxSpecularDepth;
bool m_gatherLocally;
bool m_autoCancelGathering;
};
MTS_IMPLEMENT_CLASS_S(PhotonMapIntegrator, false, SampleIntegrator)

View File

@ -63,6 +63,8 @@ public:
m_rrDepth = props.getInteger("rrDepth", 3);
/* Block size used to parallelize the photon query passes (default: 32x32 pixels). */
m_blockSize = props.getInteger("blockSize", 32);
/* Indicates if the gathering steps should be canceled if not enough photons are generated. */
m_autoCancelGathering = props.getBoolean("autoCancelGathering", true);
m_mutex = new Mutex();
#if defined(__OSX__)
Log(EError, "Progressive photon mapping currently doesn't work "
@ -277,7 +279,8 @@ public:
/* Generate the global photon map */
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
GatherPhotonProcess::EAllSurfacePhotons, m_photonCount,
m_granularity, m_maxDepth == -1 ? -1 : (m_maxDepth-1), m_rrDepth, true, job);
m_granularity, m_maxDepth == -1 ? -1 : (m_maxDepth-1), m_rrDepth, true,
m_autoCancelGathering, job);
proc->bindResource("scene", sceneResID);
proc->bindResource("camera", cameraResID);
@ -351,6 +354,7 @@ private:
size_t m_totalEmitted;
int m_blockSize;
bool m_running;
bool m_autoCancelGathering;
};
MTS_IMPLEMENT_CLASS_S(ProgressivePhotonMapIntegrator, false, Integrator)

View File

@ -64,6 +64,8 @@ public:
m_rrDepth = props.getInteger("rrDepth", 3);
/* Block size used to parallelize the photon query passes (default: 32x32 pixels). */
m_blockSize = props.getInteger("blockSize", 32);
/* Indicates if the gathering steps should be canceled if not enough photons are generated. */
m_autoCancelGathering = props.getBoolean("autoCancelGathering", true);
m_mutex = new Mutex();
#if defined(__OSX__)
Log(EError, "Stochastic progressive photon mapping currently doesn't work "
@ -265,7 +267,8 @@ public:
/* Generate the global photon map */
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
GatherPhotonProcess::EAllSurfacePhotons, m_photonCount,
m_granularity, m_maxDepth-1, m_rrDepth, true, job);
m_granularity, m_maxDepth-1, m_rrDepth, true,
m_autoCancelGathering, job);
proc->bindResource("scene", sceneResID);
proc->bindResource("camera", cameraResID);
@ -339,6 +342,7 @@ private:
size_t m_totalEmitted;
int m_blockSize;
bool m_running;
bool m_autoCancelGathering;
};
MTS_IMPLEMENT_CLASS_S(StochasticProgressivePhotonMapIntegrator, false, Integrator)

View File

@ -169,10 +169,11 @@ protected:
};
GatherPhotonProcess::GatherPhotonProcess(EGatherType type, size_t photonCount,
size_t granularity, int maxDepth, int rrDepth, bool isLocal, const void *progressReporterPayload)
size_t granularity, int maxDepth, int rrDepth, bool isLocal, bool autoCancel,
const void *progressReporterPayload)
: ParticleProcess(ParticleProcess::EGather, photonCount, granularity, "Gathering photons",
progressReporterPayload), m_type(type), m_maxDepth(maxDepth), m_rrDepth(rrDepth),
m_isLocal(isLocal), m_excess(0), m_numShot(0) {
progressReporterPayload), m_type(type), m_photonCount(photonCount), m_maxDepth(maxDepth),
m_rrDepth(rrDepth), m_isLocal(isLocal), m_autoCancel(autoCancel), m_excess(0), m_numShot(0) {
m_photonMap = new PhotonMap(photonCount);
}
@ -211,6 +212,16 @@ void GatherPhotonProcess::processResult(const WorkResult *wr, bool cancelled) {
m_resultMutex->unlock();
}
ParallelProcess::EStatus GatherPhotonProcess::generateWork(WorkUnit *unit, int worker) {
/* Use the same approach as PBRT for auto canceling */
if (m_autoCancel && m_numShot > 500000
&& unsuccessful(m_photonCount, m_photonMap->getPhotonCount(), m_numShot)) {
Log(EInfo, "Not enough photons could be collected, giving up");
return EFailure;
}
return ParticleProcess::generateWork(unit, worker);
}
MTS_IMPLEMENT_CLASS(GatherPhotonProcess, false, ParticleProcess)
MTS_IMPLEMENT_CLASS_S(GatherPhotonWorker, false, ParticleTracer)