Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 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
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
65 changes: 65 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,65 @@
#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
{

template<typename T, typename V, typename I=uint32_t>
NBL_BOOL_CONCEPT ArithmeticSharedMemoryAccessor = concepts::accessors::GenericSharedMemoryAccessor<T,V,I>;

template<typename T, typename V, typename I=uint32_t>
NBL_BOOL_CONCEPT ArithmeticReadOnlyDataAccessor = concepts::accessors::GenericReadAccessor<T,V,I>;

template<typename T, typename V, typename I=uint32_t>
NBL_BOOL_CONCEPT ArithmeticDataAccessor = concepts::accessors::GenericDataAccessor<T,V,I>;

#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)(concepts::accessors::GenericDataAccessor, T, V, uint64_t))
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((accessor.atomicMax(index, val)), is_same_v, V))
((NBL_CONCEPT_REQ_EXPR_RET_TYPE)((accessor.atomicExchange(index, val)), is_same_v, V))
);
#undef val
#undef index
#undef accessor
#include <nbl/builtin/hlsl/concepts/__end.hlsl>

// TODO: as counter, maybe just increment 1 always?
#define NBL_CONCEPT_NAME WorkgroupCounterAccessor
#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
104 changes: 94 additions & 10 deletions include/nbl/builtin/hlsl/glsl_compat/core.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,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)
{
}
*/
template<typename T>
T atomicExchange(NBL_REF_ARG(T) ptr, T value)
{
Expand All @@ -147,6 +137,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
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);
}
};
}

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
Loading
Loading