Patch by Tom Kazimiers: automatically cancel photon gathering if few or no photons are being generated
parent
5a714c3bc6
commit
5f27a96432
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue