#include "pch.h" #include "vector_buffer.h" #include #include #undef min #undef max namespace idk::vkn { VulkanView& View(); namespace hlp { namespace detail { static size_t grow_size(size_t sz) { size_t new_size = 1; while (new_size < sz) { new_size *= 2; } return new_size; } } vector_buffer::vector_buffer(vk::PhysicalDevice& pdevice, vk::Device& device, size_t num_bytes) { resize(pdevice, device, num_bytes); } void vector_buffer::resize(vk::PhysicalDevice& pdevice, vk::Device& device, size_t num_bytes, bool force_downsize) { if (num_bytes >= _capacity || force_downsize) { _capacity = detail::grow_size(num_bytes); auto [buf, mem] = hlp::CreateAllocBindBuffer( pdevice, device, _capacity, vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible, vk::DispatchLoaderStatic{} ); _memory = std::move(mem); _buffer = std::move(buf); } } void vector_buffer::resize(size_t num_bytes, bool force_downsize) { vk::PhysicalDevice& pdevice = View().PDevice(); vk::Device& device = *View().Device(); resize(pdevice, device, num_bytes, force_downsize); } void vector_buffer::update(vk::DeviceSize offset, vk::DeviceSize len, vk::CommandBuffer& cmd_buffer, unsigned char const* data) { if (offset + len > _capacity) { LOG_TO(LogPool::GFX, "Failed to update vector buffer at [Offset:%llu] with data of [Length:%llu], exceeding [Capacity:%llu]", offset, len, _capacity); return; } if (!len) return; constexpr size_t limit = 65536; size_t limit_offset = 0; do { auto limit_len = std::min(len-limit_offset, limit); cmd_buffer.updateBuffer(*_buffer, limit_offset+offset, hlp::make_array_proxy(static_cast(limit_len), data+limit_offset), vk::DispatchLoaderStatic{}); limit_offset += limit_len; } while (limit_offset bbucket_list::new_chunk(string_view chunk) { if (_buckets.size() == 0 || back().full(chunk.size())) { add_bucket(); } auto& bucket = _buckets.back(); return std::make_pair(*bucket.buffer, bucket.allocate(chunk)); } vk::Buffer bbucket_list::current_buffer() const { return *back().buffer; } void bbucket_list::update_buffers() { if (!empty()) for (size_t i = 0; i < _index + 1; i++) { auto& b = _buckets[i]; auto data = std::data(b.data); if (b.size) hlp::MapMemory(_device, b.memory->Memory(), b.memory->Offset(), data, b.size); } } void bbucket_list::add_bucket() { if (!empty()) ++_index; if (_index >= _buckets.size()) { _buckets.emplace_back(_device, _pdevice, *_allocator, _usage_flags, _mempr_flags, _chunk_size); } } bbucket_list::bucket::bucket(vk::Device device, vk::PhysicalDevice pd, MemoryAllocator& allocator, vk::BufferUsageFlags buffer_flags, vk::MemoryPropertyFlags mem_flags, size_t cap) :capacity{ cap }, data(cap, '0') { auto&& [buf, alloc] = hlp::CreateAllocBindBuffer(pd, device, cap, buffer_flags, mem_flags, allocator, vk::DispatchLoaderStatic{}); buffer = std::move(buf); memory = std::move(alloc); data.resize(0); } uint32_t bbucket_list::bucket::allocate(string_view d) { uint32_t new_size = s_cast(size); size += d.size(); data += d; return new_size; } } }