Vulkan BDA debugging force m_BufferAddresses to be sorted

The implementation usage of m_BufferAddresses assumes the container is sorted and requires the use of lower_bound() API

Added rdcsortedflatmap subclass of rdcflatmap
Only expose upper_bound(), lower_bound() APIs in rdcsortedflatmap
The upper/lower bound APIs require a sorted container
This commit is contained in:
Jake Turner
2024-02-13 17:03:42 +00:00
parent 52cfb0e083
commit a62634717e
4 changed files with 111 additions and 68 deletions
+91 -53
View File
@@ -1,3 +1,27 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2024 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#pragma once
#include <algorithm>
@@ -126,35 +150,6 @@ struct rdcflatmap
return {(begin() + idx), inserted};
}
iterator upper_bound(const Key &key)
{
if(!sorted)
sort();
size_t idx = lower_bound_idx(key);
// almost the same behaviour as lower_bound, except if we actually have the key, return the next
// element.
if(idx < size() && storage.at(idx).first == key)
return begin() + idx + 1;
return begin() + idx;
}
const_iterator upper_bound(const Key &key) const
{
size_t idx = lower_bound_idx(key);
// almost the same behaviour as lower_bound, except if we actually have the key, return the next
// element.
if(idx < size() && storage.at(idx).first == key)
return begin() + idx + 1;
return begin() + idx;
}
iterator lower_bound(const Key &key) { return begin() + lower_bound_idx(key); }
const_iterator lower_bound(const Key &key) const { return begin() + lower_bound_idx(key); }
iterator begin() { return storage.begin(); }
iterator end() { return storage.end(); }
const_iterator begin() const { return storage.begin(); }
@@ -167,8 +162,33 @@ struct rdcflatmap
storage.swap(other.storage);
}
void clear() { storage.clear(); }
private:
protected:
rdcarray<rdcpair<Key, Value>> storage;
size_t lower_bound_idx(const Key &id) const
{
// start looking at the whole range
size_t start = 0, sz = size();
// continue iterating until the range is empty
while(sz > 0)
{
const size_t halfsz = sz / 2;
const size_t mid = start + halfsz;
const Key comp = storage.at(mid).first;
if(comp < id)
{
start = mid + 1;
sz -= halfsz + 1;
}
else
{
sz = halfsz;
}
}
return start;
}
private:
bool sorted = (SortThreshold == 0);
void sort()
@@ -216,29 +236,6 @@ private:
return (begin() + idx)->second;
}
size_t lower_bound_idx(const Key &id) const
{
// start looking at the whole range
size_t start = 0, sz = size();
// continue iterating until the range is empty
while(sz > 0)
{
const size_t halfsz = sz / 2;
const size_t mid = start + halfsz;
const Key comp = storage.at(mid).first;
if(comp < id)
{
start = mid + 1;
sz -= halfsz + 1;
}
else
{
sz = halfsz;
}
}
return start;
}
iterator unsorted_find(const Key &id)
{
for(auto it = begin(); it != end(); ++it)
@@ -277,3 +274,44 @@ private:
return storage.back().second;
}
};
// a version of rdcflatmap which is guaranteed to be sorted
// adds upper_bound and lower_bound APIs
template <typename Key, typename Value>
struct rdcsortedflatmap : rdcflatmap<Key, Value, 0>
{
using iterator = rdcpair<Key, Value> *;
using const_iterator = const rdcpair<Key, Value> *;
using rdcflatmap<Key, Value, 0>::begin;
using rdcflatmap<Key, Value, 0>::size;
using rdcflatmap<Key, Value, 0>::storage;
using rdcflatmap<Key, Value, 0>::lower_bound_idx;
iterator upper_bound(const Key &key)
{
size_t idx = lower_bound_idx(key);
// almost the same behaviour as lower_bound, except if we actually have the key, return the next
// element.
if(idx < size() && storage.at(idx).first == key)
return begin() + idx + 1;
return begin() + idx;
}
const_iterator upper_bound(const Key &key) const
{
size_t idx = lower_bound_idx(key);
// almost the same behaviour as lower_bound, except if we actually have the key, return the next
// element.
if(idx < size() && storage.at(idx).first == key)
return begin() + idx + 1;
return begin() + idx;
}
iterator lower_bound(const Key &key) { return begin() + lower_bound_idx(key); }
const_iterator lower_bound(const Key &key) const { return begin() + lower_bound_idx(key); }
};