8#include <Common/assertion.h>
9#include <Common/primitive_type.h>
43 template<ERefineMode MODE>
55 real precisionStandard,
56 std::size_t initialDepthPerRegion);
61 real precisionStandard,
62 std::size_t initialDepthPerRegion,
63 std::size_t standardDepthPerRegion,
64 std::size_t terminusDepthPerRegion);
68 template<ERefineMode MODE>
71 template<ERefineMode MODE>
76 template<ERefineMode MODE>
83 const Region& finishedRegion,
92 real terminateThreshold,
93 real numFullRegionPixels);
95 std::pair<Region, Region> getNextRegions()
const;
97 real m_splitThreshold;
98 real m_terminateThreshold;
99 std::pair<Region, Region> m_nextRegions;
100 real m_rcpNumRegionPixels;
101 std::vector<real> m_accumulatedEps;
105 constexpr static std::size_t MIN_REGION_AREA = 256;
107 real m_splitThreshold;
108 real m_terminateThreshold;
109 std::size_t m_standardDepthPerRegion;
110 std::size_t m_terminusDepthPerRegion;
112 std::queue<WorkUnit> m_pendingRegions;
114 void addAnalyzedRegion(
const Region& region);
119template<DammertzDispatcher::ERefineMode MODE>
124 m_terminateThreshold,
125 static_cast<real
>(m_fullRegion.
getArea()));
128template<DammertzDispatcher::ERefineMode MODE>
131 const auto nextRegions = analyzer.getNextRegions();
132 addAnalyzedRegion(nextRegions.first);
133 addAnalyzedRegion(nextRegions.second);
136template<DammertzDispatcher::ERefineMode MODE>
138 const real splitThreshold,
139 const real terminateThreshold,
140 const real numFullRegionPixels) :
142 m_splitThreshold (splitThreshold),
143 m_terminateThreshold(terminateThreshold),
145 m_rcpNumRegionPixels(1.0_r / numFullRegionPixels),
151 return m_pendingRegions.size();
154template<DammertzDispatcher::ERefineMode MODE>
157 return m_nextRegions;
160template<DammertzDispatcher::ERefineMode MODE>
163 return !m_nextRegions.first.isArea() && !m_nextRegions.second.isArea();
168 const Region& finishedRegion,
172 using namespace math;
182 real regionError = 0;
191 const real numerator = I.
sub(
A).abs().sum();
192 const real sumOfI = I.
sum();
195 regionError += numerator * rcpDenominator;
198 regionError /= frameRegion.
getArea();
200 PH_ASSERT_MSG(std::isfinite(regionError), std::to_string(regionError));
202 if(regionError >= m_splitThreshold)
205 m_nextRegions.first = finishedRegion;
206 m_nextRegions.second =
Region({0, 0});
208 else if(regionError >= m_terminateThreshold)
210 if(finishedRegion.
getArea() >= MIN_REGION_AREA)
214 const int64 midPoint = (finishedRegion.
getMinVertex()[maxDimension] + finishedRegion.
getMaxVertex()[maxDimension]) / 2;
216 m_nextRegions = finishedRegion.
getSplitted(maxDimension, midPoint);
220 m_nextRegions.first = finishedRegion;
221 m_nextRegions.second =
Region({0, 0});
227 m_nextRegions.first =
Region({0, 0});
228 m_nextRegions.second =
Region({0, 0});
234 const Region& finishedRegion,
238 using namespace math;
248 const auto regionExtents = frameRegion.
getExtents();
249 const auto maxDimension = regionExtents.maxDimension();
251 m_accumulatedEps.resize(regionExtents[maxDimension]);
252 std::fill(m_accumulatedEps.begin(), m_accumulatedEps.end(), 0.0_r);
257 real summedRowEp = 0;
264 const real numerator = I.
sub(
A).abs().sum();
265 const real sumOfI = I.
sum();
266 const real rcpDenominator = sumOfI > 0 ?
fast_rcp_sqrt(sumOfI) : 0;
268 PH_ASSERT_GE(numerator * rcpDenominator, 0);
269 summedRowEp += numerator * rcpDenominator;
271 if(maxDimension == constant::X_AXIS)
273 m_accumulatedEps[x - frameRegion.
getMinVertex().x()] += summedRowEp;
276 summedEp += summedRowEp;
278 if(maxDimension == constant::Y_AXIS)
280 m_accumulatedEps[y - frameRegion.
getMinVertex().y()] = summedEp;
284 real regionError = summedEp;
285 regionError /= frameRegion.
getArea();
287 PH_ASSERT_MSG(regionError > 0 && std::isfinite(regionError), std::to_string(regionError));
289 if(regionError >= m_splitThreshold)
292 m_nextRegions.first = finishedRegion;
293 m_nextRegions.second =
Region({0, 0});
295 else if(regionError >= m_terminateThreshold)
297 if(finishedRegion.
getArea() >= MIN_REGION_AREA)
304 const real totalEps = m_accumulatedEps.back();
307 real minErrorDiff = totalEps *
fast_rcp_sqrt(
static_cast<real
>(m_accumulatedEps.size()));
308 for(std::size_t i = 0; i < m_accumulatedEps.size(); ++i)
310 const real summedEp0 = m_accumulatedEps[i];
311 const real summedEp1 = totalEps - summedEp0;
312 PH_ASSERT_GE(summedEp0, 0);
313 PH_ASSERT_GE(summedEp1, 0);
315 const real error0 = summedEp0 *
fast_rcp_sqrt(
static_cast<real
>(i + 1));
316 const real error1 = summedEp1 * (i != m_accumulatedEps.size() - 1 ?
317 fast_rcp_sqrt(
static_cast<real
>(m_accumulatedEps.size() - i - 1)) : 0);
318 const real errorDiff = std::abs(error0 - error1);
320 if(errorDiff < minErrorDiff)
322 minErrorDiff = errorDiff;
323 bestPosPx =
static_cast<int64
>(i + 1);
329 finishedRegion.
getMinVertex()[maxDimension] + bestPosPx);
333 m_nextRegions.first = finishedRegion;
334 m_nextRegions.second =
Region({0, 0});
340 m_nextRegions.first =
Region({0, 0});
341 m_nextRegions.second =
Region({0, 0});
345inline void DammertzDispatcher::addAnalyzedRegion(
const Region& region)
349 if(region.
getArea() <= MIN_REGION_AREA)
351 m_pendingRegions.push(
WorkUnit(region, m_terminusDepthPerRegion));
355 m_pendingRegions.push(
WorkUnit(region, m_standardDepthPerRegion));
Definition DammertzDispatcher.h:78
void analyzeFinishedRegion(const Region &finishedRegion, const HdrRgbFrame &allEffortFrame, const HdrRgbFrame &halfEffortFrame)
bool isConverged() const
Definition DammertzDispatcher.h:161
Definition DammertzDispatcher.h:35
bool dispatch(WorkUnit *out_workUnit) override
Get some amount of work.
Definition DammertzDispatcher.cpp:64
ERefineMode
Definition DammertzDispatcher.h:38
std::size_t numPendingRegions() const
Definition DammertzDispatcher.h:149
void addAnalyzedData(const TAnalyzer< MODE > &analyzer)
Definition DammertzDispatcher.h:129
DammertzDispatcher()=default
TAnalyzer< MODE > createAnalyzer() const
Definition DammertzDispatcher.h:120
A manager that distributes work.
Definition IWorkDispatcher.h:14
uint32 heightPx() const
Definition TFrame.ipp:440
uint32 widthPx() const
Definition TFrame.ipp:434
PixelType getPixel(const math::TVector2< uint32 > &coordPx) const
Definition TFrame.ipp:343
Represents some amount of work.
Definition WorkUnit.h:17
std::pair< TAABB2D, TAABB2D > getSplitted(std::size_t axis, T splitPoint) const
Definition TAABB2D.ipp:169
TVector2< T > getExtents() const
Get the side lengths of the bound.
Definition TAABB2D.ipp:150
T getHeight() const
Definition TAABB2D.ipp:144
T getWidth() const
Definition TAABB2D.ipp:138
bool isArea() const
Definition TAABB2D.ipp:205
const TVector2< T > & getMaxVertex() const
Definition TAABB2D.ipp:126
T getArea() const
Definition TAABB2D.ipp:69
const TVector2< T > & getMinVertex() const
Definition TAABB2D.ipp:120
T sum() const
Definition TArithmeticArrayBase.ipp:336
Derived sub(const Derived &rhs) const
Definition TArithmeticArrayBase.ipp:62
Definition TArithmeticArray.h:13
T & x()
Definition TVector2.ipp:38
T & y()
Definition TVector2.ipp:44
std::size_t maxDimension() const
Definition TVectorNBase.ipp:81
Miscellaneous math utilities.
float fast_rcp_sqrt(float x)
Computes 1/sqrt(x) in a fast but approximative way.
Definition math.h:407
float fast_sqrt(const float x)
Computes sqrt(x) in a fast but approximative way.
Definition math.h:436
The root for all renderer implementations.
Definition EEngineProject.h:6
math::TAABB2D< int64 > Region
Definition Region.h:8