Skip to content
Merged

RWMC #936

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions include/nbl/builtin/hlsl/concepts/accessors/loadable_image.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ namespace concepts
{
namespace accessors
{

// concept `LoadableImage` translates to smth like this:
//template<typename U, typename T, int32_t Dims>
//concept LoadableImage = requires(U a, vector<uint16_t, Dims> uv, uint16_t layer) {
// ::nbl::hlsl::is_same_v<decltype(declval<U>().template get<T,Dims>(uv,layer)), vector<T,4>>;
//};

// declare concept
#define NBL_CONCEPT_NAME StorableImage
#define NBL_CONCEPT_NAME LoadableImage
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(int32_t)
#define NBL_CONCEPT_TPLT_PRM_NAMES (U)(T)(Dims)
// not the greatest syntax but works
Expand All @@ -26,20 +33,20 @@ namespace accessors
#define NBL_CONCEPT_PARAM_2 (layer,uint16_t)
// start concept
NBL_CONCEPT_BEGIN(3)
// need to be defined AFTER the cocnept begins
// need to be defined AFTER the concept begins
#define a NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0
#define uv NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1
#define layer NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2
NBL_CONCEPT_END(
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.template get<T,Dims>(uv,layer)) , ::nbl::hlsl::is_same_v, vector<T,4>))
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((a.template get<T,Dims>(uv,layer)), ::nbl::hlsl::is_same_v, vector<T,4>))
);
#undef layer
#undef uv
#undef a
#include <nbl/builtin/hlsl/concepts/__end.hlsl>

// declare concept
#define NBL_CONCEPT_NAME MipmappedStorableImage
#define NBL_CONCEPT_NAME MipmappedLoadableImage
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(int32_t)
#define NBL_CONCEPT_TPLT_PRM_NAMES (U)(T)(Dims)
// not the greatest syntax but works
Expand Down
98 changes: 98 additions & 0 deletions include/nbl/builtin/hlsl/rwmc/CascadeAccumulator.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#ifndef _NBL_HLSL_RWMC_CASCADE_ACCUMULATOR_INCLUDED_
#define _NBL_HLSL_RWMC_CASCADE_ACCUMULATOR_INCLUDED_
#include <nbl/builtin/hlsl/cpp_compat.hlsl>
#include <nbl/builtin/hlsl/cpp_compat/promote.hlsl>
#include <nbl/builtin/hlsl/vector_utils/vector_traits.hlsl>
#include <nbl/builtin/hlsl/colorspace/encodeCIEXYZ.hlsl>
#include <nbl/builtin/hlsl/rwmc/SplattingParameters.hlsl>

namespace nbl
{
namespace hlsl
{
namespace rwmc
{

template<typename CascadeLayerType, uint32_t CascadeCount NBL_PRIMARY_REQUIRES(concepts::Vector<CascadeLayerType>)
struct CascadeAccumulator
{
struct CascadeEntry
{
uint32_t cascadeSampleCounter[CascadeCount];
CascadeLayerType data[CascadeCount];

void addSampleIntoCascadeEntry(CascadeLayerType _sample, uint32_t lowerCascadeIndex, float lowerCascadeLevelWeight, float higherCascadeLevelWeight, uint32_t sampleCount)
{
const float reciprocalSampleCount = 1.0f / float(sampleCount);

uint32_t lowerCascadeSampleCount = cascadeSampleCounter[lowerCascadeIndex];
data[lowerCascadeIndex] += (_sample * lowerCascadeLevelWeight - (sampleCount - lowerCascadeSampleCount) * data[lowerCascadeIndex]) * reciprocalSampleCount;
cascadeSampleCounter[lowerCascadeIndex] = sampleCount;

uint32_t higherCascadeIndex = lowerCascadeIndex + 1u;
if (higherCascadeIndex < CascadeCount)
{
uint32_t higherCascadeSampleCount = cascadeSampleCounter[higherCascadeIndex];
data[higherCascadeIndex] += (_sample * higherCascadeLevelWeight - (sampleCount - higherCascadeSampleCount) * data[higherCascadeIndex]) * reciprocalSampleCount;
cascadeSampleCounter[higherCascadeIndex] = sampleCount;
}
}
};

using cascade_layer_scalar_type = typename vector_traits<CascadeLayerType>::scalar_type;
using this_t = CascadeAccumulator<CascadeLayerType, CascadeCount>;
using output_storage_type = CascadeEntry;
using initialization_data = SplattingParameters;
output_storage_type accumulation;

SplattingParameters splattingParameters;

static this_t create(NBL_CONST_REF_ARG(SplattingParameters) settings)
{
this_t retval;
for (int i = 0; i < CascadeCount; ++i)
{
retval.accumulation.data[i] = promote<CascadeLayerType, float32_t>(0.0f);
retval.accumulation.cascadeSampleCounter[i] = 0u;
}
retval.splattingParameters = settings;

return retval;
}

cascade_layer_scalar_type getLuma(NBL_CONST_REF_ARG(CascadeLayerType) col)
{
return hlsl::dot<CascadeLayerType>(hlsl::transpose(colorspace::scRGBtoXYZ)[1], col);
}

// most of this code is stolen from https://cg.ivd.kit.edu/publications/2018/rwmc/tool/split.cpp
void addSample(uint32_t sampleCount, CascadeLayerType _sample)
{
const cascade_layer_scalar_type log2Start = splattingParameters.log2Start;
const cascade_layer_scalar_type log2Base = splattingParameters.log2Base;
const cascade_layer_scalar_type luma = getLuma(_sample);
const cascade_layer_scalar_type log2Luma = log2<cascade_layer_scalar_type>(luma);
const cascade_layer_scalar_type cascade = log2Luma * 1.f / log2Base - log2Start / log2Base;
const cascade_layer_scalar_type clampedCascade = clamp(cascade, 0, CascadeCount - 1);
// c<=0 -> 0, c>=Count-1 -> Count-1
uint32_t lowerCascadeIndex = floor<cascade_layer_scalar_type>(cascade);
// 0 whenever clamped or `cascade` is integer (when `clampedCascade` is integer)
cascade_layer_scalar_type higherCascadeWeight = clampedCascade - floor<cascade_layer_scalar_type>(clampedCascade);
// never 0 thanks to magic of `1-fract(x)`
cascade_layer_scalar_type lowerCascadeWeight = cascade_layer_scalar_type(1) - higherCascadeWeight;

// handle super bright sample case
if (cascade > CascadeCount - 1)
lowerCascadeWeight = exp2(log2Start + log2Base * (CascadeCount - 1) - log2Luma);

accumulation.addSampleIntoCascadeEntry(_sample, lowerCascadeIndex, lowerCascadeWeight, higherCascadeWeight, sampleCount);
}


};

}
}
}

#endif
45 changes: 45 additions & 0 deletions include/nbl/builtin/hlsl/rwmc/ResolveParameters.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#ifndef _NBL_BUILTIN_HLSL_RWMC_RESOLVE_PARAMETERS_HLSL_INCLUDED_
#define _NBL_BUILTIN_HLSL_RWMC_RESOLVE_PARAMETERS_HLSL_INCLUDED_

#include "nbl/builtin/hlsl/cpp_compat.hlsl"

namespace nbl
{
namespace hlsl
{
namespace rwmc
{

struct ResolveParameters
{
uint32_t lastCascadeIndex;
float initialEmin; // a minimum image brightness that we always consider reliable
float reciprocalBase;
float reciprocalN;
float reciprocalKappa;
float colorReliabilityFactor;
float NOverKappa;
};

ResolveParameters computeResolveParameters(float base, uint32_t sampleCount, float minReliableLuma, float kappa, uint32_t cascadeSize)
{
ResolveParameters retval;
retval.lastCascadeIndex = cascadeSize - 1u;
retval.initialEmin = minReliableLuma;
retval.reciprocalBase = 1.f / base;
const float N = float(sampleCount);
retval.reciprocalN = 1.f / N;
retval.reciprocalKappa = 1.f / kappa;
// if not interested in exact expected value estimation (kappa!=1.f), can usually accept a bit more variance relative to the image brightness we already have
// allow up to ~<cascadeBase> more energy in one sample to lessen bias in some cases
retval.colorReliabilityFactor = base + (1.f - base) * retval.reciprocalKappa;
retval.NOverKappa = N * retval.reciprocalKappa;

return retval;
}

}
}
}

#endif
23 changes: 23 additions & 0 deletions include/nbl/builtin/hlsl/rwmc/SplattingParameters.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef _NBL_BUILTIN_HLSL_RWMC_SPLATTING_PARAMETERS_HLSL_INCLUDED_
#define _NBL_BUILTIN_HLSL_RWMC_SPLATTING_PARAMETERS_HLSL_INCLUDED_

#include "nbl/builtin/hlsl/cpp_compat.hlsl"

namespace nbl
{
namespace hlsl
{
namespace rwmc
{

struct SplattingParameters
{
float log2Start;
float log2Base;
};

}
}
}

#endif
Loading