diff --git a/aster/include/aster/core/CMakeLists.txt b/aster/include/aster/core/CMakeLists.txt index 9153d89..8f562aa 100644 --- a/aster/include/aster/core/CMakeLists.txt +++ b/aster/include/aster/core/CMakeLists.txt @@ -15,6 +15,7 @@ INTERFACE "queue_allocation.h" "buffer.h" "image.h" + "image_view.h" "surface.h" "size.h" "type_traits.h" diff --git a/aster/include/aster/core/global.h b/aster/include/aster/core/global.h index fbdff20..3b05322 100644 --- a/aster/include/aster/core/global.h +++ b/aster/include/aster/core/global.h @@ -26,7 +26,9 @@ #if !defined(NDEBUG) #define VULKAN_HPP_ASSERT(expr) DEBUG_IF(!(expr), "Vulkan assert failed") #endif + #include "type_traits.h" +#include "EASTL/intrusive_ptr.h" #include #include @@ -51,6 +53,7 @@ constexpr u32 ASTER_API_VERSION = VK_API_VERSION_1_3; #define Take(ELEMENT) eastl::exchange(ELEMENT, {}) #define TODO(MSG) assert(false && ("Unimplemented: " MSG)) +#define FIX(MSG) static_assert(false && ("Unimplemented: " MSG)) [[nodiscard]] inline bool Failed(const vk::Result result) @@ -212,12 +215,5 @@ struct fmt::formatter> : nested_fo } }; -namespace aster -{ -template -TVal & -Deref(TRef ref) -{ - return ref.Deref(); -} -} +template +using Ref = eastl::intrusive_ptr; diff --git a/aster/include/aster/core/image.h b/aster/include/aster/core/image.h index b5f9a9c..dc194a0 100644 --- a/aster/include/aster/core/image.h +++ b/aster/include/aster/core/image.h @@ -7,6 +7,7 @@ #include "global.h" +struct StorageTexture; struct Device; [[nodiscard]] inline vk::Extent2D @@ -46,6 +47,28 @@ struct Image u8 m_LayerCount = 0; u8 m_MipLevels = 0; + constexpr static u8 SAMPLED_BIT = 1 << 7; + constexpr static u8 STORAGE_BIT = 1 << 6; + constexpr static u8 CUBE_BIT = 1 << 5; + + [[nodiscard]] bool + IsSampled() const + { + return m_Flags_ & SAMPLED_BIT; + } + + [[nodiscard]] bool + IsStorage() const + { + return m_Flags_ & STORAGE_BIT; + } + + [[nodiscard]] bool + IsCube() const + { + return m_Flags_ & CUBE_BIT; + } + [[nodiscard]] bool IsValid() const { @@ -83,48 +106,114 @@ struct Image } void Destroy(); + + static bool + Conforms(const Image &) + { + return true; + } }; +namespace concepts +{ +template +concept Image = std::derived_from and Manageable; + +template +concept ImageRef = Derefencable and Image>; + +template +concept SampledImage = requires() { + { T::SAMPLED } -> std::convertible_to; +} and T::SAMPLED and Image; + +template +concept SampledImageRef = Derefencable and SampledImage>; + +template +concept ImageCube = requires() { + { T::CUBED } -> std::convertible_to; +} and T::CUBED and Image; + +template +concept ImageCubeRef = Derefencable and ImageCube>; + +template +concept StorageImage = requires() { + { T::STORAGE } -> std::convertible_to; +} and T::STORAGE and Image; + +template +concept StorageImageRef = Derefencable and StorageImage>; + +} // namespace concepts + struct Texture : Image { - void Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, bool isMipMapped, cstr name = nullptr); + constexpr static bool SAMPLED = true; + + static bool + Conforms(const Image &other) + { + return other.IsSampled(); + } }; -static_assert(sizeof(Texture) == sizeof(Image)); - -struct TextureCube : Texture +struct ImageCube : Image { - void - Init(const Device *device, u32 cubeSide, vk::Format imageFormat, bool isMipMapped = false, cstr name = nullptr); + constexpr static bool CUBE = true; + + static bool + Conforms(const Image &other) + { + return other.IsCube(); + } }; -static_assert(sizeof(TextureCube) == sizeof(Image)); - -struct AttachmentImage : Image +struct TextureCube : Image { - void Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, cstr name = nullptr); + constexpr static bool SAMPLED = true; + constexpr static bool CUBE = true; + + static bool + Conforms(const Image &other) + { + return other.IsSampled() && other.IsCube(); + } }; -static_assert(sizeof(AttachmentImage) == sizeof(Image)); - -struct DepthImage : Image +struct StorageImage : Image { - void Init(const Device *device, vk::Extent2D extent, cstr name = nullptr); + constexpr static bool STORAGE = true; + + static bool + Conforms(const Image &other) + { + return other.IsStorage(); + } }; -static_assert(sizeof(DepthImage) == sizeof(Image)); - -struct StorageTexture : Texture +struct StorageTexture : StorageImage { - void Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, bool isSampled, cstr name = nullptr); + constexpr static bool SAMPLED = true; + constexpr static bool STORAGE = true; + + static bool + Conforms(const Image &other) + { + return other.IsStorage() && other.IsSampled(); + } }; -static_assert(sizeof(StorageTexture) == sizeof(Image)); - -struct StorageTextureCube : StorageTexture +struct StorageTextureCube : StorageImage { - void Init(const Device *device, u32 cubeSide, vk::Format imageFormat, bool isSampled, bool isMipMapped = false, - cstr name = nullptr); -}; + constexpr static bool SAMPLED = true; + constexpr static bool CUBE = true; + constexpr static bool STORAGE = true; -static_assert(sizeof(StorageTextureCube) == sizeof(Image)); + static bool + Conforms(const Image &other) + { + return other.IsStorage() && other.IsSampled() && other.IsCube(); + } +}; diff --git a/aster/include/aster/core/image_view.h b/aster/include/aster/core/image_view.h new file mode 100644 index 0000000..f5454c2 --- /dev/null +++ b/aster/include/aster/core/image_view.h @@ -0,0 +1,26 @@ +// ============================================= +// Aster: image_view.h +// Copyright (c) 2020-2025 Anish Bhobe +// ============================================= + +#pragma once + +#include "global.h" +#include "image.h" + +template +struct View +{ + using ImageType = TImage; + + Ref m_Image; + vk::ImageView m_View = nullptr; + vk::Extent3D m_Extent; + std::atomic m_RefCount; + u8 m_EmptyPadding_ = 0; + u8 m_Flags_ = 0; + u8 m_LayerCount = 0; + u8 m_MipLevels = 0; +}; + +using ImageView = View<>; \ No newline at end of file diff --git a/aster/include/aster/core/type_traits.h b/aster/include/aster/core/type_traits.h index 08864eb..b9d99ba 100644 --- a/aster/include/aster/core/type_traits.h +++ b/aster/include/aster/core/type_traits.h @@ -6,6 +6,7 @@ #pragma once struct Device; +struct Image; namespace concepts { @@ -16,6 +17,14 @@ concept RefCounted = requires(T a) { { a.IsReferenced() } -> std::convertible_to; }; +template +concept Derefencable = requires(T a) { + { *a }; +}; + +template +using DereferencesTo = std::remove_cvref_t())>; + template concept DeviceDestructible = requires(T a, Device *p) { { a.Destroy(p) } -> std::same_as; diff --git a/aster/include/aster/systems/CMakeLists.txt b/aster/include/aster/systems/CMakeLists.txt index 58b60b1..0055274 100644 --- a/aster/include/aster/systems/CMakeLists.txt +++ b/aster/include/aster/systems/CMakeLists.txt @@ -7,5 +7,8 @@ INTERFACE "manager.h" "buffer_manager.h" "image_manager.h" + "image_view_manager.h" "sampler_manager.h" - "render_resource_manager.h") + "resource.h" + "resource_manager.h" + "commit_manager.h") diff --git a/aster/include/aster/systems/buffer_manager.h b/aster/include/aster/systems/buffer_manager.h index b626c07..f51b652 100644 --- a/aster/include/aster/systems/buffer_manager.h +++ b/aster/include/aster/systems/buffer_manager.h @@ -5,20 +5,20 @@ #pragma once +#include "manager.h" + #include "aster/aster.h" #include "aster/core/buffer.h" -#include "manager.h" namespace systems { -using BufferHandle = Manager::Handle; - class BufferManager final : public Manager { public: - BufferManager(const Device *device, const u32 maxCount, const u8 binding); + BufferManager(const Device *device, u32 maxCount); [[nodiscard]] Handle CreateStorageBuffer(usize size, cstr name = nullptr); [[nodiscard]] Handle CreateUniformBuffer(usize size, cstr name = nullptr); + [[nodiscard]] Handle CreateStagingBuffer(usize size, cstr name = nullptr); }; } // namespace systems diff --git a/aster/include/aster/systems/render_resource_manager.h b/aster/include/aster/systems/commit_manager.h similarity index 69% rename from aster/include/aster/systems/render_resource_manager.h rename to aster/include/aster/systems/commit_manager.h index 57b26fa..82a52b2 100644 --- a/aster/include/aster/systems/render_resource_manager.h +++ b/aster/include/aster/systems/commit_manager.h @@ -16,73 +16,12 @@ #include "EASTL/intrusive_hash_map.h" #include "EASTL/bonus/fixed_ring_buffer.h" +#include "resource.h" + namespace systems { -class RenderResourceManager; - -/** - * CommitEntry manages the lifetime of the committed resource. - * @tparam T Type of the committed resource. - */ -template -class CommitEntry -{ - private: - u32 m_Index; - - explicit CommitEntry(const u32 index) - : m_Index{index} - { - AddRef(); - } - - friend class RenderResourceManager; - - public: - CommitEntry(const CommitEntry &other) - : m_Index{other.m_Index} - { - AddRef(); - } - - CommitEntry(CommitEntry &&other) noexcept - : m_Index{other.m_Index} - { - AddRef(); - } - - CommitEntry & - operator=(const CommitEntry &other) - { - if (this == &other) - return *this; - m_Index = other.m_Index; - AddRef(); - return *this; - } - - CommitEntry & - operator=(CommitEntry &&other) noexcept - { - if (this == &other) - return *this; - m_Index = other.m_Index; - AddRef(); - return *this; - } - - ~CommitEntry() - { - Release(); - } - - private: - void AddRef() const; ///< Increases the refcount in the RenderResourceManager. - void Release() const; ///< Decreases the refcount in the RenderResourceManager. -}; - -class RenderResourceManager +class CommitManager { private: template @@ -91,7 +30,7 @@ class RenderResourceManager using Type = T; using Manager = Manager; using Handle = typename Manager::Handle; - using CommitE = CommitEntry; + using Resource = ResId; struct Entry : public eastl::intrusive_hash_node_key { @@ -173,7 +112,7 @@ class RenderResourceManager PIN_MEMORY(HandleMapper); /// Returns a commit, and a bool signifying if it is a new commit. - std::tuple + std::tuple Create(const Handle &object) { // Get-from freelist @@ -184,7 +123,7 @@ class RenderResourceManager { it->AddRef(); auto i = GetIndex(*it); - return {CommitE{i}, false}; + return {Resource{i}, false}; } Entry &data = m_FreeList.Pop(); @@ -196,17 +135,23 @@ class RenderResourceManager auto i = GetIndex(data); - return {CommitE{i}, true}; + return {Resource{i}, true}; + } + + Handle + GetHandle(const Resource &res) + { + return m_Data[res.m_Index].mKey; } void - AddRef(const CommitE &commit) + AddRef(const Resource &commit) { m_Data.at(commit.m_Index).AddRef(); } void - Release(const CommitE &commit) + Release(const Resource &commit) { auto &entry = m_Data.at(commit.m_Index); entry.Release(); @@ -271,18 +216,58 @@ class RenderResourceManager public: const Device *m_Device; - RenderResourceManager(const Device *device, u32 const maxBuffers, const u32 maxImages, - const SamplerHandle &defaultSampler); - ~RenderResourceManager(); + CommitManager(const Device *device, u32 maxBuffers, u32 maxImages, u32 maxStorageImages, + Ref defaultSampler); + ~CommitManager(); - PIN_MEMORY(RenderResourceManager); + PIN_MEMORY(CommitManager); - CommitEntry Commit(const BufferHandle &buffer); - CommitEntry Commit(const ImageHandle &handle); - CommitEntry Commit(const ImageHandle &image, const SamplerHandle &sampler); + // Commit Buffer + ResId CommitBuffer(const Ref &buffer); + + // Commit Storage Images + ResId CommitStorageImage(const concepts::StorageImageRef auto &image) + { + return CommitStorageImage(CastImage(image)); + } + ResId CommitStorageImage(const Ref &image); + + // Sampled Images + ResId + CommitTexture(const concepts::SampledImageRef auto &image, const Ref &sampler) + { + return CommitTexture(CastImage(image), sampler); + } + + ResId + CommitTexture(const concepts::SampledImageRef auto &image) + { + return CommitTexture(CastImage(image)); + } + + ResId CommitTexture(const Ref &handle); + ResId CommitTexture(const Ref &image, const Ref &sampler); void Update(); + Ref + FetchHandle(const ResId &id) + { + return m_Buffers.GetHandle(id); + } + + Ref + FetchHandle(const ResId &id) + { + return m_Images.GetHandle(id); + } + + Ref + FetchHandle(const ResId &id) + { + return m_StorageImages.GetHandle(id); + } + [[nodiscard]] const vk::DescriptorSetLayout & GetDescriptorSetLayout() const { @@ -295,10 +280,10 @@ class RenderResourceManager return m_DescriptorSet; } - static RenderResourceManager * - Instance() + static CommitManager &Instance() { - return m_Instance; + assert(m_Instance); + return *m_Instance; } private: @@ -308,54 +293,68 @@ class RenderResourceManager constexpr static u8 BUFFER_BINDING_INDEX = 0x0; constexpr static u8 IMAGE_BINDING_INDEX = 0x1; + constexpr static u8 STORAGE_IMAGE_BINDING_INDEX = 0x2; HandleMapper m_Buffers; - HandleMapper m_Images; - SamplerHandle m_DefaultSampler; + HandleMapper m_Images; + HandleMapper m_StorageImages; + + Ref m_DefaultSampler; eastl::vector m_Writes; eastl::deque m_WriteInfos; // eastl::vector m_WriteOwner; - static RenderResourceManager *m_Instance; - friend CommitEntry; - friend CommitEntry; + static CommitManager *m_Instance; + friend ResId; + friend ResId; + friend ResId; void - AddRef(const CommitEntry &handle) + AddRef(const ResId &handle) { m_Buffers.AddRef(handle); } void - AddRef(const CommitEntry &handle) + AddRef(const ResId &handle) { m_Images.AddRef(handle); } + void + AddRef(const ResId &handle) + { + m_StorageImages.AddRef(handle); + } void - Release(const CommitEntry &handle) + Release(const ResId &handle) { m_Buffers.Release(handle); } void - Release(const CommitEntry &handle) + Release(const ResId &handle) { m_Images.Release(handle); } + void + Release(const ResId &handle) + { + m_StorageImages.Release(handle); + } }; template void -CommitEntry::AddRef() const +ResId::AddRef() const { - RenderResourceManager::Instance()->AddRef(*this); + CommitManager::Instance().AddRef(*this); } template void -CommitEntry::Release() const +ResId::Release() const { - RenderResourceManager::Instance()->Release(*this); + CommitManager::Instance().Release(*this); } } // namespace systems \ No newline at end of file diff --git a/aster/include/aster/systems/image_manager.h b/aster/include/aster/systems/image_manager.h index 72aa0cb..b04bccf 100644 --- a/aster/include/aster/systems/image_manager.h +++ b/aster/include/aster/systems/image_manager.h @@ -5,13 +5,22 @@ #pragma once +#include "manager.h" + #include "aster/aster.h" #include "aster/core/image.h" -#include "manager.h" namespace systems { +template TTo> +static Ref +CastImage(const concepts::ImageRef auto &from) +{ + assert(TTo::Conforms(*from.get())); + return Recast(from.get()); +} + struct Texture2DCreateInfo { vk::Format m_Format = vk::Format::eUndefined; @@ -45,16 +54,30 @@ struct DepthStencilImageCreateInfo cstr m_Name = nullptr; }; -using ImageHandle = Manager::Handle; - class ImageManager final : public Manager { public: - ImageManager(const Device *device, const u32 maxCount, const u8 binding); + ImageManager(const Device *device, const u32 maxCount); - [[nodiscard]] Handle CreateTexture2D(const Texture2DCreateInfo &createInfo); - [[nodiscard]] Handle CreateTextureCube(const TextureCubeCreateInfo &createInfo); - [[nodiscard]] Handle CreateAttachment(const AttachmentCreateInfo &createInfo); - [[nodiscard]] Handle CreateDepthStencilImage(const DepthStencilImageCreateInfo &createInfo); + template + [[nodiscard]] Ref + CreateTexture2D(const Texture2DCreateInfo &createInfo) + { + auto handle = CreateTexture2D(createInfo); + return CastImage(handle); + } + + template + [[nodiscard]] Ref + CreateTextureCube(const TextureCubeCreateInfo &createInfo) + { + auto handle = CreateTextureCube(createInfo); + return CastImage(handle); + } + + [[nodiscard]] Ref CreateTexture2D(const Texture2DCreateInfo &createInfo); + [[nodiscard]] Ref CreateTextureCube(const TextureCubeCreateInfo &createInfo); + [[nodiscard]] Ref CreateAttachment(const AttachmentCreateInfo &createInfo); + [[nodiscard]] Ref CreateDepthStencilImage(const DepthStencilImageCreateInfo &createInfo); }; } // namespace systems diff --git a/aster/include/aster/systems/image_view_manager.h b/aster/include/aster/systems/image_view_manager.h new file mode 100644 index 0000000..10125a5 --- /dev/null +++ b/aster/include/aster/systems/image_view_manager.h @@ -0,0 +1,32 @@ +// ============================================= +// Aster: image_manager.h +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#pragma once + +#include "manager.h" + +#include "aster/aster.h" +#include "aster/core/image_view.h" + +namespace systems +{ +// +//template TTo> +//static Ref +//CastView(const concepts::ImageRef auto &from) +//{ +// assert(TTo::Conforms(*from.get())); +// return Recast(from.get()); +//} + +class ImageViewManager final : public Manager +{ + public: + ImageViewManager(const Device *device, const u32 maxCount); + + +}; + +} // namespace systems diff --git a/aster/include/aster/systems/manager.h b/aster/include/aster/systems/manager.h index aff3837..4190327 100644 --- a/aster/include/aster/systems/manager.h +++ b/aster/include/aster/systems/manager.h @@ -21,28 +21,22 @@ class Manager { public: using Type = T; - using Handle = eastl::intrusive_ptr; + using Handle = Ref; /** * Constructor for the Manager class template. * @param device Device with which resources are created. * @param maxCount Max number of resources that can be created (maxCount <= Handle::INDEX_MASK) - * @param binding The shader binding at which this manager will bind its resources. */ - explicit Manager(const Device *device, const u32 maxCount, const u8 binding) + explicit Manager(const Device *device, const u32 maxCount) : m_Data{maxCount} - , m_Binding{binding} , m_Device{device} { - assert(!m_Instance && "Attempting to initialize a second Manager"); - u32 i = 0; for (auto& element : m_Data) { *Recast(&element) = ++i; } - - m_Instance = this; } virtual ~Manager() @@ -61,8 +55,6 @@ class Manager m_FreeHead = 0; m_Device = nullptr; - - m_Instance = nullptr; } void @@ -85,9 +77,6 @@ class Manager private: eastl::vector m_Data; // Data also keeps the freelist during 'not use'. u32 m_FreeHead = 0; - u8 m_Binding = 0; - - static Manager *m_Instance; protected: const Device *m_Device; diff --git a/aster/include/aster/systems/resource.h b/aster/include/aster/systems/resource.h new file mode 100644 index 0000000..dd8be2c --- /dev/null +++ b/aster/include/aster/systems/resource.h @@ -0,0 +1,92 @@ +// ============================================= +// Aster: resource.h +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#pragma once + +#include + +namespace systems +{ + +/** + * ResId manages the lifetime of the committed resource. + * @tparam T Type of the committed resource. + */ +template +class ResId +{ + public: + constexpr static u32 INVALID = MaxValue; + + private: + u32 m_Index; + + explicit ResId(const u32 index) + : m_Index{index} + { + AddRef(); + } + + friend class CommitManager; + + public: + static ResId + Null() + { + return ResId{INVALID}; + } + + ResId(const ResId &other) + : m_Index{other.m_Index} + { + AddRef(); + } + + ResId(ResId &&other) noexcept + : m_Index{other.m_Index} + { + AddRef(); + } + + ResId & + operator=(const ResId &other) + { + if (this == &other) + return *this; + m_Index = other.m_Index; + AddRef(); + return *this; + } + + ResId & + operator=(ResId &&other) noexcept + { + if (this == &other) + return *this; + m_Index = other.m_Index; + AddRef(); + return *this; + } + + ~ResId() + { + Release(); + } + + private: + void AddRef() const; ///< Increases the refcount in the CommitManager. + void Release() const; ///< Decreases the refcount in the CommitManager. +}; + +struct NullId +{ + template + operator ResId() + { + return ResId::Null(); + } +}; + +} // namespace systems diff --git a/aster/include/aster/systems/resource_manager.h b/aster/include/aster/systems/resource_manager.h new file mode 100644 index 0000000..92a850a --- /dev/null +++ b/aster/include/aster/systems/resource_manager.h @@ -0,0 +1,52 @@ +// ============================================= +// Aster: resource_manager.h +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#pragma once + +#include "aster/aster.h" + +#include "buffer_manager.h" +#include "image_manager.h" +#include "sampler_manager.h" + +namespace systems +{ +class ResourceManager +{ + BufferManager m_Buffers; + ImageManager m_Images; + SamplerManager m_Samplers; + + public: + ResourceManager(const Device *device, u32 maxBufferCount, u32 maxImageCount, u32 maxSamplerCount) + : m_Buffers{device, maxBufferCount} + , m_Images{device, maxImageCount} + , m_Samplers{device, maxSamplerCount} + { + } + + BufferManager & + Buffers() + { + return m_Buffers; + } + + ImageManager & + Images() + { + return m_Images; + } + + SamplerManager & + Samplers() + { + return m_Samplers; + } + + ~ResourceManager() = default; + + PIN_MEMORY(ResourceManager); +}; +} // namespace systems \ No newline at end of file diff --git a/aster/include/aster/systems/sampler_manager.h b/aster/include/aster/systems/sampler_manager.h index db8425a..a9cbe84 100644 --- a/aster/include/aster/systems/sampler_manager.h +++ b/aster/include/aster/systems/sampler_manager.h @@ -5,37 +5,88 @@ #pragma once -#include "EASTL/vector_map.h" +#include "manager.h" +#include "EASTL/hash_map.h" + #include "aster/aster.h" #include "aster/core/sampler.h" -#include "manager.h" + +#include "EASTL/vector_map.h" + +template <> +struct eastl::hash +{ + usize + operator()(const vk::SamplerCreateInfo &createInfo) const noexcept + { + usize hash = HashAny(createInfo.flags); + hash = HashCombine(hash, HashAny(createInfo.magFilter)); + hash = HashCombine(hash, HashAny(createInfo.minFilter)); + hash = HashCombine(hash, HashAny(createInfo.mipmapMode)); + hash = HashCombine(hash, HashAny(createInfo.addressModeU)); + hash = HashCombine(hash, HashAny(createInfo.addressModeV)); + hash = HashCombine(hash, HashAny(createInfo.addressModeW)); + hash = HashCombine(hash, HashAny(Cast(createInfo.mipLodBias * 1000))); // Resolution of 10^-3 + hash = HashCombine(hash, HashAny(createInfo.anisotropyEnable)); + hash = + HashCombine(hash, + HashAny(Cast(createInfo.maxAnisotropy * 0x20))); // 32:1 Anisotropy is enough resolution + hash = HashCombine(hash, HashAny(createInfo.compareEnable)); + hash = HashCombine(hash, HashAny(createInfo.compareOp)); + hash = HashCombine(hash, HashAny(Cast(createInfo.minLod * 1000))); // 0.001 resolution is enough. + hash = + HashCombine(hash, + HashAny(Cast(createInfo.maxLod * 1000))); // 0.001 resolution is enough. (1 == NO Clamp) + hash = HashCombine(hash, HashAny(createInfo.borderColor)); + hash = HashCombine(hash, HashAny(createInfo.unnormalizedCoordinates)); + + return hash; + } +}; namespace systems { -using SamplerHandle = Manager::Handle; -struct SamplerCreateInfo : vk::SamplerCreateInfo +struct SamplerCreateInfo { cstr m_Name = nullptr; + vk::SamplerCreateFlags m_Flags = {}; + vk::Filter m_MagFilter = vk::Filter::eLinear; + vk::Filter m_MinFilter = vk::Filter::eLinear; + vk::SamplerMipmapMode m_MipmapMode = vk::SamplerMipmapMode::eLinear; + vk::SamplerAddressMode m_AddressModeU = vk::SamplerAddressMode::eRepeat; + vk::SamplerAddressMode m_AddressModeV = vk::SamplerAddressMode::eRepeat; + vk::SamplerAddressMode m_AddressModeW = vk::SamplerAddressMode::eRepeat; + vk::BorderColor m_BorderColor = vk::BorderColor::eFloatOpaqueBlack; + vk::CompareOp m_CompareOp = vk::CompareOp::eNever; + f32 m_MipLodBias = 0.0f; + f32 m_MaxAnisotropy = 16.0f; + f32 m_MinLod = 0; + f32 m_MaxLod = VK_LOD_CLAMP_NONE; + bool m_AnisotropyEnable = true; + bool m_CompareEnable = false; + bool m_NormalizedCoordinates = true; - SamplerCreateInfo() - : vk::SamplerCreateInfo{ - .magFilter = vk::Filter::eLinear, - .minFilter = vk::Filter::eLinear, - .mipmapMode = vk::SamplerMipmapMode::eLinear, - .addressModeU = vk::SamplerAddressMode::eRepeat, - .addressModeV = vk::SamplerAddressMode::eRepeat, - .addressModeW = vk::SamplerAddressMode::eRepeat, - .mipLodBias = 0.0f, - .anisotropyEnable = true, - .maxAnisotropy = 16, - .compareEnable = false, - .minLod = 0, - .maxLod = VK_LOD_CLAMP_NONE, - .borderColor = vk::BorderColor::eFloatOpaqueBlack, - .unnormalizedCoordinates = false, - } + explicit operator vk::SamplerCreateInfo() const { + return { + .flags = m_Flags, + .magFilter = m_MagFilter, + .minFilter = m_MinFilter, + .mipmapMode = m_MipmapMode, + .addressModeU = m_AddressModeU, + .addressModeV = m_AddressModeV, + .addressModeW = m_AddressModeW, + .mipLodBias = m_MipLodBias, + .anisotropyEnable = m_AnisotropyEnable, + .maxAnisotropy = m_MaxAnisotropy, + .compareEnable = m_CompareEnable, + .compareOp = m_CompareOp, + .minLod = m_MinLod, + .maxLod = m_MaxLod, + .borderColor = m_BorderColor, + .unnormalizedCoordinates = !m_NormalizedCoordinates, + }; } }; @@ -46,12 +97,12 @@ struct SamplerCreateInfo : vk::SamplerCreateInfo */ class SamplerManager final : public Manager { - eastl::vector_map m_HashToSamplerIdx; + eastl::hash_map m_HashToSamplerIdx; public: - SamplerManager(const Device *device, const u32 maxCount, const u8 typeId); + SamplerManager(const Device *device, const u32 maxCount); ~SamplerManager() override; - SamplerHandle Create(const SamplerCreateInfo &createInfo); + Ref CreateSampler(const SamplerCreateInfo &createInfo); }; } // namespace systems diff --git a/aster/include/aster/util/CMakeLists.txt b/aster/include/aster/util/CMakeLists.txt index 242a09d..34d26b6 100644 --- a/aster/include/aster/util/CMakeLists.txt +++ b/aster/include/aster/util/CMakeLists.txt @@ -3,4 +3,6 @@ cmake_minimum_required(VERSION 3.13) target_sources(aster_core - INTERFACE "logger.h" "intrusive_slist.h") +INTERFACE + "logger.h" + "intrusive_slist.h") diff --git a/aster/src/aster/core/image.cpp b/aster/src/aster/core/image.cpp index 4ae8f09..ce40071 100644 --- a/aster/src/aster/core/image.cpp +++ b/aster/src/aster/core/image.cpp @@ -17,407 +17,407 @@ Image::Destroy() vmaDestroyImage(m_Device->m_Allocator, Take(m_Image), m_Allocation); m_Flags_ = 0; } - -void -Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageFormat, const bool isMipMapped, - const cstr name) -{ - WARN_IF(!IsPowerOfTwo(extent.width) || !IsPowerOfTwo(extent.width), "Image {2} is {0}x{1} (Non Power of Two)", - extent.width, extent.height, name ? name : ""); - - const u8 mipLevels = isMipMapped ? 1 + Cast(floor(log2(eastl::max(extent.width, extent.height)))) : 1; - - auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst; - if (isMipMapped) - { - usage |= vk::ImageUsageFlagBits::eTransferSrc; - } - - vk::ImageCreateInfo imageCreateInfo = { - .imageType = vk::ImageType::e2D, - .format = imageFormat, - .extent = ToExtent3D(extent, 1), - .mipLevels = mipLevels, - .arrayLayers = 1, - .samples = vk::SampleCountFlagBits::e1, - .tiling = vk::ImageTiling::eOptimal, - .usage = usage, - .sharingMode = vk::SharingMode::eExclusive, - .initialLayout = vk::ImageLayout::eUndefined, - }; - constexpr VmaAllocationCreateInfo allocationCreateInfo = { - .flags = {}, - .usage = VMA_MEMORY_USAGE_AUTO, - }; - - VkImage image; - VmaAllocation allocation; - auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), - &allocationCreateInfo, &image, &allocation, nullptr)); - ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result); - - vk::ImageView view; - vk::ImageViewCreateInfo imageViewCreateInfo = { - .image = image, - .viewType = vk::ImageViewType::e2D, - .format = imageFormat, - .components = {}, - .subresourceRange = - { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = mipLevels, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); - ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result); - - m_Device = device; - m_Image = image; - m_View = view; - m_Allocation = allocation; - m_Extent = imageCreateInfo.extent; - m_LayerCount = 1; - m_MipLevels = mipLevels; - - device->SetName(m_Image, name); -} - -/* -Cube map Faces info. - -TODO: Correct this based on the actual layout for upside down viewport. - -| Axis | Layer | Up | -|:----:|:-----:|:--:| -| +x | 0 | -y | -| -x | 1 | -y | -| +y | 2 | +z | -| -y | 3 | -z | -| +z | 4 | -y | -| -z | 5 | -y | - -Remember, we use upside down viewport. - -*/ - -void -TextureCube::Init(const Device *device, u32 cubeSide, vk::Format imageFormat, bool isMipMapped, cstr name) -{ - WARN_IF(!IsPowerOfTwo(cubeSide), "Image Cube {1} has side {0}x{0} (Non Power of Two)", cubeSide, - name ? name : ""); - - const u8 mipLevels = isMipMapped ? 1 + Cast(floor(log2(cubeSide))) : 1; - - auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst; - if (isMipMapped) - { - usage |= vk::ImageUsageFlagBits::eTransferSrc; - } - - const vk::Extent3D extent = {.width = cubeSide, .height = cubeSide, .depth = 1}; - - vk::ImageCreateInfo imageCreateInfo = { - .flags = vk::ImageCreateFlagBits::eCubeCompatible, - .imageType = vk::ImageType::e2D, - .format = imageFormat, - .extent = extent, - .mipLevels = mipLevels, - .arrayLayers = 6, - .samples = vk::SampleCountFlagBits::e1, - .tiling = vk::ImageTiling::eOptimal, - .usage = usage, - .sharingMode = vk::SharingMode::eExclusive, - .initialLayout = vk::ImageLayout::eUndefined, - }; - constexpr VmaAllocationCreateInfo allocationCreateInfo = { - .flags = {}, - .usage = VMA_MEMORY_USAGE_AUTO, - }; - - VkImage image; - VmaAllocation allocation; - auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), - &allocationCreateInfo, &image, &allocation, nullptr)); - ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result); - - vk::ImageView view; - vk::ImageViewCreateInfo imageViewCreateInfo = { - .image = image, - .viewType = vk::ImageViewType::eCube, - .format = imageFormat, - .components = {}, - .subresourceRange = - { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = mipLevels, - .baseArrayLayer = 0, - .layerCount = 6, - }, - }; - result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); - ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result); - - m_Device = device; - m_Image = image; - m_View = view; - m_Allocation = allocation; - m_Extent = extent; - m_MipLevels = mipLevels; - m_LayerCount = 6; - - device->SetName(m_Image, name); -} - -void -AttachmentImage::Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, cstr name) -{ - vk::ImageCreateInfo imageCreateInfo = { - .imageType = vk::ImageType::e2D, - .format = imageFormat, - .extent = ToExtent3D(extent, 1), - .mipLevels = 1, - .arrayLayers = 1, - .samples = vk::SampleCountFlagBits::e1, - .tiling = vk::ImageTiling::eOptimal, - .usage = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, - .sharingMode = vk::SharingMode::eExclusive, - .initialLayout = vk::ImageLayout::eUndefined, - }; - constexpr VmaAllocationCreateInfo allocationCreateInfo = { - .flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, - .usage = VMA_MEMORY_USAGE_AUTO, - }; - - VkImage image; - VmaAllocation allocation; - auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), - &allocationCreateInfo, &image, &allocation, nullptr)); - ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result); - - vk::ImageView view; - vk::ImageViewCreateInfo imageViewCreateInfo = { - .image = image, - .viewType = vk::ImageViewType::e2D, - .format = imageFormat, - .components = {}, - .subresourceRange = - { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); - ERROR_IF(Failed(result), "Could not create attachment image view {}. Cause: {}", name, result) THEN_ABORT(result); - - m_Device = device; - m_Image = image; - m_View = view; - m_Allocation = allocation; - m_Extent = imageCreateInfo.extent; - m_MipLevels = 1; - m_LayerCount = 1; - - device->SetName(m_Image, name); -} - -void -DepthImage::Init(const Device *device, vk::Extent2D extent, cstr name) -{ - constexpr vk::Format imageFormat = vk::Format::eD24UnormS8Uint; - vk::ImageCreateInfo imageCreateInfo = { - .imageType = vk::ImageType::e2D, - .format = imageFormat, - .extent = ToExtent3D(extent, 1), - .mipLevels = 1, - .arrayLayers = 1, - .samples = vk::SampleCountFlagBits::e1, - .tiling = vk::ImageTiling::eOptimal, - .usage = vk::ImageUsageFlagBits::eDepthStencilAttachment, - .sharingMode = vk::SharingMode::eExclusive, - .initialLayout = vk::ImageLayout::eUndefined, - }; - constexpr VmaAllocationCreateInfo allocationCreateInfo = { - .flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, - .usage = VMA_MEMORY_USAGE_AUTO, - }; - - VkImage image; - VmaAllocation allocation; - auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), - &allocationCreateInfo, &image, &allocation, nullptr)); - ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result); - - vk::ImageView view; - vk::ImageViewCreateInfo imageViewCreateInfo = { - .image = image, - .viewType = vk::ImageViewType::e2D, - .format = imageFormat, - .components = {}, - .subresourceRange = - { - .aspectMask = vk::ImageAspectFlagBits::eDepth, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); - ERROR_IF(Failed(result), "Could not create depth image view {}. Cause: {}", name, result) THEN_ABORT(result); - - m_Device = device; - m_Image = image; - m_View = view; - m_Allocation = allocation; - m_Extent = imageCreateInfo.extent; - m_MipLevels = 1; - m_LayerCount = 1; - - device->SetName(m_Image, name); -} - -void -StorageTexture::Init(const Device *device, vk::Extent2D extent, const vk::Format imageFormat, const bool isSampled, - cstr name) -{ - // Reasoning: - // Transfer Src and Dst to copy to and from the buffer since Storage will often be loaded with info, and read for - // results. - auto usage = - vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst; - if (isSampled) - { - WARN_IF(!IsPowerOfTwo(extent.width) || !IsPowerOfTwo(extent.width), "Image {2} is {0}x{1} (Non Power of Two)", - extent.width, extent.height, name ? name : ""); - usage |= vk::ImageUsageFlagBits::eSampled; - } - - vk::ImageCreateInfo imageCreateInfo = { - .imageType = vk::ImageType::e2D, - .format = imageFormat, - .extent = ToExtent3D(extent, 1), - .mipLevels = 1, - .arrayLayers = 1, - .samples = vk::SampleCountFlagBits::e1, - .tiling = vk::ImageTiling::eOptimal, - .usage = usage, - .sharingMode = vk::SharingMode::eExclusive, - .initialLayout = vk::ImageLayout::eUndefined, - }; - constexpr VmaAllocationCreateInfo allocationCreateInfo = { - .flags = {}, - .usage = VMA_MEMORY_USAGE_AUTO, - }; - - VkImage image; - VmaAllocation allocation; - auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), - &allocationCreateInfo, &image, &allocation, nullptr)); - ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result); - - vk::ImageView view; - const vk::ImageViewCreateInfo imageViewCreateInfo = { - .image = image, - .viewType = vk::ImageViewType::e2D, - .format = imageFormat, - .components = {}, - .subresourceRange = - { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); - ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result); - - m_Device = device; - m_Image = image; - m_View = view; - m_Allocation = allocation; - m_Extent = imageCreateInfo.extent; - m_MipLevels = 1; - m_LayerCount = 1; - - device->SetName(m_Image, name); -} - -void -StorageTextureCube::Init(const Device *device, u32 cubeSide, vk::Format imageFormat, bool isSampled, bool isMipMapped, - cstr name) -{ - // Reasoning: - // Transfer Src and Dst to copy to and from the buffer since Storage will often be loaded with info, and read for - // results. - auto usage = - vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst; - if (isSampled) - { - WARN_IF(!IsPowerOfTwo(cubeSide), "Image {1} is {0}x{0} (Non Power of Two)", cubeSide, - name ? name : ""); - usage |= vk::ImageUsageFlagBits::eSampled; - } - - const u8 mipLevels = isMipMapped ? 1 + Cast(floor(log2(cubeSide))) : 1; - - vk::ImageCreateInfo imageCreateInfo = { - .flags = vk::ImageCreateFlagBits::eCubeCompatible, - .imageType = vk::ImageType::e2D, - .format = imageFormat, - .extent = {cubeSide, cubeSide, 1}, - .mipLevels = mipLevels, - .arrayLayers = 6, - .samples = vk::SampleCountFlagBits::e1, - .tiling = vk::ImageTiling::eOptimal, - .usage = usage, - .sharingMode = vk::SharingMode::eExclusive, - .initialLayout = vk::ImageLayout::eUndefined, - }; - constexpr VmaAllocationCreateInfo allocationCreateInfo = { - .flags = {}, - .usage = VMA_MEMORY_USAGE_AUTO, - }; - - VkImage image; - VmaAllocation allocation; - auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), - &allocationCreateInfo, &image, &allocation, nullptr)); - ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result); - - vk::ImageView view; - const vk::ImageViewCreateInfo imageViewCreateInfo = { - .image = image, - .viewType = vk::ImageViewType::eCube, - .format = imageFormat, - .components = {}, - .subresourceRange = - { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = mipLevels, - .baseArrayLayer = 0, - .layerCount = 6, - }, - }; - result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); - ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result); - - m_Device = device; - m_Image = image; - m_View = view; - m_Allocation = allocation; - m_Extent = imageCreateInfo.extent; - m_MipLevels = mipLevels; - m_LayerCount = 6; - - device->SetName(m_Image, name); -} +// +//void +//Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageFormat, const bool isMipMapped, +// const cstr name) +//{ +// WARN_IF(!IsPowerOfTwo(extent.width) || !IsPowerOfTwo(extent.width), "Image {2} is {0}x{1} (Non Power of Two)", +// extent.width, extent.height, name ? name : ""); +// +// const u8 mipLevels = isMipMapped ? 1 + Cast(floor(log2(eastl::max(extent.width, extent.height)))) : 1; +// +// auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst; +// if (isMipMapped) +// { +// usage |= vk::ImageUsageFlagBits::eTransferSrc; +// } +// +// vk::ImageCreateInfo imageCreateInfo = { +// .imageType = vk::ImageType::e2D, +// .format = imageFormat, +// .extent = ToExtent3D(extent, 1), +// .mipLevels = mipLevels, +// .arrayLayers = 1, +// .samples = vk::SampleCountFlagBits::e1, +// .tiling = vk::ImageTiling::eOptimal, +// .usage = usage, +// .sharingMode = vk::SharingMode::eExclusive, +// .initialLayout = vk::ImageLayout::eUndefined, +// }; +// constexpr VmaAllocationCreateInfo allocationCreateInfo = { +// .flags = {}, +// .usage = VMA_MEMORY_USAGE_AUTO, +// }; +// +// VkImage image; +// VmaAllocation allocation; +// auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), +// &allocationCreateInfo, &image, &allocation, nullptr)); +// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result); +// +// vk::ImageView view; +// vk::ImageViewCreateInfo imageViewCreateInfo = { +// .image = image, +// .viewType = vk::ImageViewType::e2D, +// .format = imageFormat, +// .components = {}, +// .subresourceRange = +// { +// .aspectMask = vk::ImageAspectFlagBits::eColor, +// .baseMipLevel = 0, +// .levelCount = mipLevels, +// .baseArrayLayer = 0, +// .layerCount = 1, +// }, +// }; +// result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); +// ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result); +// +// m_Device = device; +// m_Image = image; +// m_View = view; +// m_Allocation = allocation; +// m_Extent = imageCreateInfo.extent; +// m_LayerCount = 1; +// m_MipLevels = mipLevels; +// +// device->SetName(m_Image, name); +//} +// +///* +//Cube map Faces info. +// +//TODO: Correct this based on the actual layout for upside down viewport. +// +//| Axis | Layer | Up | +//|:----:|:-----:|:--:| +//| +x | 0 | -y | +//| -x | 1 | -y | +//| +y | 2 | +z | +//| -y | 3 | -z | +//| +z | 4 | -y | +//| -z | 5 | -y | +// +//Remember, we use upside down viewport. +// +//*/ +// +//void +//TextureCube::Init(const Device *device, u32 cubeSide, vk::Format imageFormat, bool isMipMapped, cstr name) +//{ +// WARN_IF(!IsPowerOfTwo(cubeSide), "Image Cube {1} has side {0}x{0} (Non Power of Two)", cubeSide, +// name ? name : ""); +// +// const u8 mipLevels = isMipMapped ? 1 + Cast(floor(log2(cubeSide))) : 1; +// +// auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst; +// if (isMipMapped) +// { +// usage |= vk::ImageUsageFlagBits::eTransferSrc; +// } +// +// const vk::Extent3D extent = {.width = cubeSide, .height = cubeSide, .depth = 1}; +// +// vk::ImageCreateInfo imageCreateInfo = { +// .flags = vk::ImageCreateFlagBits::eCubeCompatible, +// .imageType = vk::ImageType::e2D, +// .format = imageFormat, +// .extent = extent, +// .mipLevels = mipLevels, +// .arrayLayers = 6, +// .samples = vk::SampleCountFlagBits::e1, +// .tiling = vk::ImageTiling::eOptimal, +// .usage = usage, +// .sharingMode = vk::SharingMode::eExclusive, +// .initialLayout = vk::ImageLayout::eUndefined, +// }; +// constexpr VmaAllocationCreateInfo allocationCreateInfo = { +// .flags = {}, +// .usage = VMA_MEMORY_USAGE_AUTO, +// }; +// +// VkImage image; +// VmaAllocation allocation; +// auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), +// &allocationCreateInfo, &image, &allocation, nullptr)); +// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result); +// +// vk::ImageView view; +// vk::ImageViewCreateInfo imageViewCreateInfo = { +// .image = image, +// .viewType = vk::ImageViewType::eCube, +// .format = imageFormat, +// .components = {}, +// .subresourceRange = +// { +// .aspectMask = vk::ImageAspectFlagBits::eColor, +// .baseMipLevel = 0, +// .levelCount = mipLevels, +// .baseArrayLayer = 0, +// .layerCount = 6, +// }, +// }; +// result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); +// ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result); +// +// m_Device = device; +// m_Image = image; +// m_View = view; +// m_Allocation = allocation; +// m_Extent = extent; +// m_MipLevels = mipLevels; +// m_LayerCount = 6; +// +// device->SetName(m_Image, name); +//} +// +//void +//AttachmentImage::Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, cstr name) +//{ +// vk::ImageCreateInfo imageCreateInfo = { +// .imageType = vk::ImageType::e2D, +// .format = imageFormat, +// .extent = ToExtent3D(extent, 1), +// .mipLevels = 1, +// .arrayLayers = 1, +// .samples = vk::SampleCountFlagBits::e1, +// .tiling = vk::ImageTiling::eOptimal, +// .usage = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, +// .sharingMode = vk::SharingMode::eExclusive, +// .initialLayout = vk::ImageLayout::eUndefined, +// }; +// constexpr VmaAllocationCreateInfo allocationCreateInfo = { +// .flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, +// .usage = VMA_MEMORY_USAGE_AUTO, +// }; +// +// VkImage image; +// VmaAllocation allocation; +// auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), +// &allocationCreateInfo, &image, &allocation, nullptr)); +// ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result); +// +// vk::ImageView view; +// vk::ImageViewCreateInfo imageViewCreateInfo = { +// .image = image, +// .viewType = vk::ImageViewType::e2D, +// .format = imageFormat, +// .components = {}, +// .subresourceRange = +// { +// .aspectMask = vk::ImageAspectFlagBits::eColor, +// .baseMipLevel = 0, +// .levelCount = 1, +// .baseArrayLayer = 0, +// .layerCount = 1, +// }, +// }; +// result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); +// ERROR_IF(Failed(result), "Could not create attachment image view {}. Cause: {}", name, result) THEN_ABORT(result); +// +// m_Device = device; +// m_Image = image; +// m_View = view; +// m_Allocation = allocation; +// m_Extent = imageCreateInfo.extent; +// m_MipLevels = 1; +// m_LayerCount = 1; +// +// device->SetName(m_Image, name); +//} +// +//void +//DepthImage::Init(const Device *device, vk::Extent2D extent, cstr name) +//{ +// constexpr vk::Format imageFormat = vk::Format::eD24UnormS8Uint; +// vk::ImageCreateInfo imageCreateInfo = { +// .imageType = vk::ImageType::e2D, +// .format = imageFormat, +// .extent = ToExtent3D(extent, 1), +// .mipLevels = 1, +// .arrayLayers = 1, +// .samples = vk::SampleCountFlagBits::e1, +// .tiling = vk::ImageTiling::eOptimal, +// .usage = vk::ImageUsageFlagBits::eDepthStencilAttachment, +// .sharingMode = vk::SharingMode::eExclusive, +// .initialLayout = vk::ImageLayout::eUndefined, +// }; +// constexpr VmaAllocationCreateInfo allocationCreateInfo = { +// .flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, +// .usage = VMA_MEMORY_USAGE_AUTO, +// }; +// +// VkImage image; +// VmaAllocation allocation; +// auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), +// &allocationCreateInfo, &image, &allocation, nullptr)); +// ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result); +// +// vk::ImageView view; +// vk::ImageViewCreateInfo imageViewCreateInfo = { +// .image = image, +// .viewType = vk::ImageViewType::e2D, +// .format = imageFormat, +// .components = {}, +// .subresourceRange = +// { +// .aspectMask = vk::ImageAspectFlagBits::eDepth, +// .baseMipLevel = 0, +// .levelCount = 1, +// .baseArrayLayer = 0, +// .layerCount = 1, +// }, +// }; +// result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); +// ERROR_IF(Failed(result), "Could not create depth image view {}. Cause: {}", name, result) THEN_ABORT(result); +// +// m_Device = device; +// m_Image = image; +// m_View = view; +// m_Allocation = allocation; +// m_Extent = imageCreateInfo.extent; +// m_MipLevels = 1; +// m_LayerCount = 1; +// +// device->SetName(m_Image, name); +//} +// +//void +//StorageTexture::Init(const Device *device, vk::Extent2D extent, const vk::Format imageFormat, const bool isSampled, +// cstr name) +//{ +// // Reasoning: +// // Transfer Src and Dst to copy to and from the buffer since Storage will often be loaded with info, and read for +// // results. +// auto usage = +// vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst; +// if (isSampled) +// { +// WARN_IF(!IsPowerOfTwo(extent.width) || !IsPowerOfTwo(extent.width), "Image {2} is {0}x{1} (Non Power of Two)", +// extent.width, extent.height, name ? name : ""); +// usage |= vk::ImageUsageFlagBits::eSampled; +// } +// +// vk::ImageCreateInfo imageCreateInfo = { +// .imageType = vk::ImageType::e2D, +// .format = imageFormat, +// .extent = ToExtent3D(extent, 1), +// .mipLevels = 1, +// .arrayLayers = 1, +// .samples = vk::SampleCountFlagBits::e1, +// .tiling = vk::ImageTiling::eOptimal, +// .usage = usage, +// .sharingMode = vk::SharingMode::eExclusive, +// .initialLayout = vk::ImageLayout::eUndefined, +// }; +// constexpr VmaAllocationCreateInfo allocationCreateInfo = { +// .flags = {}, +// .usage = VMA_MEMORY_USAGE_AUTO, +// }; +// +// VkImage image; +// VmaAllocation allocation; +// auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), +// &allocationCreateInfo, &image, &allocation, nullptr)); +// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result); +// +// vk::ImageView view; +// const vk::ImageViewCreateInfo imageViewCreateInfo = { +// .image = image, +// .viewType = vk::ImageViewType::e2D, +// .format = imageFormat, +// .components = {}, +// .subresourceRange = +// { +// .aspectMask = vk::ImageAspectFlagBits::eColor, +// .baseMipLevel = 0, +// .levelCount = 1, +// .baseArrayLayer = 0, +// .layerCount = 1, +// }, +// }; +// result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); +// ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result); +// +// m_Device = device; +// m_Image = image; +// m_View = view; +// m_Allocation = allocation; +// m_Extent = imageCreateInfo.extent; +// m_MipLevels = 1; +// m_LayerCount = 1; +// +// device->SetName(m_Image, name); +//} +// +//void +//StorageTextureCube::Init(const Device *device, u32 cubeSide, vk::Format imageFormat, bool isSampled, bool isMipMapped, +// cstr name) +//{ +// // Reasoning: +// // Transfer Src and Dst to copy to and from the buffer since Storage will often be loaded with info, and read for +// // results. +// auto usage = +// vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst; +// if (isSampled) +// { +// WARN_IF(!IsPowerOfTwo(cubeSide), "Image {1} is {0}x{0} (Non Power of Two)", cubeSide, +// name ? name : ""); +// usage |= vk::ImageUsageFlagBits::eSampled; +// } +// +// const u8 mipLevels = isMipMapped ? 1 + Cast(floor(log2(cubeSide))) : 1; +// +// vk::ImageCreateInfo imageCreateInfo = { +// .flags = vk::ImageCreateFlagBits::eCubeCompatible, +// .imageType = vk::ImageType::e2D, +// .format = imageFormat, +// .extent = {cubeSide, cubeSide, 1}, +// .mipLevels = mipLevels, +// .arrayLayers = 6, +// .samples = vk::SampleCountFlagBits::e1, +// .tiling = vk::ImageTiling::eOptimal, +// .usage = usage, +// .sharingMode = vk::SharingMode::eExclusive, +// .initialLayout = vk::ImageLayout::eUndefined, +// }; +// constexpr VmaAllocationCreateInfo allocationCreateInfo = { +// .flags = {}, +// .usage = VMA_MEMORY_USAGE_AUTO, +// }; +// +// VkImage image; +// VmaAllocation allocation; +// auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), +// &allocationCreateInfo, &image, &allocation, nullptr)); +// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result); +// +// vk::ImageView view; +// const vk::ImageViewCreateInfo imageViewCreateInfo = { +// .image = image, +// .viewType = vk::ImageViewType::eCube, +// .format = imageFormat, +// .components = {}, +// .subresourceRange = +// { +// .aspectMask = vk::ImageAspectFlagBits::eColor, +// .baseMipLevel = 0, +// .levelCount = mipLevels, +// .baseArrayLayer = 0, +// .layerCount = 6, +// }, +// }; +// result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); +// ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", name, result) THEN_ABORT(result); +// +// m_Device = device; +// m_Image = image; +// m_View = view; +// m_Allocation = allocation; +// m_Extent = imageCreateInfo.extent; +// m_MipLevels = mipLevels; +// m_LayerCount = 6; +// +// device->SetName(m_Image, name); +//} diff --git a/aster/src/aster/systems/CMakeLists.txt b/aster/src/aster/systems/CMakeLists.txt index 519d315..7bafe6a 100644 --- a/aster/src/aster/systems/CMakeLists.txt +++ b/aster/src/aster/systems/CMakeLists.txt @@ -8,4 +8,4 @@ PRIVATE "buffer_manager.cpp" "image_manager.cpp" "sampler_manager.cpp" -"render_resource_manager.cpp") +"commit_manager.cpp") diff --git a/aster/src/aster/systems/buffer_manager.cpp b/aster/src/aster/systems/buffer_manager.cpp index acb67f2..100bf14 100644 --- a/aster/src/aster/systems/buffer_manager.cpp +++ b/aster/src/aster/systems/buffer_manager.cpp @@ -7,17 +7,16 @@ using namespace systems; -Manager *Manager::m_Instance = nullptr; - -BufferHandle +Ref BufferManager::CreateStorageBuffer(const usize size, const cstr name) { auto object = Alloc(); // TODO: Storage and Index buffer are set. // This is hacky and should be improved. - constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndexBuffer | - vk::BufferUsageFlagBits::eShaderDeviceAddress; + constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | + vk::BufferUsageFlagBits::eIndexBuffer | + vk::BufferUsageFlagBits::eShaderDeviceAddress; constexpr VmaAllocationCreateFlags createFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT; @@ -27,7 +26,7 @@ BufferManager::CreateStorageBuffer(const usize size, const cstr name) return object; } -Manager::Handle +Ref BufferManager::CreateUniformBuffer(const usize size, const cstr name) { auto object = Alloc(); @@ -42,7 +41,21 @@ BufferManager::CreateUniformBuffer(const usize size, const cstr name) return object; } -BufferManager::BufferManager(const Device *device, const u32 maxCount, const u8 binding) - : Manager{device, maxCount, binding} +Manager::Handle +BufferManager::CreateStagingBuffer(const usize size, const cstr name) +{ + auto object = Alloc(); + + constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eTransferSrc; + constexpr VmaAllocationCreateFlags createFlags = + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT; + constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO; + object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name); + + return object; +} + +BufferManager::BufferManager(const Device *device, const u32 maxCount) + : Manager{device, maxCount} { } \ No newline at end of file diff --git a/aster/src/aster/systems/render_resource_manager.cpp b/aster/src/aster/systems/commit_manager.cpp similarity index 80% rename from aster/src/aster/systems/render_resource_manager.cpp rename to aster/src/aster/systems/commit_manager.cpp index 7e765d8..96d69e6 100644 --- a/aster/src/aster/systems/render_resource_manager.cpp +++ b/aster/src/aster/systems/commit_manager.cpp @@ -3,7 +3,7 @@ // Copyright (c) 2020-2025 Anish Bhobe // ============================================= -#include "systems/render_resource_manager.h" +#include "systems/commit_manager.h" #include "EASTL/array.h" #include "core/device.h" @@ -33,14 +33,15 @@ using namespace systems; -RenderResourceManager *RenderResourceManager::m_Instance = nullptr; +CommitManager *CommitManager::m_Instance = nullptr; -RenderResourceManager::RenderResourceManager(const Device *device, u32 const maxBuffers, const u32 maxImages, - const SamplerHandle &defaultSampler) +CommitManager::CommitManager(const Device *device, u32 const maxBuffers, const u32 maxImages, const u32 maxStorageImages, + Ref defaultSampler) : m_Device{device} , m_Buffers{maxBuffers} , m_Images{maxImages} - , m_DefaultSampler{defaultSampler} + , m_StorageImages{maxStorageImages} + , m_DefaultSampler{std::move(defaultSampler)} { assert(!m_Instance); @@ -80,12 +81,12 @@ RenderResourceManager::RenderResourceManager(const Device *device, u32 const max .descriptorCount = Cast(maxImages), .stageFlags = vk::ShaderStageFlagBits::eAll, }, - // vk::DescriptorSetLayoutBinding{ - // .binding = STORAGE_TEXTURE_BINDING_INDEX, - // .descriptorType = vk::DescriptorType::eStorageImage, - // .descriptorCount = Cast(storageTexturesCount), - // .stageFlags = vk::ShaderStageFlagBits::eAll, - // }, + vk::DescriptorSetLayoutBinding{ + .binding = STORAGE_IMAGE_BINDING_INDEX, + .descriptorType = vk::DescriptorType::eStorageImage, + .descriptorCount = Cast(maxStorageImages), + .stageFlags = vk::ShaderStageFlagBits::eAll, + }, }; vk::DescriptorBindingFlags bindingFlags = @@ -125,7 +126,7 @@ RenderResourceManager::RenderResourceManager(const Device *device, u32 const max m_Instance = this; } -RenderResourceManager::~RenderResourceManager() +CommitManager::~CommitManager() { m_Device->m_Device.destroy(m_SetLayout, nullptr); m_Device->m_Device.destroy(m_DescriptorPool, nullptr); @@ -148,8 +149,8 @@ RenderResourceManager::~RenderResourceManager() #endif } -CommitEntry -RenderResourceManager::Commit(const BufferHandle &buffer) +ResId +CommitManager::CommitBuffer(const Ref &buffer) { auto [commit, isNew] = m_Buffers.Create(buffer); @@ -173,14 +174,38 @@ RenderResourceManager::Commit(const BufferHandle &buffer) return commit; } -CommitEntry -RenderResourceManager::Commit(const ImageHandle &handle) +ResId +CommitManager::CommitStorageImage(const Ref &image) { - return Commit(handle, m_DefaultSampler); + auto [commit, isNew] = m_StorageImages.Create(image); + if (!isNew) + return commit; + + m_WriteInfos.emplace_back(vk::DescriptorImageInfo{ + .sampler = nullptr, + .imageView = image->m_View, + .imageLayout = vk::ImageLayout::eGeneral, + }); + m_Writes.push_back({ + .dstSet = m_DescriptorSet, + .dstBinding = STORAGE_IMAGE_BINDING_INDEX, + .dstArrayElement = commit.m_Index, + .descriptorCount = 1, + .descriptorType = vk::DescriptorType::eStorageImage, + .pImageInfo = &m_WriteInfos.back().uImageInfo, + }); + + return commit; } -CommitEntry -RenderResourceManager::Commit(const ImageHandle &image, const SamplerHandle &sampler) +ResId +CommitManager::CommitTexture(const Ref &handle) +{ + return CommitTexture(handle, m_DefaultSampler); +} + +ResId +CommitManager::CommitTexture(const Ref &image, const Ref &sampler) { auto [commit, isNew] = m_Images.Create(image); if (!isNew) @@ -203,23 +228,23 @@ RenderResourceManager::Commit(const ImageHandle &image, const SamplerHandle &sam return commit; } -RenderResourceManager::WriteInfo::WriteInfo(const vk::DescriptorBufferInfo &info) +CommitManager::WriteInfo::WriteInfo(const vk::DescriptorBufferInfo &info) : uBufferInfo{info} { } -RenderResourceManager::WriteInfo::WriteInfo(const vk::DescriptorImageInfo &info) +CommitManager::WriteInfo::WriteInfo(const vk::DescriptorImageInfo &info) : uImageInfo{info} { } -RenderResourceManager::WriteInfo::WriteInfo(const vk::BufferView &info) +CommitManager::WriteInfo::WriteInfo(const vk::BufferView &info) : uBufferView{info} { } void -RenderResourceManager::Update() +CommitManager::Update() { // Descriptor Updates if (!m_Writes.empty()) diff --git a/aster/src/aster/systems/image_manager.cpp b/aster/src/aster/systems/image_manager.cpp index 8d65144..51fde05 100644 --- a/aster/src/aster/systems/image_manager.cpp +++ b/aster/src/aster/systems/image_manager.cpp @@ -9,8 +9,6 @@ using namespace systems; -Manager *Manager::m_Instance = nullptr; - vk::ImageCreateInfo ToImageCreateInfo(const Texture2DCreateInfo &createInfo); vk::ImageCreateInfo ToImageCreateInfo(const TextureCubeCreateInfo &createInfo); vk::ImageCreateInfo ToImageCreateInfo(const AttachmentCreateInfo &createInfo); @@ -27,7 +25,7 @@ constexpr vk::ImageUsageFlags COLOR_ATTACHMENT = constexpr vk::ImageUsageFlags DEPTH_STENCIL_ATTACHMENT = vk::ImageUsageFlagBits::eDepthStencilAttachment; } // namespace usage_flags -ImageHandle +Ref ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo) { constexpr VmaAllocationCreateInfo allocationCreateInfo = { @@ -68,13 +66,18 @@ ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo) object->m_Extent = imageCreateInfo.extent; object->m_LayerCount = Cast(imageCreateInfo.arrayLayers); object->m_MipLevels = Cast(imageCreateInfo.mipLevels); + object->m_Flags_ = {}; + if (createInfo.m_IsSampled) + object->m_Flags_ |= Image::SAMPLED_BIT; + if (createInfo.m_IsStorage) + object->m_Flags_ |= Image::STORAGE_BIT; m_Device->SetName(object->m_Image, createInfo.m_Name); return object; } -ImageHandle +Ref ImageManager::CreateTextureCube(const TextureCubeCreateInfo &createInfo) { constexpr VmaAllocationCreateInfo allocationCreateInfo = { @@ -115,13 +118,18 @@ ImageManager::CreateTextureCube(const TextureCubeCreateInfo &createInfo) object->m_Extent = imageCreateInfo.extent; object->m_LayerCount = Cast(imageCreateInfo.arrayLayers); object->m_MipLevels = Cast(imageCreateInfo.mipLevels); + object->m_Flags_ = Image::CUBE_BIT; + if (createInfo.m_IsSampled) + object->m_Flags_ |= Image::SAMPLED_BIT; + if (createInfo.m_IsStorage) + object->m_Flags_ |= Image::STORAGE_BIT; m_Device->SetName(object->m_Image, createInfo.m_Name); - return object; + return CastImage(object); } -ImageHandle +Ref ImageManager::CreateAttachment(const AttachmentCreateInfo &createInfo) { constexpr VmaAllocationCreateInfo allocationCreateInfo = { @@ -168,7 +176,7 @@ ImageManager::CreateAttachment(const AttachmentCreateInfo &createInfo) return object; } -ImageHandle +Ref ImageManager::CreateDepthStencilImage(const DepthStencilImageCreateInfo &createInfo) { constexpr VmaAllocationCreateInfo allocationCreateInfo = { @@ -306,7 +314,7 @@ ToImageCreateInfo(const DepthStencilImageCreateInfo &createInfo) }; } -ImageManager::ImageManager(const Device *device, const u32 maxCount, const u8 binding) - : Manager{device, maxCount, binding} +ImageManager::ImageManager(const Device *device, const u32 maxCount) + : Manager{device, maxCount} { } \ No newline at end of file diff --git a/aster/src/aster/systems/sampler_manager.cpp b/aster/src/aster/systems/sampler_manager.cpp index c93080c..f4a4d8d 100644 --- a/aster/src/aster/systems/sampler_manager.cpp +++ b/aster/src/aster/systems/sampler_manager.cpp @@ -9,35 +9,8 @@ using namespace systems; -Manager *Manager::m_Instance = nullptr; - -usize -HashSamplerCreateInfo(const vk::SamplerCreateInfo &createInfo) -{ - usize hash = HashAny(createInfo.flags); - hash = HashCombine(hash, HashAny(createInfo.magFilter)); - hash = HashCombine(hash, HashAny(createInfo.minFilter)); - hash = HashCombine(hash, HashAny(createInfo.mipmapMode)); - hash = HashCombine(hash, HashAny(createInfo.addressModeU)); - hash = HashCombine(hash, HashAny(createInfo.addressModeV)); - hash = HashCombine(hash, HashAny(createInfo.addressModeW)); - hash = HashCombine(hash, HashAny(Cast(createInfo.mipLodBias * 1000))); // Resolution of 10^-3 - hash = HashCombine(hash, HashAny(createInfo.anisotropyEnable)); - hash = HashCombine(hash, - HashAny(Cast(createInfo.maxAnisotropy * 0x20))); // 32:1 Anisotropy is enough resolution - hash = HashCombine(hash, HashAny(createInfo.compareEnable)); - hash = HashCombine(hash, HashAny(createInfo.compareOp)); - hash = HashCombine(hash, HashAny(Cast(createInfo.minLod * 1000))); // 0.001 resolution is enough. - hash = HashCombine(hash, - HashAny(Cast(createInfo.maxLod * 1000))); // 0.001 resolution is enough. (1 == NO Clamp) - hash = HashCombine(hash, HashAny(createInfo.borderColor)); - hash = HashCombine(hash, HashAny(createInfo.unnormalizedCoordinates)); - - return hash; -} - -SamplerManager::SamplerManager(const Device *device, const u32 maxCount, const u8 typeId) - : Manager{device, maxCount, typeId} +SamplerManager::SamplerManager(const Device *device, const u32 maxCount) + : Manager{device, maxCount} { } @@ -46,21 +19,20 @@ SamplerManager::~SamplerManager() m_HashToSamplerIdx.clear(); } -SamplerHandle -SamplerManager::Create(const SamplerCreateInfo &createInfo) +Ref +SamplerManager::CreateSampler(const SamplerCreateInfo &createInfo) { - const auto hash = HashSamplerCreateInfo(createInfo); + auto vkCreateInfo = Cast(createInfo); - if (const auto iter = m_HashToSamplerIdx.find(hash); iter != m_HashToSamplerIdx.end()) + if (const auto iter = m_HashToSamplerIdx.find(vkCreateInfo); iter != m_HashToSamplerIdx.end()) { return iter->second; } auto object = Alloc(); - object->Init(m_Device, createInfo, createInfo.m_Name ? createInfo.m_Name : nullptr); - m_HashToSamplerIdx.emplace(hash, object); + object->Init(m_Device, vkCreateInfo, createInfo.m_Name ? createInfo.m_Name : nullptr); + m_HashToSamplerIdx.emplace(vkCreateInfo, object); return object; } - diff --git a/samples/00_util/gui.h b/samples/00_util/gui.h index d27a98e..7b8c551 100644 --- a/samples/00_util/gui.h +++ b/samples/00_util/gui.h @@ -9,7 +9,6 @@ #include -struct AttachmentImage; struct Device; struct Context; struct Window; diff --git a/samples/02_box/box.cpp b/samples/02_box/box.cpp index fd2d5f1..9f8bdde 100644 --- a/samples/02_box/box.cpp +++ b/samples/02_box/box.cpp @@ -20,7 +20,7 @@ #define STB_IMAGE_IMPLEMENTATION #include "aster/systems/buffer_manager.h" #include "aster/systems/image_manager.h" -#include "aster/systems/render_resource_manager.h" +#include "aster/systems/commit_manager.h" #include "frame.h" #include "stb_image.h" @@ -74,7 +74,7 @@ ImageFile::~ImageFile() } vk::ShaderModule CreateShader(const Device *device, cstr shaderFile); -Pipeline CreatePipeline(const systems::RenderResourceManager *resourceManager, const Swapchain *swapchain); +Pipeline CreatePipeline(const systems::CommitManager *resourceManager, const Swapchain *swapchain); struct Vertex { @@ -129,13 +129,13 @@ main(int, char **) vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0); Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"}; - systems::BufferManager bufferManager{&device, 12, 0}; - systems::ImageManager imageManager{&device, 12, 1}; - systems::SamplerManager samplerManager{&device, 1, 0xF}; + systems::BufferManager bufferManager{&device, 12}; + systems::ImageManager imageManager{&device, 12}; + systems::SamplerManager samplerManager{&device, 1}; - systems::RenderResourceManager renderResourceManager{&device, 12, 12, samplerManager.Create({})}; + systems::CommitManager commitManager{&device, 12, 12, 12, samplerManager.CreateSampler({})}; - Pipeline pipeline = CreatePipeline(&renderResourceManager, &swapchain); + Pipeline pipeline = CreatePipeline(&commitManager, &swapchain); Camera camera = { .m_Model = {1.0f}, @@ -389,7 +389,7 @@ main(int, char **) }; FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT}; - eastl::fixed_vector depthImages; + eastl::fixed_vector, MAX_FRAMES_IN_FLIGHT> depthImages; auto initDepthImages = [&depthImages, &frameManager, &imageManager](const vk::Extent2D extent) { for (u32 i = 0; i < frameManager.m_FramesInFlight; ++i) @@ -409,15 +409,15 @@ main(int, char **) struct PCB { - systems::CommitEntry m_Camera; - systems::CommitEntry m_VertexBuffer; - systems::CommitEntry m_Texture; + systems::ResId m_Camera; + systems::ResId m_VertexBuffer; + systems::ResId m_Texture; }; PCB pcb = { - .m_Camera = renderResourceManager.Commit(ubo), - .m_VertexBuffer = renderResourceManager.Commit(vbo), - .m_Texture = renderResourceManager.Commit(crate), + .m_Camera = commitManager.CommitBuffer(ubo), + .m_VertexBuffer = commitManager.CommitBuffer(vbo), + .m_Texture = commitManager.CommitTexture(systems::CastImage(crate)), }; Time::Init(); @@ -426,7 +426,7 @@ main(int, char **) while (window.Poll()) { Time::Update(); - renderResourceManager.Update(); + commitManager.Update(); camera.m_Model *= rotate(mat4{1.0f}, Cast(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f)); ubo->Write(0, sizeof camera, &camera); @@ -482,7 +482,7 @@ main(int, char **) cmd.setScissor(0, 1, &scissor); cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline); cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1, - &renderResourceManager.GetDescriptorSet(), 0, nullptr); + &commitManager.GetDescriptorSet(), 0, nullptr); cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAllGraphics, 0, 12, &pcb); cmd.draw(Cast(vertices.size()), 1, 0, 0); @@ -514,7 +514,7 @@ main(int, char **) } Pipeline -CreatePipeline(const systems::RenderResourceManager *resourceManager, const Swapchain *swapchain) +CreatePipeline(const systems::CommitManager *resourceManager, const Swapchain *swapchain) { // Pipeline Setup auto *device = resourceManager->m_Device; diff --git a/samples/03_model_render/CMakeLists.txt b/samples/03_model_render/CMakeLists.txt index 205f595..b632100 100644 --- a/samples/03_model_render/CMakeLists.txt +++ b/samples/03_model_render/CMakeLists.txt @@ -12,12 +12,11 @@ add_executable(model_render "model_render.cpp" "asset_loader.h" "light_manager.cpp" "light_manager.h" - "gpu_resource_manager.cpp" - "gpu_resource_manager.h" "nodes.cpp" "nodes.h" "ibl_helpers.cpp" - "ibl_helpers.h") + "ibl_helpers.h" + "tiny_gltf_setup.cpp") add_shader(model_render "shader/model.vs.hlsl") add_shader(model_render "shader/model.ps.hlsl") diff --git a/samples/03_model_render/asset_loader.cpp b/samples/03_model_render/asset_loader.cpp index bf0133c..e12fe82 100644 --- a/samples/03_model_render/asset_loader.cpp +++ b/samples/03_model_render/asset_loader.cpp @@ -3,26 +3,25 @@ // Copyright (c) 2020-2024 Anish Bhobe // ============================================= -#define TINYGLTF_NOEXCEPTION -#define JSON_NOEXCEPTION - -#define TINYGLTF_IMPLEMENTATION -#define STB_IMAGE_IMPLEMENTATION -#define STB_IMAGE_WRITE_IMPLEMENTATION - #include "aster/core/buffer.h" #include "aster/core/device.h" #include "aster/core/image.h" -#include "gpu_resource_manager.h" -#include "helpers.h" #include "asset_loader.h" +#include "helpers.h" + +#include "aster/systems/commit_manager.h" +#include "aster/systems/resource_manager.h" #include #include + #include +#include + #include +#include #if defined(LoadImage) #undef LoadImage @@ -54,12 +53,9 @@ VectorToVec3(const std::vector &vec) return {vec[0], vec[1], vec[2]}; } -void -AssetLoader::LoadHdrImage(Texture *texture, cstr path, cstr name) const +Ref +AssetLoader::LoadHdrImage(cstr path, cstr name) const { - const Device *pDevice = m_ResourceManager->m_Device; - ERROR_IF(texture->IsValid(), "Expected invalid image.") THEN_ABORT(-1); - i32 x, y, nChannels; f32 *data = stbi_loadf(path, &x, &y, &nChannels, 4); assert(nChannels == 3); @@ -69,11 +65,20 @@ AssetLoader::LoadHdrImage(Texture *texture, cstr path, cstr name) const u32 width = Cast(x); u32 height = Cast(y); + auto texture = m_ResourceManager->Images().CreateTexture2D({ + .m_Format = vk::Format::eR32G32B32A32Sfloat, + .m_Extent = {width, height}, + .m_Name = path, + .m_IsSampled = true, + .m_IsMipMapped = false, + .m_IsStorage = false, + }); + + auto *pDevice = m_CommitManager->m_Device; + StagingBuffer stagingBuffer; - texture->Init(m_ResourceManager->m_Device, {width, height}, vk::Format::eR32G32B32A32Sfloat, false, path); - assert(texture->IsValid()); - stagingBuffer.Init(m_ResourceManager->m_Device, (sizeof *data) * x * y * 4, "HDR Staging Buffer"); - stagingBuffer.Write(m_ResourceManager->m_Device, 0, stagingBuffer.GetSize(), data); + stagingBuffer.Init(pDevice, (sizeof *data) * x * y * 4, "HDR Staging Buffer"); + stagingBuffer.Write(0, stagingBuffer.m_Size, data); stbi_image_free(data); @@ -189,11 +194,13 @@ AssetLoader::LoadHdrImage(Texture *texture, cstr path, cstr name) const AbortIfFailed(pDevice->m_Device.resetCommandPool(m_CommandPool, {})); - stagingBuffer.Destroy(pDevice); + stagingBuffer.Destroy(); + + return texture; } void -GenerateMipMaps(vk::CommandBuffer commandBuffer, Texture *texture, vk::ImageLayout initialLayout, +GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref &texture, vk::ImageLayout initialLayout, vk::ImageLayout finalLayout, vk::PipelineStageFlags2 prevStage, vk::PipelineStageFlags2 finalStage) { #if !defined(ASTER_NDEBUG) @@ -362,8 +369,8 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, Texture *texture, vk::ImageLayo #endif } -TextureHandle -AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image, bool isSrgb) const +std::tuple, Ref> +AssetLoader::LoadImageToGpu(tinygltf::Image* image, bool isSrgb) const { assert(image->component == 4); assert(image->height > 0 && image->width > 0); @@ -373,13 +380,17 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image vk::Format imageFormat = isSrgb ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm; - Texture texture; - usize byteSize = image->image.size(); - texture.Init(m_ResourceManager->m_Device, {.width = width, .height = height}, imageFormat, true, - image->name.data()); - stagingBuffer->Init(m_ResourceManager->m_Device, byteSize); - stagingBuffer->Write(m_ResourceManager->m_Device, 0, byteSize, image->image.data()); + auto texture = m_ResourceManager->Images().CreateTexture2D({ + .m_Format = imageFormat, + .m_Extent = {width, height}, + .m_Name = image->name.c_str(), + .m_IsSampled = true, + .m_IsMipMapped = true, + .m_IsStorage = false, + }); + auto stagingBuffer = m_ResourceManager->Buffers().CreateStagingBuffer(byteSize); + stagingBuffer->Write(0, byteSize, image->image.data()); #if !defined(ASTER_NDEBUG) StackString<128> loadActionName = "Load: "; @@ -402,7 +413,7 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image .newLayout = vk::ImageLayout::eTransferDstOptimal, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = texture.m_Image, + .image = texture->m_Image, .subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor, @@ -426,7 +437,7 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image .newLayout = vk::ImageLayout::eTransferSrcOptimal, .srcQueueFamilyIndex = m_TransferQueueIndex, .dstQueueFamilyIndex = m_GraphicsQueueIndex, - .image = texture.m_Image, + .image = texture->m_Image, .subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor, @@ -455,11 +466,11 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image .layerCount = 1, }, .imageOffset = {}, - .imageExtent = texture.m_Extent, + .imageExtent = texture->m_Extent, }; vk::CopyBufferToImageInfo2 stagingCopyInfo = { .srcBuffer = stagingBuffer->m_Buffer, - .dstImage = texture.m_Image, + .dstImage = texture->m_Image, .dstImageLayout = vk::ImageLayout::eTransferDstOptimal, .regionCount = 1, .pRegions = &imageCopy, @@ -471,14 +482,14 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image m_CommandBuffer.copyBufferToImage2(&stagingCopyInfo); m_CommandBuffer.pipelineBarrier2(&postStagingDependency); - GenerateMipMaps(m_CommandBuffer, &texture, vk::ImageLayout::eTransferSrcOptimal, + GenerateMipMaps(m_CommandBuffer, texture, vk::ImageLayout::eTransferSrcOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); #if !defined(ASTER_NDEBUG) m_CommandBuffer.endDebugUtilsLabelEXT(); #endif - return m_ResourceManager->CommitTexture(&texture); + return {m_CommitManager->CommitTexture(texture), stagingBuffer}; } Model @@ -488,7 +499,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) tinygltf::Model model; tinygltf::TinyGLTF loader; - const Device *pDevice = m_ResourceManager->m_Device; + const Device *pDevice = m_CommitManager->m_Device; const auto fsPath = fs::absolute(path); const auto ext = fsPath.extension(); @@ -525,30 +536,28 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) m_CommandBuffer.beginDebugUtilsLabelEXT(&debugLabel); #endif - eastl::vector stagingBuffers; + eastl::vector> stagingBuffers; - eastl::hash_map textureHandleMap; + eastl::hash_map> textureHandleMap; eastl::vector materials; - StorageBuffer materialsBuffer; - BufferHandle materialsHandle; + systems::ResId materialsHandle = systems::ResId::Null(); if (!model.materials.empty()) { - auto getTextureHandle = [this, &textureHandleMap, &stagingBuffers, &model](i32 index, - bool isSrgb) -> TextureHandle { + auto getTextureHandle = [this, &textureHandleMap, &stagingBuffers, + &model](i32 index, const bool isSrgb) -> systems::ResId { if (index < 0) { - return {}; + return systems::NullId{}; } - const auto iter = textureHandleMap.find(index); - if (iter != textureHandleMap.end()) + if (const auto iter = textureHandleMap.find(index); iter != textureHandleMap.end()) { return iter->second; } auto *image = &model.images[index]; - TextureHandle handle = LoadImageToGpu(&stagingBuffers.push_back(), image, isSrgb); + auto [handle , staging] = LoadImageToGpu(image, isSrgb); textureHandleMap.emplace(index, handle); return handle; }; @@ -571,15 +580,15 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) } usize materialsByteSize = materials.size() * sizeof materials[0]; - materialsBuffer.Init(pDevice, materialsByteSize, false, name); - materialsHandle = m_ResourceManager->Commit(&materialsBuffer); + auto materialsBuffer = m_ResourceManager->Buffers().CreateStorageBuffer(materialsByteSize, name); + materialsHandle = m_CommitManager->CommitBuffer(materialsBuffer); - StagingBuffer &materialStaging = stagingBuffers.push_back(); - materialStaging.Init(pDevice, materialsByteSize); - materialStaging.Write(pDevice, 0, materialsByteSize, materials.data()); + auto materialStaging = m_ResourceManager->Buffers().CreateStagingBuffer(materialsByteSize); + materialStaging->Write(0, materialsByteSize, materials.data()); + stagingBuffers.emplace_back(std::move(materialStaging)); vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = materialsByteSize}; - m_CommandBuffer.copyBuffer(materialStaging.m_Buffer, materialsBuffer.m_Buffer, 1, &bufferCopy); + m_CommandBuffer.copyBuffer(materialStaging->m_Buffer, materialsBuffer->m_Buffer, 1, &bufferCopy); } // TODO: Mesh reordering based on nodes AND OR meshoptimizer @@ -862,38 +871,39 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) nodes.Update(); - StorageBuffer nodeBuffer; - nodeBuffer.Init(pDevice, nodes.GetGlobalTransformByteSize(), true); - nodeBuffer.Write(pDevice, 0, nodes.GetGlobalTransformByteSize(), nodes.GetGlobalTransformPtr()); - BufferHandle nodeHandle = m_ResourceManager->Commit(&nodeBuffer); + auto nodeBuffer = m_ResourceManager->Buffers().CreateStorageBuffer(nodes.GetGlobalTransformByteSize()); + nodeBuffer->Write(0, nodes.GetGlobalTransformByteSize(), nodes.GetGlobalTransformPtr()); + systems::ResId nodeHandle = m_CommitManager->CommitBuffer(nodeBuffer); #pragma region Staging / Transfer / Uploads - BufferHandle positionBufferHandle; - BufferHandle vertexDataHandle; - IndexBuffer indexBuffer; + systems::ResId positionBufferHandle = systems::ResId::Null(); + systems::ResId vertexDataHandle = systems::ResId::Null(); + Ref indexBuffer; { - auto uploadBufferData = [cmd = this->m_CommandBuffer, &stagingBuffers, pDevice](const Buffer *buffer, - const void *data) { - vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = buffer->GetSize()}; - StagingBuffer &stagingBuffer = stagingBuffers.push_back(); - stagingBuffer.Init(pDevice, bufferCopy.size); - stagingBuffer.Write(pDevice, 0, bufferCopy.size, data); - cmd.copyBuffer(stagingBuffer.m_Buffer, buffer->m_Buffer, 1, &bufferCopy); + auto uploadBufferData = [cmd = this->m_CommandBuffer, &stagingBuffers, resMan = this->m_ResourceManager, + pDevice](const Ref &buffer, const void *data) { + const vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = buffer->m_Size}; + auto stagingBuffer = resMan->Buffers().CreateStagingBuffer(bufferCopy.size); + stagingBuffer->Write(0, bufferCopy.size, data); + cmd.copyBuffer(stagingBuffer->m_Buffer, buffer->m_Buffer, 1, &bufferCopy); + stagingBuffers.emplace_back(std::move(stagingBuffer)); }; - StorageBuffer positionBuffer; - positionBuffer.Init(pDevice, vertexPositions.size() * sizeof vertexPositions[0], false); - positionBufferHandle = m_ResourceManager->Commit(&positionBuffer); - uploadBufferData(&positionBuffer, vertexPositions.data()); + auto positionBuffer = + m_ResourceManager->Buffers().CreateStorageBuffer(vertexPositions.size() * sizeof vertexPositions[0]); + positionBufferHandle = m_CommitManager->CommitBuffer(positionBuffer); + uploadBufferData(positionBuffer, vertexPositions.data()); - StorageBuffer vertexDataBuffer; - vertexDataBuffer.Init(pDevice, vertexData.size() * sizeof vertexData[0], false); - vertexDataHandle = m_ResourceManager->Commit(&vertexDataBuffer); - uploadBufferData(&vertexDataBuffer, vertexData.data()); + auto vertexDataBuffer = + m_ResourceManager->Buffers().CreateStorageBuffer(vertexData.size() * sizeof vertexData[0]); + vertexDataHandle = m_CommitManager->CommitBuffer(vertexDataBuffer); + uploadBufferData(vertexDataBuffer, vertexData.data()); - indexBuffer.Init(pDevice, indices.size() * sizeof indices[0]); - uploadBufferData(&indexBuffer, indices.data()); + // TODO: Index buffer needs to be separated. + indexBuffer = + m_ResourceManager->Buffers().CreateStorageBuffer(indices.size() * sizeof indices[0], "Index Buffer"); + uploadBufferData(indexBuffer, indices.data()); } #pragma endregion @@ -919,11 +929,6 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) AbortIfFailed(pDevice->m_Device.resetCommandPool(m_CommandPool, {})); - for (auto &buffer : stagingBuffers) - { - buffer.Destroy(pDevice); - } - Model::ModelHandles handles = { .m_VertexPositionHandle = positionBufferHandle, .m_VertexDataHandle = vertexDataHandle, @@ -931,7 +936,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) .m_NodeHandle = nodeHandle, }; - eastl::vector textureHandles; + eastl::vector> textureHandles; textureHandles.reserve(textureHandleMap.size()); for (auto &[key, val] : textureHandleMap) @@ -940,44 +945,23 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name) } return Model{ - m_ResourceManager, std::move(textureHandles), std::move(nodes), handles, indexBuffer, meshPrimitives, + m_CommitManager, textureHandles, std::move(nodes), nodeBuffer, handles, indexBuffer, meshPrimitives, }; } -Model::Model(GpuResourceManager *resourceManager, eastl::vector &&textureHandles, Nodes &&nodes, - const ModelHandles &handles, const IndexBuffer &indexBuffer, +Model::Model(systems::CommitManager *resourceManager, eastl::vector> &textureHandles, + Nodes &&nodes, Ref nodeBuffer, ModelHandles &handles, Ref indexBuffer, const eastl::vector &meshPrimitives) : m_ResourceManager(resourceManager) , m_TextureHandles(std::move(textureHandles)) , m_Nodes(std::move(nodes)) - , m_Handles(handles) - , m_IndexBuffer(indexBuffer) + , m_Handles(std::move(handles)) + , m_NodeBuffer(std::move(nodeBuffer)) + , m_IndexBuffer(std::move(indexBuffer)) , m_MeshPrimitives(meshPrimitives) { } -Model::Model(Model &&other) noexcept - : m_ResourceManager(Take(other.m_ResourceManager)) - , m_TextureHandles(std::move(other.m_TextureHandles)) - , m_Handles(other.m_Handles) - , m_IndexBuffer(other.m_IndexBuffer) - , m_MeshPrimitives(std::move(other.m_MeshPrimitives)) -{ -} - -Model & -Model::operator=(Model &&other) noexcept -{ - if (this == &other) - return *this; - m_ResourceManager = Take(other.m_ResourceManager); - m_TextureHandles = std::move(other.m_TextureHandles); - m_Handles = other.m_Handles; - m_IndexBuffer = other.m_IndexBuffer; - m_MeshPrimitives = std::move(other.m_MeshPrimitives); - return *this; -} - const mat4 & Model::GetModelTransform() const { @@ -990,42 +974,24 @@ Model::SetModelTransform(const mat4 &transform) m_Nodes.Set(0, transform); } -Model::~Model() -{ - if (!m_ResourceManager) - return; - - m_IndexBuffer.Destroy(m_ResourceManager->m_Device); - - m_ResourceManager->Release(m_Handles.m_VertexDataHandle); - m_ResourceManager->Release(m_Handles.m_NodeHandle); - m_ResourceManager->Release(m_Handles.m_VertexPositionHandle); - m_ResourceManager->Release(m_Handles.m_MaterialsHandle); - - for (const TextureHandle &handle : m_TextureHandles) - { - m_ResourceManager->Release(handle); - } -} - void Model::Update() { if (m_Nodes.Update()) { - m_ResourceManager->Write(m_Handles.m_NodeHandle, 0, m_Nodes.GetGlobalTransformByteSize(), - m_Nodes.GetGlobalTransformPtr()); + m_NodeBuffer->Write(0, m_Nodes.GetGlobalTransformByteSize(), m_Nodes.GetGlobalTransformPtr()); } } -AssetLoader::AssetLoader(GpuResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex, - u32 graphicsQueueIndex) +AssetLoader::AssetLoader(systems::ResourceManager *resourceManager, systems::CommitManager *commitManager, + vk::Queue transferQueue, u32 transferQueueIndex, u32 graphicsQueueIndex) : m_ResourceManager(resourceManager) + , m_CommitManager(commitManager) , m_TransferQueue(transferQueue) , m_TransferQueueIndex(transferQueueIndex) , m_GraphicsQueueIndex(graphicsQueueIndex) { - const Device *pDevice = resourceManager->m_Device; + const Device *pDevice = commitManager->m_Device; const vk::CommandPoolCreateInfo poolCreateInfo = { .flags = vk::CommandPoolCreateFlagBits::eTransient, .queueFamilyIndex = transferQueueIndex, @@ -1047,15 +1013,16 @@ AssetLoader::AssetLoader(GpuResourceManager *resourceManager, vk::Queue transfer AssetLoader::~AssetLoader() { - if (m_ResourceManager) + if (m_CommitManager && m_CommandPool) { - m_ResourceManager->m_Device->m_Device.destroy(m_CommandPool, nullptr); + m_CommitManager->m_Device->m_Device.destroy(m_CommandPool, nullptr); } } AssetLoader::AssetLoader(AssetLoader &&other) noexcept : m_ResourceManager(Take(other.m_ResourceManager)) - , m_CommandPool(other.m_CommandPool) + , m_CommitManager(Take(other.m_CommitManager)) + , m_CommandPool(Take(other.m_CommandPool)) , m_CommandBuffer(other.m_CommandBuffer) , m_TransferQueue(other.m_TransferQueue) , m_TransferQueueIndex(other.m_TransferQueueIndex) @@ -1069,7 +1036,8 @@ AssetLoader::operator=(AssetLoader &&other) noexcept if (this == &other) return *this; m_ResourceManager = Take(other.m_ResourceManager); - m_CommandPool = other.m_CommandPool; + m_CommitManager = Take(other.m_CommitManager); + m_CommandPool = Take(other.m_CommandPool); m_CommandBuffer = other.m_CommandBuffer; m_TransferQueue = other.m_TransferQueue; m_TransferQueueIndex = other.m_TransferQueueIndex; diff --git a/samples/03_model_render/asset_loader.h b/samples/03_model_render/asset_loader.h index c0d70f5..e3035b6 100644 --- a/samples/03_model_render/asset_loader.h +++ b/samples/03_model_render/asset_loader.h @@ -9,8 +9,19 @@ #include "aster/core/buffer.h" -#include "gpu_resource_manager.h" #include "nodes.h" +#include "tiny_gltf.h" +#include "aster/systems/image_manager.h" +#include "aster/systems/resource.h" + +namespace systems +{ +class ResourceManager; +class SamplerManager; +class BufferManager; +class ImageManager; +class CommitManager; +} namespace tinygltf { @@ -18,7 +29,6 @@ struct Image; } struct Image; -struct TextureHandle; struct Texture; constexpr auto GLTF_ASCII_FILE_EXTENSION = ".gltf"; @@ -39,11 +49,11 @@ struct Material vec3 m_EmissionFactor; // 12 28 f32 m_MetalFactor; // 04 32 f32 m_RoughFactor; // 04 36 - TextureHandle m_AlbedoTex; // 04 40 - TextureHandle m_NormalTex; // 04 44 - TextureHandle m_MetalRoughTex; // 04 48 - TextureHandle m_OcclusionTex; // 04 52 - TextureHandle m_EmissionTex; // 04 56 + systems::ResId m_AlbedoTex; // 04 40 + systems::ResId m_NormalTex; // 04 44 + systems::ResId m_MetalRoughTex; // 04 48 + systems::ResId m_OcclusionTex; // 04 52 + systems::ResId m_EmissionTex; // 04 56 }; struct VertexData @@ -56,33 +66,33 @@ struct VertexData struct Model { - GpuResourceManager *m_ResourceManager; + systems::CommitManager *m_ResourceManager; - eastl::vector m_TextureHandles; + eastl::vector> m_TextureHandles; Nodes m_Nodes; struct ModelHandles { - BufferHandle m_VertexPositionHandle; - BufferHandle m_VertexDataHandle; - BufferHandle m_MaterialsHandle; - BufferHandle m_NodeHandle; + systems::ResId m_VertexPositionHandle; + systems::ResId m_VertexDataHandle; + systems::ResId m_MaterialsHandle; + systems::ResId m_NodeHandle; } m_Handles; - IndexBuffer m_IndexBuffer; + Ref m_NodeBuffer; + Ref m_IndexBuffer; eastl::vector m_MeshPrimitives; [[nodiscard]] const mat4 &GetModelTransform() const; void SetModelTransform(const mat4 &transform); void Update(); - Model(GpuResourceManager *resourceManager, eastl::vector &&textureHandles, Nodes &&nodes, - const ModelHandles &handles, const IndexBuffer &indexBuffer, - const eastl::vector &meshPrimitives); - ~Model(); + Model(systems::CommitManager *resourceManager, eastl::vector> &textureHandles, Nodes &&nodes, Ref nodeBuffer, + ModelHandles &handles, Ref indexBuffer, const eastl::vector &meshPrimitives); + ~Model() = default; - Model(Model &&other) noexcept; - Model &operator=(Model &&other) noexcept; + Model(Model &&other) noexcept = default; + Model &operator=(Model &&other) noexcept = default; Model(const Model &) = delete; const Model &operator=(const Model &) = delete; @@ -90,15 +100,17 @@ struct Model struct AssetLoader { - GpuResourceManager *m_ResourceManager; + systems::ResourceManager *m_ResourceManager; + systems::CommitManager *m_CommitManager; + vk::CommandPool m_CommandPool; vk::CommandBuffer m_CommandBuffer; vk::Queue m_TransferQueue; u32 m_TransferQueueIndex; u32 m_GraphicsQueueIndex; - void LoadHdrImage(Texture *texture, cstr path, cstr name = nullptr) const; - TextureHandle LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image, bool isSrgb) const; + Ref LoadHdrImage(cstr path, cstr name = nullptr) const; + std::tuple, Ref> LoadImageToGpu(tinygltf::Image *image, bool isSrgb) const; Model LoadModelToGpu(cstr path, cstr name = nullptr); constexpr static auto ANormal = "NORMAL"; @@ -110,7 +122,8 @@ struct AssetLoader constexpr static auto AJoints0 = "JOINTS_0"; constexpr static auto AWeights0 = "WEIGHTS_0"; - AssetLoader(GpuResourceManager *resourceManager, vk::Queue transferQueue, u32 transferQueueIndex, + AssetLoader(systems::ResourceManager *resourceManager, systems::CommitManager *commitManager, + vk::Queue transferQueue, u32 transferQueueIndex, u32 graphicsQueueIndex); ~AssetLoader(); @@ -120,7 +133,18 @@ struct AssetLoader DISALLOW_COPY_AND_ASSIGN(AssetLoader); }; -void GenerateMipMaps(vk::CommandBuffer commandBuffer, Texture *texture, vk::ImageLayout initialLayout, +void +GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref &texture, vk::ImageLayout initialLayout, + vk::ImageLayout finalLayout, vk::PipelineStageFlags2 prevStage, vk::PipelineStageFlags2 finalStage); + + +void GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageRef auto& texture, vk::ImageLayout initialLayout, vk::ImageLayout finalLayout, vk::PipelineStageFlags2 prevStage = vk::PipelineStageFlagBits2::eAllCommands, - vk::PipelineStageFlags2 finalStage = vk::PipelineStageFlagBits2::eAllCommands); \ No newline at end of file + vk::PipelineStageFlags2 finalStage = vk::PipelineStageFlagBits2::eAllCommands) +{ + GenerateMipMaps(commandBuffer, systems::CastImage(texture), initialLayout, finalLayout, prevStage, + finalStage); +} + +static_assert(concepts::SampledImageRef>); \ No newline at end of file diff --git a/samples/03_model_render/gpu_resource_manager.cpp b/samples/03_model_render/gpu_resource_manager.cpp deleted file mode 100644 index 3a439d9..0000000 --- a/samples/03_model_render/gpu_resource_manager.cpp +++ /dev/null @@ -1,688 +0,0 @@ -// ============================================= -// Aster: gpu_resource_manager.cpp -// Copyright (c) 2020-2024 Anish Bhobe -// ============================================= - -#include "gpu_resource_manager.h" - -#include "helpers.h" - -#include "aster/core/buffer.h" -#include "aster/core/device.h" -#include "aster/core/image.h" - -#include - -void -TextureManager::Init(const u32 maxCapacity) -{ - m_MaxCapacity = maxCapacity; - m_FreeHead = GpuResourceHandle::INVALID_HANDLE; -} - -TextureHandle -TextureManager::Commit(Texture *texture) -{ - ERROR_IF(!texture || !texture->IsValid(), "Texture must be valid for committal") - THEN_ABORT(-1); - - if (m_FreeHead != GpuResourceHandle::INVALID_HANDLE) - { - const u32 index = m_FreeHead; - - Texture *allocatedTexture = &m_Textures[index]; - - assert(!allocatedTexture->IsValid()); - m_FreeHead = *Recast(allocatedTexture); - - // Ensure it is copyable. - static_assert(std::is_trivially_copyable_v); - *allocatedTexture = *texture; - - // Take ownership of the texture. - texture->m_Flags_ &= ~Texture::OWNED_BIT; - - return {index}; - } - - const u32 index = Cast(m_Textures.size()); - if (index < m_MaxCapacity) - { - Texture *allocatedTexture = &m_Textures.push_back(); - - // Ensure it is copyable. - static_assert(std::is_trivially_copyable_v); - *allocatedTexture = *texture; - - texture->m_Flags_ &= ~Texture::OWNED_BIT; - - return {index}; - } - - ERROR("Out of Buffers") THEN_ABORT(-1); -} - -Texture * -TextureManager::Fetch(const TextureHandle handle) -{ - assert(!handle.IsInvalid()); - - return &m_Textures[handle.m_Index]; -} - -void -TextureManager::Release(const Device *device, const TextureHandle handle) -{ - assert(!handle.IsInvalid()); - - Texture *allocatedTexture = &m_Textures[handle.m_Index]; - allocatedTexture->Destroy(device); - - assert(!allocatedTexture->IsValid()); - *Recast(allocatedTexture) = m_FreeHead; - - m_FreeHead = handle.m_Index; -} - -void -TextureManager::Destroy(const Device *device) -{ - for (auto &texture : m_Textures) - { - texture.Destroy(device); - } -} - -void -BufferManager::Init(const u32 maxCapacity) -{ - m_MaxCapacity = maxCapacity; - m_FreeHead = GpuResourceHandle::INVALID_HANDLE; -} - -BufferHandle -BufferManager::Commit(StorageBuffer *buffer) -{ - ERROR_IF(!buffer || !buffer->IsValid() || !buffer->IsOwned(), "Buffer must be valid and owned for commital") - THEN_ABORT(-1); - - if (m_FreeHead != GpuResourceHandle::INVALID_HANDLE) - { - const u32 index = m_FreeHead; - - StorageBuffer *allocatedBuffer = &m_Buffers[index]; - - assert(!allocatedBuffer->IsValid()); - m_FreeHead = *Recast(allocatedBuffer); - - // Ensure it is copyable. - static_assert(std::is_trivially_copyable_v); - *allocatedBuffer = *buffer; - - // Take ownership of the buffer. - buffer->m_Size_ &= ~StorageBuffer::OWNED_BIT; - - return {index}; - } - - const u32 index = Cast(m_Buffers.size()); - if (index < m_MaxCapacity) - { - StorageBuffer *allocatedBuffer = &m_Buffers.push_back(); - - // Ensure it is copyable. - static_assert(std::is_trivially_copyable_v); - *allocatedBuffer = *buffer; - - buffer->m_Size_ &= ~StorageBuffer::OWNED_BIT; - - return {index}; - } - - ERROR("Out of Buffers") THEN_ABORT(-1); -} - -StorageBuffer * -BufferManager::Fetch(const BufferHandle handle) -{ - assert(!handle.IsInvalid()); - - return &m_Buffers[handle.m_Index]; -} - -void -BufferManager::Release(const Device *device, const BufferHandle handle) -{ - assert(!handle.IsInvalid()); - - StorageBuffer *allocatedBuffer = &m_Buffers[handle.m_Index]; - allocatedBuffer->Destroy(device); - - assert(!allocatedBuffer->IsValid()); - *Recast(allocatedBuffer) = m_FreeHead; - - m_FreeHead = handle.m_Index; -} - -void -BufferManager::Destroy(const Device *device) -{ - for (auto &buffer : m_Buffers) - { - buffer.Destroy(device); - } -} - -StorageTextureHandle -StorageTextureManager::Commit(StorageTexture *texture) -{ - const TextureHandle tx = TextureManager::Commit(texture); - return {tx.m_Index}; -} - -StorageTexture * -StorageTextureManager::Fetch(const StorageTextureHandle handle) -{ - assert(!handle.IsInvalid()); - - return Recast(&m_Textures[handle.m_Index]); -} - -void -StorageTextureManager::Release(const Device *device, const StorageTextureHandle handle) -{ - TextureManager::Release(device, {handle.m_Index}); -} - -usize -HashSamplerCreateInfo(const vk::SamplerCreateInfo *createInfo) -{ - usize hash = HashAny(createInfo->flags); - hash = HashCombine(hash, HashAny(createInfo->magFilter)); - hash = HashCombine(hash, HashAny(createInfo->minFilter)); - hash = HashCombine(hash, HashAny(createInfo->mipmapMode)); - hash = HashCombine(hash, HashAny(createInfo->addressModeU)); - hash = HashCombine(hash, HashAny(createInfo->addressModeV)); - hash = HashCombine(hash, HashAny(createInfo->addressModeW)); - hash = HashCombine(hash, HashAny(Cast(createInfo->mipLodBias * 1000))); // Resolution of 10^-3 - hash = HashCombine(hash, HashAny(createInfo->anisotropyEnable)); - hash = HashCombine(hash, - HashAny(Cast(createInfo->maxAnisotropy * 0x10))); // 16:1 Anisotropy is enough resolution - hash = HashCombine(hash, HashAny(createInfo->compareEnable)); - hash = HashCombine(hash, HashAny(createInfo->compareOp)); - hash = HashCombine(hash, HashAny(Cast(createInfo->minLod * 1000))); // 0.001 resolution is enough. - hash = HashCombine(hash, - HashAny(Cast(createInfo->maxLod * 1000))); // 0.001 resolution is enough. (1 == NO Clamp) - hash = HashCombine(hash, HashAny(createInfo->borderColor)); - hash = HashCombine(hash, HashAny(createInfo->unnormalizedCoordinates)); - - return hash; -} - -void -SamplerManager::Init(usize size) -{ - m_Samplers.reserve(size); - m_SamplerHashes.reserve(size); -} - -SamplerHandle -SamplerManager::Create(const Device *device, const vk::SamplerCreateInfo *createInfo) -{ - const usize hash = HashSamplerCreateInfo(createInfo); - - for (u32 index = 0; usize samplerHash : m_SamplerHashes) - { - if (samplerHash == hash) - { - return {index}; - } - ++index; - } - - vk::Sampler sampler; - AbortIfFailed(device->m_Device.createSampler(createInfo, nullptr, &sampler)); - const u32 index = Cast(m_SamplerHashes.size()); - m_SamplerHashes.push_back(hash); - m_Samplers.push_back(sampler); - return {index}; -} - -vk::Sampler -SamplerManager::Fetch(const SamplerHandle handle) -{ - assert(!handle.IsInvalid()); - - return m_Samplers[handle.m_Index]; -} - -void -SamplerManager::Destroy(const Device *device) -{ - for (const auto &sampler : m_Samplers) - { - device->m_Device.destroy(sampler, nullptr); - } - m_Samplers.clear(); - m_SamplerHashes.clear(); -} - -GpuResourceManager::WriteInfo::WriteInfo(vk::DescriptorBufferInfo info) - : uBufferInfo(info) -{ -} - -GpuResourceManager::WriteInfo::WriteInfo(vk::DescriptorImageInfo info) - : uImageInfo(info) -{ -} - -GpuResourceManager::WriteInfo::WriteInfo(vk::BufferView info) - : uBufferView(info) -{ -} - -BufferHandle -GpuResourceManager::Commit(StorageBuffer *storageBuffer) -{ - const BufferHandle handle = m_BufferManager.Commit(storageBuffer); - - m_WriteInfos.emplace_back(vk::DescriptorBufferInfo{ - .buffer = storageBuffer->m_Buffer, - .offset = 0, - .range = storageBuffer->GetSize(), - }); - - m_Writes.push_back({ - .dstSet = m_DescriptorSet, - .dstBinding = BUFFER_BINDING_INDEX, - .dstArrayElement = handle.m_Index, - .descriptorCount = 1, - .descriptorType = vk::DescriptorType::eStorageBuffer, - .pBufferInfo = &m_WriteInfos.back().uBufferInfo, - }); - - m_WriteOwner.emplace_back(HandleType::eBuffer, handle.m_Index); - -#if !defined(ASTER_NDEBUG) - ++m_CommitedBufferCount; -#endif - - return handle; -} - -void -GpuResourceManager::Write(const BufferHandle handle, const usize offset, const usize size, const void *data) -{ - m_BufferManager.Fetch(handle)->Write(m_Device, offset, size, data); -} - -void -GpuResourceManager::EraseWrites(u32 handleIndex, HandleType handleType) -{ - auto writeIter = m_Writes.begin(); - auto ownerIter = m_WriteOwner.begin(); - const auto ownerEnd = m_WriteOwner.end(); - - while (ownerIter != ownerEnd) - { - if (ownerIter->first == handleType && ownerIter->second == handleIndex) - { - *writeIter = m_Writes.back(); - *ownerIter = m_WriteOwner.back(); - m_Writes.pop_back(); - m_WriteOwner.pop_back(); - return; - } - - ++ownerIter; - ++writeIter; - } -} - -void -GpuResourceManager::Release(BufferHandle handle) -{ - if (handle.IsInvalid()) - return; - - EraseWrites(handle.m_Index, HandleType::eBuffer); - - m_BufferManager.Release(m_Device, handle); - -#if !defined(ASTER_NDEBUG) - --m_CommitedBufferCount; -#endif -} - -void -GpuResourceManager::Release(StorageBuffer *storageBuffer, const BufferHandle handle) -{ - assert(storageBuffer); - assert(!storageBuffer->IsValid()); - - StorageBuffer *internal = m_BufferManager.Fetch(handle); - *storageBuffer = *internal; - internal->m_Size_ &= ~StorageBuffer::OWNED_BIT; - - Release(handle); -} - -void -GpuResourceManager::Release(TextureHandle handle) -{ - if (handle.IsInvalid()) - return; - - EraseWrites(handle.m_Index, HandleType::eTexture); - - m_TextureManager.Release(m_Device, handle); - -#if !defined(ASTER_NDEBUG) - --m_CommitedTextureCount; -#endif -} - -void -GpuResourceManager::Release(Texture *texture, TextureHandle handle) -{ - assert(texture); - assert(!texture->IsValid()); - - Texture *internal = m_TextureManager.Fetch(handle); - *texture = *internal; - internal->m_Flags_ &= ~Texture::OWNED_BIT; - - Release(handle); -} - -TextureHandle -GpuResourceManager::CommitTexture(Texture *texture, const SamplerHandle sampler) -{ - TextureHandle handle = m_TextureManager.Commit(texture); - - const vk::Sampler samplerImpl = sampler.IsInvalid() ? m_DefaultSampler : m_SamplerManager.Fetch(sampler); - - m_WriteInfos.emplace_back(vk::DescriptorImageInfo{ - .sampler = samplerImpl, - .imageView = texture->m_View, - .imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal, - }); - - m_Writes.push_back({ - .dstSet = m_DescriptorSet, - .dstBinding = TEXTURE_BINDING_INDEX, - .dstArrayElement = handle.m_Index, - .descriptorCount = 1, - .descriptorType = vk::DescriptorType::eCombinedImageSampler, - .pImageInfo = &m_WriteInfos.back().uImageInfo, - }); - - m_WriteOwner.emplace_back(HandleType::eTexture, handle.m_Index); - -#if !defined(ASTER_NDEBUG) - ++m_CommitedTextureCount; -#endif - - return {handle}; -} - -StorageTextureHandle -GpuResourceManager::CommitStorageTexture(StorageTexture *storageTexture, SamplerHandle sampler) -{ - StorageTextureHandle handle = m_StorageTextureManager.Commit(storageTexture); - - vk::Sampler samplerImpl = sampler.IsInvalid() ? m_DefaultSampler : m_SamplerManager.Fetch(sampler); - - m_WriteInfos.emplace_back(vk::DescriptorImageInfo{ - .sampler = samplerImpl, - .imageView = storageTexture->m_View, - .imageLayout = vk::ImageLayout::eGeneral, - }); - - m_Writes.push_back({ - .dstSet = m_DescriptorSet, - .dstBinding = STORAGE_TEXTURE_BINDING_INDEX, - .dstArrayElement = handle.m_Index, - .descriptorCount = 1, - .descriptorType = vk::DescriptorType::eStorageImage, - .pImageInfo = &m_WriteInfos.back().uImageInfo, - }); - - m_WriteOwner.emplace_back(HandleType::eStorageTexture, handle.m_Index); - -#if !defined(ASTER_NDEBUG) - ++m_CommitedStorageTextureCount; -#endif - - return {handle}; -} - -void -GpuResourceManager::Release(StorageTextureHandle handle) -{ - if (handle.IsInvalid()) - return; - - EraseWrites(handle.m_Index, HandleType::eTexture); - - m_StorageTextureManager.Release(m_Device, handle); - -#if !defined(ASTER_NDEBUG) - --m_CommitedStorageTextureCount; -#endif -} - -void -GpuResourceManager::Release(StorageTexture *texture, const StorageTextureHandle handle) -{ - assert(texture); - assert(!texture->IsValid()); - - StorageTexture *internal = m_StorageTextureManager.Fetch(handle); - *texture = *internal; - internal->m_Flags_ &= ~StorageTexture::OWNED_BIT; - - Release(handle); -} - -void -GpuResourceManager::Update() -{ - if (m_Writes.empty() || m_WriteInfos.empty()) - return; - - m_Device->m_Device.updateDescriptorSets(Cast(m_Writes.size()), m_Writes.data(), 0, nullptr); - - m_Writes.clear(); - m_WriteInfos.clear(); - m_WriteOwner.clear(); -} - -GpuResourceManager::GpuResourceManager(Device *device, u16 maxSize) - : m_Device(device) -{ - vk::PhysicalDeviceProperties properties; - m_Device->m_PhysicalDevice.getProperties(&properties); - - u32 buffersCount = eastl::min(properties.limits.maxPerStageDescriptorStorageBuffers - 1024, Cast(maxSize)); - u32 texturesCount = eastl::min(properties.limits.maxPerStageDescriptorSampledImages - 1024, Cast(maxSize)); - u32 storageTexturesCount = - eastl::min(properties.limits.maxPerStageDescriptorStorageImages - 1024, Cast(maxSize)); - - INFO("Max Buffer Count: {}", buffersCount); - INFO("Max Texture Count: {}", texturesCount); - INFO("Max Storage Texture Count: {}", storageTexturesCount); - - m_BufferManager.Init(buffersCount); - m_TextureManager.Init(texturesCount); - m_StorageTextureManager.Init(storageTexturesCount); - m_SamplerManager.Init(storageTexturesCount); - - m_DefaultSamplerCreateInfo = { - .magFilter = vk::Filter::eLinear, - .minFilter = vk::Filter::eLinear, - .mipmapMode = vk::SamplerMipmapMode::eLinear, - .addressModeU = vk::SamplerAddressMode::eRepeat, - .addressModeV = vk::SamplerAddressMode::eRepeat, - .addressModeW = vk::SamplerAddressMode::eRepeat, - .mipLodBias = 0.0f, - .anisotropyEnable = true, - .maxAnisotropy = properties.limits.maxSamplerAnisotropy, - .compareEnable = false, - .minLod = 0, - .maxLod = VK_LOD_CLAMP_NONE, - .borderColor = vk::BorderColor::eFloatOpaqueBlack, - .unnormalizedCoordinates = false, - }; - - m_DefaultSampler = m_SamplerManager.Fetch(m_SamplerManager.Create(device, &m_DefaultSamplerCreateInfo)); - - eastl::array poolSizes = { - vk::DescriptorPoolSize{ - .type = vk::DescriptorType::eStorageBuffer, - .descriptorCount = buffersCount, - }, - vk::DescriptorPoolSize{ - .type = vk::DescriptorType::eCombinedImageSampler, - .descriptorCount = texturesCount, - }, - vk::DescriptorPoolSize{ - .type = vk::DescriptorType::eStorageImage, - .descriptorCount = storageTexturesCount, - }, - }; - - const vk::DescriptorPoolCreateInfo poolCreateInfo = { - .flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind, - .maxSets = 1, - .poolSizeCount = Cast(poolSizes.size()), - .pPoolSizes = poolSizes.data(), - }; - AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool)); - - vk::DescriptorBindingFlags bindingFlags = - vk::DescriptorBindingFlagBits::ePartiallyBound | vk::DescriptorBindingFlagBits::eUpdateAfterBind; - eastl::array layoutBindingFlags = { - bindingFlags, - bindingFlags, - bindingFlags, - }; - - vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo = { - .bindingCount = Cast(layoutBindingFlags.size()), - .pBindingFlags = layoutBindingFlags.data(), - }; - - eastl::array descriptorLayoutBindings = { - vk::DescriptorSetLayoutBinding{ - .binding = BUFFER_BINDING_INDEX, - .descriptorType = vk::DescriptorType::eStorageBuffer, - .descriptorCount = Cast(buffersCount), - .stageFlags = vk::ShaderStageFlagBits::eAll, - }, - vk::DescriptorSetLayoutBinding{ - .binding = TEXTURE_BINDING_INDEX, - .descriptorType = vk::DescriptorType::eCombinedImageSampler, - .descriptorCount = Cast(texturesCount), - .stageFlags = vk::ShaderStageFlagBits::eAll, - }, - vk::DescriptorSetLayoutBinding{ - .binding = STORAGE_TEXTURE_BINDING_INDEX, - .descriptorType = vk::DescriptorType::eStorageImage, - .descriptorCount = Cast(storageTexturesCount), - .stageFlags = vk::ShaderStageFlagBits::eAll, - }, - }; - static_assert(layoutBindingFlags.size() == descriptorLayoutBindings.size()); - const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = { - .pNext = &bindingFlagsCreateInfo, - .flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool, - .bindingCount = Cast(descriptorLayoutBindings.size()), - .pBindings = descriptorLayoutBindings.data(), - }; - AbortIfFailed(device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &m_SetLayout)); - - // One descriptor is enough. Updating it at any time is safe. (Update until submit, data held when pending) - // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_descriptor_indexing.html - // https://github.com/KhronosGroup/Vulkan-Guide/blob/main/chapters/extensions/VK_EXT_descriptor_indexing.adoc - const vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = { - .descriptorPool = m_DescriptorPool, - .descriptorSetCount = 1, - .pSetLayouts = &m_SetLayout, - }; - AbortIfFailed(device->m_Device.allocateDescriptorSets(&descriptorSetAllocateInfo, &m_DescriptorSet)); - - m_Device->SetName(m_SetLayout, "Bindless Layout"); - m_Device->SetName(m_DescriptorPool, "Bindless Pool"); - m_Device->SetName(m_DescriptorSet, "Bindless Set"); -} - -GpuResourceManager::~GpuResourceManager() -{ -#if !defined(ASTER_NDEBUG) - WARN_IF(m_CommitedBufferCount > 0 || m_CommitedTextureCount > 0 || m_CommitedStorageTextureCount > 0, - "Resources alive: SSBO = {}, Textures = {}, RWTexture = {}", m_CommitedBufferCount, m_CommitedTextureCount, - m_CommitedStorageTextureCount); -#endif - - m_BufferManager.Destroy(m_Device); - m_TextureManager.Destroy(m_Device); - m_StorageTextureManager.Destroy(m_Device); - m_SamplerManager.Destroy(m_Device); - m_Device->m_Device.destroy(m_DescriptorPool, nullptr); - m_Device->m_Device.destroy(m_SetLayout, nullptr); -} - -GpuResourceManager::GpuResourceManager(GpuResourceManager &&other) noexcept - : m_WriteInfos(std::move(other.m_WriteInfos)) - , m_Writes(std::move(other.m_Writes)) - , m_WriteOwner(std::move(other.m_WriteOwner)) - , m_BufferManager(std::move(other.m_BufferManager)) - , m_TextureManager(std::move(other.m_TextureManager)) - , m_StorageTextureManager(std::move(other.m_StorageTextureManager)) - , m_SamplerManager(std::move(other.m_SamplerManager)) - , m_Device(Take(other.m_Device)) - , m_DescriptorPool(other.m_DescriptorPool) - , m_SetLayout(other.m_SetLayout) - , m_DescriptorSet(other.m_DescriptorSet) -#if !defined(ASTER_NDEBUG) - , m_CommitedBufferCount(other.m_CommitedBufferCount) - , m_CommitedTextureCount(other.m_CommitedTextureCount) - , m_CommitedStorageTextureCount(other.m_CommitedStorageTextureCount) -#endif -{ - assert(!other.m_Device); -} - -GpuResourceManager & -GpuResourceManager::operator=(GpuResourceManager &&other) noexcept -{ - if (this == &other) - return *this; - m_WriteInfos = std::move(other.m_WriteInfos); - m_Writes = std::move(other.m_Writes); - m_WriteOwner = std::move(other.m_WriteOwner); - m_BufferManager = std::move(other.m_BufferManager); - m_TextureManager = std::move(other.m_TextureManager); - m_StorageTextureManager = std::move(other.m_StorageTextureManager); - m_SamplerManager = std::move(other.m_SamplerManager); - m_Device = Take(other.m_Device); // Ensure taken. - m_DescriptorPool = other.m_DescriptorPool; - m_SetLayout = other.m_SetLayout; - m_DescriptorSet = other.m_DescriptorSet; -#if !defined(ASTER_NDEBUG) - m_CommitedBufferCount = other.m_CommitedBufferCount; - m_CommitedTextureCount = other.m_CommitedTextureCount; - m_CommitedStorageTextureCount = other.m_CommitedStorageTextureCount; -#endif - - assert(!other.m_Device); - return *this; -} - -SamplerHandle -GpuResourceManager::CreateSampler(const vk::SamplerCreateInfo *samplerCreateInfo) -{ - return m_SamplerManager.Create(m_Device, samplerCreateInfo); -} \ No newline at end of file diff --git a/samples/03_model_render/gpu_resource_manager.h b/samples/03_model_render/gpu_resource_manager.h deleted file mode 100644 index 6e2e3cf..0000000 --- a/samples/03_model_render/gpu_resource_manager.h +++ /dev/null @@ -1,175 +0,0 @@ -// ============================================= -// Aster: gpu_resource_manager.h -// Copyright (c) 2020-2024 Anish Bhobe -// ============================================= - -#pragma once - -#include "aster/aster.h" - -#include -#include - -struct Device; -struct Texture; -struct StorageTexture; -struct StorageBuffer; - -struct GpuResourceHandle -{ - constexpr static u32 INVALID_HANDLE = MaxValue; - u32 m_Index = INVALID_HANDLE; // Default = invalid - - [[nodiscard]] bool - IsInvalid() const - { - return m_Index == INVALID_HANDLE; - } -}; - -struct BufferHandle : GpuResourceHandle -{ -}; - -struct TextureHandle : GpuResourceHandle -{ -}; - -struct StorageTextureHandle : GpuResourceHandle -{ -}; - -struct SamplerHandle : GpuResourceHandle -{ -}; - -struct TextureManager -{ - eastl::vector m_Textures; - u32 m_MaxCapacity; - u32 m_FreeHead; - - void Init(u32 maxCapacity); - TextureHandle Commit(Texture *texture); - Texture *Fetch(TextureHandle handle); - void Release(const Device *device, TextureHandle handle); - void Destroy(const Device *device); -}; - -struct BufferManager -{ - eastl::vector m_Buffers; - u32 m_MaxCapacity; - u32 m_FreeHead; - - void Init(u32 maxCapacity); - BufferHandle Commit(StorageBuffer *buffer); - StorageBuffer *Fetch(BufferHandle handle); - void Release(const Device *device, BufferHandle handle); - void Destroy(const Device *device); -}; - -struct StorageTextureManager : TextureManager -{ - StorageTextureHandle Commit(StorageTexture *texture); - StorageTexture *Fetch(StorageTextureHandle handle); - void Release(const Device *device, StorageTextureHandle handle); -}; - -struct SamplerManager -{ - // There can only be so many samplers. - eastl::vector m_Samplers; - eastl::vector m_SamplerHashes; - - void Init(usize size); - SamplerHandle Create(const Device *device, const vk::SamplerCreateInfo *createInfo); - vk::Sampler Fetch(SamplerHandle handle); - void Destroy(const Device *device); -}; - -struct GpuResourceManager -{ - private: - union WriteInfo { - vk::DescriptorBufferInfo uBufferInfo; - vk::DescriptorImageInfo uImageInfo; - vk::BufferView uBufferView; - - WriteInfo() - { - } - - explicit WriteInfo(vk::DescriptorBufferInfo info); - explicit WriteInfo(vk::DescriptorImageInfo info); - explicit WriteInfo(vk::BufferView info); - }; - - enum class HandleType - { - eBuffer, - eTexture, - eStorageTexture, - }; - - using WriteOwner = eastl::pair; - - eastl::deque m_WriteInfos; - eastl::vector m_Writes; - eastl::vector m_WriteOwner; - - vk::Sampler m_DefaultSampler; - - BufferManager m_BufferManager; - TextureManager m_TextureManager; - StorageTextureManager m_StorageTextureManager; - SamplerManager m_SamplerManager; - - void EraseWrites(u32 handleIndex, HandleType handleType); - - public: - Device *m_Device; - - constexpr static u32 BUFFER_BINDING_INDEX = 0; - constexpr static u32 TEXTURE_BINDING_INDEX = 1; - constexpr static u32 STORAGE_TEXTURE_BINDING_INDEX = 2; - - vk::SamplerCreateInfo m_DefaultSamplerCreateInfo; - - vk::DescriptorPool m_DescriptorPool; - vk::DescriptorSetLayout m_SetLayout; - vk::DescriptorSet m_DescriptorSet; - - BufferHandle Commit(StorageBuffer *storageBuffer); // Commit to GPU and take Ownership - void Write(BufferHandle handle, usize offset, usize size, const void *data); // Write to buffer - void Release(BufferHandle handle); // Release and Destroy - void Release(StorageBuffer *storageBuffer, BufferHandle handle); // Release and Return - - TextureHandle CommitTexture(Texture *texture, SamplerHandle sampler = {}); // Commit to GPU and take Ownership - void Release(TextureHandle handle); // Release and Destroy - void Release(Texture *texture, TextureHandle handle); // Release and Return - - StorageTextureHandle - CommitStorageTexture(StorageTexture *storageTexture, SamplerHandle sampler = {}); // Commit to GPU and take Ownership - void Release(StorageTextureHandle handle); // Release and Destroy - void Release(StorageTexture *texture, StorageTextureHandle handle); // Release and Return - - SamplerHandle CreateSampler(const vk::SamplerCreateInfo *samplerCreateInfo); - - void Update(); // Update all the descriptors required. - - // Ctor/Dtor - GpuResourceManager(Device *device, u16 maxSize); - ~GpuResourceManager(); - - GpuResourceManager(GpuResourceManager &&other) noexcept; - GpuResourceManager &operator=(GpuResourceManager &&other) noexcept; - -#if !defined(ASTER_NDEBUG) - usize m_CommitedBufferCount = 0; - usize m_CommitedTextureCount = 0; - usize m_CommitedStorageTextureCount = 0; -#endif - - DISALLOW_COPY_AND_ASSIGN(GpuResourceManager); -}; \ No newline at end of file diff --git a/samples/03_model_render/ibl_helpers.cpp b/samples/03_model_render/ibl_helpers.cpp index f726302..816c8bb 100644 --- a/samples/03_model_render/ibl_helpers.cpp +++ b/samples/03_model_render/ibl_helpers.cpp @@ -9,10 +9,12 @@ #include "aster/core/image.h" #include "asset_loader.h" -#include "gpu_resource_manager.h" #include "helpers.h" #include "pipeline_utils.h" +#include "aster/systems/commit_manager.h" +#include "aster/systems/resource_manager.h" + #include #include @@ -21,70 +23,86 @@ constexpr cstr DIFFUSE_IRRADIANCE_SHADER_FILE = "shader/diffuse_irradiance.cs.hl constexpr cstr PREFILTER_SHADER_FILE = "shader/prefilter.cs.hlsl.spv"; constexpr cstr BRDF_LUT_SHADER_FILE = "shader/brdf_lut.cs.hlsl.spv"; -void -Environment::Destroy(GpuResourceManager *resourceManager) -{ - resourceManager->Release(Take(m_Skybox)); - resourceManager->Release(Take(m_Diffuse)); - resourceManager->Release(Take(m_Prefilter)); - resourceManager->Release(Take(m_BrdfLut)); -} - Environment -CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cubeSide, TextureHandle hdrEnv, - const cstr name) +CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cubeSide, + systems::ResId hdrEnv, const cstr name) { - GpuResourceManager *resMan = assetLoader->m_ResourceManager; - const Device *pDevice = resMan->m_Device; + systems::ResourceManager *resourceManager = assetLoader->m_ResourceManager; + systems::CommitManager *commitManager = assetLoader->m_CommitManager; + const Device *pDevice = commitManager->m_Device; - vk::SamplerCreateInfo brdfLutSamplerCreateInfo = resMan->m_DefaultSamplerCreateInfo; - brdfLutSamplerCreateInfo.addressModeU = vk::SamplerAddressMode::eClampToEdge; - brdfLutSamplerCreateInfo.addressModeV = vk::SamplerAddressMode::eClampToEdge; - brdfLutSamplerCreateInfo.addressModeW = vk::SamplerAddressMode::eClampToEdge; + auto skybox = resourceManager->Images().CreateTextureCube({ + .m_Format = vk::Format::eR16G16B16A16Sfloat, + .m_Side = cubeSide, + .m_Name = "Skybox", + .m_IsSampled = true, + .m_IsMipMapped = true, + .m_IsStorage = true, + }); - StorageTextureCube skybox; - StorageTextureCube diffuseIrradiance; - StorageTextureCube prefilterCube; - StorageTexture brdfLut; - SamplerHandle brdfLutSampler; + auto skyboxHandle = commitManager->CommitTexture(skybox); + auto skyboxStorageHandle = commitManager->CommitStorageImage(skybox); - skybox.Init(pDevice, cubeSide, vk::Format::eR16G16B16A16Sfloat, true, true, "Skybox"); - TextureHandle skyboxHandle = resMan->CommitTexture(&skybox); - StorageTextureHandle skyboxStorageHandle = resMan->CommitStorageTexture(&skybox); + auto diffuseIrradiance = resourceManager->Images().CreateTextureCube({ + .m_Format = vk::Format::eR16G16B16A16Sfloat, + .m_Side = 64, + .m_Name = "Diffuse Irradiance", + .m_IsSampled = true, + .m_IsMipMapped = false, + .m_IsStorage = true, + }); + auto diffuseIrradianceHandle = commitManager->CommitTexture(diffuseIrradiance); + auto diffuseIrradianceStorageHandle = commitManager->CommitStorageImage(diffuseIrradiance); - diffuseIrradiance.Init(pDevice, 64, vk::Format::eR16G16B16A16Sfloat, true, false, "Diffuse Irradiance"); - TextureHandle diffuseIrradianceHandle = resMan->CommitTexture(&diffuseIrradiance); - StorageTextureHandle diffuseIrradianceStorageHandle = resMan->CommitStorageTexture(&diffuseIrradiance); - - prefilterCube.Init(pDevice, cubeSide, vk::Format::eR16G16B16A16Sfloat, true, true, "Prefilter"); - TextureHandle prefilterHandle = resMan->CommitTexture(&prefilterCube); // This stores the original view for us. + auto prefilterCube = resourceManager->Images().CreateTextureCube({ + .m_Format = vk::Format::eR16G16B16A16Sfloat, + .m_Side = cubeSide, + .m_Name = "Prefilter", + .m_IsSampled = true, + .m_IsMipMapped = true, + .m_IsStorage = true, + }); + auto prefilterHandle = commitManager->CommitTexture(prefilterCube); // This stores the original view for us. constexpr u32 prefilterMipCountMax = 6; - eastl::array prefilterStorageHandles; + eastl::fixed_vector, prefilterMipCountMax> prefilterStorageHandles; // All non-owning copies. - for (u32 mipLevel = 0; auto &tex : prefilterStorageHandles) + for (u32 mipLevel = 0; mipLevel < prefilterMipCountMax; ++mipLevel) { vk::ImageViewCreateInfo imageViewCreateInfo = { - .image = prefilterCube.m_Image, + .image = prefilterCube->m_Image, .viewType = vk::ImageViewType::eCube, .format = vk::Format::eR16G16B16A16Sfloat, .components = vk::ComponentMapping{}, .subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = mipLevel++, + .baseMipLevel = mipLevel, .levelCount = 1, .baseArrayLayer = 0, .layerCount = 6, }, }; - AbortIfFailed(pDevice->m_Device.createImageView(&imageViewCreateInfo, nullptr, &prefilterCube.m_View)); - tex = resMan->CommitStorageTexture(&prefilterCube); + AbortIfFailed(pDevice->m_Device.createImageView(&imageViewCreateInfo, nullptr, &prefilterCube->m_View)); + // TODO: FIXME: This is an issue. This needs copying but we don't do that anymore. + // The views need to be separated from the images. + TODO("This is bad"); + prefilterStorageHandles.push_back(commitManager->CommitStorageImage(prefilterCube)); } - brdfLut.Init(pDevice, {512, 512}, vk::Format::eR16G16Sfloat, true, "BRDF LUT"); - brdfLutSampler = resMan->CreateSampler(&brdfLutSamplerCreateInfo); - TextureHandle brdfLutHandle = resMan->CommitTexture(&brdfLut, brdfLutSampler); - StorageTextureHandle brdfLutStorageHandle = resMan->CommitStorageTexture(&brdfLut); + auto brdfLut = resourceManager->Images().CreateTexture2D({.m_Format = vk::Format::eR16G16Sfloat, + .m_Extent = {512, 512}, + .m_Name = "BRDF LUT", + .m_IsSampled = true, + .m_IsMipMapped = true, + .m_IsStorage = true}); + + auto brdfLutSampler = resourceManager->Samplers().CreateSampler({ + .m_AddressModeU = vk::SamplerAddressMode::eClampToEdge, + .m_AddressModeV = vk::SamplerAddressMode::eClampToEdge, + .m_AddressModeW = vk::SamplerAddressMode::eClampToEdge, + }); + auto brdfLutHandle = commitManager->CommitTexture(brdfLut, brdfLutSampler); + auto brdfLutStorageHandle = commitManager->CommitStorageImage(brdfLut); #pragma region Dependencies and Copies vk::ImageSubresourceRange cubeSubresRange = { @@ -114,10 +132,10 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 .subresourceRange = cubeSubresRange, }; eastl::fixed_vector readyToWriteBarriers(4, readyToWriteBarrierTemplate); - readyToWriteBarriers[0].image = skybox.m_Image; - readyToWriteBarriers[1].image = diffuseIrradiance.m_Image; - readyToWriteBarriers[2].image = prefilterCube.m_Image; - readyToWriteBarriers[3].image = brdfLut.m_Image; + readyToWriteBarriers[0].image = skybox->m_Image; + readyToWriteBarriers[1].image = diffuseIrradiance->m_Image; + readyToWriteBarriers[2].image = prefilterCube->m_Image; + readyToWriteBarriers[3].image = brdfLut->m_Image; readyToWriteBarriers[3].subresourceRange = lutSubresRange; vk::DependencyInfo readyToWriteDependency = { @@ -136,16 +154,16 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 .subresourceRange = cubeSubresRange, }; auto skyboxToSampleBarrier = readyToSampleBarrierTemplate; - skyboxToSampleBarrier.image = skybox.m_Image; + skyboxToSampleBarrier.image = skybox->m_Image; auto diffIrrToSampleBarrier = readyToSampleBarrierTemplate; - diffIrrToSampleBarrier.image = diffuseIrradiance.m_Image; + diffIrrToSampleBarrier.image = diffuseIrradiance->m_Image; auto prefilterToSampleBarrier = readyToSampleBarrierTemplate; - prefilterToSampleBarrier.image = prefilterCube.m_Image; + prefilterToSampleBarrier.image = prefilterCube->m_Image; auto brdfToSampleBarrier = readyToSampleBarrierTemplate; - prefilterToSampleBarrier.image = brdfLut.m_Image; + prefilterToSampleBarrier.image = brdfLut->m_Image; prefilterToSampleBarrier.subresourceRange = lutSubresRange; vk::DependencyInfo skyboxToSampleDependency = { @@ -169,27 +187,27 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 struct SkyboxPushConstants { - TextureHandle m_HdrEnvHandle; - StorageTextureHandle m_OutputTexture; + systems::ResId m_HdrEnvHandle; + systems::ResId m_OutputTexture; u32 m_CubeSide; }; struct DiffuseIrradiancePushConstants { - TextureHandle m_SkyboxHandle; - StorageTextureHandle m_OutputTexture; + systems::ResId m_SkyboxHandle; + systems::ResId m_OutputTexture; u32 m_CubeSide; }; struct PrefilterPushConstants { - TextureHandle m_SkyboxHandle; - StorageTextureHandle m_OutputTexture; + systems::ResId m_SkyboxHandle; + systems::ResId m_OutputTexture; u32 m_CubeSide; f32 m_Roughness; u32 m_EnvSide; }; struct BrdfLutPushConstants { - StorageTextureHandle m_OutputTexture; + systems::ResId m_OutputTexture; }; #pragma region Pipeline Creation etc @@ -197,14 +215,15 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 vk::PushConstantRange pcr = { .stageFlags = vk::ShaderStageFlagBits::eCompute, .offset = 0, - .size = Cast(eastl::max(eastl::max(sizeof(SkyboxPushConstants), sizeof(BrdfLutPushConstants)), - eastl::max(sizeof(DiffuseIrradiancePushConstants), sizeof(PrefilterPushConstants)))), + .size = + Cast(eastl::max(eastl::max(sizeof(SkyboxPushConstants), sizeof(BrdfLutPushConstants)), + eastl::max(sizeof(DiffuseIrradiancePushConstants), sizeof(PrefilterPushConstants)))), }; vk::PipelineLayout pipelineLayout; const vk::PipelineLayoutCreateInfo layoutCreateInfo = { .setLayoutCount = 1, - .pSetLayouts = &resMan->m_SetLayout, + .pSetLayouts = &commitManager->GetDescriptorSetLayout(), .pushConstantRangeCount = 1, .pPushConstantRanges = &pcr, }; @@ -254,9 +273,9 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 }; eastl::array pipelines; - AbortIfFailed(pDevice->m_Device.createComputePipelines(pDevice->m_PipelineCache, Cast(computePipelineCreateInfo.size()), - computePipelineCreateInfo.data(), nullptr, - pipelines.data())); + AbortIfFailed( + pDevice->m_Device.createComputePipelines(pDevice->m_PipelineCache, Cast(computePipelineCreateInfo.size()), + computePipelineCreateInfo.data(), nullptr, pipelines.data())); vk::Pipeline eqRectToCubePipeline = pipelines[0]; vk::Pipeline diffuseIrradiancePipeline = pipelines[1]; @@ -278,17 +297,18 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 DiffuseIrradiancePushConstants diffuseIrradiancePushConstants = { .m_SkyboxHandle = skyboxHandle, .m_OutputTexture = diffuseIrradianceStorageHandle, - .m_CubeSide = diffuseIrradiance.m_Extent.width, + .m_CubeSide = diffuseIrradiance->m_Extent.width, }; PrefilterPushConstants prefilterPushConstants = { .m_SkyboxHandle = skyboxHandle, + .m_OutputTexture = systems::NullId{}, .m_EnvSide = cubeSide, }; BrdfLutPushConstants brdfLutPushConstants = { .m_OutputTexture = brdfLutStorageHandle, }; - resMan->Update(); + commitManager->Update(); auto cmd = assetLoader->m_CommandBuffer; constexpr vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit}; @@ -306,26 +326,27 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cmd.pipelineBarrier2(&readyToWriteDependency); - cmd.bindDescriptorSets(vk::PipelineBindPoint::eCompute, pipelineLayout, 0, 1, &resMan->m_DescriptorSet, 0, nullptr); + cmd.bindDescriptorSets(vk::PipelineBindPoint::eCompute, pipelineLayout, 0, 1, &commitManager->GetDescriptorSet(), 0, + nullptr); cmd.bindPipeline(vk::PipelineBindPoint::eCompute, eqRectToCubePipeline); cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof skyboxPushConstant, &skyboxPushConstant); - assert(skybox.m_Extent.width % 16 == 0 && skybox.m_Extent.height % 16 == 0); - cmd.dispatch(skybox.m_Extent.width / 16, skybox.m_Extent.height / 16, 6); + assert(skybox->m_Extent.width % 16 == 0 && skybox->m_Extent.height % 16 == 0); + cmd.dispatch(skybox->m_Extent.width / 16, skybox->m_Extent.height / 16, 6); - GenerateMipMaps(cmd, &skybox, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral, + GenerateMipMaps(cmd, skybox, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral, vk::PipelineStageFlagBits2::eComputeShader, vk::PipelineStageFlagBits2::eComputeShader); cmd.bindPipeline(vk::PipelineBindPoint::eCompute, diffuseIrradiancePipeline); cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof skyboxPushConstant, &diffuseIrradiancePushConstants); - assert(diffuseIrradiance.m_Extent.width % 16 == 0 && diffuseIrradiance.m_Extent.height % 16 == 0); - cmd.dispatch(diffuseIrradiance.m_Extent.width / 16, diffuseIrradiance.m_Extent.width / 16, 6); + assert(diffuseIrradiance->m_Extent.width % 16 == 0 && diffuseIrradiance->m_Extent.height % 16 == 0); + cmd.dispatch(diffuseIrradiance->m_Extent.width / 16, diffuseIrradiance->m_Extent.width / 16, 6); cmd.pipelineBarrier2(&diffIrrToSampleDependency); cmd.bindPipeline(vk::PipelineBindPoint::eCompute, prefilterPipeline); - u32 mipSize = prefilterCube.m_Extent.width; + u32 mipSize = prefilterCube->m_Extent.width; assert(mipSize % 16 == 0); for (u32 mipCount = 0; auto &tex : prefilterStorageHandles) { @@ -347,8 +368,8 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cmd.bindPipeline(vk::PipelineBindPoint::eCompute, brdfLutPipeline); cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof brdfLutPushConstants, &brdfLutPushConstants); - assert(brdfLut.m_Extent.width % 16 == 0 && brdfLut.m_Extent.height % 16 == 0); - cmd.dispatch(brdfLut.m_Extent.width / 16, brdfLut.m_Extent.height / 16, 1); + assert(brdfLut->m_Extent.width % 16 == 0 && brdfLut->m_Extent.height % 16 == 0); + cmd.dispatch(brdfLut->m_Extent.width / 16, brdfLut->m_Extent.height / 16, 1); #if !defined(ASTER_NDEBUG) cmd.endDebugUtilsLabelEXT(); @@ -373,13 +394,10 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 AbortIfFailed(pDevice->m_Device.resetCommandPool(assetLoader->m_CommandPool, {})); skybox = {}; - resMan->Release(skyboxStorageHandle); - resMan->Release(diffuseIrradianceStorageHandle); - resMan->Release(brdfLutStorageHandle); - for (auto &texHandles : prefilterStorageHandles) + for (auto &_ : prefilterStorageHandles) { StorageTextureCube st; - resMan->Release(&st, texHandles); + // TODO: This needs fixing pDevice->m_Device.destroy(st.m_View, nullptr); } for (auto &pipeline : pipelines) diff --git a/samples/03_model_render/ibl_helpers.h b/samples/03_model_render/ibl_helpers.h index 85d5eca..7e0bdba 100644 --- a/samples/03_model_render/ibl_helpers.h +++ b/samples/03_model_render/ibl_helpers.h @@ -6,7 +6,8 @@ #pragma once #include "aster/aster.h" -#include "gpu_resource_manager.h" +#include "aster/systems/resource.h" +#include "aster/core/image.h" struct Pipeline; struct Texture; @@ -15,14 +16,11 @@ struct AssetLoader; struct Environment { - TextureHandle m_Skybox; - TextureHandle m_Diffuse; - TextureHandle m_Prefilter; - TextureHandle m_BrdfLut; - - void Destroy(GpuResourceManager *resourceManager); + systems::ResId m_Skybox; + systems::ResId m_Diffuse; + systems::ResId m_Prefilter; + systems::ResId m_BrdfLut; }; -Environment -CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, u32 cubeSide, TextureHandle hdrEnv, - cstr name = nullptr); \ No newline at end of file +Environment CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, u32 cubeSide, systems::ResId hdrEnv, + cstr name = nullptr); \ No newline at end of file diff --git a/samples/03_model_render/light_manager.cpp b/samples/03_model_render/light_manager.cpp index 1c375ff..49f8486 100644 --- a/samples/03_model_render/light_manager.cpp +++ b/samples/03_model_render/light_manager.cpp @@ -6,30 +6,11 @@ #include "light_manager.h" #include "aster/core/buffer.h" +#include "aster/systems/resource.h" +#include "aster/systems/resource_manager.h" +#include "aster/systems/commit_manager.h" #include "glm/ext/matrix_transform.hpp" -struct Light -{ - union { - vec3 um_Position; - vec3 um_Direction; - }; - f32 m_Range; // < 0.0 for invalid - u32 m_Color_; // LSB is used for flags. (R G B Flags) - f32 m_Intensity; - - constexpr static u32 MAX_GEN = 0x40; - constexpr static u32 GEN_MASK = MAX_GEN - 1; - - constexpr static u32 TYPE_MASK = 0xC0; - constexpr static u32 TYPE_INVALID = 0x0; - constexpr static u32 TYPE_DIRECTIONAL = 1 << 6; - constexpr static u32 TYPE_POINT = 2 << 6; - constexpr static u32 TYPE_SPOT = 3 << 6; // Currently Unused - - constexpr static u32 COLOR_MASK = ~(GEN_MASK | TYPE_MASK); -}; - // Static Checks // Ensure layouts are exact. @@ -74,29 +55,25 @@ ToColor32(const vec3 &col) return r << 24 | g << 16 | b << 8 | a; } -LightManager::LightManager(GpuResourceManager *resourceManager) +LightManager::LightManager(systems::ResourceManager *resourceManager, systems::CommitManager *commitManager) : m_ResourceManager{resourceManager} + , m_CommitManager{commitManager} , m_DirectionalLightCount{} , m_PointLightCount{} - , m_MetaInfo{} + , m_MetaInfo{.m_LightBuffer = systems::ResId::Null() } , m_GpuBufferCapacity_{0} { } -LightManager::~LightManager() -{ - m_ResourceManager->Release(m_MetaInfo.m_LightBuffer); -} - LightManager::LightManager(LightManager &&other) noexcept : m_ResourceManager(other.m_ResourceManager) + , m_CommitManager(other.m_CommitManager) , m_Lights(std::move(other.m_Lights)) , m_DirectionalLightCount(other.m_DirectionalLightCount) , m_PointLightCount(other.m_PointLightCount) - , m_MetaInfo(other.m_MetaInfo) + , m_MetaInfo(std::move(other.m_MetaInfo)) , m_GpuBufferCapacity_(other.m_GpuBufferCapacity_) { - other.m_MetaInfo.m_LightBuffer = {}; } LightManager & @@ -108,8 +85,7 @@ LightManager::operator=(LightManager &&other) noexcept m_Lights = std::move(other.m_Lights); m_DirectionalLightCount = other.m_DirectionalLightCount; m_PointLightCount = other.m_PointLightCount; - m_MetaInfo = other.m_MetaInfo; - other.m_MetaInfo.m_LightBuffer = {}; + m_MetaInfo = std::move(other.m_MetaInfo); m_GpuBufferCapacity_ = other.m_GpuBufferCapacity_; return *this; } @@ -234,16 +210,15 @@ LightManager::Update() const u16 requiredBufferCapacity = eastl::min(Cast(m_Lights.capacity()), MAX_LIGHTS); if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity) { - StorageBuffer newBuffer; - newBuffer.Init(m_ResourceManager->m_Device, requiredBufferCapacity * sizeof m_Lights[0], true, "Light Buffer"); + auto newBuffer = m_ResourceManager->Buffers().CreateStorageBuffer(requiredBufferCapacity * sizeof m_Lights[0], "Light Buffer"); m_GpuBufferCapacity_ = requiredBufferCapacity | UPDATE_REQUIRED_BIT; - m_ResourceManager->Release(m_MetaInfo.m_LightBuffer); - m_MetaInfo.m_LightBuffer = m_ResourceManager->Commit(&newBuffer); + m_MetaInfo.m_LightBuffer = m_CommitManager->CommitBuffer(newBuffer); } if (m_GpuBufferCapacity_ & UPDATE_REQUIRED_BIT) { - m_ResourceManager->Write(m_MetaInfo.m_LightBuffer, 0, m_Lights.size() * sizeof m_Lights[0], m_Lights.data()); + const auto ref = m_CommitManager->FetchHandle(m_MetaInfo.m_LightBuffer); + ref->Write(0, m_Lights.size() * sizeof m_Lights[0], m_Lights.data()); } } diff --git a/samples/03_model_render/light_manager.h b/samples/03_model_render/light_manager.h index e57feeb..dbb65e5 100644 --- a/samples/03_model_render/light_manager.h +++ b/samples/03_model_render/light_manager.h @@ -8,7 +8,16 @@ #include "aster/aster.h" // TODO: Separate files so you only import handles. -#include "gpu_resource_manager.h" +#include "aster/systems/resource.h" +#include "aster/core/buffer.h" + +#include + +namespace systems +{ +class ResourceManager; +class CommitManager; +} // namespace systems struct DirectionalLight { @@ -33,7 +42,27 @@ struct LightHandle u16 m_Index; }; -struct Light; +struct Light +{ + union { + vec3 um_Position; + vec3 um_Direction; + }; + f32 m_Range; // < 0.0 for invalid + u32 m_Color_; // LSB is used for flags. (R G B Flags) + f32 m_Intensity; + + constexpr static u32 MAX_GEN = 0x40; + constexpr static u32 GEN_MASK = MAX_GEN - 1; + + constexpr static u32 TYPE_MASK = 0xC0; + constexpr static u32 TYPE_INVALID = 0x0; + constexpr static u32 TYPE_DIRECTIONAL = 1 << 6; + constexpr static u32 TYPE_POINT = 2 << 6; + constexpr static u32 TYPE_SPOT = 3 << 6; // Currently Unused + + constexpr static u32 COLOR_MASK = ~(GEN_MASK | TYPE_MASK); +}; struct LightManager { @@ -44,14 +73,15 @@ struct LightManager // We can use that with Offset = 0, and point light at further offsets. // This way we don't need to move point lights often. - BufferHandle m_LightBuffer; // 04 04 - u16 m_PointLightMaxCount; // 02 06 - u16 m_PointLightOffset; // 02 08 - u16 m_DirectionalLightMaxCount; // 02 10 - u16 m_UnusedPadding0 = 0; // 02 12 + systems::ResId m_LightBuffer; // 04 04 + u16 m_PointLightMaxCount; // 02 06 + u16 m_PointLightOffset; // 02 08 + u16 m_DirectionalLightMaxCount; // 02 10 + u16 m_UnusedPadding0 = 0; // 02 12 }; - GpuResourceManager *m_ResourceManager; + systems::ResourceManager *m_ResourceManager; + systems::CommitManager *m_CommitManager; eastl::vector m_Lights; // We don't need a Directional Light free list. We will just brute force iterate. @@ -73,9 +103,9 @@ struct LightManager void Update(); void RemoveLight(LightHandle handle); - explicit LightManager(GpuResourceManager *resourceManager); - ~LightManager(); + ~LightManager() = default; + LightManager(systems::ResourceManager *resourceManager, systems::CommitManager *commitManager); LightManager(LightManager &&other) noexcept; LightManager &operator=(LightManager &&other) noexcept; diff --git a/samples/03_model_render/model_render.cpp b/samples/03_model_render/model_render.cpp index 038a99b..0585552 100644 --- a/samples/03_model_render/model_render.cpp +++ b/samples/03_model_render/model_render.cpp @@ -15,18 +15,19 @@ #include "aster/core/swapchain.h" #include "aster/core/window.h" +#include "asset_loader.h" #include "frame.h" #include "helpers.h" #include "light_manager.h" -#include "asset_loader.h" -#include "gpu_resource_manager.h" +#include "aster/systems/buffer_manager.h" #include "gui.h" #include "ibl_helpers.h" #include "pipeline_utils.h" #include -#include +#include +#include #include #include @@ -176,24 +177,24 @@ main(int, char **) {queueAllocation}, pipelineCacheData, "Primary Device"}; vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0); Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"}; - GpuResourceManager resourceManager = {&device, 1000}; - AssetLoader assetLoader = {&resourceManager, graphicsQueue, queueAllocation.m_Family, queueAllocation.m_Family}; - LightManager lightManager = LightManager{&resourceManager}; + systems::ResourceManager resourceManager = {&device, 1000, 1000, 10}; + systems::CommitManager commitManager = {&device, 1000, 1000, 1000, resourceManager.Samplers().CreateSampler({})}; + + AssetLoader assetLoader = {&resourceManager, &commitManager, graphicsQueue, queueAllocation.m_Family, + queueAllocation.m_Family}; + LightManager lightManager = LightManager{&resourceManager, &commitManager}; Model model = assetLoader.LoadModelToGpu(MODEL_FILE); - Texture environmentHdri; - assetLoader.LoadHdrImage(&environmentHdri, BACKDROP_FILE); - auto envHdriHandle = resourceManager.CommitTexture(&environmentHdri); + auto environmentHdri = assetLoader.LoadHdrImage(BACKDROP_FILE); + auto envHdriHandle = commitManager.CommitTexture(environmentHdri); auto environment = CreateCubeFromHdrEnv(&assetLoader, graphicsQueue, 512, envHdriHandle, "Cube Env"); - resourceManager.Release(envHdriHandle); - vk::Format attachmentFormat = vk::Format::eR8G8B8A8Srgb; - Pipeline pipeline = CreatePipeline(&device, attachmentFormat, &resourceManager); - Pipeline backGroundPipeline = CreateBackgroundPipeline(&device, attachmentFormat, &resourceManager); + Pipeline pipeline = CreatePipeline(&device, attachmentFormat, &commitManager); + Pipeline backGroundPipeline = CreateBackgroundPipeline(&device, attachmentFormat, &commitManager); lightManager.AddPoint(vec3{-5.0f, -5.0f, 5.0f}, vec3{1.0f}, 30.0f, 16.0f); lightManager.AddPoint(vec3{5.0f, -5.0f, 5.0f}, vec3{1.0f}, 30.0f, 16.0f); @@ -242,19 +243,18 @@ main(int, char **) memcpy(data + lightOffset, &environment, sizeof environment); memcpy(data + lightOffset + sizeof environment, &lightManager.m_MetaInfo, sizeof lightManager.m_MetaInfo); - UniformBuffer ubo; - ubo.Init(&device, uboSize, "Desc1 UBO"); - ubo.Write(&device, 0, ubo.GetSize(), data); + auto ubo = resourceManager.Buffers().CreateUniformBuffer(uboSize, "Desc1 UBO"); + ubo->Write(0, ubo->m_Size, data); delete[] data; vk::DescriptorBufferInfo cameraBufferInfo = { - .buffer = ubo.m_Buffer, + .buffer = ubo->m_Buffer, .offset = 0, .range = cameraSize, }; vk::DescriptorBufferInfo lightingBufferInfo = { - .buffer = ubo.m_Buffer, + .buffer = ubo->m_Buffer, .offset = lightOffset, .range = lightingSize, }; @@ -278,7 +278,7 @@ main(int, char **) }; device.m_Device.updateDescriptorSets(Cast(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr); - resourceManager.Update(); + commitManager.Update(); // Persistent variables vk::Viewport viewport = { @@ -383,22 +383,23 @@ main(int, char **) }; FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT}; - eastl::fixed_vector depthImages(frameManager.m_FramesInFlight); - eastl::fixed_vector attachmentImages(frameManager.m_FramesInFlight); + eastl::fixed_vector, MAX_FRAMES_IN_FLIGHT> depthImages; + eastl::fixed_vector, MAX_FRAMES_IN_FLIGHT> attachmentImages; + + for (u32 index = 0; index < frameManager.m_FramesInFlight; ++index) { - auto depthIter = depthImages.begin(); - auto attachmentIter = attachmentImages.begin(); - for (u32 index = 0; index < frameManager.m_FramesInFlight; ++index) - { - auto name = fmt::format("Depth Frame{}", index); - depthIter->Init(&device, internalResolution, name.c_str()); + auto name = fmt::format("Depth Frame{}", index); + depthImages.emplace_back(resourceManager.Images().CreateDepthStencilImage({ + .m_Extent = internalResolution, + .m_Name = name.c_str(), + })); - name = fmt::format("Attachment0 Frame{}", index); - attachmentIter->Init(&device, internalResolution, attachmentFormat, name.c_str()); - - ++depthIter; - ++attachmentIter; - } + name = fmt::format("Attachment0 Frame{}", index); + attachmentImages.emplace_back(resourceManager.Images().CreateAttachment({ + .m_Format = attachmentFormat, + .m_Extent = internalResolution, + .m_Name = name.c_str(), + })); } gui::Init(&context, &device, &window, swapchain.m_Format, Cast(swapchain.m_ImageViews.size()), @@ -410,10 +411,10 @@ main(int, char **) bool showPrefilter = false; bool useSpecular = true; - constexpr u32 USE_DIFFUSE_BIT = 1; - constexpr u32 USE_SPECULAR_BIT = 1 << 1; - constexpr u32 SHOW_DIFFUSE_BIT = 1 << 2; - constexpr u32 SHOW_PREFILTER_BIT = 1 << 3; + constexpr static u32 USE_DIFFUSE_BIT = 1; + constexpr static u32 USE_SPECULAR_BIT = 1 << 1; + constexpr static u32 SHOW_DIFFUSE_BIT = 1 << 2; + constexpr static u32 SHOW_PREFILTER_BIT = 1 << 3; i32 height = Cast(internalResolution.height); f32 camPitch = glm::degrees(cameraController.m_Pitch); @@ -513,7 +514,7 @@ main(int, char **) } model.Update(); cameraController.m_Camera.CalculateInverses(); - ubo.Write(&device, 0, sizeof cameraController.m_Camera, &cameraController.m_Camera); + ubo->Write(0, sizeof cameraController.m_Camera, &cameraController.m_Camera); Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &surface, window.GetSize()); @@ -522,19 +523,24 @@ main(int, char **) vk::ImageView currentSwapchainImageView = swapchain.m_ImageViews[imageIndex]; vk::CommandBuffer cmd = currentFrame->m_CommandBuffer; - DepthImage *currentDepthImage = &depthImages[currentFrame->m_FrameIdx]; - AttachmentImage *currentAttachment = &attachmentImages[currentFrame->m_FrameIdx]; + auto& currentDepthImage = depthImages[currentFrame->m_FrameIdx]; + auto& currentAttachment = attachmentImages[currentFrame->m_FrameIdx]; if (currentAttachment->m_Extent.width != internalResolution.width || currentAttachment->m_Extent.height != internalResolution.height) { auto name = fmt::format("Depth Frame{}", currentFrame->m_FrameIdx); - currentDepthImage->Destroy(&device); - currentDepthImage->Init(&device, internalResolution, name.c_str()); + currentDepthImage = resourceManager.Images().CreateDepthStencilImage({ + .m_Extent = internalResolution, + .m_Name = name.c_str(), + }); name = fmt::format("Attachment0 Frame{}", currentFrame->m_FrameIdx); - currentAttachment->Destroy(&device); - currentAttachment->Init(&device, internalResolution, attachmentFormat, name.c_str()); + currentAttachment = resourceManager.Images().CreateAttachment({ + .m_Format = attachmentFormat, + .m_Extent = internalResolution, + .m_Name = name.c_str(), + }); } vk::ImageView currentDepthImageView = currentDepthImage->m_View; @@ -586,12 +592,12 @@ main(int, char **) cmd.setViewport(0, 1, &viewport); cmd.setScissor(0, 1, &scissor); cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1, - &resourceManager.m_DescriptorSet, 0, nullptr); + &commitManager.GetDescriptorSet(), 0, nullptr); cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 1, 1, &perFrameDescriptor, 0, nullptr); - cmd.bindIndexBuffer(model.m_IndexBuffer.m_Buffer, 0, vk::IndexType::eUint32); + cmd.bindIndexBuffer(model.m_IndexBuffer->m_Buffer, 0, vk::IndexType::eUint32); cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline); @@ -693,22 +699,11 @@ main(int, char **) device.WaitIdle(); - environment.Destroy(&resourceManager); - pipelineCacheData = device.DumpPipelineCache(); ERROR_IF(!WriteFileBytes(PIPELINE_CACHE_FILE, pipelineCacheData), "Pipeline Cache incorrectly written"); gui::Destroy(&device); - for (auto &depthImage : depthImages) - { - depthImage.Destroy(&device); - } - for (auto &attachmentImage : attachmentImages) - { - attachmentImage.Destroy(&device); - } - ubo.Destroy(&device); device.m_Device.destroy(descriptorPool, nullptr); return 0; diff --git a/samples/03_model_render/pipeline_utils.cpp b/samples/03_model_render/pipeline_utils.cpp index 39af77e..67187fa 100644 --- a/samples/03_model_render/pipeline_utils.cpp +++ b/samples/03_model_render/pipeline_utils.cpp @@ -8,13 +8,14 @@ #include "aster/core/device.h" #include "aster/core/pipeline.h" -#include "gpu_resource_manager.h" #include "helpers.h" +#include "aster/systems/commit_manager.h" + #include Pipeline -CreatePipeline(const Device *device, vk::Format attachmentFormat, const GpuResourceManager *resourceManager) +CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems::CommitManager *commitManager) { // Pipeline Setup auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE); @@ -35,7 +36,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const GpuResou eastl::vector descriptorSetLayouts; - descriptorSetLayouts.push_back(resourceManager->m_SetLayout); + descriptorSetLayouts.push_back(commitManager->GetDescriptorSetLayout()); { eastl::array descriptorSetLayoutBindings = { @@ -175,7 +176,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const GpuResou } Pipeline -CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, const GpuResourceManager *resourceManager) +CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, const systems::CommitManager *commitManager) { // Pipeline Setup auto vertexShaderModule = CreateShader(device, BACKGROUND_VERTEX_SHADER_FILE); @@ -196,7 +197,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons eastl::vector descriptorSetLayouts; - descriptorSetLayouts.push_back(resourceManager->m_SetLayout); + descriptorSetLayouts.push_back(commitManager->GetDescriptorSetLayout()); { eastl::array descriptorSetLayoutBindings = { diff --git a/samples/03_model_render/pipeline_utils.h b/samples/03_model_render/pipeline_utils.h index fd2695d..879714c 100644 --- a/samples/03_model_render/pipeline_utils.h +++ b/samples/03_model_render/pipeline_utils.h @@ -7,6 +7,11 @@ #include "aster/aster.h" +namespace systems +{ +class CommitManager; +} + struct GpuResourceManager; struct Swapchain; struct Device; @@ -19,6 +24,6 @@ constexpr auto BACKGROUND_VERTEX_SHADER_FILE = "shader/background.vs.hlsl.spv"; constexpr auto BACKGROUND_FRAGMENT_SHADER_FILE = "shader/background.ps.hlsl.spv"; vk::ShaderModule CreateShader(const Device *device, cstr shaderFile); -Pipeline CreatePipeline(const Device *device, vk::Format attachmentFormat, const GpuResourceManager *resourceManager); +Pipeline CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems::CommitManager *resourceManager); Pipeline -CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, const GpuResourceManager *resourceManager); \ No newline at end of file +CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, const systems::CommitManager *resourceManager); \ No newline at end of file diff --git a/samples/03_model_render/tiny_gltf_setup.cpp b/samples/03_model_render/tiny_gltf_setup.cpp new file mode 100644 index 0000000..ca67fea --- /dev/null +++ b/samples/03_model_render/tiny_gltf_setup.cpp @@ -0,0 +1,10 @@ + + +#define TINYGLTF_NOEXCEPTION +#define JSON_NOEXCEPTION + +#define TINYGLTF_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION + +#include \ No newline at end of file diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 33fa944..a20107f 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -5,5 +5,5 @@ cmake_minimum_required(VERSION 3.13) add_subdirectory("00_util") add_subdirectory("01_triangle") add_subdirectory("02_box") -# add_subdirectory("03_model_render") +add_subdirectory("03_model_render") # add_subdirectory("04_scenes")