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
|
* \param isLocal
|
||||||
* Should the parallel process only be executed locally? (sending
|
* Should the parallel process only be executed locally? (sending
|
||||||
* photons over the network may be unnecessary and wasteful)
|
* 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
|
* \param progressReporterPayload
|
||||||
* Custom pointer payload to be delivered with progress messages
|
* Custom pointer payload to be delivered with progress messages
|
||||||
*/
|
*/
|
||||||
GatherPhotonProcess(EGatherType type, size_t photonCount,
|
GatherPhotonProcess(EGatherType type, size_t photonCount,
|
||||||
size_t granularity, int maxDepth, int rrDepth, bool isLocal,
|
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
|
* Once the process has finished, this returns a reference
|
||||||
|
@ -89,6 +92,7 @@ public:
|
||||||
bool isLocal() const;
|
bool isLocal() const;
|
||||||
ref<WorkProcessor> createWorkProcessor() const;
|
ref<WorkProcessor> createWorkProcessor() const;
|
||||||
void processResult(const WorkResult *wr, bool cancelled);
|
void processResult(const WorkResult *wr, bool cancelled);
|
||||||
|
EStatus generateWork(WorkUnit *unit, int worker);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
|
@ -97,12 +101,23 @@ public:
|
||||||
protected:
|
protected:
|
||||||
/// Virtual destructor
|
/// Virtual destructor
|
||||||
virtual ~GatherPhotonProcess() { }
|
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:
|
protected:
|
||||||
EGatherType m_type;
|
EGatherType m_type;
|
||||||
ref<PhotonMap> m_photonMap;
|
ref<PhotonMap> m_photonMap;
|
||||||
|
size_t m_photonCount;
|
||||||
int m_maxDepth;
|
int m_maxDepth;
|
||||||
int m_rrDepth;
|
int m_rrDepth;
|
||||||
bool m_isLocal;
|
bool m_isLocal;
|
||||||
|
bool m_autoCancel;
|
||||||
size_t m_excess, m_numShot;
|
size_t m_excess, m_numShot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ public:
|
||||||
m_volumeLookupSize = props.getInteger("volumeLookupSize", 120);
|
m_volumeLookupSize = props.getInteger("volumeLookupSize", 120);
|
||||||
/* Should photon gathering steps exclusively run on the local machine? */
|
/* Should photon gathering steps exclusively run on the local machine? */
|
||||||
m_gatherLocally = props.getBoolean("gatherLocally", true);
|
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
|
/// Unserialize from a binary data stream
|
||||||
|
@ -77,6 +79,7 @@ public:
|
||||||
m_causticLookupSize = stream->readInt();
|
m_causticLookupSize = stream->readInt();
|
||||||
m_volumeLookupSize = stream->readInt();
|
m_volumeLookupSize = stream->readInt();
|
||||||
m_gatherLocally = stream->readBool();
|
m_gatherLocally = stream->readBool();
|
||||||
|
m_autoCancelGathering = stream->readBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
|
@ -93,6 +96,7 @@ public:
|
||||||
stream->writeInt(m_causticLookupSize);
|
stream->writeInt(m_causticLookupSize);
|
||||||
stream->writeInt(m_volumeLookupSize);
|
stream->writeInt(m_volumeLookupSize);
|
||||||
stream->writeBool(m_gatherLocally);
|
stream->writeBool(m_gatherLocally);
|
||||||
|
stream->writeBool(m_autoCancelGathering);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure the sampler for a specified amount of direct illumination samples
|
/// Configure the sampler for a specified amount of direct illumination samples
|
||||||
|
@ -142,7 +146,8 @@ public:
|
||||||
/* Generate the global photon map */
|
/* Generate the global photon map */
|
||||||
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
||||||
GatherPhotonProcess::ESurfacePhotons, m_globalPhotons,
|
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("scene", sceneResID);
|
||||||
proc->bindResource("camera", cameraResID);
|
proc->bindResource("camera", cameraResID);
|
||||||
|
@ -172,7 +177,8 @@ public:
|
||||||
/* Generate the caustic photon map */
|
/* Generate the caustic photon map */
|
||||||
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
||||||
GatherPhotonProcess::ECausticPhotons, m_causticPhotons,
|
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("scene", sceneResID);
|
||||||
proc->bindResource("camera", cameraResID);
|
proc->bindResource("camera", cameraResID);
|
||||||
|
@ -199,7 +205,8 @@ public:
|
||||||
/* Generate the volume photon map */
|
/* Generate the volume photon map */
|
||||||
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
||||||
GatherPhotonProcess::EVolumePhotons, m_volumePhotons,
|
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("scene", sceneResID);
|
||||||
proc->bindResource("camera", cameraResID);
|
proc->bindResource("camera", cameraResID);
|
||||||
|
@ -426,6 +433,7 @@ private:
|
||||||
int m_rrDepth;
|
int m_rrDepth;
|
||||||
int m_maxDepth, m_maxSpecularDepth;
|
int m_maxDepth, m_maxSpecularDepth;
|
||||||
bool m_gatherLocally;
|
bool m_gatherLocally;
|
||||||
|
bool m_autoCancelGathering;
|
||||||
};
|
};
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS_S(PhotonMapIntegrator, false, SampleIntegrator)
|
MTS_IMPLEMENT_CLASS_S(PhotonMapIntegrator, false, SampleIntegrator)
|
||||||
|
|
|
@ -63,6 +63,8 @@ public:
|
||||||
m_rrDepth = props.getInteger("rrDepth", 3);
|
m_rrDepth = props.getInteger("rrDepth", 3);
|
||||||
/* Block size used to parallelize the photon query passes (default: 32x32 pixels). */
|
/* Block size used to parallelize the photon query passes (default: 32x32 pixels). */
|
||||||
m_blockSize = props.getInteger("blockSize", 32);
|
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();
|
m_mutex = new Mutex();
|
||||||
#if defined(__OSX__)
|
#if defined(__OSX__)
|
||||||
Log(EError, "Progressive photon mapping currently doesn't work "
|
Log(EError, "Progressive photon mapping currently doesn't work "
|
||||||
|
@ -277,7 +279,8 @@ public:
|
||||||
/* Generate the global photon map */
|
/* Generate the global photon map */
|
||||||
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
||||||
GatherPhotonProcess::EAllSurfacePhotons, m_photonCount,
|
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("scene", sceneResID);
|
||||||
proc->bindResource("camera", cameraResID);
|
proc->bindResource("camera", cameraResID);
|
||||||
|
@ -351,6 +354,7 @@ private:
|
||||||
size_t m_totalEmitted;
|
size_t m_totalEmitted;
|
||||||
int m_blockSize;
|
int m_blockSize;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
|
bool m_autoCancelGathering;
|
||||||
};
|
};
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS_S(ProgressivePhotonMapIntegrator, false, Integrator)
|
MTS_IMPLEMENT_CLASS_S(ProgressivePhotonMapIntegrator, false, Integrator)
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
m_rrDepth = props.getInteger("rrDepth", 3);
|
m_rrDepth = props.getInteger("rrDepth", 3);
|
||||||
/* Block size used to parallelize the photon query passes (default: 32x32 pixels). */
|
/* Block size used to parallelize the photon query passes (default: 32x32 pixels). */
|
||||||
m_blockSize = props.getInteger("blockSize", 32);
|
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();
|
m_mutex = new Mutex();
|
||||||
#if defined(__OSX__)
|
#if defined(__OSX__)
|
||||||
Log(EError, "Stochastic progressive photon mapping currently doesn't work "
|
Log(EError, "Stochastic progressive photon mapping currently doesn't work "
|
||||||
|
@ -265,7 +267,8 @@ public:
|
||||||
/* Generate the global photon map */
|
/* Generate the global photon map */
|
||||||
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
ref<GatherPhotonProcess> proc = new GatherPhotonProcess(
|
||||||
GatherPhotonProcess::EAllSurfacePhotons, m_photonCount,
|
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("scene", sceneResID);
|
||||||
proc->bindResource("camera", cameraResID);
|
proc->bindResource("camera", cameraResID);
|
||||||
|
@ -339,6 +342,7 @@ private:
|
||||||
size_t m_totalEmitted;
|
size_t m_totalEmitted;
|
||||||
int m_blockSize;
|
int m_blockSize;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
|
bool m_autoCancelGathering;
|
||||||
};
|
};
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS_S(StochasticProgressivePhotonMapIntegrator, false, Integrator)
|
MTS_IMPLEMENT_CLASS_S(StochasticProgressivePhotonMapIntegrator, false, Integrator)
|
||||||
|
|
|
@ -169,10 +169,11 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
GatherPhotonProcess::GatherPhotonProcess(EGatherType type, size_t photonCount,
|
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",
|
: ParticleProcess(ParticleProcess::EGather, photonCount, granularity, "Gathering photons",
|
||||||
progressReporterPayload), m_type(type), m_maxDepth(maxDepth), m_rrDepth(rrDepth),
|
progressReporterPayload), m_type(type), m_photonCount(photonCount), m_maxDepth(maxDepth),
|
||||||
m_isLocal(isLocal), m_excess(0), m_numShot(0) {
|
m_rrDepth(rrDepth), m_isLocal(isLocal), m_autoCancel(autoCancel), m_excess(0), m_numShot(0) {
|
||||||
m_photonMap = new PhotonMap(photonCount);
|
m_photonMap = new PhotonMap(photonCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +212,16 @@ void GatherPhotonProcess::processResult(const WorkResult *wr, bool cancelled) {
|
||||||
m_resultMutex->unlock();
|
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(GatherPhotonProcess, false, ParticleProcess)
|
||||||
MTS_IMPLEMENT_CLASS_S(GatherPhotonWorker, false, ParticleTracer)
|
MTS_IMPLEMENT_CLASS_S(GatherPhotonWorker, false, ParticleTracer)
|
||||||
|
|
Loading…
Reference in New Issue