Compare commits
4 Commits
98660a11fa
...
703624eb86
| Author | SHA1 | Date |
|---|---|---|
|
|
703624eb86 | |
|
|
1748a48272 | |
|
|
d8770c1e06 | |
|
|
1bee73e46f |
|
|
@ -9,104 +9,109 @@
|
||||||
|
|
||||||
struct Device;
|
struct Device;
|
||||||
|
|
||||||
// TODO Refactor the Buffer Hierarchy
|
/// A Vulkan buffer wrapper.
|
||||||
|
|
||||||
struct Buffer
|
struct Buffer
|
||||||
{
|
{
|
||||||
const Device *m_Device = nullptr; ///< Will be used for book-keeping when buffer is invalid.
|
enum class FlagBits : u8
|
||||||
|
{
|
||||||
|
eNone = 0x0,
|
||||||
|
eStaging = 0x1,
|
||||||
|
eUniform = 0x2,
|
||||||
|
eStorage = 0x4,
|
||||||
|
eIndex = 0x8,
|
||||||
|
eVertex = 0x10,
|
||||||
|
eIndirect = 0x20,
|
||||||
|
};
|
||||||
|
|
||||||
|
using Flags = vk::Flags<FlagBits>;
|
||||||
|
constexpr static Flags FLAGS = {};
|
||||||
|
|
||||||
|
const Device *m_Device = nullptr;
|
||||||
vk::Buffer m_Buffer = nullptr;
|
vk::Buffer m_Buffer = nullptr;
|
||||||
VmaAllocation m_Allocation = nullptr;
|
VmaAllocation m_Allocation = nullptr;
|
||||||
|
|
||||||
u8 *m_Mapped = nullptr; ///< If the buffer is host visible, it should be (and stay) mapped.
|
u8 *m_Mapped = nullptr; ///< If the buffer is host visible, it should be (and stay) mapped.
|
||||||
|
|
||||||
usize m_Size = 0;
|
usize m_Size = 0;
|
||||||
std::atomic<u32> m_RefCount = 0;
|
Flags m_Flags = {};
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
IsHostVisible() const
|
|
||||||
{
|
|
||||||
return m_Mapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// @returns True if it is a valid vulkan buffer.
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
IsValid() const
|
IsValid() const
|
||||||
{
|
{
|
||||||
return m_Buffer;
|
return m_Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the buffer is host visible, it should be (and stay) mapped.
|
||||||
|
/// @returns True if the buffer is host-visible and mapped.
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
IsMapped() const
|
IsMapped() const
|
||||||
{
|
{
|
||||||
return m_Mapped;
|
return m_Mapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/// Writes the data to the buffer.
|
||||||
AddRef()
|
/// @note The buffer must be mapped.
|
||||||
{
|
void Write(usize offset, usize size, const void *data) const;
|
||||||
assert(++m_RefCount > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Release()
|
|
||||||
{
|
|
||||||
const auto rc = --m_RefCount;
|
|
||||||
assert(rc < MaxValue<u32>);
|
|
||||||
if (rc == 0)
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
IsReferenced()
|
|
||||||
{
|
|
||||||
return m_RefCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Destroy();
|
|
||||||
void Write(usize offset, usize size, const void *data);
|
|
||||||
|
|
||||||
void Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUsage,
|
|
||||||
VmaAllocationCreateFlags allocationFlags, VmaMemoryUsage memoryUsage, cstr name);
|
|
||||||
|
|
||||||
|
/// If Buffer Device Address is enabled,
|
||||||
|
/// Get a pointer.
|
||||||
uptr GetDeviceAddress(const Device *device) const;
|
uptr GetDeviceAddress(const Device *device) const;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
Buffer(const Device *device, usize size, vk::BufferUsageFlags bufferUsage, VmaAllocationCreateFlags allocationFlags,
|
||||||
|
VmaMemoryUsage memoryUsage, cstr name);
|
||||||
|
|
||||||
|
Buffer(Buffer &&other) noexcept;
|
||||||
|
Buffer &operator=(Buffer &&other) noexcept;
|
||||||
|
|
||||||
|
~Buffer();
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UniformBuffer : Buffer
|
struct UniformBuffer : Buffer
|
||||||
{
|
{
|
||||||
void Init(const Device *device, usize size, cstr name = nullptr);
|
constexpr static Flags FLAGS = FlagBits::eUniform;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StorageBuffer : Buffer
|
struct StorageBuffer : Buffer
|
||||||
{
|
{
|
||||||
void Init(const Device *device, usize size, bool hostVisible, cstr name = nullptr);
|
constexpr static Flags FLAGS = FlagBits::eStorage;
|
||||||
void Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name = nullptr);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IndirectBuffer : Buffer
|
struct IndirectBuffer : Buffer
|
||||||
{
|
{
|
||||||
void Init(const Device *device, usize size, bool hostVisible, cstr name = nullptr);
|
constexpr static Flags FLAGS = FlagBits::eIndirect;
|
||||||
};
|
|
||||||
|
|
||||||
struct StorageIndexBuffer : StorageBuffer
|
|
||||||
{
|
|
||||||
void Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name = nullptr);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VertexBuffer : Buffer
|
struct VertexBuffer : Buffer
|
||||||
{
|
{
|
||||||
void Init(const Device *device, usize size, cstr name = nullptr);
|
constexpr static Flags FLAGS = FlagBits::eVertex;
|
||||||
void Write(const Device *device, void *data, usize size, usize offset) const = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IndexBuffer : Buffer
|
struct IndexBuffer : Buffer
|
||||||
{
|
{
|
||||||
void Init(const Device *device, usize size, cstr name = nullptr);
|
constexpr static Flags FLAGS = FlagBits::eIndex;
|
||||||
void Write(const Device *device, void *data, usize size, usize offset) const = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StagingBuffer : Buffer
|
struct StagingBuffer : Buffer
|
||||||
{
|
{
|
||||||
void Init(const Device *device, usize size, cstr name = nullptr);
|
constexpr static Flags FLAGS = FlagBits::eStaging;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace concepts
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
concept AnyBuffer = std::derived_from<T, Buffer>;
|
||||||
|
|
||||||
|
template <typename T, typename TInto>
|
||||||
|
concept BufferInto = std::derived_from<T, Buffer> and std::derived_from<TInto, Buffer> and
|
||||||
|
(Cast<bool>(T::FLAGS & TInto::FLAGS) or std::same_as<Buffer, TInto>);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept AnyBufferRef = Deref<T> and AnyBuffer<DerefType<T>>;
|
||||||
|
|
||||||
|
template <typename T, typename TTo>
|
||||||
|
concept BufferRefTo = Deref<T> and BufferInto<DerefType<T>, TTo>;
|
||||||
|
|
||||||
|
} // namespace concepts
|
||||||
|
|
@ -221,5 +221,8 @@ struct fmt::formatter<eastl::fixed_string<TType, TCount, TOverflow>> : nested_fo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <concepts::Manageable T>
|
template <typename T>
|
||||||
using Ref = eastl::intrusive_ptr<T>;
|
using Ref = std::shared_ptr<T>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using WeakRef = std::weak_ptr<T>;
|
||||||
|
|
@ -36,186 +36,97 @@ ToOffset3D(const vk::Extent3D &extent)
|
||||||
|
|
||||||
struct Image
|
struct Image
|
||||||
{
|
{
|
||||||
|
enum class FlagBits : u8
|
||||||
|
{
|
||||||
|
eSampled = 0x1,
|
||||||
|
eStorage = 0x2,
|
||||||
|
eCube = 0x4,
|
||||||
|
};
|
||||||
|
|
||||||
|
using Flags = vk::Flags<FlagBits>;
|
||||||
|
constexpr static Flags FLAGS = {};
|
||||||
|
|
||||||
const Device *m_Device = nullptr;
|
const Device *m_Device = nullptr;
|
||||||
vk::Image m_Image = nullptr;
|
vk::Image m_Image = nullptr;
|
||||||
VmaAllocation m_Allocation = nullptr;
|
VmaAllocation m_Allocation = nullptr;
|
||||||
vk::Extent3D m_Extent;
|
vk::Extent3D m_Extent;
|
||||||
vk::Format m_Format;
|
vk::Format m_Format;
|
||||||
std::atomic<u32> m_RefCount;
|
|
||||||
u8 m_EmptyPadding_ = 0;
|
u8 m_EmptyPadding_ = 0;
|
||||||
u8 m_Flags_ = 0;
|
Flags m_Flags_ = {};
|
||||||
u8 m_LayerCount = 0;
|
u8 m_LayerCount = 0;
|
||||||
u8 m_MipLevels = 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
|
[[nodiscard]] bool
|
||||||
IsValid() const
|
IsValid() const
|
||||||
{
|
{
|
||||||
return m_Image;
|
return m_Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
IsReferenced() const
|
|
||||||
{
|
|
||||||
return m_RefCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] u32
|
[[nodiscard]] u32
|
||||||
GetMipLevels() const
|
GetMipLevels() const
|
||||||
{
|
{
|
||||||
return m_MipLevels;
|
return m_MipLevels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AddRef()
|
|
||||||
{
|
|
||||||
const auto rc = ++m_RefCount;
|
|
||||||
assert(rc > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Release()
|
|
||||||
{
|
|
||||||
const auto rc = --m_RefCount;
|
|
||||||
assert(rc < MaxValue<u32>);
|
|
||||||
if (rc == 0)
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
static bool
|
|
||||||
Conforms(const Image &)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DestroyView(vk::ImageView imageView) const;
|
void DestroyView(vk::ImageView imageView) const;
|
||||||
|
|
||||||
|
// Constructors.
|
||||||
|
|
||||||
|
explicit Image(const Device *device, vk::Image image, VmaAllocation allocation, vk::Extent3D extent,
|
||||||
|
vk::Format format, Flags flags, u8 layerCount, u8 mipLevels);
|
||||||
|
|
||||||
|
Image(Image &&other) noexcept;
|
||||||
|
Image &operator=(Image &&other) noexcept;
|
||||||
|
|
||||||
|
~Image();
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Image);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace concepts
|
|
||||||
{
|
|
||||||
template <typename T>
|
|
||||||
concept Image = std::derived_from<T, Image> and Manageable<T>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept ImageRef = Derefencable<T> and Image<DereferencesTo<T>>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept SampledImage = requires() {
|
|
||||||
{ T::SAMPLED } -> std::convertible_to<bool>;
|
|
||||||
} and T::SAMPLED and Image<T>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept SampledImageRef = Derefencable<T> and SampledImage<DereferencesTo<T>>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept ImageCube = requires() {
|
|
||||||
{ T::CUBE } -> std::convertible_to<bool>;
|
|
||||||
} and T::CUBE and Image<T>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept ImageCubeRef = Derefencable<T> and ImageCube<DereferencesTo<T>>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept StorageImage = requires() {
|
|
||||||
{ T::STORAGE } -> std::convertible_to<bool>;
|
|
||||||
} and T::STORAGE and Image<T>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept StorageImageRef = Derefencable<T> and StorageImage<DereferencesTo<T>>;
|
|
||||||
|
|
||||||
} // namespace concepts
|
|
||||||
|
|
||||||
struct Texture : Image
|
struct Texture : Image
|
||||||
{
|
{
|
||||||
constexpr static bool SAMPLED = true;
|
constexpr static Flags FLAGS = FlagBits::eSampled;
|
||||||
|
|
||||||
static bool
|
|
||||||
Conforms(const Image &other)
|
|
||||||
{
|
|
||||||
return other.IsSampled();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImageCube : Image
|
struct ImageCube : Image
|
||||||
{
|
{
|
||||||
constexpr static bool CUBE = true;
|
constexpr static Flags FLAGS = FlagBits::eCube;
|
||||||
|
|
||||||
static bool
|
|
||||||
Conforms(const Image &other)
|
|
||||||
{
|
|
||||||
return other.IsCube();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureCube : Image
|
struct TextureCube : Image
|
||||||
{
|
{
|
||||||
constexpr static bool SAMPLED = true;
|
constexpr static Flags FLAGS = Texture::FLAGS | ImageCube::FLAGS;
|
||||||
constexpr static bool CUBE = true;
|
|
||||||
|
|
||||||
static bool
|
|
||||||
Conforms(const Image &other)
|
|
||||||
{
|
|
||||||
return other.IsSampled() && other.IsCube();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StorageImage : Image
|
struct StorageImage : Image
|
||||||
{
|
{
|
||||||
constexpr static bool STORAGE = true;
|
constexpr static Flags FLAGS = FlagBits::eStorage;
|
||||||
|
|
||||||
static bool
|
|
||||||
Conforms(const Image &other)
|
|
||||||
{
|
|
||||||
return other.IsStorage();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StorageTexture : StorageImage
|
struct StorageTexture : StorageImage
|
||||||
{
|
{
|
||||||
constexpr static bool SAMPLED = true;
|
constexpr static Flags FLAGS = StorageImage::FLAGS | Texture::FLAGS;
|
||||||
constexpr static bool STORAGE = true;
|
|
||||||
|
|
||||||
static bool
|
|
||||||
Conforms(const Image &other)
|
|
||||||
{
|
|
||||||
return other.IsStorage() && other.IsSampled();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StorageTextureCube : StorageImage
|
struct StorageTextureCube : StorageImage
|
||||||
{
|
{
|
||||||
constexpr static bool SAMPLED = true;
|
constexpr static Flags FLAGS = StorageImage::FLAGS | Texture::FLAGS | ImageCube::FLAGS;
|
||||||
constexpr static bool CUBE = true;
|
};
|
||||||
constexpr static bool STORAGE = true;
|
|
||||||
|
|
||||||
static bool
|
namespace concepts
|
||||||
Conforms(const Image &other)
|
{
|
||||||
{
|
|
||||||
return other.IsStorage() && other.IsSampled() && other.IsCube();
|
template <typename T>
|
||||||
}
|
concept AnyImage = std::derived_from<T, Image>;
|
||||||
};
|
|
||||||
|
template <typename T, typename TInto>
|
||||||
|
concept ImageInto = std::derived_from<T, Image> and std::derived_from<TInto, Image> and
|
||||||
|
(Cast<bool>(T::FLAGS & TInto::FLAGS) or std::same_as<Image, TInto>);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept AnyImageRef = Deref<T> and AnyImage<DerefType<T>>;
|
||||||
|
|
||||||
|
template <typename T, typename TTo>
|
||||||
|
concept ImageRefTo = Deref<T> and ImageInto<DerefType<T>, TTo>;
|
||||||
|
|
||||||
|
} // namespace concepts
|
||||||
|
|
@ -8,16 +8,14 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
template <concepts::Image TImage>
|
template <concepts::AnyImage TImage>
|
||||||
struct View
|
struct View
|
||||||
{
|
{
|
||||||
using ImageType = TImage;
|
using ImageType = TImage;
|
||||||
|
|
||||||
const Device *m_Device;
|
|
||||||
Ref<Image> m_Image;
|
Ref<Image> m_Image;
|
||||||
vk::ImageView m_View = nullptr;
|
vk::ImageView m_View = nullptr;
|
||||||
vk::Extent3D m_Extent;
|
vk::Extent3D m_Extent;
|
||||||
std::atomic<u32> m_RefCount;
|
|
||||||
u8 m_BaseLayer = 0;
|
u8 m_BaseLayer = 0;
|
||||||
u8 m_LayerCount = 0;
|
u8 m_LayerCount = 0;
|
||||||
u8 m_BaseMipLevel = 0;
|
u8 m_BaseMipLevel = 0;
|
||||||
|
|
@ -29,38 +27,54 @@ struct View
|
||||||
return m_Image->m_Image;
|
return m_Image->m_Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AddRef()
|
|
||||||
{
|
|
||||||
const auto rc = ++m_RefCount;
|
|
||||||
assert(rc > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Release()
|
|
||||||
{
|
|
||||||
const auto rc = --m_RefCount;
|
|
||||||
assert(rc < MaxValue<u32>);
|
|
||||||
if (rc == 0)
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
IsReferenced() const
|
|
||||||
{
|
|
||||||
return m_RefCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
IsValid() const
|
IsValid() const
|
||||||
{
|
{
|
||||||
return m_Image;
|
return Cast<bool>(m_Image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
View(Ref<Image> image, const vk::ImageView view, const vk::Extent3D extent, const u8 baseLayer, const u8 layerCount,
|
||||||
Destroy()
|
const u8 baseMipLevel, const u8 mipLevelCount)
|
||||||
|
: m_Image{std::move(image)}
|
||||||
|
, m_View{view}
|
||||||
|
, m_Extent{extent}
|
||||||
|
, m_BaseLayer{baseLayer}
|
||||||
|
, m_LayerCount{layerCount}
|
||||||
|
, m_BaseMipLevel{baseMipLevel}
|
||||||
|
, m_MipLevelCount{mipLevelCount}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
View(View &&other) noexcept
|
||||||
|
: m_Image{std::move(other.m_Image)}
|
||||||
|
, m_View{Take(other.m_View)}
|
||||||
|
, m_Extent{std::move(other.m_Extent)}
|
||||||
|
, m_BaseLayer{other.m_BaseLayer}
|
||||||
|
, m_LayerCount{other.m_LayerCount}
|
||||||
|
, m_BaseMipLevel{other.m_BaseMipLevel}
|
||||||
|
, m_MipLevelCount{other.m_MipLevelCount}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
View &
|
||||||
|
operator=(View &&other) noexcept
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
using std::swap;
|
||||||
|
swap(m_Image, other.m_Image);
|
||||||
|
swap(m_View, other.m_View);
|
||||||
|
swap(m_Extent, other.m_Extent);
|
||||||
|
swap(m_BaseLayer, other.m_BaseLayer);
|
||||||
|
swap(m_LayerCount, other.m_LayerCount);
|
||||||
|
swap(m_BaseMipLevel, other.m_BaseMipLevel);
|
||||||
|
swap(m_MipLevelCount, other.m_MipLevelCount);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(View);
|
||||||
|
|
||||||
|
~View()
|
||||||
{
|
{
|
||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
@ -69,61 +83,26 @@ struct View
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImageView : View<Image>
|
using ImageView = View<Image>;
|
||||||
{
|
using ImageCubeView = View<ImageCube>;
|
||||||
};
|
using TextureView = View<Texture>;
|
||||||
|
using TextureCubeView = View<TextureCube>;
|
||||||
struct ImageCubeView : View<ImageCube>
|
using StorageImageView = View<StorageImage>;
|
||||||
{
|
using StorageTextureView = View<StorageTexture>;
|
||||||
};
|
using StorageTextureCubeView = View<StorageTextureCube>;
|
||||||
|
|
||||||
struct TextureView : View<Texture>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TextureCubeView : View<TextureCube>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StorageImageView : View<StorageImage>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StorageTextureView : View<StorageTexture>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StorageTextureCubeView : View<StorageTextureCube>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace concepts
|
namespace concepts
|
||||||
{
|
{
|
||||||
template <typename TView>
|
template <typename T>
|
||||||
concept View = std::derived_from<TView, View<typename TView::ImageType>>;
|
concept View = std::derived_from<T, View<typename T::ImageType>>;
|
||||||
|
|
||||||
|
template <typename T, typename TTo>
|
||||||
|
concept ViewTo = View<T> and ImageInto<typename T::ImageType, TTo>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept ViewRef = Derefencable<T> and View<DereferencesTo<T>>;
|
concept ViewRef = Deref<T> and View<DerefType<T>>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename TTo>
|
||||||
concept ImageView = View<T> and Image<typename T::ImageType>;
|
concept ViewRefTo = ViewRef<T> and ImageInto<typename DerefType<T>::ImageType, TTo>;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept ImageViewRef = Derefencable<T> and ImageView<DereferencesTo<T>>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept ImageCubeView = View<T> and ImageCube<typename T::ImageType>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept SampledImageView = View<T> and SampledImage<typename T::ImageType>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept SampledImageViewRef = Derefencable<T> and SampledImageView<DereferencesTo<T>>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept StorageImageView = View<T> and StorageImage<typename T::ImageType>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept StorageImageViewRef = Derefencable<T> and StorageImageView<DereferencesTo<T>>;
|
|
||||||
|
|
||||||
} // namespace concepts
|
} // namespace concepts
|
||||||
|
|
@ -9,44 +9,24 @@
|
||||||
|
|
||||||
struct Device;
|
struct Device;
|
||||||
|
|
||||||
// TODO Refactor the Buffer Hierarchy
|
struct Sampler final
|
||||||
|
|
||||||
struct Sampler
|
|
||||||
{
|
{
|
||||||
const Device *m_Device = nullptr;
|
const Device *m_Device = nullptr;
|
||||||
vk::Sampler m_Sampler = nullptr;
|
vk::Sampler m_Sampler = nullptr;
|
||||||
std::atomic<u32> m_RefCount = 0;
|
|
||||||
|
|
||||||
void Init(const Device *device, const vk::SamplerCreateInfo &samplerCreateInfo, cstr name);
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
void
|
|
||||||
AddRef()
|
|
||||||
{
|
|
||||||
const auto rc = ++m_RefCount;
|
|
||||||
assert(rc > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Release()
|
|
||||||
{
|
|
||||||
const auto rc = --m_RefCount;
|
|
||||||
assert(rc < MaxValue<u32>);
|
|
||||||
if (rc == 0)
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
|
||||||
IsReferenced() const
|
|
||||||
{
|
|
||||||
return m_RefCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
IsValid() const
|
IsValid() const
|
||||||
{
|
{
|
||||||
return m_Sampler;
|
return m_Sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
Sampler(const Device *device, const vk::SamplerCreateInfo &samplerCreateInfo, cstr name);
|
||||||
|
~Sampler();
|
||||||
|
|
||||||
|
Sampler(Sampler &&other) noexcept;
|
||||||
|
Sampler &operator=(Sampler &&other) noexcept;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Sampler);
|
||||||
};
|
};
|
||||||
|
|
@ -13,33 +13,16 @@ struct Image;
|
||||||
namespace concepts
|
namespace concepts
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept RefCounted = requires(T a) {
|
concept Deref = requires(T a) {
|
||||||
{ a.AddRef() } -> std::same_as<void>;
|
|
||||||
{ a.Release() } -> std::same_as<void>;
|
|
||||||
{ a.IsReferenced() } -> std::convertible_to<bool>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept Derefencable = requires(T a) {
|
|
||||||
{ *a };
|
{ *a };
|
||||||
};
|
};
|
||||||
|
|
||||||
template <Derefencable T>
|
template <typename TRef, typename TVal>
|
||||||
using DereferencesTo = std::remove_cvref_t<decltype(*std::declval<T>())>;
|
concept DerefTo = requires(TRef a) {
|
||||||
|
{ *a } -> std::convertible_to<TVal>;
|
||||||
template <typename T>
|
|
||||||
concept DeviceDestructible = requires(T a, Device *p) {
|
|
||||||
{ a.Destroy(p) } -> std::same_as<void>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <Deref T>
|
||||||
concept SelfDestructible = requires(T a) {
|
using DerefType = std::remove_cvref_t<decltype(*std::declval<T>())>;
|
||||||
{ a.Destroy() } -> std::same_as<void>;
|
|
||||||
{ T::m_Device } -> std::convertible_to<const Device *>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept Manageable =
|
|
||||||
std::is_default_constructible_v<T> and (DeviceDestructible<T> or SelfDestructible<T>) and RefCounted<T>;
|
|
||||||
|
|
||||||
} // namespace concepts
|
} // namespace concepts
|
||||||
|
|
@ -4,7 +4,6 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
target_sources(aster_core
|
target_sources(aster_core
|
||||||
INTERFACE
|
INTERFACE
|
||||||
"manager.h"
|
|
||||||
"buffer_manager.h"
|
"buffer_manager.h"
|
||||||
"image_manager.h"
|
"image_manager.h"
|
||||||
"view_manager.h"
|
"view_manager.h"
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,30 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "manager.h"
|
|
||||||
|
|
||||||
#include "aster/aster.h"
|
#include "aster/aster.h"
|
||||||
#include "aster/core/buffer.h"
|
#include "aster/core/buffer.h"
|
||||||
|
|
||||||
namespace systems
|
namespace systems
|
||||||
{
|
{
|
||||||
class BufferManager final : public Manager<Buffer>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BufferManager(const Device *device, u32 maxCount);
|
|
||||||
|
|
||||||
[[nodiscard]] Handle CreateStorageBuffer(usize size, cstr name = nullptr);
|
template <std::derived_from<Buffer> TTo, std::derived_from<Buffer> TFrom>
|
||||||
[[nodiscard]] Handle CreateUniformBuffer(usize size, cstr name = nullptr);
|
static Ref<TTo>
|
||||||
[[nodiscard]] Handle CreateStagingBuffer(usize size, cstr name = nullptr);
|
CastBuffer(const Ref<TFrom> &from)
|
||||||
|
{
|
||||||
|
if constexpr (not concepts::BufferInto<TFrom, TTo>)
|
||||||
|
assert(TTo::FLAGS & from->m_Flags);
|
||||||
|
return std::reinterpret_pointer_cast<TTo>(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
class BufferManager final
|
||||||
|
{
|
||||||
|
const Device *m_Device = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BufferManager(const Device *device);
|
||||||
|
|
||||||
|
[[nodiscard]] Ref<StorageBuffer> CreateStorageBuffer(usize size, cstr name = nullptr) const;
|
||||||
|
[[nodiscard]] Ref<UniformBuffer> CreateUniformBuffer(usize size, cstr name = nullptr) const;
|
||||||
|
[[nodiscard]] Ref<StagingBuffer> CreateStagingBuffer(usize size, cstr name = nullptr) const;
|
||||||
};
|
};
|
||||||
} // namespace systems
|
} // namespace systems
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "aster/aster.h"
|
#include "aster/aster.h"
|
||||||
|
|
||||||
#include "buffer_manager.h"
|
#include "buffer_manager.h"
|
||||||
#include "sampler_manager.h"
|
#include "sampler_manager.h"
|
||||||
#include "view_manager.h"
|
#include "view_manager.h"
|
||||||
|
|
@ -22,12 +23,11 @@ namespace systems
|
||||||
|
|
||||||
class CommitManager
|
class CommitManager
|
||||||
{
|
{
|
||||||
template <concepts::Manageable T>
|
template <typename T>
|
||||||
struct HandleMapper
|
struct HandleMapper
|
||||||
{
|
{
|
||||||
using Type = T;
|
using Type = T;
|
||||||
using Manager = Manager<Type>;
|
using Handle = Ref<Type>;
|
||||||
using Handle = typename Manager::Handle;
|
|
||||||
using Resource = ResId<Type>;
|
using Resource = ResId<Type>;
|
||||||
|
|
||||||
struct Entry : eastl::intrusive_hash_node_key<Handle>
|
struct Entry : eastl::intrusive_hash_node_key<Handle>
|
||||||
|
|
@ -82,8 +82,6 @@ class CommitManager
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(Entry) == 24);
|
|
||||||
|
|
||||||
eastl::vector<Entry> m_Data;
|
eastl::vector<Entry> m_Data;
|
||||||
FreeList<Entry> m_FreeList;
|
FreeList<Entry> m_FreeList;
|
||||||
eastl::intrusive_hash_map<typename Entry::key_type, Entry, 31, typename Entry::Hash> m_InUse;
|
eastl::intrusive_hash_map<typename Entry::key_type, Entry, 31, typename Entry::Hash> m_InUse;
|
||||||
|
|
@ -226,7 +224,7 @@ class CommitManager
|
||||||
|
|
||||||
// Commit Storage Images
|
// Commit Storage Images
|
||||||
ResId<StorageImageView>
|
ResId<StorageImageView>
|
||||||
CommitStorageImage(const concepts::StorageImageViewRef auto &image)
|
CommitStorageImage(const concepts::ViewRefTo<StorageImage> auto &image)
|
||||||
{
|
{
|
||||||
return CommitStorageImage(CastView<StorageImageView>(image));
|
return CommitStorageImage(CastView<StorageImageView>(image));
|
||||||
}
|
}
|
||||||
|
|
@ -235,19 +233,17 @@ class CommitManager
|
||||||
|
|
||||||
// Sampled Images
|
// Sampled Images
|
||||||
ResId<TextureView>
|
ResId<TextureView>
|
||||||
CommitTexture(const concepts::SampledImageViewRef auto &image, const Ref<Sampler> &sampler)
|
CommitTexture(const concepts::ViewRefTo<Texture> auto &image, const Ref<Sampler> &sampler)
|
||||||
{
|
{
|
||||||
return CommitTexture(CastView<TextureView>(image), sampler);
|
return CommitTexture(CastView<TextureView>(image), sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResId<TextureView>
|
ResId<TextureView>
|
||||||
CommitTexture(const concepts::SampledImageViewRef auto &image)
|
CommitTexture(const concepts::ViewRefTo<Texture> auto &image)
|
||||||
{
|
{
|
||||||
return CommitTexture(CastView<TextureView>(image));
|
return CommitTexture(CastView<TextureView>(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(concepts::SampledImageViewRef<Ref<TextureView>>);
|
|
||||||
|
|
||||||
ResId<TextureView> CommitTexture(const Ref<TextureView> &handle);
|
ResId<TextureView> CommitTexture(const Ref<TextureView> &handle);
|
||||||
ResId<TextureView> CommitTexture(const Ref<TextureView> &image, const Ref<Sampler> &sampler);
|
ResId<TextureView> CommitTexture(const Ref<TextureView> &image, const Ref<Sampler> &sampler);
|
||||||
|
|
||||||
|
|
@ -351,7 +347,7 @@ class CommitManager
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <concepts::Manageable T>
|
template <typename T>
|
||||||
void
|
void
|
||||||
ResId<T>::AddRef() const
|
ResId<T>::AddRef() const
|
||||||
{
|
{
|
||||||
|
|
@ -359,7 +355,7 @@ ResId<T>::AddRef() const
|
||||||
CommitManager::Instance().AddRef(*this);
|
CommitManager::Instance().AddRef(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <concepts::Manageable T>
|
template <typename T>
|
||||||
void
|
void
|
||||||
ResId<T>::Release() const
|
ResId<T>::Release() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,19 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "manager.h"
|
|
||||||
|
|
||||||
#include "aster/aster.h"
|
#include "aster/aster.h"
|
||||||
#include "aster/core/image.h"
|
#include "aster/core/image.h"
|
||||||
|
|
||||||
namespace systems
|
namespace systems
|
||||||
{
|
{
|
||||||
|
|
||||||
template <std::derived_from<Image> TTo>
|
template <std::derived_from<Image> TTo, std::derived_from<Image> TFrom>
|
||||||
static Ref<TTo>
|
static Ref<TTo>
|
||||||
CastImage(const concepts::ImageRef auto &from)
|
CastImage(const Ref<TFrom> &from)
|
||||||
{
|
{
|
||||||
assert(TTo::Conforms(*from.get()));
|
if constexpr (not concepts::ImageInto<TFrom, TTo>)
|
||||||
return Recast<TTo *>(from.get());
|
assert(TTo::FLAGS & from->m_Flags_);
|
||||||
|
return std::reinterpret_pointer_cast<TTo>(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Texture2DCreateInfo
|
struct Texture2DCreateInfo
|
||||||
|
|
@ -54,12 +53,14 @@ struct DepthStencilImageCreateInfo
|
||||||
cstr m_Name = nullptr;
|
cstr m_Name = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ImageManager final : public Manager<Image>
|
class ImageManager final
|
||||||
{
|
{
|
||||||
public:
|
const Device *m_Device;
|
||||||
ImageManager(const Device *device, u32 maxCount);
|
|
||||||
|
|
||||||
template <concepts::Image T>
|
public:
|
||||||
|
explicit ImageManager(const Device *device);
|
||||||
|
|
||||||
|
template <concepts::ImageInto<Texture> T>
|
||||||
[[nodiscard]] Ref<T>
|
[[nodiscard]] Ref<T>
|
||||||
CreateTexture2D(const Texture2DCreateInfo &createInfo)
|
CreateTexture2D(const Texture2DCreateInfo &createInfo)
|
||||||
{
|
{
|
||||||
|
|
@ -67,7 +68,7 @@ class ImageManager final : public Manager<Image>
|
||||||
return CastImage<T>(handle);
|
return CastImage<T>(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <concepts::Image T>
|
template <concepts::ImageInto<TextureCube> T>
|
||||||
[[nodiscard]] Ref<T>
|
[[nodiscard]] Ref<T>
|
||||||
CreateTextureCube(const TextureCubeCreateInfo &createInfo)
|
CreateTextureCube(const TextureCubeCreateInfo &createInfo)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: manager.h
|
|
||||||
// Copyright (c) 2020-2025 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "aster/aster.h"
|
|
||||||
#include "aster/core/type_traits.h"
|
|
||||||
#include "aster/util/freelist.h"
|
|
||||||
|
|
||||||
#include <EASTL/intrusive_ptr.h>
|
|
||||||
#include <EASTL/vector.h>
|
|
||||||
|
|
||||||
struct Device;
|
|
||||||
|
|
||||||
namespace systems
|
|
||||||
{
|
|
||||||
|
|
||||||
template <concepts::Manageable T>
|
|
||||||
class Manager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Type = T;
|
|
||||||
using Handle = Ref<T>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the Manager class template.
|
|
||||||
* @param device Device with which resources are created.
|
|
||||||
* @param maxCount Max number of resources that can be created (maxCount <= Handle::INDEX_MASK)
|
|
||||||
*/
|
|
||||||
explicit Manager(const Device *device, const u32 maxCount)
|
|
||||||
: m_Data{maxCount}
|
|
||||||
, m_Device{device}
|
|
||||||
{
|
|
||||||
for (auto &element : m_Data)
|
|
||||||
{
|
|
||||||
m_FreeList.Push(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Manager()
|
|
||||||
{
|
|
||||||
if constexpr (concepts::DeviceDestructible<Type>)
|
|
||||||
{
|
|
||||||
for (auto &element : m_Data)
|
|
||||||
{
|
|
||||||
element.Destroy(m_Device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Device = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Work on deletion!!
|
|
||||||
void
|
|
||||||
Sweep()
|
|
||||||
requires concepts::DeviceDestructible<Type>
|
|
||||||
{
|
|
||||||
for (i64 i = m_Data.size() - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
if (auto *pIter = &m_Data[i]; !pIter->IsReferenced())
|
|
||||||
{
|
|
||||||
pIter->Destroy(m_Device);
|
|
||||||
m_FreeList.Push(*pIter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Sweep()
|
|
||||||
requires concepts::SelfDestructible<Type>
|
|
||||||
{
|
|
||||||
for (i64 i = m_Data.size() - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
if (auto *pIter = &m_Data[i]; !pIter->IsValid())
|
|
||||||
{
|
|
||||||
pIter->Destroy();
|
|
||||||
m_FreeList.Push(*pIter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PIN_MEMORY(Manager);
|
|
||||||
|
|
||||||
private:
|
|
||||||
eastl::vector<Type> m_Data; // Data also keeps the freelist during 'not use'.
|
|
||||||
FreeList<Type> m_FreeList;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const Device *m_Device;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal Method to Allocate a resource on the manager.
|
|
||||||
* @return [Handle, Type*] Where Type* is available to initialize the resource.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] Handle
|
|
||||||
Alloc()
|
|
||||||
{
|
|
||||||
ERROR_IF(m_FreeList.Empty(), "Max buffers allocated.") THEN_ABORT(-1);
|
|
||||||
|
|
||||||
Type &pAlloc = m_FreeList.Pop();
|
|
||||||
memset(&pAlloc, 0, sizeof pAlloc);
|
|
||||||
if constexpr (concepts::SelfDestructible<Type>)
|
|
||||||
{
|
|
||||||
pAlloc.m_Device = m_Device;
|
|
||||||
}
|
|
||||||
return {&pAlloc};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace systems
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace systems
|
||||||
* ResId manages the lifetime of the committed resource.
|
* ResId manages the lifetime of the committed resource.
|
||||||
* @tparam T Type of the committed resource.
|
* @tparam T Type of the committed resource.
|
||||||
*/
|
*/
|
||||||
template <concepts::Manageable T>
|
template <typename T>
|
||||||
class ResId
|
class ResId
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -82,7 +82,7 @@ class ResId
|
||||||
|
|
||||||
struct NullId
|
struct NullId
|
||||||
{
|
{
|
||||||
template <concepts::Manageable T>
|
template <typename T>
|
||||||
operator ResId<T>()
|
operator ResId<T>()
|
||||||
{
|
{
|
||||||
return ResId<T>::Null();
|
return ResId<T>::Null();
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class ResourceManager
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <concepts::ImageView T>
|
template <concepts::ViewTo<Image> T>
|
||||||
[[nodiscard]] Ref<T>
|
[[nodiscard]] Ref<T>
|
||||||
CreateTexture2D(const Texture2DCreateInfo &createInfo)
|
CreateTexture2D(const Texture2DCreateInfo &createInfo)
|
||||||
{
|
{
|
||||||
|
|
@ -36,7 +36,7 @@ class ResourceManager
|
||||||
return CastView<T>(handle);
|
return CastView<T>(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <concepts::ImageCubeView T>
|
template <concepts::ViewTo<ImageCube> T>
|
||||||
[[nodiscard]] Ref<T>
|
[[nodiscard]] Ref<T>
|
||||||
CreateTextureCube(const TextureCubeCreateInfo &createInfo)
|
CreateTextureCube(const TextureCubeCreateInfo &createInfo)
|
||||||
{
|
{
|
||||||
|
|
@ -96,11 +96,11 @@ class ResourceManager
|
||||||
CombinedImageViewManager m_CombinedImageViews;
|
CombinedImageViewManager m_CombinedImageViews;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ResourceManager(const Device *device, u32 maxBufferCount, u32 maxImageCount, u32 maxSamplerCount, u32 maxViewCount)
|
explicit ResourceManager(const Device *device)
|
||||||
: m_Buffers{device, maxBufferCount}
|
: m_Buffers{device}
|
||||||
, m_Images{device, maxImageCount}
|
, m_Images{device}
|
||||||
, m_Samplers{device, maxSamplerCount}
|
, m_Samplers{device}
|
||||||
, m_Views{device, maxViewCount}
|
, m_Views{device}
|
||||||
, m_CombinedImageViews{&m_Images, &m_Views}
|
, m_CombinedImageViews{&m_Images, &m_Views}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -135,15 +135,6 @@ class ResourceManager
|
||||||
return m_CombinedImageViews;
|
return m_CombinedImageViews;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Update()
|
|
||||||
{
|
|
||||||
m_Views.Sweep();
|
|
||||||
m_Images.Sweep();
|
|
||||||
m_Buffers.Sweep();
|
|
||||||
m_Samplers.Sweep();
|
|
||||||
}
|
|
||||||
|
|
||||||
~ResourceManager() = default;
|
~ResourceManager() = default;
|
||||||
|
|
||||||
PIN_MEMORY(ResourceManager);
|
PIN_MEMORY(ResourceManager);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "EASTL/hash_map.h"
|
#include "EASTL/hash_map.h"
|
||||||
#include "manager.h"
|
|
||||||
|
|
||||||
#include "aster/aster.h"
|
#include "aster/aster.h"
|
||||||
#include "aster/core/sampler.h"
|
#include "aster/core/sampler.h"
|
||||||
|
|
@ -96,13 +95,17 @@ struct SamplerCreateInfo
|
||||||
*
|
*
|
||||||
* Manages (and caches) objects of sampler. Currently Samplers are never deleted.
|
* Manages (and caches) objects of sampler. Currently Samplers are never deleted.
|
||||||
*/
|
*/
|
||||||
class SamplerManager final : public Manager<Sampler>
|
class SamplerManager final
|
||||||
{
|
{
|
||||||
eastl::hash_map<vk::SamplerCreateInfo, Handle> m_HashToSamplerIdx;
|
using Handle = Ref<Sampler>;
|
||||||
|
using WeakHandle = WeakRef<Sampler>;
|
||||||
|
eastl::hash_map<vk::SamplerCreateInfo, WeakHandle> m_HashToSamplerIdx;
|
||||||
|
|
||||||
|
const Device *m_Device;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SamplerManager(const Device *device, u32 maxCount);
|
explicit SamplerManager(const Device *device);
|
||||||
~SamplerManager() override;
|
~SamplerManager();
|
||||||
|
|
||||||
Ref<Sampler> CreateSampler(const SamplerCreateInfo &createInfo);
|
Ref<Sampler> CreateSampler(const SamplerCreateInfo &createInfo);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "manager.h"
|
|
||||||
|
|
||||||
#include "aster/aster.h"
|
#include "aster/aster.h"
|
||||||
#include "aster/core/image_view.h"
|
#include "aster/core/image_view.h"
|
||||||
|
|
||||||
|
|
@ -15,15 +13,16 @@
|
||||||
namespace systems
|
namespace systems
|
||||||
{
|
{
|
||||||
|
|
||||||
template <concepts::ImageView TTo>
|
template <concepts::View TTo, std::derived_from<Image> TFrom>
|
||||||
static Ref<TTo>
|
static Ref<TTo>
|
||||||
CastView(const concepts::ImageViewRef auto &from)
|
CastView(const Ref<View<TFrom>> &from)
|
||||||
{
|
{
|
||||||
assert(TTo::ImageType::Conforms(*from->m_Image.get()));
|
if constexpr (not concepts::ImageInto<TFrom, typename TTo::ImageType>)
|
||||||
return Recast<TTo *>(from.get());
|
assert(TTo::ImageType::FLAGS & from->m_Image->m_Flags_);
|
||||||
|
return std::reinterpret_pointer_cast<TTo>(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <concepts::Image TImage = Image>
|
template <concepts::AnyImage TImage>
|
||||||
struct ViewCreateInfo
|
struct ViewCreateInfo
|
||||||
{
|
{
|
||||||
using ImageType = TImage;
|
using ImageType = TImage;
|
||||||
|
|
@ -70,7 +69,7 @@ struct ViewCreateInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
operator ViewCreateInfo<>() const
|
operator ViewCreateInfo<Image>() const
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
.m_Image = CastImage<Image>(m_Image),
|
.m_Image = CastImage<Image>(m_Image),
|
||||||
|
|
@ -86,19 +85,21 @@ struct ViewCreateInfo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ViewManager final : public Manager<ImageView>
|
class ViewManager final
|
||||||
{
|
{
|
||||||
public:
|
const Device *m_Device;
|
||||||
ViewManager(const Device *device, u32 maxCount);
|
|
||||||
|
|
||||||
template <concepts::ImageView TImageView>
|
public:
|
||||||
|
explicit ViewManager(const Device *device);
|
||||||
|
|
||||||
|
template <concepts::View TImageView>
|
||||||
Ref<TImageView>
|
Ref<TImageView>
|
||||||
CreateView(const ViewCreateInfo<typename TImageView::ImageType> &createInfo)
|
CreateView(const ViewCreateInfo<typename TImageView::ImageType> &createInfo)
|
||||||
{
|
{
|
||||||
return CastView<TImageView>(CreateView(ViewCreateInfo<>(createInfo)));
|
return CastView<TImageView>(CreateView(ViewCreateInfo<Image>(createInfo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<ImageView> CreateView(const ViewCreateInfo<> &createInfo);
|
[[nodiscard]] Ref<ImageView> CreateView(const ViewCreateInfo<Image> &createInfo) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace systems
|
} // namespace systems
|
||||||
|
|
@ -7,19 +7,8 @@
|
||||||
|
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
|
|
||||||
void
|
Buffer::Buffer(const Device *device, const usize size, const vk::BufferUsageFlags bufferUsage,
|
||||||
Buffer::Destroy()
|
const VmaAllocationCreateFlags allocationFlags, const VmaMemoryUsage memoryUsage, const cstr name)
|
||||||
{
|
|
||||||
if (!m_Buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
vmaDestroyBuffer(m_Device->m_Allocator, Take(m_Buffer), m_Allocation);
|
|
||||||
m_Size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUsage,
|
|
||||||
VmaAllocationCreateFlags allocationFlags, VmaMemoryUsage memoryUsage, cstr name)
|
|
||||||
{
|
{
|
||||||
assert(!m_Buffer);
|
assert(!m_Buffer);
|
||||||
|
|
||||||
|
|
@ -42,9 +31,9 @@ Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUs
|
||||||
&allocationCreateInfo, &buffer, &allocation, &allocationInfo));
|
&allocationCreateInfo, &buffer, &allocation, &allocationInfo));
|
||||||
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
|
||||||
|
|
||||||
vk::MemoryPropertyFlags memoryPropertyFlags;
|
// vk::MemoryPropertyFlags memoryPropertyFlags;
|
||||||
vmaGetAllocationMemoryProperties(device->m_Allocator, allocation,
|
// vmaGetAllocationMemoryProperties(device->m_Allocator, allocation, Recast<VkMemoryPropertyFlags
|
||||||
Recast<VkMemoryPropertyFlags *>(&memoryPropertyFlags));
|
// *>(&memoryPropertyFlags));
|
||||||
// TODO: Actually track Host Access
|
// TODO: Actually track Host Access
|
||||||
// bool hostAccessible = Cast<bool>(memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible);
|
// bool hostAccessible = Cast<bool>(memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
|
|
||||||
|
|
@ -52,142 +41,69 @@ Buffer::Allocate(const Device *device, usize size, vk::BufferUsageFlags bufferUs
|
||||||
m_Size = size;
|
m_Size = size;
|
||||||
m_Allocation = allocation;
|
m_Allocation = allocation;
|
||||||
m_Mapped = Cast<u8 *>(allocationInfo.pMappedData);
|
m_Mapped = Cast<u8 *>(allocationInfo.pMappedData);
|
||||||
|
m_Flags = {};
|
||||||
|
if (bufferUsage & vk::BufferUsageFlagBits::eTransferSrc)
|
||||||
|
m_Flags |= FlagBits::eStaging;
|
||||||
|
if (bufferUsage & vk::BufferUsageFlagBits::eIndexBuffer)
|
||||||
|
m_Flags |= FlagBits::eIndex;
|
||||||
|
if (bufferUsage & vk::BufferUsageFlagBits::eIndirectBuffer)
|
||||||
|
m_Flags |= FlagBits::eIndirect;
|
||||||
|
if (bufferUsage & vk::BufferUsageFlagBits::eVertexBuffer)
|
||||||
|
m_Flags |= FlagBits::eVertex;
|
||||||
|
if (bufferUsage & vk::BufferUsageFlagBits::eUniformBuffer)
|
||||||
|
m_Flags |= FlagBits::eUniform;
|
||||||
|
if (bufferUsage & vk::BufferUsageFlagBits::eStorageBuffer)
|
||||||
|
m_Flags |= FlagBits::eStorage;
|
||||||
|
|
||||||
device->SetName(m_Buffer, name);
|
device->SetName(m_Buffer, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Buffer::Buffer(Buffer &&other) noexcept
|
||||||
|
: m_Device{Take(other.m_Device)}
|
||||||
|
, m_Buffer{Take(other.m_Buffer)}
|
||||||
|
, m_Allocation{Take(other.m_Allocation)}
|
||||||
|
, m_Mapped{Take(other.m_Mapped)}
|
||||||
|
, m_Size{Take(other.m_Size)}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer &
|
||||||
|
Buffer::operator=(Buffer &&other) noexcept
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
using std::swap;
|
||||||
|
swap(m_Device, other.m_Device);
|
||||||
|
swap(m_Buffer, other.m_Buffer);
|
||||||
|
swap(m_Allocation, other.m_Allocation);
|
||||||
|
swap(m_Mapped, other.m_Mapped);
|
||||||
|
swap(m_Size, other.m_Size);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::~Buffer()
|
||||||
|
{
|
||||||
|
if (!m_Buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vmaDestroyBuffer(m_Device->m_Allocator, Take(m_Buffer), m_Allocation);
|
||||||
|
m_Size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
uptr
|
uptr
|
||||||
Buffer::GetDeviceAddress(const Device *device) const
|
Buffer::GetDeviceAddress(const Device *device) const
|
||||||
{
|
{
|
||||||
vk::BufferDeviceAddressInfo addressInfo = {.buffer = m_Buffer};
|
const vk::BufferDeviceAddressInfo addressInfo = {.buffer = m_Buffer};
|
||||||
return device->m_Device.getBufferAddress(&addressInfo);
|
return device->m_Device.getBufferAddress(&addressInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Buffer::Write(usize offset, usize size, const void *data)
|
Buffer::Write(const usize offset, const usize size, const void *data) const
|
||||||
{
|
{
|
||||||
assert(IsHostVisible());
|
assert(IsMapped());
|
||||||
|
memcpy(m_Mapped + offset, data, size);
|
||||||
if (!IsMapped())
|
|
||||||
{
|
|
||||||
void *mapped;
|
|
||||||
auto result = Cast<vk::Result>(vmaMapMemory(m_Device->m_Allocator, m_Allocation, &mapped));
|
|
||||||
ERROR_IF(Failed(result), "Memory mapping failed. Cause: {}", result);
|
|
||||||
if (!Failed(result))
|
|
||||||
{
|
|
||||||
m_Mapped = Cast<u8 *>(mapped);
|
|
||||||
memcpy(m_Mapped + offset, data, size);
|
|
||||||
|
|
||||||
vmaUnmapMemory(m_Device->m_Allocator, m_Allocation);
|
|
||||||
m_Mapped = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy(m_Mapped + offset, data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Debug this.
|
// TODO: Debug this.
|
||||||
// auto result = Cast<vk::Result>(vmaCopyMemoryToAllocation(device->m_Allocator, &data, m_Allocation, 0, size));
|
// auto result = Cast<vk::Result>(vmaCopyMemoryToAllocation(device->m_Allocator, &data, m_Allocation, 0, size));
|
||||||
// ERROR_IF(Failed(result), "Writing to buffer failed. Cause: {}", result) THEN_ABORT(result);
|
// ERROR_IF(Failed(result), "Writing to buffer failed. Cause: {}", result) THEN_ABORT(result);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
UniformBuffer::Init(const Device *device, const usize size, const cstr name)
|
|
||||||
{
|
|
||||||
Allocate(device, size, vk::BufferUsageFlagBits::eUniformBuffer,
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
|
||||||
VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StorageBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name)
|
|
||||||
{
|
|
||||||
Init(device, size, hostVisible, false, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StorageBuffer::Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name)
|
|
||||||
{
|
|
||||||
vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer;
|
|
||||||
if (deviceAddress)
|
|
||||||
{
|
|
||||||
usage |= vk::BufferUsageFlagBits::eShaderDeviceAddress;
|
|
||||||
}
|
|
||||||
if (hostVisible)
|
|
||||||
{
|
|
||||||
Allocate(device, size, usage,
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
|
||||||
VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usage |= vk::BufferUsageFlagBits::eTransferDst;
|
|
||||||
Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StorageIndexBuffer::Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name)
|
|
||||||
{
|
|
||||||
vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndexBuffer;
|
|
||||||
if (deviceAddress)
|
|
||||||
{
|
|
||||||
usage |= vk::BufferUsageFlagBits::eShaderDeviceAddress;
|
|
||||||
}
|
|
||||||
if (hostVisible)
|
|
||||||
{
|
|
||||||
Allocate(device, size, usage,
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
|
||||||
VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usage |= vk::BufferUsageFlagBits::eTransferDst;
|
|
||||||
Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
IndirectBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name)
|
|
||||||
{
|
|
||||||
vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndirectBuffer |
|
|
||||||
vk::BufferUsageFlagBits::eShaderDeviceAddress;
|
|
||||||
if (hostVisible)
|
|
||||||
{
|
|
||||||
Allocate(device, size, usage,
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
|
||||||
VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usage |= vk::BufferUsageFlagBits::eTransferDst;
|
|
||||||
Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
VertexBuffer::Init(const Device *device, usize size, cstr name)
|
|
||||||
{
|
|
||||||
Allocate(device, size, vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eTransferDst, 0,
|
|
||||||
VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
IndexBuffer::Init(const Device *device, usize size, cstr name)
|
|
||||||
{
|
|
||||||
Allocate(device, size, vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst, 0,
|
|
||||||
VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StagingBuffer::Init(const Device *device, usize size, cstr name)
|
|
||||||
{
|
|
||||||
Allocate(device, size, vk::BufferUsageFlagBits::eTransferSrc,
|
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
|
||||||
VMA_MEMORY_USAGE_AUTO, name);
|
|
||||||
}
|
}
|
||||||
|
|
@ -7,14 +7,31 @@
|
||||||
|
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
|
|
||||||
void
|
Image &
|
||||||
Image::Destroy()
|
Image::operator=(Image &&other) noexcept
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
using std::swap;
|
||||||
|
swap(m_Device, other.m_Device);
|
||||||
|
swap(m_Image, other.m_Image);
|
||||||
|
swap(m_Allocation, other.m_Allocation);
|
||||||
|
swap(m_Extent, other.m_Extent);
|
||||||
|
swap(m_Format, other.m_Format);
|
||||||
|
swap(m_EmptyPadding_, other.m_EmptyPadding_);
|
||||||
|
swap(m_Flags_, other.m_Flags_);
|
||||||
|
swap(m_LayerCount, other.m_LayerCount);
|
||||||
|
swap(m_MipLevels, other.m_MipLevels);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::~Image()
|
||||||
{
|
{
|
||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vmaDestroyImage(m_Device->m_Allocator, Take(m_Image), m_Allocation);
|
vmaDestroyImage(m_Device->m_Allocator, Take(m_Image), m_Allocation);
|
||||||
m_Flags_ = 0;
|
m_Flags_ = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -431,4 +448,29 @@ Image::DestroyView(const vk::ImageView imageView) const
|
||||||
// m_LayerCount = 6;
|
// m_LayerCount = 6;
|
||||||
//
|
//
|
||||||
// device->SetName(m_Image, name);
|
// device->SetName(m_Image, name);
|
||||||
// }
|
// }
|
||||||
|
Image::Image(Image &&other) noexcept
|
||||||
|
: m_Device{Take(other.m_Device)}
|
||||||
|
, m_Image{Take(other.m_Image)}
|
||||||
|
, m_Allocation{Take(other.m_Allocation)}
|
||||||
|
, m_Extent{other.m_Extent}
|
||||||
|
, m_Format{other.m_Format}
|
||||||
|
, m_EmptyPadding_{other.m_EmptyPadding_}
|
||||||
|
, m_Flags_{other.m_Flags_}
|
||||||
|
, m_LayerCount{other.m_LayerCount}
|
||||||
|
, m_MipLevels{other.m_MipLevels}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::Image(const Device *device, const vk::Image image, const VmaAllocation allocation, const vk::Extent3D extent,
|
||||||
|
const vk::Format format, const Flags flags, const u8 layerCount, const u8 mipLevels)
|
||||||
|
: m_Device{device}
|
||||||
|
, m_Image{image}
|
||||||
|
, m_Allocation{allocation}
|
||||||
|
, m_Extent{extent}
|
||||||
|
, m_Format{format}
|
||||||
|
, m_Flags_{flags}
|
||||||
|
, m_LayerCount{layerCount}
|
||||||
|
, m_MipLevels{mipLevels}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -7,8 +7,7 @@
|
||||||
|
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
|
|
||||||
void
|
Sampler::~Sampler()
|
||||||
Sampler::Destroy()
|
|
||||||
{
|
{
|
||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
return;
|
return;
|
||||||
|
|
@ -16,10 +15,25 @@ Sampler::Destroy()
|
||||||
m_Device->m_Device.destroy(Take(m_Sampler), nullptr);
|
m_Device->m_Device.destroy(Take(m_Sampler), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
Sampler::Sampler(const Device *device, const vk::SamplerCreateInfo &samplerCreateInfo, cstr name)
|
||||||
Sampler::Init(const Device *device, const vk::SamplerCreateInfo &samplerCreateInfo, cstr name)
|
|
||||||
{
|
{
|
||||||
m_Device = device;
|
m_Device = device;
|
||||||
const auto result = device->m_Device.createSampler(&samplerCreateInfo, nullptr, &m_Sampler);
|
const auto result = device->m_Device.createSampler(&samplerCreateInfo, nullptr, &m_Sampler);
|
||||||
ERROR_IF(Failed(result), "Could not create a sampler {}", name ? name : "<unnamed>") THEN_ABORT(-1);
|
ERROR_IF(Failed(result), "Could not create a sampler {}", name ? name : "<unnamed>") THEN_ABORT(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sampler &
|
||||||
|
Sampler::operator=(Sampler &&other) noexcept
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
using std::swap;
|
||||||
|
swap(m_Device, other.m_Device);
|
||||||
|
swap(m_Sampler, other.m_Sampler);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sampler::Sampler(Sampler &&other) noexcept: m_Device{other.m_Device}
|
||||||
|
, m_Sampler{Take(other.m_Sampler)}
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,6 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
target_sources(aster_core
|
target_sources(aster_core
|
||||||
PRIVATE
|
PRIVATE
|
||||||
"manager.cpp"
|
|
||||||
"buffer_manager.cpp"
|
"buffer_manager.cpp"
|
||||||
"image_manager.cpp"
|
"image_manager.cpp"
|
||||||
"view_manager.cpp"
|
"view_manager.cpp"
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,9 @@
|
||||||
|
|
||||||
using namespace systems;
|
using namespace systems;
|
||||||
|
|
||||||
Ref<Buffer>
|
Ref<StorageBuffer>
|
||||||
BufferManager::CreateStorageBuffer(const usize size, const cstr name)
|
BufferManager::CreateStorageBuffer(const usize size, const cstr name) const
|
||||||
{
|
{
|
||||||
auto object = Alloc();
|
|
||||||
|
|
||||||
// TODO: Storage and Index buffer are set.
|
// TODO: Storage and Index buffer are set.
|
||||||
// This is hacky and should be improved.
|
// This is hacky and should be improved.
|
||||||
constexpr vk::BufferUsageFlags usage =
|
constexpr vk::BufferUsageFlags usage =
|
||||||
|
|
@ -21,41 +19,132 @@ BufferManager::CreateStorageBuffer(const usize size, const cstr name)
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
|
||||||
VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||||
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
||||||
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name);
|
return std::make_shared<StorageBuffer>(Buffer{m_Device, size, usage, createFlags, memoryUsage, name});
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Buffer>
|
Ref<UniformBuffer>
|
||||||
BufferManager::CreateUniformBuffer(const usize size, const cstr name)
|
BufferManager::CreateUniformBuffer(const usize size, const cstr name) const
|
||||||
{
|
{
|
||||||
auto object = Alloc();
|
|
||||||
|
|
||||||
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eUniformBuffer;
|
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eUniformBuffer;
|
||||||
constexpr VmaAllocationCreateFlags createFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
constexpr VmaAllocationCreateFlags createFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
|
||||||
VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||||
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
||||||
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name);
|
return std::make_shared<UniformBuffer>(Buffer{m_Device, size, usage, createFlags, memoryUsage, name});
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager<Buffer>::Handle
|
Ref<StagingBuffer>
|
||||||
BufferManager::CreateStagingBuffer(const usize size, const cstr name)
|
BufferManager::CreateStagingBuffer(const usize size, const cstr name) const
|
||||||
{
|
{
|
||||||
auto object = Alloc();
|
|
||||||
|
|
||||||
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eTransferSrc;
|
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eTransferSrc;
|
||||||
constexpr VmaAllocationCreateFlags createFlags =
|
constexpr VmaAllocationCreateFlags createFlags =
|
||||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||||
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
|
||||||
object->Allocate(m_Device, size, usage, createFlags, memoryUsage, name);
|
return std::make_shared<StagingBuffer>(Buffer{m_Device, size, usage, createFlags, memoryUsage, name});
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferManager::BufferManager(const Device *device, const u32 maxCount)
|
//
|
||||||
: Manager{device, maxCount}
|
// void
|
||||||
|
// UniformBuffer::Init(const Device *device, const usize size, const cstr name)
|
||||||
|
//{
|
||||||
|
// Allocate(device, size, vk::BufferUsageFlagBits::eUniformBuffer,
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||||
|
// VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// void
|
||||||
|
// StorageBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name)
|
||||||
|
//{
|
||||||
|
// Init(device, size, hostVisible, false, name);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// void
|
||||||
|
// StorageBuffer::Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name)
|
||||||
|
//{
|
||||||
|
// vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer;
|
||||||
|
// if (deviceAddress)
|
||||||
|
// {
|
||||||
|
// usage |= vk::BufferUsageFlagBits::eShaderDeviceAddress;
|
||||||
|
// }
|
||||||
|
// if (hostVisible)
|
||||||
|
// {
|
||||||
|
// Allocate(device, size, usage,
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||||
|
// VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// usage |= vk::BufferUsageFlagBits::eTransferDst;
|
||||||
|
// Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// void
|
||||||
|
// StorageIndexBuffer::Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name)
|
||||||
|
//{
|
||||||
|
// vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndexBuffer;
|
||||||
|
// if (deviceAddress)
|
||||||
|
// {
|
||||||
|
// usage |= vk::BufferUsageFlagBits::eShaderDeviceAddress;
|
||||||
|
// }
|
||||||
|
// if (hostVisible)
|
||||||
|
// {
|
||||||
|
// Allocate(device, size, usage,
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||||
|
// VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// usage |= vk::BufferUsageFlagBits::eTransferDst;
|
||||||
|
// Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// void
|
||||||
|
// IndirectBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name)
|
||||||
|
//{
|
||||||
|
// vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndirectBuffer |
|
||||||
|
// vk::BufferUsageFlagBits::eShaderDeviceAddress;
|
||||||
|
// if (hostVisible)
|
||||||
|
// {
|
||||||
|
// Allocate(device, size, usage,
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||||
|
// VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// usage |= vk::BufferUsageFlagBits::eTransferDst;
|
||||||
|
// Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// void
|
||||||
|
// VertexBuffer::Init(const Device *device, usize size, cstr name)
|
||||||
|
//{
|
||||||
|
// Allocate(device, size, vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eTransferDst, 0,
|
||||||
|
// VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// void
|
||||||
|
// IndexBuffer::Init(const Device *device, usize size, cstr name)
|
||||||
|
//{
|
||||||
|
// Allocate(device, size, vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst, 0,
|
||||||
|
// VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// void
|
||||||
|
// StagingBuffer::Init(const Device *device, usize size, cstr name)
|
||||||
|
//{
|
||||||
|
// Allocate(device, size, vk::BufferUsageFlagBits::eTransferSrc,
|
||||||
|
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||||
|
// VMA_MEMORY_USAGE_AUTO, name);
|
||||||
|
//}
|
||||||
|
|
||||||
|
BufferManager::BufferManager(const Device *device)
|
||||||
|
: m_Device{device}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -25,6 +25,11 @@ constexpr vk::ImageUsageFlags COLOR_ATTACHMENT =
|
||||||
constexpr vk::ImageUsageFlags DEPTH_STENCIL_ATTACHMENT = vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
constexpr vk::ImageUsageFlags DEPTH_STENCIL_ATTACHMENT = vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||||
} // namespace usage_flags
|
} // namespace usage_flags
|
||||||
|
|
||||||
|
ImageManager::ImageManager(const Device *device)
|
||||||
|
: m_Device{device}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Ref<Image>
|
Ref<Image>
|
||||||
ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo)
|
ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo)
|
||||||
{
|
{
|
||||||
|
|
@ -33,29 +38,27 @@ ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo)
|
||||||
.usage = VMA_MEMORY_USAGE_AUTO,
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImage image;
|
VkImage rawImage;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
||||||
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
&allocationCreateInfo, &image, &allocation, nullptr));
|
&allocationCreateInfo, &rawImage, &allocation, nullptr));
|
||||||
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
auto object = Alloc();
|
vk::Image image = rawImage;
|
||||||
object->m_Image = image;
|
|
||||||
object->m_Allocation = allocation;
|
u8 layerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
||||||
object->m_Extent = imageCreateInfo.extent;
|
u8 mipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
||||||
object->m_Format = imageCreateInfo.format;
|
Image::Flags flags = {};
|
||||||
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
|
||||||
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
|
||||||
object->m_Flags_ = {};
|
|
||||||
if (createInfo.m_IsSampled)
|
if (createInfo.m_IsSampled)
|
||||||
object->m_Flags_ |= Image::SAMPLED_BIT;
|
flags |= Image::FlagBits::eSampled;
|
||||||
if (createInfo.m_IsStorage)
|
if (createInfo.m_IsStorage)
|
||||||
object->m_Flags_ |= Image::STORAGE_BIT;
|
flags |= Image::FlagBits::eStorage;
|
||||||
|
|
||||||
m_Device->SetName(object->m_Image, createInfo.m_Name);
|
m_Device->SetName(image, createInfo.m_Name);
|
||||||
|
|
||||||
return object;
|
return std::make_shared<Image>(m_Device, image, allocation, imageCreateInfo.extent, imageCreateInfo.format, flags,
|
||||||
|
layerCount, mipLevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<ImageCube>
|
Ref<ImageCube>
|
||||||
|
|
@ -66,29 +69,27 @@ ImageManager::CreateTextureCube(const TextureCubeCreateInfo &createInfo)
|
||||||
.usage = VMA_MEMORY_USAGE_AUTO,
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImage image;
|
VkImage rawImage;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
||||||
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
&allocationCreateInfo, &image, &allocation, nullptr));
|
&allocationCreateInfo, &rawImage, &allocation, nullptr));
|
||||||
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
auto object = Alloc();
|
vk::Image image = rawImage;
|
||||||
object->m_Image = image;
|
|
||||||
object->m_Allocation = allocation;
|
u8 layerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
||||||
object->m_Extent = imageCreateInfo.extent;
|
u8 mipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
||||||
object->m_Format = imageCreateInfo.format;
|
Image::Flags flags = Image::FlagBits::eCube;
|
||||||
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
|
||||||
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
|
||||||
object->m_Flags_ = Image::CUBE_BIT;
|
|
||||||
if (createInfo.m_IsSampled)
|
if (createInfo.m_IsSampled)
|
||||||
object->m_Flags_ |= Image::SAMPLED_BIT;
|
flags |= Image::FlagBits::eSampled;
|
||||||
if (createInfo.m_IsStorage)
|
if (createInfo.m_IsStorage)
|
||||||
object->m_Flags_ |= Image::STORAGE_BIT;
|
flags |= Image::FlagBits::eStorage;
|
||||||
|
|
||||||
m_Device->SetName(object->m_Image, createInfo.m_Name);
|
m_Device->SetName(image, createInfo.m_Name);
|
||||||
|
|
||||||
return CastImage<ImageCube>(object);
|
return CastImage<ImageCube>(std::make_shared<Image>(m_Device, image, allocation, imageCreateInfo.extent,
|
||||||
|
imageCreateInfo.format, flags, layerCount, mipLevels));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Image>
|
Ref<Image>
|
||||||
|
|
@ -99,24 +100,22 @@ ImageManager::CreateAttachment(const AttachmentCreateInfo &createInfo)
|
||||||
.usage = VMA_MEMORY_USAGE_AUTO,
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImage image;
|
VkImage rawImage;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
||||||
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
&allocationCreateInfo, &image, &allocation, nullptr));
|
&allocationCreateInfo, &rawImage, &allocation, nullptr));
|
||||||
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
auto object = Alloc();
|
vk::Image image = rawImage;
|
||||||
object->m_Image = image;
|
|
||||||
object->m_Allocation = allocation;
|
|
||||||
object->m_Extent = imageCreateInfo.extent;
|
|
||||||
object->m_Format = imageCreateInfo.format;
|
|
||||||
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
|
||||||
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
|
||||||
|
|
||||||
m_Device->SetName(object->m_Image, createInfo.m_Name);
|
u8 layerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
||||||
|
u8 mipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
||||||
|
|
||||||
return object;
|
m_Device->SetName(image, createInfo.m_Name);
|
||||||
|
|
||||||
|
return std::make_shared<Image>(m_Device, image, allocation, imageCreateInfo.extent, imageCreateInfo.format,
|
||||||
|
Image::Flags{}, layerCount, mipLevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Image>
|
Ref<Image>
|
||||||
|
|
@ -127,24 +126,22 @@ ImageManager::CreateDepthStencilImage(const DepthStencilImageCreateInfo &createI
|
||||||
.usage = VMA_MEMORY_USAGE_AUTO,
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImage image;
|
VkImage rawImage;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
|
||||||
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
|
||||||
&allocationCreateInfo, &image, &allocation, nullptr));
|
&allocationCreateInfo, &rawImage, &allocation, nullptr));
|
||||||
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
|
||||||
|
|
||||||
auto object = Alloc();
|
vk::Image image = rawImage;
|
||||||
object->m_Image = image;
|
|
||||||
object->m_Allocation = allocation;
|
|
||||||
object->m_Extent = imageCreateInfo.extent;
|
|
||||||
object->m_Format = imageCreateInfo.format;
|
|
||||||
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
|
||||||
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
|
||||||
|
|
||||||
m_Device->SetName(object->m_Image, createInfo.m_Name);
|
u8 layerCount = Cast<u8>(imageCreateInfo.arrayLayers);
|
||||||
|
u8 mipLevels = Cast<u8>(imageCreateInfo.mipLevels);
|
||||||
|
|
||||||
return object;
|
m_Device->SetName(image, createInfo.m_Name);
|
||||||
|
|
||||||
|
return std::make_shared<Image>(m_Device, image, allocation, imageCreateInfo.extent, imageCreateInfo.format,
|
||||||
|
Image::Flags{}, layerCount, mipLevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::ImageCreateInfo
|
vk::ImageCreateInfo
|
||||||
|
|
@ -236,9 +233,4 @@ ToImageCreateInfo(const DepthStencilImageCreateInfo &createInfo)
|
||||||
.arrayLayers = 1,
|
.arrayLayers = 1,
|
||||||
.usage = usage,
|
.usage = usage,
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
ImageManager::ImageManager(const Device *device, const u32 maxCount)
|
|
||||||
: Manager{device, maxCount}
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
// =============================================
|
|
||||||
// Aster: manager.cpp
|
|
||||||
// Copyright (c) 2020-2025 Anish Bhobe
|
|
||||||
// =============================================
|
|
||||||
|
|
||||||
#include "systems/manager.h"
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
using namespace systems;
|
using namespace systems;
|
||||||
|
|
||||||
SamplerManager::SamplerManager(const Device *device, const u32 maxCount)
|
SamplerManager::SamplerManager(const Device *device)
|
||||||
: Manager{device, maxCount}
|
: m_Device{device}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,14 +24,12 @@ SamplerManager::CreateSampler(const SamplerCreateInfo &createInfo)
|
||||||
{
|
{
|
||||||
auto vkCreateInfo = Cast<vk::SamplerCreateInfo>(createInfo);
|
auto vkCreateInfo = Cast<vk::SamplerCreateInfo>(createInfo);
|
||||||
|
|
||||||
if (const auto iter = m_HashToSamplerIdx.find(vkCreateInfo); iter != m_HashToSamplerIdx.end())
|
if (const auto iter = m_HashToSamplerIdx.find(vkCreateInfo); iter != m_HashToSamplerIdx.end() && !iter->second.expired())
|
||||||
{
|
{
|
||||||
return iter->second;
|
return iter->second.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto object = Alloc();
|
auto object = std::make_shared<Sampler>(m_Device, vkCreateInfo, createInfo.m_Name ? createInfo.m_Name : nullptr);
|
||||||
|
|
||||||
object->Init(m_Device, vkCreateInfo, createInfo.m_Name ? createInfo.m_Name : nullptr);
|
|
||||||
m_HashToSamplerIdx.emplace(vkCreateInfo, object);
|
m_HashToSamplerIdx.emplace(vkCreateInfo, object);
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,13 @@
|
||||||
|
|
||||||
using namespace systems;
|
using namespace systems;
|
||||||
|
|
||||||
ViewManager::ViewManager(const Device *device, const u32 maxCount)
|
ViewManager::ViewManager(const Device *device)
|
||||||
: Manager{device, maxCount}
|
: m_Device{device}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<ImageView>
|
Ref<ImageView>
|
||||||
ViewManager::CreateView(const ViewCreateInfo<> &createInfo)
|
ViewManager::CreateView(const ViewCreateInfo<Image> &createInfo) const
|
||||||
{
|
{
|
||||||
const auto layerCount = createInfo.GetLayerCount();
|
const auto layerCount = createInfo.GetLayerCount();
|
||||||
const auto mipCount = createInfo.GetMipLevelCount();
|
const auto mipCount = createInfo.GetMipLevelCount();
|
||||||
|
|
@ -32,14 +32,6 @@ ViewManager::CreateView(const ViewCreateInfo<> &createInfo)
|
||||||
|
|
||||||
m_Device->SetName(view, createInfo.m_Name);
|
m_Device->SetName(view, createInfo.m_Name);
|
||||||
|
|
||||||
auto object = Alloc();
|
return std::make_shared<ImageView>(createInfo.m_Image, view, createInfo.m_Image->m_Extent, createInfo.m_BaseLayer,
|
||||||
object->m_Image = createInfo.m_Image;
|
layerCount, createInfo.m_BaseMipLevel, mipCount);
|
||||||
object->m_View = view;
|
|
||||||
object->m_Extent = createInfo.m_Image->m_Extent;
|
|
||||||
object->m_BaseLayer = createInfo.m_BaseLayer;
|
|
||||||
object->m_LayerCount = layerCount;
|
|
||||||
object->m_BaseMipLevel = createInfo.m_BaseMipLevel;
|
|
||||||
object->m_MipLevelCount = mipCount;
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +131,7 @@ main(int, char **)
|
||||||
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
||||||
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
|
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
|
||||||
|
|
||||||
systems::ResourceManager resourceManager{&device, 12, 12, 1, 12};
|
systems::ResourceManager resourceManager{&device};
|
||||||
|
|
||||||
systems::CommitManager commitManager{&device, 12, 12, 12, resourceManager.Samplers().CreateSampler({})};
|
systems::CommitManager commitManager{&device, 12, 12, 12, resourceManager.Samplers().CreateSampler({})};
|
||||||
|
|
||||||
|
|
@ -221,10 +221,9 @@ main(int, char **)
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
StagingBuffer imageStaging;
|
|
||||||
|
|
||||||
imageStaging.Init(&device, imageFile.GetSize(), "Image Staging");
|
auto imageStaging = resourceManager.Buffers().CreateStagingBuffer(imageFile.GetSize(), "Image Staging");
|
||||||
imageStaging.Write(0, imageFile.GetSize(), imageFile.m_Data);
|
imageStaging->Write(0, imageFile.GetSize(), imageFile.m_Data);
|
||||||
|
|
||||||
vk::ImageMemoryBarrier2 imageReadyToWrite = {
|
vk::ImageMemoryBarrier2 imageReadyToWrite = {
|
||||||
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
|
@ -297,7 +296,7 @@ main(int, char **)
|
||||||
.imageOffset = {},
|
.imageOffset = {},
|
||||||
.imageExtent = {imageFile.m_Width, imageFile.m_Height, 1},
|
.imageExtent = {imageFile.m_Width, imageFile.m_Height, 1},
|
||||||
};
|
};
|
||||||
copyBuffer.copyBufferToImage(imageStaging.m_Buffer, crate->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
|
copyBuffer.copyBufferToImage(imageStaging->m_Buffer, crate->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
|
||||||
&imageCopy);
|
&imageCopy);
|
||||||
|
|
||||||
copyBuffer.pipelineBarrier2(&imageReadyToReadDependency);
|
copyBuffer.pipelineBarrier2(&imageReadyToReadDependency);
|
||||||
|
|
@ -318,7 +317,6 @@ main(int, char **)
|
||||||
AbortIfFailedM(device.m_Device.resetCommandPool(copyPool, {}), "Couldn't reset command pool.");
|
AbortIfFailedM(device.m_Device.resetCommandPool(copyPool, {}), "Couldn't reset command pool.");
|
||||||
|
|
||||||
device.m_Device.destroy(fence, nullptr);
|
device.m_Device.destroy(fence, nullptr);
|
||||||
imageStaging.Destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ubo = resourceManager.Buffers().CreateStorageBuffer(sizeof camera, "Camera UBO");
|
auto ubo = resourceManager.Buffers().CreateStorageBuffer(sizeof camera, "Camera UBO");
|
||||||
|
|
@ -426,7 +424,6 @@ main(int, char **)
|
||||||
{
|
{
|
||||||
Time::Update();
|
Time::Update();
|
||||||
commitManager.Update();
|
commitManager.Update();
|
||||||
resourceManager.Update();
|
|
||||||
|
|
||||||
camera.m_Model *= rotate(mat4{1.0f}, Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f));
|
camera.m_Model *= rotate(mat4{1.0f}, Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f));
|
||||||
ubo->Write(0, sizeof camera, &camera);
|
ubo->Write(0, sizeof camera, &camera);
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,9 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
|
||||||
|
|
||||||
auto *pDevice = m_CommitManager->m_Device;
|
auto *pDevice = m_CommitManager->m_Device;
|
||||||
|
|
||||||
StagingBuffer stagingBuffer;
|
auto stagingBuffer =
|
||||||
stagingBuffer.Init(pDevice, (sizeof *data) * x * y * 4, "HDR Staging Buffer");
|
m_ResourceManager->Buffers().CreateStagingBuffer((sizeof *data) * x * y * 4, "HDR Staging Buffer");
|
||||||
stagingBuffer.Write(0, stagingBuffer.m_Size, data);
|
stagingBuffer->Write(0, stagingBuffer->m_Size, data);
|
||||||
|
|
||||||
stbi_image_free(data);
|
stbi_image_free(data);
|
||||||
|
|
||||||
|
|
@ -98,7 +98,7 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
|
||||||
.imageExtent = texture->m_Extent,
|
.imageExtent = texture->m_Extent,
|
||||||
};
|
};
|
||||||
vk::CopyBufferToImageInfo2 stagingInfo = {
|
vk::CopyBufferToImageInfo2 stagingInfo = {
|
||||||
.srcBuffer = stagingBuffer.m_Buffer,
|
.srcBuffer = stagingBuffer->m_Buffer,
|
||||||
.dstImage = texture->GetImage(),
|
.dstImage = texture->GetImage(),
|
||||||
.dstImageLayout = vk::ImageLayout::eTransferDstOptimal,
|
.dstImageLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.regionCount = 1,
|
.regionCount = 1,
|
||||||
|
|
@ -194,8 +194,6 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
|
||||||
|
|
||||||
AbortIfFailed(pDevice->m_Device.resetCommandPool(m_CommandPool, {}));
|
AbortIfFailed(pDevice->m_Device.resetCommandPool(m_CommandPool, {}));
|
||||||
|
|
||||||
stagingBuffer.Destroy();
|
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref<Texture> &textureView
|
||||||
vk::ImageLayout finalLayout, vk::PipelineStageFlags2 prevStage, vk::PipelineStageFlags2 finalStage);
|
vk::ImageLayout finalLayout, vk::PipelineStageFlags2 prevStage, vk::PipelineStageFlags2 finalStage);
|
||||||
|
|
||||||
void
|
void
|
||||||
GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageRef auto &texture, vk::ImageLayout initialLayout,
|
GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::ImageRefTo<Texture> auto &texture, vk::ImageLayout initialLayout,
|
||||||
vk::ImageLayout finalLayout,
|
vk::ImageLayout finalLayout,
|
||||||
vk::PipelineStageFlags2 prevStage = vk::PipelineStageFlagBits2::eAllCommands,
|
vk::PipelineStageFlags2 prevStage = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
vk::PipelineStageFlags2 finalStage = vk::PipelineStageFlagBits2::eAllCommands)
|
vk::PipelineStageFlags2 finalStage = vk::PipelineStageFlagBits2::eAllCommands)
|
||||||
|
|
@ -149,7 +149,7 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageRef auto
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageViewRef auto &texture,
|
GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::ViewRefTo<Texture> auto &texture,
|
||||||
vk::ImageLayout initialLayout, vk::ImageLayout finalLayout,
|
vk::ImageLayout initialLayout, vk::ImageLayout finalLayout,
|
||||||
vk::PipelineStageFlags2 prevStage = vk::PipelineStageFlagBits2::eAllCommands,
|
vk::PipelineStageFlags2 prevStage = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
vk::PipelineStageFlags2 finalStage = vk::PipelineStageFlagBits2::eAllCommands)
|
vk::PipelineStageFlags2 finalStage = vk::PipelineStageFlagBits2::eAllCommands)
|
||||||
|
|
@ -157,5 +157,3 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageViewRef a
|
||||||
GenerateMipMaps(commandBuffer, systems::CastImage<Texture>(texture->m_Image), initialLayout, finalLayout, prevStage,
|
GenerateMipMaps(commandBuffer, systems::CastImage<Texture>(texture->m_Image), initialLayout, finalLayout, prevStage,
|
||||||
finalStage);
|
finalStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(concepts::SampledImageRef<Ref<Texture>>);
|
|
||||||
|
|
@ -178,7 +178,7 @@ main(int, char **)
|
||||||
vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
||||||
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
|
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
|
||||||
|
|
||||||
systems::ResourceManager resourceManager = {&device, 1000, 1000, 10, 1000};
|
auto resourceManager = systems::ResourceManager{&device};
|
||||||
systems::CommitManager commitManager = {&device, 1000, 1000, 1000,
|
systems::CommitManager commitManager = {&device, 1000, 1000, 1000,
|
||||||
resourceManager.Samplers().CreateSampler({.m_Name = "Default Sampler"})};
|
resourceManager.Samplers().CreateSampler({.m_Name = "Default Sampler"})};
|
||||||
|
|
||||||
|
|
@ -434,7 +434,6 @@ main(int, char **)
|
||||||
{
|
{
|
||||||
Time::Update();
|
Time::Update();
|
||||||
commitManager.Update();
|
commitManager.Update();
|
||||||
resourceManager.Update();
|
|
||||||
|
|
||||||
gui::StartBuild();
|
gui::StartBuild();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
add_subdirectory("00_util")
|
add_subdirectory("00_util")
|
||||||
add_subdirectory("01_triangle")
|
# add_subdirectory("01_triangle")
|
||||||
add_subdirectory("02_box")
|
add_subdirectory("02_box")
|
||||||
add_subdirectory("03_model_render")
|
add_subdirectory("03_model_render")
|
||||||
# add_subdirectory("04_scenes")
|
# add_subdirectory("04_scenes")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue