-
Notifications
You must be signed in to change notification settings - Fork 70
Expand file tree
/
Copy pathresolve.hlsl
More file actions
189 lines (159 loc) · 6.99 KB
/
resolve.hlsl
File metadata and controls
189 lines (159 loc) · 6.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#ifndef _NBL_BUILTIN_HLSL_RWMC_RESOLVE_HLSL_INCLUDED_
#define _NBL_BUILTIN_HLSL_RWMC_RESOLVE_HLSL_INCLUDED_
#include "nbl/builtin/hlsl/cpp_compat.hlsl"
#include <nbl/builtin/hlsl/colorspace/encodeCIEXYZ.hlsl>
#include <nbl/builtin/hlsl/rwmc/ResolveParameters.hlsl>
#include <nbl/builtin/hlsl/concepts/accessors/loadable_image.hlsl>
#include <nbl/builtin/hlsl/colorspace.hlsl>
#include <nbl/builtin/hlsl/vector_utils/vector_traits.hlsl>
namespace nbl
{
namespace hlsl
{
namespace rwmc
{
// declare concept
#define NBL_CONCEPT_NAME ResolveAccessorBase
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)(int32_t)
#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(VectorScalarType)(Dims)
// not the greatest syntax but works
#define NBL_CONCEPT_PARAM_0 (a,T)
#define NBL_CONCEPT_PARAM_1 (scalar,VectorScalarType)
// start concept
NBL_CONCEPT_BEGIN(2)
// need to be defined AFTER the concept begins
#define a NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0
#define scalar NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1
NBL_CONCEPT_END(
((NBL_CONCEPT_REQ_EXPR)((a.calcLuma(vector<VectorScalarType, 3>(scalar, scalar, scalar)))))
);
#undef a
#undef scalar
#include <nbl/builtin/hlsl/concepts/__end.hlsl>
/* ResolveAccessor is required to:
* - satisfy `LoadableImage` concept requirements
* - implement function called `calcLuma` which calculates luma from a 3 component pixel value
*/
template<typename T, typename VectorScalarType, int32_t Dims>
NBL_BOOL_CONCEPT ResolveAccessor = ResolveAccessorBase<T, VectorScalarType, Dims> && concepts::accessors::LoadableImage<T, VectorScalarType, Dims>;
template<typename OutputScalar>
struct ResolveAccessorAdaptor
{
using output_scalar_type = OutputScalar;
using output_type = vector<OutputScalar, 4>;
NBL_CONSTEXPR int32_t image_dimension = 2;
float32_t calcLuma(NBL_REF_ARG(float32_t3) col)
{
return hlsl::dot<float32_t3>(colorspace::scRGB::ToXYZ()[1], col);
}
template<typename OutputScalarType, int32_t Dimension>
output_type get(vector<uint16_t, 2> uv, uint16_t layer)
{
uint32_t imgWidth, imgHeight, layers;
cascade.GetDimensions(imgWidth, imgHeight, layers);
int16_t2 cascadeImageDimension = int16_t2(imgWidth, imgHeight);
if (any(uv < int16_t2(0, 0)) || any(uv > cascadeImageDimension))
return vector<OutputScalar, 4>(0, 0, 0, 0);
return cascade.Load(int32_t3(uv, int32_t(layer)));
}
};
template<typename CascadeAccessor, typename OutputColorTypeVec NBL_PRIMARY_REQUIRES(concepts::Vector<OutputColorTypeVec> && ResolveAccessor<CascadeAccessor, typename CascadeAccessor::output_scalar_type, CascadeAccessor::image_dimension>)
struct Resolver
{
using output_type = OutputColorTypeVec;
using scalar_t = typename vector_traits<output_type>::scalar_type;
struct CascadeSample
{
float32_t3 centerValue;
float normalizedCenterLuma;
float normalizedNeighbourhoodAverageLuma;
};
static Resolver create(NBL_REF_ARG(ResolveParameters) resolveParameters)
{
Resolver retval;
retval.params = resolveParameters;
return retval;
}
output_type operator()(NBL_REF_ARG(CascadeAccessor) acc, const int16_t2 coord)
{
using scalar_t = typename vector_traits<output_type>::scalar_type;
scalar_t reciprocalBaseI = 1.f;
CascadeSample curr = __sampleCascade(acc, coord, 0u, reciprocalBaseI);
output_type accumulation = output_type(0.0f, 0.0f, 0.0f);
scalar_t Emin = params.initialEmin;
scalar_t prevNormalizedCenterLuma, prevNormalizedNeighbourhoodAverageLuma;
for (int16_t i = 0u; i <= params.lastCascadeIndex; i++)
{
const bool notFirstCascade = i != 0;
const bool notLastCascade = i != params.lastCascadeIndex;
CascadeSample next;
if (notLastCascade)
{
reciprocalBaseI *= params.reciprocalBase;
next = __sampleCascade(acc, coord, int16_t(i + 1), reciprocalBaseI);
}
scalar_t reliability = 1.f;
// sample counting-based reliability estimation
if (params.reciprocalKappa <= 1.f)
{
scalar_t localReliability = curr.normalizedCenterLuma;
// reliability in 3x3 pixel block (see robustness)
scalar_t globalReliability = curr.normalizedNeighbourhoodAverageLuma;
if (notFirstCascade)
{
localReliability += prevNormalizedCenterLuma;
globalReliability += prevNormalizedNeighbourhoodAverageLuma;
}
if (notLastCascade)
{
localReliability += next.normalizedCenterLuma;
globalReliability += next.normalizedNeighbourhoodAverageLuma;
}
// check if above minimum sampling threshold (avg 9 sample occurences in 3x3 neighbourhood), then use per-pixel reliability (NOTE: tertiary op is in reverse)
reliability = globalReliability < params.reciprocalN ? globalReliability : localReliability;
{
const scalar_t accumLuma = acc.calcLuma(accumulation);
if (accumLuma > Emin)
Emin = accumLuma;
const scalar_t colorReliability = Emin * reciprocalBaseI * params.colorReliabilityFactor;
reliability += colorReliability;
reliability *= params.NOverKappa;
reliability -= params.reciprocalKappa;
reliability = clamp(reliability * 0.5f, 0.f, 1.f);
}
}
accumulation += curr.centerValue * reliability;
prevNormalizedCenterLuma = curr.normalizedCenterLuma;
prevNormalizedNeighbourhoodAverageLuma = curr.normalizedNeighbourhoodAverageLuma;
curr = next;
}
return accumulation;
}
ResolveParameters params;
// pseudo private stuff:
CascadeSample __sampleCascade(NBL_REF_ARG(CascadeAccessor) acc, int16_t2 coord, uint16_t cascadeIndex, scalar_t reciprocalBaseI)
{
output_type neighbourhood[9];
neighbourhood[0] = acc.template get<scalar_t, 2>(coord + int16_t2(-1, -1), cascadeIndex).xyz;
neighbourhood[1] = acc.template get<scalar_t, 2>(coord + int16_t2(0, -1), cascadeIndex).xyz;
neighbourhood[2] = acc.template get<scalar_t, 2>(coord + int16_t2(1, -1), cascadeIndex).xyz;
neighbourhood[3] = acc.template get<scalar_t, 2>(coord + int16_t2(-1, 0), cascadeIndex).xyz;
neighbourhood[4] = acc.template get<scalar_t, 2>(coord + int16_t2(0, 0), cascadeIndex).xyz;
neighbourhood[5] = acc.template get<scalar_t, 2>(coord + int16_t2(1, 0), cascadeIndex).xyz;
neighbourhood[6] = acc.template get<scalar_t, 2>(coord + int16_t2(-1, 1), cascadeIndex).xyz;
neighbourhood[7] = acc.template get<scalar_t, 2>(coord + int16_t2(0, 1), cascadeIndex).xyz;
neighbourhood[8] = acc.template get<scalar_t, 2>(coord + int16_t2(1, 1), cascadeIndex).xyz;
// numerical robustness
float32_t3 excl_hood_sum = ((neighbourhood[0] + neighbourhood[1]) + (neighbourhood[2] + neighbourhood[3])) +
((neighbourhood[5] + neighbourhood[6]) + (neighbourhood[7] + neighbourhood[8]));
CascadeSample retval;
retval.centerValue = neighbourhood[4];
retval.normalizedNeighbourhoodAverageLuma = retval.normalizedCenterLuma = acc.calcLuma(neighbourhood[4]) * reciprocalBaseI;
retval.normalizedNeighbourhoodAverageLuma = (acc.calcLuma(excl_hood_sum) * reciprocalBaseI + retval.normalizedNeighbourhoodAverageLuma) / 9.f;
return retval;
}
};
}
}
}
#endif