[WIP] Updated Buffers.

TODO: Update Image and Views.
This commit is contained in:
Anish Bhobe 2025-04-06 21:02:58 +02:00
parent 1bee73e46f
commit d8770c1e06
24 changed files with 130 additions and 374 deletions

View File

@ -9,109 +9,47 @@
struct Device; struct Device;
// TODO Refactor the Buffer Hierarchy /// A Vulkan buffer wrapper.
struct Buffer final
struct Buffer
{ {
const Device *m_Device = nullptr; ///< Will be used for book-keeping when buffer is invalid. const Device *m_Device = nullptr;
vk::Buffer m_Buffer = nullptr; vk::Buffer m_Buffer = nullptr;
VmaAllocation m_Allocation = nullptr; VmaAllocation m_Allocation = nullptr;
u8 *m_Mapped = nullptr; ///< If the buffer is host visible, it should be (and stay) mapped. u8 *m_Mapped = nullptr; ///< If the buffer is host visible, it should be (and stay) mapped.
usize m_Size = 0; usize m_Size = 0;
std::atomic<u32> m_RefCount = 0;
[[nodiscard]] bool
IsHostVisible() const
{
return m_Mapped;
}
/// @returns True if it is a valid vulkan buffer.
[[nodiscard]] bool [[nodiscard]] bool
IsValid() const IsValid() const
{ {
return m_Buffer; return m_Buffer;
} }
/// If the buffer is host visible, it should be (and stay) mapped.
/// @returns True if the buffer is host-visible and mapped.
[[nodiscard]] bool [[nodiscard]] bool
IsMapped() const IsMapped() const
{ {
return m_Mapped; return m_Mapped;
} }
void /// Writes the data to the buffer.
AddRef() /// @note The buffer must be mapped.
{ void Write(usize offset, usize size, const void *data) const;
assert(++m_RefCount > 0);
}
void
Release()
{
const auto rc = --m_RefCount;
assert(rc < MaxValue<u32>);
if (rc == 0)
{
Destroy();
}
}
[[nodiscard]] bool
IsReferenced()
{
return m_RefCount;
}
void Destroy();
~Buffer()
{
Destroy();
}
void Write(usize offset, usize size, const void *data);
void Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUsage,
VmaAllocationCreateFlags allocationFlags, VmaMemoryUsage memoryUsage, cstr name);
/// If Buffer Device Address is enabled,
/// Get a pointer.
uptr GetDeviceAddress(const Device *device) const; uptr GetDeviceAddress(const Device *device) const;
};
struct UniformBuffer : Buffer // Constructors
{
void Init(const Device *device, usize size, cstr name = nullptr);
};
struct StorageBuffer : Buffer Buffer(const Device *device, usize size, vk::BufferUsageFlags bufferUsage, VmaAllocationCreateFlags allocationFlags,
{ VmaMemoryUsage memoryUsage, cstr name);
void Init(const Device *device, usize size, bool hostVisible, cstr name = nullptr);
void Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name = nullptr);
};
struct IndirectBuffer : Buffer Buffer(Buffer &&other) noexcept;
{ Buffer &operator=(Buffer &&other) noexcept;
void Init(const Device *device, usize size, bool hostVisible, cstr name = nullptr);
};
struct StorageIndexBuffer : StorageBuffer ~Buffer();
{
void Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name = nullptr);
};
struct VertexBuffer : Buffer DISALLOW_COPY_AND_ASSIGN(Buffer);
{
void Init(const Device *device, usize size, cstr name = nullptr);
void Write(const Device *device, void *data, usize size, usize offset) const = delete;
};
struct IndexBuffer : Buffer
{
void Init(const Device *device, usize size, cstr name = nullptr);
void Write(const Device *device, void *data, usize size, usize offset) const = delete;
};
struct StagingBuffer : Buffer
{
void Init(const Device *device, usize size, cstr name = nullptr);
}; };

View File

@ -221,5 +221,5 @@ struct fmt::formatter<eastl::fixed_string<TType, TCount, TOverflow>> : nested_fo
} }
}; };
template <concepts::Manageable T> template <typename T>
using Ref = std::shared_ptr<T>; using Ref = std::shared_ptr<T>;

View File

@ -123,7 +123,7 @@ struct Image
namespace concepts namespace concepts
{ {
template <typename T> template <typename T>
concept Image = std::derived_from<T, Image> and Manageable<T>; concept Image = std::derived_from<T, Image>;
template <typename T> template <typename T>
concept ImageRef = Derefencable<T> and Image<DereferencesTo<T>>; concept ImageRef = Derefencable<T> and Image<DereferencesTo<T>>;

View File

@ -12,13 +12,6 @@ struct Image;
namespace concepts namespace concepts
{ {
template <typename T>
concept RefCounted = requires(T a) {
{ a.AddRef() } -> std::same_as<void>;
{ a.Release() } -> std::same_as<void>;
{ a.IsReferenced() } -> std::convertible_to<bool>;
};
template <typename T> template <typename T>
concept Derefencable = requires(T a) { concept Derefencable = requires(T a) {
{ *a }; { *a };
@ -38,8 +31,4 @@ concept SelfDestructible = requires(T a) {
{ T::m_Device } -> std::convertible_to<const Device *>; { T::m_Device } -> std::convertible_to<const Device *>;
}; };
template <typename T>
concept Manageable =
std::is_default_constructible_v<T> and (DeviceDestructible<T> or SelfDestructible<T>) and RefCounted<T>;
} // namespace concepts } // namespace concepts

View File

@ -4,7 +4,6 @@ cmake_minimum_required(VERSION 3.13)
target_sources(aster_core target_sources(aster_core
INTERFACE INTERFACE
"manager.h"
"buffer_manager.h" "buffer_manager.h"
"image_manager.h" "image_manager.h"
"view_manager.h" "view_manager.h"

View File

@ -5,17 +5,19 @@
#pragma once #pragma once
#include "manager.h"
#include "aster/aster.h" #include "aster/aster.h"
#include "aster/core/buffer.h" #include "aster/core/buffer.h"
namespace systems namespace systems
{ {
class BufferManager final : public Manager<Buffer> class BufferManager final
{ {
using Handle = Ref<Buffer>;
const Device *m_Device = nullptr;
public: public:
BufferManager(const Device *device, u32 maxCount); explicit BufferManager(const Device *device);
[[nodiscard]] Handle CreateStorageBuffer(usize size, cstr name = nullptr); [[nodiscard]] Handle CreateStorageBuffer(usize size, cstr name = nullptr);
[[nodiscard]] Handle CreateUniformBuffer(usize size, cstr name = nullptr); [[nodiscard]] Handle CreateUniformBuffer(usize size, cstr name = nullptr);

View File

@ -6,6 +6,7 @@
#pragma once #pragma once
#include "aster/aster.h" #include "aster/aster.h"
#include "buffer_manager.h" #include "buffer_manager.h"
#include "sampler_manager.h" #include "sampler_manager.h"
#include "view_manager.h" #include "view_manager.h"
@ -22,12 +23,11 @@ namespace systems
class CommitManager class CommitManager
{ {
template <concepts::Manageable T> template <typename T>
struct HandleMapper struct HandleMapper
{ {
using Type = T; using Type = T;
using Manager = Manager<Type>; using Handle = Ref<Type>;
using Handle = typename Manager::Handle;
using Resource = ResId<Type>; using Resource = ResId<Type>;
struct Entry : eastl::intrusive_hash_node_key<Handle> struct Entry : eastl::intrusive_hash_node_key<Handle>
@ -349,7 +349,7 @@ class CommitManager
} }
}; };
template <concepts::Manageable T> template <typename T>
void void
ResId<T>::AddRef() const ResId<T>::AddRef() const
{ {
@ -357,7 +357,7 @@ ResId<T>::AddRef() const
CommitManager::Instance().AddRef(*this); CommitManager::Instance().AddRef(*this);
} }
template <concepts::Manageable T> template <typename T>
void void
ResId<T>::Release() const ResId<T>::Release() const
{ {

View File

@ -5,8 +5,6 @@
#pragma once #pragma once
#include "manager.h"
#include "aster/aster.h" #include "aster/aster.h"
#include "aster/core/image.h" #include "aster/core/image.h"
@ -54,10 +52,11 @@ struct DepthStencilImageCreateInfo
cstr m_Name = nullptr; cstr m_Name = nullptr;
}; };
class ImageManager final : public Manager<Image> class ImageManager final
{ {
const Device *m_Device;
public: public:
ImageManager(const Device *device, u32 maxCount); explicit ImageManager(const Device *device);
template <concepts::Image T> template <concepts::Image T>
[[nodiscard]] Ref<T> [[nodiscard]] Ref<T>

View File

@ -1,58 +0,0 @@
// =============================================
// Aster: manager.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "aster/aster.h"
#include "aster/core/type_traits.h"
#include "aster/util/freelist.h"
#include <EASTL/intrusive_ptr.h>
#include <EASTL/vector.h>
struct Device;
namespace systems
{
template <concepts::Manageable T>
class Manager
{
public:
using Type = T;
using Handle = Ref<T>;
/**
* Constructor for the Manager class template.
* @param device Device with which resources are created.
*/
explicit Manager(const Device *device, const u32)
: m_Device{device}
{
}
virtual ~Manager()
{
m_Device = nullptr;
}
PIN_MEMORY(Manager);
protected:
const Device *m_Device;
/**
* Internal Method to Allocate a resource on the manager.
* @return [Handle, Type*] Where Type* is available to initialize the resource.
*/
[[nodiscard]] Handle
Alloc()
{
auto object = std::make_shared<Type>();
object->m_Device = m_Device;
return object;
}
};
} // namespace systems

View File

@ -14,7 +14,7 @@ namespace systems
* ResId manages the lifetime of the committed resource. * ResId manages the lifetime of the committed resource.
* @tparam T Type of the committed resource. * @tparam T Type of the committed resource.
*/ */
template <concepts::Manageable T> template <typename T>
class ResId class ResId
{ {
public: public:
@ -82,7 +82,7 @@ class ResId
struct NullId struct NullId
{ {
template <concepts::Manageable T> template <typename T>
operator ResId<T>() operator ResId<T>()
{ {
return ResId<T>::Null(); return ResId<T>::Null();

View File

@ -96,11 +96,11 @@ class ResourceManager
CombinedImageViewManager m_CombinedImageViews; CombinedImageViewManager m_CombinedImageViews;
public: public:
ResourceManager(const Device *device, u32 maxBufferCount, u32 maxImageCount, u32 maxSamplerCount, u32 maxViewCount) explicit ResourceManager(const Device *device)
: m_Buffers{device, maxBufferCount} : m_Buffers{device}
, m_Images{device, maxImageCount} , m_Images{device}
, m_Samplers{device, maxSamplerCount} , m_Samplers{device}
, m_Views{device, maxViewCount} , m_Views{device}
, m_CombinedImageViews{&m_Images, &m_Views} , m_CombinedImageViews{&m_Images, &m_Views}
{ {
} }

View File

@ -6,7 +6,6 @@
#pragma once #pragma once
#include "EASTL/hash_map.h" #include "EASTL/hash_map.h"
#include "manager.h"
#include "aster/aster.h" #include "aster/aster.h"
#include "aster/core/sampler.h" #include "aster/core/sampler.h"
@ -96,13 +95,16 @@ struct SamplerCreateInfo
* *
* Manages (and caches) objects of sampler. Currently Samplers are never deleted. * Manages (and caches) objects of sampler. Currently Samplers are never deleted.
*/ */
class SamplerManager final : public Manager<Sampler> class SamplerManager final
{ {
using Handle = Ref<Sampler>;
eastl::hash_map<vk::SamplerCreateInfo, Handle> m_HashToSamplerIdx; eastl::hash_map<vk::SamplerCreateInfo, Handle> m_HashToSamplerIdx;
const Device *m_Device;
public: public:
SamplerManager(const Device *device, u32 maxCount); explicit SamplerManager(const Device *device);
~SamplerManager() override; ~SamplerManager();
Ref<Sampler> CreateSampler(const SamplerCreateInfo &createInfo); Ref<Sampler> CreateSampler(const SamplerCreateInfo &createInfo);
}; };

View File

@ -5,8 +5,6 @@
#pragma once #pragma once
#include "manager.h"
#include "aster/aster.h" #include "aster/aster.h"
#include "aster/core/image_view.h" #include "aster/core/image_view.h"
@ -86,10 +84,12 @@ struct ViewCreateInfo
} }
}; };
class ViewManager final : public Manager<ImageView> class ViewManager final
{ {
const Device *m_Device;
public: public:
ViewManager(const Device *device, u32 maxCount); explicit ViewManager(const Device *device);
template <concepts::ImageView TImageView> template <concepts::ImageView TImageView>
Ref<TImageView> Ref<TImageView>
@ -98,7 +98,7 @@ class ViewManager final : public Manager<ImageView>
return CastView<TImageView>(CreateView(ViewCreateInfo<>(createInfo))); return CastView<TImageView>(CreateView(ViewCreateInfo<>(createInfo)));
} }
Ref<ImageView> CreateView(const ViewCreateInfo<> &createInfo); [[nodiscard]] Ref<ImageView> CreateView(const ViewCreateInfo<> &createInfo) const;
}; };
} // namespace systems } // namespace systems

View File

@ -7,19 +7,8 @@
#include "core/device.h" #include "core/device.h"
void Buffer::Buffer(const Device *device, const usize size, const vk::BufferUsageFlags bufferUsage,
Buffer::Destroy() const VmaAllocationCreateFlags allocationFlags, const VmaMemoryUsage memoryUsage, const cstr name)
{
if (!m_Buffer)
return;
vmaDestroyBuffer(m_Device->m_Allocator, Take(m_Buffer), m_Allocation);
m_Size = 0;
}
void
Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUsage,
VmaAllocationCreateFlags allocationFlags, VmaMemoryUsage memoryUsage, cstr name)
{ {
assert(!m_Buffer); assert(!m_Buffer);
@ -42,9 +31,9 @@ Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUs
&allocationCreateInfo, &buffer, &allocation, &allocationInfo)); &allocationCreateInfo, &buffer, &allocation, &allocationInfo));
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
vk::MemoryPropertyFlags memoryPropertyFlags; // vk::MemoryPropertyFlags memoryPropertyFlags;
vmaGetAllocationMemoryProperties(device->m_Allocator, allocation, // vmaGetAllocationMemoryProperties(device->m_Allocator, allocation, Recast<VkMemoryPropertyFlags
Recast<VkMemoryPropertyFlags *>(&memoryPropertyFlags)); // *>(&memoryPropertyFlags));
// TODO: Actually track Host Access // TODO: Actually track Host Access
// bool hostAccessible = Cast<bool>(memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible); // bool hostAccessible = Cast<bool>(memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible);
@ -56,138 +45,52 @@ Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUs
device->SetName(m_Buffer, name); device->SetName(m_Buffer, name);
} }
Buffer::Buffer(Buffer &&other) noexcept
: m_Device{Take(other.m_Device)}
, m_Buffer{Take(other.m_Buffer)}
, m_Allocation{Take(other.m_Allocation)}
, m_Mapped{Take(other.m_Mapped)}
, m_Size{Take(other.m_Size)}
{
}
Buffer &
Buffer::operator=(Buffer &&other) noexcept
{
if (this == &other)
return *this;
using std::swap;
swap(m_Device, other.m_Device);
swap(m_Buffer, other.m_Buffer);
swap(m_Allocation, other.m_Allocation);
swap(m_Mapped, other.m_Mapped);
swap(m_Size, other.m_Size);
return *this;
}
Buffer::~Buffer()
{
if (!m_Buffer)
return;
vmaDestroyBuffer(m_Device->m_Allocator, Take(m_Buffer), m_Allocation);
m_Size = 0;
}
uptr uptr
Buffer::GetDeviceAddress(const Device *device) const Buffer::GetDeviceAddress(const Device *device) const
{ {
vk::BufferDeviceAddressInfo addressInfo = {.buffer = m_Buffer}; const vk::BufferDeviceAddressInfo addressInfo = {.buffer = m_Buffer};
return device->m_Device.getBufferAddress(&addressInfo); return device->m_Device.getBufferAddress(&addressInfo);
} }
void void
Buffer::Write(usize offset, usize size, const void *data) Buffer::Write(const usize offset, const usize size, const void *data) const
{ {
assert(IsHostVisible()); assert(IsMapped());
if (!IsMapped())
{
void *mapped;
auto result = Cast<vk::Result>(vmaMapMemory(m_Device->m_Allocator, m_Allocation, &mapped));
ERROR_IF(Failed(result), "Memory mapping failed. Cause: {}", result);
if (!Failed(result))
{
m_Mapped = Cast<u8 *>(mapped);
memcpy(m_Mapped + offset, data, size); memcpy(m_Mapped + offset, data, size);
vmaUnmapMemory(m_Device->m_Allocator, m_Allocation);
m_Mapped = nullptr;
}
}
else
{
memcpy(m_Mapped + offset, data, size);
}
// TODO: Debug this. // TODO: Debug this.
// auto result = Cast<vk::Result>(vmaCopyMemoryToAllocation(device->m_Allocator, &data, m_Allocation, 0, size)); // auto result = Cast<vk::Result>(vmaCopyMemoryToAllocation(device->m_Allocator, &data, m_Allocation, 0, size));
// ERROR_IF(Failed(result), "Writing to buffer failed. Cause: {}", result) THEN_ABORT(result); // ERROR_IF(Failed(result), "Writing to buffer failed. Cause: {}", result) THEN_ABORT(result);
} }
void
UniformBuffer::Init(const Device *device, const usize size, const cstr name)
{
Allocate(device, size, vk::BufferUsageFlagBits::eUniformBuffer,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
VMA_MEMORY_USAGE_AUTO, name);
}
void
StorageBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name)
{
Init(device, size, hostVisible, false, name);
}
void
StorageBuffer::Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name)
{
vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer;
if (deviceAddress)
{
usage |= vk::BufferUsageFlagBits::eShaderDeviceAddress;
}
if (hostVisible)
{
Allocate(device, size, usage,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
VMA_MEMORY_USAGE_AUTO, name);
}
else
{
usage |= vk::BufferUsageFlagBits::eTransferDst;
Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
}
}
void
StorageIndexBuffer::Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name)
{
vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndexBuffer;
if (deviceAddress)
{
usage |= vk::BufferUsageFlagBits::eShaderDeviceAddress;
}
if (hostVisible)
{
Allocate(device, size, usage,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
VMA_MEMORY_USAGE_AUTO, name);
}
else
{
usage |= vk::BufferUsageFlagBits::eTransferDst;
Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
}
}
void
IndirectBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name)
{
vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndirectBuffer |
vk::BufferUsageFlagBits::eShaderDeviceAddress;
if (hostVisible)
{
Allocate(device, size, usage,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
VMA_MEMORY_USAGE_AUTO, name);
}
else
{
usage |= vk::BufferUsageFlagBits::eTransferDst;
Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
}
}
void
VertexBuffer::Init(const Device *device, usize size, cstr name)
{
Allocate(device, size, vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eTransferDst, 0,
VMA_MEMORY_USAGE_AUTO, name);
}
void
IndexBuffer::Init(const Device *device, usize size, cstr name)
{
Allocate(device, size, vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst, 0,
VMA_MEMORY_USAGE_AUTO, name);
}
void
StagingBuffer::Init(const Device *device, usize size, cstr name)
{
Allocate(device, size, vk::BufferUsageFlagBits::eTransferSrc,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
VMA_MEMORY_USAGE_AUTO, name);
}

View File

@ -4,7 +4,6 @@ cmake_minimum_required(VERSION 3.13)
target_sources(aster_core target_sources(aster_core
PRIVATE PRIVATE
"manager.cpp"
"buffer_manager.cpp" "buffer_manager.cpp"
"image_manager.cpp" "image_manager.cpp"
"view_manager.cpp" "view_manager.cpp"

View File

@ -10,8 +10,6 @@ using namespace systems;
Ref<Buffer> Ref<Buffer>
BufferManager::CreateStorageBuffer(const usize size, const cstr name) BufferManager::CreateStorageBuffer(const usize size, const cstr name)
{ {
auto object = Alloc();
// TODO: Storage and Index buffer are set. // TODO: Storage and Index buffer are set.
// This is hacky and should be improved. // This is hacky and should be improved.
constexpr vk::BufferUsageFlags usage = constexpr vk::BufferUsageFlags usage =
@ -21,41 +19,31 @@ BufferManager::CreateStorageBuffer(const usize size, const cstr name)
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT; VMA_ALLOCATION_CREATE_MAPPED_BIT;
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO; constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name); return std::make_shared<Buffer>(m_Device, size, usage, createFlags, memoryUsage, name);
return object;
} }
Ref<Buffer> Ref<Buffer>
BufferManager::CreateUniformBuffer(const usize size, const cstr name) BufferManager::CreateUniformBuffer(const usize size, const cstr name)
{ {
auto object = Alloc();
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eUniformBuffer; constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eUniformBuffer;
constexpr VmaAllocationCreateFlags createFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | constexpr VmaAllocationCreateFlags createFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT; VMA_ALLOCATION_CREATE_MAPPED_BIT;
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO; constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name); return std::make_shared<Buffer>(m_Device, size, usage, createFlags, memoryUsage, name);
return object;
} }
Manager<Buffer>::Handle Ref<Buffer>
BufferManager::CreateStagingBuffer(const usize size, const cstr name) BufferManager::CreateStagingBuffer(const usize size, const cstr name)
{ {
auto object = Alloc();
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eTransferSrc; constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eTransferSrc;
constexpr VmaAllocationCreateFlags createFlags = constexpr VmaAllocationCreateFlags createFlags =
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT; VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO; constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name); return std::make_shared<Buffer>(m_Device, size, usage, createFlags, memoryUsage, name);
return object;
} }
BufferManager::BufferManager(const Device *device, const u32 maxCount) BufferManager::BufferManager(const Device *device)
: Manager{device, maxCount} : m_Device{device}
{ {
} }

View File

@ -25,6 +25,11 @@ constexpr vk::ImageUsageFlags COLOR_ATTACHMENT =
constexpr vk::ImageUsageFlags DEPTH_STENCIL_ATTACHMENT = vk::ImageUsageFlagBits::eDepthStencilAttachment; constexpr vk::ImageUsageFlags DEPTH_STENCIL_ATTACHMENT = vk::ImageUsageFlagBits::eDepthStencilAttachment;
} // namespace usage_flags } // namespace usage_flags
ImageManager::ImageManager(const Device *device)
: m_Device{device}
{
}
Ref<Image> Ref<Image>
ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo) ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo)
{ {
@ -40,7 +45,8 @@ ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo)
&allocationCreateInfo, &image, &allocation, nullptr)); &allocationCreateInfo, &image, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
auto object = Alloc(); auto object = std::make_shared<Image>();
object->m_Device = m_Device;
object->m_Image = image; object->m_Image = image;
object->m_Allocation = allocation; object->m_Allocation = allocation;
object->m_Extent = imageCreateInfo.extent; object->m_Extent = imageCreateInfo.extent;
@ -73,7 +79,8 @@ ImageManager::CreateTextureCube(const TextureCubeCreateInfo &createInfo)
&allocationCreateInfo, &image, &allocation, nullptr)); &allocationCreateInfo, &image, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
auto object = Alloc(); auto object = std::make_shared<Image>();
object->m_Device = m_Device;
object->m_Image = image; object->m_Image = image;
object->m_Allocation = allocation; object->m_Allocation = allocation;
object->m_Extent = imageCreateInfo.extent; object->m_Extent = imageCreateInfo.extent;
@ -106,7 +113,8 @@ ImageManager::CreateAttachment(const AttachmentCreateInfo &createInfo)
&allocationCreateInfo, &image, &allocation, nullptr)); &allocationCreateInfo, &image, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
auto object = Alloc(); auto object = std::make_shared<Image>();
object->m_Device = m_Device;
object->m_Image = image; object->m_Image = image;
object->m_Allocation = allocation; object->m_Allocation = allocation;
object->m_Extent = imageCreateInfo.extent; object->m_Extent = imageCreateInfo.extent;
@ -134,7 +142,8 @@ ImageManager::CreateDepthStencilImage(const DepthStencilImageCreateInfo &createI
&allocationCreateInfo, &image, &allocation, nullptr)); &allocationCreateInfo, &image, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
auto object = Alloc(); auto object = std::make_shared<Image>();
object->m_Device = m_Device;
object->m_Image = image; object->m_Image = image;
object->m_Allocation = allocation; object->m_Allocation = allocation;
object->m_Extent = imageCreateInfo.extent; object->m_Extent = imageCreateInfo.extent;
@ -237,8 +246,3 @@ ToImageCreateInfo(const DepthStencilImageCreateInfo &createInfo)
.usage = usage, .usage = usage,
}; };
} }
ImageManager::ImageManager(const Device *device, const u32 maxCount)
: Manager{device, maxCount}
{
}

View File

@ -1,6 +0,0 @@
// =============================================
// Aster: manager.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "systems/manager.h"

View File

@ -9,8 +9,8 @@
using namespace systems; using namespace systems;
SamplerManager::SamplerManager(const Device *device, const u32 maxCount) SamplerManager::SamplerManager(const Device *device)
: Manager{device, maxCount} : m_Device{device}
{ {
} }
@ -29,7 +29,7 @@ SamplerManager::CreateSampler(const SamplerCreateInfo &createInfo)
return iter->second; return iter->second;
} }
auto object = Alloc(); auto object = std::make_shared<Sampler>();
object->Init(m_Device, vkCreateInfo, createInfo.m_Name ? createInfo.m_Name : nullptr); object->Init(m_Device, vkCreateInfo, createInfo.m_Name ? createInfo.m_Name : nullptr);
m_HashToSamplerIdx.emplace(vkCreateInfo, object); m_HashToSamplerIdx.emplace(vkCreateInfo, object);

View File

@ -9,13 +9,13 @@
using namespace systems; using namespace systems;
ViewManager::ViewManager(const Device *device, const u32 maxCount) ViewManager::ViewManager(const Device *device)
: Manager{device, maxCount} : m_Device{device}
{ {
} }
Ref<ImageView> Ref<ImageView>
ViewManager::CreateView(const ViewCreateInfo<> &createInfo) ViewManager::CreateView(const ViewCreateInfo<> &createInfo) const
{ {
const auto layerCount = createInfo.GetLayerCount(); const auto layerCount = createInfo.GetLayerCount();
const auto mipCount = createInfo.GetMipLevelCount(); const auto mipCount = createInfo.GetMipLevelCount();
@ -32,7 +32,8 @@ ViewManager::CreateView(const ViewCreateInfo<> &createInfo)
m_Device->SetName(view, createInfo.m_Name); m_Device->SetName(view, createInfo.m_Name);
auto object = Alloc(); auto object = std::make_shared<ImageView>();
object->m_Device = m_Device;
object->m_Image = createInfo.m_Image; object->m_Image = createInfo.m_Image;
object->m_View = view; object->m_View = view;
object->m_Extent = createInfo.m_Image->m_Extent; object->m_Extent = createInfo.m_Image->m_Extent;

View File

@ -131,7 +131,7 @@ main(int, char **)
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0); vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"}; Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
systems::ResourceManager resourceManager{&device, 12, 12, 1, 12}; systems::ResourceManager resourceManager{&device};
systems::CommitManager commitManager{&device, 12, 12, 12, resourceManager.Samplers().CreateSampler({})}; systems::CommitManager commitManager{&device, 12, 12, 12, resourceManager.Samplers().CreateSampler({})};
@ -221,10 +221,9 @@ main(int, char **)
}); });
{ {
StagingBuffer imageStaging;
imageStaging.Init(&device, imageFile.GetSize(), "Image Staging"); auto imageStaging = resourceManager.Buffers().CreateStagingBuffer(imageFile.GetSize(), "Image Staging");
imageStaging.Write(0, imageFile.GetSize(), imageFile.m_Data); imageStaging->Write(0, imageFile.GetSize(), imageFile.m_Data);
vk::ImageMemoryBarrier2 imageReadyToWrite = { vk::ImageMemoryBarrier2 imageReadyToWrite = {
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer, .srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
@ -297,7 +296,7 @@ main(int, char **)
.imageOffset = {}, .imageOffset = {},
.imageExtent = {imageFile.m_Width, imageFile.m_Height, 1}, .imageExtent = {imageFile.m_Width, imageFile.m_Height, 1},
}; };
copyBuffer.copyBufferToImage(imageStaging.m_Buffer, crate->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1, copyBuffer.copyBufferToImage(imageStaging->m_Buffer, crate->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
&imageCopy); &imageCopy);
copyBuffer.pipelineBarrier2(&imageReadyToReadDependency); copyBuffer.pipelineBarrier2(&imageReadyToReadDependency);
@ -318,7 +317,6 @@ main(int, char **)
AbortIfFailedM(device.m_Device.resetCommandPool(copyPool, {}), "Couldn't reset command pool."); AbortIfFailedM(device.m_Device.resetCommandPool(copyPool, {}), "Couldn't reset command pool.");
device.m_Device.destroy(fence, nullptr); device.m_Device.destroy(fence, nullptr);
imageStaging.Destroy();
} }
auto ubo = resourceManager.Buffers().CreateStorageBuffer(sizeof camera, "Camera UBO"); auto ubo = resourceManager.Buffers().CreateStorageBuffer(sizeof camera, "Camera UBO");

View File

@ -76,9 +76,9 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
auto *pDevice = m_CommitManager->m_Device; auto *pDevice = m_CommitManager->m_Device;
StagingBuffer stagingBuffer; auto stagingBuffer =
stagingBuffer.Init(pDevice, (sizeof *data) * x * y * 4, "HDR Staging Buffer"); m_ResourceManager->Buffers().CreateStagingBuffer((sizeof *data) * x * y * 4, "HDR Staging Buffer");
stagingBuffer.Write(0, stagingBuffer.m_Size, data); stagingBuffer->Write(0, stagingBuffer->m_Size, data);
stbi_image_free(data); stbi_image_free(data);
@ -98,7 +98,7 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
.imageExtent = texture->m_Extent, .imageExtent = texture->m_Extent,
}; };
vk::CopyBufferToImageInfo2 stagingInfo = { vk::CopyBufferToImageInfo2 stagingInfo = {
.srcBuffer = stagingBuffer.m_Buffer, .srcBuffer = stagingBuffer->m_Buffer,
.dstImage = texture->GetImage(), .dstImage = texture->GetImage(),
.dstImageLayout = vk::ImageLayout::eTransferDstOptimal, .dstImageLayout = vk::ImageLayout::eTransferDstOptimal,
.regionCount = 1, .regionCount = 1,
@ -194,8 +194,6 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
AbortIfFailed(pDevice->m_Device.resetCommandPool(m_CommandPool, {})); AbortIfFailed(pDevice->m_Device.resetCommandPool(m_CommandPool, {}));
stagingBuffer.Destroy();
return texture; return texture;
} }

View File

@ -178,7 +178,7 @@ main(int, char **)
vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0); vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"}; Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
systems::ResourceManager resourceManager = {&device, 1000, 1000, 10, 1000}; auto resourceManager = systems::ResourceManager{&device};
systems::CommitManager commitManager = {&device, 1000, 1000, 1000, systems::CommitManager commitManager = {&device, 1000, 1000, 1000,
resourceManager.Samplers().CreateSampler({.m_Name = "Default Sampler"})}; resourceManager.Samplers().CreateSampler({.m_Name = "Default Sampler"})};

View File

@ -3,7 +3,7 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
add_subdirectory("00_util") add_subdirectory("00_util")
add_subdirectory("01_triangle") # add_subdirectory("01_triangle")
add_subdirectory("02_box") add_subdirectory("02_box")
add_subdirectory("03_model_render") add_subdirectory("03_model_render")
# add_subdirectory("04_scenes") # add_subdirectory("04_scenes")