idk_me/src/engine/vkn/BufferHelpers.inl

181 lines
5.8 KiB
Plaintext
Raw Normal View History

2024-05-07 00:33:19 +08:00
#pragma once
#include <vulkan/vulkan.hpp>
#include "BufferHelpers.h"
size_t Track(size_t s);
namespace idk::vkn::hlp
{
template<typename Dispatcher>
vk::UniqueBuffer CreateBuffer(vk::Device device, vk::DeviceSize size, vk::BufferUsageFlags usage, Dispatcher const& dispatcher)
{
vk::BufferCreateInfo bufferInfo
{
vk::BufferCreateFlags{}
,size
,usage
,vk::SharingMode::eExclusive //Exclusive to the graphics queue family
};
2024-05-22 22:06:12 +08:00
return device.createBufferUnique(bufferInfo, nullptr);
2024-05-07 00:33:19 +08:00
}
template<typename T, typename Dispatcher>
vk::UniqueBuffer CreateVertexBuffer(vk::Device device, T* const begin, T* const end, const Dispatcher& dispatcher)
{
2024-05-22 22:06:12 +08:00
return CreateBuffer(device, buffer_size(begin, end), vk::BufferUsageFlagBits::eVertexBuffer);
2024-05-07 00:33:19 +08:00
}
template<typename T, typename Dispatcher>
vk::UniqueBuffer CreateVertexBuffer(vk::Device device, std::vector<T> const& vertices, const Dispatcher& dispatcher)
{
2024-05-22 22:06:12 +08:00
return CreateVertexBuffer(device, vertices.data(), vertices.data() + vertices.size());
2024-05-07 00:33:19 +08:00
}
//
template<typename Dispatcher>
vk::UniqueDeviceMemory AllocateBuffer(
vk::PhysicalDevice pdevice, vk::Device device, vk::Buffer const& buffer, vk::MemoryPropertyFlags memory_flags, Dispatcher const& dispatcher)
{
2024-05-22 22:06:12 +08:00
vk::MemoryRequirements req = device.getBufferMemoryRequirements(buffer);
2024-05-07 00:33:19 +08:00
vk::MemoryAllocateInfo allocInfo
{
Track(req.size)
,findMemoryType(pdevice,req.memoryTypeBits, memory_flags)
};
2024-05-22 22:06:12 +08:00
return device.allocateMemoryUnique(allocInfo, nullptr);
2024-05-07 00:33:19 +08:00
}
template<typename Dispatcher>
void BindBufferMemory(vk::Device device, vk::Buffer buffer, vk::DeviceMemory memory, uint32_t offset, Dispatcher const& dispatcher)
{
2024-05-22 22:06:12 +08:00
device.bindBufferMemory(buffer, memory, offset);
2024-05-07 00:33:19 +08:00
}
template<typename Dispatcher>
std::pair<vk::UniqueBuffer, vk::UniqueDeviceMemory> CreateAllocBindBuffer(
vk::PhysicalDevice pdevice, vk::Device device,
vk::DeviceSize buffer_size,
vk::BufferUsageFlags buffer_usage,
vk::MemoryPropertyFlags memory_flags,
const Dispatcher& dispatcher
)
{
2024-05-22 22:06:12 +08:00
auto buffer = CreateBuffer(device, buffer_size, buffer_usage);
auto memory = AllocateBuffer(pdevice, device, *buffer, memory_flags);
BindBufferMemory(device, *buffer, *memory, 0);
2024-05-07 00:33:19 +08:00
return std::make_pair(std::move(buffer), std::move(memory));
}
template<typename Dispatcher>
std::pair<vk::UniqueBuffer, UniqueAlloc> CreateAllocBindBuffer(
vk::PhysicalDevice pdevice, vk::Device device,
vk::DeviceSize buffer_size,
vk::BufferUsageFlags buffer_usage,
vk::MemoryPropertyFlags memory_flags,
MemoryAllocator& allocator,
const Dispatcher& dispatcher
)
{
2024-05-22 22:06:12 +08:00
auto buffer = CreateBuffer(device, buffer_size, buffer_usage);
2024-05-07 00:33:19 +08:00
auto memory = allocator.Allocate(pdevice, device, *buffer, memory_flags);
2024-05-22 22:06:12 +08:00
BindBufferMemory(device, *buffer, memory->Memory(), s_cast<uint32_t>(memory->Offset()));
2024-05-07 00:33:19 +08:00
return std::make_pair(std::move(buffer), std::move(memory));
}
template<typename T, typename Dispatcher>
std::pair<vk::UniqueBuffer, vk::UniqueDeviceMemory> CreateAllocBindVertexBuffer(
vk::PhysicalDevice pdevice, vk::Device device, T const* vertices, T const* vertices_end, const Dispatcher& dispatcher
)
{
2024-05-22 22:06:12 +08:00
return CreateAllocBindBuffer(pdevice, device, buffer_size(vertices, vertices_end), vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
2024-05-07 00:33:19 +08:00
}
template<typename T, typename Dispatcher>
std::pair<vk::UniqueBuffer, vk::UniqueDeviceMemory> CreateAllocBindVertexBuffer(
vk::PhysicalDevice pdevice, vk::Device device, std::vector<T> const& vertices, const Dispatcher& dispatcher
)
{
2024-05-22 22:06:12 +08:00
return CreateAllocBindVertexBuffer(pdevice, device, vertices.data(), vertices.data() + vertices.size());
2024-05-07 00:33:19 +08:00
}
template<typename T, typename Dispatcher>
void MapMemory(vk::Device device, vk::DeviceMemory memory, vk::DeviceSize dest_offset, T* src_start, vk::DeviceSize trf_size, Dispatcher const& dispatcher)
{
vk::MappedMemoryRange mmr
{
memory
,dest_offset
,trf_size
};
2024-05-22 22:06:12 +08:00
auto handle = device.mapMemory(memory, mmr.offset, mmr.size, vk::MemoryMapFlags{});
2024-05-07 00:33:19 +08:00
memcpy_s(handle, mmr.size, src_start, mmr.size);
//std::vector<decltype(mmr)> memory_ranges
//{
// mmr
//};
//Not necessary rn since we set the HostCoherent bit
//This command only guarantees that the memory(on gpu) will be updated by vkQueueSubmit
//device.flushMappedMemoryRanges(memory_ranges, dispatcher);
device.unmapMemory(memory);
}
template<typename T>
vk::ArrayProxy<const T> make_array_proxy(uint32_t sz, T* arr)
{
return vk::ArrayProxy<const T>{sz, arr};
}
namespace detail
{
template<typename T, typename = decltype(std::data(std::declval<T>()))>
std::true_type has_data(const T&);
template<typename T, typename ...Args>
std::false_type has_data(T, Args...);
template<typename T>
static constexpr bool has_data_v = std::is_same_v<decltype(has_data(std::declval<T>())), std::true_type>;
}
//
template<typename RT = size_t, typename T>
RT buffer_size(T const& vertices)
{
if constexpr (detail::has_data_v<T>)
{
return static_cast<RT>(sizeof(*std::data(vertices)) * hlp::arr_count(vertices));
}
else
{
return static_cast<RT>(sizeof(vertices));
}
}
template<typename RT = size_t, typename T = int>
RT buffer_size(T* begin, T* end)
{
return static_cast<RT>(sizeof(T) * (end - begin));
}
template<typename T>
auto buffer_data(T& obj)
{
if constexpr (detail::has_data_v<T>)
{
return std::data(obj);
}
else
{
return &obj;
}
}
template<typename RT, typename T>
RT buffer_data(T& obj)
{
return reinterpret_cast<RT>(buffer_data(obj));
}
#pragma optimize("",on)
template<typename T>
string_view to_data(const T& obj)
{
static_assert(!std::is_pointer_v<T>, "Pointers should not be read as data. Convert to intptr_t if that is indeed the intention.");
return string_view{ reinterpret_cast<const char*>(hlp::buffer_data(obj)), hlp::buffer_size(obj) };
}
}