-
Notifications
You must be signed in to change notification settings - Fork 67
RWMC #936
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: hlsl_path_tracer_example
Are you sure you want to change the base?
RWMC #936
Changes from all commits
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,100 @@ | ||
| #ifndef _NBL_HLSL_RWMC_CASCADE_ACCUMULATOR_INCLUDED_ | ||
| #define _NBL_HLSL_RWMC_CASCADE_ACCUMULATOR_INCLUDED_ | ||
| #include "nbl/builtin/hlsl/cpp_compat.hlsl" | ||
| #include <nbl/builtin/hlsl/vector_utils/vector_traits.hlsl> | ||
| #include <nbl/builtin/hlsl/colorspace/encodeCIEXYZ.hlsl> | ||
|
|
||
| namespace nbl | ||
| { | ||
| namespace hlsl | ||
| { | ||
| namespace rwmc | ||
| { | ||
|
|
||
| struct CascadeSettings | ||
| { | ||
| uint32_t size; | ||
| uint32_t start; | ||
| uint32_t base; | ||
|
Comment on lines
+16
to
+18
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 completely different members, see the old GLSL code Also put the structs in separate headers (so easier to share with C++ without sharing the accumulator and resolve):
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. moved structs to seperate headers 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. now my 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. ok i see #936 (comment) |
||
| }; | ||
|
|
||
| template<typename CascadeLayerType, uint32_t CascadeSize> | ||
|
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. require the 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. btw if you want we can nest this struct inside the |
||
| struct CascadeEntry | ||
| { | ||
| CascadeLayerType data[CascadeSize]; | ||
| }; | ||
|
|
||
| template<typename CascadeLayerType, uint32_t CascadeSize> | ||
| struct CascadeAccumulator | ||
| { | ||
| using output_storage_type = CascadeEntry<CascadeLayerType, CascadeSize>; | ||
| using initialization_data = CascadeSettings; | ||
| output_storage_type accumulation; | ||
| uint32_t cascadeSampleCounter[CascadeSize]; | ||
|
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. stick sample count into the 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. why? 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. because then you can have a method in Nobody is gonna store the On another note, maybe it would be best to do a CascadeAccessor and template the accumulator on that, because I may:
In either case this means that the current value and sample count are no longer members but accessed through templated (just to stop HLSL doing implicit type conversions) with |
||
| CascadeSettings cascadeSettings; | ||
|
Comment on lines
+16
to
+34
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 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 separate the aliases from member declarations (even better put member declarations at the bottom of struct) so its easier to read |
||
|
|
||
| void initialize(in CascadeSettings settings) | ||
|
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 use 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. idk i like 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. because Dead Code Elimination, one can call Also our convention is to use |
||
| { | ||
| for (int i = 0; i < CascadeSize; ++i) | ||
| { | ||
| accumulation.data[i] = (CascadeLayerType)0.0f; | ||
|
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.
|
||
| cascadeSampleCounter[i] = 0u; | ||
| } | ||
|
|
||
| cascadeSettings.size = settings.size; | ||
| cascadeSettings.start = settings.start; | ||
| cascadeSettings.base = settings.base; | ||
|
Comment on lines
+44
to
+46
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 don't need to assign member by member, struct to struct assignment works just fine |
||
| } | ||
|
|
||
| typename vector_traits<CascadeLayerType>::scalar_type getLuma(NBL_CONST_REF_ARG(CascadeLayerType) col) | ||
|
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. make a |
||
| { | ||
| return hlsl::dot<CascadeLayerType>(hlsl::transpose(colorspace::scRGBtoXYZ)[1], col); | ||
| } | ||
|
|
||
| // most of this code is stolen from https://cg.ivd.kit.edu/publications/2018/rwmc/tool/split.cpp | ||
| void addSample(uint32_t sampleIndex, float32_t3 sample) | ||
|
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 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 why |
||
| { | ||
| float lowerScale = cascadeSettings.start; | ||
| float upperScale = lowerScale * cascadeSettings.base; | ||
|
|
||
| const float luma = getLuma(sample); | ||
|
Comment on lines
+57
to
+60
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. instead of float use the alias https://github.com/Devsh-Graphics-Programming/Nabla/pull/936/files#r2473742745 for |
||
|
|
||
| uint32_t lowerCascadeIndex = 0u; | ||
| while (!(luma < upperScale) && lowerCascadeIndex < cascadeSettings.size - 2) | ||
| { | ||
| lowerScale = upperScale; | ||
| upperScale *= cascadeSettings.base; | ||
| ++lowerCascadeIndex; | ||
| } | ||
|
Comment on lines
+62
to
+68
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 can get the floating point cascade index by dealing with logarithms clamp((log2(luma) - log2(Start))*1.f/log2(Base), 0 , CascadeSize-1)this is why I say that the Splatting Parameters need to be precomputing different things, like |
||
|
|
||
| float lowerCascadeLevelWeight; | ||
| float higherCascadeLevelWeight; | ||
|
|
||
| if (luma <= lowerScale) | ||
| lowerCascadeLevelWeight = 1.0f; | ||
| else if (luma < upperScale) | ||
| lowerCascadeLevelWeight = max(0.0f, (lowerScale / luma - lowerScale / upperScale) / (1.0f - lowerScale / upperScale)); | ||
| else // Inf, NaN ... | ||
| lowerCascadeLevelWeight = 0.0f; | ||
|
Comment on lines
+62
to
+78
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 can get the floating point cascade index by dealing with logarithms const scalar_t log2Luma= log2<scalar_t>(luma);
const scalar_t cascade = max(log2Luma*1.f/log2(Base) - log2(Start)/log2(Base), 0, CascadeCount-1);
const scalar_t clampedCascade = clamp(cascade, 0, CascadeCount-1);
// c<=0 -> 0, c>=Count-1 -> Count-1
uint16_t lowerCascadeIndex = floor<scalar_t>(clampedCascade);
// 0 whenever clamped or `cascade` is integer (when `clampedCascade` is integer)
scalar_t higherCascadeWeight = cascade-floor<scalar_t>(clampedCascade);
// never 0 thanks to magic of `1-fract(x)`
scalar_t lowerCascadeWeight = scalar_type(1)-higherCascadeWeight;
// handle super bright sample case
if (cascade>CascadeCount-1)
lowerCascadeWeight = exp2(log2(Start)+log2(Base)*(CascadeCount-1)-log2Luma);
// only deal with splatting the higher cascade if you're not out of bound
// when out of bounds negatively, we use lower cascade as the only cascade (follow the math above)
if (clampedCascade==cascade) // equivalent condition is `higherCascadeWeight!=0`
{
const uint16_t higherCascadeIndex = lowerCascadeIndex+1;
// do stuff for higher cascade
}this is why I say that the Splatting Parameters need to be precomputing different things, like |
||
|
|
||
| if (luma < upperScale) | ||
| higherCascadeLevelWeight = max(0.0f, 1.0f - lowerCascadeLevelWeight); | ||
| else | ||
| higherCascadeLevelWeight = upperScale / luma; | ||
|
|
||
| uint32_t higherCascadeIndex = lowerCascadeIndex + 1u; | ||
|
|
||
| const uint32_t sampleCount = sampleIndex + 1u; | ||
|
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. take 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 don't get it 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 mean pass |
||
| const float reciprocalSampleCount = 1.0f / float(sampleCount); | ||
| accumulation.data[lowerCascadeIndex] += (sample * lowerCascadeLevelWeight - (sampleCount - (cascadeSampleCounter[lowerCascadeIndex])) * accumulation.data[lowerCascadeIndex]) * reciprocalSampleCount; | ||
| accumulation.data[higherCascadeIndex] += (sample * higherCascadeLevelWeight - (sampleCount - (cascadeSampleCounter[higherCascadeIndex])) * accumulation.data[higherCascadeIndex]) * reciprocalSampleCount; | ||
| cascadeSampleCounter[lowerCascadeIndex] = sampleCount; | ||
| cascadeSampleCounter[higherCascadeIndex] = sampleCount; | ||
|
Comment on lines
+89
to
+92
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 is really long in a line and reads badly, could be turned into a method you call per cascade. Also remove the extra 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 moved this code to another function for now. I'm not sure what kind of refactoring you have in mind — maybe we should discuss it later. |
||
| } | ||
| }; | ||
|
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| #ifndef _NBL_BUILTIN_HLSL_RWMC_RWMC_HLSL_INCLUDED_ | ||
| #define _NBL_BUILTIN_HLSL_RWMC_RWMC_HLSL_INCLUDED_ | ||
|
Comment on lines
+1
to
+2
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 header very clearly deals with Resolving, so call it |
||
|
|
||
| #include "nbl/builtin/hlsl/cpp_compat.hlsl" | ||
| #include <nbl/builtin/hlsl/colorspace/encodeCIEXYZ.hlsl> | ||
|
|
||
| namespace nbl | ||
| { | ||
| namespace hlsl | ||
| { | ||
| namespace rwmc | ||
| { | ||
| namespace impl | ||
| { | ||
|
|
||
| struct CascadeSample | ||
| { | ||
| float32_t3 centerValue; | ||
| float normalizedCenterLuma; | ||
| float normalizedNeighbourhoodAverageLuma; | ||
| }; | ||
|
|
||
| // TODO: figure out what values should pixels outside have, 0.0f is incorrect | ||
|
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. if you use accessors, you make it user-configurable, all that you can write is that MIRROR and CLAMP will falsely make similar neighbour pixels reducing RWMC effect on the border, while CLAMP_TO_BORDER (returning 0) will boost the RWMC effect because samples think they have more 0 neighbours You usually want vignetting, so what you're doing now (CLAMP_TO_BORDER with black border) is probably desirable 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. wirte it all in a comment |
||
| float32_t3 sampleCascadeTexel(int32_t2 currentCoord, int32_t2 offset, in RWTexture2DArray<float32_t4> cascade, uint32_t cascadeIndex) | ||
| { | ||
| const int32_t2 texelCoord = currentCoord + offset; | ||
| if (any(texelCoord < int32_t2(0, 0))) | ||
| return float32_t3(0.0f, 0.0f, 0.0f); | ||
|
Comment on lines
+27
to
+28
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 doesn't check for being out of bounds with |
||
|
|
||
| float32_t4 output = cascade.Load(int32_t3(texelCoord, int32_t(cascadeIndex))); | ||
| return float32_t3(output.r, output.g, output.b); | ||
| } | ||
|
Comment on lines
+23
to
+32
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 weird input textures, make this an Accessor Adaptor (does out of bound checks) which requires btw nothe that the names of the concepts need fixing https://github.com/Devsh-Graphics-Programming/Nabla/blob/aa5d6cb90b383e68b52c6abe69c6efe96281c7dd/include/nbl/builtin/hlsl/concepts/accessors/loadable_image.hlsl I copy pasted and they have 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. The |
||
|
|
||
| float32_t calcLuma(in float32_t3 col) | ||
| { | ||
| return hlsl::dot<float32_t3>(hlsl::transpose(colorspace::scRGBtoXYZ)[1], col); | ||
| } | ||
|
|
||
| CascadeSample SampleCascade(in int32_t2 coord, in RWTexture2DArray<float32_t4> cascade, in uint cascadeIndex, in float reciprocalBaseI) | ||
| { | ||
| float32_t3 neighbourhood[9]; | ||
| neighbourhood[0] = sampleCascadeTexel(coord, int32_t2(-1, -1), cascade, cascadeIndex); | ||
| neighbourhood[1] = sampleCascadeTexel(coord, int32_t2(0, -1), cascade, cascadeIndex); | ||
| neighbourhood[2] = sampleCascadeTexel(coord, int32_t2(1, -1), cascade, cascadeIndex); | ||
| neighbourhood[3] = sampleCascadeTexel(coord, int32_t2(-1, 0), cascade, cascadeIndex); | ||
| neighbourhood[4] = sampleCascadeTexel(coord, int32_t2(0, 0), cascade, cascadeIndex); | ||
| neighbourhood[5] = sampleCascadeTexel(coord, int32_t2(1, 0), cascade, cascadeIndex); | ||
| neighbourhood[6] = sampleCascadeTexel(coord, int32_t2(-1, 1), cascade, cascadeIndex); | ||
| neighbourhood[7] = sampleCascadeTexel(coord, int32_t2(0, 1), cascade, cascadeIndex); | ||
| neighbourhood[8] = sampleCascadeTexel(coord, int32_t2(1, 1), cascade, cascadeIndex); | ||
|
Comment on lines
+39
to
+50
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.
|
||
|
|
||
| // numerical robustness | ||
| float32_t3 excl_hood_sum = ((neighbourhood[0] + neighbourhood[1]) + (neighbourhood[2] + neighbourhood[3])) + | ||
| ((neighbourhood[5] + neighbourhood[6]) + (neighbourhood[7] + neighbourhood[8])); | ||
|
|
||
| CascadeSample retval; | ||
| retval.centerValue = neighbourhood[4]; | ||
| retval.normalizedNeighbourhoodAverageLuma = retval.normalizedCenterLuma = calcLuma(neighbourhood[4]) * reciprocalBaseI; | ||
| retval.normalizedNeighbourhoodAverageLuma = (calcLuma(excl_hood_sum) * reciprocalBaseI + retval.normalizedNeighbourhoodAverageLuma) / 9.f; | ||
| return retval; | ||
| } | ||
|
|
||
| } // namespace impl | ||
|
Comment on lines
+13
to
+63
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. instead of using an 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 roll it up into a 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. general note, you should allow using any |
||
|
|
||
| struct ReweightingParameters | ||
|
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. rename to 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 divide into two structs
and
so |
||
| { | ||
| uint32_t lastCascadeIndex; | ||
| float initialEmin; // a minimum image brightness that we always consider reliable | ||
| float reciprocalBase; | ||
| float reciprocalN; | ||
| float reciprocalKappa; | ||
| float colorReliabilityFactor; | ||
| float NOverKappa; | ||
| }; | ||
|
|
||
| ReweightingParameters computeReweightingParameters(float base, uint32_t sampleCount, float minReliableLuma, float kappa, uint32_t cascadeSize) | ||
| { | ||
| ReweightingParameters retval; | ||
| retval.lastCascadeIndex = cascadeSize - 1u; | ||
| retval.initialEmin = minReliableLuma; | ||
| retval.reciprocalBase = 1.f / base; | ||
| const float N = float(sampleCount); | ||
| retval.reciprocalN = 1.f / N; | ||
| retval.reciprocalKappa = 1.f / kappa; | ||
| // if not interested in exact expected value estimation (kappa!=1.f), can usually accept a bit more variance relative to the image brightness we already have | ||
| // allow up to ~<cascadeBase> more energy in one sample to lessen bias in some cases | ||
| retval.colorReliabilityFactor = base + (1.f - base) * retval.reciprocalKappa; | ||
| retval.NOverKappa = N * retval.reciprocalKappa; | ||
|
|
||
| return retval; | ||
| } | ||
|
|
||
| float32_t3 reweight(in ReweightingParameters params, in RWTexture2DArray<float32_t4> cascade, in int32_t2 coord) | ||
| { | ||
|
Comment on lines
+93
to
+94
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. make this into a Resolve struct templated on the Accessor you'll use instead of you |
||
| float reciprocalBaseI = 1.f; | ||
| impl::CascadeSample curr = impl::SampleCascade(coord, cascade, 0u, reciprocalBaseI); | ||
|
|
||
| float32_t3 accumulation = float32_t3(0.0f, 0.0f, 0.0f); | ||
|
Comment on lines
+95
to
+98
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. would be good to template everything on the vector type and its scalar |
||
| float Emin = params.initialEmin; | ||
|
|
||
| float prevNormalizedCenterLuma, prevNormalizedNeighbourhoodAverageLuma; | ||
| for (uint i = 0u; i <= params.lastCascadeIndex; i++) | ||
| { | ||
| const bool notFirstCascade = i != 0u; | ||
| const bool notLastCascade = i != params.lastCascadeIndex; | ||
|
|
||
| impl::CascadeSample next; | ||
| if (notLastCascade) | ||
| { | ||
| reciprocalBaseI *= params.reciprocalBase; | ||
| next = impl::SampleCascade(coord, cascade, i + 1u, reciprocalBaseI); | ||
| } | ||
|
|
||
| float reliability = 1.f; | ||
| // sample counting-based reliability estimation | ||
| if (params.reciprocalKappa <= 1.f) | ||
| { | ||
| float localReliability = curr.normalizedCenterLuma; | ||
| // reliability in 3x3 pixel block (see robustness) | ||
| float globalReliability = curr.normalizedNeighbourhoodAverageLuma; | ||
| if (notFirstCascade) | ||
| { | ||
| localReliability += prevNormalizedCenterLuma; | ||
| globalReliability += prevNormalizedNeighbourhoodAverageLuma; | ||
| } | ||
| if (notLastCascade) | ||
| { | ||
| localReliability += next.normalizedCenterLuma; | ||
| globalReliability += next.normalizedNeighbourhoodAverageLuma; | ||
| } | ||
| // check if above minimum sampling threshold (avg 9 sample occurences in 3x3 neighbourhood), then use per-pixel reliability (NOTE: tertiary op is in reverse) | ||
| reliability = globalReliability < params.reciprocalN ? globalReliability : localReliability; | ||
| { | ||
| const float accumLuma = impl::calcLuma(accumulation); | ||
| if (accumLuma > Emin) | ||
| Emin = accumLuma; | ||
|
|
||
| const float colorReliability = Emin * reciprocalBaseI * params.colorReliabilityFactor; | ||
|
|
||
| reliability += colorReliability; | ||
| reliability *= params.NOverKappa; | ||
| reliability -= params.reciprocalKappa; | ||
| reliability = clamp(reliability * 0.5f, 0.f, 1.f); | ||
| } | ||
| } | ||
| accumulation += curr.centerValue * reliability; | ||
|
|
||
| prevNormalizedCenterLuma = curr.normalizedCenterLuma; | ||
| prevNormalizedNeighbourhoodAverageLuma = curr.normalizedNeighbourhoodAverageLuma; | ||
| curr = next; | ||
| } | ||
|
|
||
| return accumulation; | ||
| } | ||
|
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -389,5 +389,8 @@ LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/tgmath/output_structs.hlsl") | |
| #blur | ||
| LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/prefix_sum_blur/blur.hlsl") | ||
| LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/prefix_sum_blur/box_sampler.hlsl") | ||
| #rwmc | ||
| LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/rwmc/rwmc.hlsl") | ||
| LIST_BUILTIN_RESOURCE(NBL_RESOURCES_TO_EMBED "hlsl/rwmc/CascadeAccumulator.hlsl") | ||
|
Comment on lines
+393
to
+394
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. need to separate parameter structs passed and initialized between c++ and HLSL from the HLSL algorithms for splatting and resolve, so more headers Chop it up! |
||
|
|
||
| ADD_CUSTOM_BUILTIN_RESOURCES(nblBuiltinResourceData NBL_RESOURCES_TO_EMBED "${NBL_ROOT_PATH}/include" "nbl/builtin" "nbl::builtin" "${NBL_ROOT_PATH_BINARY}/include" "${NBL_ROOT_PATH_BINARY}/src" "STATIC" "INTERNAL") | ||
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.
use
<>for HLSL includes in the Nabla headers (prioritizes looking in builtin DLL / most important search paths before doing anything local)