Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
007f23e
chained scan initial commit w rough outline
keptsecret Jul 14, 2026
9604ca6
implement proper read/write with separate data accessor for workgroup
keptsecret Jul 15, 2026
4192826
use correct binop
keptsecret Jul 15, 2026
b132a2e
minor fix to creating wg accessor
keptsecret Jul 16, 2026
b46cad2
use a separate accessor type for reduction buf
keptsecret Jul 16, 2026
59219c5
fix some compilation bugs, still not running correct
keptsecret Jul 17, 2026
a056aeb
fix some bugs in chained scan, still need to add lookback fallback
keptsecret Jul 21, 2026
12b2d9b
lookback fallback to avoid spin
keptsecret Jul 21, 2026
068776e
implement atomic min and max
keptsecret Jul 22, 2026
747d35b
some bug fixes to atomic min/max
keptsecret Jul 22, 2026
972a8fb
a number of bug fixes to indexing stuff
keptsecret Jul 22, 2026
9085b5d
fix exclusive scan to reduction store
keptsecret Jul 22, 2026
3a59e93
use a workgroup counter to determine execution order
keptsecret Jul 23, 2026
25e2d01
fix for indexing in workgroup scan accessor (unsure if temp fix)
keptsecret Jul 27, 2026
ba9e151
fix lookback to spin a bit for some more consistency
keptsecret Jul 28, 2026
dd61813
can use single scratch address + fixes bug in example, memorybarrier …
keptsecret Jul 30, 2026
02d6966
fixes to indexing in preload
keptsecret Jul 30, 2026
833081c
Merge branch 'master' into device_chained_scan
keptsecret Jul 30, 2026
e5153a9
add chain scan hlsl to cmakelist
keptsecret Jul 30, 2026
fbf4b57
latest example
keptsecret Jul 30, 2026
c5b3031
concepts for accessors of device scan, removed obsolete comments
keptsecret Jul 31, 2026
12a8f56
latest example
keptsecret Jul 31, 2026
f1ad2fa
examples with latest master merge
keptsecret Oct 8, 2026
dc7bfa6
removed unnecessary workgroup barriers, added some clarifying comment…
keptsecret Oct 8, 2026
a94a8ca
add spirv atomic load/store ops
keptsecret Oct 9, 2026
ad803f3
use atomic store instead of exchange
keptsecret Oct 9, 2026
ba1466e
generalize the concepts for atomic accessors
keptsecret Oct 9, 2026
b07782f
add comment about ongoing issue with dxc for atomics ptr scope
keptsecret Oct 9, 2026
4cb1b2a
use binop identity to initialize prevReduction
keptsecret Oct 12, 2026
b9d550f
use spirv intrinsics directly for builtins and clean up glsl_compat u…
Erfan-Ahmadi Oct 22, 2026
f7d10b0
updated examples_tests
Erfan-Ahmadi Oct 22, 2026
8810a06
Merge branch 'master' into device_chained_scan
Erfan-Ahmadi Oct 22, 2026
1ea808d
comment about SubgroupContiguousIndex
Erfan-Ahmadi Oct 23, 2026
42c8a7d
explainer comments on subgroup2, todo for removing glsl:: dependency,…
Erfan-Ahmadi Oct 23, 2026
c8c42e3
Merge branch 'master' into device_chained_scan
keptsecret Oct 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions include/nbl/builtin/hlsl/bda/bda_accessor.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#ifndef _NBL_BUILTIN_HLSL_BDA_ACCESSOR_INCLUDED_
#define _NBL_BUILTIN_HLSL_BDA_ACCESSOR_INCLUDED_

#include "nbl/builtin/hlsl/glsl_compat/core.hlsl"
#include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl"
#include "nbl/builtin/hlsl/bda/__ptr.hlsl"

namespace nbl
Expand Down Expand Up @@ -66,15 +66,15 @@ struct BdaAccessor : impl::BdaAccessorBase
atomicAdd(const uint64_t index, const T value)
{
bda::__ptr<T> target = ptr + index;
return glsl::atomicAdd(target.template deref().ptr.value, value);
return spirv::atomicIAdd<T>(target.template deref().ptr.value, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}

template<typename S = T>
enable_if_t<is_same_v<S,T> && is_integral<T>::value && (sizeof(T) == 4 || sizeof(T) == 8), T>
atomicSub(const uint64_t index, const T value)
{
bda::__ptr<T> target = ptr + index;
return glsl::atomicSub(target.template deref().ptr.value, value);
return spirv::atomicISub<T>(target.template deref().ptr.value, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}

bda::__ptr<T> ptr;
Expand Down
2 changes: 1 addition & 1 deletion include/nbl/builtin/hlsl/bda/legacy_bda_accessor.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef _NBL_BUILTIN_HLSL_LEGACY_BDA_ACCESSOR_INCLUDED_
#define _NBL_BUILTIN_HLSL_LEGACY_BDA_ACCESSOR_INCLUDED_

#include "nbl/builtin/hlsl/glsl_compat/core.hlsl"
#include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl"
#include "nbl/builtin/hlsl/bda/__ptr.hlsl"


Expand Down
2 changes: 1 addition & 1 deletion include/nbl/builtin/hlsl/blit/default_blit.comp.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void main()
OutImgAccessor outImgA;
outImgA.descIx = pc.outputDescIx;

const uint16_t3 wgID = _static_cast<uint16_t3>(glsl::gl_WorkGroupID());
const uint16_t3 wgID = _static_cast<uint16_t3>(spirv::WorkgroupId);
const uint16_t3 baseCoord = pc.perWG.getOutputBaseCoord(wgID);
// TODO: If and when someone can be bothered, change the blit api to compile a pipeline per image dimension, maybe it will be faster
switch (pc.perWG.imageDim)
Expand Down
73 changes: 73 additions & 0 deletions include/nbl/builtin/hlsl/concepts/accessors/device_arithmetic.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#ifndef _NBL_BUILTIN_HLSL_CONCEPTS_ACCESSORS_DEVICE_ARITHMETIC_INCLUDED_
#define _NBL_BUILTIN_HLSL_CONCEPTS_ACCESSORS_DEVICE_ARITHMETIC_INCLUDED_

#include "nbl/builtin/hlsl/concepts/accessors/generic_shared_data.hlsl"

namespace nbl
{
namespace hlsl
{
namespace scan
{

#define NBL_CONCEPT_NAME GenericAtomicAccessor
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)
#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(V)
#define NBL_CONCEPT_PARAM_0 (accessor, T)
#define NBL_CONCEPT_PARAM_1 (val, V)
#define NBL_CONCEPT_PARAM_2 (index, uint64_t)
NBL_CONCEPT_BEGIN(3)
#define accessor NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0
#define val NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1
#define index NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2
NBL_CONCEPT_END(
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(concepts::accessors::GenericDataAccessor, T, V, uint64_t))
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((accessor.atomicStore(index, val)), is_same_v, void))
);
#undef val
#undef index
#undef accessor
#include <nbl/builtin/hlsl/concepts/__end.hlsl>

#define NBL_CONCEPT_NAME DeviceReductionsAccessor
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)(typename)
#define NBL_CONCEPT_TPLT_PRM_NAMES (T)(V)
#define NBL_CONCEPT_PARAM_0 (accessor, T)
#define NBL_CONCEPT_PARAM_1 (val, V)
#define NBL_CONCEPT_PARAM_2 (index, uint64_t)
NBL_CONCEPT_BEGIN(3)
#define accessor NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0
#define val NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1
#define index NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2
NBL_CONCEPT_END(
((NBL_CONCEPT_REQ_TYPE_ALIAS_CONCEPT)(GenericAtomicAccessor, T, V))
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((accessor.atomicMax(index, val)), is_same_v, V))
);
#undef val
#undef index
#undef accessor
#include <nbl/builtin/hlsl/concepts/__end.hlsl>

Comment on lines +32 to +50

@devshgraphicsprogramming devshgraphicsprogramming Aug 24, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we generalize more and hoist it out into a GenericAtomicAccessor (no arithmetic)

#define NBL_CONCEPT_NAME GenericAtomicArithmeticAccessor
#define NBL_CONCEPT_TPLT_PRM_KINDS (typename)
#define NBL_CONCEPT_TPLT_PRM_NAMES (T)
#define NBL_CONCEPT_PARAM_0 (accessor, T)
#define NBL_CONCEPT_PARAM_1 (val, uint32_t)
#define NBL_CONCEPT_PARAM_2 (index, uint64_t)
NBL_CONCEPT_BEGIN(3)
#define accessor NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_0
#define val NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_1
#define index NBL_CONCEPT_PARAM_T NBL_CONCEPT_PARAM_2
NBL_CONCEPT_END(
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((accessor.atomicAdd(index, val)), is_same_v, uint32_t))
);
#undef val
#undef index
#undef accessor
#include <nbl/builtin/hlsl/concepts/__end.hlsl>

}
}
}

#endif
1 change: 0 additions & 1 deletion include/nbl/builtin/hlsl/emulated/float64_t_impl.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <nbl/builtin/hlsl/cpp_compat.hlsl>
#include <nbl/builtin/hlsl/ieee754.hlsl>
#include <nbl/builtin/hlsl/algorithm.hlsl>
#include <nbl/builtin/hlsl/glsl_compat/core.hlsl>
#include <nbl/builtin/hlsl/tgmath.hlsl>

// TODO: when it will be possible, use this unions wherever they fit:
Expand Down
2 changes: 1 addition & 1 deletion include/nbl/builtin/hlsl/functional.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#define _NBL_BUILTIN_HLSL_FUNCTIONAL_INCLUDED_


#include "nbl/builtin/hlsl/glsl_compat/core.hlsl"
#include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl"
#include "nbl/builtin/hlsl/limits.hlsl"
#include "nbl/builtin/hlsl/concepts/vector.hlsl"
#include "nbl/builtin/hlsl/array_accessors.hlsl"
Expand Down
118 changes: 107 additions & 11 deletions include/nbl/builtin/hlsl/glsl_compat/core.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ namespace nbl
{
namespace hlsl
{
// TODO: rename this namespace to `glsl_compat`
// The functions in this namespace are meant for porting GLSL shaders with minimal changes.
// Many of them are also handy utilities (default scopes and memory semantics, signed/unsigned/float dispatch, 16-bit emulation,
// a C++ path) and get called all over the codebase because they are easier to use than the raw `spirv::` intrinsics.
// Avoid calling them from code that isn't a GLSL port; those utilities need a home outside the `glsl` namespace.
namespace glsl
{

Expand Down Expand Up @@ -125,16 +130,6 @@ enable_if_t<spirv::is_pointer_v<Ptr_T>, T> atomicXor(Ptr_T ptr, T value)
{
return spirv::atomicXor<T, Ptr_T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}
/* TODO: @Hazardu struct dispatchers like for `bitfieldExtract`
template<typename T>
T atomicMin(NBL_REF_ARG(T) ptr, T value)
{
}
template<typename T>
T atomicMax(NBL_REF_ARG(T) ptr, T value)
{
}
*/
// reference form: `ptr` is the variable itself, e.g. `buf[i]`, `bufferPtr.Get().member`, or a groupshared variable with `T` given explicitly
template<typename T>
T atomicExchange(NBL_REF_ARG(T) ptr, T value)
Expand All @@ -160,6 +155,100 @@ enable_if_t<spirv::is_pointer_v<Ptr_T>, T> atomicCompSwap(Ptr_T ptr, T comparato
return spirv::atomicCompareExchange<T, Ptr_T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, spv::MemorySemanticsMaskNone, value, comparator);
}

namespace impl
{
template<typename T NBL_STRUCT_CONSTRAINABLE>
struct atomicMin;

template<typename T>
NBL_PARTIAL_REQ_TOP(concepts::SignedIntegral<T>)
struct atomicMin<T NBL_PARTIAL_REQ_BOT(concepts::SignedIntegral<T>) >
{
static T __call(NBL_REF_ARG(T) ptr, T value)
{
return spirv::atomicSMin<T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}

template<typename Ptr_T> // DXC Workaround

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's best to say exactly what dxc issue we're working around and be more detailed in the comments. in case they fix it and we can upgrade our code.
I think it's something to do with passing groupshared or other address qualifiers here.

I have a question though.
These don't need to be cpp compatible, it's gpu specific, why are we using NBL_REF_ARG and both REQ_TOP and REQ_BOT (hlsl enable_if and c++20 requires). I think BOT is enough?


Side note:
Just putting it out there that I don't like TOP/BOT naming 😆 I'd prefer something along the lines of:

  • NBL_HOST_CONCEPT + NBL_DEVICE_CONCEPT or NBL_DEVICE_SFINAE. which is more clear

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These don't need to be cpp compatible, it's gpu specific, why are we using NBL_REF_ARG and both REQ_TOP and REQ_BOT (hlsl enable_if and c++20 requires). I think BOT is enough?

Because in C++20 you need the requires clause on the top, but enable_if workaround needs it in the bottom.

Thats the convention we already chose and if we were to change it we'd have to change a lot of other code as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a question though.
These don't need to be cpp compatible, it's gpu specific, why are we using NBL_REF_ARG and both REQ_TOP and REQ_BOT (hlsl enable_if and c++20 requires). I think BOT is enough?

you want to be forward compatible with C++20, because HLSL is going that way, also it keeps the code easy to port to CUDA and SYCL later on.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's best to say exactly what dxc issue we're working around and be more detailed in the comments. in case they fix it and we can upgrade our code.
I think it's something to do with passing groupshared or other address qualifiers here.

Yes @keptsecret please cite/link the DXC issue in the comments for stuff like that (git commit message too)

static T __call(Ptr_T ptr, T value)
{
return spirv::atomicSMin<T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}
};

template<typename T>
NBL_PARTIAL_REQ_TOP(concepts::UnsignedIntegral<T>)
struct atomicMin<T NBL_PARTIAL_REQ_BOT(concepts::UnsignedIntegral<T>) >
{
static T __call(NBL_REF_ARG(T) ptr, T value)
{
return spirv::atomicUMin<T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}

template<typename Ptr_T> // DXC Workaround
static T __call(Ptr_T ptr, T value)
{
return spirv::atomicUMin<T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}
};

template<typename T NBL_STRUCT_CONSTRAINABLE>
struct atomicMax;

template<typename T>
NBL_PARTIAL_REQ_TOP(concepts::SignedIntegral<T>)
struct atomicMax<T NBL_PARTIAL_REQ_BOT(concepts::SignedIntegral<T>) >
{
static T __call(NBL_REF_ARG(T) ptr, T value)
{
return spirv::atomicSMax<T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}

template<typename Ptr_T> // DXC Workaround
static T __call(Ptr_T ptr, T value)
{
return spirv::atomicSMax<T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}
};

template<typename T>
NBL_PARTIAL_REQ_TOP(concepts::UnsignedIntegral<T>)
struct atomicMax<T NBL_PARTIAL_REQ_BOT(concepts::UnsignedIntegral<T>) >
{
static T __call(NBL_REF_ARG(T) ptr, T value)
{
return spirv::atomicUMax<T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}

template<typename Ptr_T> // DXC Workaround
static T __call(Ptr_T ptr, T value)
{
return spirv::atomicUMax<T>(ptr, spv::ScopeDevice, spv::MemorySemanticsMaskNone, value);
}
};
}
Comment on lines +158 to +229

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we actually have a huge problem here and I think this is why I didn't pour that much effort into the GLSL compat functions

  1. You don't know the address space so don't know the scope to emit by default - comment at the top of the atomic code block
  2. memory semantics are always None

Ideally none of our code should be using the GLSL atomics because they're so bad and imprecise

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This atm just matches the memory semantics of the prior atomics.
So I suppose the examples will just use the spirv stuff directly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes let's use spirv ones directly and avoid these glsl compat function as much as possible.


template<typename T>
T atomicMin(NBL_REF_ARG(T) ptr, T value)
{
return impl::atomicMin<T>::__call(ptr, value);
}
template<typename T, typename Ptr_T> // DXC Workaround
enable_if_t<spirv::is_pointer_v<Ptr_T>, T> atomicMin(Ptr_T ptr, T value)
{
return impl::atomicMin<T>::template __call<Ptr_T>(ptr, value);
}
template<typename T>
T atomicMax(NBL_REF_ARG(T) ptr, T value)
{
return impl::atomicMax<T>::__call(ptr, value);
}
template<typename T, typename Ptr_T> // DXC Workaround
enable_if_t<spirv::is_pointer_v<Ptr_T>, T> atomicMax(Ptr_T ptr, T value)
{
return impl::atomicMax<T>::template __call<Ptr_T>(ptr, value);
}

/**
* GLSL extended math
*/
Expand Down Expand Up @@ -189,7 +278,11 @@ uint32_t gl_InstanceIndex() {return spirv::InstanceIndex;}

// TODO: Extemely annoying that HLSL doesn't have references, so we can't transparently alias the variables as `const&` :(
uint32_t3 gl_NumWorkGroups() {return spirv::NumWorkGroups;}
// TODO: DXC BUG prevents us from defining this!
// Not a DXC bug: SPIR-V only lets a shader declare its workgroup size, there is nothing to read back.
// `[numthreads]` emits the `LocalSize` execution mode, whose operands are literals that no instruction can reference.
// `LocalSizeId` and the `WorkgroupSize` builtin take ids instead, but those must be constants (`WorkgroupSize` on an input
// variable is invalid), so "reading" them just means reusing the constant that declared the size in the first place.
// Hence the user defines this, returning the same compile-time constant they pass to `[numthreads]`.
uint32_t3 gl_WorkGroupSize();
uint32_t3 gl_WorkGroupID() {return spirv::WorkgroupId;}
uint32_t3 gl_LocalInvocationID() {return spirv::LocalInvocationId;}
Expand Down Expand Up @@ -298,6 +391,8 @@ struct bitfieldExtract<T NBL_PARTIAL_REQ_BOT(concepts::UnsignedIntegral<typename
};
}

// TODO: `bitfieldInsert` and `bitfieldExtract` are used as general utilities outside GLSL ports (16-bit emulation, C++ path),
// they need a home outside the `glsl` namespace
template<typename T>
T bitfieldInsert(T base, T insert, uint32_t offset, uint32_t bits)
{
Expand Down Expand Up @@ -413,6 +508,7 @@ struct notEqual_helper<Vectorial NBL_PARTIAL_REQ_BOT(concepts::Vectorial<Vectori
#endif
}

// TODO: `equal` and `notEqual` are used as general utilities outside GLSL ports (C++ path), they need a home outside the `glsl` namespace
template<typename T>
inline vector<bool,vector_traits<T>::Dimension> equal(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y)
{
Expand Down
2 changes: 2 additions & 0 deletions include/nbl/builtin/hlsl/glsl_compat/subgroup_arithmetic.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace hlsl
namespace glsl
{

// TODO: these are used as general utilities outside GLSL ports (one name per operation for every type),
// they need a home outside the `glsl` namespace, see the note above `namespace glsl` in glsl_compat/core.hlsl
// TODO: @Hazardu this will need touching up in the impl when the `spirv::groupXXX` will change names to a predictable pattern from SPIR-V
// TODO: Furthermore you'll need `bitfieldExtract`-like struct dispatcher to choose between int/float add/mul and sint/uint/float min/max
template<typename T>
Expand Down
1 change: 1 addition & 0 deletions include/nbl/builtin/hlsl/glsl_compat/subgroup_basic.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace glsl
// TODO: Extemely annoying that HLSL doesn't have referencies, so we can't transparently alias the variables as `const&` :(
// NOTE: These are not `uint16_t` even though they could be, because IIUtSC they're `uint32_t` in SPIR-V
uint32_t gl_SubgroupSize() {return spirv::SubgroupSize;}
// TODO: not a GLSL builtin, move it out of the `glsl` namespace to a better place
uint32_t gl_SubgroupSizeLog2() {return firstbithigh(spirv::SubgroupSize);}
uint32_t gl_SubgroupInvocationID() {return spirv::SubgroupLocalInvocationId;}

Expand Down
1 change: 0 additions & 1 deletion include/nbl/builtin/hlsl/memory_accessor.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#ifndef _NBL_BUILTIN_HLSL_MEMORY_ACCESSOR_INCLUDED_
#define _NBL_BUILTIN_HLSL_MEMORY_ACCESSOR_INCLUDED_

#include "nbl/builtin/hlsl/glsl_compat/core.hlsl"
#include "nbl/builtin/hlsl/member_test_macros.hlsl"

// weird namespace placing, see the comment where the macro is defined
Expand Down
1 change: 0 additions & 1 deletion include/nbl/builtin/hlsl/prefix_sum_blur/blur.hlsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "nbl/builtin/hlsl/cpp_compat.hlsl"
#include "nbl/builtin/hlsl/glsl_compat/core.hlsl"
#include "nbl/builtin/hlsl/workgroup/basic.hlsl"
#include "nbl/builtin/hlsl/workgroup/arithmetic.hlsl"
#include "nbl/builtin/hlsl/device_capabilities_traits.hlsl"
Expand Down
Loading
Loading