Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5d6322a
created a structured like fft
CrabExtra Oct 2, 2025
264650c
config question
CrabExtra Oct 2, 2025
268949e
subgroupsort
CrabExtra Oct 5, 2025
73aa820
added bitonic_sort name space
CrabExtra Oct 5, 2025
dcb5e6e
Merge branch 'Devsh-Graphics-Programming:master' into master
CrabExtra Oct 7, 2025
b84a4bd
subgroup changes
CrabExtra Oct 7, 2025
779815e
removed unused
CrabExtra Oct 7, 2025
78a307a
Merge branch 'master' of https://github.com/CrabExtra/Nabla
CrabExtra Oct 7, 2025
ad7a4c5
added last merge step as a function
CrabExtra Oct 19, 2025
b80283a
uncomplete workgroup fn
CrabExtra Oct 19, 2025
7c91744
complete the logic for some pr questions
CrabExtra Oct 19, 2025
4d253f3
Refactor bitonic sort for workgroup + Accessor support
CrabExtra Oct 22, 2025
f03b8b2
Update bitonic_sort.hlsl
CrabExtra Oct 22, 2025
555dcbe
VT implumentation
CrabExtra Oct 27, 2025
0eb301e
Update bitonic_sort.hlsl
CrabExtra Oct 29, 2025
52a7cb8
Update common.hlsl
CrabExtra Oct 29, 2025
0b60d0c
Update bitonic_sort.hlsl
CrabExtra Oct 29, 2025
cbfa188
Update common.hlsl
CrabExtra Nov 2, 2025
0de0167
Update bitonic_sort.hlsl
CrabExtra Nov 2, 2025
1b1ba15
Update CMakeLists.txt
CrabExtra Nov 2, 2025
a20ba6e
pair added
CrabExtra Nov 2, 2025
8c7b7e5
comment outdated pair impl
CrabExtra Nov 2, 2025
06af50b
bitonic sort acessor added
CrabExtra Nov 2, 2025
ecb7182
Update common.hlsl
CrabExtra Nov 5, 2025
08867d6
Update bitonic_sort.hlsl
CrabExtra Nov 5, 2025
e2937ce
Update bitonic_sort.hlsl
CrabExtra Nov 5, 2025
686618c
Update utility.hlsl
CrabExtra Nov 5, 2025
c8e990d
Delete include/nbl/builtin/hlsl/utility.hlsl
CrabExtra Nov 5, 2025
55b7813
Delete include/nbl/builtin/hlsl/pair.hlsl
CrabExtra Nov 5, 2025
d0cd7a3
Add files via upload
CrabExtra Nov 5, 2025
e8f6134
Update CMakeLists.txt
CrabExtra Nov 5, 2025
034cd33
Remove unused pair struct from memory_accessor.hlsl
CrabExtra Nov 5, 2025
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
53 changes: 53 additions & 0 deletions include/nbl/builtin/hlsl/bitonic_sort/common.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#ifndef _NBL_BUILTIN_HLSL_BITONIC_SORT_COMMON_INCLUDED_
#define _NBL_BUILTIN_HLSL_BITONIC_SORT_COMMON_INCLUDED_

#include <nbl/builtin/hlsl/cpp_compat.hlsl>
#include <nbl/builtin/hlsl/concepts.hlsl>
#include <nbl/builtin/hlsl/math/intutil.hlsl>
#include <nbl/builtin/hlsl/utility.hlsl>

namespace nbl
{
namespace hlsl
{
namespace bitonic_sort
{

template<typename KeyType, typename ValueType, typename Comparator>
void compareExchangeWithPartner(
bool takeLarger,
NBL_REF_ARG(pair<KeyType, ValueType>) loPair,
NBL_CONST_REF_ARG(pair<KeyType, ValueType>) partnerLoPair,
NBL_REF_ARG(pair<KeyType, ValueType>) hiPair,
NBL_CONST_REF_ARG(pair<KeyType, ValueType>) partnerHiPair,
NBL_CONST_REF_ARG(Comparator) comp)
{
const bool loSelfSmaller = comp(loPair.first, partnerLoPair.first);
const bool takePartnerLo = takeLarger ? loSelfSmaller : !loSelfSmaller;
if (takePartnerLo)
loPair = partnerLoPair;

const bool hiSelfSmaller = comp(hiPair.first, partnerHiPair.first);
const bool takePartnerHi = takeLarger ? hiSelfSmaller : !hiSelfSmaller;
if (takePartnerHi)
hiPair = partnerHiPair;
}

template<typename KeyType, typename ValueType, typename Comparator>
void compareSwap(
bool ascending,
NBL_REF_ARG(pair<KeyType, ValueType>) loPair,
NBL_REF_ARG(pair<KeyType, ValueType>) hiPair,
NBL_CONST_REF_ARG(Comparator) comp)
{
const bool shouldSwap = comp(hiPair.first, loPair.first);
const bool doSwap = (shouldSwap == ascending);

if (doSwap)
swap(loPair, hiPair);
}
}
}
}

#endif
31 changes: 31 additions & 0 deletions include/nbl/builtin/hlsl/concepts/accessors/bitonic_sort.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef _NBL_BUILTIN_HLSL_CONCEPTS_ACCESSORS_BITONIC_SORT_INCLUDED_
#define _NBL_BUILTIN_HLSL_CONCEPTS_ACCESSORS_BITONIC_SORT_INCLUDED_

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

namespace nbl
{
namespace hlsl
{
namespace workgroup
{
namespace bitonic_sort
{
// The SharedMemoryAccessor MUST provide the following methods:
// * void get(uint32_t index, NBL_REF_ARG(uint32_t) value);
// * void set(uint32_t index, in uint32_t value);
// * void workgroupExecutionAndMemoryBarrier();
template<typename T, typename V = uint32_t, typename I = uint32_t>
NBL_BOOL_CONCEPT BitonicSortSharedMemoryAccessor = concepts::accessors::GenericSharedMemoryAccessor<T, V, I>;

// The Accessor MUST provide the following methods:
// * void get(uint32_t index, NBL_REF_ARG(pair<KeyType, ValueType>) value);
// * void set(uint32_t index, in pair<KeyType, ValueType> value);
template<typename T, typename KeyType, typename ValueType, typename I = uint32_t>
NBL_BOOL_CONCEPT BitonicSortAccessor = concepts::accessors::GenericDataAccessor<T, pair<KeyType, ValueType>, I>;

}
}
}
}
#endif
14 changes: 1 addition & 13 deletions include/nbl/builtin/hlsl/memory_accessor.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,6 @@ namespace nbl
{
namespace hlsl
{

// TODO: flesh out and move to `nbl/builtin/hlsl/utility.hlsl`
template<typename T1, typename T2>
struct pair
{
using first_type = T1;
using second_type = T2;

first_type first;
second_type second;
};

namespace accessor_adaptors
{
namespace impl
Expand Down Expand Up @@ -227,4 +215,4 @@ struct Offset : impl::OffsetBase<IndexType,_Offset>
}
}
}
#endif
#endif
83 changes: 83 additions & 0 deletions include/nbl/builtin/hlsl/subgroup/bitonic_sort.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#ifndef NBL_BUILTIN_HLSL_SUBGROUP_BITONIC_SORT_INCLUDED
#define NBL_BUILTIN_HLSL_SUBGROUP_BITONIC_SORT_INCLUDED
#include "nbl/builtin/hlsl/bitonic_sort/common.hlsl"
#include "nbl/builtin/hlsl/glsl_compat/subgroup_basic.hlsl"
#include "nbl/builtin/hlsl/glsl_compat/subgroup_shuffle.hlsl"
#include "nbl/builtin/hlsl/functional.hlsl"
namespace nbl
{
namespace hlsl
{
namespace subgroup
{

template<typename KeyType, typename ValueType, typename Comparator = less<KeyType> >
struct bitonic_sort_config
{
using key_t = KeyType;
using value_t = ValueType;
using comparator_t = Comparator;
};

template<typename Config, class device_capabilities = void>
struct bitonic_sort;

template<typename KeyType, typename ValueType, typename Comparator, class device_capabilities>
struct bitonic_sort<bitonic_sort_config<KeyType, ValueType, Comparator>, device_capabilities>
{
using config_t = bitonic_sort_config<KeyType, ValueType, Comparator>;
using key_t = typename config_t::key_t;
using value_t = typename config_t::value_t;
using comparator_t = typename config_t::comparator_t;

static void mergeStage(uint32_t stage, bool bitonicAscending, uint32_t invocationID,
NBL_REF_ARG(pair<key_t, value_t>) loPair, NBL_REF_ARG(pair<key_t, value_t>) hiPair)
{
comparator_t comp;

[unroll]
for (uint32_t pass = 0; pass <= stage; pass++)
{
const uint32_t stride = 1u << (stage - pass); // Element stride
const uint32_t threadStride = stride >> 1;
if (threadStride == 0)
{
// Local compare and swap for stage 0
nbl::hlsl::bitonic_sort::compareSwap(bitonicAscending, loPair, hiPair, comp);
}
else
{
// Shuffle from partner using XOR
const key_t pLoKey = glsl::subgroupShuffleXor<key_t>(loPair.first, threadStride);
const value_t pLoVal = glsl::subgroupShuffleXor<value_t>(loPair.second, threadStride);
const key_t pHiKey = glsl::subgroupShuffleXor<key_t>(hiPair.first, threadStride);
const value_t pHiVal = glsl::subgroupShuffleXor<value_t>(hiPair.second, threadStride);

const pair<key_t, value_t> partnerLoPair = make_pair(pLoKey, pLoVal);
const pair<key_t, value_t> partnerHiPair = make_pair(pHiKey, pHiVal);

const bool isUpper = bool(invocationID & threadStride);
const bool takeLarger = isUpper == bitonicAscending;

nbl::hlsl::bitonic_sort::compareExchangeWithPartner(takeLarger, loPair, partnerLoPair, hiPair, partnerHiPair, comp);
}
}
}

static void __call(bool ascending, NBL_REF_ARG(pair<key_t, value_t>) loPair, NBL_REF_ARG(pair<key_t, value_t>) hiPair)
{
const uint32_t invocationID = glsl::gl_SubgroupInvocationID();
const uint32_t subgroupSizeLog2 = glsl::gl_SubgroupSizeLog2();
[unroll]
for (uint32_t stage = 0; stage <= subgroupSizeLog2; stage++)
{
const bool bitonicAscending = (stage == subgroupSizeLog2) ? ascending : !bool(invocationID & (1u << stage));
mergeStage(stage, bitonicAscending, invocationID, loPair, hiPair);
}
}
};

}
}
}
#endif
110 changes: 70 additions & 40 deletions include/nbl/builtin/hlsl/utility.hlsl
Original file line number Diff line number Diff line change
@@ -1,40 +1,70 @@
// Copyright (C) 2024 - 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_UTILITY_INCLUDED_
#define _NBL_BUILTIN_HLSL_UTILITY_INCLUDED_


#include <nbl/builtin/hlsl/type_traits.hlsl>


// for now we only implement declval
namespace nbl
{
namespace hlsl
{
template<typename T>
const static bool always_true = true;
#ifndef __HLSL_VERSION

template<class T>
std::add_rvalue_reference_t<T> declval() noexcept
{
static_assert(false,"Actually calling declval is ill-formed.");
}

#else

namespace experimental
{

template<class T>
T declval() {}

}

#endif
}
}

#endif
// Copyright (C) 2024 - 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_UTILITY_INCLUDED_
#define _NBL_BUILTIN_HLSL_UTILITY_INCLUDED_


#include <nbl/builtin/hlsl/type_traits.hlsl>


namespace nbl
{
namespace hlsl
{

template<typename T1, typename T2>
struct pair
{
using first_type = T1;
using second_type = T2;

first_type first;
second_type second;
};

template<typename T1, typename T2>
pair<T1, T2> make_pair(T1 f, T2 s)
{
pair<T1, T2> p;
p.first = f;
p.second = s;
return p;
}

template<typename T1, typename T2>
void swap(NBL_REF_ARG(pair<T1, T2>) a, NBL_REF_ARG(pair<T1, T2>) b)
{
T1 temp_first = a.first;
T2 temp_second = a.second;
a.first = b.first;
a.second = b.second;
b.first = temp_first;
b.second = temp_second;
}

template<typename T>
const static bool always_true = true;
#ifndef __HLSL_VERSION

template<class T>
std::add_rvalue_reference_t<T> declval() noexcept
{
static_assert(false,"Actually calling declval is ill-formed.");
}

#else

namespace experimental
{

template<class T>
T declval() {}

}

#endif
}
}

#endif
Loading