From 3668d993b8e175fa624ac1dc88a38a79fec020a5 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 15 Jan 2025 11:50:17 +0700 Subject: [PATCH 01/40] check util functions --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 38 ++++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 256ed3ce9..e8dec9d5f 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -82,6 +82,30 @@ T rngUniformDist(NBL_REF_ARG(nbl::hlsl::Xoroshiro64Star) rng) return impl::RNGUniformDist::__call(rng); } +template +bool checkEq(T a, T b, float32_t eps) +{ + return nbl::hlsl::all>(nbl::hlsl::max(a / b, b / a) <= (T)(1 + eps)); +} + +template +bool checkLt(T a, T b) +{ + return nbl::hlsl::all>(a < b); +} + +template +bool checkZero(T a, float32_t eps) +{ + return nbl::hlsl::all>(nbl::hlsl::abs(a) < (T)eps); +} + +template<> +bool checkZero(float32_t a, float32_t eps) +{ + return nbl::hlsl::abs(a) < eps; +} + struct SBxDFTestResources { @@ -371,7 +395,7 @@ struct TestUOffset : TestBxDF using base_t = TestBxDFBase; using this_t = TestUOffset; - void compute() override + virtual void compute() override { aniso_cache cache, dummy; @@ -428,25 +452,23 @@ struct TestUOffset : TestBxDF { compute(); - if (nbl::hlsl::abs(pdf.pdf) < base_t::rc.eps) // something generated cannot have 0 probability of getting generated + if (checkZero(pdf.pdf, base_t::rc.eps)) // something generated cannot have 0 probability of getting generated return PDF_ZERO; - if (!all(pdf.quotient < (float32_t3)numeric_limits::infinity)) // importance sampler's job to prevent inf + if (!checkLt(pdf.quotient, (float32_t3)numeric_limits::infinity)) // importance sampler's job to prevent inf return QUOTIENT_INF; - if (all(nbl::hlsl::abs(bsdf) < (float32_t3)base_t::rc.eps) || all(pdf.quotient < (float32_t3)base_t::rc.eps)) + if (checkZero(bsdf, base_t::rc.eps) || checkZero(pdf.quotient, base_t::rc.eps)) return NOERR; // produces an "impossible" sample // get jacobian float32_t2x2 m = float32_t2x2(sx.TdotL - s.TdotL, sy.TdotL - s.TdotL, sx.BdotL - s.BdotL, sy.BdotL - s.BdotL); float det = nbl::hlsl::determinant(m); - bool jacobian_test = nbl::hlsl::abs(det*pdf.pdf/s.NdotL) < base_t::rc.eps; - if (!jacobian_test) + if (!checkZero(det * pdf.pdf / s.NdotL, base_t::rc.eps)) return JACOBIAN; - bool32_t3 diff_test = nbl::hlsl::max(pdf.value() / bsdf, bsdf / pdf.value()) <= (float32_t3)(1 + base_t::rc.eps); - if (!all(diff_test)) + if (!checkEq(pdf.value(), bsdf, base_t::rc.eps)) return PDF_EVAL_DIFF; return NOERR; From a66dc440963f10bb52f4f061f2313b87e70fb701 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 15 Jan 2025 14:52:35 +0700 Subject: [PATCH 02/40] reciprocity test --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 86 ++++++++++++++++++++++- 66_HLSLBxDFTests/main.cpp | 21 +++++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index e8dec9d5f..8f74229d6 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -138,7 +138,7 @@ struct SBxDFTestResources } // epsilon - float eps = 1e-3; + float eps = 1e-2; nbl::hlsl::Xoroshiro64Star rng; ray_dir_info_t V; @@ -495,6 +495,90 @@ struct TestUOffset : TestBxDF float32_t3 bsdf; }; +template +struct TestReciprocity : TestBxDF +{ + using base_t = TestBxDFBase; + using this_t = TestReciprocity; + + virtual void compute() override + { + aniso_cache cache, rec_cache; + + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) + s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy); + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) + s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy, cache); + if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) + s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u); + if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) + s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u, cache); + + ray_dir_info_t rec_V = s.L; + float VdotL = nbl::hlsl::dot(base_t::rc.V.direction,s.L.direction); + rec_s = sample_t::create(base_t::rc.V, VdotL, base_t::rc.T, base_t::rc.B, base_t::rc.N); + + iso_interaction rec_isointer = iso_interaction::create(rec_V, base_t::rc.N); + aniso_interaction rec_anisointer = aniso_interaction::create(rec_isointer, base_t::rc.T, base_t::rc.B); + rec_cache = cache; + rec_cache.VdotH = cache.LdotH; + rec_cache.LdotH = cache.VdotH; + + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v || is_basic_bsdf_v) + { + bsdf = float32_t3(base_t::bxdf.eval(s, base_t::isointer)); + rec_bsdf = float32_t3(base_t::bxdf.eval(rec_s, rec_isointer)); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) + { + if NBL_CONSTEXPR_FUNC (aniso) + { + bsdf = float32_t3(base_t::bxdf.eval(s, base_t::anisointer, cache)); + rec_bsdf = float32_t3(base_t::bxdf.eval(rec_s, rec_anisointer, rec_cache)); + } + else + { + iso_cache isocache = (iso_cache)cache; + iso_cache rec_isocache = (iso_cache)rec_cache; + bsdf = float32_t3(base_t::bxdf.eval(s, base_t::isointer, isocache)); + rec_bsdf = float32_t3(base_t::bxdf.eval(rec_s, rec_isointer, rec_isocache)); + } + } + } + + ErrorType test() + { + compute(); + + if (checkZero(bsdf, base_t::rc.eps)) + return NOERR; // produces an "impossible" sample + + if (!!checkEq(bsdf, rec_bsdf, base_t::rc.eps)) + return RECIPROCITY; + + return NOERR; + } + + static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) + { + uint32_t2 state = pcg32x2(seed); + + this_t t; + t.init(state); + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) + t.template initBxDF(t.rc); + else + t.initBxDF(t.rc); + + ErrorType e = t.test(); + if (e != NOERR) + cb.__call(e, t); + } + + sample_t s, rec_s; + float32_t3 bsdf, rec_bsdf; +}; + } } diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index f91ed5f02..f8278ca38 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -62,12 +62,29 @@ int main(int argc, char** argv) TestUOffset,true>::run(state, cb); TestUOffset>::run(state, cb); - //TestUOffset>::run(state); - //TestUOffset>::run(state); + //TestUOffset>::run(state, cb); + //TestUOffset>::run(state, cb); TestUOffset,false>::run(state, cb); TestUOffset,true>::run(state, cb); TestUOffset,false>::run(state, cb); TestUOffset,true>::run(state, cb); + + // test reciprocity + TestReciprocity>::run(state, cb); + TestReciprocity>::run(state, cb); + TestReciprocity, false>::run(state, cb); + TestReciprocity, true>::run(state, cb); + TestReciprocity, false>::run(state, cb); + TestReciprocity, true>::run(state, cb); + + TestReciprocity>::run(state, cb); + //TestReciprocity>::run(state, cb); + //TestReciprocity>::run(state, cb); + TestReciprocity, false>::run(state, cb); + TestReciprocity, true>::run(state, cb); + TestReciprocity, false>::run(state, cb); + TestReciprocity, true>::run(state, cb); + return 0; } \ No newline at end of file From b5d9778bb8ed7c37ad28da357ca709ede3706e9b Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 15 Jan 2025 16:43:36 +0700 Subject: [PATCH 03/40] negative value checks --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 8f74229d6..269dd5880 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -30,18 +30,6 @@ using spectral_t = vector; using bool32_t3 = vector; -// uint32_t pcg_hash(uint32_t v) -// { -// uint32_t state = v * 747796405u + 2891336453u; -// uint32_t word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; -// return (word >> 22u) ^ word; -// } - -// uint32_t2 pcg2d_hash(uint32_t v) -// { -// return uint32_t2(pcg_hash(v), pcg_hash(v+1)); -// } - namespace impl { @@ -156,7 +144,7 @@ struct SBxDFTestResources enum ErrorType : uint32_t { NOERR = 0, - NEGATIVE_VAL, // pdf/quotient/eval < 0 + NEGATIVE_VAL, // pdf/quotient/eval < 0 PDF_ZERO, // pdf = 0 QUOTIENT_INF, // quotient -> inf JACOBIAN, @@ -452,6 +440,9 @@ struct TestUOffset : TestBxDF { compute(); + if (checkLt(bsdf, (float32_t3)0.0) || checkLt(pdf.quotient, (float32_t3)0.0) || pdf.pdf < 0.0) + return NEGATIVE_VAL; + if (checkZero(pdf.pdf, base_t::rc.eps)) // something generated cannot have 0 probability of getting generated return PDF_ZERO; @@ -550,6 +541,9 @@ struct TestReciprocity : TestBxDF { compute(); + if (checkLt(bsdf, (float32_t3)0.0)) + return NEGATIVE_VAL; + if (checkZero(bsdf, base_t::rc.eps)) return NOERR; // produces an "impossible" sample From 5df264a96b2c7daf9056b3f77b247e0fd5d53a1e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 16 Jan 2025 11:43:31 +0700 Subject: [PATCH 04/40] fix test orders --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 50 +++++++++++------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 269dd5880..f694f495a 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -143,13 +143,13 @@ struct SBxDFTestResources enum ErrorType : uint32_t { - NOERR = 0, - NEGATIVE_VAL, // pdf/quotient/eval < 0 - PDF_ZERO, // pdf = 0 - QUOTIENT_INF, // quotient -> inf - JACOBIAN, - PDF_EVAL_DIFF, - RECIPROCITY + BET_NONE = 0, + BET_NEGATIVE_VAL, // pdf/quotient/eval < 0 + BET_PDF_ZERO, // pdf = 0 + BET_QUOTIENT_INF, // quotient -> inf + BET_JACOBIAN, + BET_PDF_EVAL_DIFF, + BET_RECIPROCITY }; struct TestBase @@ -440,29 +440,29 @@ struct TestUOffset : TestBxDF { compute(); - if (checkLt(bsdf, (float32_t3)0.0) || checkLt(pdf.quotient, (float32_t3)0.0) || pdf.pdf < 0.0) - return NEGATIVE_VAL; - if (checkZero(pdf.pdf, base_t::rc.eps)) // something generated cannot have 0 probability of getting generated - return PDF_ZERO; + return BET_PDF_ZERO; if (!checkLt(pdf.quotient, (float32_t3)numeric_limits::infinity)) // importance sampler's job to prevent inf - return QUOTIENT_INF; + return BET_QUOTIENT_INF; if (checkZero(bsdf, base_t::rc.eps) || checkZero(pdf.quotient, base_t::rc.eps)) - return NOERR; // produces an "impossible" sample + return BET_NONE; // produces an "impossible" sample + + if (checkLt(bsdf, (float32_t3)0.0) || checkLt(pdf.quotient, (float32_t3)0.0) || pdf.pdf < 0.0) + return BET_NEGATIVE_VAL; - // get jacobian + // get BET_jacobian float32_t2x2 m = float32_t2x2(sx.TdotL - s.TdotL, sy.TdotL - s.TdotL, sx.BdotL - s.BdotL, sy.BdotL - s.BdotL); float det = nbl::hlsl::determinant(m); if (!checkZero(det * pdf.pdf / s.NdotL, base_t::rc.eps)) - return JACOBIAN; + return BET_JACOBIAN; if (!checkEq(pdf.value(), bsdf, base_t::rc.eps)) - return PDF_EVAL_DIFF; + return BET_PDF_EVAL_DIFF; - return NOERR; + return BET_NONE; } static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) @@ -477,7 +477,7 @@ struct TestUOffset : TestBxDF t.initBxDF(t.rc); ErrorType e = t.test(); - if (e != NOERR) + if (e != BET_NONE) cb.__call(e, t); } @@ -541,16 +541,16 @@ struct TestReciprocity : TestBxDF { compute(); - if (checkLt(bsdf, (float32_t3)0.0)) - return NEGATIVE_VAL; - if (checkZero(bsdf, base_t::rc.eps)) - return NOERR; // produces an "impossible" sample + return BET_NONE; // produces an "impossible" sample + + if (checkLt(bsdf, (float32_t3)0.0)) + return BET_NEGATIVE_VAL; if (!!checkEq(bsdf, rec_bsdf, base_t::rc.eps)) - return RECIPROCITY; + return BET_RECIPROCITY; - return NOERR; + return BET_NONE; } static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) @@ -565,7 +565,7 @@ struct TestReciprocity : TestBxDF t.initBxDF(t.rc); ErrorType e = t.test(); - if (e != NOERR) + if (e != BET_NONE) cb.__call(e, t); } From e6e434a9e0ebfe92bf3187f4bcd81acd0f01de27 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 17 Jan 2025 14:46:07 +0700 Subject: [PATCH 05/40] use new param structs for bxdf funcs --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 105 ++++++++++++++++++---- 66_HLSLBxDFTests/main.cpp | 16 ++-- 2 files changed, 97 insertions(+), 24 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index f694f495a..97eac4ed3 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -27,6 +27,7 @@ using iso_cache = bxdf::SIsotropicMicrofacetCache; using aniso_cache = bxdf::SAnisotropicMicrofacetCache; using quotient_pdf_t = bxdf::quotient_and_pdf; using spectral_t = vector; +using params_t = bxdf::SBxDFParams; using bool32_t3 = vector; @@ -126,7 +127,7 @@ struct SBxDFTestResources } // epsilon - float eps = 1e-2; + float eps = 1e-3; nbl::hlsl::Xoroshiro64Star rng; ray_dir_info_t V; @@ -386,6 +387,8 @@ struct TestUOffset : TestBxDF virtual void compute() override { aniso_cache cache, dummy; + iso_cache isocache; + params_t params; float32_t3 ux = base_t::rc.u + float32_t3(base_t::rc.eps,0,0); float32_t3 uy = base_t::rc.u + float32_t3(0,base_t::rc.eps,0); @@ -395,43 +398,60 @@ struct TestUOffset : TestBxDF s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy); sx = base_t::bxdf.generate(base_t::anisointer, ux.xy); sy = base_t::bxdf.generate(base_t::anisointer, uy.xy); + params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy, cache); sx = base_t::bxdf.generate(base_t::anisointer, ux.xy, dummy); sy = base_t::bxdf.generate(base_t::anisointer, uy.xy, dummy); + + if NBL_CONSTEXPR_FUNC (aniso) + params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); + else + { + isocache = (iso_cache)cache; + params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); + } } if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u); sx = base_t::bxdf.generate(base_t::anisointer, ux); sy = base_t::bxdf.generate(base_t::anisointer, uy); + params = params_t::template create(s, base_t::isointer, bxdf::BCM_ABS); } if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u, cache); sx = base_t::bxdf.generate(base_t::anisointer, ux, dummy); sy = base_t::bxdf.generate(base_t::anisointer, uy, dummy); + + if NBL_CONSTEXPR_FUNC (aniso) + params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); + else + { + isocache = (iso_cache)cache; + params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); + } } if NBL_CONSTEXPR_FUNC (is_basic_brdf_v || is_basic_bsdf_v) { - pdf = base_t::bxdf.quotient_and_pdf(s, base_t::isointer); - bsdf = float32_t3(base_t::bxdf.eval(s, base_t::isointer)); + pdf = base_t::bxdf.quotient_and_pdf(params); + bsdf = float32_t3(base_t::bxdf.eval(params)); } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) { if NBL_CONSTEXPR_FUNC (aniso) { - pdf = base_t::bxdf.quotient_and_pdf(s, base_t::anisointer, cache); - bsdf = float32_t3(base_t::bxdf.eval(s, base_t::anisointer, cache)); + pdf = base_t::bxdf.quotient_and_pdf(params); + bsdf = float32_t3(base_t::bxdf.eval(params)); } else { - iso_cache isocache = (iso_cache)cache; - pdf = base_t::bxdf.quotient_and_pdf(s, base_t::isointer, isocache); - bsdf = float32_t3(base_t::bxdf.eval(s, base_t::isointer, isocache)); + pdf = base_t::bxdf.quotient_and_pdf(params); + bsdf = float32_t3(base_t::bxdf.eval(params)); } } } @@ -495,16 +515,44 @@ struct TestReciprocity : TestBxDF virtual void compute() override { aniso_cache cache, rec_cache; + iso_cache isocache, rec_isocache; + params_t params, rec_params; if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) + { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy); + params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); + } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) + { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy, cache); + + if NBL_CONSTEXPR_FUNC (aniso) + params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); + else + { + isocache = (iso_cache)cache; + params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); + } + } if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) + { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u); + params = params_t::template create(s, base_t::isointer, bxdf::BCM_ABS); + } if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) + { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u, cache); + if NBL_CONSTEXPR_FUNC (aniso) + params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); + else + { + isocache = (iso_cache)cache; + params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); + } + } + ray_dir_info_t rec_V = s.L; float VdotL = nbl::hlsl::dot(base_t::rc.V.direction,s.L.direction); rec_s = sample_t::create(base_t::rc.V, VdotL, base_t::rc.T, base_t::rc.B, base_t::rc.N); @@ -514,25 +562,50 @@ struct TestReciprocity : TestBxDF rec_cache = cache; rec_cache.VdotH = cache.LdotH; rec_cache.LdotH = cache.VdotH; + + rec_isocache = (iso_cache)rec_cache; + + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) + rec_params = params_t::template create(rec_s, rec_isointer, bxdf::BCM_MAX); + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) + { + if NBL_CONSTEXPR_FUNC (aniso) + rec_params = params_t::template create(rec_s, rec_anisointer, cache, bxdf::BCM_MAX); + else + { + rec_isocache = (iso_cache)rec_cache; + rec_params = params_t::template create(rec_s, rec_isointer, rec_isocache, bxdf::BCM_MAX); + } + } + if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) + rec_params = params_t::template create(rec_s, rec_isointer, bxdf::BCM_ABS); + if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) + { + if NBL_CONSTEXPR_FUNC (aniso) + rec_params = params_t::template create(rec_s, rec_anisointer, cache, bxdf::BCM_ABS); + else + { + rec_isocache = (iso_cache)rec_cache; + rec_params = params_t::template create(rec_s, rec_isointer, rec_isocache, bxdf::BCM_ABS); + } + } if NBL_CONSTEXPR_FUNC (is_basic_brdf_v || is_basic_bsdf_v) { - bsdf = float32_t3(base_t::bxdf.eval(s, base_t::isointer)); - rec_bsdf = float32_t3(base_t::bxdf.eval(rec_s, rec_isointer)); + bsdf = float32_t3(base_t::bxdf.eval(params)); + rec_bsdf = float32_t3(base_t::bxdf.eval(rec_params)); } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) { if NBL_CONSTEXPR_FUNC (aniso) { - bsdf = float32_t3(base_t::bxdf.eval(s, base_t::anisointer, cache)); - rec_bsdf = float32_t3(base_t::bxdf.eval(rec_s, rec_anisointer, rec_cache)); + bsdf = float32_t3(base_t::bxdf.eval(params)); + rec_bsdf = float32_t3(base_t::bxdf.eval(rec_params)); } else { - iso_cache isocache = (iso_cache)cache; - iso_cache rec_isocache = (iso_cache)rec_cache; - bsdf = float32_t3(base_t::bxdf.eval(s, base_t::isointer, isocache)); - rec_bsdf = float32_t3(base_t::bxdf.eval(rec_s, rec_isointer, rec_isocache)); + bsdf = float32_t3(base_t::bxdf.eval(params)); + rec_bsdf = float32_t3(base_t::bxdf.eval(rec_params)); } } } diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index f8278ca38..1603e9572 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -14,22 +14,22 @@ struct PrintFailureCallback : FailureCallback { switch (error) { - case NEGATIVE_VAL: + case BET_NEGATIVE_VAL: fprintf(stderr, "%s pdf/quotient/eval < 0\n", failedFor.name.c_str()); break; - case PDF_ZERO: + case BET_PDF_ZERO: fprintf(stderr, "%s pdf = 0\n", failedFor.name.c_str()); break; - case QUOTIENT_INF: + case BET_QUOTIENT_INF: fprintf(stderr, "%s quotient -> inf\n", failedFor.name.c_str()); break; - case JACOBIAN: + case BET_JACOBIAN: fprintf(stderr, "%s failed the jacobian * pdf test\n", failedFor.name.c_str()); break; - case PDF_EVAL_DIFF: - fprintf(stderr, "%s quotient * pdf - eval not 0\n", failedFor.name.c_str()); + case BET_PDF_EVAL_DIFF: + fprintf(stderr, "%s quotient * pdf != eval\n", failedFor.name.c_str()); break; - case RECIPROCITY: + case BET_RECIPROCITY: fprintf(stderr, "%s failed the reprocity test\n", failedFor.name.c_str()); break; default: @@ -49,7 +49,7 @@ int main(int argc, char** argv) { std::cout << std::fixed << std::setprecision(4); - const uint32_t state = 69u; + const uint32_t state = 1u; PrintFailureCallback cb; From d494e3de99e5b4779ac1eadc8db7fd001cb253d9 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 20 Jan 2025 09:57:48 +0700 Subject: [PATCH 06/40] print more info on error --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 6 +- 66_HLSLBxDFTests/main.cpp | 79 +++++++++++++---------- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 97eac4ed3..3f953f67e 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -126,8 +126,8 @@ struct SBxDFTestResources return retval; } - // epsilon - float eps = 1e-3; + float eps = 1e-3; // epsilon + uint32_t state; // init state seed, for debugging nbl::hlsl::Xoroshiro64Star rng; ray_dir_info_t V; @@ -491,6 +491,7 @@ struct TestUOffset : TestBxDF this_t t; t.init(state); + t.rc.state = seed; if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) t.template initBxDF(t.rc); else @@ -632,6 +633,7 @@ struct TestReciprocity : TestBxDF this_t t; t.init(state); + t.rc.state = seed; if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) t.template initBxDF(t.rc); else diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 1603e9572..9046eb22b 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include @@ -15,25 +17,25 @@ struct PrintFailureCallback : FailureCallback switch (error) { case BET_NEGATIVE_VAL: - fprintf(stderr, "%s pdf/quotient/eval < 0\n", failedFor.name.c_str()); + fprintf(stderr, "seed %u: %s pdf/quotient/eval < 0\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_PDF_ZERO: - fprintf(stderr, "%s pdf = 0\n", failedFor.name.c_str()); + fprintf(stderr, "seed %u: %s pdf = 0\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_QUOTIENT_INF: - fprintf(stderr, "%s quotient -> inf\n", failedFor.name.c_str()); + fprintf(stderr, "seed %u: %s quotient -> inf\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_JACOBIAN: - fprintf(stderr, "%s failed the jacobian * pdf test\n", failedFor.name.c_str()); + fprintf(stderr, "seed %u: %s failed the jacobian * pdf test\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_PDF_EVAL_DIFF: - fprintf(stderr, "%s quotient * pdf != eval\n", failedFor.name.c_str()); + fprintf(stderr, "seed %u: %s quotient * pdf != eval\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_RECIPROCITY: - fprintf(stderr, "%s failed the reprocity test\n", failedFor.name.c_str()); + fprintf(stderr, "seed %u: %s failed the reprocity test\n", failedFor.rc.state, failedFor.name.c_str()); break; default: - fprintf(stderr, "%s unknown error\n", failedFor.name.c_str()); + fprintf(stderr, "seed %u: %s unknown error\n", failedFor.rc.state, failedFor.name.c_str()); } for (volatile bool repeat = true; IsDebuggerPresent() && repeat; ) @@ -45,46 +47,53 @@ struct PrintFailureCallback : FailureCallback } }; +#define FOR_EACH_BEGIN(r) std::for_each(std::execution::par_unseq, r.begin(), r.end(), [&](uint32_t i) { +#define FOR_EACH_END }); + int main(int argc, char** argv) { std::cout << std::fixed << std::setprecision(4); - const uint32_t state = 1u; - + auto r = std::ranges::views::iota(0u, 10u); PrintFailureCallback cb; // test u offset, 2 axis - TestUOffset>::run(state, cb); - TestUOffset>::run(state, cb); - TestUOffset,false>::run(state, cb); - TestUOffset,true>::run(state, cb); - TestUOffset,false>::run(state, cb); - TestUOffset,true>::run(state, cb); + FOR_EACH_BEGIN(r) + TestUOffset>::run(i, cb); + TestUOffset>::run(i, cb); + TestUOffset,false>::run(i, cb); + TestUOffset,true>::run(i, cb); + TestUOffset,false>::run(i, cb); + TestUOffset,true>::run(i, cb); - TestUOffset>::run(state, cb); - //TestUOffset>::run(state, cb); - //TestUOffset>::run(state, cb); - TestUOffset,false>::run(state, cb); - TestUOffset,true>::run(state, cb); - TestUOffset,false>::run(state, cb); - TestUOffset,true>::run(state, cb); + TestUOffset>::run(i, cb); + //TestUOffset>::run(i, cb); + //TestUOffset>::run(i, cb); + TestUOffset,false>::run(i, cb); + TestUOffset,true>::run(i, cb); + TestUOffset,false>::run(i, cb); + TestUOffset,true>::run(i, cb); + FOR_EACH_END // test reciprocity - TestReciprocity>::run(state, cb); - TestReciprocity>::run(state, cb); - TestReciprocity, false>::run(state, cb); - TestReciprocity, true>::run(state, cb); - TestReciprocity, false>::run(state, cb); - TestReciprocity, true>::run(state, cb); + FOR_EACH_BEGIN(r) + TestReciprocity>::run(i, cb); + TestReciprocity>::run(i, cb); + TestReciprocity, false>::run(i, cb); + TestReciprocity, true>::run(i, cb); + TestReciprocity, false>::run(i, cb); + TestReciprocity, true>::run(i, cb); - TestReciprocity>::run(state, cb); - //TestReciprocity>::run(state, cb); - //TestReciprocity>::run(state, cb); - TestReciprocity, false>::run(state, cb); - TestReciprocity, true>::run(state, cb); - TestReciprocity, false>::run(state, cb); - TestReciprocity, true>::run(state, cb); + TestReciprocity>::run(i, cb); + //TestReciprocity>::run(i, cb); + //TestReciprocity>::run(i, cb); + TestReciprocity, false>::run(i, cb); + TestReciprocity, true>::run(i, cb); + TestReciprocity, false>::run(i, cb); + TestReciprocity, true>::run(i, cb); + FOR_EACH_END + return 0; } \ No newline at end of file From 3625ad2d55e619e36f38fbf1cbd2a742677b02b2 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 21 Jan 2025 17:22:16 +0700 Subject: [PATCH 07/40] fix reciprocity test, adjust comparison --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 18 +++++++++--------- 66_HLSLBxDFTests/main.cpp | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 3f953f67e..edd223bb3 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -460,13 +460,13 @@ struct TestUOffset : TestBxDF { compute(); - if (checkZero(pdf.pdf, base_t::rc.eps)) // something generated cannot have 0 probability of getting generated + if (checkZero(pdf.pdf, 1e-5)) // something generated cannot have 0 probability of getting generated return BET_PDF_ZERO; if (!checkLt(pdf.quotient, (float32_t3)numeric_limits::infinity)) // importance sampler's job to prevent inf return BET_QUOTIENT_INF; - if (checkZero(bsdf, base_t::rc.eps) || checkZero(pdf.quotient, base_t::rc.eps)) + if (checkZero(bsdf, 1e-5) || checkZero(pdf.quotient, 1e-5)) return BET_NONE; // produces an "impossible" sample if (checkLt(bsdf, (float32_t3)0.0) || checkLt(pdf.quotient, (float32_t3)0.0) || pdf.pdf < 0.0) @@ -476,10 +476,10 @@ struct TestUOffset : TestBxDF float32_t2x2 m = float32_t2x2(sx.TdotL - s.TdotL, sy.TdotL - s.TdotL, sx.BdotL - s.BdotL, sy.BdotL - s.BdotL); float det = nbl::hlsl::determinant(m); - if (!checkZero(det * pdf.pdf / s.NdotL, base_t::rc.eps)) + if (!checkZero(det * pdf.pdf / s.NdotL, 1e-5)) return BET_JACOBIAN; - if (!checkEq(pdf.value(), bsdf, base_t::rc.eps)) + if (!checkEq(pdf.value(), bsdf, 1e-2)) return BET_PDF_EVAL_DIFF; return BET_NONE; @@ -556,7 +556,7 @@ struct TestReciprocity : TestBxDF ray_dir_info_t rec_V = s.L; float VdotL = nbl::hlsl::dot(base_t::rc.V.direction,s.L.direction); - rec_s = sample_t::create(base_t::rc.V, VdotL, base_t::rc.T, base_t::rc.B, base_t::rc.N); + rec_s = sample_t::create(base_t::rc.V, s.VdotL, base_t::rc.T, base_t::rc.B, base_t::rc.N); iso_interaction rec_isointer = iso_interaction::create(rec_V, base_t::rc.N); aniso_interaction rec_anisointer = aniso_interaction::create(rec_isointer, base_t::rc.T, base_t::rc.B); @@ -571,7 +571,7 @@ struct TestReciprocity : TestBxDF if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) { if NBL_CONSTEXPR_FUNC (aniso) - rec_params = params_t::template create(rec_s, rec_anisointer, cache, bxdf::BCM_MAX); + rec_params = params_t::template create(rec_s, rec_anisointer, rec_cache, bxdf::BCM_MAX); else { rec_isocache = (iso_cache)rec_cache; @@ -583,7 +583,7 @@ struct TestReciprocity : TestBxDF if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) { if NBL_CONSTEXPR_FUNC (aniso) - rec_params = params_t::template create(rec_s, rec_anisointer, cache, bxdf::BCM_ABS); + rec_params = params_t::template create(rec_s, rec_anisointer, rec_cache, bxdf::BCM_ABS); else { rec_isocache = (iso_cache)rec_cache; @@ -615,13 +615,13 @@ struct TestReciprocity : TestBxDF { compute(); - if (checkZero(bsdf, base_t::rc.eps)) + if (checkZero(bsdf, 1e-5)) return BET_NONE; // produces an "impossible" sample if (checkLt(bsdf, (float32_t3)0.0)) return BET_NEGATIVE_VAL; - if (!!checkEq(bsdf, rec_bsdf, base_t::rc.eps)) + if (!checkEq(bsdf, rec_bsdf, 1e-2)) return BET_RECIPROCITY; return BET_NONE; diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 9046eb22b..494030a54 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -32,7 +32,7 @@ struct PrintFailureCallback : FailureCallback fprintf(stderr, "seed %u: %s quotient * pdf != eval\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_RECIPROCITY: - fprintf(stderr, "seed %u: %s failed the reprocity test\n", failedFor.rc.state, failedFor.name.c_str()); + fprintf(stderr, "seed %u: %s failed the reciprocity test\n", failedFor.rc.state, failedFor.name.c_str()); break; default: fprintf(stderr, "seed %u: %s unknown error\n", failedFor.rc.state, failedFor.name.c_str()); @@ -47,7 +47,7 @@ struct PrintFailureCallback : FailureCallback } }; -#define FOR_EACH_BEGIN(r) std::for_each(std::execution::par_unseq, r.begin(), r.end(), [&](uint32_t i) { +#define FOR_EACH_BEGIN(r) std::for_each(std::execution::seq, r.begin(), r.end(), [&](uint32_t i) { #define FOR_EACH_END }); int main(int argc, char** argv) From 839d42c7cfd5d11e550f1463a32fd3650eb3a99f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 22 Jan 2025 15:14:30 +0700 Subject: [PATCH 08/40] fixed reciprocity test --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index edd223bb3..67090fd15 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -435,7 +435,7 @@ struct TestUOffset : TestBxDF params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } } - + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v || is_basic_bsdf_v) { pdf = base_t::bxdf.quotient_and_pdf(params); @@ -479,7 +479,7 @@ struct TestUOffset : TestBxDF if (!checkZero(det * pdf.pdf / s.NdotL, 1e-5)) return BET_JACOBIAN; - if (!checkEq(pdf.value(), bsdf, 1e-2)) + if (!checkEq(pdf.value(), bsdf, 5e-2)) return BET_PDF_EVAL_DIFF; return BET_NONE; @@ -517,7 +517,6 @@ struct TestReciprocity : TestBxDF { aniso_cache cache, rec_cache; iso_cache isocache, rec_isocache; - params_t params, rec_params; if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) { @@ -554,9 +553,11 @@ struct TestReciprocity : TestBxDF } } + float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); ray_dir_info_t rec_V = s.L; - float VdotL = nbl::hlsl::dot(base_t::rc.V.direction,s.L.direction); - rec_s = sample_t::create(base_t::rc.V, s.VdotL, base_t::rc.T, base_t::rc.B, base_t::rc.N); + ray_dir_info_t rec_localV = ray_dir_info_t::transform(toTangentSpace, rec_V); + ray_dir_info_t rec_localL = ray_dir_info_t::transform(toTangentSpace, base_t::rc.V); + rec_s = sample_t::createFromTangentSpace(rec_localV.direction, rec_localL, base_t::anisointer.getFromTangentSpace()); iso_interaction rec_isointer = iso_interaction::create(rec_V, base_t::rc.N); aniso_interaction rec_anisointer = aniso_interaction::create(rec_isointer, base_t::rc.T, base_t::rc.B); @@ -621,8 +622,11 @@ struct TestReciprocity : TestBxDF if (checkLt(bsdf, (float32_t3)0.0)) return BET_NEGATIVE_VAL; - if (!checkEq(bsdf, rec_bsdf, 1e-2)) - return BET_RECIPROCITY; + float32_t3 a = bsdf * nbl::hlsl::abs(params.NdotV); + float32_t3 b = rec_bsdf * nbl::hlsl::abs(rec_params.NdotV); + if (!(a == b)) // avoid division by 0 + if (!checkEq(a, b, 1e-2)) + return BET_RECIPROCITY; return BET_NONE; } @@ -646,6 +650,7 @@ struct TestReciprocity : TestBxDF sample_t s, rec_s; float32_t3 bsdf, rec_bsdf; + params_t params, rec_params; }; } From a40ba940b372b635a3ff353f63229a6f77f87337 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 23 Jan 2025 13:41:04 +0700 Subject: [PATCH 09/40] test buckets of inf --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 162 +++++++++++++++++++++- 66_HLSLBxDFTests/main.cpp | 59 +++++--- 2 files changed, 200 insertions(+), 21 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 67090fd15..4820a11b1 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -12,6 +12,10 @@ #ifndef __HLSL_VERSION #include +#include +#include +#include +#include #endif namespace nbl @@ -150,7 +154,8 @@ enum ErrorType : uint32_t BET_QUOTIENT_INF, // quotient -> inf BET_JACOBIAN, BET_PDF_EVAL_DIFF, - BET_RECIPROCITY + BET_RECIPROCITY, + BET_PRINT_MSG }; struct TestBase @@ -172,6 +177,7 @@ struct TestBase #ifndef __HLSL_VERSION std::string name = "base"; + std::string errMsg = ""; #endif }; @@ -379,10 +385,10 @@ NBL_CONSTEXPR bool is_microfacet_bsdf_v = is_microfacet_bsdf::value; template -struct TestUOffset : TestBxDF +struct TestJacobian : TestBxDF { using base_t = TestBxDFBase; - using this_t = TestUOffset; + using this_t = TestJacobian; virtual void compute() override { @@ -653,6 +659,156 @@ struct TestReciprocity : TestBxDF params_t params, rec_params; }; +#ifndef __HLSL_VERSION // because unordered_map +template +struct TestBucket : TestBxDF +{ + using base_t = TestBxDFBase; + using this_t = TestBucket; + + void clearBuckets() + { + for (float z = -1.0f; z < 1.0f; z += stride) + { + for (float y = -1.0f; y < 1.0f; y += stride) + { + for (float x = -1.0f; x < 1.0f; x += stride) + { + buckets[float32_t3(x, y, z)] = 0; + } + } + } + } + + float bin(float a) + { + float diff = std::fmod(a, stride); + float b = (a < 0) ? -0.2f : 0.0f; + return a - diff + b; + } + + virtual void compute() override + { + clearBuckets(); + + aniso_cache cache, dummy; + iso_cache isocache; + params_t params; + + sample_t s; + quotient_pdf_t pdf; + float32_t3 bsdf; + + NBL_CONSTEXPR uint32_t samples = 500; + for (uint32_t i = 0; i < samples; i++) + { + float32_t3 u = float32_t3(rngUniformDist(base_t::rc.rng), 0.0); + + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) + { + s = base_t::bxdf.generate(base_t::anisointer, u.xy); + params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) + { + s = base_t::bxdf.generate(base_t::anisointer, u.xy, cache); + + if NBL_CONSTEXPR_FUNC (aniso) + params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); + else + { + isocache = (iso_cache)cache; + params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); + } + } + if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) + { + s = base_t::bxdf.generate(base_t::anisointer, u); + params = params_t::template create(s, base_t::isointer, bxdf::BCM_ABS); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) + { + s = base_t::bxdf.generate(base_t::anisointer, u, cache); + + if NBL_CONSTEXPR_FUNC (aniso) + params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); + else + { + isocache = (iso_cache)cache; + params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); + } + } + + // put s into bucket + // TODO: probably change to bucket with polar coords + const float32_t3 L = s.L.direction; + float32_t3 bucket = float32_t3(bin(L.x), bin(L.y), bin(L.z)); + + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v || is_basic_bsdf_v) + { + pdf = base_t::bxdf.quotient_and_pdf(params); + bsdf = float32_t3(base_t::bxdf.eval(params)); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) + { + if NBL_CONSTEXPR_FUNC (aniso) + { + pdf = base_t::bxdf.quotient_and_pdf(params); + bsdf = float32_t3(base_t::bxdf.eval(params)); + } + else + { + pdf = base_t::bxdf.quotient_and_pdf(params); + bsdf = float32_t3(base_t::bxdf.eval(params)); + } + } + + // check pdf == INF + if (pdf.pdf == numeric_limits::infinity) + buckets[bucket] += 1; + } + +#ifndef __HLSL_VERSION + for (auto const& b : buckets) { + if (!selective || b.second > 0) + { + const float32_t3 v = b.first; + base_t::errMsg += std::format("({:.1f},{:.1f},{:.1f}): {}\n", v.x, v.y, v.z, b.second); + } + } +#endif + } + + ErrorType test() + { + compute(); + + return (base_t::errMsg.length() == 0) ? BET_NONE : BET_PRINT_MSG; + } + + static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) + { + uint32_t2 state = pcg32x2(seed); + + this_t t; + t.init(state); + t.rc.state = seed; + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) + t.template initBxDF(t.rc); + else + t.initBxDF(t.rc); + + ErrorType e = t.test(); + if (e != BET_NONE) + cb.__call(e, t); + } + + bool selective = true; // print only buckets with count > 0 + float stride = 0.2f; + std::unordered_map> buckets; +}; +#endif + } } diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 494030a54..b1d795d81 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -34,11 +34,15 @@ struct PrintFailureCallback : FailureCallback case BET_RECIPROCITY: fprintf(stderr, "seed %u: %s failed the reciprocity test\n", failedFor.rc.state, failedFor.name.c_str()); break; + case BET_PRINT_MSG: + fprintf(stderr, "seed %u: %s error message\n%s\n", failedFor.rc.state, failedFor.name.c_str(), failedFor.errMsg.c_str()); + break; default: fprintf(stderr, "seed %u: %s unknown error\n", failedFor.rc.state, failedFor.name.c_str()); } - for (volatile bool repeat = true; IsDebuggerPresent() && repeat; ) + // TODO: #ifdef NBL_ENABLE_DEBUGBREAK + for (volatile bool repeat = true; IsDebuggerPresent() && repeat && (error != BET_PRINT_MSG); ) { repeat = false; __debugbreak(); @@ -54,30 +58,30 @@ int main(int argc, char** argv) { std::cout << std::fixed << std::setprecision(4); - auto r = std::ranges::views::iota(0u, 10u); + auto r10 = std::ranges::views::iota(0u, 10u); PrintFailureCallback cb; // test u offset, 2 axis - FOR_EACH_BEGIN(r) - TestUOffset>::run(i, cb); - TestUOffset>::run(i, cb); - TestUOffset,false>::run(i, cb); - TestUOffset,true>::run(i, cb); - TestUOffset,false>::run(i, cb); - TestUOffset,true>::run(i, cb); - - TestUOffset>::run(i, cb); - //TestUOffset>::run(i, cb); - //TestUOffset>::run(i, cb); - TestUOffset,false>::run(i, cb); - TestUOffset,true>::run(i, cb); - TestUOffset,false>::run(i, cb); - TestUOffset,true>::run(i, cb); + FOR_EACH_BEGIN(r10) + TestJacobian>::run(i, cb); + TestJacobian>::run(i, cb); + TestJacobian, false>::run(i, cb); + TestJacobian, true>::run(i, cb); + TestJacobian, false>::run(i, cb); + TestJacobian,true>::run(i, cb); + + TestJacobian>::run(i, cb); + //TestJacobian>::run(i, cb); + //TestJacobian>::run(i, cb); + TestJacobian, false>::run(i, cb); + TestJacobian, true>::run(i, cb); + TestJacobian, false>::run(i, cb); + TestJacobian,true>::run(i, cb); FOR_EACH_END // test reciprocity - FOR_EACH_BEGIN(r) + FOR_EACH_BEGIN(r10) TestReciprocity>::run(i, cb); TestReciprocity>::run(i, cb); TestReciprocity, false>::run(i, cb); @@ -93,6 +97,25 @@ int main(int argc, char** argv) TestReciprocity, false>::run(i, cb); TestReciprocity, true>::run(i, cb); FOR_EACH_END + + + // test buckets of inf + FOR_EACH_BEGIN(r10) + TestBucket>::run(i, cb); + TestBucket>::run(i, cb); + TestBucket, false>::run(i, cb); + TestBucket, true>::run(i, cb); + TestBucket, false>::run(i, cb); + TestBucket, true>::run(i, cb); + + TestBucket>::run(i, cb); + //TestBucket>::run(i, cb); + //TestBucket>::run(i, cb); + TestBucket, false>::run(i, cb); + TestBucket, true>::run(i, cb); + TestBucket, false>::run(i, cb); + TestBucket, true>::run(i, cb); + FOR_EACH_END return 0; From d0d5d9382b7850cd660d9eeb6681ff550b3b4c5a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 23 Jan 2025 14:34:28 +0700 Subject: [PATCH 10/40] bucket by polar coords --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 44 ++++++++++++++--------- 66_HLSLBxDFTests/main.cpp | 32 ++++++++--------- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 4820a11b1..59490524f 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -99,6 +99,22 @@ bool checkZero(float32_t a, float32_t eps) return nbl::hlsl::abs(a) < eps; } +#ifndef __HLSL_VERSION +// because atan2 is not in tgmath.hlsl yet + +// takes in normalized vectors +inline float32_t3 polarToCartesian(float32_t2 theta_phi) +{ + return float32_t3(std::cos(theta_phi.x) * std::cos(theta_phi.y), + std::sin(theta_phi.x) * std::cos(theta_phi.y), + std::sin(theta_phi.y)); +} + +inline float32_t2 cartesianToPolar(float32_t3 coords) +{ + return float32_t2(std::atan2(coords.y, coords.x), std::acos(coords.z)); +} +#endif struct SBxDFTestResources { @@ -668,14 +684,11 @@ struct TestBucket : TestBxDF void clearBuckets() { - for (float z = -1.0f; z < 1.0f; z += stride) + for (float y = -1.0f; y < 1.0f; y += stride) { - for (float y = -1.0f; y < 1.0f; y += stride) + for (float x = -1.0f; x < 1.0f; x += stride) { - for (float x = -1.0f; x < 1.0f; x += stride) - { - buckets[float32_t3(x, y, z)] = 0; - } + buckets[float32_t2(x, y)] = 0; } } } @@ -683,7 +696,7 @@ struct TestBucket : TestBxDF float bin(float a) { float diff = std::fmod(a, stride); - float b = (a < 0) ? -0.2f : 0.0f; + float b = (a < 0) ? -stride : 0.0f; return a - diff + b; } @@ -739,11 +752,6 @@ struct TestBucket : TestBxDF } } - // put s into bucket - // TODO: probably change to bucket with polar coords - const float32_t3 L = s.L.direction; - float32_t3 bucket = float32_t3(bin(L.x), bin(L.y), bin(L.z)); - if NBL_CONSTEXPR_FUNC (is_basic_brdf_v || is_basic_bsdf_v) { pdf = base_t::bxdf.quotient_and_pdf(params); @@ -763,17 +771,21 @@ struct TestBucket : TestBxDF } } - // check pdf == INF + // put s into bucket + const float32_t2 coords = cartesianToPolar(s.L.direction); + float32_t2 bucket = float32_t2(bin(coords.x * 0.5f * numbers::inv_pi), bin(coords.y * numbers::inv_pi)); + if (pdf.pdf == numeric_limits::infinity) buckets[bucket] += 1; } #ifndef __HLSL_VERSION + // double check this conversion makes sense for (auto const& b : buckets) { if (!selective || b.second > 0) { - const float32_t3 v = b.first; - base_t::errMsg += std::format("({:.1f},{:.1f},{:.1f}): {}\n", v.x, v.y, v.z, b.second); + const float32_t3 v = polarToCartesian(b.first * float32_t2(2, 1) * numbers::pi); + base_t::errMsg += std::format("({:.3f},{:.3f},{:.3f}): {}\n", v.x, v.y, v.z, b.second); } } #endif @@ -805,7 +817,7 @@ struct TestBucket : TestBxDF bool selective = true; // print only buckets with count > 0 float stride = 0.2f; - std::unordered_map> buckets; + std::unordered_map> buckets; }; #endif diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index b1d795d81..ebed2c896 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -100,22 +100,22 @@ int main(int argc, char** argv) // test buckets of inf - FOR_EACH_BEGIN(r10) - TestBucket>::run(i, cb); - TestBucket>::run(i, cb); - TestBucket, false>::run(i, cb); - TestBucket, true>::run(i, cb); - TestBucket, false>::run(i, cb); - TestBucket, true>::run(i, cb); - - TestBucket>::run(i, cb); - //TestBucket>::run(i, cb); - //TestBucket>::run(i, cb); - TestBucket, false>::run(i, cb); - TestBucket, true>::run(i, cb); - TestBucket, false>::run(i, cb); - TestBucket, true>::run(i, cb); - FOR_EACH_END + //FOR_EACH_BEGIN(r10) + TestBucket>::run(5u, cb); + //TestBucket>::run(i, cb); + //TestBucket, false>::run(i, cb); + //TestBucket, true>::run(i, cb); + //TestBucket, false>::run(i, cb); + //TestBucket, true>::run(i, cb); + + //TestBucket>::run(i, cb); + ////TestBucket>::run(i, cb); + ////TestBucket>::run(i, cb); + //TestBucket, false>::run(i, cb); + //TestBucket, true>::run(i, cb); + //TestBucket, false>::run(i, cb); + //TestBucket, true>::run(i, cb); + //FOR_EACH_END return 0; From c8f8dae80af839bd27f6bfdceddc1a559c512201 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 24 Jan 2025 14:52:32 +0700 Subject: [PATCH 11/40] chi2 test --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 398 +++++++++++++++++++++- 66_HLSLBxDFTests/main.cpp | 35 +- 2 files changed, 408 insertions(+), 25 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 59490524f..b78ee9e94 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -14,8 +14,10 @@ #include #include #include +#include #include #include +#include #endif namespace nbl @@ -105,14 +107,14 @@ bool checkZero(float32_t a, float32_t eps) // takes in normalized vectors inline float32_t3 polarToCartesian(float32_t2 theta_phi) { - return float32_t3(std::cos(theta_phi.x) * std::cos(theta_phi.y), - std::sin(theta_phi.x) * std::cos(theta_phi.y), - std::sin(theta_phi.y)); + return float32_t3(std::cos(theta_phi.y) * std::cos(theta_phi.x), + std::sin(theta_phi.y) * std::cos(theta_phi.x), + std::sin(theta_phi.x)); } inline float32_t2 cartesianToPolar(float32_t3 coords) { - return float32_t2(std::atan2(coords.y, coords.x), std::acos(coords.z)); + return float32_t2(std::acos(coords.z), std::atan2(coords.y, coords.x)); } #endif @@ -704,7 +706,7 @@ struct TestBucket : TestBxDF { clearBuckets(); - aniso_cache cache, dummy; + aniso_cache cache; iso_cache isocache; params_t params; @@ -772,8 +774,10 @@ struct TestBucket : TestBxDF } // put s into bucket - const float32_t2 coords = cartesianToPolar(s.L.direction); - float32_t2 bucket = float32_t2(bin(coords.x * 0.5f * numbers::inv_pi), bin(coords.y * numbers::inv_pi)); + float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); + const ray_dir_info_t localL = ray_dir_info_t::transform(toTangentSpace, s.L); + const float32_t2 coords = cartesianToPolar(localL.direction); + float32_t2 bucket = float32_t2(bin(coords.x * numbers::inv_pi), bin(coords.y * 0.5f * numbers::inv_pi)); if (pdf.pdf == numeric_limits::infinity) buckets[bucket] += 1; @@ -784,7 +788,7 @@ struct TestBucket : TestBxDF for (auto const& b : buckets) { if (!selective || b.second > 0) { - const float32_t3 v = polarToCartesian(b.first * float32_t2(2, 1) * numbers::pi); + const float32_t3 v = polarToCartesian(b.first * float32_t2(1, 2) * numbers::pi); base_t::errMsg += std::format("({:.3f},{:.3f},{:.3f}): {}\n", v.x, v.y, v.z, b.second); } } @@ -819,6 +823,384 @@ struct TestBucket : TestBxDF float stride = 0.2f; std::unordered_map> buckets; }; + +inline float adaptiveSimpson(const std::function& f, float x0, float x1, float eps = 1e-6, int depth = 6) +{ + int count = 0; + std::function integrate = + [&](float a, float b, float c, float fa, float fb, float fc, float I, float eps, int depth) + { + float d = 0.5f * (a + b); + float e = 0.5f * (b + c); + float fd = f(d); + float fe = f(e); + + float h = c - a; + float I0 = (1.0f / 12.0f) * h * (fa + 4 * fd + fb); + float I1 = (1.0f / 12.0f) * h * (fb + 4 * fe + fc); + float Ip = I0 + I1; + count++; + + if (depth <= 0 || std::abs(Ip - I) < 15 * eps) + return Ip + (1.0f / 15.0f) * (Ip - I); + + return integrate(a, d, b, fa, fd, fb, I0, .5f * eps, depth - 1) + + integrate(b, e, c, fb, fe, fc, I1, .5f * eps, depth - 1); + }; + + float a = x0; + float b = 0.5f * (x0 + x1); + float c = x1; + float fa = f(a); + float fb = f(b); + float fc = f(c); + float I = (c - a) * (1.0f / 6.0f) * (fa + 4.f * fb + fc); + return integrate(a, b, c, fa, fb, fc, I, eps, depth); +} + +inline float adaptiveSimpson2D(const std::function& f, float32_t2 x0, float32_t2 x1, float eps = 1e-6, int depth = 6) +{ + const auto integrate = [&](float y) -> float + { + return adaptiveSimpson(std::bind(f, std::placeholders::_1, y), x0.x, x1.x, eps, depth); + }; + return adaptiveSimpson(integrate, x0.y, x1.y, eps, depth); +} + +// adapted from pbrt chi2 test: https://github.com/mmp/pbrt-v4/blob/792aaaa08d97dbedf11a3bb23e246b6443d847b4/src/pbrt/bsdfs_test.cpp#L280 +template +struct TestChi2 : TestBxDF +{ + using base_t = TestBxDFBase; + using this_t = TestChi2; + + void clearBuckets() + { + const uint32_t freqSize = thetaSplits * phiSplits; + countFreq.resize(freqSize); + std::fill(countFreq.begin(), countFreq.end(), 0); + integrateFreq.resize(freqSize); + std::fill(integrateFreq.begin(), integrateFreq.end(), 0); + } + + double RLGamma(double a, double x) { + const double epsilon = 0.000000000000001; + const double big = 4503599627370496.0; + const double bigInv = 2.22044604925031308085e-16; + assert(a < 0 || x < 0); + + if (x == 0) + return 0.0f; + + double ax = (a * std::log(x)) - x - std::lgamma(a); + if (ax < -709.78271289338399) + return a < x ? 1.0 : 0.0; + + if (x <= 1 || x <= a) + { + double r2 = a; + double c2 = 1; + double ans2 = 1; + + do { + r2 = r2 + 1; + c2 = c2 * x / r2; + ans2 += c2; + } while ((c2 / ans2) > epsilon); + + return std::exp(ax) * ans2 / a; + } + + int c = 0; + double y = 1 - a; + double z = x + y + 1; + double p3 = 1; + double q3 = x; + double p2 = x + 1; + double q2 = z * x; + double ans = p2 / q2; + double error; + + do { + c++; + y += 1; + z += 2; + double yc = y * c; + double p = (p2 * z) - (p3 * yc); + double q = (q2 * z) - (q3 * yc); + + if (q != 0) + { + double nextans = p / q; + error = std::abs((ans - nextans) / nextans); + ans = nextans; + } + else + { + error = 1; + } + + p3 = p2; + p2 = p; + q3 = q2; + q2 = q; + + if (std::abs(p) > big) + { + p3 *= bigInv; + p2 *= bigInv; + q3 *= bigInv; + q2 *= bigInv; + } + } while (error > epsilon); + + return 1.0 - (std::exp(ax) * ans); + } + + double chi2CDF(double x, int dof) + { + if (dof < 1 || x < 0) + { + return 0.0; + } + else if (dof == 2) + { + return 1.0 - std::exp(-0.5 * x); + } + else + { + return RLGamma(0.5 * dof, 0.5 * x); + } + } + + virtual void compute() override + { + clearBuckets(); + + float thetaFactor = thetaSplits * numbers::inv_pi; + float phiFactor = phiSplits * 0.5f * numbers::inv_pi; + + sample_t s; + aniso_cache cache; + for (uint32_t i = 0; i < numSamples; i++) + { + float32_t3 u = float32_t3(rngUniformDist(base_t::rc.rng), 0.0); + + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) + { + s = base_t::bxdf.generate(base_t::anisointer, u.xy); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) + { + s = base_t::bxdf.generate(base_t::anisointer, u.xy, cache); + } + if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) + { + s = base_t::bxdf.generate(base_t::anisointer, u); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) + { + s = base_t::bxdf.generate(base_t::anisointer, u, cache); + } + + // put s into bucket + float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); + const ray_dir_info_t localL = ray_dir_info_t::transform(toTangentSpace, s.L); + float32_t2 coords = cartesianToPolar(localL.direction) * float32_t2(thetaFactor, phiFactor); + if (coords.y < 0) + coords.y += 2.f * numbers::pi * thetaFactor; + + int thetaBin = clamp((int)std::floor(coords.x), 0, thetaSplits - 1); + int phiBin = clamp((int)std::floor(coords.y), 0, phiSplits - 1); + + countFreq[thetaBin * phiSplits + phiBin] += 1; + } + + thetaFactor = 1.f / thetaFactor; + phiFactor = 1.f / phiFactor; + + int idx = 0; + for (int i = 0; i < thetaSplits; i++) + { + for (int j = 0; j < phiSplits; j++) + { + integrateFreq[idx++] = numSamples * adaptiveSimpson2D([&](float theta, float phi) -> float + { + float cosTheta = std::cos(theta), sinTheta = std::sin(theta); + float cosPhi = std::cos(phi), sinPhi = std::sin(phi); + + float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); + ray_dir_info_t localV = ray_dir_info_t::transform(toTangentSpace, base_t::rc.V); + ray_dir_info_t L; + L.direction = float32_t3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta); + ray_dir_info_t localL = ray_dir_info_t::transform(toTangentSpace, L); + sample_t s = sample_t::createFromTangentSpace(localV.direction, localL, base_t::anisointer.getFromTangentSpace()); + + params_t params; + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) + { + params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) + { + aniso_cache cache = aniso_cache::template createForReflection(base_t::anisointer, s); + + if NBL_CONSTEXPR_FUNC (aniso) + params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); + else + { + iso_cache isocache = (iso_cache)cache; + params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); + } + } + if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) + { + params = params_t::template create(s, base_t::isointer, bxdf::BCM_ABS); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) + { + aniso_cache cache = aniso_cache::template createForReflection(base_t::anisointer, s); + + if NBL_CONSTEXPR_FUNC (aniso) + params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); + else + { + iso_cache isocache = (iso_cache)cache; + params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); + } + } + + quotient_pdf_t pdf; + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v || is_basic_bsdf_v) + { + pdf = base_t::bxdf.quotient_and_pdf(params); + } + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) + { + if NBL_CONSTEXPR_FUNC (aniso) + { + pdf = base_t::bxdf.quotient_and_pdf(params); + } + else + { + pdf = base_t::bxdf.quotient_and_pdf(params); + } + } + return pdf.pdf * sinTheta; + }, + float32_t2(i * thetaFactor, j * phiFactor), float32_t2((i + 1) * thetaFactor, (j + 1) * phiFactor)); + } + } + } + + ErrorType test() + { + compute(); + + // chi2 + std::vector cells(thetaSplits * phiSplits); + for (uint32_t i = 0; i < cells.size(); i++) + { + cells[i].expFreq = integrateFreq[i]; + cells[i].index = i; + } + std::sort(cells.begin(), cells.end(), [](const Cell& a, const Cell& b) + { + return a.expFreq < b.expFreq; + }); + + float pooledFreqs = 0, pooledExpFreqs = 0, chsq = 0; + int pooledCells = 0, dof = 0; + + for (const Cell& c : cells) + { + if (integrateFreq[c.index] == 0) + { + if (countFreq[c.index] > numSamples * 1e-5) + { + base_t::errMsg = std::format("expected frequency of 0 for c but found {} samples", countFreq[c.index]); + return BET_PRINT_MSG; + } + } + else if (integrateFreq[c.index] < minFreq) + { + pooledFreqs += countFreq[c.index]; + pooledExpFreqs += integrateFreq[c.index]; + pooledCells++; + } + else if (pooledExpFreqs > 0 && pooledExpFreqs < minFreq) + { + pooledFreqs += countFreq[c.index]; + pooledExpFreqs += integrateFreq[c.index]; + pooledCells++; + } + else + { + float diff = countFreq[c.index] - integrateFreq[c.index]; + chsq += (diff * diff) / integrateFreq[c.index]; + ++dof; + } + } + + if (pooledExpFreqs > 0 || pooledFreqs > 0) + { + float diff = pooledFreqs - pooledExpFreqs; + chsq += (diff * diff) / pooledExpFreqs; + dof++; + } + dof--; + + if (dof <= 0) + { + base_t::errMsg = std::format("degrees of freedom {} too low", dof); + return BET_PRINT_MSG; + } + + float pval = 1.0f - static_cast(chi2CDF(chsq, dof)); + float alpha = 1.0f - std::pow(1.0f - threshold, 1.0f / numTests); + + if (pval < alpha || !std::isfinite(pval)) + { + base_t::errMsg = std::format("chi2 test: rejected the null hypothesis (p-value = {:.3f}, significance level = {:.3f}", pval, alpha); + return BET_PRINT_MSG; + } + + return BET_NONE; + } + + static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) + { + uint32_t2 state = pcg32x2(seed); + + this_t t; + t.init(state); + t.rc.state = seed; + if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) + t.template initBxDF(t.rc); + else + t.initBxDF(t.rc); + + ErrorType e = t.test(); + if (e != BET_NONE) + cb.__call(e, t); + } + + struct Cell { + float expFreq; + uint32_t index; + }; + + uint32_t thetaSplits = 80; + uint32_t phiSplits = 160; + uint32_t numSamples = 1000; + + uint32_t threshold = 1e-2; + uint32_t minFreq = 5; + uint32_t numTests = 5; + + std::vector countFreq; + std::vector integrateFreq; +}; #endif } diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index ebed2c896..23429a810 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -61,7 +61,7 @@ int main(int argc, char** argv) auto r10 = std::ranges::views::iota(0u, 10u); PrintFailureCallback cb; - // test u offset, 2 axis + // test jacobian * pdf FOR_EACH_BEGIN(r10) TestJacobian>::run(i, cb); TestJacobian>::run(i, cb); @@ -100,23 +100,24 @@ int main(int argc, char** argv) // test buckets of inf - //FOR_EACH_BEGIN(r10) - TestBucket>::run(5u, cb); - //TestBucket>::run(i, cb); - //TestBucket, false>::run(i, cb); - //TestBucket, true>::run(i, cb); - //TestBucket, false>::run(i, cb); - //TestBucket, true>::run(i, cb); - - //TestBucket>::run(i, cb); - ////TestBucket>::run(i, cb); - ////TestBucket>::run(i, cb); - //TestBucket, false>::run(i, cb); - //TestBucket, true>::run(i, cb); - //TestBucket, false>::run(i, cb); - //TestBucket, true>::run(i, cb); - //FOR_EACH_END + FOR_EACH_BEGIN(r10) + TestBucket>::run(i, cb); + TestBucket>::run(i, cb); + TestBucket, false>::run(i, cb); + TestBucket, true>::run(i, cb); + TestBucket, false>::run(i, cb); + TestBucket, true>::run(i, cb); + + TestBucket>::run(i, cb); + //TestBucket>::run(i, cb); + //TestBucket>::run(i, cb); + TestBucket, false>::run(i, cb); + TestBucket, true>::run(i, cb); + TestBucket, false>::run(i, cb); + TestBucket, true>::run(i, cb); + FOR_EACH_END + TestChi2>::run(5u, cb); return 0; } \ No newline at end of file From 8781cb08ace883d996ced0538cf749fa5426e709 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 27 Jan 2025 17:01:23 +0700 Subject: [PATCH 12/40] fix chi2 test, beckmann still error --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 24 ++++++++++++----------- 66_HLSLBxDFTests/main.cpp | 24 ++++++++++++++++++++++- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index b78ee9e94..371f82b48 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -114,7 +114,7 @@ inline float32_t3 polarToCartesian(float32_t2 theta_phi) inline float32_t2 cartesianToPolar(float32_t3 coords) { - return float32_t2(std::acos(coords.z), std::atan2(coords.y, coords.x)); + return float32_t2(std::acos(clamp(coords.z, -1, 1)), std::atan2(coords.y, coords.x)); } #endif @@ -887,7 +887,7 @@ struct TestChi2 : TestBxDF const double epsilon = 0.000000000000001; const double big = 4503599627370496.0; const double bigInv = 2.22044604925031308085e-16; - assert(a < 0 || x < 0); + assert(a >= 0 && x >= 0); if (x == 0) return 0.0f; @@ -982,7 +982,8 @@ struct TestChi2 : TestBxDF sample_t s; aniso_cache cache; - for (uint32_t i = 0; i < numSamples; i++) + uint32_t i = 0; + for (; i < numSamples; i++) { float32_t3 u = float32_t3(rngUniformDist(base_t::rc.rng), 0.0); @@ -1004,16 +1005,17 @@ struct TestChi2 : TestBxDF } // put s into bucket - float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); - const ray_dir_info_t localL = ray_dir_info_t::transform(toTangentSpace, s.L); - float32_t2 coords = cartesianToPolar(localL.direction) * float32_t2(thetaFactor, phiFactor); + // float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); + // const ray_dir_info_t localL = ray_dir_info_t::transform(toTangentSpace, s.L); + float32_t2 coords = cartesianToPolar(s.L.direction) * float32_t2(thetaFactor, phiFactor); if (coords.y < 0) - coords.y += 2.f * numbers::pi * thetaFactor; + coords.y += 2.f * numbers::pi * phiFactor; int thetaBin = clamp((int)std::floor(coords.x), 0, thetaSplits - 1); int phiBin = clamp((int)std::floor(coords.y), 0, phiSplits - 1); - countFreq[thetaBin * phiSplits + phiBin] += 1; + uint32_t idx = thetaBin * phiSplits + phiBin; + countFreq[idx] += 1; } thetaFactor = 1.f / thetaFactor; @@ -1138,7 +1140,7 @@ struct TestChi2 : TestBxDF { float diff = countFreq[c.index] - integrateFreq[c.index]; chsq += (diff * diff) / integrateFreq[c.index]; - ++dof; + dof++; } } @@ -1148,7 +1150,7 @@ struct TestChi2 : TestBxDF chsq += (diff * diff) / pooledExpFreqs; dof++; } - dof--; + dof -= 1; if (dof <= 0) { @@ -1192,7 +1194,7 @@ struct TestChi2 : TestBxDF uint32_t thetaSplits = 80; uint32_t phiSplits = 160; - uint32_t numSamples = 1000; + uint32_t numSamples = 1000000; uint32_t threshold = 1e-2; uint32_t minFreq = 5; diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 23429a810..5f6f425b8 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -58,6 +58,7 @@ int main(int argc, char** argv) { std::cout << std::fixed << std::setprecision(4); + auto r5 = std::ranges::views::iota(0u, 5u); auto r10 = std::ranges::views::iota(0u, 10u); PrintFailureCallback cb; @@ -117,7 +118,28 @@ int main(int argc, char** argv) TestBucket, true>::run(i, cb); FOR_EACH_END - TestChi2>::run(5u, cb); + //TestChi2>::run(5u, cb); + TestChi2, false>::run(1u, cb); + TestChi2, true>::run(1u, cb); + + + // chi2 test for sampling and pdf + //FOR_EACH_BEGIN(r5) + //TestChi2>::run(i, cb); + //TestChi2>::run(i, cb); + //TestChi2, false>::run(i, cb); + //TestChi2, true>::run(i, cb); + //TestChi2, false>::run(i, cb); + //TestChi2, true>::run(i, cb); + + //TestChi2>::run(i, cb); + ////TestChi2>::run(i, cb); + ////TestChi2>::run(i, cb); + //TestChi2, false>::run(i, cb); + //TestChi2, true>::run(i, cb); + //TestChi2, false>::run(i, cb); + //TestChi2, true>::run(i, cb); + //FOR_EACH_END return 0; } \ No newline at end of file From 724acd5d62da9f643588bd60d787a1da4747665f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 28 Jan 2025 17:25:43 +0700 Subject: [PATCH 13/40] add visualization option for chi2 samples --- 66_HLSLBxDFTests/CMakeLists.txt | 24 +++-- 66_HLSLBxDFTests/app_resources/tests.hlsl | 115 ++++++++++++++++++++-- 66_HLSLBxDFTests/main.cpp | 2 +- 3 files changed, 124 insertions(+), 17 deletions(-) diff --git a/66_HLSLBxDFTests/CMakeLists.txt b/66_HLSLBxDFTests/CMakeLists.txt index d26a90205..66168ba88 100644 --- a/66_HLSLBxDFTests/CMakeLists.txt +++ b/66_HLSLBxDFTests/CMakeLists.txt @@ -1,28 +1,32 @@ set(NBL_INCLUDE_SEARCH_DIRECTORIES - "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/include" ) include(common RESULT_VARIABLE RES) if(NOT RES) - message(FATAL_ERROR "common.cmake not found. Should be in {repo_root}/cmake directory") + message(FATAL_ERROR "common.cmake not found. Should be in {repo_root}/cmake directory") endif() nbl_create_executable_project("" "" "${NBL_INCLUDE_SEARCH_DIRECTORIES}" "" "${NBL_EXECUTABLE_PROJECT_CREATION_PCH_TARGET}") if(NBL_EMBED_BUILTIN_RESOURCES) - set(_BR_TARGET_ ${EXECUTABLE_NAME}_builtinResourceData) - set(RESOURCE_DIR "app_resources") + set(_BR_TARGET_ ${EXECUTABLE_NAME}_builtinResourceData) + set(RESOURCE_DIR "app_resources") - get_filename_component(_SEARCH_DIRECTORIES_ "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) - get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/src" ABSOLUTE) - get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE) + get_filename_component(_SEARCH_DIRECTORIES_ "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) + get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/src" ABSOLUTE) + get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE) file(GLOB_RECURSE BUILTIN_RESOURCE_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}" CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}/*") foreach(RES_FILE ${BUILTIN_RESOURCE_FILES}) LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "${RES_FILE}") endforeach() - ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_SEARCH_DIRECTORIES_}" "${RESOURCE_DIR}" "nbl::this_example::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}") + ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_SEARCH_DIRECTORIES_}" "${RESOURCE_DIR}" "nbl::this_example::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}") - LINK_BUILTIN_RESOURCES_TO_TARGET(${EXECUTABLE_NAME} ${_BR_TARGET_}) -endif() \ No newline at end of file + LINK_BUILTIN_RESOURCES_TO_TARGET(${EXECUTABLE_NAME} ${_BR_TARGET_}) +endif() + +add_dependencies(${EXECUTABLE_NAME} OpenEXR) +target_link_libraries(${EXECUTABLE_NAME} PRIVATE OpenEXR) +target_include_directories(${EXECUTABLE_NAME} PUBLIC $) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 371f82b48..b859d5d96 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -18,6 +18,10 @@ #include #include #include + +#include "ImfRgbaFile.h" +#include "ImfArray.h" +#include #endif namespace nbl @@ -973,6 +977,101 @@ struct TestChi2 : TestBxDF } } + Imf::Rgba mapColor(float v, float vmin, float vmax) + { + Imf::Rgba c(1, 1, 1); + float diff = vmax - vmin; + v = clamp(v, vmin, vmax); + + if (v < (vmin + 0.25f * diff)) + { + c.r = 0; + c.g = 4.f * (v - vmin) / diff; + } + else if (v < (vmin + 0.5f * diff)) + { + c.r = 0; + c.b = 1.f + 4.f * (vmin + 0.25f * diff - v) / diff; + } + else if (v < (vmin + 0.75f * diff)) + { + c.r = 4.f * (v - vmin - 0.5f * diff) / diff; + c.b = 0; + } + else + { + c.g = 1.f + 4.f * (vmin + 0.75f * diff - v) / diff; + c.b = 0; + } + + return(c); + } + + void writeToEXR() + { + std::string filename = std::format("chi2test_{}.exr", base_t::name); + // std::ofstream f(filename.c_str()); + + // f << "countFreq = [ "; + // for (int i = 0; i < thetaSplits; ++i) + // { + // for (int j = 0; j < phiSplits; ++j) + // { + // f << countFreq[i * phiSplits + j]; + // if (j + 1 < phiSplits) + // f << ", "; + // } + // if (i + 1 < thetaSplits) + // f << "; "; + // } + // f << " ];" << std::endl << "integrateFreq = [ "; + // for (int i = 0; i < thetaSplits; ++i) + // { + // for (int j = 0; j < phiSplits; ++j) + // { + // f << integrateFreq[i * phiSplits + j]; + // if (j + 1 < phiSplits) + // f << ", "; + // } + // if (i + 1 < thetaSplits) + // f << "; "; + // } + // f << " ];" << std::endl + // << "colormap(jet);" << std::endl + // << "clf; subplot(2,1,1);" << std::endl + // << "imagesc(countFreq);" << std::endl + // << "title('Observed frequencies');" << std::endl + // << "axis equal;" << std::endl + // << "subplot(2,1,2);" << std::endl + // << "imagesc(integrateFreq);" << std::endl + // << "axis equal;" << std::endl + // << "title('Expected frequencies');" << std::endl; + // f.close(); + + // int width = 10; + // int height = 10; + + int totalWidth = phiSplits; + int totalHeight = 2 * thetaSplits + 1; + + Imf::Array2D pixels(totalWidth, totalHeight); + for (int y = 0; y < thetaSplits; y++) + for (int x = 0; x < phiSplits; x++) + pixels[y][x] = mapColor(countFreq[y * phiSplits + x], 0, 255); + + for (int x = 0; x < phiSplits; x++) + pixels[thetaSplits][x] = Imf::Rgba(1, 1, 1); + + for (int y = 0; y < thetaSplits; y++) + for (int x = 0; x < phiSplits; x++) + pixels[thetaSplits + 1 + y][x] = mapColor(integrateFreq[y * phiSplits + x], 0, 255); + + Imf::Header header(totalWidth, totalHeight); + Imf::RgbaOutputFile file(filename.c_str(), header, Imf::WRITE_RGBA); + file.setFrameBuffer(&pixels[0][0], 1, totalWidth); + file.writePixels(totalHeight); + } + virtual void compute() override { clearBuckets(); @@ -982,8 +1081,7 @@ struct TestChi2 : TestBxDF sample_t s; aniso_cache cache; - uint32_t i = 0; - for (; i < numSamples; i++) + for (uint32_t i = 0; i < numSamples; i++) { float32_t3 u = float32_t3(rngUniformDist(base_t::rc.rng), 0.0); @@ -1014,19 +1112,19 @@ struct TestChi2 : TestBxDF int thetaBin = clamp((int)std::floor(coords.x), 0, thetaSplits - 1); int phiBin = clamp((int)std::floor(coords.y), 0, phiSplits - 1); - uint32_t idx = thetaBin * phiSplits + phiBin; - countFreq[idx] += 1; + uint32_t freqidx = thetaBin * phiSplits + phiBin; + countFreq[freqidx] += 1; } thetaFactor = 1.f / thetaFactor; phiFactor = 1.f / phiFactor; - int idx = 0; + uint32_t intidx = 0; for (int i = 0; i < thetaSplits; i++) { for (int j = 0; j < phiSplits; j++) { - integrateFreq[idx++] = numSamples * adaptiveSimpson2D([&](float theta, float phi) -> float + integrateFreq[intidx++] = numSamples * adaptiveSimpson2D([&](float theta, float phi) -> float { float cosTheta = std::cos(theta), sinTheta = std::sin(theta); float cosPhi = std::cos(phi), sinPhi = std::sin(phi); @@ -1099,6 +1197,9 @@ struct TestChi2 : TestBxDF { compute(); + if (write_frequencies) + writeToEXR(); + // chi2 std::vector cells(thetaSplits * phiSplits); for (uint32_t i = 0; i < cells.size(); i++) @@ -1199,6 +1300,8 @@ struct TestChi2 : TestBxDF uint32_t threshold = 1e-2; uint32_t minFreq = 5; uint32_t numTests = 5; + + bool write_frequencies = true; std::vector countFreq; std::vector integrateFreq; diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 5f6f425b8..f88a284ad 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -119,7 +119,7 @@ int main(int argc, char** argv) FOR_EACH_END //TestChi2>::run(5u, cb); - TestChi2, false>::run(1u, cb); + //TestChi2, false>::run(1u, cb); TestChi2, true>::run(1u, cb); From e1cbc1a547c021ca7445338048c89e1bb0fe077a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 29 Jan 2025 11:22:23 +0700 Subject: [PATCH 14/40] fixed exr visualization --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 74 ++++++++--------------- 66_HLSLBxDFTests/main.cpp | 2 +- 2 files changed, 26 insertions(+), 50 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index b859d5d96..9e6d409bd 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -20,8 +20,24 @@ #include #include "ImfRgbaFile.h" +#include "ImfOutputFile.h" +#include "ImfChannelList.h" +#include "ImfChannelListAttribute.h" +#include "ImfStringAttribute.h" +#include "ImfMatrixAttribute.h" #include "ImfArray.h" + +#include "ImfFrameBuffer.h" +#include "ImfHeader.h" + +#include "ImfNamespace.h" #include + +namespace IMF = Imf; +namespace IMATH = Imath; + +using namespace IMF; +using namespace IMATH; #endif namespace nbl @@ -1004,71 +1020,31 @@ struct TestChi2 : TestBxDF c.b = 0; } - return(c); + return c; } void writeToEXR() { std::string filename = std::format("chi2test_{}.exr", base_t::name); - // std::ofstream f(filename.c_str()); - - // f << "countFreq = [ "; - // for (int i = 0; i < thetaSplits; ++i) - // { - // for (int j = 0; j < phiSplits; ++j) - // { - // f << countFreq[i * phiSplits + j]; - // if (j + 1 < phiSplits) - // f << ", "; - // } - // if (i + 1 < thetaSplits) - // f << "; "; - // } - // f << " ];" << std::endl << "integrateFreq = [ "; - // for (int i = 0; i < thetaSplits; ++i) - // { - // for (int j = 0; j < phiSplits; ++j) - // { - // f << integrateFreq[i * phiSplits + j]; - // if (j + 1 < phiSplits) - // f << ", "; - // } - // if (i + 1 < thetaSplits) - // f << "; "; - // } - // f << " ];" << std::endl - // << "colormap(jet);" << std::endl - // << "clf; subplot(2,1,1);" << std::endl - // << "imagesc(countFreq);" << std::endl - // << "title('Observed frequencies');" << std::endl - // << "axis equal;" << std::endl - // << "subplot(2,1,2);" << std::endl - // << "imagesc(integrateFreq);" << std::endl - // << "axis equal;" << std::endl - // << "title('Expected frequencies');" << std::endl; - // f.close(); - - // int width = 10; - // int height = 10; int totalWidth = phiSplits; int totalHeight = 2 * thetaSplits + 1; - Imf::Array2D pixels(totalWidth, totalHeight); + Array2D pixels(totalWidth, totalHeight); for (int y = 0; y < thetaSplits; y++) for (int x = 0; x < phiSplits; x++) - pixels[y][x] = mapColor(countFreq[y * phiSplits + x], 0, 255); + pixels[y][x] = mapColor(countFreq[y * phiSplits + x], -512.f, 511.f); // TODO: shouldn't map to negative numbers - for (int x = 0; x < phiSplits; x++) - pixels[thetaSplits][x] = Imf::Rgba(1, 1, 1); + // for (int x = 0; x < phiSplits; x++) + // pixels[thetaSplits][x] = Rgba(1, 1, 1); for (int y = 0; y < thetaSplits; y++) for (int x = 0; x < phiSplits; x++) - pixels[thetaSplits + 1 + y][x] = mapColor(integrateFreq[y * phiSplits + x], 0, 255); + pixels[thetaSplits + y][x] = mapColor(integrateFreq[y * phiSplits + x], -512.f, 511.f); - Imf::Header header(totalWidth, totalHeight); - Imf::RgbaOutputFile file(filename.c_str(), header, Imf::WRITE_RGBA); - file.setFrameBuffer(&pixels[0][0], 1, totalWidth); + Header header(totalWidth, totalHeight); + RgbaOutputFile file(filename.c_str(), header, WRITE_RGBA); + file.setFrameBuffer(&pixels[0][0], 1, totalWidth+1); file.writePixels(totalHeight); } diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index f88a284ad..0b23bb7a4 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -120,7 +120,7 @@ int main(int argc, char** argv) //TestChi2>::run(5u, cb); //TestChi2, false>::run(1u, cb); - TestChi2, true>::run(1u, cb); + TestChi2, true>::run(10u, cb); // chi2 test for sampling and pdf From 9387298379805f90f5f36982f2f18917bc837a17 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 29 Jan 2025 17:03:02 +0700 Subject: [PATCH 15/40] use bxdf traits in test, better chi2 vis --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 117 +++++++++++++++++++--- 66_HLSLBxDFTests/main.cpp | 59 ++++++----- 2 files changed, 134 insertions(+), 42 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 9e6d409bd..f7053de0e 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -9,6 +9,7 @@ #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" #include "nbl/builtin/hlsl/bxdf/transmission.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" #ifndef __HLSL_VERSION #include @@ -193,6 +194,9 @@ enum ErrorType : uint32_t BET_JACOBIAN, BET_PDF_EVAL_DIFF, BET_RECIPROCITY, + + BET_NOBREAK, // not an error code, ones after this don't break + BET_INVALID, BET_PRINT_MSG }; @@ -206,7 +210,7 @@ struct TestBase anisointer = aniso_interaction::create(isointer, rc.T, rc.B); } - virtual void compute() {} + virtual ErrorType compute() { return BET_NONE; } SBxDFTestResources rc; @@ -428,7 +432,7 @@ struct TestJacobian : TestBxDF using base_t = TestBxDFBase; using this_t = TestJacobian; - virtual void compute() override + virtual ErrorType compute() override { aniso_cache cache, dummy; iso_cache isocache; @@ -480,6 +484,18 @@ struct TestJacobian : TestBxDF } } + // TODO: add checks with need clamp trait + if (bxdf_traits::type == BT_BRDF) + { + if (s.NdotL <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + else if (bxdf_traits::type == BT_BSDF) + { + if (abs(s.NdotL) <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + if NBL_CONSTEXPR_FUNC (is_basic_brdf_v || is_basic_bsdf_v) { pdf = base_t::bxdf.quotient_and_pdf(params); @@ -498,11 +514,26 @@ struct TestJacobian : TestBxDF bsdf = float32_t3(base_t::bxdf.eval(params)); } } + + return BET_NONE; } ErrorType test() { - compute(); + if (bxdf_traits::type == BT_BRDF) + { + if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + else if (bxdf_traits::type == BT_BSDF) + { + if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + + ErrorType res = compute(); + if (res != BET_NONE) + return res; if (checkZero(pdf.pdf, 1e-5)) // something generated cannot have 0 probability of getting generated return BET_PDF_ZERO; @@ -557,7 +588,7 @@ struct TestReciprocity : TestBxDF using base_t = TestBxDFBase; using this_t = TestReciprocity; - virtual void compute() override + virtual ErrorType compute() override { aniso_cache cache, rec_cache; iso_cache isocache, rec_isocache; @@ -597,6 +628,18 @@ struct TestReciprocity : TestBxDF } } + // TODO: add checks with need clamp trait + if (bxdf_traits::type == BT_BRDF) + { + if (s.NdotL <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + else if (bxdf_traits::type == BT_BSDF) + { + if (abs(s.NdotL) <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); ray_dir_info_t rec_V = s.L; ray_dir_info_t rec_localV = ray_dir_info_t::transform(toTangentSpace, rec_V); @@ -654,11 +697,26 @@ struct TestReciprocity : TestBxDF rec_bsdf = float32_t3(base_t::bxdf.eval(rec_params)); } } + + return BET_NONE; } ErrorType test() { - compute(); + if (bxdf_traits::type == BT_BRDF) + { + if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + else if (bxdf_traits::type == BT_BSDF) + { + if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + + ErrorType res = compute(); + if (res != BET_NONE) + return res; if (checkZero(bsdf, 1e-5)) return BET_NONE; // produces an "impossible" sample @@ -722,7 +780,7 @@ struct TestBucket : TestBxDF return a - diff + b; } - virtual void compute() override + virtual ErrorType compute() override { clearBuckets(); @@ -813,11 +871,25 @@ struct TestBucket : TestBxDF } } #endif + return BET_NONE; } ErrorType test() { - compute(); + if (bxdf_traits::type == BT_BRDF) + { + if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + else if (bxdf_traits::type == BT_BSDF) + { + if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) + return BET_INVALID; + } + + ErrorType res = compute(); + if (res != BET_NONE) + return res; return (base_t::errMsg.length() == 0) ? BET_NONE : BET_PRINT_MSG; } @@ -1025,22 +1097,23 @@ struct TestChi2 : TestBxDF void writeToEXR() { - std::string filename = std::format("chi2test_{}.exr", base_t::name); + std::string filename = std::format("chi2test_{}_{}.exr", base_t::rc.state, base_t::name); int totalWidth = phiSplits; int totalHeight = 2 * thetaSplits + 1; + float maxFreq = max(maxCountFreq, maxIntFreq); Array2D pixels(totalWidth, totalHeight); for (int y = 0; y < thetaSplits; y++) for (int x = 0; x < phiSplits; x++) - pixels[y][x] = mapColor(countFreq[y * phiSplits + x], -512.f, 511.f); // TODO: shouldn't map to negative numbers + pixels[y][x] = mapColor(countFreq[y * phiSplits + x], 0.f, maxFreq); // for (int x = 0; x < phiSplits; x++) // pixels[thetaSplits][x] = Rgba(1, 1, 1); for (int y = 0; y < thetaSplits; y++) for (int x = 0; x < phiSplits; x++) - pixels[thetaSplits + y][x] = mapColor(integrateFreq[y * phiSplits + x], -512.f, 511.f); + pixels[thetaSplits + y][x] = mapColor(integrateFreq[y * phiSplits + x], 0.f, maxFreq); Header header(totalWidth, totalHeight); RgbaOutputFile file(filename.c_str(), header, WRITE_RGBA); @@ -1048,7 +1121,7 @@ struct TestChi2 : TestBxDF file.writePixels(totalHeight); } - virtual void compute() override + virtual ErrorType compute() override { clearBuckets(); @@ -1090,6 +1163,9 @@ struct TestChi2 : TestBxDF uint32_t freqidx = thetaBin * phiSplits + phiBin; countFreq[freqidx] += 1; + + if (write_frequencies && maxCountFreq < countFreq[freqidx]) + maxCountFreq = countFreq[freqidx]; } thetaFactor = 1.f / thetaFactor; @@ -1100,6 +1176,7 @@ struct TestChi2 : TestBxDF { for (int j = 0; j < phiSplits; j++) { + uint32_t lastidx = intidx; integrateFreq[intidx++] = numSamples * adaptiveSimpson2D([&](float theta, float phi) -> float { float cosTheta = std::cos(theta), sinTheta = std::sin(theta); @@ -1165,13 +1242,27 @@ struct TestChi2 : TestBxDF return pdf.pdf * sinTheta; }, float32_t2(i * thetaFactor, j * phiFactor), float32_t2((i + 1) * thetaFactor, (j + 1) * phiFactor)); + + if (write_frequencies && maxIntFreq < integrateFreq[lastidx]) + maxIntFreq = integrateFreq[lastidx]; } } + + return BET_NONE; } ErrorType test() { - compute(); + if (bxdf_traits::type == BT_BRDF) + if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) + return BET_INVALID; + else if (bxdf_traits::type == BT_BSDF) + if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) + return BET_INVALID; + + ErrorType res = compute(); + if (res != BET_NONE) + return res; if (write_frequencies) writeToEXR(); @@ -1278,6 +1369,8 @@ struct TestChi2 : TestBxDF uint32_t numTests = 5; bool write_frequencies = true; + float maxCountFreq; + float maxIntFreq; std::vector countFreq; std::vector integrateFreq; diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 0b23bb7a4..5f97710c8 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -16,33 +16,36 @@ struct PrintFailureCallback : FailureCallback { switch (error) { + case BET_INVALID: + fprintf(stderr, "[INFO] seed %u: %s skipping test due to invalid NdotV/NdotL config\n", failedFor.rc.state, failedFor.name.c_str()); + break; case BET_NEGATIVE_VAL: - fprintf(stderr, "seed %u: %s pdf/quotient/eval < 0\n", failedFor.rc.state, failedFor.name.c_str()); + fprintf(stderr, "[ERROR] seed %u: %s pdf/quotient/eval < 0\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_PDF_ZERO: - fprintf(stderr, "seed %u: %s pdf = 0\n", failedFor.rc.state, failedFor.name.c_str()); + fprintf(stderr, "[ERROR] seed %u: %s pdf = 0\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_QUOTIENT_INF: - fprintf(stderr, "seed %u: %s quotient -> inf\n", failedFor.rc.state, failedFor.name.c_str()); + fprintf(stderr, "[ERROR] seed %u: %s quotient -> inf\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_JACOBIAN: - fprintf(stderr, "seed %u: %s failed the jacobian * pdf test\n", failedFor.rc.state, failedFor.name.c_str()); + fprintf(stderr, "[ERROR] seed %u: %s failed the jacobian * pdf test\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_PDF_EVAL_DIFF: - fprintf(stderr, "seed %u: %s quotient * pdf != eval\n", failedFor.rc.state, failedFor.name.c_str()); + fprintf(stderr, "[ERROR] seed %u: %s quotient * pdf != eval\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_RECIPROCITY: - fprintf(stderr, "seed %u: %s failed the reciprocity test\n", failedFor.rc.state, failedFor.name.c_str()); + fprintf(stderr, "[ERROR] seed %u: %s failed the reciprocity test\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_PRINT_MSG: - fprintf(stderr, "seed %u: %s error message\n%s\n", failedFor.rc.state, failedFor.name.c_str(), failedFor.errMsg.c_str()); + fprintf(stderr, "[ERROR] seed %u: %s error message\n%s\n", failedFor.rc.state, failedFor.name.c_str(), failedFor.errMsg.c_str()); break; default: - fprintf(stderr, "seed %u: %s unknown error\n", failedFor.rc.state, failedFor.name.c_str()); + fprintf(stderr, "[ERROR] seed %u: %s unknown error\n", failedFor.rc.state, failedFor.name.c_str()); } // TODO: #ifdef NBL_ENABLE_DEBUGBREAK - for (volatile bool repeat = true; IsDebuggerPresent() && repeat && (error != BET_PRINT_MSG); ) + for (volatile bool repeat = true; IsDebuggerPresent() && repeat && error < BET_NOBREAK; ) { repeat = false; __debugbreak(); @@ -51,7 +54,7 @@ struct PrintFailureCallback : FailureCallback } }; -#define FOR_EACH_BEGIN(r) std::for_each(std::execution::seq, r.begin(), r.end(), [&](uint32_t i) { +#define FOR_EACH_BEGIN(r) std::for_each(std::execution::par_unseq, r.begin(), r.end(), [&](uint32_t i) { #define FOR_EACH_END }); int main(int argc, char** argv) @@ -117,29 +120,25 @@ int main(int argc, char** argv) TestBucket, false>::run(i, cb); TestBucket, true>::run(i, cb); FOR_EACH_END - - //TestChi2>::run(5u, cb); - //TestChi2, false>::run(1u, cb); - TestChi2, true>::run(10u, cb); // chi2 test for sampling and pdf - //FOR_EACH_BEGIN(r5) - //TestChi2>::run(i, cb); - //TestChi2>::run(i, cb); - //TestChi2, false>::run(i, cb); - //TestChi2, true>::run(i, cb); - //TestChi2, false>::run(i, cb); - //TestChi2, true>::run(i, cb); - - //TestChi2>::run(i, cb); - ////TestChi2>::run(i, cb); - ////TestChi2>::run(i, cb); - //TestChi2, false>::run(i, cb); - //TestChi2, true>::run(i, cb); - //TestChi2, false>::run(i, cb); - //TestChi2, true>::run(i, cb); - //FOR_EACH_END + FOR_EACH_BEGIN(r5) + TestChi2>::run(i, cb); + TestChi2>::run(i, cb); + TestChi2, false>::run(i, cb); + TestChi2, true>::run(i, cb); + TestChi2, false>::run(i, cb); + TestChi2, true>::run(i, cb); + + TestChi2>::run(i, cb); + //TestChi2>::run(i, cb); + //TestChi2>::run(i, cb); + TestChi2, false>::run(i, cb); + TestChi2, true>::run(i, cb); + TestChi2, false>::run(i, cb); + TestChi2, true>::run(i, cb); + FOR_EACH_END return 0; } \ No newline at end of file From df07bfddcb7b8028d40d3adf2228585ea0707a25 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 30 Jan 2025 13:34:13 +0700 Subject: [PATCH 16/40] test config with json --- 66_HLSLBxDFTests/app_resources/config.json | 20 +++ 66_HLSLBxDFTests/app_resources/tests.hlsl | 61 ++++---- 66_HLSLBxDFTests/main.cpp | 157 ++++++++++++--------- 3 files changed, 149 insertions(+), 89 deletions(-) create mode 100644 66_HLSLBxDFTests/app_resources/config.json diff --git a/66_HLSLBxDFTests/app_resources/config.json b/66_HLSLBxDFTests/app_resources/config.json new file mode 100644 index 000000000..a329006e5 --- /dev/null +++ b/66_HLSLBxDFTests/app_resources/config.json @@ -0,0 +1,20 @@ +{ + "logInfo": false, + "TestJacobian": { + "runs": 10 + }, + "TestReciprocity": { + "runs": 10 + }, + "TestBucket": { + "runs": 10, + "samples": 500 + }, + "TestChi2": { + "runs": 5, + "samples": 1000000, + "thetaSplits": 80, + "phiSplits": 160, + "writeFrequencies": false + } +} diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index f7053de0e..582eddb47 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -21,24 +21,20 @@ #include #include "ImfRgbaFile.h" -#include "ImfOutputFile.h" -#include "ImfChannelList.h" -#include "ImfChannelListAttribute.h" -#include "ImfStringAttribute.h" -#include "ImfMatrixAttribute.h" #include "ImfArray.h" - -#include "ImfFrameBuffer.h" #include "ImfHeader.h" #include "ImfNamespace.h" #include +#include "nlohmann/json.hpp" + namespace IMF = Imf; namespace IMATH = Imath; using namespace IMF; using namespace IMATH; +using json = nlohmann::json; #endif namespace nbl @@ -185,6 +181,16 @@ struct SBxDFTestResources float32_t3 luma_coeff; }; +struct STestInitParams +{ + bool logInfo; + uint32_t state; + uint32_t samples; + uint32_t thetaSplits; + uint32_t phiSplits; + bool writeFrequencies; +} + enum ErrorType : uint32_t { BET_NONE = 0, @@ -225,7 +231,7 @@ struct TestBase struct FailureCallback { - virtual void __call(ErrorType error, NBL_REF_ARG(TestBase) failedFor) {} + virtual void __call(ErrorType error, NBL_REF_ARG(TestBase) failedFor, bool logInfo) {} }; template @@ -560,13 +566,13 @@ struct TestJacobian : TestBxDF return BET_NONE; } - static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) + static void run(NBL_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - uint32_t2 state = pcg32x2(seed); + uint32_t2 state = pcg32x2(initparams.state); this_t t; t.init(state); - t.rc.state = seed; + t.rc.state = initparams.state; if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) t.template initBxDF(t.rc); else @@ -574,7 +580,7 @@ struct TestJacobian : TestBxDF ErrorType e = t.test(); if (e != BET_NONE) - cb.__call(e, t); + cb.__call(e, t, initparams.logInfo); } sample_t s, sx, sy; @@ -733,13 +739,13 @@ struct TestReciprocity : TestBxDF return BET_NONE; } - static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) + static void run(NBL_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - uint32_t2 state = pcg32x2(seed); + uint32_t2 state = pcg32x2(initparams.state); this_t t; t.init(state); - t.rc.state = seed; + t.rc.state = initparams.state; if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) t.template initBxDF(t.rc); else @@ -747,7 +753,7 @@ struct TestReciprocity : TestBxDF ErrorType e = t.test(); if (e != BET_NONE) - cb.__call(e, t); + cb.__call(e, t, initparams.logInfo); } sample_t s, rec_s; @@ -792,7 +798,6 @@ struct TestBucket : TestBxDF quotient_pdf_t pdf; float32_t3 bsdf; - NBL_CONSTEXPR uint32_t samples = 500; for (uint32_t i = 0; i < samples; i++) { float32_t3 u = float32_t3(rngUniformDist(base_t::rc.rng), 0.0); @@ -894,13 +899,14 @@ struct TestBucket : TestBxDF return (base_t::errMsg.length() == 0) ? BET_NONE : BET_PRINT_MSG; } - static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) + static void run(NBL_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - uint32_t2 state = pcg32x2(seed); + uint32_t2 state = pcg32x2(initparams.state); this_t t; t.init(state); - t.rc.state = seed; + t.rc.state = initparams.state; + t.samples = initparams.samples; if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) t.template initBxDF(t.rc); else @@ -908,11 +914,12 @@ struct TestBucket : TestBxDF ErrorType e = t.test(); if (e != BET_NONE) - cb.__call(e, t); + cb.__call(e, t, initparams.logInfo); } bool selective = true; // print only buckets with count > 0 float stride = 0.2f; + uint32_t samples = 500; std::unordered_map> buckets; }; @@ -1338,13 +1345,17 @@ struct TestChi2 : TestBxDF return BET_NONE; } - static void run(uint32_t seed, NBL_REF_ARG(FailureCallback) cb) + static void run(NBL_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - uint32_t2 state = pcg32x2(seed); + uint32_t2 state = pcg32x2(initparams.state); this_t t; t.init(state); - t.rc.state = seed; + t.rc.state = initparams.state; + t.samples = initparams.samples; + t.thetaSplits = initparams.thetaSplits; + t.phiSplits = initparams.phiSplits; + t.write_frequencies = initparams.writeFrequencies; if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) t.template initBxDF(t.rc); else @@ -1352,7 +1363,7 @@ struct TestChi2 : TestBxDF ErrorType e = t.test(); if (e != BET_NONE) - cb.__call(e, t); + cb.__call(e, t, initparams.logInfo); } struct Cell { diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 5f97710c8..922eba6f1 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -12,12 +12,13 @@ using namespace nbl::hlsl; struct PrintFailureCallback : FailureCallback { - void __call(ErrorType error, NBL_REF_ARG(TestBase) failedFor) override + void __call(ErrorType error, NBL_REF_ARG(TestBase) failedFor, bool logInfo) override { switch (error) { case BET_INVALID: - fprintf(stderr, "[INFO] seed %u: %s skipping test due to invalid NdotV/NdotL config\n", failedFor.rc.state, failedFor.name.c_str()); + if (logInfo) + fprintf(stderr, "[INFO] seed %u: %s skipping test due to invalid NdotV/NdotL config\n", failedFor.rc.state, failedFor.name.c_str()); break; case BET_NEGATIVE_VAL: fprintf(stderr, "[ERROR] seed %u: %s pdf/quotient/eval < 0\n", failedFor.rc.state, failedFor.name.c_str()); @@ -61,83 +62,111 @@ int main(int argc, char** argv) { std::cout << std::fixed << std::setprecision(4); - auto r5 = std::ranges::views::iota(0u, 5u); - auto r10 = std::ranges::views::iota(0u, 10u); + std::ifstream f("app_resources/config.json"); + json testconfigs = json::parse(f); + + //auto r5 = std::ranges::views::iota(0u, 5u); + //auto r10 = std::ranges::views::iota(0u, 10u); PrintFailureCallback cb; // test jacobian * pdf - FOR_EACH_BEGIN(r10) - TestJacobian>::run(i, cb); - TestJacobian>::run(i, cb); - TestJacobian, false>::run(i, cb); - TestJacobian, true>::run(i, cb); - TestJacobian, false>::run(i, cb); - TestJacobian,true>::run(i, cb); - - TestJacobian>::run(i, cb); - //TestJacobian>::run(i, cb); - //TestJacobian>::run(i, cb); - TestJacobian, false>::run(i, cb); - TestJacobian, true>::run(i, cb); - TestJacobian, false>::run(i, cb); - TestJacobian,true>::run(i, cb); + uint32_t runs = testconfigs["TestJacobian"]["runs"]; + auto rJacobian = std::ranges::views::iota(0u, runs); + FOR_EACH_BEGIN(rJacobian) + STestInitParams initparams; + initparams.state = i; + + TestJacobian>::run(initparams, cb); + TestJacobian>::run(initparams, cb); + TestJacobian, false>::run(initparams, cb); + TestJacobian, true>::run(initparams, cb); + TestJacobian, false>::run(initparams, cb); + TestJacobian,true>::run(initparams, cb); + + TestJacobian>::run(initparams, cb); + //TestJacobian>::run(initparams, cb); + //TestJacobian>::run(initparams, cb); + TestJacobian, false>::run(initparams, cb); + TestJacobian, true>::run(initparams, cb); + TestJacobian, false>::run(initparams, cb); + TestJacobian,true>::run(initparams, cb); FOR_EACH_END // test reciprocity - FOR_EACH_BEGIN(r10) - TestReciprocity>::run(i, cb); - TestReciprocity>::run(i, cb); - TestReciprocity, false>::run(i, cb); - TestReciprocity, true>::run(i, cb); - TestReciprocity, false>::run(i, cb); - TestReciprocity, true>::run(i, cb); - - TestReciprocity>::run(i, cb); - //TestReciprocity>::run(i, cb); - //TestReciprocity>::run(i, cb); - TestReciprocity, false>::run(i, cb); - TestReciprocity, true>::run(i, cb); - TestReciprocity, false>::run(i, cb); - TestReciprocity, true>::run(i, cb); + runs = testconfigs["TestReciprocity"]["runs"]; + auto rReciprocity = std::ranges::views::iota(0u, runs); + FOR_EACH_BEGIN(rReciprocity) + STestInitParams initparams; + initparams.state = i; + + TestReciprocity>::run(initparams, cb); + TestReciprocity>::run(initparams, cb); + TestReciprocity, false>::run(initparams, cb); + TestReciprocity, true>::run(initparams, cb); + TestReciprocity, false>::run(initparams, cb); + TestReciprocity, true>::run(initparams, cb); + + TestReciprocity>::run(initparams, cb); + //TestReciprocity>::run(initparams, cb); + //TestReciprocity>::run(initparams, cb); + TestReciprocity, false>::run(initparams, cb); + TestReciprocity, true>::run(initparams, cb); + TestReciprocity, false>::run(initparams, cb); + TestReciprocity, true>::run(initparams, cb); FOR_EACH_END // test buckets of inf - FOR_EACH_BEGIN(r10) - TestBucket>::run(i, cb); - TestBucket>::run(i, cb); - TestBucket, false>::run(i, cb); - TestBucket, true>::run(i, cb); - TestBucket, false>::run(i, cb); - TestBucket, true>::run(i, cb); - - TestBucket>::run(i, cb); - //TestBucket>::run(i, cb); - //TestBucket>::run(i, cb); - TestBucket, false>::run(i, cb); - TestBucket, true>::run(i, cb); - TestBucket, false>::run(i, cb); - TestBucket, true>::run(i, cb); + runs = testconfigs["TestBucket"]["runs"]; + auto rBucket = std::ranges::views::iota(0u, runs); + FOR_EACH_BEGIN(rBucket) + STestInitParams initparams; + initparams.state = i; + initparams.samples = testconfigs["TestBucket"]["samples"]; + + TestBucket>::run(initparams, cb); + TestBucket>::run(initparams, cb); + TestBucket, false>::run(initparams, cb); + TestBucket, true>::run(initparams, cb); + TestBucket, false>::run(initparams, cb); + TestBucket, true>::run(initparams, cb); + + TestBucket>::run(initparams, cb); + //TestBucket>::run(initparams, cb); + //TestBucket>::run(initparams, cb); + TestBucket, false>::run(initparams, cb); + TestBucket, true>::run(initparams, cb); + TestBucket, false>::run(initparams, cb); + TestBucket, true>::run(initparams, cb); FOR_EACH_END // chi2 test for sampling and pdf - FOR_EACH_BEGIN(r5) - TestChi2>::run(i, cb); - TestChi2>::run(i, cb); - TestChi2, false>::run(i, cb); - TestChi2, true>::run(i, cb); - TestChi2, false>::run(i, cb); - TestChi2, true>::run(i, cb); - - TestChi2>::run(i, cb); - //TestChi2>::run(i, cb); - //TestChi2>::run(i, cb); - TestChi2, false>::run(i, cb); - TestChi2, true>::run(i, cb); - TestChi2, false>::run(i, cb); - TestChi2, true>::run(i, cb); + runs = testconfigs["TestChi2"]["runs"]; + auto rChi2 = std::ranges::views::iota(0u, runs); + FOR_EACH_BEGIN(rChi2) + STestInitParams initparams; + initparams.state = i; + initparams.samples = testconfigs["TestChi2"]["samples"]; + initparams.thetaSplits = testconfigs["TestChi2"]["thetaSplits"]; + initparams.phiSplits = testconfigs["TestChi2"]["phiSplits"]; + initparams.writeFrequencies = testconfigs["TestChi2"]["writeFrequencies"]; + + TestChi2>::run(initparams, cb); + TestChi2>::run(initparams, cb); + TestChi2, false>::run(initparams, cb); + TestChi2, true>::run(initparams, cb); + TestChi2, false>::run(initparams, cb); + TestChi2, true>::run(initparams, cb); + + TestChi2>::run(initparams, cb); + //TestChi2>::run(initparams, cb); + //TestChi2>::run(initparams, cb); + TestChi2, false>::run(initparams, cb); + TestChi2, true>::run(initparams, cb); + TestChi2, false>::run(initparams, cb); + TestChi2, true>::run(initparams, cb); FOR_EACH_END return 0; From da1a4ade14fa02a9b8ad9ab850473a3b1b9db287 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 30 Jan 2025 14:50:03 +0700 Subject: [PATCH 17/40] fixed json config bugs --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 18 ++++++------- 66_HLSLBxDFTests/main.cpp | 31 ++++++++++++++++------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 582eddb47..1fb419708 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -189,7 +189,7 @@ struct STestInitParams uint32_t thetaSplits; uint32_t phiSplits; bool writeFrequencies; -} +}; enum ErrorType : uint32_t { @@ -566,7 +566,7 @@ struct TestJacobian : TestBxDF return BET_NONE; } - static void run(NBL_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) + static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { uint32_t2 state = pcg32x2(initparams.state); @@ -739,7 +739,7 @@ struct TestReciprocity : TestBxDF return BET_NONE; } - static void run(NBL_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) + static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { uint32_t2 state = pcg32x2(initparams.state); @@ -798,7 +798,7 @@ struct TestBucket : TestBxDF quotient_pdf_t pdf; float32_t3 bsdf; - for (uint32_t i = 0; i < samples; i++) + for (uint32_t i = 0; i < numSamples; i++) { float32_t3 u = float32_t3(rngUniformDist(base_t::rc.rng), 0.0); @@ -899,14 +899,14 @@ struct TestBucket : TestBxDF return (base_t::errMsg.length() == 0) ? BET_NONE : BET_PRINT_MSG; } - static void run(NBL_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) + static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { uint32_t2 state = pcg32x2(initparams.state); this_t t; t.init(state); t.rc.state = initparams.state; - t.samples = initparams.samples; + t.numSamples = initparams.samples; if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v || is_microfacet_bsdf_v) t.template initBxDF(t.rc); else @@ -919,7 +919,7 @@ struct TestBucket : TestBxDF bool selective = true; // print only buckets with count > 0 float stride = 0.2f; - uint32_t samples = 500; + uint32_t numSamples = 500; std::unordered_map> buckets; }; @@ -1345,14 +1345,14 @@ struct TestChi2 : TestBxDF return BET_NONE; } - static void run(NBL_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) + static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { uint32_t2 state = pcg32x2(initparams.state); this_t t; t.init(state); t.rc.state = initparams.state; - t.samples = initparams.samples; + t.numSamples = initparams.samples; t.thetaSplits = initparams.thetaSplits; t.phiSplits = initparams.phiSplits; t.write_frequencies = initparams.writeFrequencies; diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 922eba6f1..4fa36c082 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -62,18 +62,31 @@ int main(int argc, char** argv) { std::cout << std::fixed << std::setprecision(4); - std::ifstream f("app_resources/config.json"); - json testconfigs = json::parse(f); + std::ifstream f("../app_resources/config.json"); + if (f.fail()) + { + fprintf(stderr, "[ERROR] could not open config file\n"); + return -1; + } + json testconfigs; + try + { + testconfigs = json::parse(f); + } + catch (json::parse_error& ex) + { + fprintf(stderr, "[ERROR] parse_error.%d failed to parse config file at byte %u: %s\n", ex.id, ex.byte, ex.what()); + return -1; + } - //auto r5 = std::ranges::views::iota(0u, 5u); - //auto r10 = std::ranges::views::iota(0u, 10u); + const bool logInfo = testconfigs["logInfo"]; PrintFailureCallback cb; // test jacobian * pdf uint32_t runs = testconfigs["TestJacobian"]["runs"]; auto rJacobian = std::ranges::views::iota(0u, runs); FOR_EACH_BEGIN(rJacobian) - STestInitParams initparams; + STestInitParams initparams{ .logInfo = logInfo }; initparams.state = i; TestJacobian>::run(initparams, cb); @@ -97,7 +110,7 @@ int main(int argc, char** argv) runs = testconfigs["TestReciprocity"]["runs"]; auto rReciprocity = std::ranges::views::iota(0u, runs); FOR_EACH_BEGIN(rReciprocity) - STestInitParams initparams; + STestInitParams initparams{ .logInfo = logInfo }; initparams.state = i; TestReciprocity>::run(initparams, cb); @@ -121,7 +134,7 @@ int main(int argc, char** argv) runs = testconfigs["TestBucket"]["runs"]; auto rBucket = std::ranges::views::iota(0u, runs); FOR_EACH_BEGIN(rBucket) - STestInitParams initparams; + STestInitParams initparams{ .logInfo = logInfo }; initparams.state = i; initparams.samples = testconfigs["TestBucket"]["samples"]; @@ -146,7 +159,7 @@ int main(int argc, char** argv) runs = testconfigs["TestChi2"]["runs"]; auto rChi2 = std::ranges::views::iota(0u, runs); FOR_EACH_BEGIN(rChi2) - STestInitParams initparams; + STestInitParams initparams{ .logInfo = logInfo }; initparams.state = i; initparams.samples = testconfigs["TestChi2"]["samples"]; initparams.thetaSplits = testconfigs["TestChi2"]["thetaSplits"]; From d7f7a87fa08a56a16cd1bcc7d4d9fd48fc8c278c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 31 Jan 2025 13:28:16 +0700 Subject: [PATCH 18/40] smooth dielectric tests --- 66_HLSLBxDFTests/main.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 4fa36c082..41afde041 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -82,6 +82,7 @@ int main(int argc, char** argv) const bool logInfo = testconfigs["logInfo"]; PrintFailureCallback cb; + // test jacobian * pdf uint32_t runs = testconfigs["TestJacobian"]["runs"]; auto rJacobian = std::ranges::views::iota(0u, runs); @@ -97,8 +98,8 @@ int main(int argc, char** argv) TestJacobian,true>::run(initparams, cb); TestJacobian>::run(initparams, cb); - //TestJacobian>::run(initparams, cb); - //TestJacobian>::run(initparams, cb); + TestJacobian>::run(initparams, cb); + TestJacobian>::run(initparams, cb); TestJacobian, false>::run(initparams, cb); TestJacobian, true>::run(initparams, cb); TestJacobian, false>::run(initparams, cb); @@ -121,8 +122,8 @@ int main(int argc, char** argv) TestReciprocity, true>::run(initparams, cb); TestReciprocity>::run(initparams, cb); - //TestReciprocity>::run(initparams, cb); - //TestReciprocity>::run(initparams, cb); + TestReciprocity>::run(initparams, cb); + TestReciprocity>::run(initparams, cb); TestReciprocity, false>::run(initparams, cb); TestReciprocity, true>::run(initparams, cb); TestReciprocity, false>::run(initparams, cb); @@ -131,6 +132,7 @@ int main(int argc, char** argv) // test buckets of inf + // NOTE: can safely ignore any errors for smooth dielectric BxDFs because pdf SHOULD be inf runs = testconfigs["TestBucket"]["runs"]; auto rBucket = std::ranges::views::iota(0u, runs); FOR_EACH_BEGIN(rBucket) @@ -146,8 +148,8 @@ int main(int argc, char** argv) TestBucket, true>::run(initparams, cb); TestBucket>::run(initparams, cb); - //TestBucket>::run(initparams, cb); - //TestBucket>::run(initparams, cb); + TestBucket>::run(initparams, cb); + TestBucket>::run(initparams, cb); TestBucket, false>::run(initparams, cb); TestBucket, true>::run(initparams, cb); TestBucket, false>::run(initparams, cb); @@ -174,8 +176,8 @@ int main(int argc, char** argv) TestChi2, true>::run(initparams, cb); TestChi2>::run(initparams, cb); - //TestChi2>::run(initparams, cb); - //TestChi2>::run(initparams, cb); + TestChi2>::run(initparams, cb); + TestChi2>::run(initparams, cb); TestChi2, false>::run(initparams, cb); TestChi2, true>::run(initparams, cb); TestChi2, false>::run(initparams, cb); From 111c11b51d6076d67654a67eb53774f1c27dc55d Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 12 Feb 2025 13:38:26 +0700 Subject: [PATCH 19/40] fix pcg usage --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 1fb419708..725d1606f 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -568,7 +568,8 @@ struct TestJacobian : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - uint32_t2 state = pcg32x2(initparams.state); + PCG32x2 pcg = PCG32x2::construct(initparams.state); + uint32_t2 state = pcg(); this_t t; t.init(state); @@ -741,7 +742,8 @@ struct TestReciprocity : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - uint32_t2 state = pcg32x2(initparams.state); + PCG32x2 pcg = PCG32x2::construct(initparams.state); + uint32_t2 state = pcg(); this_t t; t.init(state); @@ -901,7 +903,8 @@ struct TestBucket : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - uint32_t2 state = pcg32x2(initparams.state); + PCG32x2 pcg = PCG32x2::construct(initparams.state); + uint32_t2 state = pcg(); this_t t; t.init(state); @@ -1347,7 +1350,8 @@ struct TestChi2 : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - uint32_t2 state = pcg32x2(initparams.state); + PCG32x2 pcg = PCG32x2::construct(initparams.state); + uint32_t2 state = pcg(); this_t t; t.init(state); From f3144f14c107d86667a23f64b2686a71b20ee473 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 27 Feb 2025 17:38:31 +0700 Subject: [PATCH 20/40] refactor according to changes with bxdf --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 39 ++++++++++++----------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 725d1606f..562f6ea65 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -146,15 +146,18 @@ struct SBxDFTestResources retval.V.direction = nbl::hlsl::normalize(uniform_sphere_generate(rngUniformDist(retval.rng))); retval.N = nbl::hlsl::normalize(uniform_sphere_generate(rngUniformDist(retval.rng))); - float32_t2x3 tb = math::frisvad(retval.N); + float32_t3 tangent, bitangent; + math::frisvad(retval.N, tangent, bitangent); + tangent = nbl::hlsl::normalize(tangent); + bitangent = nbl::hlsl::normalize(bitangent); #ifndef __HLSL_VERSION const float angle = 2 * numbers::pi * rngUniformDist(retval.rng); glm::quat rot = glm::angleAxis(angle, retval.N); - retval.T = rot * tb[0]; - retval.B = rot * tb[1]; + retval.T = rot * tangent; + retval.B = rot * bitangent; #else - retval.T = tb[0]; - retval.B = tb[1]; + retval.T = tangent; + retval.B = bitangent; #endif retval.alpha.x = rngUniformDist(retval.rng); @@ -464,7 +467,7 @@ struct TestJacobian : TestBxDF params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); else { - isocache = (iso_cache)cache; + isocache = cache.iso_cache; params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); } } @@ -485,7 +488,7 @@ struct TestJacobian : TestBxDF params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); else { - isocache = (iso_cache)cache; + isocache = cache.iso_cache; params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } } @@ -613,7 +616,7 @@ struct TestReciprocity : TestBxDF params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); else { - isocache = (iso_cache)cache; + isocache = cache.iso_cache; params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); } } @@ -630,7 +633,7 @@ struct TestReciprocity : TestBxDF params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); else { - isocache = (iso_cache)cache; + isocache = cache.iso_cache; params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } } @@ -656,10 +659,10 @@ struct TestReciprocity : TestBxDF iso_interaction rec_isointer = iso_interaction::create(rec_V, base_t::rc.N); aniso_interaction rec_anisointer = aniso_interaction::create(rec_isointer, base_t::rc.T, base_t::rc.B); rec_cache = cache; - rec_cache.VdotH = cache.LdotH; - rec_cache.LdotH = cache.VdotH; + rec_cache.iso_cache.VdotH = cache.iso_cache.LdotH; + rec_cache.iso_cache.LdotH = cache.iso_cache.VdotH; - rec_isocache = (iso_cache)rec_cache; + rec_isocache = rec_cache.iso_cache; if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) rec_params = params_t::template create(rec_s, rec_isointer, bxdf::BCM_MAX); @@ -669,7 +672,7 @@ struct TestReciprocity : TestBxDF rec_params = params_t::template create(rec_s, rec_anisointer, rec_cache, bxdf::BCM_MAX); else { - rec_isocache = (iso_cache)rec_cache; + rec_isocache = rec_cache.iso_cache; rec_params = params_t::template create(rec_s, rec_isointer, rec_isocache, bxdf::BCM_MAX); } } @@ -681,7 +684,7 @@ struct TestReciprocity : TestBxDF rec_params = params_t::template create(rec_s, rec_anisointer, rec_cache, bxdf::BCM_ABS); else { - rec_isocache = (iso_cache)rec_cache; + rec_isocache = rec_cache.iso_cache; rec_params = params_t::template create(rec_s, rec_isointer, rec_isocache, bxdf::BCM_ABS); } } @@ -817,7 +820,7 @@ struct TestBucket : TestBxDF params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); else { - isocache = (iso_cache)cache; + isocache = cache.iso_cache; params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); } } @@ -834,7 +837,7 @@ struct TestBucket : TestBxDF params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); else { - isocache = (iso_cache)cache; + isocache = cache.iso_cache; params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } } @@ -1212,7 +1215,7 @@ struct TestChi2 : TestBxDF params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); else { - iso_cache isocache = (iso_cache)cache; + iso_cache isocache = cache.iso_cache; params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); } } @@ -1228,7 +1231,7 @@ struct TestChi2 : TestBxDF params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); else { - iso_cache isocache = (iso_cache)cache; + iso_cache isocache = cache.iso_cache; params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } } From 5a9e8b51b3e3549e80879a79f1b6d67ae2aa1fb8 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 28 Feb 2025 14:01:38 +0700 Subject: [PATCH 21/40] added a compile shader test --- .../app_resources/test_compile.comp.hlsl | 49 ++++++++++++++ 66_HLSLBxDFTests/main.cpp | 64 ++++++++++++++++++- 2 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl new file mode 100644 index 000000000..cb8128daf --- /dev/null +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -0,0 +1,49 @@ +#include "nbl/builtin/hlsl/cpp_compat.hlsl" + +#include "nbl/builtin/hlsl/bxdf/common.hlsl" +#include "nbl/builtin/hlsl/bxdf/reflection.hlsl" +#include "nbl/builtin/hlsl/bxdf/transmission.hlsl" +#include "nbl/builtin/hlsl/bxdf/bxdf_traits.hlsl" + +[[vk::binding(0,0)]] RWStructuredBuffer buff; + +using namespace nbl::hlsl; + +using ray_dir_info_t = bxdf::ray_dir_info::SBasic; +using iso_interaction = bxdf::surface_interactions::SIsotropic; +using aniso_interaction = bxdf::surface_interactions::SAnisotropic; +using sample_t = bxdf::SLightSample; +using iso_cache = bxdf::SIsotropicMicrofacetCache; +using aniso_cache = bxdf::SAnisotropicMicrofacetCache; +using quotient_pdf_t = bxdf::quotient_and_pdf; +using spectral_t = vector; +using params_t = bxdf::SBxDFParams; + +[numthreads(WORKGROUP_SIZE,1,1)] +void main(uint32_t3 ID : SV_DispatchThreadID) +{ + bxdf::reflection::SLambertianBxDF lambertianBRDF; + bxdf::reflection::SOrenNayarBxDF orenNayarBRDF; + bxdf::reflection::SBeckmannBxDF beckmannBRDF; + bxdf::reflection::SGGXBxDF ggxBRDF; + + bxdf::transmission::SLambertianBxDF lambertianBSDF; + bxdf::transmission::SSmoothDielectricBxDF smoothDielectricBSDF; + bxdf::transmission::SSmoothDielectricBxDF thinSmoothDielectricBSDF; + bxdf::transmission::SBeckmannDielectricBxDF beckmannBSDF; + bxdf::transmission::SGGXDielectricBxDF ggxBSDF; + + + // do some nonsense calculations, but call all the relevant functions + const float3 V = nbl::hlsl::normalize(float3(1, 1, 1)); + const float3 N = float3(0, 1, 0); + float3 T, B; + math::frisvad(N, T, B); + const float3 u = float3(0.5, 0.5, 0); + + iso_interaction isointer = iso_interaction::create(V, N); + aniso_interaction anisointer = aniso_interaction::create(isointer, T, B); + + sample_t s = lambertianBRDF.generate(anisointer, u.xy); + buff[ID.x] = s.xyz; +} \ No newline at end of file diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 41afde041..14b881d14 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -5,7 +5,14 @@ #include #include - +#include "nbl/system/CColoredStdoutLoggerANSI.h" +#include "nbl/system/IApplicationFramework.h" + +using namespace nbl; +using namespace core; +using namespace system; +using namespace asset; +using namespace video; using namespace nbl::hlsl; #include "app_resources/tests.hlsl" @@ -79,6 +86,57 @@ int main(int argc, char** argv) return -1; } + // test compile with dxc + { + smart_refctd_ptr m_system = system::IApplicationFramework::createSystem(); + smart_refctd_ptr m_logger = core::make_smart_refctd_ptr(system::ILogger::DefaultLogMask()); + m_logger->log("Logger Created!", system::ILogger::ELL_INFO); + smart_refctd_ptr m_assetMgr = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); + + path CWD = system::path(argv[0]).parent_path().generic_string() + "/"; + path localInputCWD = CWD / "../"; + auto resourceArchive = +#ifdef NBL_EMBED_BUILTIN_RESOURCES + make_smart_refctd_ptr(smart_refctd_ptr(m_logger)); +#else + make_smart_refctd_ptr(localInputCWD/"app_resources", smart_refctd_ptr(m_logger), m_system.get()); +#endif + m_system->mount(std::move(resourceArchive), "app_resources"); + + constexpr uint32_t WorkgroupSize = 256; + const std::string WorkgroupSizeAsStr = std::to_string(WorkgroupSize); + const std::string filePath = "app_resources/test_compile.comp.hlsl"; + + IAssetLoader::SAssetLoadParams lparams = {}; + lparams.logger = m_logger.get(); + lparams.workingDirectory = ""; + auto bundle = m_assetMgr->getAsset(filePath, lparams); + if (bundle.getContents().empty() || bundle.getAssetType() != IAsset::ET_SHADER) + { + m_logger->log("Shader %s not found!", ILogger::ELL_ERROR, filePath); + exit(-1); + } + + const auto assets = bundle.getContents(); + assert(assets.size() == 1); + smart_refctd_ptr shaderSrc = IAsset::castDown(assets[0]); + + smart_refctd_ptr shader = shaderSrc; + auto compiler = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); + CHLSLCompiler::SOptions options = {}; + options.stage = asset::IShader::E_SHADER_STAGE::ESS_COMPUTE; + options.debugInfoFlags |= IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_LINE_BIT; + options.spirvOptimizer = nullptr; + // if you don't set the logger and source identifier you'll have no meaningful errors + options.preprocessorOptions.sourceIdentifier = shaderSrc->getFilepathHint(); + options.preprocessorOptions.logger = m_logger.get(); + options.preprocessorOptions.includeFinder = compiler->getDefaultIncludeFinder(); + const IShaderCompiler::SMacroDefinition WorkgroupSizeDefine = { "WORKGROUP_SIZE", WorkgroupSizeAsStr }; + options.preprocessorOptions.extraDefines = { &WorkgroupSizeDefine,&WorkgroupSizeDefine + 1 }; + if (!(shader = compiler->compileToSPIRV((const char*)shaderSrc->getContent()->getPointer(), options))) + fprintf(stderr, "[ERROR] compile shader test failed!\n"); + } + const bool logInfo = testconfigs["logInfo"]; PrintFailureCallback cb; @@ -148,8 +206,8 @@ int main(int argc, char** argv) TestBucket, true>::run(initparams, cb); TestBucket>::run(initparams, cb); - TestBucket>::run(initparams, cb); - TestBucket>::run(initparams, cb); + //TestBucket>::run(initparams, cb); + //TestBucket>::run(initparams, cb); TestBucket, false>::run(initparams, cb); TestBucket, true>::run(initparams, cb); TestBucket, false>::run(initparams, cb); From a1334527a4ac822a3220f557084672bb7c4ec86e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 28 Feb 2025 16:36:24 +0700 Subject: [PATCH 22/40] fix compile test --- .../app_resources/test_compile.comp.hlsl | 17 +++++++++-------- 66_HLSLBxDFTests/app_resources/tests.hlsl | 8 ++++---- 66_HLSLBxDFTests/main.cpp | 8 ++++---- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl index cb8128daf..7e5db86c1 100644 --- a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -24,18 +24,19 @@ void main(uint32_t3 ID : SV_DispatchThreadID) { bxdf::reflection::SLambertianBxDF lambertianBRDF; bxdf::reflection::SOrenNayarBxDF orenNayarBRDF; - bxdf::reflection::SBeckmannBxDF beckmannBRDF; - bxdf::reflection::SGGXBxDF ggxBRDF; + bxdf::reflection::SBeckmannBxDF beckmannBRDF; + bxdf::reflection::SGGXBxDF ggxBRDF; bxdf::transmission::SLambertianBxDF lambertianBSDF; - bxdf::transmission::SSmoothDielectricBxDF smoothDielectricBSDF; - bxdf::transmission::SSmoothDielectricBxDF thinSmoothDielectricBSDF; - bxdf::transmission::SBeckmannDielectricBxDF beckmannBSDF; - bxdf::transmission::SGGXDielectricBxDF ggxBSDF; + bxdf::transmission::SSmoothDielectricBxDF smoothDielectricBSDF; + bxdf::transmission::SSmoothDielectricBxDF thinSmoothDielectricBSDF; + bxdf::transmission::SBeckmannDielectricBxDF beckmannBSDF; + bxdf::transmission::SGGXDielectricBxDF ggxBSDF; // do some nonsense calculations, but call all the relevant functions - const float3 V = nbl::hlsl::normalize(float3(1, 1, 1)); + ray_dir_info_t V; + V.direction = nbl::hlsl::normalize(float3(1, 1, 1)); const float3 N = float3(0, 1, 0); float3 T, B; math::frisvad(N, T, B); @@ -45,5 +46,5 @@ void main(uint32_t3 ID : SV_DispatchThreadID) aniso_interaction anisointer = aniso_interaction::create(isointer, T, B); sample_t s = lambertianBRDF.generate(anisointer, u.xy); - buff[ID.x] = s.xyz; + buff[ID.x] = s.L.direction; } \ No newline at end of file diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 562f6ea65..331a45cb6 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -322,13 +322,13 @@ struct TestBxDF -struct TestBxDF> : TestBxDFBase> +struct TestBxDF> : TestBxDFBase> { - using base_t = TestBxDFBase>; + using base_t = TestBxDFBase>; void initBxDF(SBxDFTestResources _rc) { - base_t::bxdf = bxdf::transmission::SSmoothDielectricBxDF::create(rc.eta); + base_t::bxdf = bxdf::transmission::SSmoothDielectricBxDF::create(rc.eta); #ifndef __HLSL_VERSION base_t::name = "Smooth dielectric BSDF"; #endif @@ -415,7 +415,7 @@ struct is_microfacet_brdf : bool_constant< template struct is_basic_bsdf : bool_constant< is_same>::value || - is_same>::value || + is_same>::value || is_same>::value > {}; diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 14b881d14..d118c92f3 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -156,7 +156,7 @@ int main(int argc, char** argv) TestJacobian,true>::run(initparams, cb); TestJacobian>::run(initparams, cb); - TestJacobian>::run(initparams, cb); + TestJacobian>::run(initparams, cb); TestJacobian>::run(initparams, cb); TestJacobian, false>::run(initparams, cb); TestJacobian, true>::run(initparams, cb); @@ -180,7 +180,7 @@ int main(int argc, char** argv) TestReciprocity, true>::run(initparams, cb); TestReciprocity>::run(initparams, cb); - TestReciprocity>::run(initparams, cb); + TestReciprocity>::run(initparams, cb); TestReciprocity>::run(initparams, cb); TestReciprocity, false>::run(initparams, cb); TestReciprocity, true>::run(initparams, cb); @@ -206,7 +206,7 @@ int main(int argc, char** argv) TestBucket, true>::run(initparams, cb); TestBucket>::run(initparams, cb); - //TestBucket>::run(initparams, cb); + //TestBucket>::run(initparams, cb); //TestBucket>::run(initparams, cb); TestBucket, false>::run(initparams, cb); TestBucket, true>::run(initparams, cb); @@ -234,7 +234,7 @@ int main(int argc, char** argv) TestChi2, true>::run(initparams, cb); TestChi2>::run(initparams, cb); - TestChi2>::run(initparams, cb); + TestChi2>::run(initparams, cb); TestChi2>::run(initparams, cb); TestChi2, false>::run(initparams, cb); TestChi2, true>::run(initparams, cb); From 1bbc59aa190260efbdf938d377dca4939768f7d1 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 28 Feb 2025 16:57:06 +0700 Subject: [PATCH 23/40] expand compile test --- .../app_resources/test_compile.comp.hlsl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl index 7e5db86c1..acade699a 100644 --- a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -44,7 +44,20 @@ void main(uint32_t3 ID : SV_DispatchThreadID) iso_interaction isointer = iso_interaction::create(V, N); aniso_interaction anisointer = aniso_interaction::create(isointer, T, B); + aniso_cache cache; + float3 L; sample_t s = lambertianBRDF.generate(anisointer, u.xy); - buff[ID.x] = s.L.direction; + L += s.L.direction; + + sample_t s = orenNayarBRDF.generate(anisointer, u.xy); + L += s.L.direction; + + sample_t s = beckmannBRDF.generate(anisointer, u.xy, cache); + L += s.L.direction; + + sample_t s = ggxBRDF.generate(anisointer, u.xy, cache); + L += s.L.direction; + + buff[ID.x] = L; } \ No newline at end of file From 98bd4e4345c4fc882a536e5bad18bba062510caa Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 3 Mar 2025 11:11:47 +0700 Subject: [PATCH 24/40] fix typo bug --- 66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl index acade699a..dda494b4e 100644 --- a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -50,13 +50,13 @@ void main(uint32_t3 ID : SV_DispatchThreadID) sample_t s = lambertianBRDF.generate(anisointer, u.xy); L += s.L.direction; - sample_t s = orenNayarBRDF.generate(anisointer, u.xy); + s = orenNayarBRDF.generate(anisointer, u.xy); L += s.L.direction; - sample_t s = beckmannBRDF.generate(anisointer, u.xy, cache); + s = beckmannBRDF.generate(anisointer, u.xy, cache); L += s.L.direction; - sample_t s = ggxBRDF.generate(anisointer, u.xy, cache); + s = ggxBRDF.generate(anisointer, u.xy, cache); L += s.L.direction; buff[ID.x] = L; From 4a68b75a37a11f40944ac15bb0a1d5cc52a9072e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 3 Mar 2025 17:13:40 +0700 Subject: [PATCH 25/40] added test for arccos sum --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 6 +++--- 66_HLSLBxDFTests/main.cpp | 24 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 331a45cb6..1d40c1a46 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -97,19 +97,19 @@ T rngUniformDist(NBL_REF_ARG(nbl::hlsl::Xoroshiro64Star) rng) template bool checkEq(T a, T b, float32_t eps) { - return nbl::hlsl::all>(nbl::hlsl::max(a / b, b / a) <= (T)(1 + eps)); + return nbl::hlsl::all::Dimension> >(nbl::hlsl::max(a / b, b / a) <= (T)(1 + eps)); } template bool checkLt(T a, T b) { - return nbl::hlsl::all>(a < b); + return nbl::hlsl::all::Dimension> >(a < b); } template bool checkZero(T a, float32_t eps) { - return nbl::hlsl::all>(nbl::hlsl::abs(a) < (T)eps); + return nbl::hlsl::all::Dimension> >(nbl::hlsl::abs(a) < (T)eps); } template<> diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index d118c92f3..e207ffeaf 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -137,10 +137,10 @@ int main(int argc, char** argv) fprintf(stderr, "[ERROR] compile shader test failed!\n"); } + const bool logInfo = testconfigs["logInfo"]; PrintFailureCallback cb; - // test jacobian * pdf uint32_t runs = testconfigs["TestJacobian"]["runs"]; auto rJacobian = std::ranges::views::iota(0u, runs); @@ -242,5 +242,27 @@ int main(int argc, char** argv) TestChi2, true>::run(initparams, cb); FOR_EACH_END + // test arccos angle sums + { + Xoroshiro64Star rng = Xoroshiro64Star::construct(uint32_t2(4, 2)); + for (uint32_t i = 0; i < 10; i++) + { + const float a = rng() * numbers::pi; + const float b = rng() * numbers::pi; + const float c = rng() * numbers::pi; + const float d = rng() * numbers::pi; + + const float exAB = acos(a) + acos(b); + float res = math::getSumofArccosAB(a, b); + if (res != exAB) + fprintf(stderr, "[ERROR] math::getSumofArccosAB failed! expected %f, got %f\n", exAB, res); + + const float exABCD = exAB + acos(c) + acos(d); + res = math::getSumofArccosABCD(a, b, c, d); + if (res != exABCD) + fprintf(stderr, "[ERROR] math::getSumofArccosABCD failed! expected %f, got %f\n", exABCD, res); + } + } + return 0; } \ No newline at end of file From 631f7f1da020e1db77b0ef4a788eff2afd069439 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 5 Mar 2025 14:24:23 +0700 Subject: [PATCH 26/40] added more to shader compile test --- .../app_resources/test_compile.comp.hlsl | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl index dda494b4e..a2d6ba113 100644 --- a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -46,18 +46,48 @@ void main(uint32_t3 ID : SV_DispatchThreadID) aniso_interaction anisointer = aniso_interaction::create(isointer, T, B); aniso_cache cache; - float3 L; + float3 L = float3(0,0,0); + float3 q = float3(0,0,0); sample_t s = lambertianBRDF.generate(anisointer, u.xy); L += s.L.direction; s = orenNayarBRDF.generate(anisointer, u.xy); L += s.L.direction; - + + params_t params = params_t::template create(s, isointer, bxdf::BxDFClampMode::BCM_MAX); + quotient_pdf_t qp = orenNayarBRDF.quotient_and_pdf(params); + L -= qp.quotient; + s = beckmannBRDF.generate(anisointer, u.xy, cache); L += s.L.direction; - + + params = params_t::template create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_MAX); + qp = beckmannBRDF.quotient_and_pdf(params); + L -= qp.quotient; + s = ggxBRDF.generate(anisointer, u.xy, cache); L += s.L.direction; - + + params = params_t::template create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_MAX); + qp = ggxBRDF.quotient_and_pdf(params); + L -= qp.quotient; + + s = lambertianBSDF.generate(anisointer, u); + L += s.L.direction; + + s = thinSmoothDielectricBSDF.generate(anisointer, u); + L += s.L.direction; + + params = params_t::template create(s, isointer, bxdf::BxDFClampMode::BCM_ABS); + qp = thinSmoothDielectricBSDF.quotient_and_pdf(params); + L -= qp.quotient; + + s = ggxBSDF.generate(anisointer, u, cache); + L += s.L.direction; + + params = params_t::template create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_ABS); + qp = ggxBSDF.quotient_and_pdf(params); + L -= qp.quotient; + buff[ID.x] = L; } \ No newline at end of file From 222dc24dcfec42885c6cbad669543fe722cb76c7 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 7 Mar 2025 17:03:53 +0700 Subject: [PATCH 27/40] update infinity usage --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 1d40c1a46..755add08c 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -547,7 +547,7 @@ struct TestJacobian : TestBxDF if (checkZero(pdf.pdf, 1e-5)) // something generated cannot have 0 probability of getting generated return BET_PDF_ZERO; - if (!checkLt(pdf.quotient, (float32_t3)numeric_limits::infinity)) // importance sampler's job to prevent inf + if (!checkLt(pdf.quotient, bit_cast(numeric_limits::infinity))) // importance sampler's job to prevent inf return BET_QUOTIENT_INF; if (checkZero(bsdf, 1e-5) || checkZero(pdf.quotient, 1e-5)) @@ -867,7 +867,7 @@ struct TestBucket : TestBxDF const float32_t2 coords = cartesianToPolar(localL.direction); float32_t2 bucket = float32_t2(bin(coords.x * numbers::inv_pi), bin(coords.y * 0.5f * numbers::inv_pi)); - if (pdf.pdf == numeric_limits::infinity) + if (pdf.pdf == bit_cast(numeric_limits::infinity)) buckets[bucket] += 1; } From a490635dbd867a2ddec3afd3185a1cb9cbd729e4 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 11 Mar 2025 11:22:27 +0700 Subject: [PATCH 28/40] updated tests --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 8 ++++---- 66_HLSLBxDFTests/main.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 755add08c..1940f0a32 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -547,7 +547,7 @@ struct TestJacobian : TestBxDF if (checkZero(pdf.pdf, 1e-5)) // something generated cannot have 0 probability of getting generated return BET_PDF_ZERO; - if (!checkLt(pdf.quotient, bit_cast(numeric_limits::infinity))) // importance sampler's job to prevent inf + if (!checkLt(pdf.quotient, (float32_t3)bit_cast(numeric_limits::infinity))) // importance sampler's job to prevent inf return BET_QUOTIENT_INF; if (checkZero(bsdf, 1e-5) || checkZero(pdf.quotient, 1e-5)) @@ -1252,7 +1252,7 @@ struct TestChi2 : TestBxDF pdf = base_t::bxdf.quotient_and_pdf(params); } } - return pdf.pdf * sinTheta; + return pdf.pdf == bit_cast(numeric_limits::infinity) ? 0.0 : pdf.pdf * sinTheta; }, float32_t2(i * thetaFactor, j * phiFactor), float32_t2((i + 1) * thetaFactor, (j + 1) * phiFactor)); @@ -1267,10 +1267,10 @@ struct TestChi2 : TestBxDF ErrorType test() { if (bxdf_traits::type == BT_BRDF) - if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) + if (base_t::isointer.NdotV <= numeric_limits::min) return BET_INVALID; else if (bxdf_traits::type == BT_BSDF) - if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) + if (abs(base_t::isointer.NdotV) <= numeric_limits::min) return BET_INVALID; ErrorType res = compute(); diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index e207ffeaf..f613b6a29 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -52,13 +52,14 @@ struct PrintFailureCallback : FailureCallback fprintf(stderr, "[ERROR] seed %u: %s unknown error\n", failedFor.rc.state, failedFor.name.c_str()); } - // TODO: #ifdef NBL_ENABLE_DEBUGBREAK +#ifdef _NBL_DEBUG for (volatile bool repeat = true; IsDebuggerPresent() && repeat && error < BET_NOBREAK; ) { repeat = false; - __debugbreak(); + _NBL_DEBUG_BREAK_IF(true); failedFor.compute(); } +#endif } }; @@ -234,8 +235,8 @@ int main(int argc, char** argv) TestChi2, true>::run(initparams, cb); TestChi2>::run(initparams, cb); - TestChi2>::run(initparams, cb); - TestChi2>::run(initparams, cb); + //TestChi2>::run(initparams, cb); + //TestChi2>::run(initparams, cb); TestChi2, false>::run(initparams, cb); TestChi2, true>::run(initparams, cb); TestChi2, false>::run(initparams, cb); From 37326879c97a2df27c3ce21cebcaa2580501175c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 2 Apr 2025 17:11:07 +0700 Subject: [PATCH 29/40] refactor changes in bxdf, sampling --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 36 +++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 1940f0a32..5c0b64a9f 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -143,8 +143,8 @@ struct SBxDFTestResources retval.rng = nbl::hlsl::Xoroshiro64Star::construct(seed); retval.u = float32_t3(rngUniformDist(retval.rng), 0.0); - retval.V.direction = nbl::hlsl::normalize(uniform_sphere_generate(rngUniformDist(retval.rng))); - retval.N = nbl::hlsl::normalize(uniform_sphere_generate(rngUniformDist(retval.rng))); + retval.V.direction = nbl::hlsl::normalize(sampling::UniformSphere::generate(rngUniformDist(retval.rng))); + retval.N = nbl::hlsl::normalize(sampling::UniformSphere::generate(rngUniformDist(retval.rng))); float32_t3 tangent, bitangent; math::frisvad(retval.N, tangent, bitangent); @@ -494,12 +494,12 @@ struct TestJacobian : TestBxDF } // TODO: add checks with need clamp trait - if (bxdf_traits::type == BT_BRDF) + if (bxdf::traits::type == bxdf::BT_BRDF) { if (s.NdotL <= bit_cast(numeric_limits::min)) return BET_INVALID; } - else if (bxdf_traits::type == BT_BSDF) + else if (bxdf::traits::type == bxdf::BT_BSDF) { if (abs(s.NdotL) <= bit_cast(numeric_limits::min)) return BET_INVALID; @@ -529,12 +529,12 @@ struct TestJacobian : TestBxDF ErrorType test() { - if (bxdf_traits::type == BT_BRDF) + if (bxdf::traits::type == bxdf::BT_BRDF) { if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) return BET_INVALID; } - else if (bxdf_traits::type == BT_BSDF) + else if (bxdf::traits::type == bxdf::BT_BSDF) { if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) return BET_INVALID; @@ -571,7 +571,7 @@ struct TestJacobian : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - PCG32x2 pcg = PCG32x2::construct(initparams.state); + random::PCG32x2 pcg = random::PCG32x2::construct(initparams.state); uint32_t2 state = pcg(); this_t t; @@ -639,12 +639,12 @@ struct TestReciprocity : TestBxDF } // TODO: add checks with need clamp trait - if (bxdf_traits::type == BT_BRDF) + if (bxdf::traits::type == bxdf::BT_BRDF) { if (s.NdotL <= bit_cast(numeric_limits::min)) return BET_INVALID; } - else if (bxdf_traits::type == BT_BSDF) + else if (bxdf::traits::type == bxdf::BT_BSDF) { if (abs(s.NdotL) <= bit_cast(numeric_limits::min)) return BET_INVALID; @@ -713,12 +713,12 @@ struct TestReciprocity : TestBxDF ErrorType test() { - if (bxdf_traits::type == BT_BRDF) + if (bxdf::traits::type == bxdf::BT_BRDF) { if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) return BET_INVALID; } - else if (bxdf_traits::type == BT_BSDF) + else if (bxdf::traits::type == bxdf::BT_BSDF) { if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) return BET_INVALID; @@ -745,7 +745,7 @@ struct TestReciprocity : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - PCG32x2 pcg = PCG32x2::construct(initparams.state); + random::PCG32x2 pcg = random::PCG32x2::construct(initparams.state); uint32_t2 state = pcg(); this_t t; @@ -886,12 +886,12 @@ struct TestBucket : TestBxDF ErrorType test() { - if (bxdf_traits::type == BT_BRDF) + if (bxdf::traits::type == bxdf::BT_BRDF) { if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) return BET_INVALID; } - else if (bxdf_traits::type == BT_BSDF) + else if (bxdf::traits::type == bxdf::BT_BSDF) { if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) return BET_INVALID; @@ -906,7 +906,7 @@ struct TestBucket : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - PCG32x2 pcg = PCG32x2::construct(initparams.state); + random::PCG32x2 pcg = random::PCG32x2::construct(initparams.state); uint32_t2 state = pcg(); this_t t; @@ -1266,10 +1266,10 @@ struct TestChi2 : TestBxDF ErrorType test() { - if (bxdf_traits::type == BT_BRDF) + if (bxdf::traits::type == bxdf::BT_BRDF) if (base_t::isointer.NdotV <= numeric_limits::min) return BET_INVALID; - else if (bxdf_traits::type == BT_BSDF) + else if (bxdf::traits::type == bxdf::BT_BSDF) if (abs(base_t::isointer.NdotV) <= numeric_limits::min) return BET_INVALID; @@ -1353,7 +1353,7 @@ struct TestChi2 : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - PCG32x2 pcg = PCG32x2::construct(initparams.state); + random::PCG32x2 pcg = random::PCG32x2::construct(initparams.state); uint32_t2 state = pcg(); this_t t; From 4864a4525e998186423f0376c480cda2e71759da Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 3 Apr 2025 16:34:13 +0700 Subject: [PATCH 30/40] use getters for interaction, samples --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 44 +++++++++++------------ 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 5c0b64a9f..4d447a542 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -496,12 +496,12 @@ struct TestJacobian : TestBxDF // TODO: add checks with need clamp trait if (bxdf::traits::type == bxdf::BT_BRDF) { - if (s.NdotL <= bit_cast(numeric_limits::min)) + if (s.getNdotL() <= bit_cast(numeric_limits::min)) return BET_INVALID; } else if (bxdf::traits::type == bxdf::BT_BSDF) { - if (abs(s.NdotL) <= bit_cast(numeric_limits::min)) + if (abs(s.getNdotL()) <= bit_cast(numeric_limits::min)) return BET_INVALID; } @@ -531,12 +531,12 @@ struct TestJacobian : TestBxDF { if (bxdf::traits::type == bxdf::BT_BRDF) { - if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) + if (base_t::isointer.getNdotV() <= bit_cast(numeric_limits::min)) return BET_INVALID; } else if (bxdf::traits::type == bxdf::BT_BSDF) { - if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) + if (abs(base_t::isointer.getNdotV()) <= bit_cast(numeric_limits::min)) return BET_INVALID; } @@ -557,10 +557,10 @@ struct TestJacobian : TestBxDF return BET_NEGATIVE_VAL; // get BET_jacobian - float32_t2x2 m = float32_t2x2(sx.TdotL - s.TdotL, sy.TdotL - s.TdotL, sx.BdotL - s.BdotL, sy.BdotL - s.BdotL); + float32_t2x2 m = float32_t2x2(sx.getTdotL() - s.getTdotL(), sy.getTdotL() - s.getTdotL(), sx.getBdotL() - s.getBdotL(), sy.getBdotL() - s.getBdotL()); float det = nbl::hlsl::determinant(m); - if (!checkZero(det * pdf.pdf / s.NdotL, 1e-5)) + if (!checkZero(det * pdf.pdf / s.getNdotL(), 1e-5)) return BET_JACOBIAN; if (!checkEq(pdf.value(), bsdf, 5e-2)) @@ -641,19 +641,19 @@ struct TestReciprocity : TestBxDF // TODO: add checks with need clamp trait if (bxdf::traits::type == bxdf::BT_BRDF) { - if (s.NdotL <= bit_cast(numeric_limits::min)) + if (s.getNdotL() <= bit_cast(numeric_limits::min)) return BET_INVALID; } else if (bxdf::traits::type == bxdf::BT_BSDF) { - if (abs(s.NdotL) <= bit_cast(numeric_limits::min)) + if (abs(s.getNdotL()) <= bit_cast(numeric_limits::min)) return BET_INVALID; } float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); - ray_dir_info_t rec_V = s.L; - ray_dir_info_t rec_localV = ray_dir_info_t::transform(toTangentSpace, rec_V); - ray_dir_info_t rec_localL = ray_dir_info_t::transform(toTangentSpace, base_t::rc.V); + ray_dir_info_t rec_V = s.getL(); + ray_dir_info_t rec_localV = rec_V.transform(toTangentSpace); + ray_dir_info_t rec_localL = base_t::rc.V.transform(toTangentSpace); rec_s = sample_t::createFromTangentSpace(rec_localV.direction, rec_localL, base_t::anisointer.getFromTangentSpace()); iso_interaction rec_isointer = iso_interaction::create(rec_V, base_t::rc.N); @@ -715,12 +715,12 @@ struct TestReciprocity : TestBxDF { if (bxdf::traits::type == bxdf::BT_BRDF) { - if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) + if (base_t::isointer.getNdotV() <= bit_cast(numeric_limits::min)) return BET_INVALID; } else if (bxdf::traits::type == bxdf::BT_BSDF) { - if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) + if (abs(base_t::isointer.getNdotV()) <= bit_cast(numeric_limits::min)) return BET_INVALID; } @@ -863,7 +863,7 @@ struct TestBucket : TestBxDF // put s into bucket float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); - const ray_dir_info_t localL = ray_dir_info_t::transform(toTangentSpace, s.L); + const ray_dir_info_t localL = s.getL().transform(toTangentSpace); const float32_t2 coords = cartesianToPolar(localL.direction); float32_t2 bucket = float32_t2(bin(coords.x * numbers::inv_pi), bin(coords.y * 0.5f * numbers::inv_pi)); @@ -888,12 +888,12 @@ struct TestBucket : TestBxDF { if (bxdf::traits::type == bxdf::BT_BRDF) { - if (base_t::isointer.NdotV <= bit_cast(numeric_limits::min)) + if (base_t::isointer.getNdotV() <= bit_cast(numeric_limits::min)) return BET_INVALID; } else if (bxdf::traits::type == bxdf::BT_BSDF) { - if (abs(base_t::isointer.NdotV) <= bit_cast(numeric_limits::min)) + if (abs(base_t::isointer.getNdotV()) <= bit_cast(numeric_limits::min)) return BET_INVALID; } @@ -1165,9 +1165,7 @@ struct TestChi2 : TestBxDF } // put s into bucket - // float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); - // const ray_dir_info_t localL = ray_dir_info_t::transform(toTangentSpace, s.L); - float32_t2 coords = cartesianToPolar(s.L.direction) * float32_t2(thetaFactor, phiFactor); + float32_t2 coords = cartesianToPolar(s.getL().getDirection()) * float32_t2(thetaFactor, phiFactor); if (coords.y < 0) coords.y += 2.f * numbers::pi * phiFactor; @@ -1196,10 +1194,10 @@ struct TestChi2 : TestBxDF float cosPhi = std::cos(phi), sinPhi = std::sin(phi); float32_t3x3 toTangentSpace = base_t::anisointer.getToTangentSpace(); - ray_dir_info_t localV = ray_dir_info_t::transform(toTangentSpace, base_t::rc.V); + ray_dir_info_t localV = base_t::rc.V.transform(toTangentSpace); ray_dir_info_t L; L.direction = float32_t3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta); - ray_dir_info_t localL = ray_dir_info_t::transform(toTangentSpace, L); + ray_dir_info_t localL = L.transform(toTangentSpace); sample_t s = sample_t::createFromTangentSpace(localV.direction, localL, base_t::anisointer.getFromTangentSpace()); params_t params; @@ -1267,10 +1265,10 @@ struct TestChi2 : TestBxDF ErrorType test() { if (bxdf::traits::type == bxdf::BT_BRDF) - if (base_t::isointer.NdotV <= numeric_limits::min) + if (base_t::isointer.getNdotV() <= numeric_limits::min) return BET_INVALID; else if (bxdf::traits::type == bxdf::BT_BSDF) - if (abs(base_t::isointer.NdotV) <= numeric_limits::min) + if (abs(base_t::isointer.getNdotV()) <= numeric_limits::min) return BET_INVALID; ErrorType res = compute(); From 9dc93dd995c004f1396179ea1530658bd3a82c53 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 4 Apr 2025 11:19:43 +0700 Subject: [PATCH 31/40] use microfacet cache getters --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 4d447a542..f2a91f564 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -659,8 +659,8 @@ struct TestReciprocity : TestBxDF iso_interaction rec_isointer = iso_interaction::create(rec_V, base_t::rc.N); aniso_interaction rec_anisointer = aniso_interaction::create(rec_isointer, base_t::rc.T, base_t::rc.B); rec_cache = cache; - rec_cache.iso_cache.VdotH = cache.iso_cache.LdotH; - rec_cache.iso_cache.LdotH = cache.iso_cache.VdotH; + rec_cache.iso_cache.VdotH = cache.iso_cache.getLdotH(); + rec_cache.iso_cache.LdotH = cache.iso_cache.getVdotH(); rec_isocache = rec_cache.iso_cache; From 6f3706aaaf35af9df173bc4dcb6c92885d831526 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 4 Apr 2025 14:29:43 +0700 Subject: [PATCH 32/40] use new rng wrapper --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index f2a91f564..756d7622d 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -5,6 +5,7 @@ #include "nbl/builtin/hlsl/random/xoroshiro.hlsl" #include "nbl/builtin/hlsl/random/pcg.hlsl" +#include "nbl/builtin/hlsl/random/rand_gen.hlsl" #include "nbl/builtin/hlsl/sampling/uniform.hlsl" #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" @@ -571,7 +572,7 @@ struct TestJacobian : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - random::PCG32x2 pcg = random::PCG32x2::construct(initparams.state); + random::Uniform2D pcg = random::Uniform2D::construct(initparams.state); uint32_t2 state = pcg(); this_t t; @@ -745,7 +746,7 @@ struct TestReciprocity : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - random::PCG32x2 pcg = random::PCG32x2::construct(initparams.state); + random::Uniform2D pcg = random::Uniform2D::construct(initparams.state); uint32_t2 state = pcg(); this_t t; @@ -906,7 +907,7 @@ struct TestBucket : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - random::PCG32x2 pcg = random::PCG32x2::construct(initparams.state); + random::Uniform2D pcg = random::Uniform2D::construct(initparams.state); uint32_t2 state = pcg(); this_t t; @@ -1351,7 +1352,7 @@ struct TestChi2 : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - random::PCG32x2 pcg = random::PCG32x2::construct(initparams.state); + random::Uniform2D pcg = random::Uniform2D::construct(initparams.state); uint32_t2 state = pcg(); this_t t; From 6d298fdfd2cfb3d1bd1aabbb4912e6b1080e0f38 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 14 Apr 2025 10:59:27 +0700 Subject: [PATCH 33/40] refactor uniform2d usage --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 756d7622d..71673473b 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -572,8 +572,9 @@ struct TestJacobian : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - random::Uniform2D pcg = random::Uniform2D::construct(initparams.state); - uint32_t2 state = pcg(); + random::PCG32 pcg = random::PCG32::construct(initparams.state); + random::Uniform rand2d = random::Uniform::construct(pcg); + uint32_t2 state = rand2d(); this_t t; t.init(state); @@ -746,8 +747,9 @@ struct TestReciprocity : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - random::Uniform2D pcg = random::Uniform2D::construct(initparams.state); - uint32_t2 state = pcg(); + random::PCG32 pcg = random::PCG32::construct(initparams.state); + random::Uniform rand2d = random::Uniform::construct(pcg); + uint32_t2 state = rand2d(); this_t t; t.init(state); @@ -907,8 +909,9 @@ struct TestBucket : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - random::Uniform2D pcg = random::Uniform2D::construct(initparams.state); - uint32_t2 state = pcg(); + random::PCG32 pcg = random::PCG32::construct(initparams.state); + random::Uniform rand2d = random::Uniform::construct(pcg); + uint32_t2 state = rand2d(); this_t t; t.init(state); @@ -1352,8 +1355,9 @@ struct TestChi2 : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { - random::Uniform2D pcg = random::Uniform2D::construct(initparams.state); - uint32_t2 state = pcg(); + random::PCG32 pcg = random::PCG32::construct(initparams.state); + random::Uniform rand2d = random::Uniform::construct(pcg); + uint32_t2 state = rand2d(); this_t t; t.init(state); From dd7c0c7a12cc5a15d5d48f97cf2b7647ff07f426 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 14 Apr 2025 14:29:21 +0700 Subject: [PATCH 34/40] refactor quotient_pdf usage --- 66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl | 2 +- 66_HLSLBxDFTests/app_resources/tests.hlsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl index a2d6ba113..65645751b 100644 --- a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -15,7 +15,7 @@ using aniso_interaction = bxdf::surface_interactions::SAnisotropic; using iso_cache = bxdf::SIsotropicMicrofacetCache; using aniso_cache = bxdf::SAnisotropicMicrofacetCache; -using quotient_pdf_t = bxdf::quotient_and_pdf; +using quotient_pdf_t = sampling::quotient_and_pdf; using spectral_t = vector; using params_t = bxdf::SBxDFParams; diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 71673473b..0ed0e5642 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -49,7 +49,7 @@ using aniso_interaction = bxdf::surface_interactions::SAnisotropic; using iso_cache = bxdf::SIsotropicMicrofacetCache; using aniso_cache = bxdf::SAnisotropicMicrofacetCache; -using quotient_pdf_t = bxdf::quotient_and_pdf; +using quotient_pdf_t = sampling::quotient_and_pdf; using spectral_t = vector; using params_t = bxdf::SBxDFParams; From 9b071a656775966350513899c1af5901d48a684a Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Apr 2025 14:32:29 +0700 Subject: [PATCH 35/40] refactor changes to aniso cache --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 0ed0e5642..31f280fb2 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -453,9 +453,9 @@ struct TestJacobian : TestBxDF if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) { - s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy); - sx = base_t::bxdf.generate(base_t::anisointer, ux.xy); - sy = base_t::bxdf.generate(base_t::anisointer, uy.xy); + s = base_t::bxdf.generate(base_t::isointer, base_t::rc.u.xy); + sx = base_t::bxdf.generate(base_t::isointer, ux.xy); + sy = base_t::bxdf.generate(base_t::isointer, uy.xy); params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) @@ -1211,7 +1211,7 @@ struct TestChi2 : TestBxDF } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) { - aniso_cache cache = aniso_cache::template createForReflection(base_t::anisointer, s); + aniso_cache cache = aniso_cache::template createForReflection(base_t::anisointer, s); if NBL_CONSTEXPR_FUNC (aniso) params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); @@ -1227,7 +1227,7 @@ struct TestChi2 : TestBxDF } if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) { - aniso_cache cache = aniso_cache::template createForReflection(base_t::anisointer, s); + aniso_cache cache = aniso_cache::template createForReflection(base_t::anisointer, s); if NBL_CONSTEXPR_FUNC (aniso) params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); From 61757af8b5417c276f843fcc463cf33c80a5ea92 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Apr 2025 16:57:38 +0700 Subject: [PATCH 36/40] added checking concepts work --- 66_HLSLBxDFTests/main.cpp | 107 ++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 50 deletions(-) diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index f613b6a29..a2a068445 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -88,56 +88,63 @@ int main(int argc, char** argv) } // test compile with dxc - { - smart_refctd_ptr m_system = system::IApplicationFramework::createSystem(); - smart_refctd_ptr m_logger = core::make_smart_refctd_ptr(system::ILogger::DefaultLogMask()); - m_logger->log("Logger Created!", system::ILogger::ELL_INFO); - smart_refctd_ptr m_assetMgr = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); - - path CWD = system::path(argv[0]).parent_path().generic_string() + "/"; - path localInputCWD = CWD / "../"; - auto resourceArchive = -#ifdef NBL_EMBED_BUILTIN_RESOURCES - make_smart_refctd_ptr(smart_refctd_ptr(m_logger)); -#else - make_smart_refctd_ptr(localInputCWD/"app_resources", smart_refctd_ptr(m_logger), m_system.get()); -#endif - m_system->mount(std::move(resourceArchive), "app_resources"); - - constexpr uint32_t WorkgroupSize = 256; - const std::string WorkgroupSizeAsStr = std::to_string(WorkgroupSize); - const std::string filePath = "app_resources/test_compile.comp.hlsl"; - - IAssetLoader::SAssetLoadParams lparams = {}; - lparams.logger = m_logger.get(); - lparams.workingDirectory = ""; - auto bundle = m_assetMgr->getAsset(filePath, lparams); - if (bundle.getContents().empty() || bundle.getAssetType() != IAsset::ET_SHADER) - { - m_logger->log("Shader %s not found!", ILogger::ELL_ERROR, filePath); - exit(-1); - } - - const auto assets = bundle.getContents(); - assert(assets.size() == 1); - smart_refctd_ptr shaderSrc = IAsset::castDown(assets[0]); - - smart_refctd_ptr shader = shaderSrc; - auto compiler = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); - CHLSLCompiler::SOptions options = {}; - options.stage = asset::IShader::E_SHADER_STAGE::ESS_COMPUTE; - options.debugInfoFlags |= IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_LINE_BIT; - options.spirvOptimizer = nullptr; - // if you don't set the logger and source identifier you'll have no meaningful errors - options.preprocessorOptions.sourceIdentifier = shaderSrc->getFilepathHint(); - options.preprocessorOptions.logger = m_logger.get(); - options.preprocessorOptions.includeFinder = compiler->getDefaultIncludeFinder(); - const IShaderCompiler::SMacroDefinition WorkgroupSizeDefine = { "WORKGROUP_SIZE", WorkgroupSizeAsStr }; - options.preprocessorOptions.extraDefines = { &WorkgroupSizeDefine,&WorkgroupSizeDefine + 1 }; - if (!(shader = compiler->compileToSPIRV((const char*)shaderSrc->getContent()->getPointer(), options))) - fprintf(stderr, "[ERROR] compile shader test failed!\n"); - } - +// { +// smart_refctd_ptr m_system = system::IApplicationFramework::createSystem(); +// smart_refctd_ptr m_logger = core::make_smart_refctd_ptr(system::ILogger::DefaultLogMask()); +// m_logger->log("Logger Created!", system::ILogger::ELL_INFO); +// smart_refctd_ptr m_assetMgr = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); +// +// path CWD = system::path(argv[0]).parent_path().generic_string() + "/"; +// path localInputCWD = CWD / "../"; +// auto resourceArchive = +//#ifdef NBL_EMBED_BUILTIN_RESOURCES +// make_smart_refctd_ptr(smart_refctd_ptr(m_logger)); +//#else +// make_smart_refctd_ptr(localInputCWD/"app_resources", smart_refctd_ptr(m_logger), m_system.get()); +//#endif +// m_system->mount(std::move(resourceArchive), "app_resources"); +// +// constexpr uint32_t WorkgroupSize = 256; +// const std::string WorkgroupSizeAsStr = std::to_string(WorkgroupSize); +// const std::string filePath = "app_resources/test_compile.comp.hlsl"; +// +// IAssetLoader::SAssetLoadParams lparams = {}; +// lparams.logger = m_logger.get(); +// lparams.workingDirectory = ""; +// auto bundle = m_assetMgr->getAsset(filePath, lparams); +// if (bundle.getContents().empty() || bundle.getAssetType() != IAsset::ET_SHADER) +// { +// m_logger->log("Shader %s not found!", ILogger::ELL_ERROR, filePath); +// exit(-1); +// } +// +// const auto assets = bundle.getContents(); +// assert(assets.size() == 1); +// smart_refctd_ptr shaderSrc = IAsset::castDown(assets[0]); +// +// smart_refctd_ptr shader = shaderSrc; +// auto compiler = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); +// CHLSLCompiler::SOptions options = {}; +// options.stage = asset::IShader::E_SHADER_STAGE::ESS_COMPUTE; +// options.debugInfoFlags |= IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_LINE_BIT; +// options.spirvOptimizer = nullptr; +// // if you don't set the logger and source identifier you'll have no meaningful errors +// options.preprocessorOptions.sourceIdentifier = shaderSrc->getFilepathHint(); +// options.preprocessorOptions.logger = m_logger.get(); +// options.preprocessorOptions.includeFinder = compiler->getDefaultIncludeFinder(); +// const IShaderCompiler::SMacroDefinition WorkgroupSizeDefine = { "WORKGROUP_SIZE", WorkgroupSizeAsStr }; +// options.preprocessorOptions.extraDefines = { &WorkgroupSizeDefine,&WorkgroupSizeDefine + 1 }; +// if (!(shader = compiler->compileToSPIRV((const char*)shaderSrc->getContent()->getPointer(), options))) +// fprintf(stderr, "[ERROR] compile shader test failed!\n"); +// } + + assert(bxdf::surface_interactions::Isotropic); + assert(bxdf::surface_interactions::Isotropic); + assert(bxdf::surface_interactions::Anisotropic); + + assert(bxdf::CreatableIsotropicMicrofacetCache); + assert(bxdf::ReadableIsotropicMicrofacetCache); + assert(bxdf::AnisotropicMicrofacetCache); const bool logInfo = testconfigs["logInfo"]; PrintFailureCallback cb; From 2ae583ff5bcc49948017bb856dbdfb3de991d764 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 16 Apr 2025 17:00:42 +0700 Subject: [PATCH 37/40] uncommented shader compile test --- 66_HLSLBxDFTests/main.cpp | 98 +++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index a2a068445..983b0fc96 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -88,55 +88,55 @@ int main(int argc, char** argv) } // test compile with dxc -// { -// smart_refctd_ptr m_system = system::IApplicationFramework::createSystem(); -// smart_refctd_ptr m_logger = core::make_smart_refctd_ptr(system::ILogger::DefaultLogMask()); -// m_logger->log("Logger Created!", system::ILogger::ELL_INFO); -// smart_refctd_ptr m_assetMgr = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); -// -// path CWD = system::path(argv[0]).parent_path().generic_string() + "/"; -// path localInputCWD = CWD / "../"; -// auto resourceArchive = -//#ifdef NBL_EMBED_BUILTIN_RESOURCES -// make_smart_refctd_ptr(smart_refctd_ptr(m_logger)); -//#else -// make_smart_refctd_ptr(localInputCWD/"app_resources", smart_refctd_ptr(m_logger), m_system.get()); -//#endif -// m_system->mount(std::move(resourceArchive), "app_resources"); -// -// constexpr uint32_t WorkgroupSize = 256; -// const std::string WorkgroupSizeAsStr = std::to_string(WorkgroupSize); -// const std::string filePath = "app_resources/test_compile.comp.hlsl"; -// -// IAssetLoader::SAssetLoadParams lparams = {}; -// lparams.logger = m_logger.get(); -// lparams.workingDirectory = ""; -// auto bundle = m_assetMgr->getAsset(filePath, lparams); -// if (bundle.getContents().empty() || bundle.getAssetType() != IAsset::ET_SHADER) -// { -// m_logger->log("Shader %s not found!", ILogger::ELL_ERROR, filePath); -// exit(-1); -// } -// -// const auto assets = bundle.getContents(); -// assert(assets.size() == 1); -// smart_refctd_ptr shaderSrc = IAsset::castDown(assets[0]); -// -// smart_refctd_ptr shader = shaderSrc; -// auto compiler = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); -// CHLSLCompiler::SOptions options = {}; -// options.stage = asset::IShader::E_SHADER_STAGE::ESS_COMPUTE; -// options.debugInfoFlags |= IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_LINE_BIT; -// options.spirvOptimizer = nullptr; -// // if you don't set the logger and source identifier you'll have no meaningful errors -// options.preprocessorOptions.sourceIdentifier = shaderSrc->getFilepathHint(); -// options.preprocessorOptions.logger = m_logger.get(); -// options.preprocessorOptions.includeFinder = compiler->getDefaultIncludeFinder(); -// const IShaderCompiler::SMacroDefinition WorkgroupSizeDefine = { "WORKGROUP_SIZE", WorkgroupSizeAsStr }; -// options.preprocessorOptions.extraDefines = { &WorkgroupSizeDefine,&WorkgroupSizeDefine + 1 }; -// if (!(shader = compiler->compileToSPIRV((const char*)shaderSrc->getContent()->getPointer(), options))) -// fprintf(stderr, "[ERROR] compile shader test failed!\n"); -// } + { + smart_refctd_ptr m_system = system::IApplicationFramework::createSystem(); + smart_refctd_ptr m_logger = core::make_smart_refctd_ptr(system::ILogger::DefaultLogMask()); + m_logger->log("Logger Created!", system::ILogger::ELL_INFO); + smart_refctd_ptr m_assetMgr = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); + + path CWD = system::path(argv[0]).parent_path().generic_string() + "/"; + path localInputCWD = CWD / "../"; + auto resourceArchive = +#ifdef NBL_EMBED_BUILTIN_RESOURCES + make_smart_refctd_ptr(smart_refctd_ptr(m_logger)); +#else + make_smart_refctd_ptr(localInputCWD/"app_resources", smart_refctd_ptr(m_logger), m_system.get()); +#endif + m_system->mount(std::move(resourceArchive), "app_resources"); + + constexpr uint32_t WorkgroupSize = 256; + const std::string WorkgroupSizeAsStr = std::to_string(WorkgroupSize); + const std::string filePath = "app_resources/test_compile.comp.hlsl"; + + IAssetLoader::SAssetLoadParams lparams = {}; + lparams.logger = m_logger.get(); + lparams.workingDirectory = ""; + auto bundle = m_assetMgr->getAsset(filePath, lparams); + if (bundle.getContents().empty() || bundle.getAssetType() != IAsset::ET_SHADER) + { + m_logger->log("Shader %s not found!", ILogger::ELL_ERROR, filePath); + exit(-1); + } + + const auto assets = bundle.getContents(); + assert(assets.size() == 1); + smart_refctd_ptr shaderSrc = IAsset::castDown(assets[0]); + + smart_refctd_ptr shader = shaderSrc; + auto compiler = make_smart_refctd_ptr(smart_refctd_ptr(m_system)); + CHLSLCompiler::SOptions options = {}; + options.stage = asset::IShader::E_SHADER_STAGE::ESS_COMPUTE; + options.debugInfoFlags |= IShaderCompiler::E_DEBUG_INFO_FLAGS::EDIF_LINE_BIT; + options.spirvOptimizer = nullptr; + // if you don't set the logger and source identifier you'll have no meaningful errors + options.preprocessorOptions.sourceIdentifier = shaderSrc->getFilepathHint(); + options.preprocessorOptions.logger = m_logger.get(); + options.preprocessorOptions.includeFinder = compiler->getDefaultIncludeFinder(); + const IShaderCompiler::SMacroDefinition WorkgroupSizeDefine = { "WORKGROUP_SIZE", WorkgroupSizeAsStr }; + options.preprocessorOptions.extraDefines = { &WorkgroupSizeDefine,&WorkgroupSizeDefine + 1 }; + if (!(shader = compiler->compileToSPIRV((const char*)shaderSrc->getContent()->getPointer(), options))) + fprintf(stderr, "[ERROR] compile shader test failed!\n"); + } assert(bxdf::surface_interactions::Isotropic); assert(bxdf::surface_interactions::Isotropic); From d4d94e61dead828a09525b27291686ab58b06e05 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 17 Apr 2025 11:44:11 +0700 Subject: [PATCH 38/40] refactor tests to quotient pdf changes --- 66_HLSLBxDFTests/app_resources/tests.hlsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 31f280fb2..1992b2190 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -5,7 +5,7 @@ #include "nbl/builtin/hlsl/random/xoroshiro.hlsl" #include "nbl/builtin/hlsl/random/pcg.hlsl" -#include "nbl/builtin/hlsl/random/rand_gen.hlsl" +#include "nbl/builtin/hlsl/random/dim_adaptor_recursive.hlsl" #include "nbl/builtin/hlsl/sampling/uniform.hlsl" #include "nbl/builtin/hlsl/bxdf/common.hlsl" #include "nbl/builtin/hlsl/bxdf/reflection.hlsl" @@ -573,7 +573,7 @@ struct TestJacobian : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { random::PCG32 pcg = random::PCG32::construct(initparams.state); - random::Uniform rand2d = random::Uniform::construct(pcg); + random::DimAdaptorRecursive rand2d = random::DimAdaptorRecursive::construct(pcg); uint32_t2 state = rand2d(); this_t t; @@ -748,7 +748,7 @@ struct TestReciprocity : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { random::PCG32 pcg = random::PCG32::construct(initparams.state); - random::Uniform rand2d = random::Uniform::construct(pcg); + random::DimAdaptorRecursive rand2d = random::DimAdaptorRecursive::construct(pcg); uint32_t2 state = rand2d(); this_t t; @@ -910,7 +910,7 @@ struct TestBucket : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { random::PCG32 pcg = random::PCG32::construct(initparams.state); - random::Uniform rand2d = random::Uniform::construct(pcg); + random::DimAdaptorRecursive rand2d = random::DimAdaptorRecursive::construct(pcg); uint32_t2 state = rand2d(); this_t t; @@ -1356,7 +1356,7 @@ struct TestChi2 : TestBxDF static void run(NBL_CONST_REF_ARG(STestInitParams) initparams, NBL_REF_ARG(FailureCallback) cb) { random::PCG32 pcg = random::PCG32::construct(initparams.state); - random::Uniform rand2d = random::Uniform::construct(pcg); + random::DimAdaptorRecursive rand2d = random::DimAdaptorRecursive::construct(pcg); uint32_t2 state = rand2d(); this_t t; From cf2dbcffd37ddc8d8268e256bef94477c84cb636 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Thu, 17 Apr 2025 16:04:43 +0700 Subject: [PATCH 39/40] refactor typedef changes in bxdfs --- .../app_resources/test_compile.comp.hlsl | 16 ++-- 66_HLSLBxDFTests/app_resources/tests.hlsl | 60 +++++++------- 66_HLSLBxDFTests/main.cpp | 80 +++++++++---------- 3 files changed, 78 insertions(+), 78 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl index 65645751b..e6e9533f0 100644 --- a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -11,10 +11,10 @@ using namespace nbl::hlsl; using ray_dir_info_t = bxdf::ray_dir_info::SBasic; using iso_interaction = bxdf::surface_interactions::SIsotropic; -using aniso_interaction = bxdf::surface_interactions::SAnisotropic; +using aniso_interaction = bxdf::surface_interactions::SAnisotropic; using sample_t = bxdf::SLightSample; using iso_cache = bxdf::SIsotropicMicrofacetCache; -using aniso_cache = bxdf::SAnisotropicMicrofacetCache; +using aniso_cache = bxdf::SAnisotropicMicrofacetCache; using quotient_pdf_t = sampling::quotient_and_pdf; using spectral_t = vector; using params_t = bxdf::SBxDFParams; @@ -24,14 +24,14 @@ void main(uint32_t3 ID : SV_DispatchThreadID) { bxdf::reflection::SLambertianBxDF lambertianBRDF; bxdf::reflection::SOrenNayarBxDF orenNayarBRDF; - bxdf::reflection::SBeckmannBxDF beckmannBRDF; - bxdf::reflection::SGGXBxDF ggxBRDF; + bxdf::reflection::SBeckmannBxDF beckmannBRDF; + bxdf::reflection::SGGXBxDF ggxBRDF; bxdf::transmission::SLambertianBxDF lambertianBSDF; - bxdf::transmission::SSmoothDielectricBxDF smoothDielectricBSDF; - bxdf::transmission::SSmoothDielectricBxDF thinSmoothDielectricBSDF; - bxdf::transmission::SBeckmannDielectricBxDF beckmannBSDF; - bxdf::transmission::SGGXDielectricBxDF ggxBSDF; + bxdf::transmission::SSmoothDielectricBxDF smoothDielectricBSDF; + bxdf::transmission::SSmoothDielectricBxDF thinSmoothDielectricBSDF; + bxdf::transmission::SBeckmannDielectricBxDF beckmannBSDF; + bxdf::transmission::SGGXDielectricBxDF ggxBSDF; // do some nonsense calculations, but call all the relevant functions diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index 1992b2190..fb837a378 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -45,10 +45,10 @@ namespace hlsl using ray_dir_info_t = bxdf::ray_dir_info::SBasic; using iso_interaction = bxdf::surface_interactions::SIsotropic; -using aniso_interaction = bxdf::surface_interactions::SAnisotropic; +using aniso_interaction = bxdf::surface_interactions::SAnisotropic; using sample_t = bxdf::SLightSample; using iso_cache = bxdf::SIsotropicMicrofacetCache; -using aniso_cache = bxdf::SAnisotropicMicrofacetCache; +using aniso_cache = bxdf::SAnisotropicMicrofacetCache; using quotient_pdf_t = sampling::quotient_and_pdf; using spectral_t = vector; using params_t = bxdf::SBxDFParams; @@ -273,23 +273,23 @@ struct TestBxDF -struct TestBxDF> : TestBxDFBase> +struct TestBxDF> : TestBxDFBase> { - using base_t = TestBxDFBase>; + using base_t = TestBxDFBase>; template void initBxDF(SBxDFTestResources _rc) { if (aniso) { - base_t::bxdf = bxdf::reflection::SBeckmannBxDF::create(rc.alpha.x,rc.alpha.y,(float32_t3)(rc.ior.x),(float32_t3)(rc.ior.y)); + base_t::bxdf = bxdf::reflection::SBeckmannBxDF::create(rc.alpha.x,rc.alpha.y,(float32_t3)(rc.ior.x),(float32_t3)(rc.ior.y)); #ifndef __HLSL_VERSION base_t::name = "Beckmann Aniso BRDF"; #endif } else { - base_t::bxdf = bxdf::reflection::SBeckmannBxDF::create(rc.alpha.x,(float32_t3)(rc.ior.x),(float32_t3)(rc.ior.y)); + base_t::bxdf = bxdf::reflection::SBeckmannBxDF::create(rc.alpha.x,(float32_t3)(rc.ior.x),(float32_t3)(rc.ior.y)); #ifndef __HLSL_VERSION base_t::name = "Beckmann BRDF"; #endif @@ -298,23 +298,23 @@ struct TestBxDF -struct TestBxDF> : TestBxDFBase> +struct TestBxDF> : TestBxDFBase> { - using base_t = TestBxDFBase>; + using base_t = TestBxDFBase>; template void initBxDF(SBxDFTestResources _rc) { if (aniso) { - base_t::bxdf = bxdf::reflection::SGGXBxDF::create(rc.alpha.x,rc.alpha.y,(float32_t3)(rc.ior.x),(float32_t3)(rc.ior.y)); + base_t::bxdf = bxdf::reflection::SGGXBxDF::create(rc.alpha.x,rc.alpha.y,(float32_t3)(rc.ior.x),(float32_t3)(rc.ior.y)); #ifndef __HLSL_VERSION base_t::name = "GGX Aniso BRDF"; #endif } else { - base_t::bxdf = bxdf::reflection::SGGXBxDF::create(rc.alpha.x,(float32_t3)(rc.ior.x),(float32_t3)(rc.ior.y)); + base_t::bxdf = bxdf::reflection::SGGXBxDF::create(rc.alpha.x,(float32_t3)(rc.ior.x),(float32_t3)(rc.ior.y)); #ifndef __HLSL_VERSION base_t::name = "GGX BRDF"; #endif @@ -323,13 +323,13 @@ struct TestBxDF -struct TestBxDF> : TestBxDFBase> +struct TestBxDF> : TestBxDFBase> { - using base_t = TestBxDFBase>; + using base_t = TestBxDFBase>; void initBxDF(SBxDFTestResources _rc) { - base_t::bxdf = bxdf::transmission::SSmoothDielectricBxDF::create(rc.eta); + base_t::bxdf = bxdf::transmission::SSmoothDielectricBxDF::create(rc.eta); #ifndef __HLSL_VERSION base_t::name = "Smooth dielectric BSDF"; #endif @@ -337,13 +337,13 @@ struct TestBxDF -struct TestBxDF> : TestBxDFBase> +struct TestBxDF> : TestBxDFBase> { - using base_t = TestBxDFBase>; + using base_t = TestBxDFBase>; void initBxDF(SBxDFTestResources _rc) { - base_t::bxdf = bxdf::transmission::SSmoothDielectricBxDF::create(float32_t3(rc.eta * rc.eta),rc.luma_coeff); + base_t::bxdf = bxdf::transmission::SSmoothDielectricBxDF::create(float32_t3(rc.eta * rc.eta),rc.luma_coeff); #ifndef __HLSL_VERSION base_t::name = "Thin smooth dielectric BSDF"; #endif @@ -351,23 +351,23 @@ struct TestBxDF -struct TestBxDF> : TestBxDFBase> +struct TestBxDF> : TestBxDFBase> { - using base_t = TestBxDFBase>; + using base_t = TestBxDFBase>; template void initBxDF(SBxDFTestResources _rc) { if (aniso) { - base_t::bxdf = bxdf::transmission::SBeckmannDielectricBxDF::create(rc.eta,rc.alpha.x,rc.alpha.y); + base_t::bxdf = bxdf::transmission::SBeckmannDielectricBxDF::create(rc.eta,rc.alpha.x,rc.alpha.y); #ifndef __HLSL_VERSION base_t::name = "Beckmann Dielectric Aniso BSDF"; #endif } else { - base_t::bxdf = bxdf::transmission::SBeckmannDielectricBxDF::create(rc.eta,rc.alpha.x); + base_t::bxdf = bxdf::transmission::SBeckmannDielectricBxDF::create(rc.eta,rc.alpha.x); #ifndef __HLSL_VERSION base_t::name = "Beckmann Dielectric BSDF"; #endif @@ -376,23 +376,23 @@ struct TestBxDF -struct TestBxDF> : TestBxDFBase> +struct TestBxDF> : TestBxDFBase> { - using base_t = TestBxDFBase>; + using base_t = TestBxDFBase>; template void initBxDF(SBxDFTestResources _rc) { if (aniso) { - base_t::bxdf = bxdf::transmission::SGGXDielectricBxDF::create(rc.eta,rc.alpha.x,rc.alpha.y); + base_t::bxdf = bxdf::transmission::SGGXDielectricBxDF::create(rc.eta,rc.alpha.x,rc.alpha.y); #ifndef __HLSL_VERSION base_t::name = "GGX Dielectric Aniso BSDF"; #endif } else { - base_t::bxdf = bxdf::transmission::SGGXDielectricBxDF::create(rc.eta,rc.alpha.x); + base_t::bxdf = bxdf::transmission::SGGXDielectricBxDF::create(rc.eta,rc.alpha.x); #ifndef __HLSL_VERSION base_t::name = "GGX Dielectric BSDF"; #endif @@ -409,21 +409,21 @@ struct is_basic_brdf : bool_constant< template struct is_microfacet_brdf : bool_constant< - is_same>::value || - is_same>::value + is_same>::value || + is_same>::value > {}; template struct is_basic_bsdf : bool_constant< is_same>::value || - is_same>::value || - is_same>::value + is_same>::value || + is_same>::value > {}; template struct is_microfacet_bsdf : bool_constant< - is_same>::value || - is_same>::value + is_same>::value || + is_same>::value > {}; template diff --git a/66_HLSLBxDFTests/main.cpp b/66_HLSLBxDFTests/main.cpp index 983b0fc96..e2da0539d 100644 --- a/66_HLSLBxDFTests/main.cpp +++ b/66_HLSLBxDFTests/main.cpp @@ -158,18 +158,18 @@ int main(int argc, char** argv) TestJacobian>::run(initparams, cb); TestJacobian>::run(initparams, cb); - TestJacobian, false>::run(initparams, cb); - TestJacobian, true>::run(initparams, cb); - TestJacobian, false>::run(initparams, cb); - TestJacobian,true>::run(initparams, cb); + TestJacobian, false>::run(initparams, cb); + TestJacobian, true>::run(initparams, cb); + TestJacobian, false>::run(initparams, cb); + TestJacobian,true>::run(initparams, cb); TestJacobian>::run(initparams, cb); - TestJacobian>::run(initparams, cb); - TestJacobian>::run(initparams, cb); - TestJacobian, false>::run(initparams, cb); - TestJacobian, true>::run(initparams, cb); - TestJacobian, false>::run(initparams, cb); - TestJacobian,true>::run(initparams, cb); + TestJacobian >::run(initparams, cb); + TestJacobian >::run(initparams, cb); + TestJacobian, false>::run(initparams, cb); + TestJacobian, true>::run(initparams, cb); + TestJacobian, false>::run(initparams, cb); + TestJacobian,true>::run(initparams, cb); FOR_EACH_END @@ -182,18 +182,18 @@ int main(int argc, char** argv) TestReciprocity>::run(initparams, cb); TestReciprocity>::run(initparams, cb); - TestReciprocity, false>::run(initparams, cb); - TestReciprocity, true>::run(initparams, cb); - TestReciprocity, false>::run(initparams, cb); - TestReciprocity, true>::run(initparams, cb); + TestReciprocity, false>::run(initparams, cb); + TestReciprocity, true>::run(initparams, cb); + TestReciprocity, false>::run(initparams, cb); + TestReciprocity, true>::run(initparams, cb); TestReciprocity>::run(initparams, cb); - TestReciprocity>::run(initparams, cb); - TestReciprocity>::run(initparams, cb); - TestReciprocity, false>::run(initparams, cb); - TestReciprocity, true>::run(initparams, cb); - TestReciprocity, false>::run(initparams, cb); - TestReciprocity, true>::run(initparams, cb); + TestReciprocity>::run(initparams, cb); + TestReciprocity>::run(initparams, cb); + TestReciprocity, false>::run(initparams, cb); + TestReciprocity, true>::run(initparams, cb); + TestReciprocity, false>::run(initparams, cb); + TestReciprocity, true>::run(initparams, cb); FOR_EACH_END @@ -208,18 +208,18 @@ int main(int argc, char** argv) TestBucket>::run(initparams, cb); TestBucket>::run(initparams, cb); - TestBucket, false>::run(initparams, cb); - TestBucket, true>::run(initparams, cb); - TestBucket, false>::run(initparams, cb); - TestBucket, true>::run(initparams, cb); + TestBucket, false>::run(initparams, cb); + TestBucket, true>::run(initparams, cb); + TestBucket, false>::run(initparams, cb); + TestBucket, true>::run(initparams, cb); TestBucket>::run(initparams, cb); - //TestBucket>::run(initparams, cb); - //TestBucket>::run(initparams, cb); - TestBucket, false>::run(initparams, cb); - TestBucket, true>::run(initparams, cb); - TestBucket, false>::run(initparams, cb); - TestBucket, true>::run(initparams, cb); + //TestBucket>::run(initparams, cb); + //TestBucket>::run(initparams, cb); + TestBucket, false>::run(initparams, cb); + TestBucket, true>::run(initparams, cb); + TestBucket, false>::run(initparams, cb); + TestBucket, true>::run(initparams, cb); FOR_EACH_END @@ -236,18 +236,18 @@ int main(int argc, char** argv) TestChi2>::run(initparams, cb); TestChi2>::run(initparams, cb); - TestChi2, false>::run(initparams, cb); - TestChi2, true>::run(initparams, cb); - TestChi2, false>::run(initparams, cb); - TestChi2, true>::run(initparams, cb); + TestChi2, false>::run(initparams, cb); + TestChi2, true>::run(initparams, cb); + TestChi2, false>::run(initparams, cb); + TestChi2, true>::run(initparams, cb); TestChi2>::run(initparams, cb); - //TestChi2>::run(initparams, cb); - //TestChi2>::run(initparams, cb); - TestChi2, false>::run(initparams, cb); - TestChi2, true>::run(initparams, cb); - TestChi2, false>::run(initparams, cb); - TestChi2, true>::run(initparams, cb); + //TestChi2>::run(initparams, cb); + //TestChi2>::run(initparams, cb); + TestChi2, false>::run(initparams, cb); + TestChi2, true>::run(initparams, cb); + TestChi2, false>::run(initparams, cb); + TestChi2, true>::run(initparams, cb); FOR_EACH_END // test arccos angle sums From c4a9602bf50dd7f4bb97582ce30440cdf706de53 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 18 Apr 2025 16:57:50 +0700 Subject: [PATCH 40/40] refactor changes to using bxdf params struct --- .../app_resources/test_compile.comp.hlsl | 21 +++--- 66_HLSLBxDFTests/app_resources/tests.hlsl | 69 ++++++++++--------- 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl index e6e9533f0..916b5e281 100644 --- a/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl +++ b/66_HLSLBxDFTests/app_resources/test_compile.comp.hlsl @@ -17,7 +17,6 @@ using iso_cache = bxdf::SIsotropicMicrofacetCache; using aniso_cache = bxdf::SAnisotropicMicrofacetCache; using quotient_pdf_t = sampling::quotient_and_pdf; using spectral_t = vector; -using params_t = bxdf::SBxDFParams; [numthreads(WORKGROUP_SIZE,1,1)] void main(uint32_t3 ID : SV_DispatchThreadID) @@ -54,22 +53,22 @@ void main(uint32_t3 ID : SV_DispatchThreadID) s = orenNayarBRDF.generate(anisointer, u.xy); L += s.L.direction; - params_t params = params_t::template create(s, isointer, bxdf::BxDFClampMode::BCM_MAX); - quotient_pdf_t qp = orenNayarBRDF.quotient_and_pdf(params); + bxdf::reflection::SOrenNayarBxDF::params_isotropic_t params0 = bxdf::reflection::SOrenNayarBxDF::params_isotropic_t::create(s, isointer, bxdf::BxDFClampMode::BCM_MAX); + quotient_pdf_t qp = orenNayarBRDF.quotient_and_pdf(params0); L -= qp.quotient; s = beckmannBRDF.generate(anisointer, u.xy, cache); L += s.L.direction; - params = params_t::template create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_MAX); - qp = beckmannBRDF.quotient_and_pdf(params); + bxdf::reflection::SBeckmannBxDF::params_anisotropic_t params1 = bxdf::reflection::SBeckmannBxDF::params_anisotropic_t::create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_MAX); + qp = beckmannBRDF.quotient_and_pdf(params1); L -= qp.quotient; s = ggxBRDF.generate(anisointer, u.xy, cache); L += s.L.direction; - params = params_t::template create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_MAX); - qp = ggxBRDF.quotient_and_pdf(params); + bxdf::reflection::SGGXBxDF::params_anisotropic_t params2 = bxdf::reflection::SGGXBxDF::params_anisotropic_t::create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_MAX); + qp = ggxBRDF.quotient_and_pdf(params2); L -= qp.quotient; s = lambertianBSDF.generate(anisointer, u); @@ -78,15 +77,15 @@ void main(uint32_t3 ID : SV_DispatchThreadID) s = thinSmoothDielectricBSDF.generate(anisointer, u); L += s.L.direction; - params = params_t::template create(s, isointer, bxdf::BxDFClampMode::BCM_ABS); - qp = thinSmoothDielectricBSDF.quotient_and_pdf(params); + bxdf::transmission::SSmoothDielectricBxDF::params_isotropic_t params3 = bxdf::transmission::SSmoothDielectricBxDF::params_isotropic_t::create(s, isointer, bxdf::BxDFClampMode::BCM_ABS); + qp = thinSmoothDielectricBSDF.quotient_and_pdf(params3); L -= qp.quotient; s = ggxBSDF.generate(anisointer, u, cache); L += s.L.direction; - params = params_t::template create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_ABS); - qp = ggxBSDF.quotient_and_pdf(params); + bxdf::transmission::SGGXDielectricBxDF::params_anisotropic_t params4 = bxdf::transmission::SGGXDielectricBxDF::params_anisotropic_t::create(s, anisointer, cache, bxdf::BxDFClampMode::BCM_ABS); + qp = ggxBSDF.quotient_and_pdf(params4); L -= qp.quotient; buff[ID.x] = L; diff --git a/66_HLSLBxDFTests/app_resources/tests.hlsl b/66_HLSLBxDFTests/app_resources/tests.hlsl index fb837a378..b0fa7d643 100644 --- a/66_HLSLBxDFTests/app_resources/tests.hlsl +++ b/66_HLSLBxDFTests/app_resources/tests.hlsl @@ -51,7 +51,6 @@ using iso_cache = bxdf::SIsotropicMicrofacetCache; using aniso_cache = bxdf::SAnisotropicMicrofacetCache; using quotient_pdf_t = sampling::quotient_and_pdf; using spectral_t = vector; -using params_t = bxdf::SBxDFParams; using bool32_t3 = vector; @@ -441,6 +440,7 @@ struct TestJacobian : TestBxDF { using base_t = TestBxDFBase; using this_t = TestJacobian; + using params_t = conditional_t; virtual ErrorType compute() override { @@ -456,7 +456,7 @@ struct TestJacobian : TestBxDF s = base_t::bxdf.generate(base_t::isointer, base_t::rc.u.xy); sx = base_t::bxdf.generate(base_t::isointer, ux.xy); sy = base_t::bxdf.generate(base_t::isointer, uy.xy); - params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); + params = params_t::create(s, base_t::isointer, bxdf::BCM_MAX); } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) { @@ -465,11 +465,11 @@ struct TestJacobian : TestBxDF sy = base_t::bxdf.generate(base_t::anisointer, uy.xy, dummy); if NBL_CONSTEXPR_FUNC (aniso) - params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); + params = params_t::create(s, base_t::anisointer, cache, bxdf::BCM_MAX); else { isocache = cache.iso_cache; - params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); + params = params_t::create(s, base_t::isointer, isocache, bxdf::BCM_MAX); } } if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) @@ -477,7 +477,7 @@ struct TestJacobian : TestBxDF s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u); sx = base_t::bxdf.generate(base_t::anisointer, ux); sy = base_t::bxdf.generate(base_t::anisointer, uy); - params = params_t::template create(s, base_t::isointer, bxdf::BCM_ABS); + params = params_t::create(s, base_t::isointer, bxdf::BCM_ABS); } if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) { @@ -486,11 +486,11 @@ struct TestJacobian : TestBxDF sy = base_t::bxdf.generate(base_t::anisointer, uy, dummy); if NBL_CONSTEXPR_FUNC (aniso) - params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); + params = params_t::create(s, base_t::anisointer, cache, bxdf::BCM_ABS); else { isocache = cache.iso_cache; - params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); + params = params_t::create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } } @@ -599,6 +599,7 @@ struct TestReciprocity : TestBxDF { using base_t = TestBxDFBase; using this_t = TestReciprocity; + using params_t = conditional_t; virtual ErrorType compute() override { @@ -608,35 +609,35 @@ struct TestReciprocity : TestBxDF if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy); - params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); + params = params_t::create(s, base_t::isointer, bxdf::BCM_MAX); } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u.xy, cache); if NBL_CONSTEXPR_FUNC (aniso) - params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); + params = params_t::create(s, base_t::anisointer, cache, bxdf::BCM_MAX); else { isocache = cache.iso_cache; - params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); + params = params_t::create(s, base_t::isointer, isocache, bxdf::BCM_MAX); } } if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u); - params = params_t::template create(s, base_t::isointer, bxdf::BCM_ABS); + params = params_t::create(s, base_t::isointer, bxdf::BCM_ABS); } if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) { s = base_t::bxdf.generate(base_t::anisointer, base_t::rc.u, cache); if NBL_CONSTEXPR_FUNC (aniso) - params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); + params = params_t::create(s, base_t::anisointer, cache, bxdf::BCM_ABS); else { isocache = cache.iso_cache; - params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); + params = params_t::create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } } @@ -667,27 +668,27 @@ struct TestReciprocity : TestBxDF rec_isocache = rec_cache.iso_cache; if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) - rec_params = params_t::template create(rec_s, rec_isointer, bxdf::BCM_MAX); + rec_params = params_t::create(rec_s, rec_isointer, bxdf::BCM_MAX); if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) { if NBL_CONSTEXPR_FUNC (aniso) - rec_params = params_t::template create(rec_s, rec_anisointer, rec_cache, bxdf::BCM_MAX); + rec_params = params_t::create(rec_s, rec_anisointer, rec_cache, bxdf::BCM_MAX); else { rec_isocache = rec_cache.iso_cache; - rec_params = params_t::template create(rec_s, rec_isointer, rec_isocache, bxdf::BCM_MAX); + rec_params = params_t::create(rec_s, rec_isointer, rec_isocache, bxdf::BCM_MAX); } } if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) - rec_params = params_t::template create(rec_s, rec_isointer, bxdf::BCM_ABS); + rec_params = params_t::create(rec_s, rec_isointer, bxdf::BCM_ABS); if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) { if NBL_CONSTEXPR_FUNC (aniso) - rec_params = params_t::template create(rec_s, rec_anisointer, rec_cache, bxdf::BCM_ABS); + rec_params = params_t::create(rec_s, rec_anisointer, rec_cache, bxdf::BCM_ABS); else { rec_isocache = rec_cache.iso_cache; - rec_params = params_t::template create(rec_s, rec_isointer, rec_isocache, bxdf::BCM_ABS); + rec_params = params_t::create(rec_s, rec_isointer, rec_isocache, bxdf::BCM_ABS); } } @@ -736,8 +737,8 @@ struct TestReciprocity : TestBxDF if (checkLt(bsdf, (float32_t3)0.0)) return BET_NEGATIVE_VAL; - float32_t3 a = bsdf * nbl::hlsl::abs(params.NdotV); - float32_t3 b = rec_bsdf * nbl::hlsl::abs(rec_params.NdotV); + float32_t3 a = bsdf * nbl::hlsl::abs(params.getNdotV()); + float32_t3 b = rec_bsdf * nbl::hlsl::abs(rec_params.getNdotV()); if (!(a == b)) // avoid division by 0 if (!checkEq(a, b, 1e-2)) return BET_RECIPROCITY; @@ -775,6 +776,7 @@ struct TestBucket : TestBxDF { using base_t = TestBxDFBase; using this_t = TestBucket; + using params_t = conditional_t; void clearBuckets() { @@ -813,35 +815,35 @@ struct TestBucket : TestBxDF if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) { s = base_t::bxdf.generate(base_t::anisointer, u.xy); - params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); + params = params_t::create(s, base_t::isointer, bxdf::BCM_MAX); } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) { s = base_t::bxdf.generate(base_t::anisointer, u.xy, cache); if NBL_CONSTEXPR_FUNC (aniso) - params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); + params = params_t::create(s, base_t::anisointer, cache, bxdf::BCM_MAX); else { isocache = cache.iso_cache; - params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); + params = params_t::create(s, base_t::isointer, isocache, bxdf::BCM_MAX); } } if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) { s = base_t::bxdf.generate(base_t::anisointer, u); - params = params_t::template create(s, base_t::isointer, bxdf::BCM_ABS); + params = params_t::create(s, base_t::isointer, bxdf::BCM_ABS); } if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) { s = base_t::bxdf.generate(base_t::anisointer, u, cache); if NBL_CONSTEXPR_FUNC (aniso) - params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); + params = params_t::create(s, base_t::anisointer, cache, bxdf::BCM_ABS); else { isocache = cache.iso_cache; - params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); + params = params_t::create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } } @@ -982,6 +984,7 @@ struct TestChi2 : TestBxDF { using base_t = TestBxDFBase; using this_t = TestChi2; + using params_t = conditional_t; void clearBuckets() { @@ -1207,34 +1210,34 @@ struct TestChi2 : TestBxDF params_t params; if NBL_CONSTEXPR_FUNC (is_basic_brdf_v) { - params = params_t::template create(s, base_t::isointer, bxdf::BCM_MAX); + params = params_t::create(s, base_t::isointer, bxdf::BCM_MAX); } if NBL_CONSTEXPR_FUNC (is_microfacet_brdf_v) { aniso_cache cache = aniso_cache::template createForReflection(base_t::anisointer, s); if NBL_CONSTEXPR_FUNC (aniso) - params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_MAX); + params = params_t::create(s, base_t::anisointer, cache, bxdf::BCM_MAX); else { iso_cache isocache = cache.iso_cache; - params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_MAX); + params = params_t::create(s, base_t::isointer, isocache, bxdf::BCM_MAX); } } if NBL_CONSTEXPR_FUNC (is_basic_bsdf_v) { - params = params_t::template create(s, base_t::isointer, bxdf::BCM_ABS); + params = params_t::create(s, base_t::isointer, bxdf::BCM_ABS); } if NBL_CONSTEXPR_FUNC (is_microfacet_bsdf_v) { aniso_cache cache = aniso_cache::template createForReflection(base_t::anisointer, s); if NBL_CONSTEXPR_FUNC (aniso) - params = params_t::template create(s, base_t::anisointer, cache, bxdf::BCM_ABS); + params = params_t::create(s, base_t::anisointer, cache, bxdf::BCM_ABS); else { iso_cache isocache = cache.iso_cache; - params = params_t::template create(s, base_t::isointer, isocache, bxdf::BCM_ABS); + params = params_t::create(s, base_t::isointer, isocache, bxdf::BCM_ABS); } }