feat(renderer): buffer #61
17 changed files with 493 additions and 31 deletions
|
|
@ -8,15 +8,17 @@ add_library_module(
|
|||
backend/vk/context/instance.cpp
|
||||
backend/vk/context/surface.cpp
|
||||
backend/vk/context/swapchain.cpp
|
||||
backend/vk/data/buffer.cpp
|
||||
backend/vk/renderer/pass.cpp
|
||||
backend/vk/renderer/renderer.cpp
|
||||
# Vulkan - frontend
|
||||
# frontend
|
||||
frontend/messenger.cpp
|
||||
frontend/context/device.cpp
|
||||
frontend/context/gpu.cpp
|
||||
frontend/context/instance.cpp
|
||||
frontend/context/surface.cpp
|
||||
frontend/context/swapchain.cpp
|
||||
frontend/data/buffer.cpp
|
||||
frontend/renderer/renderer.cpp
|
||||
frontend/renderer/pass.cpp)
|
||||
|
||||
|
|
@ -34,11 +36,10 @@ add_test_module(
|
|||
frontend/context/surface.test.cpp
|
||||
frontend/context/device.test.cpp
|
||||
frontend/context/swapchain.test.cpp
|
||||
frontend/data/buffer.test.cpp
|
||||
frontend/renderer/pass.test.cpp
|
||||
frontend/renderer/renderer.test.cpp
|
||||
# backend specific tests -- vk
|
||||
backend/vk/context/instance.test.cpp
|
||||
# backend specific tests -- dx backend specific tests -- mt
|
||||
)
|
||||
backend/vk/context/instance.test.cpp)
|
||||
|
||||
target_link_libraries(renderer_tests PRIVATE surface pthread)
|
||||
|
|
|
|||
|
|
@ -207,6 +207,31 @@ void Device::wait_for_fences(std::span<VkFence> fences) const
|
|||
return images;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Device::get_memory_requirements(VkBuffer buffer) const -> VkMemoryRequirements
|
||||
{
|
||||
auto requirements = VkMemoryRequirements {};
|
||||
vk_get_buffer_memory_requirements(m_device, buffer, &requirements);
|
||||
return requirements;
|
||||
}
|
||||
|
||||
void Device::bind_memory(VkBuffer buffer, VkDeviceMemory memory, size_t offset /* = 0u */) const
|
||||
{
|
||||
vkc(vk_bind_buffer_memory(m_device, buffer, memory, offset));
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Device::map_memory(VkDeviceMemory memory, size_t size, size_t offset) const
|
||||
-> std::span<std::byte>
|
||||
{
|
||||
void *data = {};
|
||||
vkc(vk_map_memory(m_device, memory, offset, size, {}, &data));
|
||||
return { std::bit_cast<std::byte *>(data), size };
|
||||
}
|
||||
|
||||
void Device::unmap_memory(VkDeviceMemory memory)
|
||||
{
|
||||
vk_unmap_memory(m_device, memory);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Device::create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR
|
||||
{
|
||||
auto *swapchain = VkSwapchainKHR {};
|
||||
|
|
@ -299,6 +324,13 @@ void Device::wait_for_fences(std::span<VkFence> fences) const
|
|||
return fences;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Device::create_buffer(VkBufferCreateInfo info) const -> VkBuffer
|
||||
{
|
||||
auto *buffer = VkBuffer {};
|
||||
vkc(vk_create_buffer(m_device, &info, nullptr, &buffer));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Device::allocate_command_buffers(VkCommandBufferAllocateInfo info) const
|
||||
-> std::vector<VkCommandBuffer>
|
||||
{
|
||||
|
|
@ -307,6 +339,18 @@ void Device::wait_for_fences(std::span<VkFence> fences) const
|
|||
return command_buffers;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Device::allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory
|
||||
{
|
||||
auto *memory = VkDeviceMemory {};
|
||||
vkc(vk_allocate_memory(m_device, &info, nullptr, &memory));
|
||||
return memory;
|
||||
}
|
||||
|
||||
void Device::free_memory(VkDeviceMemory memory) const
|
||||
{
|
||||
vk_free_memory(m_device, memory, nullptr);
|
||||
}
|
||||
|
||||
void Device::destroy_swapchain(VkSwapchainKHR swapchain) const
|
||||
{
|
||||
vk_destroy_swapchain_khr(m_device, swapchain, m_allocator);
|
||||
|
|
@ -389,4 +433,9 @@ void Device::destroy_fences(std::span<VkFence> fences) const
|
|||
}
|
||||
}
|
||||
|
||||
void Device::destroy_buffer(VkBuffer buffer) const
|
||||
{
|
||||
vk_destroy_buffer(m_device, buffer, nullptr);
|
||||
}
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
|
|||
|
|
@ -96,6 +96,16 @@ public:
|
|||
|
||||
[[nodiscard]] auto get_swapchain_images(VkSwapchainKHR swapchain) const -> std::vector<VkImage>;
|
||||
|
||||
[[nodiscard]] auto get_memory_requirements(VkBuffer buffer) const -> VkMemoryRequirements;
|
||||
|
||||
/** binders / mappers */
|
||||
void bind_memory(VkBuffer buffer, VkDeviceMemory memory, size_t offset = 0u) const;
|
||||
|
||||
[[nodiscard]] auto map_memory(VkDeviceMemory memory, size_t size, size_t offset) const
|
||||
-> std::span<std::byte>;
|
||||
|
||||
void unmap_memory(VkDeviceMemory memory);
|
||||
|
||||
/** create functions */
|
||||
[[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR;
|
||||
|
||||
|
|
@ -120,10 +130,17 @@ public:
|
|||
[[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const
|
||||
-> std::vector<VkFence>;
|
||||
|
||||
[[nodiscard]] auto create_buffer(VkBufferCreateInfo info) const -> VkBuffer;
|
||||
|
||||
/** allocation functions */
|
||||
[[nodiscard]] auto allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory;
|
||||
|
||||
[[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const
|
||||
-> std::vector<VkCommandBuffer>;
|
||||
|
||||
/** de-allocation functions */
|
||||
void free_memory(VkDeviceMemory memory) const;
|
||||
|
||||
/** destroy functions */
|
||||
void destroy_swapchain(VkSwapchainKHR swapchain) const;
|
||||
|
||||
|
|
@ -153,6 +170,8 @@ public:
|
|||
|
||||
void destroy_fences(std::span<VkFence> fences) const;
|
||||
|
||||
void destroy_buffer(VkBuffer buffer) const;
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static auto get_object_type(const T &object) -> VkObjectType
|
||||
|
|
|
|||
|
|
@ -67,5 +67,11 @@ Gpu::Gpu(IInstance *instance)
|
|||
return formats;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Gpu::get_memory_properties() const -> VkPhysicalDeviceMemoryProperties
|
||||
{
|
||||
auto memory_properties = VkPhysicalDeviceMemoryProperties {};
|
||||
vk_get_physical_device_memory_properties(m_gpu, &memory_properties);
|
||||
return memory_properties;
|
||||
}
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ public:
|
|||
[[nodiscard]] auto get_surface_formats(VkSurfaceKHR surface) const
|
||||
-> std::vector<VkSurfaceFormatKHR>;
|
||||
|
||||
[[nodiscard]] auto get_memory_properties() const -> VkPhysicalDeviceMemoryProperties;
|
||||
|
||||
private:
|
||||
memory::NullOnMove<VkPhysicalDevice> m_gpu = VK_NULL_HANDLE;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ PFN_vkGetDeviceProcAddr vk_get_device_proc_address {};
|
|||
PFN_vkDestroyDevice vk_destroy_device {};
|
||||
PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features {};
|
||||
PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties {};
|
||||
PFN_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties {};
|
||||
|
||||
// extension instance functions
|
||||
PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label {};
|
||||
|
|
@ -87,6 +88,16 @@ PFN_vkCmdDraw vk_cmd_draw {};
|
|||
PFN_vkCmdSetViewport vk_cmd_set_viewport {};
|
||||
PFN_vkCmdSetScissor vk_cmd_set_scissors {};
|
||||
|
||||
PFN_vkCreateBuffer vk_create_buffer {};
|
||||
PFN_vkDestroyBuffer vk_destroy_buffer {};
|
||||
PFN_vkGetBufferMemoryRequirements vk_get_buffer_memory_requirements {};
|
||||
PFN_vkAllocateMemory vk_allocate_memory {};
|
||||
PFN_vkBindBufferMemory vk_bind_buffer_memory {};
|
||||
PFN_vkMapMemory vk_map_memory {};
|
||||
PFN_vkUnmapMemory vk_unmap_memory {};
|
||||
PFN_vkFreeMemory vk_free_memory {};
|
||||
|
||||
|
||||
PFN_vkResetCommandBuffer vk_reset_command_buffer {};
|
||||
|
||||
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {};
|
||||
|
|
@ -298,6 +309,7 @@ void Instance::load_instance_functions()
|
|||
load_fn(vk_destroy_device, "vkDestroyDevice");
|
||||
load_fn(vk_get_physical_device_features, "vkGetPhysicalDeviceFeatures");
|
||||
load_fn(vk_enumerate_device_extension_properties, "vkEnumerateDeviceExtensionProperties");
|
||||
load_fn(vk_get_physical_device_memory_properties, "vkGetPhysicalDeviceMemoryProperties");
|
||||
|
||||
load_fn(vk_cmd_begin_debug_label, "vkCmdBeginDebugUtilsLabelEXT");
|
||||
load_fn(vk_cmd_end_debug_label, "vkCmdEndDebugUtilsLabelEXT");
|
||||
|
|
@ -370,6 +382,14 @@ void Instance::load_device_functions_impl(VkDevice device)
|
|||
load_fn(vk_cmd_draw, "vkCmdDraw");
|
||||
load_fn(vk_cmd_set_viewport, "vkCmdSetViewport");
|
||||
load_fn(vk_cmd_set_scissors, "vkCmdSetScissor");
|
||||
load_fn(vk_create_buffer, "vkCreateBuffer");
|
||||
load_fn(vk_destroy_buffer, "vkDestroyBuffer");
|
||||
load_fn(vk_allocate_memory, "vkAllocateMemory");
|
||||
load_fn(vk_bind_buffer_memory, "vkBindBufferMemory");
|
||||
load_fn(vk_map_memory, "vkMapMemory");
|
||||
load_fn(vk_unmap_memory, "vkUnmapMemory");
|
||||
load_fn(vk_free_memory, "vkFreeMemory");
|
||||
load_fn(vk_get_buffer_memory_requirements, "vkGetBufferMemoryRequirements");
|
||||
load_fn(vk_reset_command_buffer, "vkResetCommandBuffer");
|
||||
}
|
||||
|
||||
|
|
|
|||
72
modules/renderer/private/backend/vk/data/buffer.cpp
Normal file
72
modules/renderer/private/backend/vk/data/buffer.cpp
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#include <renderer/backend/vk/context/device.hpp>
|
||||
#include <renderer/backend/vk/context/gpu.hpp>
|
||||
#include <renderer/backend/vk/data/buffer.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
Buffer::Buffer(IDevice *device, IGpu *gpu, const CreateInfo &info)
|
||||
: m_device(static_cast<Device *>(device))
|
||||
, m_gpu(static_cast<Gpu *>(gpu))
|
||||
, m_buffer(
|
||||
m_device,
|
||||
VkBufferCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = info.size,
|
||||
.usage = to_native_usage_flags(info.usage),
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
}
|
||||
)
|
||||
, m_memory(m_device, m_buffer, allocation_info_from_memory_requirements())
|
||||
, m_size(info.size)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Buffer::map() -> std::span<std::byte> /* override */
|
||||
{
|
||||
return m_device->map_memory(m_memory, m_size, 0ul);
|
||||
}
|
||||
|
||||
void Buffer::unmap() /* override */
|
||||
{
|
||||
m_device->unmap_memory(m_memory);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags
|
||||
{
|
||||
switch (usage)
|
||||
{
|
||||
case Usage::vertex: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||
case Usage::index: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||
}
|
||||
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Buffer::allocation_info_from_memory_requirements() const -> VkMemoryAllocateInfo
|
||||
{
|
||||
const auto requirements = m_device->get_memory_requirements(m_buffer);
|
||||
auto memory_properties = m_gpu->get_memory_properties();
|
||||
|
||||
const auto required_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
||||
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
||||
auto type = 0u;
|
||||
for (auto idx = 0; idx < memory_properties.memoryTypeCount; ++idx)
|
||||
{
|
||||
if ((requirements.memoryTypeBits & (1 << idx))
|
||||
&& ((memory_properties.memoryTypes[idx].propertyFlags & required_properties)
|
||||
== required_properties))
|
||||
|
||||
{
|
||||
type = idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return VkMemoryAllocateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = requirements.size,
|
||||
.memoryTypeIndex = type,
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
39
modules/renderer/private/backend/vk/data/buffer.hpp
Normal file
39
modules/renderer/private/backend/vk/data/buffer.hpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include <renderer/backend/vk/raii/raii.hpp>
|
||||
#include <renderer/frontend/data/buffer.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
class Buffer: public IBuffer
|
||||
{
|
||||
public:
|
||||
Buffer(class IDevice *device, class IGpu *gpu, const CreateInfo &info);
|
||||
|
||||
[[nodiscard]] auto map() -> std::span<std::byte> override;
|
||||
|
||||
void unmap() override;
|
||||
|
||||
[[nodiscard]] auto get_size() const -> size_t override
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags;
|
||||
|
||||
[[nodiscard]] auto allocation_info_from_memory_requirements() const -> VkMemoryAllocateInfo;
|
||||
|
||||
Device *m_device {};
|
||||
|
||||
Gpu *m_gpu {};
|
||||
|
||||
raii::Buffer m_buffer;
|
||||
|
||||
raii::Memory m_memory;
|
||||
|
||||
// TODO(Light): should this reflect the allocation size instead?
|
||||
size_t m_size {};
|
||||
};
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
#include <memory/pointer_types/null_on_move.hpp>
|
||||
#include <renderer/backend/vk/context/device.hpp>
|
||||
#include <renderer/backend/vk/context/instance.hpp>
|
||||
#include <renderer/backend/vk/vulkan.hpp>
|
||||
|
||||
namespace lt::renderer::vk::raii {
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
|
||||
namespace lt::renderer::vk::raii { // NOLINTBEGIN(cppcoreguidelines-special-member-functions)
|
||||
|
||||
class DebugMessenger
|
||||
{
|
||||
public:
|
||||
|
|
@ -16,12 +17,10 @@ public:
|
|||
|
||||
~DebugMessenger()
|
||||
{
|
||||
if (!m_instance)
|
||||
if (m_instance)
|
||||
{
|
||||
return;
|
||||
m_instance->destroy_messenger(m_object);
|
||||
}
|
||||
|
||||
m_instance->destroy_messenger(m_object);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -30,4 +29,74 @@ private:
|
|||
VkDebugUtilsMessengerEXT m_object;
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
Buffer(Device *device, VkBufferCreateInfo info)
|
||||
: m_device(device)
|
||||
, m_object(m_device->create_buffer(info))
|
||||
{
|
||||
}
|
||||
|
||||
~Buffer()
|
||||
{
|
||||
if (m_device)
|
||||
{
|
||||
m_device->destroy_buffer(m_object);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] auto operator*() const -> VkBuffer
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
[[nodiscard]] operator VkBuffer() const
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
private:
|
||||
memory::NullOnMove<Device *> m_device {};
|
||||
|
||||
VkBuffer m_object;
|
||||
};
|
||||
|
||||
class Memory
|
||||
{
|
||||
public:
|
||||
Memory(Device *device, VkBuffer buffer, VkMemoryAllocateInfo info)
|
||||
: m_device(device)
|
||||
, m_object(m_device->allocate_memory(info))
|
||||
{
|
||||
m_device->bind_memory(buffer, m_object);
|
||||
}
|
||||
|
||||
~Memory()
|
||||
{
|
||||
if (m_device)
|
||||
{
|
||||
m_device->free_memory(m_object);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] auto operator*() const -> VkDeviceMemory
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
[[nodiscard]] operator VkDeviceMemory() const
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
private:
|
||||
memory::NullOnMove<Device *> m_device {};
|
||||
|
||||
VkDeviceMemory m_object = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-special-member-functions)
|
||||
} // namespace lt::renderer::vk::raii
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
// template<>
|
||||
// struct std::formatter<VkExtent2D>
|
||||
// {
|
||||
// constexpr auto parse(std::format_parse_context &context)
|
||||
// {
|
||||
// return context.begin();
|
||||
// }
|
||||
//
|
||||
// auto format(const VkExtent2D &val, std::format_context &context) const
|
||||
// {
|
||||
// return std::format_to(context.out(), "{}, {}", val.width, val.height);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// inline auto operator==(VkExtent2D lhs, VkExtent2D rhs) -> bool
|
||||
// {
|
||||
// return lhs.width == rhs.width && lhs.height == rhs.height;
|
||||
// }
|
||||
|
|
@ -15,6 +15,7 @@ extern PFN_vkGetDeviceProcAddr vk_get_device_proc_address;
|
|||
extern PFN_vkDestroyDevice vk_destroy_device;
|
||||
extern PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features;
|
||||
extern PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties;
|
||||
extern PFN_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties;
|
||||
|
||||
// extension instance functions
|
||||
extern PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label;
|
||||
|
|
@ -76,6 +77,15 @@ extern PFN_vkCmdDraw vk_cmd_draw;
|
|||
extern PFN_vkCmdSetViewport vk_cmd_set_viewport;
|
||||
extern PFN_vkCmdSetScissor vk_cmd_set_scissors;
|
||||
|
||||
extern PFN_vkCreateBuffer vk_create_buffer;
|
||||
extern PFN_vkDestroyBuffer vk_destroy_buffer;
|
||||
extern PFN_vkGetBufferMemoryRequirements vk_get_buffer_memory_requirements;
|
||||
extern PFN_vkAllocateMemory vk_allocate_memory;
|
||||
extern PFN_vkBindBufferMemory vk_bind_buffer_memory;
|
||||
extern PFN_vkMapMemory vk_map_memory;
|
||||
extern PFN_vkUnmapMemory vk_unmap_memory;
|
||||
extern PFN_vkFreeMemory vk_free_memory;
|
||||
|
||||
extern PFN_vkResetCommandBuffer vk_reset_command_buffer;
|
||||
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
|
|
|
|||
29
modules/renderer/private/frontend/data/buffer.cpp
Normal file
29
modules/renderer/private/frontend/data/buffer.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include <renderer/backend/vk/data/buffer.hpp>
|
||||
#include <renderer/frontend/data/buffer.hpp>
|
||||
|
||||
namespace lt::renderer {
|
||||
|
||||
|
||||
[[nodiscard]] /* static */ auto IBuffer::create(
|
||||
Api target_api,
|
||||
class IDevice *device,
|
||||
class IGpu *gpu,
|
||||
const CreateInfo &info
|
||||
) -> memory::Scope<IBuffer>
|
||||
{
|
||||
ensure(device, "Failed to create renderer::IBuffer: null device");
|
||||
ensure(gpu, "Failed to create renderer::IBuffer: null gpu");
|
||||
ensure(info.size > 0, "Failed to create renderer::IBuffer: null size");
|
||||
|
||||
switch (target_api)
|
||||
{
|
||||
case Api::vulkan: return memory::create_scope<vk::Buffer>(device, gpu, info);
|
||||
case Api::none:
|
||||
case Api::metal:
|
||||
case Api::direct_x: throw std::runtime_error { "Invalid API" };
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lt::renderer
|
||||
55
modules/renderer/private/frontend/data/buffer.hpp
Normal file
55
modules/renderer/private/frontend/data/buffer.hpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory/scope.hpp>
|
||||
#include <renderer/api.hpp>
|
||||
|
||||
namespace lt::renderer {
|
||||
|
||||
class IBuffer
|
||||
{
|
||||
public:
|
||||
enum Usage : uint8_t
|
||||
{
|
||||
vertex,
|
||||
|
||||
index,
|
||||
};
|
||||
|
||||
struct CreateInfo
|
||||
{
|
||||
Usage usage;
|
||||
|
||||
size_t size;
|
||||
|
||||
std::string debug_name;
|
||||
};
|
||||
|
||||
[[nodiscard]] static auto create(
|
||||
Api target_api,
|
||||
class IDevice *device,
|
||||
class IGpu *gpu,
|
||||
const CreateInfo &info
|
||||
) -> memory::Scope<IBuffer>;
|
||||
|
||||
IBuffer() = default;
|
||||
|
||||
virtual ~IBuffer() = default;
|
||||
|
||||
IBuffer(IBuffer &&) = default;
|
||||
|
||||
IBuffer(const IBuffer &) = delete;
|
||||
|
||||
auto operator=(IBuffer &&) -> IBuffer & = default;
|
||||
|
||||
auto operator=(const IBuffer &) -> IBuffer & = delete;
|
||||
|
||||
[[nodiscard]] virtual auto map() -> std::span<std::byte> = 0;
|
||||
|
||||
virtual void unmap() = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_size() const -> size_t = 0;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace lt::renderer
|
||||
112
modules/renderer/private/frontend/data/buffer.test.cpp
Normal file
112
modules/renderer/private/frontend/data/buffer.test.cpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#include <renderer/frontend/data/buffer.hpp>
|
||||
#include <renderer/test/utils.hpp>
|
||||
|
||||
using ::lt::renderer::IBuffer;
|
||||
using enum ::lt::renderer::IMessenger::MessageSeverity;
|
||||
|
||||
Suite raii = "buffer_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
IBuffer::CreateInfo {
|
||||
.usage = IBuffer::Usage::vertex,
|
||||
.size = 1000u,
|
||||
.debug_name = "",
|
||||
}
|
||||
);
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
auto info = IBuffer::CreateInfo {
|
||||
.usage = IBuffer::Usage::vertex,
|
||||
.size = 10000u,
|
||||
.debug_name = "",
|
||||
};
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(lt::renderer::Api::vulkan, nullptr, fixture.gpu(), info);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(lt::renderer::Api::vulkan, fixture.device(), nullptr, info);
|
||||
});
|
||||
|
||||
expect_throw([&, info] mutable {
|
||||
info.size = 0;
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::direct_x,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::metal,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::none,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
/** Make sure the default-case was good */
|
||||
ignore = IBuffer::create(lt::renderer::Api::vulkan, fixture.device(), fixture.gpu(), info);
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
};
|
||||
|
||||
Suite mapping = "buffer_mapping"_suite = [] {
|
||||
Case { "mapping" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
constexpr auto size = 1000u;
|
||||
|
||||
auto buffer = IBuffer::create(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
IBuffer::CreateInfo {
|
||||
.usage = IBuffer::Usage::vertex,
|
||||
.size = size,
|
||||
.debug_name = "",
|
||||
}
|
||||
);
|
||||
|
||||
auto map = buffer->map();
|
||||
expect_eq(map.size(), size);
|
||||
expect_not_nullptr(map.data());
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
};
|
||||
|
|
@ -1 +0,0 @@
|
|||
|
||||
|
|
@ -148,7 +148,6 @@ public:
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] auto has_any_messages() const -> bool
|
||||
{
|
||||
return m_user_data->m_has_any_messages;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace lt::renderer {
|
||||
|
||||
|
||||
class IMessenger
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue