Skip to content

CAD DTM Rendering #858

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

Open
wants to merge 84 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
81e440a
Update examples
Przemog1 Feb 27, 2025
f83d462
Merge branch 'master' of github.com:Devsh-Graphics-Programming/Nabla …
Przemog1 Mar 7, 2025
be37c6a
Updated examples
Przemog1 Mar 20, 2025
c9e0926
Implemented height shading
Przemog1 Mar 26, 2025
896d0c4
update examples
Erfan-Ahmadi Mar 30, 2025
25eceed
update examples
Erfan-Ahmadi Apr 10, 2025
df77044
update examples
Erfan-Ahmadi Apr 10, 2025
a327c29
Updated examples
Przemog1 Apr 12, 2025
3bf7c61
Updated examples
Przemog1 Apr 14, 2025
a77ca95
Updated_examples
Przemog1 Apr 14, 2025
4ed3af9
update examples
Erfan-Ahmadi Apr 15, 2025
631c63e
update examples
Erfan-Ahmadi Apr 15, 2025
f85956d
Updated examples
Przemog1 Apr 15, 2025
2456127
update examples
Erfan-Ahmadi Apr 15, 2025
7674e43
Updated examples
Przemog1 Apr 19, 2025
6030045
update examples
Erfan-Ahmadi Apr 21, 2025
f997894
update examples
Erfan-Ahmadi Apr 21, 2025
38d5ee2
update examples
Erfan-Ahmadi Apr 22, 2025
ca49224
Updated examples
Przemog1 Apr 22, 2025
2218dfe
Resolved conflicts, merged master
Przemog1 Apr 22, 2025
ab57b02
Updated examples
Przemog1 Apr 22, 2025
38baf9f
Updated examples
Przemog1 Apr 23, 2025
f810b5d
Updated examples
Przemog1 Apr 24, 2025
e19e644
update examples
Erfan-Ahmadi Apr 25, 2025
5c27651
update examples
Erfan-Ahmadi May 1, 2025
6d2011f
update examples tests
Erfan-Ahmadi May 2, 2025
0d6542a
update examples
Erfan-Ahmadi May 2, 2025
095eda5
update examples
Erfan-Ahmadi May 2, 2025
93297f2
update examples
Erfan-Ahmadi May 3, 2025
219b3b0
update examples
Erfan-Ahmadi May 4, 2025
3540cc9
update examples
Erfan-Ahmadi May 5, 2025
b4290eb
Merge branch 'master' into dtm
Erfan-Ahmadi May 5, 2025
02488df
update examples
Erfan-Ahmadi May 5, 2025
8c93578
update examples
Erfan-Ahmadi May 12, 2025
7e428bd
LRUCache new functionalities
Erfan-Ahmadi May 13, 2025
460475b
small dumb fix
Erfan-Ahmadi May 13, 2025
0f3f207
update examples
Erfan-Ahmadi May 13, 2025
6efb44c
update examples
Erfan-Ahmadi May 14, 2025
ddba6e4
fix suballocated descriptorset destructor and cull_frees
Erfan-Ahmadi May 14, 2025
d418ad5
update examples
Erfan-Ahmadi May 14, 2025
4a3720e
update example
Erfan-Ahmadi May 14, 2025
c4bc0c1
Fix IGPUDescriptorSet holding on to descriptors ref at correct arrayE…
Erfan-Ahmadi May 15, 2025
08ff1df
Fix IGPUDescriptorSet holding on to mutableSamplers
Erfan-Ahmadi May 15, 2025
2cf7ec8
SubAllocatedDescriptorSet to hold onto additional refcounted objects
Erfan-Ahmadi May 15, 2025
1c95943
Updated examples
Przemog1 May 15, 2025
9fd1360
Resolved conflicts, merged dtm
Przemog1 May 15, 2025
2e61c53
Resolved conflicts, merged master
Przemog1 May 15, 2025
24dfb15
Updated examples_tests
Przemog1 May 15, 2025
37785e5
fix wrong check for nullDescriptors feature
Erfan-Ahmadi May 15, 2025
667e30d
update examples
Erfan-Ahmadi May 16, 2025
8b094b4
small LRUCache comment to help with usage
Erfan-Ahmadi May 16, 2025
7c04af6
update examples
Erfan-Ahmadi May 16, 2025
4378a7b
Merge branch 'master' into dtm
Erfan-Ahmadi May 18, 2025
315ce86
update examples
Erfan-Ahmadi May 18, 2025
a4b4250
update examples
Erfan-Ahmadi May 20, 2025
93cf3cf
Adds standard bidirectional (const) iterator to the ResizableLRUCache
Fletterio May 21, 2025
bca340c
update examples
Erfan-Ahmadi May 21, 2025
f8327dd
Merge remote-tracking branch 'origin/dtm_LRUCacheUpgrades' into dtm
Erfan-Ahmadi May 21, 2025
a53c1aa
update examples
Erfan-Ahmadi May 21, 2025
4dcdcb2
update examples
Erfan-Ahmadi May 22, 2025
9ddd2e2
update examples
Erfan-Ahmadi May 23, 2025
048ff07
Updated examples
Przemog1 May 23, 2025
d63b34a
Resolved conflicts, merged dtm
Przemog1 May 23, 2025
bc97090
Updated examples
Przemog1 May 23, 2025
3d15320
Resolved conflicts, merged master
Przemog1 May 23, 2025
a2a6d17
Add both const and mutable iterators, option for Value or Key-Value e…
Fletterio May 24, 2025
1c529e9
Minor comment added
Fletterio May 24, 2025
0694b84
update examples
Erfan-Ahmadi May 24, 2025
6d5e678
update examples
Erfan-Ahmadi May 24, 2025
81f26c8
Address PR name consistency comments, adds copy contructor logic for …
Fletterio May 24, 2025
3acdf24
Minor refactor to previous commit
Fletterio May 24, 2025
636a6ea
Merge branch 'dtm_LRUCacheUpgrades' into dtm
Erfan-Ahmadi May 26, 2025
61d33b0
update examples
Erfan-Ahmadi May 26, 2025
716aaf2
Merge branch 'dtm_LRUCacheUpgrades' into dtm
Erfan-Ahmadi May 26, 2025
b6534f5
Updated examples
Przemog1 May 26, 2025
dea34a1
Merge branch 'dtm' of github.com:Devsh-Graphics-Programming/Nabla int…
Przemog1 May 26, 2025
1c73014
Updated examples
Przemog1 May 26, 2025
2fae94b
update examples_tests
Erfan-Ahmadi May 28, 2025
6959ecc
Updated examples
Przemog1 May 29, 2025
7a7bfdd
Updated examples
Przemog1 May 30, 2025
3bf9fc1
Updated examples_tests
Przemog1 May 31, 2025
db7cc9a
Updated examples
Przemog1 May 31, 2025
f6315dd
Updated examples
Przemog1 Jun 3, 2025
1fa2bff
Updated examples
Przemog1 Jun 3, 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
173 changes: 167 additions & 6 deletions include/nbl/core/containers/DoublyLinkedList.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ template<typename Value, class allocator = core::allocator<SDoublyLinkedNode<Val
class DoublyLinkedList
{
public:
template <bool Mutable>
class Iterator;
template <bool Mutable>
friend class Iterator;

using iterator = Iterator<true>;
using const_iterator = Iterator<false>;

using allocator_t = allocator;
using allocator_traits_t = std::allocator_traits<allocator_t>;
using address_allocator_t = PoolAddressAllocator<uint32_t>;
Expand Down Expand Up @@ -233,16 +241,43 @@ class DoublyLinkedList
// Offset the array start by the storage used by the address allocator
m_array = reinterpret_cast<node_t*>(reinterpret_cast<uint8_t*>(m_reservedSpace) + addressAllocatorStorageSize * sizeof(node_t));

m_addressAllocator = address_allocator_t(m_reservedSpace, 0u, 0u, 1u, capacity, 1u);
// If allocation failed, create list with no capacity to indicate creation failed
m_cap = m_reservedSpace ? capacity : 0;
m_back = invalid_iterator;
m_begin = invalid_iterator;
m_addressAllocator = address_allocator_t(m_reservedSpace, 0u, 0u, 1u, m_cap, 1u);
}

DoublyLinkedList() = default;

DoublyLinkedList(const DoublyLinkedList& other) = delete;
// Copy Constructor
explicit DoublyLinkedList(const DoublyLinkedList& other) : m_dispose_f(other.m_dispose_f), m_allocator(other.m_allocator)
{
const size_t addressAllocatorStorageSize = (address_allocator_t::reserved_size(1u, other.m_cap, 1u) + sizeof(node_t) - 1) / sizeof(node_t);
m_currentAllocationSize = addressAllocatorStorageSize + other.m_cap;
m_reservedSpace = reinterpret_cast<void*>(allocator_traits_t::allocate(m_allocator, m_currentAllocationSize));
// If allocation failed, create a list with no capacity
m_cap = m_reservedSpace ? other.m_cap : 0;
if (!m_cap) return; // Allocation failed
// Offset the array start by the storage used by the address allocator
m_array = reinterpret_cast<node_t*>(reinterpret_cast<uint8_t*>(m_reservedSpace) + addressAllocatorStorageSize * sizeof(node_t));

if constexpr (std::is_trivially_copyable_v<Value>)
{
// Create new address allocator by copying state
m_addressAllocator = address_allocator_t(m_cap, other.m_addressAllocator, m_reservedSpace);
// Copy memory over
memcpy(m_array, other.m_array, m_cap * sizeof(node_t));
m_back = other.m_back;
m_begin = other.m_begin;
}
else
{
m_addressAllocator = address_allocator_t(m_reservedSpace, 0u, 0u, 1u, m_cap, 1u);
// Reverse iteration since we push from the front
for (auto it = other.crbegin(); it != other.crend(); it++)
pushFront(value_t(*it));

}
}

DoublyLinkedList& operator=(const DoublyLinkedList& other) = delete;

Expand Down Expand Up @@ -273,6 +308,16 @@ class DoublyLinkedList
}
}

// Iterator stuff
iterator begin();
iterator end();
const_iterator cbegin() const;
const_iterator cend() const;
std::reverse_iterator<iterator> rbegin();
std::reverse_iterator<iterator> rend();
std::reverse_iterator<const_iterator> crbegin() const;
std::reverse_iterator<const_iterator> crend() const;

private:
//allocate and get the address of the next free node
inline uint32_t reserveAddress()
Expand Down Expand Up @@ -339,14 +384,130 @@ class DoublyLinkedList
node_t* m_array;

uint32_t m_cap;
uint32_t m_back;
uint32_t m_begin;
uint32_t m_back = invalid_iterator;
uint32_t m_begin = invalid_iterator;
disposal_func_t m_dispose_f;
};

// ---------------------------------------------------- ITERATOR -----------------------------------------------------------

// Satifies std::bidirectional_iterator
template<typename Value, class allocator>
template<bool Mutable>
class DoublyLinkedList<Value, allocator>::Iterator
{
using base_iterable_t = DoublyLinkedList<Value, allocator>;
using iterable_t = std::conditional_t<Mutable, base_iterable_t, const base_iterable_t>;
friend class base_iterable_t;
public:
using value_type = std::conditional_t<Mutable, Value, const Value>;
using pointer = value_type*;
using reference = value_type&;
using difference_type = int32_t;

Iterator() = default;

// Prefix
Iterator& operator++()
{
m_current = m_iterable->get(m_current)->next;
return *this;
}

Iterator& operator--()
{
m_current = m_current != invalid_iterator ? m_iterable->get(m_current)->prev : m_iterable->m_back;
return *this;
}

// Postfix
Iterator operator++(int)
{
Iterator beforeIncrement = *this;
operator++();
return beforeIncrement;
}

Iterator operator--(int)
{
Iterator beforeDecrement = *this;
operator--();
return beforeDecrement;
}

// Comparison
bool operator==(const Iterator& rhs) const
{
return m_iterable == rhs.m_iterable && m_current == rhs.m_current;
}

//Deref
reference operator*() const
{
return m_iterable->get(m_current)->data;
}

pointer operator->() const
{
return & operator*();
}
private:
Iterator(iterable_t* const iterable, uint32_t idx) : m_iterable(iterable), m_current(idx) {}

iterable_t* m_iterable;
uint32_t m_current;
};

template<typename Value, class allocator>
DoublyLinkedList<Value, allocator>::iterator DoublyLinkedList<Value, allocator>::begin()
{
return iterator(this, m_begin);
}

template<typename Value, class allocator>
DoublyLinkedList<Value, allocator>::const_iterator DoublyLinkedList<Value, allocator>::cbegin() const
{
return const_iterator(this, m_begin);
}

template<typename Value, class allocator>
DoublyLinkedList<Value, allocator>::iterator DoublyLinkedList<Value, allocator>::end()
{
return iterator(this, invalid_iterator);
}

template<typename Value, class allocator>
DoublyLinkedList<Value, allocator>::const_iterator DoublyLinkedList<Value, allocator>::cend() const
{
return const_iterator(this, invalid_iterator);
}

template<typename Value, class allocator>
std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::iterator> DoublyLinkedList<Value, allocator>::rbegin()
{
return std::reverse_iterator<iterator>(iterator(this, invalid_iterator));
}

template<typename Value, class allocator>
std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::const_iterator> DoublyLinkedList<Value, allocator>::crbegin() const
{
return std::reverse_iterator<const_iterator>(const_iterator(this, invalid_iterator));
}

template<typename Value, class allocator>
std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::iterator> DoublyLinkedList<Value, allocator>::rend()
{
return std::reverse_iterator<iterator>(iterator(this, m_begin));
}

template<typename Value, class allocator>
std::reverse_iterator<typename DoublyLinkedList<Value, allocator>::const_iterator> DoublyLinkedList<Value, allocator>::crend() const
{
return std::reverse_iterator<const_iterator>(const_iterator(this, m_begin));
}

} //namespace core
} //namespace nbl


#endif
71 changes: 66 additions & 5 deletions include/nbl/core/containers/LRUCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class LRUCacheBase
LRUCacheBase(const uint32_t capacity, MapHash&& _hash, MapEquals&& _equals, disposal_func_t&& df) : m_list(capacity, std::move(df)), m_hash(std::move(_hash)), m_equals(std::move(_equals)), searchedKey(nullptr)
{ }

LRUCacheBase(const LRUCacheBase& other) : m_list(other.m_list), m_hash(other.m_hash), m_equals(other.m_equals), searchedKey(nullptr) {}

public:
inline const Key& getReference(const uint32_t nodeAddr) const
{
Expand Down Expand Up @@ -221,14 +223,27 @@ class [[deprecated]] LRUCache : protected impl::LRUCacheBase<Key,Value,MapHash,M
unordered_set<uint32_t,WrapHash,WrapEquals> m_shortcut_map;
};

namespace impl
{
template<typename EvictionCallback, typename Value>
concept LRUCacheValueEvictionCallback = std::invocable<EvictionCallback, const Value&>;

template<typename EvictionCallback, typename Key, typename Value>
concept LRUCacheKeyValueEvictionCallback = std::invocable<EvictionCallback, const Key&, const Value&>;

template<typename EvictionCallback, typename Key, typename Value>
concept LRUCacheInsertEvictionCallback = LRUCacheValueEvictionCallback<EvictionCallback, Value>
|| LRUCacheKeyValueEvictionCallback<EvictionCallback, Key, Value>;
} //namespace impl

// Key-Value Least Recently Used cache
// Capacity can be increased at user's will
// When the cache is full inserting will remove the least used entry
template<typename Key, typename Value, typename MapHash = std::hash<Key>, typename MapEquals = std::equal_to<Key> >
class ResizableLRUCache : protected impl::LRUCacheBase<Key, Value, MapHash, MapEquals, DoublyLinkedList<std::pair<Key, Value> > >, public core::Unmovable, public core::Uncopyable
{
// typedefs
using list_t = DoublyLinkedList<std::pair<Key, Value> >;
using list_t = DoublyLinkedList<std::pair<Key, Value>>;
using base_t = impl::LRUCacheBase<Key, Value, MapHash, MapEquals, list_t>;
using this_t = ResizableLRUCache<Key, Value, MapHash, MapEquals>;

Expand Down Expand Up @@ -277,6 +292,10 @@ class ResizableLRUCache : protected impl::LRUCacheBase<Key, Value, MapHash, MapE
}

public:
// Keep it simple
using iterator = typename list_t::iterator;
using const_iterator = typename list_t::const_iterator;

using disposal_func_t = typename base_t::disposal_func_t;
using assoc_t = typename base_t::list_value_t;

Expand All @@ -289,6 +308,15 @@ class ResizableLRUCache : protected impl::LRUCacheBase<Key, Value, MapHash, MapE
}
ResizableLRUCache() = delete;

// It's not possible to copy the unordered_set memory-wise and just change hashing and KeyEquals functions unfortunately
// (in the general case that wouldn't make sense but it does here due to the way the wrappers work)
// Anyway, we must iterate over the old cache and copy the map over
explicit ResizableLRUCache(const ResizableLRUCache& other) : base_t(other), m_capacity(other.m_capacity),
m_shortcut_map(other.m_shortcut_map.cbegin(), other.m_shortcut_map.cend(), other.m_capacity >> 2, WrapHash{this}, WrapEquals{this})
{
m_shortcut_map.reserve(m_capacity);
}

inline void print(core::smart_refctd_ptr<system::ILogger> logger)
{
logger->log("Printing LRU cache contents");
Expand Down Expand Up @@ -323,7 +351,7 @@ class ResizableLRUCache : protected impl::LRUCacheBase<Key, Value, MapHash, MapE
return stringStream.str();
}

template<typename K, typename V, std::invocable<const Value&> EvictionCallback> requires std::is_constructible_v<Value, V> // && (std::is_same_v<Value,V> || std::is_assignable_v<Value,V>) // is_assignable_v<int, int&> returns false :(
template<typename K, typename V, typename EvictionCallback> requires std::is_constructible_v<Value, V> && impl::LRUCacheInsertEvictionCallback<EvictionCallback, Key, Value>// && (std::is_same_v<Value,V> || std::is_assignable_v<Value,V>) // is_assignable_v<int, int&> returns false :(
inline Value* insert(K&& k, V&& v, EvictionCallback&& evictCallback)
{
bool success;
Expand All @@ -336,10 +364,18 @@ class ResizableLRUCache : protected impl::LRUCacheBase<Key, Value, MapHash, MapE
}
else
{
const bool overflow = m_shortcut_map.size() >= base_t::m_list.getCapacity();
const bool overflow = size() >= base_t::m_list.getCapacity();
if (overflow)
{
evictCallback(base_t::m_list.getBack()->data.second);
if constexpr (impl::LRUCacheValueEvictionCallback<EvictionCallback, Value>)
{
evictCallback(base_t::m_list.getBack()->data.second);
}
// LRUCacheKeyValueEvictionCallback
else
{
evictCallback(base_t::m_list.getBack()->data.first, base_t::m_list.getBack()->data.second);
}
m_shortcut_map.erase(base_t::m_list.getLastAddress());
base_t::m_list.popBack();
}
Expand Down Expand Up @@ -389,7 +425,7 @@ class ResizableLRUCache : protected impl::LRUCacheBase<Key, Value, MapHash, MapE
return nullptr;
}

//remove element at key if present
// remove element at key if present
inline void erase(const Key& key)
{
bool success;
Expand All @@ -400,6 +436,20 @@ class ResizableLRUCache : protected impl::LRUCacheBase<Key, Value, MapHash, MapE
m_shortcut_map.erase(iterator);
}
}

// returns key for least recently used
// use in evictin callback to know which Key is being evicted
inline const Key* get_least_recently_used() const
{
if (size() > 0)
return &base_t::m_list.getBack()->data.first;
else
return nullptr;
}

inline size_t size() const { return m_shortcut_map.size(); }

inline bool empty() const { return size() <= 0ull; }

/**
* @brief Resizes the cache by extending its capacity so it can hold more elements. Returns a bool indicating if capacity was indeed increased.
Expand Down Expand Up @@ -427,6 +477,17 @@ class ResizableLRUCache : protected impl::LRUCacheBase<Key, Value, MapHash, MapE
m_shortcut_map.erase(mapBegin, mapEnd);
}

// Iterator stuff
// Normal iterator order is MRU -> LRU
iterator begin() { return base_t::m_list.begin(); }
iterator end() { return base_t::m_list.end(); }
const_iterator cbegin() const { return base_t::m_list.cbegin(); }
const_iterator cend() const { return base_t::m_list.cend(); }
std::reverse_iterator<iterator> rbegin() { return base_t::m_list.rbegin(); }
std::reverse_iterator<iterator> rend() { return base_t::m_list.rend(); }
std::reverse_iterator<const_iterator> crbegin() const { return base_t::m_list.crbegin(); }
std::reverse_iterator<const_iterator> crend() const { return base_t::m_list.crend(); }

protected:
unordered_set<uint32_t, WrapHash, WrapEquals> m_shortcut_map;
uint32_t m_capacity;
Expand Down
Loading