project-aster/aster/include/aster/core/image.h

206 lines
4.2 KiB
C++

// =============================================
// Aster: image.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "global.h"
struct StorageTexture;
struct Device;
[[nodiscard]] inline vk::Extent2D
ToExtent2D(const vk::Extent3D &extent)
{
return {extent.width, extent.height};
}
[[nodiscard]] inline vk::Extent3D
ToExtent3D(const vk::Extent2D &extent, const u32 depth)
{
return {extent.width, extent.height, depth};
}
[[nodiscard]] inline vk::Offset2D
ToOffset2D(const vk::Extent3D &extent)
{
return {Cast<i32>(extent.width), Cast<i32>(extent.height)};
}
[[nodiscard]] inline vk::Offset3D
ToOffset3D(const vk::Extent3D &extent)
{
return {Cast<i32>(extent.width), Cast<i32>(extent.height), Cast<i32>(extent.depth)};
}
struct Image
{
const Device *m_Device = nullptr;
vk::Image m_Image = nullptr;
VmaAllocation m_Allocation = nullptr;
vk::Extent3D m_Extent;
vk::Format m_Format;
u8 m_EmptyPadding_ = 0;
u8 m_Flags_ = 0;
u8 m_LayerCount = 0;
u8 m_MipLevels = 0;
constexpr static u8 SAMPLED_BIT = 1 << 7;
constexpr static u8 STORAGE_BIT = 1 << 6;
constexpr static u8 CUBE_BIT = 1 << 5;
[[nodiscard]] bool
IsSampled() const
{
return m_Flags_ & SAMPLED_BIT;
}
[[nodiscard]] bool
IsStorage() const
{
return m_Flags_ & STORAGE_BIT;
}
[[nodiscard]] bool
IsCube() const
{
return m_Flags_ & CUBE_BIT;
}
[[nodiscard]] bool
IsValid() const
{
return m_Image;
}
[[nodiscard]] u32
GetMipLevels() const
{
return m_MipLevels;
}
static bool
Conforms(const Image &)
{
return true;
}
void DestroyView(vk::ImageView imageView) const;
// Constructors.
explicit Image(const Device *device, vk::Image image, VmaAllocation allocation, vk::Extent3D extent,
vk::Format format, u8 flags, u8 layerCount, u8 mipLevels);
Image(Image &&other) noexcept;
Image &operator=(Image &&other) noexcept;
~Image();
DISALLOW_COPY_AND_ASSIGN(Image);
};
namespace concepts
{
template <typename T>
concept Image = std::derived_from<T, Image>;
template <typename T>
concept ImageRef = Derefencable<T> and Image<DereferencesTo<T>>;
template <typename T>
concept SampledImage = requires() {
{ T::SAMPLED } -> std::convertible_to<bool>;
} and T::SAMPLED and Image<T>;
template <typename T>
concept SampledImageRef = Derefencable<T> and SampledImage<DereferencesTo<T>>;
template <typename T>
concept ImageCube = requires() {
{ T::CUBE } -> std::convertible_to<bool>;
} and T::CUBE and Image<T>;
template <typename T>
concept ImageCubeRef = Derefencable<T> and ImageCube<DereferencesTo<T>>;
template <typename T>
concept StorageImage = requires() {
{ T::STORAGE } -> std::convertible_to<bool>;
} and T::STORAGE and Image<T>;
template <typename T>
concept StorageImageRef = Derefencable<T> and StorageImage<DereferencesTo<T>>;
} // namespace concepts
struct Texture : Image
{
constexpr static bool SAMPLED = true;
static bool
Conforms(const Image &other)
{
return other.IsSampled();
}
};
struct ImageCube : Image
{
constexpr static bool CUBE = true;
static bool
Conforms(const Image &other)
{
return other.IsCube();
}
};
struct TextureCube : Image
{
constexpr static bool SAMPLED = true;
constexpr static bool CUBE = true;
static bool
Conforms(const Image &other)
{
return other.IsSampled() && other.IsCube();
}
};
struct StorageImage : Image
{
constexpr static bool STORAGE = true;
static bool
Conforms(const Image &other)
{
return other.IsStorage();
}
};
struct StorageTexture : StorageImage
{
constexpr static bool SAMPLED = true;
constexpr static bool STORAGE = true;
static bool
Conforms(const Image &other)
{
return other.IsStorage() && other.IsSampled();
}
};
struct StorageTextureCube : StorageImage
{
constexpr static bool SAMPLED = true;
constexpr static bool CUBE = true;
constexpr static bool STORAGE = true;
static bool
Conforms(const Image &other)
{
return other.IsStorage() && other.IsSampled() && other.IsCube();
}
};