Skip to content

Commit 36cd283

Browse files
committed
add sidechannel bool if D is infinity
1 parent 589b7df commit 36cd283

File tree

4 files changed

+79
-52
lines changed

4 files changed

+79
-52
lines changed

include/nbl/builtin/hlsl/bxdf/base/cook_torrance_base.hlsl

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -121,27 +121,6 @@ struct getOrientedFresnel<F, true NBL_PARTIAL_REQ_BOT(fresnel::TwoSidedFresnel<F
121121
return fresnel.getReorientedFresnel(NdotV);
122122
}
123123
};
124-
125-
template<class N, class LS, class Interaction, class MicrofacetCache>
126-
struct overwrite_DG
127-
{
128-
using scalar_type = typename N::scalar_type;
129-
using quant_type = typename N::quant_type;
130-
using quant_query_type = typename N::quant_query_type;
131-
using g2g1_query_type = typename N::g2g1_query_type;
132-
NBL_CONSTEXPR_STATIC_INLINE bool HasOverwrite = ndf::NDF_CanOverwriteDG<N>;
133-
134-
template<typename C=bool_constant<!HasOverwrite> >
135-
static enable_if_t<C::value && !HasOverwrite, void> __call(NBL_REF_ARG(scalar_type) DG, N ndf, NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
136-
{
137-
}
138-
template<typename C=bool_constant<HasOverwrite> >
139-
static enable_if_t<C::value && HasOverwrite, void> __call(NBL_REF_ARG(scalar_type) DG, N ndf, NBL_CONST_REF_ARG(g2g1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
140-
{
141-
quant_type dg = ndf.template Dcorrelated<LS, Interaction, MicrofacetCache>(query, quant_query, _sample, interaction, cache);
142-
DG = dg.projectedLightMeasure;
143-
}
144-
};
145124
}
146125

147126
// N (NDF), F (fresnel)
@@ -159,6 +138,23 @@ struct SCookTorrance
159138
NBL_CONSTEXPR_STATIC_INLINE bool IsBSDF = ndf_type::SupportedPaths != ndf::MTT_REFLECT;
160139
NBL_HLSL_BXDF_ANISOTROPIC_COND_DECLS(IsAnisotropic);
161140

141+
template<class Interaction=conditional_t<IsAnisotropic,anisotropic_interaction_type,isotropic_interaction_type>,
142+
class MicrofacetCache=conditional_t<IsAnisotropic,anisocache_type,isocache_type>
143+
NBL_FUNC_REQUIRES(!ndf::NDF_CanOverwriteDG<ndf_type> && RequiredInteraction<Interaction> && RequiredMicrofacetCache<MicrofacetCache>)
144+
static void overwriteDG(NBL_REF_ARG(scalar_type) DG, ndf_type ndf, NBL_CONST_REF_ARG(typename ndf_type::g2g1_query_type) query, NBL_CONST_REF_ARG(typename ndf_type::quant_query_type) quant_query,
145+
NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache, NBL_REF_ARG(bool) isInfinity)
146+
{
147+
}
148+
template<class Interaction=conditional_t<IsAnisotropic,anisotropic_interaction_type,isotropic_interaction_type>,
149+
class MicrofacetCache=conditional_t<IsAnisotropic,anisocache_type,isocache_type>
150+
NBL_FUNC_REQUIRES(ndf::NDF_CanOverwriteDG<ndf_type> && RequiredInteraction<Interaction> && RequiredMicrofacetCache<MicrofacetCache>)
151+
static void overwriteDG(NBL_REF_ARG(scalar_type) DG, ndf_type ndf, NBL_CONST_REF_ARG(typename ndf_type::g2g1_query_type) query, NBL_CONST_REF_ARG(typename ndf_type::quant_query_type) quant_query,
152+
NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache, NBL_REF_ARG(bool) isInfinity)
153+
{
154+
quant_type dg = ndf.template Dcorrelated<sample_type, Interaction, MicrofacetCache>(query, quant_query, _sample, interaction, cache, isInfinity);
155+
DG = dg.projectedLightMeasure;
156+
}
157+
162158
template<class Interaction=conditional_t<IsAnisotropic,anisotropic_interaction_type,isotropic_interaction_type>,
163159
class MicrofacetCache=conditional_t<IsAnisotropic,anisocache_type,isocache_type>
164160
NBL_FUNC_REQUIRES(RequiredInteraction<Interaction> && RequiredMicrofacetCache<MicrofacetCache>)
@@ -174,14 +170,16 @@ struct SCookTorrance
174170
using g2g1_query_type = typename ndf_type::g2g1_query_type;
175171
g2g1_query_type gq = ndf.template createG2G1Query<sample_type, Interaction>(_sample, interaction);
176172

177-
quant_type D = ndf.template D<sample_type, Interaction, MicrofacetCache>(qq, _sample, interaction, cache);
173+
bool isInfinity;
174+
quant_type D = ndf.template D<sample_type, Interaction, MicrofacetCache>(qq, _sample, interaction, cache, isInfinity);
178175
scalar_type DG = D.projectedLightMeasure;
179-
if (D.microfacetMeasure < bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity))
176+
if (!isInfinity)
180177
DG *= ndf.template correlated<sample_type, Interaction, MicrofacetCache>(gq, _sample, interaction, cache);
181-
else
182-
return hlsl::promote<spectral_type>(0.0);
183178

184-
impl::overwrite_DG<ndf_type, sample_type, Interaction, MicrofacetCache>::__call(DG, ndf, gq, qq, _sample, interaction, cache);
179+
overwriteDG<Interaction, MicrofacetCache>(DG, ndf, gq, qq, _sample, interaction, cache, isInfinity);
180+
181+
if (isInfinity)
182+
return hlsl::promote<spectral_type>(0.0);
185183

186184
scalar_type clampedVdotH = cache.getVdotH();
187185
NBL_IF_CONSTEXPR(IsBSDF)
@@ -320,7 +318,7 @@ struct SCookTorrance
320318
}
321319

322320
template<class Interaction, class MicrofacetCache>
323-
scalar_type __pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
321+
scalar_type __pdf(NBL_CONST_REF_ARG(sample_type) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache, NBL_REF_ARG(bool) isInfinity)
324322
{
325323
using quant_query_type = typename ndf_type::quant_query_type;
326324
using dg1_query_type = typename ndf_type::dg1_query_type;
@@ -329,7 +327,7 @@ struct SCookTorrance
329327

330328
fresnel_type _f = impl::getOrientedFresnel<fresnel_type, IsBSDF>::__call(fresnel, interaction.getNdotV());
331329
quant_query_type qq = impl::quant_query_helper<ndf_type, fresnel_type, IsBSDF>::template __call<Interaction, MicrofacetCache>(ndf, _f, interaction, cache);
332-
quant_type DG1 = ndf.template DG1<sample_type, Interaction>(dq, qq, _sample, interaction);
330+
quant_type DG1 = ndf.template DG1<sample_type, Interaction>(dq, qq, _sample, interaction, isInfinity);
333331

334332
NBL_IF_CONSTEXPR(IsBSDF)
335333
{
@@ -350,8 +348,9 @@ struct SCookTorrance
350348
if (!impl::checkValid<fresnel_type, IsBSDF>::template __call<sample_type, Interaction, MicrofacetCache>(_f, _sample, interaction, cache))
351349
return scalar_type(0.0);
352350

353-
scalar_type _pdf = __pdf<Interaction, MicrofacetCache>(_sample, interaction, cache);
354-
return hlsl::mix(scalar_type(0.0), _pdf, _pdf < bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity));
351+
bool isInfinity;
352+
scalar_type _pdf = __pdf<Interaction, MicrofacetCache>(_sample, interaction, cache, isInfinity);
353+
return hlsl::mix(_pdf, scalar_type(0.0), isInfinity);
355354
}
356355

357356
template<class Interaction=conditional_t<IsAnisotropic,anisotropic_interaction_type,isotropic_interaction_type>,
@@ -362,14 +361,15 @@ struct SCookTorrance
362361
if (!_sample.isValid())
363362
return quotient_pdf_type::create(scalar_type(0.0), scalar_type(0.0)); // set pdf=0 when quo=0 because we don't want to give high weight to sampling strategy that yields 0 contribution
364363

365-
scalar_type _pdf = __pdf<Interaction, MicrofacetCache>(_sample, interaction, cache);
364+
bool isInfinity;
365+
scalar_type _pdf = __pdf<Interaction, MicrofacetCache>(_sample, interaction, cache, isInfinity);
366366
fresnel_type _f = impl::getOrientedFresnel<fresnel_type, IsBSDF>::__call(fresnel, interaction.getNdotV());
367367

368368
const bool valid = impl::checkValid<fresnel_type, IsBSDF>::template __call<sample_type, Interaction, MicrofacetCache>(_f, _sample, interaction, cache);
369369
assert(valid); // expect the generated sample to always be valid, different checks for brdf and btdf
370370

371371
scalar_type G2_over_G1 = scalar_type(1.0);
372-
if (_pdf < bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity))
372+
if (!isInfinity)
373373
{
374374
using g2g1_query_type = typename N::g2g1_query_type;
375375
g2g1_query_type gq = ndf.template createG2G1Query<sample_type, Interaction>(_sample, interaction);

include/nbl/builtin/hlsl/bxdf/ndf.hlsl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,29 @@ using cache_t = SAnisotropicMicrofacetCache<SIsotropicMicrofacetCache<float> >;
3434
#define NBL_CONCEPT_PARAM_4 (cache, dummy_impl::cache_t)
3535
#define NBL_CONCEPT_PARAM_5 (dg1_query, typename T::dg1_query_type)
3636
#define NBL_CONCEPT_PARAM_6 (g2_query, typename T::g2g1_query_type)
37-
NBL_CONCEPT_BEGIN(7)
37+
#define NBL_CONCEPT_PARAM_7 (is_inf, bool)
38+
NBL_CONCEPT_BEGIN(8)
3839
#define ndf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0
3940
#define quant_query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1
4041
#define _sample NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2
4142
#define interaction NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3
4243
#define cache NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_4
4344
#define dg1_query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_5
4445
#define g2_query NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_6
46+
#define is_inf NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_7
4547
NBL_CONCEPT_END(
4648
((NBL_CONCEPT_REQ_TYPE)(T::scalar_type))
4749
((NBL_CONCEPT_REQ_TYPE)(T::quant_type))
4850
((NBL_CONCEPT_REQ_TYPE)(T::dg1_query_type))
4951
((NBL_CONCEPT_REQ_TYPE)(T::g2g1_query_type))
5052
((NBL_CONCEPT_REQ_TYPE)(T::quant_query_type))
5153
// ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((T::GuaranteedVNDF), ::nbl::hlsl::is_same_v, bool))
52-
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D<dummy_impl::sample_t, dummy_impl::interaction_t, dummy_impl::cache_t>(quant_query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::quant_type))
53-
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1<dummy_impl::sample_t, dummy_impl::interaction_t>(dg1_query, quant_query, _sample, interaction)), ::nbl::hlsl::is_same_v, typename T::quant_type))
54+
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template D<dummy_impl::sample_t, dummy_impl::interaction_t, dummy_impl::cache_t>(quant_query, _sample, interaction, cache, is_inf)), ::nbl::hlsl::is_same_v, typename T::quant_type))
55+
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template DG1<dummy_impl::sample_t, dummy_impl::interaction_t>(dg1_query, quant_query, _sample, interaction, is_inf)), ::nbl::hlsl::is_same_v, typename T::quant_type))
5456
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template correlated<dummy_impl::sample_t, dummy_impl::interaction_t, dummy_impl::cache_t>(g2_query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type))
5557
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((ndf.template G2_over_G1<dummy_impl::sample_t, dummy_impl::interaction_t, dummy_impl::cache_t>(g2_query, _sample, interaction, cache)), ::nbl::hlsl::is_same_v, typename T::scalar_type))
5658
);
59+
#undef is_inf
5760
#undef g2_query
5861
#undef dg1_query
5962
#undef cache

include/nbl/builtin/hlsl/bxdf/ndf/beckmann.hlsl

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,14 @@ struct BeckmannCommon<T,false NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<
100100
using scalar_type = T;
101101

102102
template<class MicrofacetCache NBL_FUNC_REQUIRES(ReadableIsotropicMicrofacetCache<MicrofacetCache>)
103-
scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache)
103+
scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache, NBL_REF_ARG(bool) isInfinity)
104104
{
105105
if (a2 < numeric_limits<scalar_type>::min)
106+
{
107+
isInfinity = true;
106108
return bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity);
109+
}
110+
isInfinity = false;
107111
scalar_type NdotH2 = cache.getNdotH2();
108112
scalar_type nom = exp2<scalar_type>((NdotH2 - scalar_type(1.0)) / (log<scalar_type>(2.0) * a2 * NdotH2));
109113
scalar_type denom = a2 * NdotH2 * NdotH2;
@@ -126,10 +130,14 @@ struct BeckmannCommon<T,true NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T
126130
using scalar_type = T;
127131

128132
template<class MicrofacetCache NBL_FUNC_REQUIRES(AnisotropicMicrofacetCache<MicrofacetCache>)
129-
scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache)
133+
scalar_type D(NBL_CONST_REF_ARG(MicrofacetCache) cache, NBL_REF_ARG(bool) isInfinity)
130134
{
131135
if (a2 < numeric_limits<scalar_type>::min)
136+
{
137+
isInfinity = true;
132138
return bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity);
139+
}
140+
isInfinity = false;
133141
scalar_type NdotH2 = cache.getNdotH2();
134142
scalar_type nom = exp<scalar_type>(-(cache.getTdotH2() / ax2 + cache.getBdotH2() / ay2) / NdotH2);
135143
scalar_type denom = a2 * NdotH2 * NdotH2;
@@ -282,7 +290,8 @@ struct Beckmann
282290
enable_if_t<C::value && !IsAnisotropic, dg1_query_type> createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
283291
{
284292
dg1_query_type dg1_query;
285-
dg1_query.ndf = __ndf_base.template D<MicrofacetCache>(cache);
293+
bool dummy;
294+
dg1_query.ndf = __ndf_base.template D<MicrofacetCache>(cache, dummy);
286295
dg1_query.lambda_V = Lambda(__ndf_base.C2(interaction.getNdotV2()));
287296
return dg1_query;
288297
}
@@ -298,7 +307,8 @@ struct Beckmann
298307
enable_if_t<C::value && IsAnisotropic, dg1_query_type> createDG1Query(NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
299308
{
300309
dg1_query_type dg1_query;
301-
dg1_query.ndf = __ndf_base.template D<MicrofacetCache>(cache);
310+
bool dummy;
311+
dg1_query.ndf = __ndf_base.template D<MicrofacetCache>(cache, dummy);
302312
dg1_query.lambda_V = Lambda(__ndf_base.C2(interaction.getTdotV2(), interaction.getBdotV2(), interaction.getNdotV2()));
303313
return dg1_query;
304314
}
@@ -317,16 +327,18 @@ struct Beckmann
317327
}
318328

319329
template<class LS, class Interaction, class MicrofacetCache NBL_FUNC_REQUIRES(LightSample<LS> && RequiredInteraction<Interaction> && RequiredMicrofacetCache<MicrofacetCache>)
320-
quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache)
330+
quant_type D(NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_CONST_REF_ARG(MicrofacetCache) cache, NBL_REF_ARG(bool) isInfinity)
321331
{
322-
scalar_type d = __ndf_base.template D<MicrofacetCache>(cache);
332+
scalar_type d = __ndf_base.template D<MicrofacetCache>(cache, isInfinity);
323333
return createDualMeasureQuantity<T, reflect_refract, quant_query_type>(d, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query);
324334
}
325335

326336
template<class LS, class Interaction NBL_FUNC_REQUIRES(LightSample<LS> && RequiredInteraction<Interaction>)
327-
quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction)
337+
quant_type DG1(NBL_CONST_REF_ARG(dg1_query_type) query, NBL_CONST_REF_ARG(quant_query_type) quant_query, NBL_CONST_REF_ARG(LS) _sample, NBL_CONST_REF_ARG(Interaction) interaction, NBL_REF_ARG(bool) isInfinity)
328338
{
339+
scalar_type D = query.getNdf();
329340
scalar_type dg1 = query.getNdf() / (scalar_type(1.0) + query.getLambdaV());
341+
isInfinity = D == bit_cast<scalar_type>(numeric_limits<scalar_type>::infinity);
330342
return createDualMeasureQuantity<T, reflect_refract, quant_query_type>(dg1, interaction.getNdotV(BxDFClampMode::BCM_ABS), _sample.getNdotL(BxDFClampMode::BCM_ABS), quant_query);
331343
}
332344

0 commit comments

Comments
 (0)