348 lines
8.8 KiB
C++
348 lines
8.8 KiB
C++
#ifndef INCLUDE_SHADER_SOURCE_STORE_IMPLEMENTATION
|
|
# error Never include this file directly include 'shader_source_store.hpp'
|
|
#endif
|
|
|
|
#include <vector>
|
|
#include <span>
|
|
#include <tuple>
|
|
#include <cstddef>
|
|
#include <type_traits>
|
|
#include <algorithm>
|
|
|
|
#include "opengl/metadata/shader_source_metadata.hpp"
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char>::shader_source_store_iterator(
|
|
id_iterator_type ids,
|
|
string_iterator_type strings,
|
|
length_iterator_type lengths,
|
|
metadata_iterator_type metadata,
|
|
const size_type index,
|
|
const offset_type& offset
|
|
) :
|
|
m_ids{ ids },
|
|
m_strings{ strings },
|
|
m_lengths{ lengths },
|
|
m_metadata{ metadata },
|
|
m_index{ index },
|
|
m_offset{ offset } {}
|
|
|
|
|
|
template<typename Char>
|
|
typename assets::shader_source_store_iterator<Char>::reference assets::shader_source_store_iterator<Char>::operator*() const {
|
|
return dereference();
|
|
}
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator++() {
|
|
calc_offset(1);
|
|
++m_index;
|
|
return *this;
|
|
}
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<Char>::operator++(int) {
|
|
shader_source_store_iterator tmp = *this;
|
|
++(*this);
|
|
return tmp;
|
|
}
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator--() {
|
|
calc_offset(-1);
|
|
--m_index;
|
|
return *this;
|
|
}
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<Char>::operator--(int) {
|
|
auto tmp = *this;
|
|
--(*this);
|
|
return tmp;
|
|
}
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator+=(const difference_type n)
|
|
{
|
|
calc_offset(n);
|
|
m_index += n;
|
|
return *this;
|
|
}
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char>& assets::shader_source_store_iterator<Char>::operator-=(const difference_type n)
|
|
{
|
|
return (*this) += -n;
|
|
}
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<Char>::operator+(const difference_type n) const
|
|
{
|
|
auto tmp = *this;
|
|
return tmp += n; // TODO clion says n is unused
|
|
}
|
|
|
|
template<typename Char>
|
|
assets::shader_source_store_iterator<Char> assets::shader_source_store_iterator<Char>::operator-(const difference_type n) const
|
|
{
|
|
auto tmp = *this;
|
|
return tmp -= n; // TODO clion says n is unused
|
|
}
|
|
|
|
template<typename Char>
|
|
typename assets::shader_source_store_iterator<Char>::difference_type
|
|
assets::shader_source_store_iterator<Char>::operator-(const shader_source_store_iterator& other) const
|
|
{
|
|
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
|
|
}
|
|
|
|
template<typename Char>
|
|
typename assets::shader_source_store_iterator<Char>::reference assets::shader_source_store_iterator<Char>::operator[](
|
|
const difference_type n
|
|
) const {
|
|
return *(*this + n);
|
|
}
|
|
|
|
template<typename Char>
|
|
bool assets::shader_source_store_iterator<Char>::operator==(const shader_source_store_iterator& other) const
|
|
{
|
|
return m_ids == other.m_ids and m_index == other.m_index;
|
|
}
|
|
|
|
template<typename Char>
|
|
bool assets::shader_source_store_iterator<Char>::operator!=(const shader_source_store_iterator& other) const
|
|
{
|
|
return not (*this == other);
|
|
}
|
|
|
|
template<typename Char>
|
|
bool assets::shader_source_store_iterator<Char>::operator<(const shader_source_store_iterator& other) const
|
|
{
|
|
return m_index < other.m_index;
|
|
}
|
|
|
|
template<typename Char>
|
|
bool assets::shader_source_store_iterator<Char>::operator<=(const shader_source_store_iterator& other) const
|
|
{
|
|
return m_index <= other.m_index;
|
|
}
|
|
|
|
template<typename Char>
|
|
bool assets::shader_source_store_iterator<Char>::operator>(const shader_source_store_iterator& other) const
|
|
{
|
|
return m_index > other.m_index;
|
|
}
|
|
|
|
template<typename Char>
|
|
bool assets::shader_source_store_iterator<Char>::operator>=(const shader_source_store_iterator& other) const
|
|
{
|
|
return m_index >= other.m_index;
|
|
}
|
|
|
|
template<typename Char>
|
|
void assets::shader_source_store_iterator<Char>::calc_offset(
|
|
difference_type n
|
|
) {
|
|
|
|
const auto negative = n < difference_type{ 0 };
|
|
const auto positive = n > difference_type{ 0 };
|
|
const auto step = difference_type{ positive } - difference_type{ negative };
|
|
n = negative ? -n : n;
|
|
|
|
// TODO template optimize for single steps
|
|
|
|
while (n--)
|
|
{
|
|
const auto& count = m_lengths[m_index] + sizeof('\0');
|
|
m_offset += step * count;
|
|
m_index += step;
|
|
}
|
|
}
|
|
|
|
template<typename Char>
|
|
typename assets::shader_source_store_iterator<Char>::reference
|
|
assets::shader_source_store_iterator<Char>::dereference() const
|
|
{
|
|
return std::make_pair(
|
|
m_ids[m_index],
|
|
shader_source_view{
|
|
.source = { m_strings[m_offset], m_lengths[m_index] },
|
|
.meta = m_metadata[m_index]
|
|
}
|
|
);
|
|
}
|
|
|
|
inline bool assets::shader_source_store::insert(const id_type id, const data_type& data)
|
|
{
|
|
auto lock = std::unique_lock{ m_mutex };
|
|
|
|
const auto result = find(id);
|
|
|
|
return insert(result.first, id, data);
|
|
}
|
|
|
|
inline std::pair<assets::shader_source_store::iterator, bool> assets::shader_source_store::find(id_type id)
|
|
{
|
|
auto lock = std::shared_lock{ m_mutex };
|
|
|
|
return unsafe_find(id);
|
|
}
|
|
|
|
inline std::pair<assets::shader_source_store::const_iterator, bool> assets::shader_source_store::find(id_type id) const
|
|
{
|
|
auto lock = std::shared_lock{ m_mutex };
|
|
|
|
return unsafe_find(id);
|
|
}
|
|
|
|
inline bool assets::shader_source_store::unsafe_insert(iterator it, const id_type id, const data_type& data)
|
|
{
|
|
auto lock = std::unique_lock{ m_mutex };
|
|
|
|
const auto index = it.m_index;
|
|
const auto new_entry = index == m_ids.size() or m_ids[index] != id;
|
|
|
|
auto dst_source_length = count_type{};
|
|
const auto src_source_length = data.source.size();
|
|
|
|
if (new_entry) {
|
|
m_ids.insert(m_ids.begin() + index, id);
|
|
m_lengths.insert(m_lengths.begin() + index, src_source_length);
|
|
m_metadata.insert(m_metadata.begin() + index, data.meta);
|
|
}
|
|
else
|
|
{
|
|
dst_source_length = m_lengths[index];
|
|
m_lengths[index] = src_source_length;
|
|
m_metadata[index] = data.meta;
|
|
}
|
|
|
|
const auto dst_string_it = m_strings.begin() + it.m_offset;
|
|
ztu::replace_range(
|
|
m_strings,
|
|
dst_string_it,
|
|
dst_string_it + dst_source_length,
|
|
data.source.begin(),
|
|
data.source.end()
|
|
);
|
|
|
|
if (new_entry)
|
|
{
|
|
m_strings.insert(m_strings.begin() + it.m_offset + src_source_length, '\0');
|
|
}
|
|
|
|
return new_entry;
|
|
}
|
|
|
|
inline std::pair<assets::shader_source_store::iterator, bool> assets::shader_source_store::unsafe_find(id_type id)
|
|
{
|
|
const auto it = std::ranges::lower_bound(m_ids, id);
|
|
|
|
const auto found = it != m_ids.end() and *it == id;
|
|
const auto index = std::distance(m_ids.begin(), it);
|
|
|
|
return { begin() + index, found };
|
|
}
|
|
|
|
inline std::pair<assets::shader_source_store::const_iterator, bool> assets::shader_source_store::unsafe_find(id_type id) const
|
|
{
|
|
const auto it = std::ranges::lower_bound(m_ids, id);
|
|
|
|
const auto found = it != m_ids.end() and *it == id;
|
|
const auto index = std::distance(m_ids.begin(), it);
|
|
|
|
return { begin() + index, found };
|
|
}
|
|
|
|
void assets::shader_source_store::remove(const iterator& it)
|
|
{
|
|
auto lock = std::unique_lock{ m_mutex };
|
|
|
|
const auto index = it.m_index;
|
|
|
|
m_ids.erase(m_ids.begin() + index);
|
|
|
|
const auto strings_begin = m_strings.begin() + it.m_offset;
|
|
const auto strings_end = strings_begin + it.m_lengths[it.m_index] + sizeof('\0');
|
|
m_strings.erase(strings_begin, strings_end);
|
|
|
|
m_lengths.erase(m_lengths.begin() + index);
|
|
m_metadata.erase(m_metadata.begin() + index);
|
|
}
|
|
|
|
void assets::shader_source_store::clear()
|
|
{
|
|
auto lock = std::unique_lock{ m_mutex };
|
|
|
|
m_ids.clear();
|
|
m_strings.clear();
|
|
m_lengths.clear();
|
|
m_metadata.clear();
|
|
}
|
|
|
|
std::shared_lock<std::shared_mutex> assets::shader_source_store::acquire_read_lock() const {
|
|
return std::shared_lock{ m_mutex };
|
|
}
|
|
|
|
std::unique_lock<std::shared_mutex> assets::shader_source_store::acquire_write_lock() {
|
|
return std::unique_lock{ m_mutex };
|
|
}
|
|
|
|
assets::shader_source_store::iterator assets::shader_source_store::begin()
|
|
{
|
|
return iterator{
|
|
m_ids.data(),
|
|
m_strings.data(),
|
|
m_lengths.data(),
|
|
m_metadata.data(),
|
|
0,
|
|
{}
|
|
};
|
|
}
|
|
|
|
assets::shader_source_store::iterator assets::shader_source_store::end()
|
|
{
|
|
return iterator{
|
|
m_ids.data(),
|
|
m_strings.data(),
|
|
m_lengths.data(),
|
|
m_metadata.data(),
|
|
m_lengths.size(),
|
|
m_strings.size()
|
|
};
|
|
}
|
|
|
|
assets::shader_source_store::const_iterator assets::shader_source_store::begin() const
|
|
{
|
|
return const_iterator{
|
|
m_ids.data(),
|
|
m_strings.data(),
|
|
m_lengths.data(),
|
|
m_metadata.data(),
|
|
0,
|
|
{}
|
|
};
|
|
}
|
|
|
|
assets::shader_source_store::const_iterator assets::shader_source_store::end() const
|
|
{
|
|
return const_iterator{
|
|
m_ids.data(),
|
|
m_strings.data(),
|
|
m_lengths.data(),
|
|
m_metadata.data(),
|
|
m_lengths.size(),
|
|
m_strings.size()
|
|
};
|
|
}
|
|
|
|
assets::shader_source_store::const_iterator assets::shader_source_store::cbegin() const
|
|
{
|
|
return this->begin();
|
|
}
|
|
|
|
assets::shader_source_store::const_iterator assets::shader_source_store::cend() const
|
|
{
|
|
return this->end();
|
|
}
|