Skip to content

Commit 3f78f0c

Browse files
Ensuring Update-After-Bind is supporting by the Device (#492)
* updated vulkan device * added update-after-bind detection * fixed binding name cmp ops * updated bindless logic * fixed missing props * simplified expr * reduced descriptorset usage * fixed descriptor set count logic * Mitigate undesired unsynchronized effect of changing SwapchainImage Count (#495) * Re-Arrange Code flow after swapchainimage count change - The code that relies on the SwapchainImageCount such as the command buffer are re-arranged to ensure that they run after we establish the correct number of Swapchain Images * Pull Request #495 Requested Changes - Removed Redundant parameter to the CommandBufferManager.Initialize method - Moved the EnquedCommandBuffers.init method to be called right after the m_buffer_manager.Initialize function call --------- Co-authored-by: Mathew Benson <mathew@benson.co.ke> * improved buffer manager * prevent swapchain image count change in after first creation * fixed string deref * filled dummy set for imgui * fixed usage of Shader LocalArena * fixed rendering on wrong framebuffer --------- Co-authored-by: Mathew Benson <benson.orina@live.com> Co-authored-by: Mathew Benson <mathew@benson.co.ke>
1 parent 107b917 commit 3f78f0c

File tree

12 files changed

+738
-369
lines changed

12 files changed

+738
-369
lines changed

Resources/Shaders/fragment_common.glsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ layout(std140, set = 0, binding = 5) readonly buffer MatSB
6161
}
6262
MaterialDataBuffer;
6363

64-
layout(set = 0, binding = 9) uniform sampler2D TextureArray[];
64+
layout(set = 1, binding = 0) uniform sampler2D TextureArray[];
6565

6666
MaterialData FetchMaterial(uint dataIndex)
6767
{

Resources/Shaders/imgui.frag

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
44

55
layout(location = 0) out vec4 fColor;
6-
layout(set = 0, binding = 0) uniform sampler2D TextureArray[];
6+
layout(set = 0, binding = 0) uniform sampler2D _unused;
7+
layout(set = 1, binding = 0) uniform sampler2D TextureArray[];
78

89
layout(location = 0) in struct
910
{

ZEngine/ZEngine/Core/Containers/HashMap.h

Lines changed: 35 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ namespace ZEngine::Core::Containers
3232
{
3333
public:
3434
using Entry = HashEntry<K, V>;
35-
using ArrayType = std::conditional_t<IsConst, const Array<Entry>, Array<Entry>>;
36-
using value_type = std::conditional_t<IsConst, std::pair<const K&, const V&>, std::pair<const K&, V&>>;
35+
using EntryPointer = std::conditional_t<IsConst, const Entry*, Entry*>;
36+
using value_type = std::conditional_t<IsConst, std::pair<const K, const V>, std::pair<const K, V>>;
3737
using reference = value_type;
3838
using pointer = value_type*;
39-
using iterator_category = std::forward_iterator_tag;
39+
using iterator_category = std::input_iterator_tag;
4040
using difference_type = std::ptrdiff_t;
4141

4242
// Constructs an iterator for the hash map's entries, starting at the given index.
43-
// @param entries Reference to the array of hash map entries.
43+
// @param entries Value to the array of hash map entries.
4444
// @param index Starting index for iteration.
45-
HashMapIterator(ArrayType& entries, std::size_t index) : m_entries(entries), m_index(index)
45+
HashMapIterator(EntryPointer entries, std::size_t index, std::size_t size) : m_entries(entries), m_index(index), m_size(size)
4646
{
4747
advance_to_valid();
4848
}
@@ -91,22 +91,22 @@ namespace ZEngine::Core::Containers
9191
// @return A pointer to a temporary key-value pair.
9292
pointer operator->() const
9393
{
94-
static value_type temp = **this;
95-
return &temp;
94+
return std::addressof(**this);
9695
}
9796

9897
private:
9998
// Advances the iterator to the next occupied entry, skipping empty or deleted entries.
10099
void advance_to_valid()
101100
{
102-
while (m_index < m_entries.size() && m_entries[m_index].state != EntryState::Occupied)
101+
while (m_index < m_size && m_entries[m_index].state != EntryState::Occupied)
103102
{
104103
++m_index;
105104
}
106105
}
107106

108-
ArrayType& m_entries;
109-
std::size_t m_index;
107+
EntryPointer m_entries;
108+
std::size_t m_index;
109+
std::size_t m_size;
110110
};
111111

112112
template <typename K, typename V>
@@ -122,11 +122,11 @@ namespace ZEngine::Core::Containers
122122
// @param allocator Pointer to the arena allocator for memory management.
123123
// @param initial_capacity Initial number of slots (default: 16).
124124
// @param load_factor Maximum load factor before resizing (default: 0.75).
125-
void init(Memory::ArenaAllocator* allocator, size_type initial_capacity = 32)
125+
void init(Memory::ArenaAllocator* allocator, size_type initial_capacity = 16)
126126
{
127127
m_allocator = allocator;
128128
m_load_factor = 0.75f;
129-
m_entries.init(m_allocator, initial_capacity, 0);
129+
m_entries.init(m_allocator, initial_capacity);
130130
for (size_type i = 0; i < initial_capacity; ++i)
131131
{
132132
m_entries.push({});
@@ -146,12 +146,6 @@ namespace ZEngine::Core::Containers
146146
size_type index = probe_for_insert(key);
147147
auto& entry = m_entries[index];
148148

149-
if (entry.state == EntryState::Occupied && key_equals(entry.key, key))
150-
{
151-
entry.value = value; // Update existing key
152-
return;
153-
}
154-
155149
if (entry.state == EntryState::Empty || entry.state == EntryState::Deleted)
156150
{
157151
entry.key = key;
@@ -161,15 +155,10 @@ namespace ZEngine::Core::Containers
161155
}
162156
else
163157
{
164-
throw std::runtime_error("HashMap insert failed: table full");
158+
entry.value = value;
165159
}
166160
}
167161

168-
// Accesses or inserts a value for a key, returning a reference to the value.
169-
// Inserts a default-constructed value if the key is not found.
170-
// @param key The key to access or insert.
171-
// @return Reference to the associated value.
172-
// @throws std::runtime_error if the table is full and cannot be resized.
173162
V& operator[](const K& key)
174163
{
175164
maybe_grow();
@@ -184,11 +173,6 @@ namespace ZEngine::Core::Containers
184173
entry.state = EntryState::Occupied;
185174
++m_size;
186175
}
187-
else if (entry.state == EntryState::Occupied && entry.key != key)
188-
{
189-
throw std::runtime_error("HashMap insert failed: table full");
190-
}
191-
192176
return entry.value;
193177
}
194178

@@ -282,29 +266,29 @@ namespace ZEngine::Core::Containers
282266
// @note Iterators are invalidated by insert, remove, or reserve operations.
283267
iterator begin()
284268
{
285-
return iterator(m_entries, 0);
269+
return iterator(m_entries.data(), 0, m_entries.size());
286270
}
287271

288272
// Returns an iterator to the end of the hash map.
289273
// @return Iterator representing the past-the-end position.
290274
iterator end()
291275
{
292-
return iterator(m_entries, m_entries.size());
276+
return iterator(m_entries.data(), m_entries.size(), m_entries.size());
293277
}
294278

295279
// Returns a const iterator to the first occupied entry.
296280
// @return Const iterator pointing to the first key-value pair or end() if empty.
297281
// @note Iterators are invalidated by insert, remove, or reserve operations.
298282
const_iterator begin() const
299283
{
300-
return const_iterator(m_entries, 0);
284+
return const_iterator(m_entries.data(), 0, m_entries.size());
301285
}
302286

303287
// Returns a const iterator to the end of the hash map.
304288
// @return Const iterator representing the past-the-end position.
305289
const_iterator end() const
306290
{
307-
return const_iterator(m_entries, m_entries.size());
291+
return const_iterator(m_entries.data(), m_entries.size(), m_entries.size());
308292
}
309293

310294
// Returns a const iterator to the first occupied entry (alias for begin() const).
@@ -339,7 +323,7 @@ namespace ZEngine::Core::Containers
339323
{
340324
if (static_cast<float>(m_size + 1) / m_entries.size() > m_load_factor)
341325
{
342-
size_type new_capacity = std::max<size_type>(16, m_entries.size() * 3 / 2); // Growth factor 1.5
326+
size_type new_capacity = std::max<size_type>(16, static_cast<size_type>(m_entries.size() * 1.5f)); // Growth factor 1.5
343327
rehash(new_capacity);
344328
}
345329
}
@@ -364,18 +348,20 @@ namespace ZEngine::Core::Containers
364348
{
365349
Array<Entry> old_entries = m_entries; // Move to avoid copying
366350
m_entries = Array<Entry>{};
367-
m_entries.init(m_allocator, new_capacity, 0);
351+
m_entries.init(m_allocator, new_capacity);
368352
for (size_type i = 0; i < new_capacity; ++i)
369353
{
370354
m_entries.push({});
371355
}
372356
m_size = 0;
373357

374-
for (const auto& entry : old_entries)
358+
for (size_type i = 0; i < old_entries.size(); ++i)
375359
{
376-
if (entry.state == EntryState::Occupied)
360+
if (old_entries[i].state == EntryState::Occupied)
377361
{
378-
insert(entry.key, entry.value);
362+
size_type index = probe_for_insert(old_entries[i].key);
363+
m_entries[index] = old_entries[i]; // Direct assignment
364+
++m_size;
379365
}
380366
}
381367
}
@@ -386,8 +372,6 @@ namespace ZEngine::Core::Containers
386372
size_type probe_for_key(const K& key) const
387373
{
388374
size_type index = hash(key) % m_entries.size();
389-
size_type step = double_hash(key);
390-
size_type start = index;
391375
size_type i = 0;
392376

393377
do
@@ -401,9 +385,9 @@ namespace ZEngine::Core::Containers
401385
{
402386
return index;
403387
}
404-
index = (index + step) % m_entries.size();
405388
++i;
406-
} while (index != start && i < m_entries.size());
389+
index = (index + i) % m_entries.size();
390+
} while (i < m_entries.size());
407391

408392
return size_type(-1);
409393
}
@@ -415,47 +399,36 @@ namespace ZEngine::Core::Containers
415399
size_type probe_for_insert(const K& key)
416400
{
417401
size_type index = hash(key) % m_entries.size();
418-
size_type step = double_hash(key);
419-
size_type start = index;
420402
size_type first_deleted = size_type(-1);
421403
size_type i = 0;
422404

423405
do
424406
{
425407
auto& entry = m_entries[index];
408+
if (entry.state == EntryState::Occupied && key_equals(entry.key, key))
409+
{
410+
return index;
411+
}
412+
426413
if (entry.state == EntryState::Empty)
427414
{
428415
return (first_deleted != size_type(-1)) ? first_deleted : index;
429416
}
417+
430418
if (entry.state == EntryState::Deleted && first_deleted == size_type(-1))
431419
{
432420
first_deleted = index;
433421
}
434-
else if (entry.state == EntryState::Occupied && key_equals(entry.key, key))
435-
{
436-
return index;
437-
}
438-
index = (index + step) % m_entries.size();
422+
439423
++i;
440-
} while (index != start && i < m_entries.size());
424+
index = (index + i) % m_entries.size();
425+
} while (i < m_entries.size());
441426

442427
if (first_deleted != size_type(-1))
443428
{
444429
return first_deleted;
445430
}
446431

447-
// Debug table state on failure
448-
size_type empty_count = 0, deleted_count = 0, occupied_count = 0;
449-
for (const auto& entry : m_entries)
450-
{
451-
if (entry.state == EntryState::Empty)
452-
++empty_count;
453-
else if (entry.state == EntryState::Deleted)
454-
++deleted_count;
455-
else if (entry.state == EntryState::Occupied)
456-
++occupied_count;
457-
}
458-
459432
throw std::runtime_error("HashMap probe failed: table full");
460433
}
461434

0 commit comments

Comments
 (0)