[WIP] Separated ImageViews.

This commit is contained in:
Anish Bhobe 2025-04-01 08:54:30 +02:00
parent 73c96dc56b
commit 3ab9d838fa
19 changed files with 477 additions and 250 deletions

View File

@ -39,8 +39,8 @@ struct Image
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::ImageView m_View = nullptr;
vk::Extent3D m_Extent; vk::Extent3D m_Extent;
vk::Format m_Format;
std::atomic<u32> m_RefCount; std::atomic<u32> m_RefCount;
u8 m_EmptyPadding_ = 0; u8 m_EmptyPadding_ = 0;
u8 m_Flags_ = 0; u8 m_Flags_ = 0;
@ -112,6 +112,8 @@ struct Image
{ {
return true; return true;
} }
void DestroyView(vk::ImageView imageView) const;
}; };
namespace concepts namespace concepts
@ -132,8 +134,8 @@ concept SampledImageRef = Derefencable<T> and SampledImage<DereferencesTo<T>>;
template <typename T> template <typename T>
concept ImageCube = requires() { concept ImageCube = requires() {
{ T::CUBED } -> std::convertible_to<bool>; { T::CUBE } -> std::convertible_to<bool>;
} and T::CUBED and Image<T>; } and T::CUBE and Image<T>;
template <typename T> template <typename T>
concept ImageCubeRef = Derefencable<T> and ImageCube<DereferencesTo<T>>; concept ImageCubeRef = Derefencable<T> and ImageCube<DereferencesTo<T>>;

View File

@ -13,14 +13,97 @@ struct View
{ {
using ImageType = TImage; using ImageType = TImage;
Ref<ImageType> m_Image; const Device *m_Device;
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; std::atomic<u32> m_RefCount;
u8 m_EmptyPadding_ = 0; u8 m_BaseLayer = 0;
u8 m_Flags_ = 0;
u8 m_LayerCount = 0; u8 m_LayerCount = 0;
u8 m_MipLevels = 0; u8 m_BaseMipLevel = 0;
u8 m_MipLevelCount = 0;
[[nodiscard]] vk::Image
GetImage() const
{
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
IsValid() const
{
return m_Image;
}
void
Destroy()
{
if (!IsValid())
return;
m_Image->DestroyView(Take(m_View));
}
}; };
using ImageView = View<>; struct ImageView : View<> {};
struct ImageCubeView : View<ImageCube> {};
struct TextureView : View<Texture> {};
struct TextureCubeView : View<TextureCube> {};
struct StorageImageView : View<StorageImage> {};
struct StorageTextureView : View<StorageTexture> {};
struct StorageTextureCubeView : View<StorageTextureCube> {};
namespace concepts
{
template <typename TView>
concept View = std::derived_from<TView, ::View<typename TView::ImageType>>;
template <typename T>
concept ViewRef = Derefencable<T> and View<DereferencesTo<T>>;
template <typename T>
concept ImageView = View<T> and Image<typename T::ImageType>;
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

View File

@ -13,11 +13,12 @@ struct Device;
struct Sampler struct Sampler
{ {
const Device *m_Device = nullptr;
vk::Sampler m_Sampler = nullptr; vk::Sampler m_Sampler = nullptr;
std::atomic<u32> m_RefCount = 0; std::atomic<u32> m_RefCount = 0;
void Init(const Device *device, const vk::SamplerCreateInfo &samplerCreateInfo, cstr name); void Init(const Device *device, const vk::SamplerCreateInfo &samplerCreateInfo, cstr name);
void Destroy(const Device *device); void Destroy();
void void
AddRef() AddRef()

View File

@ -17,6 +17,7 @@
#include "EASTL/bonus/fixed_ring_buffer.h" #include "EASTL/bonus/fixed_ring_buffer.h"
#include "resource.h" #include "resource.h"
#include "aster/core/image_view.h"
namespace systems namespace systems
{ {
@ -226,27 +227,29 @@ class CommitManager
ResId<Buffer> CommitBuffer(const Ref<Buffer> &buffer); ResId<Buffer> CommitBuffer(const Ref<Buffer> &buffer);
// Commit Storage Images // Commit Storage Images
ResId<StorageImage> CommitStorageImage(const concepts::StorageImageRef auto &image) ResId<StorageImageView> CommitStorageImage(const concepts::StorageImageViewRef auto &image)
{ {
return CommitStorageImage(CastImage<StorageImage>(image)); return CommitStorageImage(CastView<StorageImageView>(image));
} }
ResId<StorageImage> CommitStorageImage(const Ref<StorageImage> &image); ResId<StorageImageView> CommitStorageImage(const Ref<StorageImageView> &image);
// Sampled Images // Sampled Images
ResId<Texture> ResId<TextureView>
CommitTexture(const concepts::SampledImageRef auto &image, const Ref<Sampler> &sampler) CommitTexture(const concepts::SampledImageViewRef auto &image, const Ref<Sampler> &sampler)
{ {
return CommitTexture(CastImage<Texture>(image), sampler); return CommitTexture(CastView<TextureView>(image), sampler);
} }
ResId<Texture> ResId<TextureView>
CommitTexture(const concepts::SampledImageRef auto &image) CommitTexture(const concepts::SampledImageViewRef auto &image)
{ {
return CommitTexture(CastImage<Texture>(image)); return CommitTexture(CastView<TextureView>(image));
} }
ResId<Texture> CommitTexture(const Ref<Texture> &handle); static_assert(concepts::SampledImageViewRef<Ref<TextureView>>);
ResId<Texture> CommitTexture(const Ref<Texture> &image, const Ref<Sampler> &sampler);
ResId<TextureView> CommitTexture(const Ref<TextureView> &handle);
ResId<TextureView> CommitTexture(const Ref<TextureView> &image, const Ref<Sampler> &sampler);
void Update(); void Update();
@ -256,14 +259,14 @@ class CommitManager
return m_Buffers.GetHandle(id); return m_Buffers.GetHandle(id);
} }
Ref<Texture> Ref<TextureView>
FetchHandle(const ResId<Texture> &id) FetchHandle(const ResId<TextureView> &id)
{ {
return m_Images.GetHandle(id); return m_Images.GetHandle(id);
} }
Ref<StorageImage> Ref<StorageImageView>
FetchHandle(const ResId<StorageImage> &id) FetchHandle(const ResId<StorageImageView> &id)
{ {
return m_StorageImages.GetHandle(id); return m_StorageImages.GetHandle(id);
} }
@ -296,8 +299,8 @@ class CommitManager
constexpr static u8 STORAGE_IMAGE_BINDING_INDEX = 0x2; constexpr static u8 STORAGE_IMAGE_BINDING_INDEX = 0x2;
HandleMapper<Buffer> m_Buffers; HandleMapper<Buffer> m_Buffers;
HandleMapper<Texture> m_Images; HandleMapper<TextureView> m_Images;
HandleMapper<StorageImage> m_StorageImages; HandleMapper<StorageImageView> m_StorageImages;
Ref<Sampler> m_DefaultSampler; Ref<Sampler> m_DefaultSampler;
@ -307,8 +310,8 @@ class CommitManager
static CommitManager *m_Instance; static CommitManager *m_Instance;
friend ResId<Buffer>; friend ResId<Buffer>;
friend ResId<Texture>; friend ResId<TextureView>;
friend ResId<StorageImage>; friend ResId<StorageImageView>;
void void
AddRef(const ResId<Buffer> &handle) AddRef(const ResId<Buffer> &handle)
@ -316,12 +319,12 @@ class CommitManager
m_Buffers.AddRef(handle); m_Buffers.AddRef(handle);
} }
void void
AddRef(const ResId<Texture> &handle) AddRef(const ResId<TextureView> &handle)
{ {
m_Images.AddRef(handle); m_Images.AddRef(handle);
} }
void void
AddRef(const ResId<StorageImage> &handle) AddRef(const ResId<StorageImageView> &handle)
{ {
m_StorageImages.AddRef(handle); m_StorageImages.AddRef(handle);
} }
@ -332,12 +335,12 @@ class CommitManager
m_Buffers.Release(handle); m_Buffers.Release(handle);
} }
void void
Release(const ResId<Texture> &handle) Release(const ResId<TextureView> &handle)
{ {
m_Images.Release(handle); m_Images.Release(handle);
} }
void void
Release(const ResId<StorageImage> &handle) Release(const ResId<StorageImageView> &handle)
{ {
m_StorageImages.Release(handle); m_StorageImages.Release(handle);
} }
@ -347,6 +350,7 @@ template <concepts::Manageable T>
void void
ResId<T>::AddRef() const ResId<T>::AddRef() const
{ {
if (m_Index != INVALID)
CommitManager::Instance().AddRef(*this); CommitManager::Instance().AddRef(*this);
} }
@ -354,6 +358,7 @@ template <concepts::Manageable T>
void void
ResId<T>::Release() const ResId<T>::Release() const
{ {
if (m_Index != INVALID)
CommitManager::Instance().Release(*this); CommitManager::Instance().Release(*this);
} }

View File

@ -10,23 +10,95 @@
#include "aster/aster.h" #include "aster/aster.h"
#include "aster/core/image_view.h" #include "aster/core/image_view.h"
#include <EASTL/optional.h>
namespace systems namespace systems
{ {
//
//template <std::derived_from<Image> TTo> template <concepts::ImageView TTo>
//static Ref<TTo> static Ref<TTo>
//CastView(const concepts::ImageRef auto &from) CastView(const concepts::ImageViewRef auto &from)
//{ {
// assert(TTo::Conforms(*from.get())); assert(TTo::ImageType::Conforms(*from->m_Image.get()));
// return Recast<TTo *>(from.get()); return Recast<TTo *>(from.get());
//} }
template <concepts::Image TImage = Image>
struct ViewCreateInfo
{
using ImageType = TImage;
Ref<ImageType> m_Image;
cstr m_Name;
vk::ImageViewType m_ViewType = vk::ImageViewType::e2D;
vk::ComponentMapping m_Components = {};
vk::ImageAspectFlags m_AspectMask = {};
eastl::optional<u8> m_MipLevelCount = eastl::nullopt;
eastl::optional<u8> m_LayerCount = eastl::nullopt;
u8 m_BaseMipLevel = 0;
u8 m_BaseLayer = 0;
[[nodiscard]] u8
GetMipLevelCount() const
{
return m_MipLevelCount.value_or(m_Image->m_MipLevels - m_BaseMipLevel);
}
[[nodiscard]] u8
GetLayerCount() const
{
return m_LayerCount.value_or(m_Image->m_LayerCount - m_BaseLayer);
}
explicit
operator vk::ImageViewCreateInfo() const
{
return {
.image = m_Image->m_Image,
.viewType = m_ViewType,
.format = m_Image->m_Format,
.components = m_Components,
.subresourceRange =
{
.aspectMask = m_AspectMask,
.baseMipLevel = m_BaseMipLevel,
.levelCount = GetMipLevelCount(),
.baseArrayLayer = m_BaseLayer,
.layerCount = GetLayerCount(),
},
};
}
explicit
operator ViewCreateInfo<>() const
{
return {
.m_Image = CastImage<Image>(m_Image),
.m_Name = m_Name,
.m_ViewType = m_ViewType,
.m_Components = m_Components,
.m_AspectMask = m_AspectMask,
.m_MipLevelCount = m_MipLevelCount,
.m_LayerCount = m_LayerCount,
.m_BaseMipLevel = m_BaseMipLevel,
.m_BaseLayer = m_BaseLayer,
};
}
};
class ImageViewManager final : public Manager<ImageView> class ImageViewManager final : public Manager<ImageView>
{ {
public: public:
ImageViewManager(const Device *device, const u32 maxCount); ImageViewManager(const Device *device, const u32 maxCount);
template <concepts::ImageView TImageView>
Ref<TImageView>
CreateView(const ViewCreateInfo<typename TImageView::ImageType> &createInfo)
{
return CastView<TImageView>(CreateView(ViewCreateInfo<>(createInfo)));
}
Ref<ImageView> CreateView(const ViewCreateInfo<> &createInfo);
}; };
} // namespace systems } // namespace systems

View File

@ -40,14 +40,10 @@ class Manager
} }
virtual ~Manager() virtual ~Manager()
{
if constexpr (concepts::DeviceDestructible<Type>)
{ {
for (auto &element : m_Data) for (auto &element : m_Data)
{
if constexpr (concepts::SelfDestructible<Type>)
{
element.Destroy();
}
else if constexpr (concepts::DeviceDestructible<Type>)
{ {
element.Destroy(m_Device); element.Destroy(m_Device);
} }

View File

@ -9,21 +9,94 @@
#include "buffer_manager.h" #include "buffer_manager.h"
#include "image_manager.h" #include "image_manager.h"
#include "image_view_manager.h"
#include "sampler_manager.h" #include "sampler_manager.h"
namespace systems namespace systems
{ {
class ResourceManager class ResourceManager
{ {
struct CombinedImageViewManager
{
ImageManager *m_ImageManager;
ImageViewManager *m_ViewManager;
CombinedImageViewManager(ImageManager *imageManager, ImageViewManager *viewManager)
: m_ImageManager{imageManager}
, m_ViewManager{viewManager}
{
}
template <concepts::ImageView T>
[[nodiscard]] Ref<T>
CreateTexture2D(const Texture2DCreateInfo &createInfo)
{
auto handle = CreateTexture2D(createInfo);
return CastView<T>(handle);
}
template <concepts::ImageCubeView T>
[[nodiscard]] Ref<T>
CreateTextureCube(const TextureCubeCreateInfo &createInfo)
{
auto handle = CreateTextureCube(createInfo);
return CastView<T>(handle);
}
[[nodiscard]] Ref<TextureView> CreateTexture2D(const Texture2DCreateInfo &createInfo) const
{
return m_ViewManager->CreateView<TextureView>({
.m_Image = CastImage<Texture>(m_ImageManager->CreateTexture2D(createInfo)),
.m_Name = createInfo.m_Name,
.m_ViewType = vk::ImageViewType::e2D,
.m_AspectMask = vk::ImageAspectFlagBits::eColor,
});
}
[[nodiscard]] Ref<ImageCubeView> CreateTextureCube(const TextureCubeCreateInfo &createInfo) const
{
return m_ViewManager->CreateView<ImageCubeView>({
.m_Image = m_ImageManager->CreateTextureCube(createInfo),
.m_Name = createInfo.m_Name,
.m_ViewType = vk::ImageViewType::eCube,
.m_AspectMask = vk::ImageAspectFlagBits::eColor,
});
}
[[nodiscard]] Ref<ImageView> CreateAttachment(const AttachmentCreateInfo &createInfo) const
{
return m_ViewManager->CreateView({
.m_Image = m_ImageManager->CreateAttachment(createInfo),
.m_Name = createInfo.m_Name,
.m_ViewType = vk::ImageViewType::e2D,
.m_AspectMask = vk::ImageAspectFlagBits::eColor,
});
}
[[nodiscard]] Ref<ImageView> CreateDepthStencilImage(const DepthStencilImageCreateInfo &createInfo) const
{
return m_ViewManager->CreateView({
.m_Image = m_ImageManager->CreateDepthStencilImage(createInfo),
.m_Name = createInfo.m_Name,
.m_ViewType = vk::ImageViewType::e2D,
.m_AspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
});
}
};
BufferManager m_Buffers; BufferManager m_Buffers;
ImageManager m_Images; ImageManager m_Images;
SamplerManager m_Samplers; SamplerManager m_Samplers;
ImageViewManager m_Views;
CombinedImageViewManager m_CombinedImageViews;
public: public:
ResourceManager(const Device *device, u32 maxBufferCount, u32 maxImageCount, u32 maxSamplerCount) ResourceManager(const Device *device, u32 maxBufferCount, u32 maxImageCount, u32 maxSamplerCount, u32 maxViewCount)
: m_Buffers{device, maxBufferCount} : m_Buffers{device, maxBufferCount}
, m_Images{device, maxImageCount} , m_Images{device, maxImageCount}
, m_Samplers{device, maxSamplerCount} , m_Samplers{device, maxSamplerCount}
, m_Views{device, maxViewCount}
, m_CombinedImageViews{&m_Images, &m_Views}
{ {
} }
@ -39,12 +112,23 @@ class ResourceManager
return m_Images; return m_Images;
} }
ImageViewManager &
Views()
{
return m_Views;
}
SamplerManager & SamplerManager &
Samplers() Samplers()
{ {
return m_Samplers; return m_Samplers;
} }
CombinedImageViewManager &CombinedImageViews()
{
return m_CombinedImageViews;
}
~ResourceManager() = default; ~ResourceManager() = default;
PIN_MEMORY(ResourceManager); PIN_MEMORY(ResourceManager);

View File

@ -13,10 +13,16 @@ Image::Destroy()
if (!IsValid()) if (!IsValid())
return; return;
m_Device->m_Device.destroy(m_View, nullptr);
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_ = 0;
} }
void
Image::DestroyView(const vk::ImageView imageView) const
{
m_Device->m_Device.destroy(imageView, nullptr);
}
// //
//void //void
//Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageFormat, const bool isMipMapped, //Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageFormat, const bool isMipMapped,

View File

@ -8,17 +8,18 @@
#include "core/device.h" #include "core/device.h"
void void
Sampler::Destroy(const Device *device) Sampler::Destroy()
{ {
if (!IsValid()) if (!IsValid())
return; return;
device->m_Device.destroy(Take(m_Sampler), nullptr); m_Device->m_Device.destroy(Take(m_Sampler), nullptr);
} }
void void
Sampler::Init(const Device *device, const vk::SamplerCreateInfo &samplerCreateInfo, cstr name) Sampler::Init(const Device *device, const vk::SamplerCreateInfo &samplerCreateInfo, cstr name)
{ {
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);
} }

View File

@ -7,5 +7,6 @@ PRIVATE
"manager.cpp" "manager.cpp"
"buffer_manager.cpp" "buffer_manager.cpp"
"image_manager.cpp" "image_manager.cpp"
"image_view_manager.cpp"
"sampler_manager.cpp" "sampler_manager.cpp"
"commit_manager.cpp") "commit_manager.cpp")

View File

@ -7,6 +7,7 @@
#include "EASTL/array.h" #include "EASTL/array.h"
#include "core/device.h" #include "core/device.h"
#include "core/image_view.h"
#define AbortIfFailed(RESULT) \ #define AbortIfFailed(RESULT) \
do \ do \
@ -174,8 +175,8 @@ CommitManager::CommitBuffer(const Ref<Buffer> &buffer)
return commit; return commit;
} }
ResId<StorageImage> ResId<StorageImageView>
CommitManager::CommitStorageImage(const Ref<StorageImage> &image) CommitManager::CommitStorageImage(const Ref<StorageImageView> &image)
{ {
auto [commit, isNew] = m_StorageImages.Create(image); auto [commit, isNew] = m_StorageImages.Create(image);
if (!isNew) if (!isNew)
@ -198,14 +199,14 @@ CommitManager::CommitStorageImage(const Ref<StorageImage> &image)
return commit; return commit;
} }
ResId<Texture> ResId<TextureView>
CommitManager::CommitTexture(const Ref<Texture> &handle) CommitManager::CommitTexture(const Ref<TextureView> &handle)
{ {
return CommitTexture(handle, m_DefaultSampler); return CommitTexture(handle, m_DefaultSampler);
} }
ResId<Texture> ResId<TextureView>
CommitManager::CommitTexture(const Ref<Texture> &image, const Ref<Sampler> &sampler) CommitManager::CommitTexture(const Ref<TextureView> &image, const Ref<Sampler> &sampler)
{ {
auto [commit, isNew] = m_Images.Create(image); auto [commit, isNew] = m_Images.Create(image);
if (!isNew) if (!isNew)

View File

@ -40,30 +40,11 @@ ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo)
&allocationCreateInfo, &image, &allocation, nullptr)); &allocationCreateInfo, &image, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
vk::ImageView view;
const vk::ImageViewCreateInfo imageViewCreateInfo = {
.image = image,
.viewType = vk::ImageViewType::e2D,
.format = imageCreateInfo.format,
.components = {},
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = imageCreateInfo.mipLevels,
.baseArrayLayer = 0,
.layerCount = imageCreateInfo.arrayLayers,
},
};
result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
THEN_ABORT(result);
auto object = Alloc(); auto object = Alloc();
object->m_Image = image; object->m_Image = image;
object->m_View = view;
object->m_Allocation = allocation; object->m_Allocation = allocation;
object->m_Extent = imageCreateInfo.extent; object->m_Extent = imageCreateInfo.extent;
object->m_Format = imageCreateInfo.format;
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers); object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels); object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
object->m_Flags_ = {}; object->m_Flags_ = {};
@ -92,30 +73,11 @@ ImageManager::CreateTextureCube(const TextureCubeCreateInfo &createInfo)
&allocationCreateInfo, &image, &allocation, nullptr)); &allocationCreateInfo, &image, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
vk::ImageView view;
const vk::ImageViewCreateInfo imageViewCreateInfo = {
.image = image,
.viewType = vk::ImageViewType::eCube,
.format = imageCreateInfo.format,
.components = {},
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = imageCreateInfo.mipLevels,
.baseArrayLayer = 0,
.layerCount = imageCreateInfo.arrayLayers,
},
};
result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
THEN_ABORT(result);
auto object = Alloc(); auto object = Alloc();
object->m_Image = image; object->m_Image = image;
object->m_View = view;
object->m_Allocation = allocation; object->m_Allocation = allocation;
object->m_Extent = imageCreateInfo.extent; object->m_Extent = imageCreateInfo.extent;
object->m_Format = imageCreateInfo.format;
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers); object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels); object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
object->m_Flags_ = Image::CUBE_BIT; object->m_Flags_ = Image::CUBE_BIT;
@ -144,30 +106,11 @@ ImageManager::CreateAttachment(const AttachmentCreateInfo &createInfo)
&allocationCreateInfo, &image, &allocation, nullptr)); &allocationCreateInfo, &image, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
vk::ImageView view;
const vk::ImageViewCreateInfo imageViewCreateInfo = {
.image = image,
.viewType = vk::ImageViewType::e2D,
.format = imageCreateInfo.format,
.components = {},
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = imageCreateInfo.mipLevels,
.baseArrayLayer = 0,
.layerCount = imageCreateInfo.arrayLayers,
},
};
result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
THEN_ABORT(result);
auto object = Alloc(); auto object = Alloc();
object->m_Image = image; object->m_Image = image;
object->m_View = view;
object->m_Allocation = allocation; object->m_Allocation = allocation;
object->m_Extent = imageCreateInfo.extent; object->m_Extent = imageCreateInfo.extent;
object->m_Format = imageCreateInfo.format;
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers); object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels); object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);
@ -191,30 +134,11 @@ ImageManager::CreateDepthStencilImage(const DepthStencilImageCreateInfo &createI
&allocationCreateInfo, &image, &allocation, nullptr)); &allocationCreateInfo, &image, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result); ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
vk::ImageView view;
const vk::ImageViewCreateInfo imageViewCreateInfo = {
.image = image,
.viewType = vk::ImageViewType::e2D,
.format = imageCreateInfo.format,
.components = {},
.subresourceRange =
{
.aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
.baseMipLevel = 0,
.levelCount = imageCreateInfo.mipLevels,
.baseArrayLayer = 0,
.layerCount = imageCreateInfo.arrayLayers,
},
};
result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
THEN_ABORT(result);
auto object = Alloc(); auto object = Alloc();
object->m_Image = image; object->m_Image = image;
object->m_View = view;
object->m_Allocation = allocation; object->m_Allocation = allocation;
object->m_Extent = imageCreateInfo.extent; object->m_Extent = imageCreateInfo.extent;
object->m_Format = imageCreateInfo.format;
object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers); object->m_LayerCount = Cast<u8>(imageCreateInfo.arrayLayers);
object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels); object->m_MipLevels = Cast<u8>(imageCreateInfo.mipLevels);

View File

@ -0,0 +1,47 @@
// =============================================
// Aster: image_view_manager.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "systems/image_view_manager.h"
#include "core/device.h"
using namespace systems;
ImageViewManager::ImageViewManager(const Device *device, const u32 maxCount)
: Manager{device, maxCount}
{
}
Ref<ImageView>
ImageViewManager::CreateView(const ViewCreateInfo<> &createInfo)
{
const auto layerCount = createInfo.GetLayerCount();
const auto mipCount = createInfo.GetMipLevelCount();
ERROR_IF((createInfo.m_BaseLayer + layerCount) > createInfo.m_Image->m_LayerCount,
"Invalid Layer Access")
THEN_ABORT(-1);
ERROR_IF((createInfo.m_BaseMipLevel + mipCount) > createInfo.m_Image->m_MipLevels,
"Invalid Mip Level Access")
THEN_ABORT(-1);
vk::ImageView view;
const auto imageViewCreateInfo = Cast<vk::ImageViewCreateInfo>(createInfo);
auto result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
THEN_ABORT(result);
m_Device->SetName(view, createInfo.m_Name);
auto object = Alloc();
object->m_Image = createInfo.m_Image;
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;
}

View File

@ -23,6 +23,8 @@
#include "aster/systems/commit_manager.h" #include "aster/systems/commit_manager.h"
#include "frame.h" #include "frame.h"
#include "stb_image.h" #include "stb_image.h"
#include "aster/systems/image_view_manager.h"
#include "aster/systems/resource_manager.h"
#include <EASTL/array.h> #include <EASTL/array.h>
@ -129,11 +131,9 @@ 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::BufferManager bufferManager{&device, 12}; systems::ResourceManager resourceManager{&device, 12, 12, 1, 12};
systems::ImageManager imageManager{&device, 12};
systems::SamplerManager samplerManager{&device, 1};
systems::CommitManager commitManager{&device, 12, 12, 12, samplerManager.CreateSampler({})}; systems::CommitManager commitManager{&device, 12, 12, 12, resourceManager.Samplers().CreateSampler({})};
Pipeline pipeline = CreatePipeline(&commitManager, &swapchain); Pipeline pipeline = CreatePipeline(&commitManager, &swapchain);
@ -211,10 +211,10 @@ main(int, char **)
assert(loaded); assert(loaded);
INFO("Image {}x{} : {} channels", imageFile.m_Width, imageFile.m_Height, imageFile.m_NumChannels); INFO("Image {}x{} : {} channels", imageFile.m_Width, imageFile.m_Height, imageFile.m_NumChannels);
auto vbo = bufferManager.CreateStorageBuffer(vertices.size() * sizeof vertices[0], "Vertex Buffer"); auto vbo = resourceManager.Buffers().CreateStorageBuffer(vertices.size() * sizeof vertices[0], "Vertex Buffer");
vbo->Write(0, vertices.size() * sizeof vertices[0], vertices.data()); vbo->Write(0, vertices.size() * sizeof vertices[0], vertices.data());
auto crate = imageManager auto crate = resourceManager.CombinedImageViews()
.CreateTexture2D({ .CreateTexture2D({
.m_Format = vk::Format::eR8G8B8A8Srgb, .m_Format = vk::Format::eR8G8B8A8Srgb,
.m_Extent = {imageFile.m_Width, imageFile.m_Height}, .m_Extent = {imageFile.m_Width, imageFile.m_Height},
@ -236,7 +236,7 @@ main(int, char **)
.newLayout = vk::ImageLayout::eTransferDstOptimal, .newLayout = vk::ImageLayout::eTransferDstOptimal,
.srcQueueFamilyIndex = queueAllocation.m_Family, .srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family, .dstQueueFamilyIndex = queueAllocation.m_Family,
.image = crate->m_Image, .image = crate->GetImage(),
.subresourceRange = .subresourceRange =
{ {
.aspectMask = vk::ImageAspectFlagBits::eColor, .aspectMask = vk::ImageAspectFlagBits::eColor,
@ -260,7 +260,7 @@ main(int, char **)
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal, .newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
.srcQueueFamilyIndex = queueAllocation.m_Family, .srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family, .dstQueueFamilyIndex = queueAllocation.m_Family,
.image = crate->m_Image, .image = crate->GetImage(),
.subresourceRange = .subresourceRange =
{ {
.aspectMask = vk::ImageAspectFlagBits::eColor, .aspectMask = vk::ImageAspectFlagBits::eColor,
@ -298,7 +298,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->m_Image, vk::ImageLayout::eTransferDstOptimal, 1, copyBuffer.copyBufferToImage(imageStaging.m_Buffer, crate->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
&imageCopy); &imageCopy);
copyBuffer.pipelineBarrier2(&imageReadyToReadDependency); copyBuffer.pipelineBarrier2(&imageReadyToReadDependency);
@ -322,7 +322,7 @@ main(int, char **)
imageStaging.Destroy(); imageStaging.Destroy();
} }
auto ubo = bufferManager.CreateStorageBuffer(sizeof camera, "Camera UBO"); auto ubo = resourceManager.Buffers().CreateStorageBuffer(sizeof camera, "Camera UBO");
ubo->Write(0, sizeof camera, &camera); ubo->Write(0, sizeof camera, &camera);
// Persistent variables // Persistent variables
@ -389,13 +389,13 @@ main(int, char **)
}; };
FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT}; FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT};
eastl::fixed_vector<Ref<Image>, MAX_FRAMES_IN_FLIGHT> depthImages; eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> depthImages;
auto initDepthImages = [&depthImages, &frameManager, &imageManager](const vk::Extent2D extent) { auto initDepthImages = [&depthImages, &frameManager, &resourceManager](const vk::Extent2D extent) {
for (u32 i = 0; i < frameManager.m_FramesInFlight; ++i) for (u32 i = 0; i < frameManager.m_FramesInFlight; ++i)
{ {
depthImages.push_back( depthImages.push_back(
imageManager.CreateDepthStencilImage({.m_Extent = extent, .m_Name = "Depth"})); resourceManager.CombinedImageViews().CreateDepthStencilImage({.m_Extent = extent, .m_Name = "Depth"}));
} }
}; };
@ -411,13 +411,13 @@ main(int, char **)
{ {
systems::ResId<Buffer> m_Camera; systems::ResId<Buffer> m_Camera;
systems::ResId<Buffer> m_VertexBuffer; systems::ResId<Buffer> m_VertexBuffer;
systems::ResId<Texture> m_Texture; systems::ResId<TextureView> m_Texture;
}; };
PCB pcb = { PCB pcb = {
.m_Camera = commitManager.CommitBuffer(ubo), .m_Camera = commitManager.CommitBuffer(ubo),
.m_VertexBuffer = commitManager.CommitBuffer(vbo), .m_VertexBuffer = commitManager.CommitBuffer(vbo),
.m_Texture = commitManager.CommitTexture(systems::CastImage<Texture>(crate)), .m_Texture = commitManager.CommitTexture(crate),
}; };
Time::Init(); Time::Init();

View File

@ -20,8 +20,8 @@
#include <filesystem> #include <filesystem>
#include <tiny_gltf.h>
#include <stb_image.h> #include <stb_image.h>
#include <tiny_gltf.h>
#if defined(LoadImage) #if defined(LoadImage)
#undef LoadImage #undef LoadImage
@ -53,7 +53,7 @@ VectorToVec3(const std::vector<double> &vec)
return {vec[0], vec[1], vec[2]}; return {vec[0], vec[1], vec[2]};
} }
Ref<Texture> Ref<TextureView>
AssetLoader::LoadHdrImage(cstr path, cstr name) const AssetLoader::LoadHdrImage(cstr path, cstr name) const
{ {
i32 x, y, nChannels; i32 x, y, nChannels;
@ -65,7 +65,7 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
u32 width = Cast<u32>(x); u32 width = Cast<u32>(x);
u32 height = Cast<u32>(y); u32 height = Cast<u32>(y);
auto texture = m_ResourceManager->Images().CreateTexture2D<Texture>({ auto texture = m_ResourceManager->CombinedImageViews().CreateTexture2D<TextureView>({
.m_Format = vk::Format::eR32G32B32A32Sfloat, .m_Format = vk::Format::eR32G32B32A32Sfloat,
.m_Extent = {width, height}, .m_Extent = {width, height},
.m_Name = path, .m_Name = path,
@ -99,7 +99,7 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
}; };
vk::CopyBufferToImageInfo2 stagingInfo = { vk::CopyBufferToImageInfo2 stagingInfo = {
.srcBuffer = stagingBuffer.m_Buffer, .srcBuffer = stagingBuffer.m_Buffer,
.dstImage = texture->m_Image, .dstImage = texture->GetImage(),
.dstImageLayout = vk::ImageLayout::eTransferDstOptimal, .dstImageLayout = vk::ImageLayout::eTransferDstOptimal,
.regionCount = 1, .regionCount = 1,
.pRegions = &copyRegion, .pRegions = &copyRegion,
@ -113,7 +113,7 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
.newLayout = vk::ImageLayout::eTransferDstOptimal, .newLayout = vk::ImageLayout::eTransferDstOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = texture->m_Image, .image = texture->GetImage(),
.subresourceRange = .subresourceRange =
{ {
.aspectMask = vk::ImageAspectFlagBits::eColor, .aspectMask = vk::ImageAspectFlagBits::eColor,
@ -138,7 +138,7 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal, .newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
.srcQueueFamilyIndex = m_TransferQueueIndex, .srcQueueFamilyIndex = m_TransferQueueIndex,
.dstQueueFamilyIndex = m_GraphicsQueueIndex, .dstQueueFamilyIndex = m_GraphicsQueueIndex,
.image = texture->m_Image, .image = texture->GetImage(),
.subresourceRange = .subresourceRange =
{ {
.aspectMask = vk::ImageAspectFlagBits::eColor, .aspectMask = vk::ImageAspectFlagBits::eColor,
@ -369,9 +369,11 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref<Texture> &texture, vk
#endif #endif
} }
std::tuple<systems::ResId<Texture>, Ref<Buffer>> std::tuple<systems::ResId<TextureView>, Ref<Buffer>>
AssetLoader::LoadImageToGpu(tinygltf::Image *image, bool isSrgb) const AssetLoader::LoadImageToGpu(tinygltf::Image *image, bool isSrgb) const
{ {
// TODO(Something not loading properly).
assert(image->component == 4); assert(image->component == 4);
assert(image->height > 0 && image->width > 0); assert(image->height > 0 && image->width > 0);
@ -447,7 +449,6 @@ AssetLoader::LoadImageToGpu(tinygltf::Image* image, bool isSrgb) const
.layerCount = 1, .layerCount = 1,
}, },
}; };
;
vk::DependencyInfo postStagingDependency = { vk::DependencyInfo postStagingDependency = {
.imageMemoryBarrierCount = 1, .imageMemoryBarrierCount = 1,
@ -489,7 +490,10 @@ AssetLoader::LoadImageToGpu(tinygltf::Image* image, bool isSrgb) const
m_CommandBuffer.endDebugUtilsLabelEXT(); m_CommandBuffer.endDebugUtilsLabelEXT();
#endif #endif
return {m_CommitManager->CommitTexture(texture), stagingBuffer}; auto textureView = m_ResourceManager->Views().CreateView<TextureView>(
{.m_Image = texture, .m_Name = image->name.data(), .m_AspectMask = vk::ImageAspectFlagBits::eColor});
return {m_CommitManager->CommitTexture(textureView), stagingBuffer};
} }
Model Model
@ -538,15 +542,16 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
eastl::vector<Ref<Buffer>> stagingBuffers; eastl::vector<Ref<Buffer>> stagingBuffers;
eastl::hash_map<i32, systems::ResId<Texture>> textureHandleMap; eastl::hash_map<i32, systems::ResId<TextureView>> textureHandleMap;
eastl::vector<Material> materials; eastl::vector<Material> materials;
systems::ResId<Buffer> materialsHandle = systems::ResId<Buffer>::Null(); systems::ResId<Buffer> materialsHandle = systems::ResId<Buffer>::Null();
if (!model.materials.empty()) if (!model.materials.empty())
{ {
auto getTextureHandle = [this, &textureHandleMap, &stagingBuffers, // TODO("Something broken on load here.");
&model](i32 index, const bool isSrgb) -> systems::ResId<Texture> { auto getTextureHandle = [this, &textureHandleMap, &model](i32 index,
const bool isSrgb) -> systems::ResId<TextureView> {
if (index < 0) if (index < 0)
{ {
return systems::NullId{}; return systems::NullId{};
@ -585,10 +590,11 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
auto materialStaging = m_ResourceManager->Buffers().CreateStagingBuffer(materialsByteSize); auto materialStaging = m_ResourceManager->Buffers().CreateStagingBuffer(materialsByteSize);
materialStaging->Write(0, materialsByteSize, materials.data()); materialStaging->Write(0, materialsByteSize, materials.data());
stagingBuffers.emplace_back(std::move(materialStaging));
vk::BufferCopy bufferCopy = {.srcOffset = 0, .dstOffset = 0, .size = materialsByteSize}; 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);
stagingBuffers.emplace_back(std::move(materialStaging));
} }
// TODO: Mesh reordering based on nodes AND OR meshoptimizer // TODO: Mesh reordering based on nodes AND OR meshoptimizer
@ -936,7 +942,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
.m_NodeHandle = nodeHandle, .m_NodeHandle = nodeHandle,
}; };
eastl::vector<systems::ResId<Texture>> textureHandles; eastl::vector<systems::ResId<TextureView>> textureHandles;
textureHandles.reserve(textureHandleMap.size()); textureHandles.reserve(textureHandleMap.size());
for (auto &[key, val] : textureHandleMap) for (auto &[key, val] : textureHandleMap)
@ -949,7 +955,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
}; };
} }
Model::Model(systems::CommitManager *resourceManager, eastl::vector<systems::ResId<Texture>> &textureHandles, Model::Model(systems::CommitManager *resourceManager, eastl::vector<systems::ResId<TextureView>> &textureHandles,
Nodes &&nodes, Ref<Buffer> nodeBuffer, ModelHandles &handles, Ref<Buffer> indexBuffer, Nodes &&nodes, Ref<Buffer> nodeBuffer, ModelHandles &handles, Ref<Buffer> indexBuffer,
const eastl::vector<MeshPrimitive> &meshPrimitives) const eastl::vector<MeshPrimitive> &meshPrimitives)
: m_ResourceManager(resourceManager) : m_ResourceManager(resourceManager)

View File

@ -12,6 +12,7 @@
#include "nodes.h" #include "nodes.h"
#include "tiny_gltf.h" #include "tiny_gltf.h"
#include "aster/systems/image_manager.h" #include "aster/systems/image_manager.h"
#include "aster/systems/image_view_manager.h"
#include "aster/systems/resource.h" #include "aster/systems/resource.h"
namespace systems namespace systems
@ -49,11 +50,11 @@ struct Material
vec3 m_EmissionFactor; // 12 28 vec3 m_EmissionFactor; // 12 28
f32 m_MetalFactor; // 04 32 f32 m_MetalFactor; // 04 32
f32 m_RoughFactor; // 04 36 f32 m_RoughFactor; // 04 36
systems::ResId<Texture> m_AlbedoTex; // 04 40 systems::ResId<TextureView> m_AlbedoTex; // 04 40
systems::ResId<Texture> m_NormalTex; // 04 44 systems::ResId<TextureView> m_NormalTex; // 04 44
systems::ResId<Texture> m_MetalRoughTex; // 04 48 systems::ResId<TextureView> m_MetalRoughTex; // 04 48
systems::ResId<Texture> m_OcclusionTex; // 04 52 systems::ResId<TextureView> m_OcclusionTex; // 04 52
systems::ResId<Texture> m_EmissionTex; // 04 56 systems::ResId<TextureView> m_EmissionTex; // 04 56
}; };
struct VertexData struct VertexData
@ -68,7 +69,7 @@ struct Model
{ {
systems::CommitManager *m_ResourceManager; systems::CommitManager *m_ResourceManager;
eastl::vector<systems::ResId<Texture>> m_TextureHandles; eastl::vector<systems::ResId<TextureView>> m_TextureHandles;
Nodes m_Nodes; Nodes m_Nodes;
struct ModelHandles struct ModelHandles
@ -87,7 +88,7 @@ struct Model
void SetModelTransform(const mat4 &transform); void SetModelTransform(const mat4 &transform);
void Update(); void Update();
Model(systems::CommitManager *resourceManager, eastl::vector<systems::ResId<Texture>> &textureHandles, Nodes &&nodes, Ref<Buffer> nodeBuffer, Model(systems::CommitManager *resourceManager, eastl::vector<systems::ResId<TextureView>> &textureHandles, Nodes &&nodes, Ref<Buffer> nodeBuffer,
ModelHandles &handles, Ref<Buffer> indexBuffer, const eastl::vector<MeshPrimitive> &meshPrimitives); ModelHandles &handles, Ref<Buffer> indexBuffer, const eastl::vector<MeshPrimitive> &meshPrimitives);
~Model() = default; ~Model() = default;
@ -109,8 +110,8 @@ struct AssetLoader
u32 m_TransferQueueIndex; u32 m_TransferQueueIndex;
u32 m_GraphicsQueueIndex; u32 m_GraphicsQueueIndex;
Ref<Texture> LoadHdrImage(cstr path, cstr name = nullptr) const; Ref<TextureView> LoadHdrImage(cstr path, cstr name = nullptr) const;
std::tuple<systems::ResId<Texture>, Ref<Buffer>> LoadImageToGpu(tinygltf::Image *image, bool isSrgb) const; std::tuple<systems::ResId<TextureView>, Ref<Buffer>> LoadImageToGpu(tinygltf::Image *image, bool isSrgb) const;
Model LoadModelToGpu(cstr path, cstr name = nullptr); Model LoadModelToGpu(cstr path, cstr name = nullptr);
constexpr static auto ANormal = "NORMAL"; constexpr static auto ANormal = "NORMAL";
@ -134,11 +135,12 @@ struct AssetLoader
}; };
void void
GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref<Texture> &texture, vk::ImageLayout initialLayout, GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref<Texture> &textureView, vk::ImageLayout initialLayout,
vk::ImageLayout finalLayout, vk::PipelineStageFlags2 prevStage, vk::PipelineStageFlags2 finalStage); vk::ImageLayout finalLayout, vk::PipelineStageFlags2 prevStage, vk::PipelineStageFlags2 finalStage);
void GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageRef auto& texture, vk::ImageLayout initialLayout, void
GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageRef 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)
@ -147,4 +149,14 @@ void GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageRef
finalStage); finalStage);
} }
void
GenerateMipMaps(vk::CommandBuffer commandBuffer, concepts::SampledImageViewRef auto &texture, vk::ImageLayout initialLayout,
vk::ImageLayout finalLayout,
vk::PipelineStageFlags2 prevStage = vk::PipelineStageFlagBits2::eAllCommands,
vk::PipelineStageFlags2 finalStage = vk::PipelineStageFlagBits2::eAllCommands)
{
GenerateMipMaps(commandBuffer, systems::CastImage<Texture>(texture->m_Image), initialLayout, finalLayout, prevStage,
finalStage);
}
static_assert(concepts::SampledImageRef<Ref<Texture>>); static_assert(concepts::SampledImageRef<Ref<Texture>>);

View File

@ -25,13 +25,13 @@ constexpr cstr BRDF_LUT_SHADER_FILE = "shader/brdf_lut.cs.hlsl.spv";
Environment Environment
CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cubeSide, CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cubeSide,
systems::ResId<Texture> hdrEnv, const cstr name) systems::ResId<TextureView> hdrEnv, const cstr name)
{ {
systems::ResourceManager *resourceManager = assetLoader->m_ResourceManager; systems::ResourceManager *resourceManager = assetLoader->m_ResourceManager;
systems::CommitManager *commitManager = assetLoader->m_CommitManager; systems::CommitManager *commitManager = assetLoader->m_CommitManager;
const Device *pDevice = commitManager->m_Device; const Device *pDevice = commitManager->m_Device;
auto skybox = resourceManager->Images().CreateTextureCube<StorageTexture>({ auto skybox = resourceManager->CombinedImageViews().CreateTextureCube<StorageTextureCubeView>({
.m_Format = vk::Format::eR16G16B16A16Sfloat, .m_Format = vk::Format::eR16G16B16A16Sfloat,
.m_Side = cubeSide, .m_Side = cubeSide,
.m_Name = "Skybox", .m_Name = "Skybox",
@ -43,7 +43,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
auto skyboxHandle = commitManager->CommitTexture(skybox); auto skyboxHandle = commitManager->CommitTexture(skybox);
auto skyboxStorageHandle = commitManager->CommitStorageImage(skybox); auto skyboxStorageHandle = commitManager->CommitStorageImage(skybox);
auto diffuseIrradiance = resourceManager->Images().CreateTextureCube<StorageTexture>({ auto diffuseIrradiance = resourceManager->CombinedImageViews().CreateTextureCube<StorageTextureCubeView>({
.m_Format = vk::Format::eR16G16B16A16Sfloat, .m_Format = vk::Format::eR16G16B16A16Sfloat,
.m_Side = 64, .m_Side = 64,
.m_Name = "Diffuse Irradiance", .m_Name = "Diffuse Irradiance",
@ -54,7 +54,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
auto diffuseIrradianceHandle = commitManager->CommitTexture(diffuseIrradiance); auto diffuseIrradianceHandle = commitManager->CommitTexture(diffuseIrradiance);
auto diffuseIrradianceStorageHandle = commitManager->CommitStorageImage(diffuseIrradiance); auto diffuseIrradianceStorageHandle = commitManager->CommitStorageImage(diffuseIrradiance);
auto prefilterCube = resourceManager->Images().CreateTextureCube<StorageTextureCube>({ auto prefilterCube = resourceManager->CombinedImageViews().CreateTextureCube<StorageTextureCubeView>({
.m_Format = vk::Format::eR16G16B16A16Sfloat, .m_Format = vk::Format::eR16G16B16A16Sfloat,
.m_Side = cubeSide, .m_Side = cubeSide,
.m_Name = "Prefilter", .m_Name = "Prefilter",
@ -64,32 +64,23 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
}); });
auto prefilterHandle = commitManager->CommitTexture(prefilterCube); // This stores the original view for us. auto prefilterHandle = commitManager->CommitTexture(prefilterCube); // This stores the original view for us.
constexpr u32 prefilterMipCountMax = 6; constexpr u32 prefilterMipCountMax = 6;
eastl::fixed_vector<systems::ResId<StorageImage>, prefilterMipCountMax> prefilterStorageHandles; eastl::fixed_vector<systems::ResId<StorageImageView>, prefilterMipCountMax> prefilterStorageHandles;
// All non-owning copies. // All non-owning copies.
for (u32 mipLevel = 0; mipLevel < prefilterMipCountMax; ++mipLevel) for (u8 mipLevel = 0; mipLevel < prefilterMipCountMax; ++mipLevel)
{ {
vk::ImageViewCreateInfo imageViewCreateInfo = { auto view = resourceManager->Views().CreateView<StorageTextureCubeView>({
.image = prefilterCube->m_Image, .m_Image = systems::CastImage<StorageTextureCube>(prefilterCube->m_Image),
.viewType = vk::ImageViewType::eCube, .m_ViewType = vk::ImageViewType::eCube,
.format = vk::Format::eR16G16B16A16Sfloat, .m_AspectMask = vk::ImageAspectFlagBits::eColor,
.components = vk::ComponentMapping{}, .m_MipLevelCount = 1,
.subresourceRange = .m_LayerCount = 6,
{ .m_BaseMipLevel = mipLevel,
.aspectMask = vk::ImageAspectFlagBits::eColor, .m_BaseLayer = 0,
.baseMipLevel = mipLevel, });
.levelCount = 1, prefilterStorageHandles.push_back(commitManager->CommitStorageImage(view));
.baseArrayLayer = 0,
.layerCount = 6,
},
};
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));
} }
auto brdfLut = resourceManager->Images().CreateTexture2D<StorageTexture>({.m_Format = vk::Format::eR16G16Sfloat, auto brdfLut = resourceManager->CombinedImageViews().CreateTexture2D<StorageTextureView>({.m_Format = vk::Format::eR16G16Sfloat,
.m_Extent = {512, 512}, .m_Extent = {512, 512},
.m_Name = "BRDF LUT", .m_Name = "BRDF LUT",
.m_IsSampled = true, .m_IsSampled = true,
@ -132,10 +123,10 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
.subresourceRange = cubeSubresRange, .subresourceRange = cubeSubresRange,
}; };
eastl::fixed_vector<vk::ImageMemoryBarrier2, 4> readyToWriteBarriers(4, readyToWriteBarrierTemplate); eastl::fixed_vector<vk::ImageMemoryBarrier2, 4> readyToWriteBarriers(4, readyToWriteBarrierTemplate);
readyToWriteBarriers[0].image = skybox->m_Image; readyToWriteBarriers[0].image = skybox->GetImage();
readyToWriteBarriers[1].image = diffuseIrradiance->m_Image; readyToWriteBarriers[1].image = diffuseIrradiance->GetImage();
readyToWriteBarriers[2].image = prefilterCube->m_Image; readyToWriteBarriers[2].image = prefilterCube->GetImage();
readyToWriteBarriers[3].image = brdfLut->m_Image; readyToWriteBarriers[3].image = brdfLut->GetImage();
readyToWriteBarriers[3].subresourceRange = lutSubresRange; readyToWriteBarriers[3].subresourceRange = lutSubresRange;
vk::DependencyInfo readyToWriteDependency = { vk::DependencyInfo readyToWriteDependency = {
@ -154,16 +145,16 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
.subresourceRange = cubeSubresRange, .subresourceRange = cubeSubresRange,
}; };
auto skyboxToSampleBarrier = readyToSampleBarrierTemplate; auto skyboxToSampleBarrier = readyToSampleBarrierTemplate;
skyboxToSampleBarrier.image = skybox->m_Image; skyboxToSampleBarrier.image = skybox->GetImage();
auto diffIrrToSampleBarrier = readyToSampleBarrierTemplate; auto diffIrrToSampleBarrier = readyToSampleBarrierTemplate;
diffIrrToSampleBarrier.image = diffuseIrradiance->m_Image; diffIrrToSampleBarrier.image = diffuseIrradiance->GetImage();
auto prefilterToSampleBarrier = readyToSampleBarrierTemplate; auto prefilterToSampleBarrier = readyToSampleBarrierTemplate;
prefilterToSampleBarrier.image = prefilterCube->m_Image; prefilterToSampleBarrier.image = prefilterCube->GetImage();
auto brdfToSampleBarrier = readyToSampleBarrierTemplate; auto brdfToSampleBarrier = readyToSampleBarrierTemplate;
prefilterToSampleBarrier.image = brdfLut->m_Image; prefilterToSampleBarrier.image = brdfLut->GetImage();
prefilterToSampleBarrier.subresourceRange = lutSubresRange; prefilterToSampleBarrier.subresourceRange = lutSubresRange;
vk::DependencyInfo skyboxToSampleDependency = { vk::DependencyInfo skyboxToSampleDependency = {
@ -187,27 +178,27 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
struct SkyboxPushConstants struct SkyboxPushConstants
{ {
systems::ResId<Texture> m_HdrEnvHandle; systems::ResId<TextureView> m_HdrEnvHandle;
systems::ResId<StorageImage> m_OutputTexture; systems::ResId<StorageImageView> m_OutputTexture;
u32 m_CubeSide; u32 m_CubeSide;
}; };
struct DiffuseIrradiancePushConstants struct DiffuseIrradiancePushConstants
{ {
systems::ResId<Texture> m_SkyboxHandle; systems::ResId<TextureView> m_SkyboxHandle;
systems::ResId<StorageImage> m_OutputTexture; systems::ResId<StorageImageView> m_OutputTexture;
u32 m_CubeSide; u32 m_CubeSide;
}; };
struct PrefilterPushConstants struct PrefilterPushConstants
{ {
systems::ResId<Texture> m_SkyboxHandle; systems::ResId<TextureView> m_SkyboxHandle;
systems::ResId<StorageImage> m_OutputTexture; systems::ResId<StorageImageView> m_OutputTexture;
u32 m_CubeSide; u32 m_CubeSide;
f32 m_Roughness; f32 m_Roughness;
u32 m_EnvSide; u32 m_EnvSide;
}; };
struct BrdfLutPushConstants struct BrdfLutPushConstants
{ {
systems::ResId<StorageImage> m_OutputTexture; systems::ResId<StorageImageView> m_OutputTexture;
}; };
#pragma region Pipeline Creation etc #pragma region Pipeline Creation etc
@ -394,12 +385,6 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
AbortIfFailed(pDevice->m_Device.resetCommandPool(assetLoader->m_CommandPool, {})); AbortIfFailed(pDevice->m_Device.resetCommandPool(assetLoader->m_CommandPool, {}));
skybox = {}; skybox = {};
for (auto &_ : prefilterStorageHandles)
{
StorageTextureCube st;
// TODO: This needs fixing
pDevice->m_Device.destroy(st.m_View, nullptr);
}
for (auto &pipeline : pipelines) for (auto &pipeline : pipelines)
{ {
pDevice->m_Device.destroy(pipeline, nullptr); pDevice->m_Device.destroy(pipeline, nullptr);

View File

@ -8,6 +8,7 @@
#include "aster/aster.h" #include "aster/aster.h"
#include "aster/systems/resource.h" #include "aster/systems/resource.h"
#include "aster/core/image.h" #include "aster/core/image.h"
#include "aster/core/image_view.h"
struct Pipeline; struct Pipeline;
struct Texture; struct Texture;
@ -16,11 +17,11 @@ struct AssetLoader;
struct Environment struct Environment
{ {
systems::ResId<Texture> m_Skybox; systems::ResId<TextureView> m_Skybox;
systems::ResId<Texture> m_Diffuse; systems::ResId<TextureView> m_Diffuse;
systems::ResId<Texture> m_Prefilter; systems::ResId<TextureView> m_Prefilter;
systems::ResId<Texture> m_BrdfLut; systems::ResId<TextureView> m_BrdfLut;
}; };
Environment CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, u32 cubeSide, systems::ResId<Texture> hdrEnv, Environment CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, u32 cubeSide, systems::ResId<TextureView> hdrEnv,
cstr name = nullptr); cstr name = nullptr);

View File

@ -178,7 +178,7 @@ main(int, char **)
vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0); vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"}; Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
systems::ResourceManager resourceManager = {&device, 1000, 1000, 10}; systems::ResourceManager resourceManager = {&device, 1000, 1000, 10, 1000};
systems::CommitManager commitManager = {&device, 1000, 1000, 1000, resourceManager.Samplers().CreateSampler({})}; systems::CommitManager commitManager = {&device, 1000, 1000, 1000, resourceManager.Samplers().CreateSampler({})};
AssetLoader assetLoader = {&resourceManager, &commitManager, graphicsQueue, queueAllocation.m_Family, AssetLoader assetLoader = {&resourceManager, &commitManager, graphicsQueue, queueAllocation.m_Family,
@ -383,19 +383,19 @@ main(int, char **)
}; };
FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT}; FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT};
eastl::fixed_vector<Ref<Image>, MAX_FRAMES_IN_FLIGHT> depthImages; eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> depthImages;
eastl::fixed_vector<Ref<Image>, MAX_FRAMES_IN_FLIGHT> attachmentImages; eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> attachmentImages;
for (u32 index = 0; index < frameManager.m_FramesInFlight; ++index) for (u32 index = 0; index < frameManager.m_FramesInFlight; ++index)
{ {
auto name = fmt::format("Depth Frame{}", index); auto name = fmt::format("Depth Frame{}", index);
depthImages.emplace_back(resourceManager.Images().CreateDepthStencilImage({ depthImages.emplace_back(resourceManager.CombinedImageViews().CreateDepthStencilImage({
.m_Extent = internalResolution, .m_Extent = internalResolution,
.m_Name = name.c_str(), .m_Name = name.c_str(),
})); }));
name = fmt::format("Attachment0 Frame{}", index); name = fmt::format("Attachment0 Frame{}", index);
attachmentImages.emplace_back(resourceManager.Images().CreateAttachment({ attachmentImages.emplace_back(resourceManager.CombinedImageViews().CreateAttachment({
.m_Format = attachmentFormat, .m_Format = attachmentFormat,
.m_Extent = internalResolution, .m_Extent = internalResolution,
.m_Name = name.c_str(), .m_Name = name.c_str(),
@ -530,13 +530,13 @@ main(int, char **)
currentAttachment->m_Extent.height != internalResolution.height) currentAttachment->m_Extent.height != internalResolution.height)
{ {
auto name = fmt::format("Depth Frame{}", currentFrame->m_FrameIdx); auto name = fmt::format("Depth Frame{}", currentFrame->m_FrameIdx);
currentDepthImage = resourceManager.Images().CreateDepthStencilImage({ currentDepthImage = resourceManager.CombinedImageViews().CreateDepthStencilImage({
.m_Extent = internalResolution, .m_Extent = internalResolution,
.m_Name = name.c_str(), .m_Name = name.c_str(),
}); });
name = fmt::format("Attachment0 Frame{}", currentFrame->m_FrameIdx); name = fmt::format("Attachment0 Frame{}", currentFrame->m_FrameIdx);
currentAttachment = resourceManager.Images().CreateAttachment({ currentAttachment = resourceManager.CombinedImageViews().CreateAttachment({
.m_Format = attachmentFormat, .m_Format = attachmentFormat,
.m_Extent = internalResolution, .m_Extent = internalResolution,
.m_Name = name.c_str(), .m_Name = name.c_str(),
@ -544,7 +544,7 @@ main(int, char **)
} }
vk::ImageView currentDepthImageView = currentDepthImage->m_View; vk::ImageView currentDepthImageView = currentDepthImage->m_View;
vk::Image currentImage = currentAttachment->m_Image; vk::Image currentImage = currentAttachment->m_Image->m_Image;
vk::ImageView currentImageView = currentAttachment->m_View; vk::ImageView currentImageView = currentAttachment->m_View;
preRenderBarrier.image = currentImage; preRenderBarrier.image = currentImage;