feat(renderer): storage & staging buffer types
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
This commit is contained in:
parent
2ddb90faff
commit
5422792705
5 changed files with 101 additions and 34 deletions
|
|
@ -16,7 +16,7 @@ Buffer::Buffer(IDevice *device, IGpu *gpu, const CreateInfo &info)
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
.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)
|
, m_size(info.size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -31,30 +31,18 @@ void Buffer::unmap() /* override */
|
||||||
m_device->unmap_memory(m_memory);
|
m_device->unmap_memory(m_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags
|
[[nodiscard]] auto Buffer::determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo
|
||||||
{
|
|
||||||
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);
|
const auto requirements = m_device->get_memory_requirements(m_buffer);
|
||||||
auto memory_properties = m_gpu->get_memory_properties();
|
auto memory_properties = m_gpu->get_memory_properties();
|
||||||
|
|
||||||
const auto required_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
const auto required_properties = to_native_memory_properties(usage);
|
||||||
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
||||||
auto type = 0u;
|
auto type = 0u;
|
||||||
for (auto idx = 0; idx < memory_properties.memoryTypeCount; ++idx)
|
for (auto idx = 0; idx < memory_properties.memoryTypeCount; ++idx)
|
||||||
{
|
{
|
||||||
if ((requirements.memoryTypeBits & (1 << idx))
|
const auto property_flags = memory_properties.memoryTypes[idx].propertyFlags;
|
||||||
&& ((memory_properties.memoryTypes[idx].propertyFlags & required_properties)
|
if (has_correct_memory_type_bit(requirements.memoryTypeBits, idx)
|
||||||
== required_properties))
|
&& has_required_memory_properties(required_properties, property_flags))
|
||||||
|
|
||||||
{
|
{
|
||||||
type = idx;
|
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
|
} // namespace lt::renderer::vk
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,36 @@ public:
|
||||||
|
|
||||||
void unmap() override;
|
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
|
[[nodiscard]] auto get_size() const -> size_t override
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
[[nodiscard]] auto determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo;
|
||||||
|
|
||||||
[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags;
|
[[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 {};
|
Device *m_device {};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <renderer/backend/vk/data/buffer.hpp>
|
#include <renderer/backend/vk/data/buffer.hpp>
|
||||||
#include <renderer/frontend/data/buffer.hpp>
|
#include <renderer/frontend/data/buffer.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,15 @@ namespace lt::renderer {
|
||||||
class IBuffer
|
class IBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Usage : uint8_t
|
enum class Usage : uint8_t
|
||||||
{
|
{
|
||||||
vertex,
|
vertex,
|
||||||
|
|
||||||
index,
|
index,
|
||||||
|
|
||||||
|
storage,
|
||||||
|
|
||||||
|
staging,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CreateInfo
|
struct CreateInfo
|
||||||
|
|
@ -24,6 +28,13 @@ public:
|
||||||
std::string debug_name;
|
std::string debug_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CopyInfo
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] static auto create(
|
[[nodiscard]] static auto create(
|
||||||
Api target_api,
|
Api target_api,
|
||||||
class IDevice *device,
|
class IDevice *device,
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,19 @@ Suite raii = "buffer_raii"_suite = [] {
|
||||||
Case { "happy path won't throw" } = [] {
|
Case { "happy path won't throw" } = [] {
|
||||||
auto fixture = FixtureDeviceSwapchain {};
|
auto fixture = FixtureDeviceSwapchain {};
|
||||||
|
|
||||||
ignore = IBuffer::create(
|
for (auto idx = 0; idx <= std::to_underlying(IBuffer::Usage::staging); ++idx)
|
||||||
lt::renderer::Api::vulkan,
|
{
|
||||||
fixture.device(),
|
ignore = IBuffer::create(
|
||||||
fixture.gpu(),
|
lt::renderer::Api::vulkan,
|
||||||
IBuffer::CreateInfo {
|
fixture.device(),
|
||||||
.usage = IBuffer::Usage::vertex,
|
fixture.gpu(),
|
||||||
.size = 1000u,
|
IBuffer::CreateInfo {
|
||||||
.debug_name = "",
|
.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(error));
|
||||||
expect_false(fixture.has_any_messages_of(warning));
|
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);
|
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(error));
|
||||||
|
|
@ -96,7 +99,7 @@ Suite mapping = "buffer_mapping"_suite = [] {
|
||||||
fixture.device(),
|
fixture.device(),
|
||||||
fixture.gpu(),
|
fixture.gpu(),
|
||||||
IBuffer::CreateInfo {
|
IBuffer::CreateInfo {
|
||||||
.usage = IBuffer::Usage::vertex,
|
.usage = IBuffer::Usage::staging,
|
||||||
.size = size,
|
.size = size,
|
||||||
.debug_name = "",
|
.debug_name = "",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue