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