feat(renderer): storage & staging buffer types
Some checks reported errors
continuous-integration/drone/push Build was killed

This commit is contained in:
light7734 2025-10-27 23:29:08 +03:30
parent 2ddb90faff
commit 5422792705
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
5 changed files with 101 additions and 34 deletions

View file

@ -16,7 +16,7 @@ Buffer::Buffer(IDevice *device, IGpu *gpu, const CreateInfo &info)
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
}
)
, m_memory(m_device, m_buffer, allocation_info_from_memory_requirements())
, m_memory(m_device, m_buffer, determine_allocation_info(info.usage))
, m_size(info.size)
{
}
@ -31,30 +31,18 @@ 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
[[nodiscard]] auto Buffer::determine_allocation_info(Usage usage) 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;
const auto required_properties = to_native_memory_properties(usage);
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))
const auto property_flags = memory_properties.memoryTypes[idx].propertyFlags;
if (has_correct_memory_type_bit(requirements.memoryTypeBits, idx)
&& has_required_memory_properties(required_properties, property_flags))
{
type = idx;
@ -69,4 +57,50 @@ void Buffer::unmap() /* override */
};
}
[[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags
{
switch (usage)
{
case Usage::vertex: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
case Usage::index: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
case Usage::storage:
return VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
case Usage::staging: return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
}
std::unreachable();
}
[[nodiscard]] auto Buffer::to_native_memory_properties(Usage usage) const -> VkMemoryPropertyFlags
{
switch (usage)
{
case Usage::vertex:
case Usage::index:
case Usage::storage: return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
case Usage::staging:
return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
}
std::unreachable();
}
[[nodiscard]] auto Buffer::has_correct_memory_type_bit(uint32_t type_bits, uint32_t type_idx) const
-> bool
{
return type_bits & (1 << type_idx);
}
[[nodiscard]] auto Buffer::has_required_memory_properties(
uint32_t required_properties,
uint32_t property_flags
) const -> bool
{
return (property_flags & required_properties) == required_properties;
}
} // namespace lt::renderer::vk

View file

@ -14,15 +14,36 @@ public:
void unmap() override;
// TODO(Light): this is to make copying possible.
// But it should be removed in the future,
// Right now it's not possible because: buffers can't understand CommandBuffers.
// And I'm not sure how to properly abstract over command buffers,
// before using other APIs...
[[nodiscard]] auto vk()
{
return *m_buffer;
}
[[nodiscard]] auto get_size() const -> size_t override
{
return m_size;
}
private:
[[nodiscard]] auto determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo;
[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags;
[[nodiscard]] auto allocation_info_from_memory_requirements() const -> VkMemoryAllocateInfo;
[[nodiscard]] auto to_native_memory_properties(Usage usage) const -> VkMemoryPropertyFlags;
[[nodiscard]] auto has_correct_memory_type_bit(uint32_t type_bits, uint32_t type_idx) const
-> bool;
[[nodiscard]] auto has_required_memory_properties(
uint32_t required_properties,
uint32_t property_flags
) const -> bool;
Device *m_device {};

View file

@ -1,5 +1,3 @@
#pragma once
#include <renderer/backend/vk/data/buffer.hpp>
#include <renderer/frontend/data/buffer.hpp>

View file

@ -8,11 +8,15 @@ namespace lt::renderer {
class IBuffer
{
public:
enum Usage : uint8_t
enum class Usage : uint8_t
{
vertex,
index,
storage,
staging,
};
struct CreateInfo
@ -24,6 +28,13 @@ public:
std::string debug_name;
};
struct CopyInfo
{
size_t offset;
size_t size;
};
[[nodiscard]] static auto create(
Api target_api,
class IDevice *device,

View file

@ -8,16 +8,19 @@ Suite raii = "buffer_raii"_suite = [] {
Case { "happy path won't throw" } = [] {
auto fixture = FixtureDeviceSwapchain {};
for (auto idx = 0; idx <= std::to_underlying(IBuffer::Usage::staging); ++idx)
{
ignore = IBuffer::create(
lt::renderer::Api::vulkan,
fixture.device(),
fixture.gpu(),
IBuffer::CreateInfo {
.usage = IBuffer::Usage::vertex,
.usage = static_cast<IBuffer::Usage>(idx),
.size = 1000u,
.debug_name = "",
}
);
}
expect_false(fixture.has_any_messages_of(error));
expect_false(fixture.has_any_messages_of(warning));
@ -77,7 +80,7 @@ Suite raii = "buffer_raii"_suite = [] {
);
});
/** Make sure the default-case was good */
/** Make sure the default-case was OK */
ignore = IBuffer::create(lt::renderer::Api::vulkan, fixture.device(), fixture.gpu(), info);
expect_false(fixture.has_any_messages_of(error));
@ -96,7 +99,7 @@ Suite mapping = "buffer_mapping"_suite = [] {
fixture.device(),
fixture.gpu(),
IBuffer::CreateInfo {
.usage = IBuffer::Usage::vertex,
.usage = IBuffer::Usage::staging,
.size = size,
.debug_name = "",
}