-
Notifications
You must be signed in to change notification settings - Fork 70
Env map importance sampling #969
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
b99ae6e
b9537ea
a737173
64349db
e44fcf4
9b29dfd
06ae3e4
16ecb52
8d682b9
890f7c6
f99c63b
3ff2791
76ef536
ef773fd
b9467fe
3682604
ac1e2f3
baca1cf
f12b797
0957aed
1b35d34
665bb8d
b522b4f
3e51c69
c72d305
5ee2ce7
867868c
1a66157
d4b8105
8853738
6bde489
756fbb0
8d64a19
70d8423
2842d29
a51848c
58c9c13
fa94ac2
8494124
b273d87
3bc0e57
1dadf92
f19cbe9
fde2bba
81cae21
733a4ab
ba6be93
f04d98b
df2bfc3
4930e25
05b862a
d50b50f
1498094
39da42b
47799ab
0f69171
43b88ef
9aa3113
16c374e
126aa21
86a00f9
7509c83
833b388
ac63441
dacf493
a2b57f9
3343e64
834163a
94d1f14
23a7e12
e8930ef
de4807f
a158057
4dd4e1f
fe14c93
bb41942
6b87e69
9657c66
fe91d9a
48e16e3
1c7abcf
f05132d
08a7356
df8e8d7
150fac0
858dbe8
a977070
a2f2662
58abf25
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,314 @@ | ||
| // Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. | ||
| // This file is part of the "Nabla Engine". | ||
| // For conditions of distribution and use, see copyright notice in nabla.h | ||
|
|
||
| #ifndef _NBL_BUILTIN_HLSL_SAMPLING_HIERARCHICAL_IMAGE_INCLUDED_ | ||
| #define _NBL_BUILTIN_HLSL_SAMPLING_HIERARCHICAL_IMAGE_INCLUDED_ | ||
|
|
||
| #include <nbl/builtin/hlsl/concepts/accessors/loadable_image.hlsl> | ||
| #include <nbl/builtin/hlsl/sampling/basic.hlsl> | ||
| #include <nbl/builtin/hlsl/sampling/warp.hlsl> | ||
| #include <nbl/builtin/hlsl/sampling/hierarchical_image/accessors.hlsl> | ||
| #include <nbl/builtin/hlsl/cpp_compat/intrinsics.hlsl> | ||
|
|
||
| namespace nbl | ||
| { | ||
| namespace hlsl | ||
| { | ||
| namespace sampling | ||
| { | ||
|
|
||
| // TODO(kevinyu): Temporary struct before PR #1001 merged to master | ||
| template<typename V, typename P> | ||
| struct value_and_rcpPdf | ||
| { | ||
| using this_t = value_and_rcpPdf<V, P>; | ||
|
|
||
| static this_t create(const V _value, const P _rcpPdf) | ||
| { | ||
| this_t retval; | ||
| retval._value = _value; | ||
| retval._rcpPdf = _rcpPdf; | ||
| return retval; | ||
| } | ||
|
|
||
| V value() { return _value; } | ||
| P rcpPdf() { return _rcpPdf; } | ||
|
|
||
| V _value; | ||
| P _rcpPdf; | ||
| }; | ||
|
|
||
| template<typename V, typename P> | ||
| struct value_and_pdf | ||
| { | ||
| using this_t = value_and_pdf<V, P>; | ||
|
|
||
| static this_t create(const V _value, const P _pdf) | ||
| { | ||
| this_t retval; | ||
| retval._value = _value; | ||
| retval._pdf = _pdf; | ||
| return retval; | ||
| } | ||
|
|
||
| V value() { return _value; } | ||
| P pdf() { return _pdf; } | ||
|
|
||
| V _value; | ||
| P _pdf; | ||
| }; | ||
|
|
||
| // TODO: Add an option for corner sampling or centered sampling as boolean parameter | ||
| template <typename ScalarT, typename LuminanceAccessorT | ||
|
Comment on lines
+62
to
+63
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. adjust the comment, its the LuminanceAccessor that should tell you if you're supposed to corner sample (because the luma image needs to take that into account at the borders so it had to be made "that way") |
||
| NBL_PRIMARY_REQUIRES( | ||
| is_scalar_v<ScalarT> && | ||
| concepts::accessors::MipmappedLoadableImage<LuminanceAccessorT, ScalarT, 2, 1> | ||
| ) | ||
| struct HierarchicalWarpGenerator | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since thanks to PR #1001 warps will be indistinguishable from |
||
| { | ||
| using scalar_type = ScalarT; | ||
| using vector2_type = vector<scalar_type, 2>; | ||
| using vector4_type = vector<scalar_type, 4>; | ||
| using domain_type = vector2_type; | ||
| using codomain_type = vector2_type; | ||
| using sample_type = value_and_pdf<codomain_type, scalar_type>; | ||
| using density_type = scalar_type; | ||
|
|
||
| LuminanceAccessorT _map; | ||
| uint16_t2 _mapSize; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you shold really store |
||
| uint16_t _layerIndex; | ||
| uint16_t _lastMipLevel : 15; | ||
| uint16_t _aspect2x1 : 1; | ||
|
|
||
| static HierarchicalWarpGenerator<ScalarT, LuminanceAccessorT> create(NBL_CONST_REF_ARG(LuminanceAccessorT) lumaMap, uint16_t2 mapSize, uint16_t layerIndex) | ||
| { | ||
| HierarchicalWarpGenerator<ScalarT, LuminanceAccessorT> result; | ||
| result._map = lumaMap; | ||
| result._mapSize = mapSize; | ||
| result._layerIndex = layerIndex; | ||
| // Note: We use mapSize.y here because the currently the map aspect ratio can only be 1x1 or 2x1 | ||
| result._lastMipLevel = _static_cast<uint16_t>(findMSB(_static_cast<uint32_t>(mapSize.y))); | ||
| result._aspect2x1 = mapSize.x != mapSize.y; | ||
| return result; | ||
| } | ||
|
|
||
| static bool __choseSecond(scalar_type first, scalar_type second, NBL_REF_ARG(scalar_type) xi, NBL_REF_ARG(scalar_type) rcpPmf) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| // numerical resilience against IEEE754 | ||
| scalar_type rcpChoiceProb = scalar_type(0); | ||
| PartitionRandVariable<scalar_type> partition; | ||
| partition.leftProb = scalar_type(1) / (scalar_type(1) + (second / first)); | ||
| bool choseSecond = partition(xi, rcpChoiceProb); | ||
| rcpPmf *= rcpChoiceProb; | ||
| return choseSecond; | ||
| } | ||
|
|
||
| // Cannot use textureGather since we need to pass the mipLevel | ||
| vector4_type __texelGather(uint16_t2 coord, uint16_t level) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| assert(coord.x < _mapSize.x - 1 && coord.y < _mapSize.y - 1); | ||
| vector<scalar_type, 1> p0, p1, p2, p3; | ||
| _map.get(p0, coord + uint16_t2(0, 1), _layerIndex, level); | ||
| _map.get(p1, coord + uint16_t2(1, 1), _layerIndex, level); | ||
| _map.get(p2, coord + uint16_t2(1, 0), _layerIndex, level); | ||
| _map.get(p3, coord + uint16_t2(0, 0), _layerIndex, level); | ||
| return vector4_type(p0, p1, p2, p3); | ||
| } | ||
|
|
||
| sample_type generate(vector2_type xi) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| uint16_t2 p = uint16_t2(0, 0); | ||
|
|
||
| scalar_type rcpPmf = 1; | ||
| if (_aspect2x1) { | ||
| vector<scalar_type, 1> p0, p1; | ||
| // do one split in the X axis first cause penultimate full mip would have been 2x1 | ||
| _map.get(p0, uint16_t2(0, 0), _layerIndex, _lastMipLevel); | ||
| _map.get(p1, uint16_t2(1, 0), _layerIndex, _lastMipLevel); | ||
| p.x = __choseSecond(p0.x, p1, xi.x, rcpPmf) ? 1 : 0; | ||
| } | ||
|
|
||
| for (int i = _lastMipLevel - 1; i >= 0; i--) | ||
| { | ||
| p <<= 1; | ||
| const vector4_type values = __texelGather(p, i); | ||
| scalar_type wx_0, wx_1; | ||
| { | ||
| const scalar_type wy_0 = values[3] + values[2]; | ||
| const scalar_type wy_1 = values[1] + values[0]; | ||
| if (__choseSecond(wy_0, wy_1, xi.y, rcpPmf)) | ||
| { | ||
| p.y |= 1; | ||
| wx_0 = values[0]; | ||
| wx_1 = values[1]; | ||
| } | ||
| else | ||
| { | ||
| wx_0 = values[3]; | ||
| wx_1 = values[2]; | ||
| } | ||
| } | ||
| if (__choseSecond(wx_0, wx_1, xi.x, rcpPmf)) | ||
| p.x |= 1; | ||
| } | ||
|
|
||
|
|
||
| // If we don`t add xi, the sample will clump to the lowest corner of environment map texel. Each time we call PartitionRandVariable(), the output xi is the new xi that determines how left and right(or top and bottom for y axis) to choose the child partition. It means that if for some input xi, the output xi = 0, then the input xi is the edge of choosing this partition and the previous partition, and vice versa, if output xi = 1, then the input xi is the edge of choosing this partition and the next partition. Hence, by adding xi to the lower corner of the texel, we create a gradual transition from one pixel to another. Without adding output xi, the calculation of jacobian using the difference of sample value would not work. | ||
| // Since we want to do corner sampling. We have to handle edge texels as corner cases. Remember, in corner sampling we map uv [0,1] to [center of first texel, center of last texel]. So when p is an edge texel, we have to remap xi. [0.5, 1] when p == 0, and [0.5, 1] when p == length - 1. | ||
| if (p.x == 0) | ||
| xi.x = xi.x * scalar_type(0.5) + scalar_type(0.5); | ||
| if (p.y == 0) | ||
| xi.y = xi.y * scalar_type(0.5) + scalar_type(0.5); | ||
| if (p.x == _mapSize.x - 1) | ||
| xi.x = xi.x * scalar_type(0.5); | ||
| if (p.y == _mapSize.y - 1) | ||
| xi.y = xi.y * scalar_type(0.5); | ||
|
|
||
| const vector2_type directionUV = (vector2_type(p.x, p.y) + xi) / _mapSize; | ||
|
Comment on lines
+159
to
+168
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there's a bit of a problem with what you're returning (corner sampled) because the PostWarp is resolution agnostic, it doesn't know about corner sampling and expects a So I'd divide by
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also means that you return |
||
| return sample_type::create(directionUV, (_mapSize.x * _mapSize.y) / rcpPmf); | ||
| } | ||
|
|
||
| density_type forwardPdf(domain_type xi) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| return generate(xi).pdf(); | ||
| } | ||
|
Comment on lines
+172
to
+175
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PR #1001 lets you pass a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and you'll be able to stuff Edit: taking into account https://github.com/Devsh-Graphics-Programming/Nabla/pull/969/changes#r2991807597 it would be |
||
|
|
||
| // Doesn't comply with sampler concept. This class is extracted so can be used on warpmap generation without passing in unnecessary information like avgLuma. So, need to pass in avgLuma when calculating backwardPdf. | ||
| density_type backwardPdf(codomain_type codomainVal, scalar_type rcpAvgLuma) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| return _map.load(codomainVal) * rcpAvgLuma; | ||
|
Comment on lines
+178
to
+180
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but you already have a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also you need to use the const uint16_t2 coord = codomainVal*vector2_type(_lastTexel) + promote<vector2_type>(0.5); |
||
| } | ||
|
|
||
| }; | ||
|
|
||
| template <typename ScalarT, typename LuminanceAccessorT, typename PostWarpT | ||
| NBL_PRIMARY_REQUIRES( | ||
| is_scalar_v<ScalarT> && | ||
| concepts::accessors::MipmappedLoadableImage<LuminanceAccessorT, ScalarT, 2, 1> && | ||
| concepts::Warp<PostWarpT> | ||
| ) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when #1001 gets merged, this sampler will be a and your PostWarpT will be required to meet |
||
| struct HierarchicalWarpSampler | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just call it |
||
| { | ||
| using warp_generator_type = HierarchicalWarpGenerator<ScalarT, LuminanceAccessorT>; | ||
| using warp_sample_type = typename warp_generator_type::sample_type; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could just assert that your |
||
| using scalar_type = ScalarT; | ||
| using density_type = scalar_type; | ||
| using vector2_type = vector<scalar_type, 2>; | ||
| using vector3_type = vector<scalar_type, 3>; | ||
| using vector4_type = vector<scalar_type, 4>; | ||
| using domain_type = vector2_type; | ||
| using codomain_type = vector3_type; | ||
|
Comment on lines
+200
to
+201
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| using sample_type = value_and_pdf<codomain_type, density_type>; | ||
|
|
||
| warp_generator_type _warpGenerator; | ||
| scalar_type _rcpAvgLuma; | ||
|
|
||
| static HierarchicalWarpSampler<ScalarT, LuminanceAccessorT, PostWarpT> create(NBL_CONST_REF_ARG(LuminanceAccessorT) lumaMap, scalar_type avgLuma, uint16_t2 mapSize, uint16_t layerIndex) | ||
| { | ||
| HierarchicalWarpSampler result; | ||
| result._warpGenerator = warp_generator_type::create(lumaMap, mapSize, layerIndex); | ||
| result._rcpAvgLuma = scalar_type(1.0) / avgLuma; | ||
| return result; | ||
| } | ||
|
|
||
| sample_type generate(domain_type xi) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| const warp_sample_type warpSample = _warpGenerator.generate(xi); | ||
| const WarpResult<codomain_type> postWarpResult = PostWarpT::warp(warpSample.value()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you need to store a |
||
| return sample_type::create(postWarpResult.dst, postWarpResult.density * warpSample.pdf()); | ||
| } | ||
|
|
||
| density_type forwardPdf(domain_type xi) NBL_CONST_MEMBER_FUNC | ||
|
Comment on lines
+215
to
+222
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when #1001 comes, you'll need to put into this struct's cache:
|
||
| { | ||
| const warp_sample_type warpSample = _warpGenerator.generate(xi); | ||
| return PostWarpT::forwardDensity(warpSample.value()) * warpSample.pdf(); | ||
| } | ||
|
|
||
| density_type backwardPdf(codomain_type codomainVal) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| return PostWarpT::backwardPdf(codomainVal, _rcpAvgLuma) * _warpGenerator.backwardPdf(codomainVal); | ||
| } | ||
|
Comment on lines
+228
to
+231
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does your test even compile, its the anyway neither should care.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anyway the function is wrong, because you'd need to call |
||
|
|
||
| }; | ||
|
|
||
|
|
||
| template <typename ScalarT, typename LuminanceAccessorT, typename HierarchicalSamplerT, typename PostWarpT | ||
| NBL_PRIMARY_REQUIRES(is_scalar_v<ScalarT> && | ||
| concepts::accessors::GenericReadAccessor<LuminanceAccessorT, ScalarT, float32_t2> && | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use LuminanceRead accessor, and add a |
||
| hierarchical_image::WarpAccessor<HierarchicalSamplerT, ScalarT> && | ||
| concepts::Warp<PostWarpT>) | ||
|
Comment on lines
+236
to
+240
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can pretty much just template on
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wait, but your |
||
| struct WarpmapSampler | ||
| { | ||
| using scalar_type = ScalarT; | ||
| using vector2_type = vector<ScalarT, 2>; | ||
| using vector3_type = vector<ScalarT, 3>; | ||
| using vector4_type = vector<ScalarT, 4>; | ||
| using domain_type = vector2_type; | ||
| using codomain_type = vector3_type; | ||
|
Comment on lines
+247
to
+248
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as with the |
||
| using weight_type = scalar_type; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. after PR1001 you'll also need a |
||
| using sample_type = value_and_pdf<codomain_type, weight_type>; | ||
|
|
||
| LuminanceAccessorT _lumaMap; | ||
| HierarchicalSamplerT _warpMap; | ||
| uint32_t _effectiveWarpArea; | ||
| scalar_type _rcpAvgLuma; | ||
|
|
||
| static WarpmapSampler create(NBL_CONST_REF_ARG(LuminanceAccessorT) lumaMap, NBL_CONST_REF_ARG(HierarchicalSamplerT) warpMap, uint16_t2 warpSize, scalar_type avgLuma) | ||
| { | ||
| WarpmapSampler<ScalarT, LuminanceAccessorT, HierarchicalSamplerT, PostWarpT> result; | ||
| result._lumaMap = lumaMap; | ||
| result._warpMap = warpMap; | ||
| result._effectiveWarpArea = (warpSize.x - 1) * (warpSize.y - 1); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also store |
||
| result._rcpAvgLuma = ScalarT(1.0) / avgLuma; | ||
| return result; | ||
| } | ||
|
|
||
| weight_type forwardWeight(domain_type xi) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| return generate(xi).value(); | ||
| } | ||
|
|
||
| weight_type backwardWeight(codomain_type direction) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| vector2_type envmapUv = PostWarpT::inverseWarp(direction); | ||
| scalar_type luma; | ||
| _lumaMap.get(envmapUv, luma); | ||
| return luma * _rcpAvgLuma * PostWarpT::backwardDensity(direction); | ||
| } | ||
|
Comment on lines
+267
to
+278
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no the forward and backward weights need to be identical, so:
|
||
|
|
||
| sample_type generate(vector2_type xi) NBL_CONST_MEMBER_FUNC | ||
| { | ||
| const vector2_type interpolant; | ||
| matrix<scalar_type, 4, 2> uvs; | ||
| _warpMap.gatherUv(xi, uvs, interpolant); | ||
|
Comment on lines
+282
to
+284
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you know the warp size, make it your job to compute the interpolant and apply corner sampling, so you give the Lesss code for user to write and get wrong, see https://github.com/Devsh-Graphics-Programming/Nabla-Examples-and-Tests/pull/257/changes#r2991829432 |
||
|
|
||
| const vector2_type xDiffs[] = { | ||
| uvs[2] - uvs[3], | ||
| uvs[1] - uvs[0] | ||
| }; | ||
| const vector2_type yVals[] = { | ||
| xDiffs[0] * interpolant.x + uvs[3], | ||
| xDiffs[1] * interpolant.x + uvs[0] | ||
| }; | ||
| const vector2_type yDiff = yVals[1] - yVals[0]; | ||
| vector2_type uv = yDiff * interpolant.y + yVals[0]; | ||
|
|
||
| const WarpResult<vector3_type> warpResult = PostWarpT::warp(uv); | ||
|
|
||
| const scalar_type detInterpolJacobian = determinant(matrix<scalar_type, 2, 2>( | ||
| lerp(xDiffs[0], xDiffs[1], interpolant.y), // first column dFdx | ||
| yDiff // second column dFdy | ||
| )) * _effectiveWarpArea; | ||
|
|
||
| const scalar_type pdf = abs(warpResult.density / detInterpolJacobian); | ||
|
Comment on lines
+299
to
+304
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also the |
||
|
|
||
| return sample_type::create(warpResult.dst, pdf); | ||
| } | ||
| }; | ||
|
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| #ifndef _NBL_BUILTIN_HLSL_HIERARCHICAL_IMAGE_ACCESSORS_INCLUDED_ | ||
| #define _NBL_BUILTIN_HLSL_CONCEPTS_ACCESSORS_HIERARCHICAL_IMAGE_INCLUDED_ | ||
|
|
||
| #include "nbl/builtin/hlsl/concepts/accessors/generic_shared_data.hlsl" | ||
|
|
||
| namespace nbl | ||
| { | ||
| namespace hlsl | ||
| { | ||
| namespace sampling | ||
| { | ||
| namespace hierarchical_image | ||
| { | ||
|
|
||
| // gatherUvs return 4 UVs in a square for manual bilinear interpolation with differentiability | ||
| // declare concept | ||
| #define NBL_CONCEPT_NAME WarpAccessor | ||
| #define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename) | ||
| #define NBL_CONCEPT_TPLT_PRM_NAMES (WarpAccessorT)(ScalarT) | ||
| // not the greatest syntax but works | ||
| #define NBL_CONCEPT_PARAM_0 (accessor,WarpAccessorT) | ||
| #define NBL_CONCEPT_PARAM_1 (coord,vector<uint32_t, 2>) | ||
| #define NBL_CONCEPT_PARAM_2 (val, matrix<ScalarT, 4, 2>) | ||
| #define NBL_CONCEPT_PARAM_3 (interpolant, vector<ScalarT, 2>) | ||
| // start concept | ||
| NBL_CONCEPT_BEGIN(4) | ||
| // need to be defined AFTER the concept begins | ||
| #define accessor NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0 | ||
| #define coord NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1 | ||
| #define val NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2 | ||
| #define interpolant NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_3 | ||
| NBL_CONCEPT_END( | ||
| ((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((accessor.gatherUv(coord, val, interpolant)), ::nbl::hlsl::is_same_v, void)) | ||
| ); | ||
| #undef accessor | ||
| #undef coord | ||
| #undef val | ||
| #undef interpolant | ||
| #include <nbl/builtin/hlsl/concepts/__end.hlsl> | ||
|
|
||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually PR #1027 will have the replacements for these