Compare commits

...

10 Commits

Author SHA1 Message Date
Anish Bhobe 3a7a2b4ab7 [WIP] Box moved to 'new API' pending fixes. 2025-05-08 17:44:55 +02:00
Anish Bhobe 63282c3587 [WIP] Added a transfer context for uploads. 2025-05-08 00:34:59 +02:00
Anish Bhobe 7351415ebf Consolidate Present as a special submit. 2025-05-07 18:27:13 +02:00
Anish Bhobe 1db942f1a9 Remove Cast and Recast. 2025-05-07 17:44:01 +02:00
Anish Bhobe 3dc6501246 fix: Error on window resize. 2025-05-06 19:06:04 +02:00
Anish Bhobe 5d6ddbb158 Added slang for Shader code compilation.
TODO: Use slang to create descriptors.
2025-05-06 15:32:58 +02:00
Anish Bhobe 7507394af9 Added Pipeline creation into the Device. 2025-05-03 13:46:44 +02:00
Anish Bhobe 2facb3e6c1 fix: Context memory leak. 2025-05-02 20:32:15 +02:00
Anish Bhobe d683de3181 Draw Triangle and bug-fixes. 2025-05-01 20:05:31 +02:00
Anish Bhobe d82e81d104 Begin Consolidation all objects under the systems::Device interface.
Currently clears a screen.
- Merge all resource creation API under Device.
- Begin a basic Context setup.
2025-05-01 13:27:19 +02:00
82 changed files with 3441 additions and 2195 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ build/
.direnv/
.ccls-cache/
*.user
/vcpkg_installed

View File

@ -4,12 +4,12 @@ cmake_minimum_required(VERSION 3.13)
project(Aster VERSION 0.1.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (MSVC)
set(CMAKE_CXX_FLAGS "/W4 /GR- ${MSVC_FLAGS}")
set(CMAKE_CXX_FLAGS "/W4 /GR- ${MSVC_FLAGS} /utf-8")
set(CMAKE_CXX_FLAGS_RELEASE "/O3")
add_compile_definitions(_HAS_EXCEPTIONS=0)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)

View File

@ -1,10 +1,14 @@
function(add_shader TARGET SHADER)
find_package(Vulkan REQUIRED COMPONENTS dxc)
get_filename_component(vulkan-bin-dir ${Vulkan_GLSLC_EXECUTABLE} DIRECTORY)
find_program(slangc_exe NAMES "slangc")
if (NOT slangc_exe STREQUAL "slangc_exe-NOTFOUND")
set(slangc_exe_FOUND true)
endif()
get_filename_component(shader-ext ${SHADER} LAST_EXT)
get_filename_component(shader-inner ${SHADER} NAME_WLE)
get_filename_component(shader-type ${shader-inner} LAST_EXT)
string(REPLACE "." "" shader-type ${shader-type})
set(current-shader-path ${CMAKE_CURRENT_SOURCE_DIR}/${SHADER})
set(current-output-path ${CMAKE_CURRENT_BINARY_DIR}/${SHADER}.spv)
@ -14,6 +18,11 @@ function(add_shader TARGET SHADER)
if (Vulkan_dxc_exe_FOUND AND ${shader-ext} STREQUAL ".hlsl")
message("Marked as hlsl file. ${current-output-path}")
get_filename_component(shader-inner ${SHADER} NAME_WLE)
get_filename_component(shader-type ${shader-inner} LAST_EXT)
string(REPLACE "." "" shader-type ${shader-type})
add_custom_command(
OUTPUT ${current-output-path}
COMMAND Vulkan::dxc_exe ${DXC_SHADER_FLAGS} -spirv -T "${shader-type}_6_0" -E main ${current-shader-path} -Fo ${current-output-path}
@ -28,6 +37,14 @@ function(add_shader TARGET SHADER)
DEPENDS ${current-shader-path}
IMPLICIT_DEPENDS CXX ${current-shader-path}
VERBATIM)
elseif (${shader-ext} STREQUAL ".slang")
message("Marked as slang file. ${current-output-path}")
add_custom_command(
OUTPUT ${current-output-path}
COMMAND ${slangc_exe} -target spirv -o ${current-output-path} ${current-shader-path}
DEPENDS ${current-shader-path}
IMPLICIT_DEPENDS CXX ${current-shader-path}
VERBATIM)
endif ()
# Make sure our build depends on this output.

View File

@ -9,13 +9,14 @@ find_package(Vulkan REQUIRED)
find_package(fmt CONFIG REQUIRED)
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
find_package(EASTL CONFIG REQUIRED)
find_library(slang NAMES "slang" CONFIG REQUIRED)
add_library(aster_core STATIC)
add_subdirectory("include")
add_subdirectory("src")
set_property(TARGET aster_core PROPERTY CXX_STANDARD 20)
target_compile_features(aster_core PUBLIC cxx_std_23)
target_include_directories(aster_core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/aster")
target_include_directories(aster_core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
@ -26,4 +27,5 @@ target_include_directories(aster_core PRIVATE ${SCOTTT_DEBUGBREAK_INCLUDE_DIRS})
target_link_libraries(aster_core PRIVATE fmt::fmt)
target_link_libraries(aster_core PRIVATE EASTL)
target_link_libraries(aster_core PUBLIC Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
target_link_libraries(aster_core PUBLIC ${slang})

View File

@ -106,7 +106,7 @@ concept AnyBuffer = std::derived_from<T, Buffer>;
template <typename T, typename TInto>
concept BufferInto = std::derived_from<T, Buffer> and std::derived_from<TInto, Buffer> and
(Cast<bool>(T::FLAGS & TInto::FLAGS) or std::same_as<Buffer, TInto>);
(static_cast<bool>(T::FLAGS & TInto::FLAGS) or std::same_as<Buffer, TInto>);
template <typename T>
concept AnyBufferRef = Deref<T> and AnyBuffer<DerefType<T>>;

View File

@ -16,6 +16,7 @@
#define VULKAN_HPP_DISABLE_ENHANCED_MODE 1
#define VULKAN_HPP_NO_EXCEPTIONS 1
#define VULKAN_HPP_NO_SMART_HANDLE 1
#define VULKAN_HPP_NO_STRUCT_SETTERS 1
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1

View File

@ -44,42 +44,28 @@ constexpr auto White = "\u001b[37m";
constexpr auto Reset = "\u001b[0m";
} // namespace ansi_color
template <typename TType, typename TFrom>
constexpr auto
Cast(TFrom &&in)
{
return static_cast<TType>(std::forward<TFrom>(in));
}
template <typename TType, typename TFrom>
constexpr auto
Recast(TFrom &&in)
{
return reinterpret_cast<TType>(std::forward<TFrom>(in));
}
constexpr f32
operator""_deg(long double degrees)
{
return glm::radians<f32>(Cast<f32>(degrees));
return glm::radians<f32>(static_cast<f32>(degrees));
}
constexpr f32
operator""_deg(unsigned long long int degrees)
{
return glm::radians<f32>(Cast<f32>(degrees));
return glm::radians<f32>(static_cast<f32>(degrees));
}
constexpr f32
operator""_rad(long double rads)
{
return Cast<f32>(rads);
return static_cast<f32>(rads);
}
constexpr f32
operator""_rad(unsigned long long int rads)
{
return Cast<f32>(rads);
return static_cast<f32>(rads);
}
using glm::ivec2;

View File

@ -39,11 +39,22 @@ struct Device final
void WaitIdle() const;
vk::Device *
operator->()
{
return &m_Device;
}
const vk::Device *
operator->() const
{
return &m_Device;
}
// Ctor/Dtor
Device(const Instance *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
const eastl::vector<QueueAllocation> &queueAllocations, NameString &&name);
Device(const Instance *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
const eastl::vector<QueueAllocation> &queueAllocations, eastl::span<u8> &&pipelineCacheData,
Device() = default;
Device(const Instance &context, PhysicalDevice &physicalDevice, Features &enabledFeatures,
const eastl::span<QueueAllocation> &queueAllocations, const eastl::span<u8> &pipelineCacheData,
NameString &&name);
~Device();
@ -61,7 +72,7 @@ Device::SetName(const T &object, cstr name) const
if (!m_ValidationEnabled || !name || !object)
return;
auto handle = Recast<u64>(Cast<typename T::NativeType>(object));
auto handle = reinterpret_cast<u64>(static_cast<typename T::NativeType>(object));
const vk::DebugUtilsObjectNameInfoEXT objectNameInfo = {
.objectType = object.objectType,
.objectHandle = handle,

View File

@ -55,6 +55,29 @@ constexpr u32 ASTER_API_VERSION = VK_API_VERSION_1_3;
#define TODO(MSG) assert(false && ("Unimplemented: " MSG))
#define FIX(MSG) static_assert(false && ("Unimplemented: " MSG))
#define AbortIfFailed(RESULT) \
do \
{ \
vk::Result _checkResultValue_; \
ERROR_IF(Failed(_checkResultValue_ = static_cast<vk::Result>(RESULT)), "Cause: {}", _checkResultValue_) \
THEN_ABORT(_checkResultValue_); \
} while (false)
#define AbortIfFailedMV(RESULT, MSG, EXTRA) \
do \
{ \
vk::Result _checkResultValue_; \
ERROR_IF(Failed(_checkResultValue_ = static_cast<vk::Result>(RESULT)), MSG " Cause: {}", EXTRA, _checkResultValue_) \
THEN_ABORT(_checkResultValue_); \
} while (false)
#define AbortIfFailedM(RESULT, MSG) \
do \
{ \
auto _checkResultValue_ = static_cast<vk::Result>(RESULT); \
ERROR_IF(Failed(_checkResultValue_), MSG " Cause: {}", _checkResultValue_) THEN_ABORT(_checkResultValue_); \
} while (false)
[[nodiscard]] inline bool
Failed(const vk::Result result)
{
@ -75,7 +98,7 @@ struct eastl::hash<vk::Flags<TFlagBits>> // NOLINT(*-dcl58-cpp)
[[nodiscard]] usize
operator()(const vk::Flags<TFlagBits> &val)
{
return std::hash<u32>()(Cast<u32>(val));
return std::hash<u32>()(static_cast<u32>(val));
}
};
@ -206,7 +229,7 @@ struct fmt::formatter<vk::Result> : nested_formatter<std::string>
format(vk::Result result, format_context &ctx) const
{
return write_padded(ctx,
[this, result](auto out) { return v10::format_to(out, "{}", nested(to_string(result))); });
[this, result](auto out) { return v11::format_to(out, "{}", nested(to_string(result))); });
}
};
@ -217,7 +240,7 @@ struct fmt::formatter<eastl::fixed_string<TType, TCount, TOverflow>> : nested_fo
// ReSharper disable once CppInconsistentNaming
format(const eastl::fixed_string<TType, TCount, TOverflow> &str, format_context &ctx) const
{
return write_padded(ctx, [this, str](auto out) { return v10::format_to(out, "{}", nested(str.c_str())); });
return write_padded(ctx, [this, str](auto out) { return v11::format_to(out, "{}", nested(str.c_str())); });
}
};

View File

@ -25,13 +25,13 @@ ToExtent3D(const vk::Extent2D &extent, const u32 depth)
[[nodiscard]] inline vk::Offset2D
ToOffset2D(const vk::Extent3D &extent)
{
return {Cast<i32>(extent.width), Cast<i32>(extent.height)};
return {static_cast<i32>(extent.width), static_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)};
return {static_cast<i32>(extent.width), static_cast<i32>(extent.height), static_cast<i32>(extent.depth)};
}
struct Image
@ -121,7 +121,7 @@ concept AnyImage = std::derived_from<T, Image>;
template <typename T, typename TInto>
concept ImageInto = std::derived_from<T, Image> and std::derived_from<TInto, Image> and
(Cast<bool>(T::FLAGS & TInto::FLAGS) or std::same_as<Image, TInto>);
(static_cast<bool>(T::FLAGS & TInto::FLAGS) or std::same_as<Image, TInto>);
template <typename T>
concept AnyImageRef = Deref<T> and AnyImage<DerefType<T>>;

View File

@ -30,7 +30,7 @@ struct View
[[nodiscard]] bool
IsValid() const
{
return Cast<bool>(m_Image);
return static_cast<bool>(m_Image);
}
View(Ref<Image> image, const vk::ImageView view, const vk::Extent3D extent, const u8 baseLayer, const u8 layerCount,

View File

@ -21,6 +21,7 @@ struct Instance final
vk::DebugUtilsMessengerEXT m_DebugMessenger = nullptr;
// Ctor/Dtor
Instance() = default;
Instance(cstr appName, Version version, bool enableValidation = ENABLE_LAYER_MESSAGES_DEFAULT_VALUE);
~Instance();

View File

@ -54,5 +54,5 @@ struct PhysicalDevice final
class PhysicalDevices : public eastl::fixed_vector<PhysicalDevice, 4>
{
public:
PhysicalDevices(const Surface *surface, const Instance *context);
PhysicalDevices(const Surface &surface, const Instance &context);
};

View File

@ -18,7 +18,30 @@ struct Pipeline
vk::Pipeline m_Pipeline;
eastl::vector<vk::DescriptorSetLayout> m_SetLayouts;
Pipeline() = default;
Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline,
eastl::vector<vk::DescriptorSetLayout> &&setLayouts);
~Pipeline();
DISALLOW_COPY_AND_ASSIGN(Pipeline);
Pipeline(Pipeline &&other) noexcept
: m_Device{other.m_Device},
m_Layout{Take(other.m_Layout)},
m_Pipeline{Take(other.m_Pipeline)},
m_SetLayouts{std::move(other.m_SetLayouts)}
{
}
Pipeline &
operator=(Pipeline &&other) noexcept
{
if (this == &other)
return *this;
m_Device = other.m_Device;
m_Layout = Take(other.m_Layout);
m_Pipeline = Take(other.m_Pipeline);
m_SetLayouts = std::move(other.m_SetLayouts);
return *this;
}
};

View File

@ -9,10 +9,33 @@
struct Size2D
{
u32 m_Width;
u32 m_Height;
u32 m_Width = 0;
u32 m_Height = 0;
Size2D() = default;
Size2D(const u32 width, const u32 height)
: m_Width{width}
, m_Height{height}
{
}
Size2D(const vk::Extent2D extent)
: m_Width{extent.width}
, m_Height{extent.height}
{
}
Size2D &
operator=(const vk::Extent2D other)
{
m_Height = other.height;
m_Width = other.width;
return *this;
}
bool operator==(const Size2D&) const = default;
explicit
operator vk::Extent2D() const
{
return {m_Width, m_Height};

View File

@ -17,7 +17,8 @@ struct Surface
NameString m_Name;
// Ctor Dtor
Surface(Instance *context, const Window *window, cstr name);
Surface() = default;
Surface(Instance &context, const Window &window);
~Surface();
// Move

View File

@ -21,7 +21,6 @@ struct Swapchain final
const Device *m_Device;
vk::SwapchainKHR m_Swapchain;
NameString m_Name;
vk::Extent2D m_Extent;
vk::Format m_Format;
eastl::fixed_vector<vk::Image, 4> m_Images;
@ -29,11 +28,12 @@ struct Swapchain final
eastl::vector<FnResizeCallback> m_ResizeCallbacks;
void Create(const Surface *window, Size2D size);
void Create(const Surface &surface, Size2D size);
void RegisterResizeCallback(FnResizeCallback &&callback);
// Ctor/Dtor
Swapchain(const Surface *window, const Device *device, Size2D size, NameString &&name);
Swapchain() = default;
Swapchain(const Surface &surface, const Device &device, Size2D size);
~Swapchain();
// Move

View File

@ -20,6 +20,8 @@ struct Window final
static std::atomic_uint64_t m_WindowCount;
static std::atomic_bool m_IsGlfwInit;
static void SetupLibrary();
static cstr *GetInstanceExtensions(u32 *extensionCount);
// Methods
[[nodiscard]] bool

View File

@ -4,10 +4,6 @@ cmake_minimum_required(VERSION 3.13)
target_sources(aster_core
INTERFACE
"buffer_manager.h"
"image_manager.h"
"view_manager.h"
"sampler_manager.h"
"device.h"
"resource.h"
"resource_manager.h"
"commit_manager.h")

View File

@ -1,35 +0,0 @@
// =============================================
// Aster: buffer_manager.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "aster/aster.h"
#include "aster/core/buffer.h"
namespace systems
{
template <std::derived_from<Buffer> TTo, std::derived_from<Buffer> TFrom>
static Ref<TTo>
CastBuffer(const Ref<TFrom> &from)
{
if constexpr (not concepts::BufferInto<TFrom, TTo>)
assert(TTo::FLAGS & from->m_Flags);
return std::reinterpret_pointer_cast<TTo>(from);
}
class BufferManager final
{
const Device *m_Device = nullptr;
public:
explicit BufferManager(const Device *device);
[[nodiscard]] Ref<StorageBuffer> CreateStorageBuffer(usize size, cstr name = nullptr) const;
[[nodiscard]] Ref<UniformBuffer> CreateUniformBuffer(usize size, cstr name = nullptr) const;
[[nodiscard]] Ref<StagingBuffer> CreateStagingBuffer(usize size, cstr name = nullptr) const;
[[nodiscard]] Ref<VertexBuffer> CreateVertexBuffer(usize size, cstr name = nullptr) const;
};
} // namespace systems

View File

@ -7,19 +7,20 @@
#include "aster/aster.h"
#include "buffer_manager.h"
#include "sampler_manager.h"
#include "view_manager.h"
#include "aster/util/freelist.h"
#include "EASTL/deque.h"
#include "EASTL/intrusive_hash_map.h"
#include "resource.h"
#include "EASTL/vector.h"
#include "aster/core/buffer.h"
#include "aster/core/image_view.h"
#include "aster/core/sampler.h"
namespace systems
{
class Device;
class CommitManager
{
@ -63,7 +64,7 @@ class CommitManager
Entry *
Next()
{
return Recast<Entry *>(this->mpNext);
return reinterpret_cast<Entry *>(this->mpNext);
}
void
@ -174,7 +175,7 @@ class CommitManager
u32
GetIndex(const Entry &entry)
{
return Cast<u32>(&entry - m_Data.begin());
return static_cast<u32>(&entry - m_Data.begin());
}
void
@ -286,6 +287,11 @@ class CommitManager
return *m_Instance;
}
static bool IsInit()
{
return static_cast<bool>(m_Instance);
}
private:
vk::DescriptorPool m_DescriptorPool;
vk::DescriptorSetLayout m_SetLayout;

View File

@ -0,0 +1,734 @@
// =============================================
// Aster: device.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "resource.h"
#include "aster/aster.h"
#include "aster/core/buffer.h"
#include "aster/core/device.h"
#include "aster/core/image.h"
#include "aster/core/image_view.h"
#include "aster/core/instance.h"
#include "aster/core/physical_device.h"
#include "aster/core/pipeline.h"
#include "aster/core/sampler.h"
#include "aster/core/size.h"
#include "aster/core/swapchain.h"
#include "EASTL/deque.h"
#include <EASTL/hash_map.h>
#include <EASTL/optional.h>
#include <slang-com-ptr.h>
#include <slang.h>
#include <variant>
constexpr static u32 MAX_FRAMES_IN_FLIGHT = 3;
struct Window;
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(static_cast<usize>(createInfo.mipLodBias * 1000))); // Resolution of 10^-3
hash = HashCombine(hash, HashAny(createInfo.anisotropyEnable));
hash = HashCombine(
hash,
HashAny(static_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(static_cast<usize>(createInfo.minLod * 1000))); // 0.001 resolution is enough.
hash = HashCombine(
hash,
HashAny(static_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
{
// ====================================================================================================
#pragma region Creation Structs
// ====================================================================================================
// ----------------------------------------------------------------------------------------------------
#pragma region Image
// ----------------------------------------------------------------------------------------------------
struct Texture2DCreateInfo
{
vk::Format m_Format = vk::Format::eUndefined;
vk::Extent2D m_Extent = {};
cstr m_Name = nullptr;
bool m_IsSampled = true;
bool m_IsMipMapped = false;
bool m_IsStorage = false;
};
struct TextureCubeCreateInfo
{
vk::Format m_Format = vk::Format::eUndefined;
u32 m_Side = 0;
cstr m_Name = nullptr;
bool m_IsSampled = true;
bool m_IsMipMapped = false;
bool m_IsStorage = false;
};
struct AttachmentCreateInfo
{
vk::Format m_Format = vk::Format::eUndefined;
vk::Extent2D m_Extent = {};
cstr m_Name = nullptr;
};
struct DepthStencilImageCreateInfo
{
vk::Extent2D m_Extent = {};
cstr m_Name = nullptr;
};
#pragma endregion
// ----------------------------------------------------------------------------------------------------
#pragma region View
// ----------------------------------------------------------------------------------------------------
template <concepts::AnyImage TImage>
struct ViewCreateInfo
{
using ImageType = TImage;
Ref<ImageType> m_Image;
cstr m_Name;
vk::ImageViewType m_ViewType = vk::ImageViewType::e2D;
vk::ComponentMapping m_Components = {};
vk::ImageAspectFlags m_AspectMask = {};
eastl::optional<u8> m_MipLevelCount = eastl::nullopt;
eastl::optional<u8> m_LayerCount = eastl::nullopt;
u8 m_BaseMipLevel = 0;
u8 m_BaseLayer = 0;
[[nodiscard]] u8
GetMipLevelCount() const
{
return m_MipLevelCount.value_or(m_Image->m_MipLevels - m_BaseMipLevel);
}
[[nodiscard]] u8
GetLayerCount() const
{
return m_LayerCount.value_or(m_Image->m_LayerCount - m_BaseLayer);
}
explicit
operator vk::ImageViewCreateInfo() const
{
return {
.image = m_Image->m_Image,
.viewType = m_ViewType,
.format = m_Image->m_Format,
.components = m_Components,
.subresourceRange =
{
.aspectMask = m_AspectMask,
.baseMipLevel = m_BaseMipLevel,
.levelCount = GetMipLevelCount(),
.baseArrayLayer = m_BaseLayer,
.layerCount = GetLayerCount(),
},
};
}
explicit
operator ViewCreateInfo<Image>() const
{
return {
.m_Image = CastImage<Image>(m_Image),
.m_Name = m_Name,
.m_ViewType = m_ViewType,
.m_Components = m_Components,
.m_AspectMask = m_AspectMask,
.m_MipLevelCount = m_MipLevelCount,
.m_LayerCount = m_LayerCount,
.m_BaseMipLevel = m_BaseMipLevel,
.m_BaseLayer = m_BaseLayer,
};
}
};
#pragma endregion
// ----------------------------------------------------------------------------------------------------
#pragma region Sampler
// ----------------------------------------------------------------------------------------------------
struct SamplerCreateInfo
{
cstr m_Name = nullptr;
vk::SamplerCreateFlags m_Flags = {};
vk::Filter m_MagFilter = vk::Filter::eLinear;
vk::Filter m_MinFilter = vk::Filter::eLinear;
vk::SamplerMipmapMode m_MipmapMode = vk::SamplerMipmapMode::eLinear;
vk::SamplerAddressMode m_AddressModeU = vk::SamplerAddressMode::eRepeat;
vk::SamplerAddressMode m_AddressModeV = vk::SamplerAddressMode::eRepeat;
vk::SamplerAddressMode m_AddressModeW = vk::SamplerAddressMode::eRepeat;
vk::BorderColor m_BorderColor = vk::BorderColor::eFloatOpaqueBlack;
vk::CompareOp m_CompareOp = vk::CompareOp::eNever;
f32 m_MipLodBias = 0.0f;
f32 m_MaxAnisotropy = 16.0f;
f32 m_MinLod = 0;
f32 m_MaxLod = VK_LOD_CLAMP_NONE;
bool m_AnisotropyEnable = true;
bool m_CompareEnable = false;
bool m_NormalizedCoordinates = true;
explicit
operator vk::SamplerCreateInfo() const
{
return {
.flags = m_Flags,
.magFilter = m_MagFilter,
.minFilter = m_MinFilter,
.mipmapMode = m_MipmapMode,
.addressModeU = m_AddressModeU,
.addressModeV = m_AddressModeV,
.addressModeW = m_AddressModeW,
.mipLodBias = m_MipLodBias,
.anisotropyEnable = m_AnisotropyEnable,
.maxAnisotropy = m_MaxAnisotropy,
.compareEnable = m_CompareEnable,
.compareOp = m_CompareOp,
.minLod = m_MinLod,
.maxLod = m_MaxLod,
.borderColor = m_BorderColor,
.unnormalizedCoordinates = !m_NormalizedCoordinates,
};
}
};
#pragma endregion
// ----------------------------------------------------------------------------------------------------
#pragma region Pipeline
// ----------------------------------------------------------------------------------------------------
struct PipelineCreationError
{
enum class Kind
{
eNone,
eVulkan,
eSlang,
} m_Kind;
union {
u32 uNone;
vk::Result uVulkanResult;
SlangResult uSlangResult;
};
operator bool() const
{
return m_Kind != Kind::eNone;
}
std::string
What()
{
switch (m_Kind)
{
case Kind::eNone:
return "No Error";
case Kind::eVulkan:
return fmt::format("{}", uVulkanResult);
case Kind::eSlang:
return fmt::format("{}", uSlangResult);
}
return "No Error";
}
PipelineCreationError()
: m_Kind{Kind::eNone}
, uNone{}
{
}
PipelineCreationError(vk::Result result)
: m_Kind{Kind::eVulkan}
, uVulkanResult{result}
{
}
PipelineCreationError(SlangResult result)
: m_Kind{Kind::eSlang}
, uSlangResult{result}
{
}
};
struct AttributeInfo
{
u32 m_Location;
u32 m_Offset;
enum class Format
{
eFloat32X4,
eFloat32X3,
eFloat32X2,
eFloat32,
} m_Format;
[[nodiscard]] vk::Format
GetFormat() const
{
switch (m_Format)
{
case Format::eFloat32X4:
return vk::Format::eR32G32B32A32Sfloat;
case Format::eFloat32X3:
return vk::Format::eR32G32B32Sfloat;
case Format::eFloat32X2:
return vk::Format::eR32G32Sfloat;
case Format::eFloat32:
return vk::Format::eR32Sfloat;
}
return vk::Format::eUndefined;
}
};
struct VertexInput
{
eastl::vector<AttributeInfo> m_Attribute;
u32 m_Stride;
bool m_IsPerInstance;
};
enum class ShaderType
{
eInvalid = 0,
eVertex = vk::ShaderStageFlagBits::eVertex,
eTesselationControl = vk::ShaderStageFlagBits::eTessellationControl,
eTesselationEvaluation = vk::ShaderStageFlagBits::eTessellationEvaluation,
eGeometry = vk::ShaderStageFlagBits::eGeometry,
eFragment = vk::ShaderStageFlagBits::eFragment,
eCompute = vk::ShaderStageFlagBits::eCompute,
eTask = vk::ShaderStageFlagBits::eTaskEXT,
eMesh = vk::ShaderStageFlagBits::eMeshEXT,
eMax,
};
constexpr static u32 ShaderTypeCount = 8;
static_assert(static_cast<u32>(ShaderType::eMax) == 1 + (1 << (ShaderTypeCount - 1)));
struct ShaderInfo
{
std::string_view m_ShaderFile;
eastl::vector<std::string_view> m_EntryPoints;
};
struct GraphicsPipelineCreateInfo
{
eastl::fixed_vector<VertexInput, 4, false> m_VertexInputs;
eastl::fixed_vector<ShaderInfo, 4, false> m_Shaders;
};
#pragma endregion
// ----------------------------------------------------------------------------------------------------
#pragma region Device
// ----------------------------------------------------------------------------------------------------
PhysicalDevice DefaultPhysicalDeviceSelector(const PhysicalDevices &physicalDevices);
using PhysicalDeviceSelectorFn = PhysicalDevice (*)(const PhysicalDevices &);
static_assert(std::convertible_to<decltype(DefaultPhysicalDeviceSelector), PhysicalDeviceSelectorFn>);
struct DeviceCreateInfo
{
std::reference_wrapper<Window> m_Window;
Features m_Features;
cstr m_AppName = "Aster App";
Version m_AppVersion = {0, 1, 0};
PhysicalDeviceSelectorFn m_PhysicalDeviceSelector = DefaultPhysicalDeviceSelector;
std::span<u8> m_PipelineCacheData = {};
eastl::vector<cstr> m_ShaderSearchPaths;
bool m_UseBindless = true;
cstr m_Name = "Primary";
};
#pragma endregion
#pragma endregion
namespace _internal
{
class SyncServer;
}
class Receipt
{
void *m_Opaque;
explicit Receipt(void *opaque)
: m_Opaque{opaque}
{
}
friend _internal::SyncServer;
};
class Device;
struct Frame;
#define DEPRECATE_RAW_CALLS
class Context
{
protected:
vk::CommandBuffer m_Cmd;
friend Device;
friend Frame;
explicit Context(const vk::CommandBuffer cmd)
: m_Cmd{cmd}
{
}
public:
DEPRECATE_RAW_CALLS void Dependency(const vk::DependencyInfo &dependencyInfo);
void Begin();
void End();
};
class GraphicsContext : public Context
{
protected:
friend Device;
friend Frame;
explicit GraphicsContext(const vk::CommandBuffer cmd)
: Context{cmd}
{
}
const Pipeline *m_PipelineInUse;
public:
DEPRECATE_RAW_CALLS void SetViewport(const vk::Viewport &viewport);
void BindVertexBuffer(const Ref<VertexBuffer> &vertexBuffer);
void BindPipeline(const Pipeline &pipeline);
void
PushConstantBlock(auto &block)
{
m_Cmd.pushConstants(m_PipelineInUse->m_Layout, vk::ShaderStageFlagBits::eAllGraphics, 0, sizeof block, &block);
}
void Draw(u32 vertexCount);
void DrawIndexed(u32 indexCount);
DEPRECATE_RAW_CALLS void BeginRendering(const vk::RenderingInfo &renderingInfo);
void EndRendering();
};
class TransferContext : public Context
{
protected:
friend Device;
friend Frame;
Device *m_Device;
explicit TransferContext(Device &device, const vk::CommandBuffer cmd)
: Context{cmd}
, m_Device{&device}
{
}
eastl::vector<Ref<Buffer>> m_OwnedBuffers;
eastl::vector<Ref<Image>> m_OwnedImages;
void Reset();
public:
struct ImageData
{
void *m_Data;
usize m_NumBytes;
};
void UploadTexture(const Ref<Image> &image, const ImageData &data);
TransferContext(TransferContext &&other) noexcept;
TransferContext &operator=(TransferContext &&other) noexcept;
DISALLOW_COPY_AND_ASSIGN(TransferContext);
};
struct Frame
{
// Persistent
Device *m_Device;
// TODO: ThreadSafe
vk::CommandPool m_Pool;
vk::Fence m_FrameAvailableFence;
vk::Semaphore m_ImageAcquireSem;
vk::Semaphore m_RenderFinishSem;
u32 m_FrameIdx;
eastl::vector<vk::CommandBuffer> m_CommandBuffers;
// Transient
vk::Image m_SwapchainImage;
vk::ImageView m_SwapchainImageView;
Size2D m_SwapchainSize;
u32 m_ImageIdx;
u32 m_CommandBuffersAllocated;
void Reset(u32 imageIdx, vk::Image swapchainImage, vk::ImageView swapchainImageView, Size2D swapchainSize);
GraphicsContext CreateGraphicsContext();
TransferContext CreateTransferContext();
void WaitUntilReady();
Frame() = default;
Frame(Device &device, u32 primaryQueueFamily, u32 frameIndex);
Frame(Frame &&other) noexcept;
Frame &operator=(Frame &&other) noexcept;
DISALLOW_COPY_AND_ASSIGN(Frame);
};
class Device final
{
public: // TODO: Temp
std::reference_wrapper<Window> m_Window;
Instance m_Instance;
Surface m_Surface;
::Device m_Device;
Swapchain m_Swapchain;
std::unique_ptr<CommitManager> m_CommitManager;
// TODO: This is single-threaded.
vk::Queue m_GraphicsQueue;
u32 m_PrimaryQueueFamily;
vk::Queue m_TransferQueue;
u32 m_TransferQueueFamily;
std::array<Frame, MAX_FRAMES_IN_FLIGHT> m_Frames;
u32 m_CurrentFrameIdx = 0;
public:
// ====================================================================================================
// Resource Management
// ====================================================================================================
//
// Buffer Management
// ----------------------------------------------------------------------------------------------------
[[nodiscard]] Ref<StorageBuffer> CreateStorageBuffer(usize size, cstr name = nullptr);
[[nodiscard]] Ref<UniformBuffer> CreateUniformBuffer(usize size, cstr name = nullptr);
[[nodiscard]] Ref<StagingBuffer> CreateStagingBuffer(usize size, cstr name = nullptr);
[[nodiscard]] Ref<VertexBuffer> CreateVertexBuffer(usize size, cstr name = nullptr);
//
// Image Management
// ----------------------------------------------------------------------------------------------------
template <concepts::ImageInto<Texture> T>
[[nodiscard]] Ref<T>
CreateTexture2D(const Texture2DCreateInfo &createInfo)
{
return CastImage<T>(CreateTexture2D(createInfo));
}
template <concepts::ImageInto<TextureCube> T>
[[nodiscard]] Ref<T>
CreateTextureCube(const TextureCubeCreateInfo &createInfo)
{
return CastImage<T>(CreateTextureCube(createInfo));
}
[[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);
//
// View Management
// ----------------------------------------------------------------------------------------------------
template <concepts::View TImageView>
Ref<TImageView>
CreateView(const ViewCreateInfo<typename TImageView::ImageType> &createInfo)
{
return CastView<TImageView>(CreateView(ViewCreateInfo<Image>(createInfo)));
}
[[nodiscard]] Ref<ImageView> CreateView(const ViewCreateInfo<Image> &createInfo);
//
// Image - View Combined Management
// ----------------------------------------------------------------------------------------------------
template <concepts::ViewTo<Image> T>
[[nodiscard]] Ref<T>
CreateTexture2DWithView(const Texture2DCreateInfo &createInfo)
{
auto handle = CreateTexture2D(createInfo);
return CastView<T>(handle);
}
template <concepts::ViewTo<ImageCube> T>
[[nodiscard]] Ref<T>
CreateTextureCubeWithView(const TextureCubeCreateInfo &createInfo)
{
auto handle = CreateTextureCube(createInfo);
return CastView<T>(handle);
}
[[nodiscard]] Ref<TextureView> CreateTexture2DWithView(const Texture2DCreateInfo &createInfo);
[[nodiscard]] Ref<ImageCubeView> CreateTextureCubeWithView(const TextureCubeCreateInfo &createInfo);
[[nodiscard]] Ref<ImageView> CreateAttachmentWithView(const AttachmentCreateInfo &createInfo);
[[nodiscard]] Ref<ImageView> CreateDepthStencilImageWithView(const DepthStencilImageCreateInfo &createInfo);
//
// Sampler Management
// ----------------------------------------------------------------------------------------------------
private:
eastl::hash_map<vk::SamplerCreateInfo, WeakRef<Sampler>> m_HashToSamplerIdx;
public:
Ref<Sampler> CreateSampler(const SamplerCreateInfo &createInfo);
//
// Pipeline
// ----------------------------------------------------------------------------------------------------
// TODO: Cache shader modules for reuse. Time to move to `slang`
private:
Slang::ComPtr<slang::IGlobalSession> m_GlobalSlangSession;
Slang::ComPtr<slang::ISession> m_SlangSession;
PipelineCreationError
CreateShaders(eastl::fixed_vector<vk::PipelineShaderStageCreateInfo, ShaderTypeCount, false> &shadersOut,
Slang::ComPtr<slang::IComponentType> &program, const std::span<const ShaderInfo> &shaders);
PipelineCreationError
CreatePipelineLayout(vk::PipelineLayout &pipelineLayout, const Slang::ComPtr<slang::IComponentType> &program);
public:
// Pipelines, unlike the other resources, are not ref-counted.
PipelineCreationError CreatePipeline(Pipeline &pipeline, const GraphicsPipelineCreateInfo &createInfo);
//
// Frames
// ----------------------------------------------------------------------------------------------------
private:
Frame CreateFrame(u32 frameIndex);
public:
Frame &GetNextFrame();
Size2D
GetSwapchainSize() const
{
return {m_Swapchain.m_Extent.width, m_Swapchain.m_Extent.height};
}
void Present(Frame &frame, GraphicsContext &graphicsContext);
//
// Context
// ----------------------------------------------------------------------------------------------------
friend Context;
friend GraphicsContext;
friend TransferContext;
vk::CommandPool m_TransferPool;
eastl::deque<TransferContext> m_TransferContexts;
eastl::vector<u32> m_TransferContextFreeList;
TransferContext &CreateTransferContext();
Receipt Submit(Context &context);
//
// Sync
// ----------------------------------------------------------------------------------------------------
std::unique_ptr<_internal::SyncServer> m_SyncServer;
void WaitOn(Receipt recpt);
//
// Device Methods
// ----------------------------------------------------------------------------------------------------
template <concepts::VkHandle T>
void
SetName(const T &object, cstr name) const
{
m_Device.SetName(object, name);
}
[[nodiscard]] vk::Queue
GetQueue(const u32 familyIndex, const u32 queueIndex) const
{
return m_Device.GetQueue(familyIndex, queueIndex);
}
[[nodiscard]] eastl::vector<u8>
DumpPipelineCache() const
{
return m_Device.DumpPipelineCache();
}
void
WaitIdle() const
{
m_Device.WaitIdle();
}
// Inner
// ----------------------------------------------------------------------------------------------------
[[nodiscard]] ::Device &
GetInner()
{
return m_Device;
}
[[nodiscard]] vk::Device &
GetHandle()
{
return m_Device.m_Device;
}
// Ctor/Dtor
// ----------------------------------------------------------------------------------------------------
explicit Device(const DeviceCreateInfo &createInfo);
~Device();
PIN_MEMORY(Device);
};
} // namespace systems

View File

@ -1,84 +0,0 @@
// =============================================
// Aster: image_manager.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "aster/aster.h"
#include "aster/core/image.h"
namespace systems
{
template <std::derived_from<Image> TTo, std::derived_from<Image> TFrom>
static Ref<TTo>
CastImage(const Ref<TFrom> &from)
{
if constexpr (not concepts::ImageInto<TFrom, TTo>)
assert(TTo::FLAGS & from->m_Flags_);
return std::reinterpret_pointer_cast<TTo>(from);
}
struct Texture2DCreateInfo
{
vk::Format m_Format = vk::Format::eUndefined;
vk::Extent2D m_Extent = {};
cstr m_Name = nullptr;
bool m_IsSampled = true;
bool m_IsMipMapped = false;
bool m_IsStorage = false;
};
struct TextureCubeCreateInfo
{
vk::Format m_Format = vk::Format::eUndefined;
u32 m_Side = 0;
cstr m_Name = nullptr;
bool m_IsSampled = true;
bool m_IsMipMapped = false;
bool m_IsStorage = false;
};
struct AttachmentCreateInfo
{
vk::Format m_Format = vk::Format::eUndefined;
vk::Extent2D m_Extent = {};
cstr m_Name = nullptr;
};
struct DepthStencilImageCreateInfo
{
vk::Extent2D m_Extent = {};
cstr m_Name = nullptr;
};
class ImageManager final
{
const Device *m_Device;
public:
explicit ImageManager(const Device *device);
template <concepts::ImageInto<Texture> T>
[[nodiscard]] Ref<T>
CreateTexture2D(const Texture2DCreateInfo &createInfo)
{
auto handle = CreateTexture2D(createInfo);
return CastImage<T>(handle);
}
template <concepts::ImageInto<TextureCube> 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

View File

@ -5,11 +5,63 @@
#pragma once
#include "aster/core/buffer.h"
#include "aster/core/image.h"
#include "aster/core/image_view.h"
#include <EASTL/intrusive_ptr.h>
namespace systems
{
// ====================================================================================================
#pragma region Util Methods
// ====================================================================================================
#pragma region Buffer
// ----------------------------------------------------------------------------------------------------
template <std::derived_from<Buffer> TTo, std::derived_from<Buffer> TFrom>
static Ref<TTo>
CastBuffer(const Ref<TFrom> &from)
{
if constexpr (not concepts::BufferInto<TFrom, TTo>)
assert(TTo::FLAGS & from->m_Flags);
return std::reinterpret_pointer_cast<TTo>(from);
}
#pragma endregion
#pragma region Image
// ----------------------------------------------------------------------------------------------------
template <std::derived_from<Image> TTo, std::derived_from<Image> TFrom>
static Ref<TTo>
CastImage(const Ref<TFrom> &from)
{
if constexpr (not concepts::ImageInto<TFrom, TTo>)
assert(TTo::FLAGS & from->m_Flags_);
return std::reinterpret_pointer_cast<TTo>(from);
}
#pragma endregion
#pragma region View
// ----------------------------------------------------------------------------------------------------
template <concepts::View TTo, std::derived_from<Image> TFrom>
static Ref<TTo>
CastView(const Ref<View<TFrom>> &from)
{
if constexpr (not concepts::ImageInto<TFrom, typename TTo::ImageType>)
assert(TTo::ImageType::FLAGS & from->m_Image->m_Flags_);
return std::reinterpret_pointer_cast<TTo>(from);
}
#pragma endregion
#pragma endregion
/**
* ResId manages the lifetime of the committed resource.
* @tparam T Type of the committed resource.

View File

@ -1,142 +0,0 @@
// =============================================
// Aster: resource_manager.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "aster/aster.h"
#include "buffer_manager.h"
#include "image_manager.h"
#include "sampler_manager.h"
#include "view_manager.h"
namespace systems
{
class ResourceManager
{
struct CombinedImageViewManager
{
ImageManager *m_ImageManager;
ViewManager *m_ViewManager;
CombinedImageViewManager(ImageManager *imageManager, ViewManager *viewManager)
: m_ImageManager{imageManager}
, m_ViewManager{viewManager}
{
}
template <concepts::ViewTo<Image> T>
[[nodiscard]] Ref<T>
CreateTexture2D(const Texture2DCreateInfo &createInfo)
{
auto handle = CreateTexture2D(createInfo);
return CastView<T>(handle);
}
template <concepts::ViewTo<ImageCube> T>
[[nodiscard]] Ref<T>
CreateTextureCube(const TextureCubeCreateInfo &createInfo)
{
auto handle = CreateTextureCube(createInfo);
return CastView<T>(handle);
}
[[nodiscard]] Ref<TextureView>
CreateTexture2D(const Texture2DCreateInfo &createInfo) const
{
return m_ViewManager->CreateView<TextureView>({
.m_Image = CastImage<Texture>(m_ImageManager->CreateTexture2D(createInfo)),
.m_Name = createInfo.m_Name,
.m_ViewType = vk::ImageViewType::e2D,
.m_AspectMask = vk::ImageAspectFlagBits::eColor,
});
}
[[nodiscard]] Ref<ImageCubeView>
CreateTextureCube(const TextureCubeCreateInfo &createInfo) const
{
return m_ViewManager->CreateView<ImageCubeView>({
.m_Image = m_ImageManager->CreateTextureCube(createInfo),
.m_Name = createInfo.m_Name,
.m_ViewType = vk::ImageViewType::eCube,
.m_AspectMask = vk::ImageAspectFlagBits::eColor,
});
}
[[nodiscard]] Ref<ImageView>
CreateAttachment(const AttachmentCreateInfo &createInfo) const
{
return m_ViewManager->CreateView({
.m_Image = m_ImageManager->CreateAttachment(createInfo),
.m_Name = createInfo.m_Name,
.m_ViewType = vk::ImageViewType::e2D,
.m_AspectMask = vk::ImageAspectFlagBits::eColor,
});
}
[[nodiscard]] Ref<ImageView>
CreateDepthStencilImage(const DepthStencilImageCreateInfo &createInfo) const
{
return m_ViewManager->CreateView({
.m_Image = m_ImageManager->CreateDepthStencilImage(createInfo),
.m_Name = createInfo.m_Name,
.m_ViewType = vk::ImageViewType::e2D,
.m_AspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
});
}
};
BufferManager m_Buffers;
ImageManager m_Images;
SamplerManager m_Samplers;
ViewManager m_Views;
CombinedImageViewManager m_CombinedImageViews;
public:
explicit ResourceManager(const Device *device)
: m_Buffers{device}
, m_Images{device}
, m_Samplers{device}
, m_Views{device}
, m_CombinedImageViews{&m_Images, &m_Views}
{
}
BufferManager &
Buffers()
{
return m_Buffers;
}
ImageManager &
Images()
{
return m_Images;
}
ViewManager &
Views()
{
return m_Views;
}
SamplerManager &
Samplers()
{
return m_Samplers;
}
CombinedImageViewManager &
CombinedImageViews()
{
return m_CombinedImageViews;
}
~ResourceManager() = default;
PIN_MEMORY(ResourceManager);
};
} // namespace systems

View File

@ -1,112 +0,0 @@
// =============================================
// Aster: sampler_manager.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "EASTL/hash_map.h"
#include "aster/aster.h"
#include "aster/core/sampler.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
{
struct SamplerCreateInfo
{
cstr m_Name = nullptr;
vk::SamplerCreateFlags m_Flags = {};
vk::Filter m_MagFilter = vk::Filter::eLinear;
vk::Filter m_MinFilter = vk::Filter::eLinear;
vk::SamplerMipmapMode m_MipmapMode = vk::SamplerMipmapMode::eLinear;
vk::SamplerAddressMode m_AddressModeU = vk::SamplerAddressMode::eRepeat;
vk::SamplerAddressMode m_AddressModeV = vk::SamplerAddressMode::eRepeat;
vk::SamplerAddressMode m_AddressModeW = vk::SamplerAddressMode::eRepeat;
vk::BorderColor m_BorderColor = vk::BorderColor::eFloatOpaqueBlack;
vk::CompareOp m_CompareOp = vk::CompareOp::eNever;
f32 m_MipLodBias = 0.0f;
f32 m_MaxAnisotropy = 16.0f;
f32 m_MinLod = 0;
f32 m_MaxLod = VK_LOD_CLAMP_NONE;
bool m_AnisotropyEnable = true;
bool m_CompareEnable = false;
bool m_NormalizedCoordinates = true;
explicit
operator vk::SamplerCreateInfo() const
{
return {
.flags = m_Flags,
.magFilter = m_MagFilter,
.minFilter = m_MinFilter,
.mipmapMode = m_MipmapMode,
.addressModeU = m_AddressModeU,
.addressModeV = m_AddressModeV,
.addressModeW = m_AddressModeW,
.mipLodBias = m_MipLodBias,
.anisotropyEnable = m_AnisotropyEnable,
.maxAnisotropy = m_MaxAnisotropy,
.compareEnable = m_CompareEnable,
.compareOp = m_CompareOp,
.minLod = m_MinLod,
.maxLod = m_MaxLod,
.borderColor = m_BorderColor,
.unnormalizedCoordinates = !m_NormalizedCoordinates,
};
}
};
/**
* @class SamplerManager sampler_manager.h
*
* Manages (and caches) objects of sampler. Currently Samplers are never deleted.
*/
class SamplerManager final
{
using Handle = Ref<Sampler>;
using WeakHandle = WeakRef<Sampler>;
eastl::hash_map<vk::SamplerCreateInfo, WeakHandle> m_HashToSamplerIdx;
const Device *m_Device;
public:
explicit SamplerManager(const Device *device);
~SamplerManager();
Ref<Sampler> CreateSampler(const SamplerCreateInfo &createInfo);
};
} // namespace systems

View File

@ -0,0 +1,69 @@
// =============================================
// Aster: sync_server.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "aster/aster.h"
#include <EASTL/deque.h>
#include <EASTL/intrusive_list.h>
namespace systems
{
class Receipt;
class Device;
} // namespace systems
namespace systems::_internal
{
struct TimelinePoint
{
u64 m_WaitValue;
u64 m_NextValue;
};
class SyncServer
{
struct Entry : eastl::intrusive_list_node
{
vk::Semaphore m_Semaphore;
TimelinePoint m_CurrentPoint;
static Entry Create(Device &device);
void Destroy(Device &device);
void Wait(Device &device);
void Next();
};
Device *m_Device;
eastl::deque<Entry> m_Allocations;
eastl::intrusive_list<Entry> m_FreeList;
public:
Receipt Allocate();
void Free(Receipt);
void WaitOn(Receipt);
private:
static Entry &GetEntry(Receipt receipt);
// Inner Alloc/Free functions.
Entry &AllocateEntry();
void FreeEntry(Entry &entry);
// Constructor/Destructor
explicit SyncServer(Device &device);
public:
~SyncServer();
// Move Constructors.
SyncServer(SyncServer &&other) noexcept;
SyncServer &operator=(SyncServer &&other) noexcept;
friend Device;
DISALLOW_COPY_AND_ASSIGN(SyncServer);
};
} // namespace systems::_internal

View File

@ -1,105 +0,0 @@
// =============================================
// Aster: view_manager.h
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#pragma once
#include "aster/aster.h"
#include "aster/core/image_view.h"
#include <EASTL/optional.h>
namespace systems
{
template <concepts::View TTo, std::derived_from<Image> TFrom>
static Ref<TTo>
CastView(const Ref<View<TFrom>> &from)
{
if constexpr (not concepts::ImageInto<TFrom, typename TTo::ImageType>)
assert(TTo::ImageType::FLAGS & from->m_Image->m_Flags_);
return std::reinterpret_pointer_cast<TTo>(from);
}
template <concepts::AnyImage TImage>
struct ViewCreateInfo
{
using ImageType = TImage;
Ref<ImageType> m_Image;
cstr m_Name;
vk::ImageViewType m_ViewType = vk::ImageViewType::e2D;
vk::ComponentMapping m_Components = {};
vk::ImageAspectFlags m_AspectMask = {};
eastl::optional<u8> m_MipLevelCount = eastl::nullopt;
eastl::optional<u8> m_LayerCount = eastl::nullopt;
u8 m_BaseMipLevel = 0;
u8 m_BaseLayer = 0;
[[nodiscard]] u8
GetMipLevelCount() const
{
return m_MipLevelCount.value_or(m_Image->m_MipLevels - m_BaseMipLevel);
}
[[nodiscard]] u8
GetLayerCount() const
{
return m_LayerCount.value_or(m_Image->m_LayerCount - m_BaseLayer);
}
explicit
operator vk::ImageViewCreateInfo() const
{
return {
.image = m_Image->m_Image,
.viewType = m_ViewType,
.format = m_Image->m_Format,
.components = m_Components,
.subresourceRange =
{
.aspectMask = m_AspectMask,
.baseMipLevel = m_BaseMipLevel,
.levelCount = GetMipLevelCount(),
.baseArrayLayer = m_BaseLayer,
.layerCount = GetLayerCount(),
},
};
}
explicit
operator ViewCreateInfo<Image>() const
{
return {
.m_Image = CastImage<Image>(m_Image),
.m_Name = m_Name,
.m_ViewType = m_ViewType,
.m_Components = m_Components,
.m_AspectMask = m_AspectMask,
.m_MipLevelCount = m_MipLevelCount,
.m_LayerCount = m_LayerCount,
.m_BaseMipLevel = m_BaseMipLevel,
.m_BaseLayer = m_BaseLayer,
};
}
};
class ViewManager final
{
const Device *m_Device;
public:
explicit ViewManager(const Device *device);
template <concepts::View TImageView>
Ref<TImageView>
CreateView(const ViewCreateInfo<typename TImageView::ImageType> &createInfo)
{
return CastView<TImageView>(CreateView(ViewCreateInfo<Image>(createInfo)));
}
[[nodiscard]] Ref<ImageView> CreateView(const ViewCreateInfo<Image> &createInfo) const;
};
} // namespace systems

View File

@ -5,4 +5,5 @@ cmake_minimum_required(VERSION 3.13)
target_sources(aster_core
INTERFACE
"logger.h"
"freelist.h")
"freelist.h"
"files.h")

View File

@ -0,0 +1,15 @@
// =============================================
// Aster: files.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "aster/core/constants.h"
#include <EASTL/span.h>
#include <EASTL/vector.h>
eastl::vector<u32> ReadFile(std::string_view fileName);
eastl::vector<u8> ReadFileBytes(std::string_view fileName, bool errorOnFail = true);
bool WriteFileBytes(std::string_view fileName, eastl::span<u8> data);

View File

@ -61,7 +61,7 @@ struct FreeList
Pop()
{
assert(m_Top);
Reference ref = *Recast<Pointer>(m_Top);
Reference ref = *reinterpret_cast<Pointer>(m_Top);
m_Top = m_Top->m_Next;
return ref;
}
@ -69,7 +69,7 @@ struct FreeList
void
Push(Reference ref)
{
auto next = Recast<FreeListNode *>(&ref);
auto next = reinterpret_cast<FreeListNode *>(&ref);
next->m_Next = m_Top;
m_Top = next;
}

View File

@ -20,12 +20,12 @@ struct Logger
eVerbose,
};
u32 m_MinimumLoggingLevel{Cast<u32>(LogType::eDebug)};
u32 m_MinimumLoggingLevel{static_cast<u32>(LogType::eDebug)};
void
SetMinimumLoggingLevel(LogType logType)
{
m_MinimumLoggingLevel = Cast<u32>(logType);
m_MinimumLoggingLevel = static_cast<u32>(logType);
}
template <LogType TLogLevel>
@ -64,7 +64,7 @@ struct Logger
void
Log(const std::string_view &message, const char *loc, u32 line) const
{
if (Cast<u32>(TLogLevel) <= m_MinimumLoggingLevel)
if (static_cast<u32>(TLogLevel) <= m_MinimumLoggingLevel)
{
fmt::println("{}{} {} {} at {}:{}{}", ToColorCstr<TLogLevel>(), ToCstr<TLogLevel>(), message.data(),
ansi_color::Black, loc, line, ansi_color::Reset);
@ -81,7 +81,7 @@ struct Logger
void
LogCond(const char *exprStr, const std::string_view &message, const char *loc, u32 line) const
{
if (Cast<u32>(TLogLevel) <= m_MinimumLoggingLevel)
if (static_cast<u32>(TLogLevel) <= m_MinimumLoggingLevel)
{
fmt::println("{}{} ({}) {} {} at {}:{}{}", ToColorCstr<TLogLevel>(), ToCstr<TLogLevel>(), exprStr,
message.data(), ansi_color::Black, loc, line, ansi_color::Reset);
@ -103,26 +103,26 @@ extern Logger g_Logger;
#define INFO(...) g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ERROR_IF(expr, ...) \
if (Cast<bool>(expr)) [[unlikely]] \
if (static_cast<bool>(expr)) [[unlikely]] \
g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define WARN_IF(expr, ...) \
if (Cast<bool>(expr)) [[unlikely]] \
if (static_cast<bool>(expr)) [[unlikely]] \
g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define INFO_IF(expr, ...) \
if (Cast<bool>(expr)) \
if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_ERROR(expr, ...) \
; \
else if (Cast<bool>(expr)) \
else if (static_cast<bool>(expr)) \
[[unlikely]] g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_WARN(expr, ...) \
; \
else if (Cast<bool>(expr)) \
else if (static_cast<bool>(expr)) \
[[unlikely]] g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_INFO(expr, ...) \
; \
else if (Cast<bool>(expr)) \
else if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_ERROR(...) \
@ -139,11 +139,11 @@ extern Logger g_Logger;
#define DEBUG(...) g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define DEBUG_IF(expr, ...) \
if (Cast<bool>(expr)) \
if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_DEBUG(expr, ...) \
; \
else if (Cast<bool>(expr)) \
else if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_DEBUG(...) \
; \
@ -174,11 +174,11 @@ extern Logger g_Logger;
#define VERBOSE(...) g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define VERBOSE_IF(expr, ...) \
if (Cast<bool>(expr)) \
if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_VERBOSE(expr, ...) \
; \
else if (Cast<bool>(expr)) \
else if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_VERBOSE(...) \
; \
@ -207,5 +207,5 @@ extern Logger g_Logger;
#endif // !defined(VERBOSE_LOG_DISABLED)
#define DO(code) , code
#define ABORT(code) exit(Cast<i32>(code))
#define ABORT(code) exit(static_cast<i32>(code))
#define THEN_ABORT(code) , ABORT(code)

View File

@ -27,7 +27,7 @@ Buffer::Buffer(const Device *device, const usize size, const vk::BufferUsageFlag
VkBuffer buffer;
VmaAllocation allocation;
VmaAllocationInfo allocationInfo;
auto result = Cast<vk::Result>(vmaCreateBuffer(device->m_Allocator, Recast<VkBufferCreateInfo *>(&bufferCreateInfo),
auto result = static_cast<vk::Result>(vmaCreateBuffer(device->m_Allocator, reinterpret_cast<VkBufferCreateInfo *>(&bufferCreateInfo),
&allocationCreateInfo, &buffer, &allocation, &allocationInfo));
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
@ -35,12 +35,12 @@ Buffer::Buffer(const Device *device, const usize size, const vk::BufferUsageFlag
// vmaGetAllocationMemoryProperties(device->m_Allocator, allocation, Recast<VkMemoryPropertyFlags
// *>(&memoryPropertyFlags));
// TODO: Actually track Host Access
// bool hostAccessible = Cast<bool>(memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible);
// bool hostAccessible = static_cast<bool>(memoryPropertyFlags & vk::MemoryPropertyFlagBits::eHostVisible);
m_Buffer = buffer;
m_Size = size;
m_Allocation = allocation;
m_Mapped = Cast<u8 *>(allocationInfo.pMappedData);
m_Mapped = static_cast<u8 *>(allocationInfo.pMappedData);
m_Flags = {};
if (bufferUsage & vk::BufferUsageFlagBits::eTransferSrc)
m_Flags |= FlagBits::eStaging;
@ -104,6 +104,6 @@ Buffer::Write(const usize offset, const usize size, const void *data) const
memcpy(m_Mapped + offset, data, size);
// TODO: Debug this.
// auto result = Cast<vk::Result>(vmaCopyMemoryToAllocation(device->m_Allocator, &data, m_Allocation, 0, size));
// auto result = static_cast<vk::Result>(vmaCopyMemoryToAllocation(device->m_Allocator, &data, m_Allocation, 0, size));
// ERROR_IF(Failed(result), "Writing to buffer failed. Cause: {}", result) THEN_ABORT(result);
}

View File

@ -17,18 +17,12 @@ constexpr eastl::array DEVICE_EXTENSIONS = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
const eastl::vector<QueueAllocation> &queueAllocations, NameString &&name)
: Device(context, physicalDevice, enabledFeatures, queueAllocations, {}, std::move(name))
{
}
Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
const eastl::vector<QueueAllocation> &queueAllocations, eastl::span<u8> &&pipelineCacheData,
Device::Device(const Instance &context, PhysicalDevice &physicalDevice, Features &enabledFeatures,
const eastl::span<QueueAllocation> &queueAllocations, const eastl::span<u8> &pipelineCacheData,
NameString &&name)
: m_Name(std::move(name))
, m_PhysicalDevice(physicalDevice->m_PhysicalDevice)
, m_ValidationEnabled(context->m_DebugMessenger != nullptr)
, m_PhysicalDevice(physicalDevice.m_PhysicalDevice)
, m_ValidationEnabled(context.m_DebugMessenger != nullptr)
{
// Shouldn't have more than 4 deviceQueueFamilies in use anyway. Else we can heap
eastl::fixed_vector<vk::DeviceQueueCreateInfo, 4> deviceQueueCreateInfos;
@ -51,19 +45,19 @@ Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features
});
}
vk::PhysicalDeviceFeatures *deviceFeatures = &enabledFeatures->m_Vulkan10Features;
vk::PhysicalDeviceVulkan11Features *vulkan11Features = &enabledFeatures->m_Vulkan11Features;
vk::PhysicalDeviceVulkan12Features *vulkan12Features = &enabledFeatures->m_Vulkan12Features;
vk::PhysicalDeviceVulkan13Features *vulkan13Features = &enabledFeatures->m_Vulkan13Features;
vk::PhysicalDeviceFeatures *deviceFeatures = &enabledFeatures.m_Vulkan10Features;
vk::PhysicalDeviceVulkan11Features *vulkan11Features = &enabledFeatures.m_Vulkan11Features;
vk::PhysicalDeviceVulkan12Features *vulkan12Features = &enabledFeatures.m_Vulkan12Features;
vk::PhysicalDeviceVulkan13Features *vulkan13Features = &enabledFeatures.m_Vulkan13Features;
vulkan11Features->pNext = vulkan12Features;
vulkan12Features->pNext = vulkan13Features;
vk::DeviceCreateInfo deviceCreateInfo = {
.pNext = vulkan11Features,
.queueCreateInfoCount = Cast<u32>(deviceQueueCreateInfos.size()),
.queueCreateInfoCount = static_cast<u32>(deviceQueueCreateInfos.size()),
.pQueueCreateInfos = deviceQueueCreateInfos.data(),
.enabledExtensionCount = Cast<u32>(DEVICE_EXTENSIONS.size()),
.enabledExtensionCount = static_cast<u32>(DEVICE_EXTENSIONS.size()),
.ppEnabledExtensionNames = DEVICE_EXTENSIONS.data(),
.pEnabledFeatures = deviceFeatures,
};
@ -71,13 +65,13 @@ Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features
vk::Result result = m_PhysicalDevice.createDevice(&deviceCreateInfo, nullptr, &m_Device);
ERROR_IF(Failed(result), "Could not initialize Vulkan Device. Cause: {}", result)
THEN_ABORT(result)
ELSE_DEBUG("{} ({}) Initialized.", m_Name, physicalDevice->m_DeviceProperties.deviceName.data());
ELSE_DEBUG("{} ({}) Initialized.", m_Name, physicalDevice.m_DeviceProperties.deviceName.data());
SetName(m_Device, m_Name.data());
VmaVulkanFunctions vmaVulkanFunctions = {
.vkGetInstanceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
.vkGetDeviceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
.vkGetInstanceProcAddr = vk::detail::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
.vkGetDeviceProcAddr = vk::detail::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
};
const VmaAllocatorCreateInfo allocatorCreateInfo = {
@ -85,11 +79,11 @@ Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features
.physicalDevice = m_PhysicalDevice,
.device = m_Device,
.pVulkanFunctions = &vmaVulkanFunctions,
.instance = context->m_Instance,
.instance = context.m_Instance,
.vulkanApiVersion = ASTER_API_VERSION,
};
result = Cast<vk::Result>(vmaCreateAllocator(&allocatorCreateInfo, &m_Allocator));
result = static_cast<vk::Result>(vmaCreateAllocator(&allocatorCreateInfo, &m_Allocator));
ERROR_IF(Failed(result), "Memory allocator creation failed. Cause: {}", result)
DO(m_Device.destroy(nullptr))
THEN_ABORT(result)
@ -110,6 +104,9 @@ Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features
Device::~Device()
{
if (!m_Device)
return;
m_Device.destroy(m_PipelineCache, nullptr);
if (m_Allocator)
{
@ -156,6 +153,7 @@ Device::Device(Device &&other) noexcept
, m_PhysicalDevice(Take(other.m_PhysicalDevice))
, m_Device(Take(other.m_Device))
, m_Allocator(Take(other.m_Allocator))
, m_PipelineCache(Take(other.m_PipelineCache))
{
}
@ -168,5 +166,6 @@ Device::operator=(Device &&other) noexcept
m_PhysicalDevice = Take(other.m_PhysicalDevice);
m_Device = Take(other.m_Device);
m_Allocator = Take(other.m_Allocator);
m_PipelineCache = Take(other.m_PipelineCache);
return *this;
}

View File

@ -30,7 +30,7 @@ struct MemorySize
m_Kilobytes = totalKb % 1024;
const usize totalMb = m_Megabytes + totalKb / 1024;
m_Megabytes = totalMb % 1024;
m_Gigabytes += Cast<u16>(totalMb / 1024);
m_Gigabytes += static_cast<u16>(totalMb / 1024);
return *this;
}
@ -56,18 +56,18 @@ struct fmt::formatter<MemorySize>
// return format_to(ctx.out(), "({}, {})", foo.a, foo.b); // --== KEY LINE ==--
if (mem.m_Gigabytes > 0)
{
return v10::format_to(ctx.out(), "{}.{} GB", mem.m_Gigabytes, Cast<u16>(mem.m_Megabytes / 1024.0));
return v11::format_to(ctx.out(), "{}.{} GB", mem.m_Gigabytes, static_cast<u16>(mem.m_Megabytes / 1024.0));
}
if (mem.m_Megabytes > 0)
{
return v10::format_to(ctx.out(), "{}.{} MB", mem.m_Megabytes, Cast<u16>(mem.m_Kilobytes / 1024.0));
return v11::format_to(ctx.out(), "{}.{} MB", mem.m_Megabytes, static_cast<u16>(mem.m_Kilobytes / 1024.0));
}
if (mem.m_Kilobytes > 0)
{
return v10::format_to(ctx.out(), "{}.{} KB", mem.m_Kilobytes, Cast<u16>(mem.m_Bytes / 1024.0));
return v11::format_to(ctx.out(), "{}.{} KB", mem.m_Kilobytes, static_cast<u16>(mem.m_Bytes / 1024.0));
}
return v10::format_to(ctx.out(), "{} Bytes", mem.m_Bytes);
return v11::format_to(ctx.out(), "{} Bytes", mem.m_Bytes);
}
};

View File

@ -48,7 +48,7 @@ Image::DestroyView(const vk::ImageView imageView) const
// 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>");
//
// const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
// const u8 mipLevels = isMipMapped ? 1 + static_cast<u8>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
//
// auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
// if (isMipMapped)
@ -75,7 +75,7 @@ Image::DestroyView(const vk::ImageView imageView) const
//
// VkImage image;
// VmaAllocation allocation;
// auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
// auto result = static_cast<vk::Result>(vmaCreateImage(device->m_Allocator, reinterpret_cast<VkImageCreateInfo *>(&imageCreateInfo),
// &allocationCreateInfo, &image, &allocation, nullptr));
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
//
@ -132,7 +132,7 @@ Image::DestroyView(const vk::ImageView imageView) const
// WARN_IF(!IsPowerOfTwo(cubeSide), "Image Cube {1} has side {0}x{0} (Non Power of Two)", cubeSide,
// name ? name : "<unnamed>");
//
// const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(cubeSide))) : 1;
// const u8 mipLevels = isMipMapped ? 1 + static_cast<u8>(floor(log2(cubeSide))) : 1;
//
// auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
// if (isMipMapped)
@ -162,7 +162,7 @@ Image::DestroyView(const vk::ImageView imageView) const
//
// VkImage image;
// VmaAllocation allocation;
// auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
// auto result = static_cast<vk::Result>(vmaCreateImage(device->m_Allocator, reinterpret_cast<VkImageCreateInfo *>(&imageCreateInfo),
// &allocationCreateInfo, &image, &allocation, nullptr));
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
//
@ -217,7 +217,7 @@ Image::DestroyView(const vk::ImageView imageView) const
//
// VkImage image;
// VmaAllocation allocation;
// auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
// auto result = static_cast<vk::Result>(vmaCreateImage(device->m_Allocator, reinterpret_cast<VkImageCreateInfo *>(&imageCreateInfo),
// &allocationCreateInfo, &image, &allocation, nullptr));
// ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result);
//
@ -274,7 +274,7 @@ Image::DestroyView(const vk::ImageView imageView) const
//
// VkImage image;
// VmaAllocation allocation;
// auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
// auto result = static_cast<vk::Result>(vmaCreateImage(device->m_Allocator, reinterpret_cast<VkImageCreateInfo *>(&imageCreateInfo),
// &allocationCreateInfo, &image, &allocation, nullptr));
// ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result);
//
@ -344,7 +344,7 @@ Image::DestroyView(const vk::ImageView imageView) const
//
// VkImage image;
// VmaAllocation allocation;
// auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
// auto result = static_cast<vk::Result>(vmaCreateImage(device->m_Allocator, reinterpret_cast<VkImageCreateInfo *>(&imageCreateInfo),
// &allocationCreateInfo, &image, &allocation, nullptr));
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
//
@ -395,7 +395,7 @@ Image::DestroyView(const vk::ImageView imageView) const
// usage |= vk::ImageUsageFlagBits::eSampled;
// }
//
// const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(cubeSide))) : 1;
// const u8 mipLevels = isMipMapped ? 1 + static_cast<u8>(floor(log2(cubeSide))) : 1;
//
// vk::ImageCreateInfo imageCreateInfo = {
// .flags = vk::ImageCreateFlagBits::eCubeCompatible,
@ -417,7 +417,7 @@ Image::DestroyView(const vk::ImageView imageView) const
//
// VkImage image;
// VmaAllocation allocation;
// auto result = Cast<vk::Result>(vmaCreateImage(device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
// auto result = static_cast<vk::Result>(vmaCreateImage(device->m_Allocator, reinterpret_cast<VkImageCreateInfo *>(&imageCreateInfo),
// &allocationCreateInfo, &image, &allocation, nullptr));
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
//

View File

@ -5,30 +5,28 @@
#include "core/instance.h"
#include "core/window.h"
#include <EASTL/array.h>
#include <EASTL/fixed_vector.h>
VKAPI_ATTR b32 VKAPI_CALL
DebugCallback(const VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
const VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT *callbackData, [[maybe_unused]] void *userData)
DebugCallback(const vk::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
const vk::DebugUtilsMessageTypeFlagsEXT messageType,
const vk::DebugUtilsMessengerCallbackDataEXT *callbackData, [[maybe_unused]] void *userData)
{
using Severity = vk::DebugUtilsMessageSeverityFlagsEXT;
using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT;
using MessageType = vk::DebugUtilsMessageTypeFlagsEXT;
using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT;
const auto severity = Severity(messageSeverity);
if (MessageType(messageType) & MessageTypeBits::eValidation)
if (messageType & MessageTypeBits::eValidation)
{
if (severity & SeverityBits::eError)
if (messageSeverity & SeverityBits::eError)
ERROR("{}", callbackData->pMessage);
if (severity & SeverityBits::eWarning)
if (messageSeverity & SeverityBits::eWarning)
WARN("{}", callbackData->pMessage);
if (severity & SeverityBits::eInfo)
if (messageSeverity & SeverityBits::eInfo)
INFO("{}", callbackData->pMessage);
if (severity & SeverityBits::eVerbose)
if (messageSeverity & SeverityBits::eVerbose)
VERBOSE("{}", callbackData->pMessage);
}
@ -61,15 +59,15 @@ Instance::Instance(const cstr appName, const Version version, bool enableValidat
.pUserData = nullptr,
};
u32 glfwExtensionCount = 0;
cstr *glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
eastl::fixed_vector<cstr, 3> instanceExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
u32 windowExtensionCount = 0;
cstr *windowExtensions = Window::GetInstanceExtensions(&windowExtensionCount);
eastl::fixed_vector<cstr, 3> instanceExtensions(windowExtensions, windowExtensions + windowExtensionCount);
if (enableValidation)
{
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
const vk::DynamicLoader dl;
const vk::detail::DynamicLoader dl;
// ReSharper disable once CppInconsistentNaming
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
@ -77,7 +75,7 @@ Instance::Instance(const cstr appName, const Version version, bool enableValidat
const auto instanceCreateInfo = vk::InstanceCreateInfo{
.pNext = enableValidation ? &debugUtilsMessengerCreateInfo : nullptr,
.pApplicationInfo = &appInfo,
.enabledExtensionCount = Cast<u32>(instanceExtensions.size()),
.enabledExtensionCount = static_cast<u32>(instanceExtensions.size()),
.ppEnabledExtensionNames = instanceExtensions.data(),
};
@ -99,6 +97,9 @@ Instance::Instance(const cstr appName, const Version version, bool enableValidat
Instance::~Instance()
{
if (!m_Instance)
return;
if (m_DebugMessenger)
{
m_Instance.destroy(m_DebugMessenger, nullptr);

View File

@ -154,11 +154,10 @@ EnumeratePhysicalDevices(const vk::Instance instance)
return physicalDevices;
}
PhysicalDevices::PhysicalDevices(const Surface *surface, const Instance *context)
PhysicalDevices::PhysicalDevices(const Surface &surface, const Instance &context)
{
auto physicalDevices = EnumeratePhysicalDevices(context->m_Instance);
for (auto physicalDevice : physicalDevices)
for (auto physicalDevices = EnumeratePhysicalDevices(context.m_Instance); auto physicalDevice : physicalDevices)
{
this->emplace_back(surface->m_Surface, physicalDevice);
this->emplace_back(surface.m_Surface, physicalDevice);
}
}

View File

@ -8,13 +8,12 @@
#include "core/instance.h"
#include "core/window.h"
Surface::Surface(Instance *context, const Window *window, cstr name)
: m_Context(context)
, m_Name(name)
Surface::Surface(Instance &context, const Window &window)
: m_Context(&context)
{
VkSurfaceKHR surface;
auto result = Cast<vk::Result>(
glfwCreateWindowSurface(Cast<VkInstance>(m_Context->m_Instance), window->m_Window, nullptr, &surface));
auto result = static_cast<vk::Result>(
glfwCreateWindowSurface(static_cast<VkInstance>(m_Context->m_Instance), window.m_Window, nullptr, &surface));
ERROR_IF(Failed(result), "Failed to create Surface with {}", result)
THEN_ABORT(result)
ELSE_DEBUG("Surface {} Created", m_Name);
@ -23,15 +22,15 @@ Surface::Surface(Instance *context, const Window *window, cstr name)
Surface::~Surface()
{
if (m_Context && m_Surface)
{
if (!m_Context || !m_Context->m_Instance || !m_Surface)
return;
m_Context->m_Instance.destroy(m_Surface, nullptr);
DEBUG("Surface Destroyed");
m_Surface = nullptr;
m_Context = nullptr;
}
}
Surface::Surface(Surface &&other) noexcept
: m_Context(Take(other.m_Context))

View File

@ -11,9 +11,8 @@
[[nodiscard]] vk::Extent2D GetExtent(Size2D size, vk::SurfaceCapabilitiesKHR *surfaceCapabilities);
Swapchain::Swapchain(const Surface *surface, const Device *device, Size2D size, NameString &&name)
: m_Device(device)
, m_Name(std::move(name))
Swapchain::Swapchain(const Surface &surface, const Device &device, Size2D size)
: m_Device(&device)
, m_Format(vk::Format::eUndefined)
{
this->Create(surface, size);
@ -27,11 +26,11 @@ Swapchain::~Swapchain()
Swapchain::Swapchain(Swapchain &&other) noexcept
: m_Device(other.m_Device)
, m_Swapchain(Take(other.m_Swapchain))
, m_Name(std::move(other.m_Name))
, m_Extent(other.m_Extent)
, m_Format(other.m_Format)
, m_Images(std::move(other.m_Images))
, m_ImageViews(std::move(other.m_ImageViews))
, m_ResizeCallbacks(std::move(other.m_ResizeCallbacks))
{
}
@ -42,29 +41,29 @@ Swapchain::operator=(Swapchain &&other) noexcept
return *this;
m_Device = other.m_Device;
m_Swapchain = Take(other.m_Swapchain);
m_Name = std::move(other.m_Name);
m_Extent = other.m_Extent;
m_Format = other.m_Format;
m_Images = std::move(other.m_Images);
m_ImageViews = std::move(other.m_ImageViews);
m_ResizeCallbacks = std::move(other.m_ResizeCallbacks);
return *this;
}
void
Swapchain::Create(const Surface *surface, Size2D size)
Swapchain::Create(const Surface &surface, Size2D size)
{
auto surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, surface->m_Surface);
auto surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, surface.m_Surface);
m_Extent = GetExtent(size, &surfaceCapabilities);
while (m_Extent.width == 0 || m_Extent.height == 0)
{
glfwWaitEvents();
surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, surface->m_Surface);
surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, surface.m_Surface);
m_Extent = GetExtent(size, &surfaceCapabilities);
}
auto surfaceFormats = GetSurfaceFormats(m_Device->m_PhysicalDevice, surface->m_Surface);
auto presentModes = GetSurfacePresentModes(m_Device->m_PhysicalDevice, surface->m_Surface);
auto surfaceFormats = GetSurfaceFormats(m_Device->m_PhysicalDevice, surface.m_Surface);
auto presentModes = GetSurfacePresentModes(m_Device->m_PhysicalDevice, surface.m_Surface);
m_Format = vk::Format::eUndefined;
auto swapchainColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
@ -95,16 +94,14 @@ Swapchain::Create(const Surface *surface, Size2D size)
}
u32 swapchainImageCount = 3;
if (surfaceCapabilities.maxImageCount > 0)
{
swapchainImageCount =
glm::clamp(swapchainImageCount, surfaceCapabilities.minImageCount, surfaceCapabilities.maxImageCount);
}
u32 maxImageCount =
glm::max(swapchainImageCount, glm::max(surfaceCapabilities.maxImageCount, surfaceCapabilities.minImageCount));
swapchainImageCount = glm::clamp(swapchainImageCount, surfaceCapabilities.minImageCount, maxImageCount);
// TODO: Note that different queues might need the images to be shared.
const vk::SwapchainCreateInfoKHR swapchainCreateInfo = {
.surface = surface->m_Surface,
.surface = surface.m_Surface,
.minImageCount = swapchainImageCount,
.imageFormat = m_Format,
.imageColorSpace = swapchainColorSpace,
@ -120,28 +117,30 @@ Swapchain::Create(const Surface *surface, Size2D size)
};
vk::Device device = m_Device->m_Device;
NameString name = "Swapchain of ";
name += m_Device->m_Name;
vk::SwapchainKHR swapchain;
vk::Result result = device.createSwapchainKHR(&swapchainCreateInfo, nullptr, &swapchain);
ERROR_IF(Failed(result), "Swapchain {} creation failed. Cause {}", m_Name, result)
ERROR_IF(Failed(result), "'{}' creation failed. Cause {}", name, result)
THEN_ABORT(result)
ELSE_DEBUG("Created Swapchain '{}'", m_Name);
ELSE_DEBUG("Created '{}'", name);
// Irrelevant on the first run. Required for re-creation.
Cleanup();
m_Swapchain = swapchain;
m_Device->SetName(m_Swapchain, m_Name.data());
m_Device->SetName(m_Swapchain, m_Device->m_Name.data());
result = device.getSwapchainImagesKHR(m_Swapchain, &swapchainImageCount, nullptr);
ERROR_IF(Failed(result), "Failed getting swapchain {}'s images. Cause {}", m_Name, result)
ERROR_IF(Failed(result), "Failed getting {}'s images. Cause {}", name, result)
THEN_ABORT(result);
// Managed by the Swapchain.
m_Images.resize(swapchainImageCount);
m_Images.resize(swapchainImageCount, nullptr);
result = device.getSwapchainImagesKHR(m_Swapchain, &swapchainImageCount, m_Images.data());
ERROR_IF(Failed(result), "Failed getting swapchain {}'s images. Cause {}", m_Name, result)
ERROR_IF(Failed(result), "Failed getting {}'s images. Cause {}", name, result)
THEN_ABORT(result);
vk::ImageViewCreateInfo viewCreateInfo = {
@ -165,7 +164,7 @@ Swapchain::Create(const Surface *surface, Size2D size)
vk::ImageView imageView;
result = device.createImageView(&viewCreateInfo, nullptr, &imageView);
ERROR_IF(Failed(result), "Failed creating swapchain {}'s image view [{}]. Cause {}", m_Name, index, result)
ERROR_IF(Failed(result), "Failed creating {}'s image view [{}]. Cause {}", name, index, result)
THEN_ABORT(result);
m_ImageViews.push_back(imageView);
@ -173,7 +172,7 @@ Swapchain::Create(const Surface *surface, Size2D size)
++index;
}
DEBUG("Swapchain {} Image Views created.", m_Name);
DEBUG("{} Image Views created.", name);
for (auto &callback : m_ResizeCallbacks)
{
@ -184,24 +183,31 @@ Swapchain::Create(const Surface *surface, Size2D size)
void
Swapchain::RegisterResizeCallback(FnResizeCallback &&callback)
{
m_ResizeCallbacks.emplace_back(callback);
m_ResizeCallbacks.emplace_back(std::move(callback));
}
void
Swapchain::Cleanup()
{
if (!m_ImageViews.empty()) // Don't want the condition in the logs.
DEBUG("Swapchain {} Image Views destroyed.", m_Name);
if (!m_Swapchain)
return;
NameString name = "Swapchain of ";
name += m_Device->m_Name;
for (const auto imageView : m_ImageViews)
{
m_Device->m_Device.destroy(imageView, nullptr);
}
if (!m_ImageViews.empty()) // Don't want the condition in the logs.
DEBUG("Swapchain {} Image Views destroyed.", name);
m_ImageViews.clear();
m_Images.clear();
if (m_Swapchain)
{
m_Device->m_Device.destroy(m_Swapchain, nullptr);
m_Swapchain = nullptr;
DEBUG("Swapchain '{}' destroyed.", m_Name);
DEBUG("Swapchain '{}' destroyed.", name);
}
}

View File

@ -11,6 +11,30 @@
std::atomic_uint64_t Window::m_WindowCount = 0;
std::atomic_bool Window::m_IsGlfwInit = false;
void
Window::SetupLibrary()
{
if (!m_IsGlfwInit)
{
if (!glfwInit())
{
const char *error = nullptr;
const auto code = glfwGetError(&error);
ERROR("GLFW Init failed. Cause: ({}) {}", code, error)
THEN_ABORT(code);
}
m_WindowCount = 0;
m_IsGlfwInit = true;
}
}
cstr*
Window::GetInstanceExtensions(u32 *extensionCount)
{
SetupLibrary();
return glfwGetRequiredInstanceExtensions(extensionCount);
}
void
Window::RequestExit() const noexcept
{
@ -26,7 +50,7 @@ Window::SetWindowSize(const vk::Extent2D &extent) const noexcept
void
Window::SetWindowSize(const u32 width, const u32 height) const noexcept
{
glfwSetWindowSize(m_Window, Cast<i32>(width), Cast<i32>(height));
glfwSetWindowSize(m_Window, static_cast<i32>(width), static_cast<i32>(height));
}
Size2D
@ -35,25 +59,14 @@ Window::GetSize() const
int width;
int height;
glfwGetFramebufferSize(m_Window, &width, &height);
return {Cast<u32>(width), Cast<u32>(height)};
return {static_cast<u32>(width), static_cast<u32>(height)};
}
Window::Window(const cstr title, Size2D extent, const b8 isFullScreen)
{
m_Name = title;
if (!m_IsGlfwInit)
{
if (!glfwInit())
{
const char *error = nullptr;
const auto code = glfwGetError(&error);
ERROR("GLFW Init failed. Cause: ({}) {}", code, error)
THEN_ABORT(code);
}
m_WindowCount = 0;
m_IsGlfwInit = true;
}
SetupLibrary();
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
ERROR_IF(!monitor, "No monitor found");
@ -64,7 +77,7 @@ Window::Window(const cstr title, Size2D extent, const b8 isFullScreen)
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE);
m_Window = glfwCreateWindow(Cast<i32>(extent.m_Width), Cast<i32>(extent.m_Height), m_Name.c_str(),
m_Window = glfwCreateWindow(static_cast<i32>(extent.m_Width), static_cast<i32>(extent.m_Height), m_Name.c_str(),
isFullScreen ? monitor : nullptr, nullptr);
ERROR_IF(m_Window == nullptr, "Window creation failed")
ELSE_DEBUG("Window '{}' created with resolution '{}x{}'", m_Name, extent.m_Width, extent.m_Height);
@ -78,8 +91,8 @@ Window::Window(const cstr title, Size2D extent, const b8 isFullScreen)
if (isFullScreen == false)
{
glfwSetWindowPos(m_Window, Cast<i32>(windowWidth - extent.m_Width) / 2,
Cast<i32>(windowHeight - extent.m_Height) / 2);
glfwSetWindowPos(m_Window, static_cast<i32>(windowWidth - extent.m_Width) / 2,
static_cast<i32>(windowHeight - extent.m_Height) / 2);
}
glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);

View File

@ -4,8 +4,6 @@ cmake_minimum_required(VERSION 3.13)
target_sources(aster_core
PRIVATE
"buffer_manager.cpp"
"image_manager.cpp"
"view_manager.cpp"
"sampler_manager.cpp"
"commit_manager.cpp")
"device.cpp"
"commit_manager.cpp"
"sync_server.cpp")

View File

@ -1,160 +0,0 @@
// =============================================
// Aster: buffer_manager.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "systems/buffer_manager.h"
using namespace systems;
Ref<StorageBuffer>
BufferManager::CreateStorageBuffer(const usize size, const cstr name) const
{
// TODO: Storage and Index buffer are set.
// This is hacky and should be improved.
constexpr vk::BufferUsageFlags usage =
vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndexBuffer |
vk::BufferUsageFlagBits::eShaderDeviceAddress | vk::BufferUsageFlagBits::eTransferDst;
constexpr VmaAllocationCreateFlags createFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT;
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
return std::make_shared<StorageBuffer>(Buffer{m_Device, size, usage, createFlags, memoryUsage, name});
}
Ref<UniformBuffer>
BufferManager::CreateUniformBuffer(const usize size, const cstr name) const
{
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eUniformBuffer;
constexpr VmaAllocationCreateFlags createFlags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
VMA_ALLOCATION_CREATE_MAPPED_BIT;
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
return std::make_shared<UniformBuffer>(Buffer{m_Device, size, usage, createFlags, memoryUsage, name});
}
Ref<StagingBuffer>
BufferManager::CreateStagingBuffer(const usize size, const cstr name) const
{
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;
return std::make_shared<StagingBuffer>(Buffer{m_Device, size, usage, createFlags, memoryUsage, name});
}
Ref<VertexBuffer>
BufferManager::CreateVertexBuffer(const usize size, const cstr name) const
{
constexpr vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eVertexBuffer;
constexpr VmaAllocationCreateFlags createFlags =
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
constexpr VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO;
return std::make_shared<VertexBuffer>(Buffer{m_Device, size, usage, createFlags, memoryUsage, name});
}
//
// void
// UniformBuffer::Init(const Device *device, const usize size, const cstr name)
//{
// Allocate(device, size, vk::BufferUsageFlagBits::eUniformBuffer,
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
// VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
// VMA_MEMORY_USAGE_AUTO, name);
//}
//
// void
// StorageBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name)
//{
// Init(device, size, hostVisible, false, name);
//}
//
// void
// StorageBuffer::Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name)
//{
// vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer;
// if (deviceAddress)
// {
// usage |= vk::BufferUsageFlagBits::eShaderDeviceAddress;
// }
// if (hostVisible)
// {
// Allocate(device, size, usage,
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
// VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
// VMA_MEMORY_USAGE_AUTO, name);
// }
// else
// {
// usage |= vk::BufferUsageFlagBits::eTransferDst;
// Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
// }
//}
//
// void
// StorageIndexBuffer::Init(const Device *device, usize size, bool hostVisible, bool deviceAddress, cstr name)
//{
// vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndexBuffer;
// if (deviceAddress)
// {
// usage |= vk::BufferUsageFlagBits::eShaderDeviceAddress;
// }
// if (hostVisible)
// {
// Allocate(device, size, usage,
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
// VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
// VMA_MEMORY_USAGE_AUTO, name);
// }
// else
// {
// usage |= vk::BufferUsageFlagBits::eTransferDst;
// Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
// }
//}
//
// void
// IndirectBuffer::Init(const Device *device, usize size, bool hostVisible, cstr name)
//{
// vk::BufferUsageFlags usage = vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eIndirectBuffer |
// vk::BufferUsageFlagBits::eShaderDeviceAddress;
// if (hostVisible)
// {
// Allocate(device, size, usage,
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
// VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
// VMA_MEMORY_USAGE_AUTO, name);
// }
// else
// {
// usage |= vk::BufferUsageFlagBits::eTransferDst;
// Allocate(device, size, usage, 0, VMA_MEMORY_USAGE_AUTO, name);
// }
//}
//
// void
// VertexBuffer::Init(const Device *device, usize size, cstr name)
//{
// Allocate(device, size, vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eTransferDst, 0,
// VMA_MEMORY_USAGE_AUTO, name);
//}
//
// void
// IndexBuffer::Init(const Device *device, usize size, cstr name)
//{
// Allocate(device, size, vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst, 0,
// VMA_MEMORY_USAGE_AUTO, name);
//}
//
// void
// StagingBuffer::Init(const Device *device, usize size, cstr name)
//{
// Allocate(device, size, vk::BufferUsageFlagBits::eTransferSrc,
// VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
// VMA_MEMORY_USAGE_AUTO, name);
//}
BufferManager::BufferManager(const Device *device)
: m_Device{device}
{
}

View File

@ -8,29 +8,7 @@
#include "EASTL/array.h"
#include "core/device.h"
#include "core/image_view.h"
#define AbortIfFailed(RESULT) \
do \
{ \
vk::Result _checkResultValue_; \
ERROR_IF(Failed(_checkResultValue_ = Cast<vk::Result>(RESULT)), "Cause: {}", _checkResultValue_) \
THEN_ABORT(_checkResultValue_); \
} while (false)
#define AbortIfFailedMV(RESULT, MSG, EXTRA) \
do \
{ \
vk::Result _checkResultValue_; \
ERROR_IF(Failed(_checkResultValue_ = Cast<vk::Result>(RESULT)), MSG " Cause: {}", EXTRA, _checkResultValue_) \
THEN_ABORT(_checkResultValue_); \
} while (false)
#define AbortIfFailedM(RESULT, MSG) \
do \
{ \
auto _checkResultValue_ = Cast<vk::Result>(RESULT); \
ERROR_IF(Failed(_checkResultValue_), MSG " Cause: {}", _checkResultValue_) THEN_ABORT(_checkResultValue_); \
} while (false)
#include "systems/device.h"
using namespace systems;
@ -64,28 +42,28 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
const vk::DescriptorPoolCreateInfo poolCreateInfo = {
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
.maxSets = 1,
.poolSizeCount = Cast<u32>(poolSizes.size()),
.poolSizeCount = static_cast<u32>(poolSizes.size()),
.pPoolSizes = poolSizes.data(),
};
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
AbortIfFailed(device->m_Device->createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
eastl::array descriptorLayoutBindings = {
vk::DescriptorSetLayoutBinding{
.binding = BUFFER_BINDING_INDEX,
.descriptorType = vk::DescriptorType::eStorageBuffer,
.descriptorCount = Cast<u32>(maxBuffers),
.descriptorCount = static_cast<u32>(maxBuffers),
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
vk::DescriptorSetLayoutBinding{
.binding = IMAGE_BINDING_INDEX,
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
.descriptorCount = Cast<u32>(maxImages),
.descriptorCount = static_cast<u32>(maxImages),
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
vk::DescriptorSetLayoutBinding{
.binding = STORAGE_IMAGE_BINDING_INDEX,
.descriptorType = vk::DescriptorType::eStorageImage,
.descriptorCount = Cast<u32>(maxStorageImages),
.descriptorCount = static_cast<u32>(maxStorageImages),
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
};
@ -93,11 +71,11 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
vk::DescriptorBindingFlags bindingFlags =
vk::DescriptorBindingFlagBits::ePartiallyBound | vk::DescriptorBindingFlagBits::eUpdateAfterBind;
eastl::array<vk::DescriptorBindingFlags, decltype(descriptorLayoutBindings)::count> layoutBindingFlags;
eastl::array<vk::DescriptorBindingFlags, descriptorLayoutBindings.size()> layoutBindingFlags;
layoutBindingFlags.fill(bindingFlags);
vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo = {
.bindingCount = Cast<u32>(layoutBindingFlags.size()),
.bindingCount = static_cast<u32>(layoutBindingFlags.size()),
.pBindingFlags = layoutBindingFlags.data(),
};
@ -105,10 +83,10 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.pNext = &bindingFlagsCreateInfo,
.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
.bindingCount = Cast<u32>(descriptorLayoutBindings.size()),
.bindingCount = static_cast<u32>(descriptorLayoutBindings.size()),
.pBindings = descriptorLayoutBindings.data(),
};
AbortIfFailed(device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &m_SetLayout));
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
@ -118,7 +96,7 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
.descriptorSetCount = 1,
.pSetLayouts = &m_SetLayout,
};
AbortIfFailed(device->m_Device.allocateDescriptorSets(&descriptorSetAllocateInfo, &m_DescriptorSet));
AbortIfFailed(device->m_Device->allocateDescriptorSets(&descriptorSetAllocateInfo, &m_DescriptorSet));
device->SetName(m_SetLayout, "Bindless Layout");
device->SetName(m_DescriptorPool, "Bindless Pool");
@ -129,8 +107,8 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
CommitManager::~CommitManager()
{
m_Device->m_Device.destroy(m_SetLayout, nullptr);
m_Device->m_Device.destroy(m_DescriptorPool, nullptr);
m_Device->m_Device->destroy(m_SetLayout, nullptr);
m_Device->m_Device->destroy(m_DescriptorPool, nullptr);
#if !defined(ASTER_NDEBUG)
u32 bufferCount = 0;
@ -250,7 +228,7 @@ CommitManager::Update()
// Descriptor Updates
if (!m_Writes.empty())
{
m_Device->m_Device.updateDescriptorSets(Cast<u32>(m_Writes.size()), m_Writes.data(), 0, nullptr);
m_Device->m_Device->updateDescriptorSets(static_cast<u32>(m_Writes.size()), m_Writes.data(), 0, nullptr);
m_Writes.clear();
m_WriteInfos.clear();

File diff suppressed because it is too large Load Diff

View File

@ -1,236 +0,0 @@
// =============================================
// Aster: image_manager.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "systems/image_manager.h"
#include "core/device.h"
using namespace systems;
vk::ImageCreateInfo ToImageCreateInfo(const Texture2DCreateInfo &createInfo);
vk::ImageCreateInfo ToImageCreateInfo(const TextureCubeCreateInfo &createInfo);
vk::ImageCreateInfo ToImageCreateInfo(const AttachmentCreateInfo &createInfo);
vk::ImageCreateInfo ToImageCreateInfo(const DepthStencilImageCreateInfo &createInfo);
namespace usage_flags
{
constexpr vk::ImageUsageFlags MIPMAP = vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eTransferDst;
constexpr vk::ImageUsageFlags SAMPLE = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
constexpr vk::ImageUsageFlags STORAGE =
vk::ImageUsageFlagBits::eStorage | vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eTransferSrc;
constexpr vk::ImageUsageFlags COLOR_ATTACHMENT =
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc;
constexpr vk::ImageUsageFlags DEPTH_STENCIL_ATTACHMENT = vk::ImageUsageFlagBits::eDepthStencilAttachment;
} // namespace usage_flags
ImageManager::ImageManager(const Device *device)
: m_Device{device}
{
}
Ref<Image>
ImageManager::CreateTexture2D(const Texture2DCreateInfo &createInfo)
{
constexpr VmaAllocationCreateInfo allocationCreateInfo = {
.flags = {},
.usage = VMA_MEMORY_USAGE_AUTO,
};
VkImage rawImage;
VmaAllocation allocation;
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
&allocationCreateInfo, &rawImage, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
vk::Image image = rawImage;
u8 layerCount = Cast<u8>(imageCreateInfo.arrayLayers);
u8 mipLevels = Cast<u8>(imageCreateInfo.mipLevels);
Image::Flags flags = {};
if (createInfo.m_IsSampled)
flags |= Image::FlagBits::eSampled;
if (createInfo.m_IsStorage)
flags |= Image::FlagBits::eStorage;
m_Device->SetName(image, createInfo.m_Name);
return std::make_shared<Image>(m_Device, image, allocation, imageCreateInfo.extent, imageCreateInfo.format, flags,
layerCount, mipLevels);
}
Ref<ImageCube>
ImageManager::CreateTextureCube(const TextureCubeCreateInfo &createInfo)
{
constexpr VmaAllocationCreateInfo allocationCreateInfo = {
.flags = {},
.usage = VMA_MEMORY_USAGE_AUTO,
};
VkImage rawImage;
VmaAllocation allocation;
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
&allocationCreateInfo, &rawImage, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
vk::Image image = rawImage;
u8 layerCount = Cast<u8>(imageCreateInfo.arrayLayers);
u8 mipLevels = Cast<u8>(imageCreateInfo.mipLevels);
Image::Flags flags = Image::FlagBits::eCube;
if (createInfo.m_IsSampled)
flags |= Image::FlagBits::eSampled;
if (createInfo.m_IsStorage)
flags |= Image::FlagBits::eStorage;
m_Device->SetName(image, createInfo.m_Name);
return CastImage<ImageCube>(std::make_shared<Image>(m_Device, image, allocation, imageCreateInfo.extent,
imageCreateInfo.format, flags, layerCount, mipLevels));
}
Ref<Image>
ImageManager::CreateAttachment(const AttachmentCreateInfo &createInfo)
{
constexpr VmaAllocationCreateInfo allocationCreateInfo = {
.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
.usage = VMA_MEMORY_USAGE_AUTO,
};
VkImage rawImage;
VmaAllocation allocation;
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
&allocationCreateInfo, &rawImage, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
vk::Image image = rawImage;
u8 layerCount = Cast<u8>(imageCreateInfo.arrayLayers);
u8 mipLevels = Cast<u8>(imageCreateInfo.mipLevels);
m_Device->SetName(image, createInfo.m_Name);
return std::make_shared<Image>(m_Device, image, allocation, imageCreateInfo.extent, imageCreateInfo.format,
Image::Flags{}, layerCount, mipLevels);
}
Ref<Image>
ImageManager::CreateDepthStencilImage(const DepthStencilImageCreateInfo &createInfo)
{
constexpr VmaAllocationCreateInfo allocationCreateInfo = {
.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
.usage = VMA_MEMORY_USAGE_AUTO,
};
VkImage rawImage;
VmaAllocation allocation;
vk::ImageCreateInfo imageCreateInfo = ToImageCreateInfo(createInfo);
auto result = Cast<vk::Result>(vmaCreateImage(m_Device->m_Allocator, Recast<VkImageCreateInfo *>(&imageCreateInfo),
&allocationCreateInfo, &rawImage, &allocation, nullptr));
ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", createInfo.m_Name, result) THEN_ABORT(result);
vk::Image image = rawImage;
u8 layerCount = Cast<u8>(imageCreateInfo.arrayLayers);
u8 mipLevels = Cast<u8>(imageCreateInfo.mipLevels);
m_Device->SetName(image, createInfo.m_Name);
return std::make_shared<Image>(m_Device, image, allocation, imageCreateInfo.extent, imageCreateInfo.format,
Image::Flags{}, layerCount, mipLevels);
}
vk::ImageCreateInfo
ToImageCreateInfo(const Texture2DCreateInfo &createInfo)
{
auto &[format, extent, name, isSampled, isMipMapped, isStorage] = createInfo;
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>");
const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
auto usage = vk::ImageUsageFlags{};
if (isSampled)
usage |= usage_flags::SAMPLE;
if (isMipMapped)
usage |= usage_flags::MIPMAP;
if (isStorage)
usage |= usage_flags::STORAGE;
return {
.imageType = vk::ImageType::e2D,
.format = format,
.extent = ToExtent3D(extent, 1),
.mipLevels = mipLevels,
.arrayLayers = 1,
.usage = usage,
};
}
vk::ImageCreateInfo
ToImageCreateInfo(const TextureCubeCreateInfo &createInfo)
{
auto &[format, side, name, isSampled, isMipMapped, isStorage] = createInfo;
WARN_IF(!IsPowerOfTwo(side), "ImageCube {1} is {0}x{0} (Non Power of Two)", side, name ? name : "<unnamed>");
const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(side))) : 1;
auto usage = vk::ImageUsageFlags{};
if (isSampled)
usage |= usage_flags::SAMPLE;
if (isMipMapped)
usage |= usage_flags::MIPMAP;
if (isStorage)
usage |= usage_flags::STORAGE;
return {
.flags = vk::ImageCreateFlagBits::eCubeCompatible,
.imageType = vk::ImageType::e2D,
.format = format,
.extent = {side, side, 1},
.mipLevels = mipLevels,
.arrayLayers = 6,
.usage = usage,
};
}
vk::ImageCreateInfo
ToImageCreateInfo(const AttachmentCreateInfo &createInfo)
{
auto &[format, extent, name] = createInfo;
constexpr auto usage = usage_flags::COLOR_ATTACHMENT;
return {
.imageType = vk::ImageType::e2D,
.format = format,
.extent = ToExtent3D(extent, 1),
.mipLevels = 1,
.arrayLayers = 1,
.usage = usage,
};
}
vk::ImageCreateInfo
ToImageCreateInfo(const DepthStencilImageCreateInfo &createInfo)
{
auto &[extent, name] = createInfo;
constexpr auto format = vk::Format::eD24UnormS8Uint;
constexpr auto usage = usage_flags::DEPTH_STENCIL_ATTACHMENT;
return {
.imageType = vk::ImageType::e2D,
.format = format,
.extent = ToExtent3D(extent, 1),
.mipLevels = 1,
.arrayLayers = 1,
.usage = usage,
};
}

View File

@ -1,36 +0,0 @@
// =============================================
// Aster: sampler_manager.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "systems/sampler_manager.h"
#include "core/device.h"
using namespace systems;
SamplerManager::SamplerManager(const Device *device)
: m_Device{device}
{
}
SamplerManager::~SamplerManager()
{
m_HashToSamplerIdx.clear();
}
Ref<Sampler>
SamplerManager::CreateSampler(const SamplerCreateInfo &createInfo)
{
auto vkCreateInfo = Cast<vk::SamplerCreateInfo>(createInfo);
if (const auto iter = m_HashToSamplerIdx.find(vkCreateInfo); iter != m_HashToSamplerIdx.end() && !iter->second.expired())
{
return iter->second.lock();
}
auto object = std::make_shared<Sampler>(m_Device, vkCreateInfo, createInfo.m_Name ? createInfo.m_Name : nullptr);
m_HashToSamplerIdx.emplace(vkCreateInfo, object);
return object;
}

View File

@ -0,0 +1,144 @@
// =============================================
// Aster: sync_server.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "aster/systems/sync_server.h"
#include "aster/systems/device.h"
using namespace systems::_internal;
SyncServer::Entry
SyncServer::Entry::Create(Device &device)
{
constexpr static vk::SemaphoreTypeCreateInfo TYPE_CREATE_INFO = {
.semaphoreType = vk::SemaphoreType::eTimeline,
.initialValue = 0,
};
constexpr static vk::SemaphoreCreateInfo SEMAPHORE_CREATE_INFO = {.pNext = &TYPE_CREATE_INFO};
vk::Semaphore semaphore;
AbortIfFailed(device.m_Device->createSemaphore(&SEMAPHORE_CREATE_INFO, nullptr, &semaphore));
return {
.m_Semaphore = semaphore,
.m_CurrentPoint = {.m_WaitValue = 0, .m_NextValue = 1},
};
}
void
SyncServer::Entry::Destroy(Device &device)
{
if (m_Semaphore)
{
device.m_Device->destroy(Take(m_Semaphore), nullptr);
}
}
void
SyncServer::Entry::Wait(Device &device)
{
const vk::SemaphoreWaitInfo waitInfo = {
.semaphoreCount = 1,
.pSemaphores = &m_Semaphore,
.pValues = &m_CurrentPoint.m_NextValue,
};
// This blocks.
// So `m_NextValue` is not modified while we wait for the signal.
AbortIfFailed(device.m_Device->waitSemaphores(&waitInfo, MaxValue<u64>));
// Thus, this is safe.
m_CurrentPoint.m_WaitValue = m_CurrentPoint.m_NextValue;
m_CurrentPoint.m_WaitValue = m_CurrentPoint.m_NextValue + 1;
}
void
SyncServer::Entry::Next()
{
m_CurrentPoint.m_WaitValue = m_CurrentPoint.m_NextValue;
++m_CurrentPoint.m_NextValue;
}
systems::Receipt
SyncServer::Allocate()
{
auto &entry = AllocateEntry();
return Receipt{&entry};
}
void
SyncServer::Free(const Receipt receipt)
{
FreeEntry(GetEntry(receipt));
}
void
SyncServer::WaitOn(const Receipt receipt)
{
auto &entry = GetEntry(receipt);
entry.Wait(*m_Device);
FreeEntry(entry);
}
SyncServer::Entry &
SyncServer::AllocateEntry()
{
if (not m_FreeList.empty())
{
auto &alloc = m_FreeList.back();
m_FreeList.pop_back();
return alloc;
}
m_Allocations.push_back(Entry::Create(*m_Device));
return m_Allocations.back();
}
void
SyncServer::FreeEntry(Entry &entry)
{
entry.Next();
m_FreeList.push_back(entry);
}
SyncServer::Entry &
SyncServer::GetEntry(Receipt receipt)
{
return *static_cast<Entry *>(receipt.m_Opaque);
}
SyncServer::SyncServer(Device &device)
: m_Device{&device}
{
}
SyncServer::~SyncServer()
{
if (m_Device && !m_Allocations.empty())
{
for (auto &entry : m_Allocations)
{
entry.Destroy(*m_Device);
}
m_Device = nullptr;
}
}
SyncServer::SyncServer(SyncServer &&other) noexcept
: m_Device{Take(other.m_Device)}
, m_Allocations{std::move(other.m_Allocations)}
, m_FreeList{Take(other.m_FreeList)}
{
}
SyncServer &
SyncServer::operator=(SyncServer &&other) noexcept
{
if (this == &other)
return *this;
m_Device = Take(other.m_Device);
m_Allocations = std::move(other.m_Allocations);
m_FreeList = Take(other.m_FreeList);
return *this;
}

View File

@ -1,37 +0,0 @@
// =============================================
// Aster: view_manager.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "systems/view_manager.h"
#include "core/device.h"
using namespace systems;
ViewManager::ViewManager(const Device *device)
: m_Device{device}
{
}
Ref<ImageView>
ViewManager::CreateView(const ViewCreateInfo<Image> &createInfo) const
{
const auto layerCount = createInfo.GetLayerCount();
const auto mipCount = createInfo.GetMipLevelCount();
ERROR_IF((createInfo.m_BaseLayer + layerCount) > createInfo.m_Image->m_LayerCount, "Invalid Layer Access")
THEN_ABORT(-1);
ERROR_IF((createInfo.m_BaseMipLevel + mipCount) > createInfo.m_Image->m_MipLevels, "Invalid Mip Level Access")
THEN_ABORT(-1);
vk::ImageView view;
const auto imageViewCreateInfo = Cast<vk::ImageViewCreateInfo>(createInfo);
auto result = m_Device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view);
ERROR_IF(Failed(result), "Could not create image view {}. Cause: {}", createInfo.m_Name, result)
THEN_ABORT(result);
m_Device->SetName(view, createInfo.m_Name);
return std::make_shared<ImageView>(createInfo.m_Image, view, createInfo.m_Image->m_Extent, createInfo.m_BaseLayer,
layerCount, createInfo.m_BaseMipLevel, mipCount);
}

View File

@ -2,4 +2,4 @@
cmake_minimum_required(VERSION 3.13)
target_sources(aster_core PRIVATE "logger.cpp" )
target_sources(aster_core PRIVATE "logger.cpp" "files.cpp")

View File

@ -0,0 +1,79 @@
// =============================================
// Aster: files.cpp
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#include "aster/util/files.h"
eastl::vector<u32>
ReadFile(std::string_view fileName)
{
FILE *filePtr = fopen(fileName.data(), "rb");
if (!filePtr)
{
ERROR("Invalid read of {}", fileName) THEN_ABORT(-1);
}
eastl::vector<u32> outputVec;
eastl::array<u32, 1024> buffer{};
usize totalRead = 0;
usize readCount;
do
{
readCount = fread(buffer.data(), sizeof(u32), buffer.size(), filePtr);
const auto nextSize = totalRead + readCount;
outputVec.resize(nextSize);
memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data());
totalRead = nextSize;
} while (readCount == buffer.size());
return outputVec;
}
eastl::vector<u8>
ReadFileBytes(std::string_view fileName, bool errorOnFail)
{
FILE *filePtr = fopen(fileName.data(), "rb");
if (!filePtr)
{
ERROR_IF(errorOnFail, "Invalid open (r) of {}. Cause: {}", fileName, errno);
return {};
}
eastl::vector<u8> outputVec;
eastl::array<u8, 4096> buffer{};
usize totalRead = 0;
usize readCount;
do
{
readCount = fread(buffer.data(), sizeof(u8), buffer.size(), filePtr);
const auto nextSize = totalRead + readCount;
outputVec.resize(nextSize);
memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data());
totalRead = nextSize;
} while (readCount == buffer.size());
(void)fclose(filePtr);
return outputVec;
}
bool
WriteFileBytes(std::string_view fileName, const eastl::span<u8> data)
{
FILE *filePtr = fopen(fileName.data(), "wb");
if (!filePtr)
{
ERROR("Invalid open (w) of {}. Cause: {}", fileName, errno);
return false;
}
const usize written = fwrite(data.data(), sizeof(u8), data.size(), filePtr);
(void)fclose(filePtr);
return written == data.size();
}

View File

@ -17,7 +17,7 @@ Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCo
m_Device = device;
eastl::fixed_string<char, 50, false> name = "Frame ";
name += Cast<char>('0' + frameCount);
name += static_cast<char>('0' + frameCount);
const vk::CommandPoolCreateInfo commandPoolCreateInfo = {
.flags = vk::CommandPoolCreateFlagBits::eTransient,
.queueFamilyIndex = queueFamilyIndex,
@ -71,7 +71,7 @@ Frame::Present(const vk::Queue commandQueue, Swapchain *swapchain, const Surface
case vk::Result::eErrorOutOfDateKHR:
case vk::Result::eSuboptimalKHR:
DEBUG("Recreating Swapchain. Cause: {}", result);
swapchain->Create(surface, size);
swapchain->Create(*surface, size);
break; // Present failed. We do nothing. Frame is skipped.
default:
AbortIfFailedM(result, "Swapchain Present failed.");
@ -154,7 +154,7 @@ FrameManager::GetNextFrame(Swapchain *swapchain, const Surface *surface, Size2D
break; // Image acquired. Break out of loop.
case vk::Result::eErrorOutOfDateKHR:
DEBUG("Recreating Swapchain. Cause: {}", result);
swapchain->Create(surface, size);
swapchain->Create(*surface, size);
break; // Image acquire has failed. We move to the next frame.
default:
AbortIfFailedMV(result, "Waiting for swapchain image {} failed.", frameIndex);

View File

@ -48,7 +48,7 @@ Init(const Instance *context, const Device *device, const Window *window, vk::Fo
const vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
.flags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
.maxSets = 1000,
.poolSizeCount = Cast<u32>(poolSizes.size()),
.poolSizeCount = static_cast<u32>(poolSizes.size()),
.pPoolSizes = poolSizes.data(),
};

View File

@ -62,76 +62,3 @@ FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
ERROR("No suitable queue family on the GPU.")
THEN_ABORT(vk::Result::eErrorUnknown);
}
eastl::vector<u32>
ReadFile(cstr fileName)
{
FILE *filePtr = fopen(fileName, "rb");
if (!filePtr)
{
ERROR("Invalid read of {}", fileName) THEN_ABORT(-1);
}
eastl::vector<u32> outputVec;
eastl::array<u32, 1024> buffer{};
usize totalRead = 0;
usize readCount;
do
{
readCount = fread(buffer.data(), sizeof(u32), buffer.size(), filePtr);
const auto nextSize = totalRead + readCount;
outputVec.resize(nextSize);
memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data());
totalRead = nextSize;
} while (readCount == buffer.size());
return outputVec;
}
eastl::vector<u8>
ReadFileBytes(cstr fileName, bool errorOnFail)
{
FILE *filePtr = fopen(fileName, "rb");
if (!filePtr)
{
ERROR_IF(errorOnFail, "Invalid open (r) of {}. Cause: {}", fileName, errno);
return {};
}
eastl::vector<u8> outputVec;
eastl::array<u8, 4096> buffer{};
usize totalRead = 0;
usize readCount;
do
{
readCount = fread(buffer.data(), sizeof(u8), buffer.size(), filePtr);
const auto nextSize = totalRead + readCount;
outputVec.resize(nextSize);
memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data());
totalRead = nextSize;
} while (readCount == buffer.size());
(void)fclose(filePtr);
return outputVec;
}
bool
WriteFileBytes(cstr fileName, eastl::span<u8> data)
{
FILE *filePtr = fopen(fileName, "wb");
if (!filePtr)
{
ERROR("Invalid open (w) of {}. Cause: {}", fileName, errno);
return false;
}
const usize written = fwrite(data.data(), sizeof(u8), data.size(), filePtr);
(void)fclose(filePtr);
return written == data.size();
}

View File

@ -18,9 +18,6 @@ class PhysicalDevices;
PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices);
QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice);
eastl::vector<u32> ReadFile(cstr fileName);
eastl::vector<u8> ReadFileBytes(cstr fileName, bool errorOnFail = true);
bool WriteFileBytes(cstr fileName, eastl::span<u8> data);
template <usize TSize>
using StackString = eastl::fixed_string<char, TSize, false>;
@ -29,7 +26,7 @@ using StackString = eastl::fixed_string<char, TSize, false>;
do \
{ \
vk::Result _checkResultValue_; \
ERROR_IF(Failed(_checkResultValue_ = Cast<vk::Result>(RESULT)), "Cause: {}", _checkResultValue_) \
ERROR_IF(Failed(_checkResultValue_ = static_cast<vk::Result>(RESULT)), "Cause: {}", _checkResultValue_) \
THEN_ABORT(_checkResultValue_); \
} while (false)
@ -37,13 +34,13 @@ using StackString = eastl::fixed_string<char, TSize, false>;
do \
{ \
vk::Result _checkResultValue_; \
ERROR_IF(Failed(_checkResultValue_ = Cast<vk::Result>(RESULT)), MSG " Cause: {}", EXTRA, _checkResultValue_) \
ERROR_IF(Failed(_checkResultValue_ = static_cast<vk::Result>(RESULT)), MSG " Cause: {}", EXTRA, _checkResultValue_) \
THEN_ABORT(_checkResultValue_); \
} while (false)
#define AbortIfFailedM(RESULT, MSG) \
do \
{ \
auto _checkResultValue_ = Cast<vk::Result>(RESULT); \
auto _checkResultValue_ = static_cast<vk::Result>(RESULT); \
ERROR_IF(Failed(_checkResultValue_), MSG " Cause: {}", _checkResultValue_) THEN_ABORT(_checkResultValue_); \
} while (false)

View File

@ -3,8 +3,8 @@
cmake_minimum_required(VERSION 3.13)
add_executable(triangle "triangle.cpp")
add_shader(triangle "shader/triangle.vert.glsl")
add_shader(triangle "shader/triangle.frag.glsl")
add_shader(triangle "shader/triangle.slang")
add_resource_dir(triangle "shader")
target_link_libraries(triangle PRIVATE aster_core)
target_link_libraries(triangle PRIVATE util_helper)

View File

@ -1,9 +0,0 @@
#version 450
#pragma shader_stage(fragment)
layout (location = 0) in vec3 inColor;
layout (location = 0) out vec4 outColor;
void main() {
outColor = vec4(inColor, 1.0);
}

View File

@ -0,0 +1,35 @@
struct Vertex {
float3 point;
float3 color;
};
struct VSIn {
Vertex vertex;
};
struct VSOut
{
float4 Pos : SV_POSITION;
float3 Color : COLOR0;
};
[shader("vertex")]
VSOut vsmain(VSIn input) {
VSOut output;
output.Pos = float4(input.vertex.point, 1.0f);
output.Color = input.vertex.color;
return output;
}
struct FSOut {
float4 Color;
};
[shader("fragment")]
FSOut fsmain(VSOut input) {
FSOut outp;
outp.Color = float4(input.Color, 1.0);
return outp;
}

View File

@ -1,27 +0,0 @@
#version 450
#pragma shader_stage(vertex)
layout(location=0) in vec4 position;
layout(location=1) in vec4 color;
layout(location=0) out vec3 outColor;
void main() {
/*
vec3 points[] = {
vec3(-0.5f, -0.5f, 0.0f),
vec3(0.5f, -0.5f, 0.0f),
vec3(0.0f, 0.5f, 0.0f)
};
vec3 colors[] = {
vec3( 1.0f, 0.0f, 0.0f ),
vec3( 0.0f, 1.0f, 0.0f ),
vec3( 0.0f, 0.0f, 1.0f ),
};
gl_Position = vec4(points[gl_VertexIndex], 1.0f);
outColor = vec3(colors[gl_VertexIndex]); //*/
//*
gl_Position = vec4(position.xyz, 1.0f);
outColor = vec3(color.rgb); //*/
}

View File

@ -1,28 +0,0 @@
struct VSIn {
int idx : SV_VERTEXID;
};
struct VSOut
{
float4 Pos : SV_POSITION;
[[vk::location(0)]] float3 Color : COLOR0;
};
VSOut main(VSIn input) {
float3 points[] = {
float3(-0.5f, -0.5f, 0.0f),
float3(0.5f, -0.5f, 0.0f),
float3(0.0f, 0.5f, 0.0f)
};
float3 colors[] = {
float3( 1.0f, 0.0f, 0.0f ),
float3( 0.0f, 1.0f, 0.0f ),
float3( 0.0f, 0.0f, 1.0f ),
};
VSOut output;
output.Pos = float4(points[input.idx], 1.0f);
output.Color = colors[input.idx];
return output;
}

View File

@ -8,110 +8,71 @@
#include "aster/core/buffer.h"
#include "aster/core/constants.h"
#include "aster/core/instance.h"
#include "aster/core/device.h"
#include "aster/core/physical_device.h"
#include "aster/core/pipeline.h"
#include "aster/core/swapchain.h"
#include "aster/core/window.h"
#include "aster/core/pipeline.h"
#include "aster/systems/device.h"
#include "aster/util/files.h"
#include "helpers.h"
#include "aster/systems/resource_manager.h"
#include <EASTL/array.h>
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
constexpr auto VERTEX_SHADER_FILE = "shader/triangle.vert.glsl.spv";
constexpr auto FRAGMENT_SHADER_FILE = "shader/triangle.frag.glsl.spv";
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain);
constexpr auto SHADER_MODULE = "triangle.slang";
struct Vertex
{
vec3 m_Position;
vec3 m_Color;
constexpr static vk::VertexInputBindingDescription
GetBinding(const u32 binding)
{
return {.binding = binding, .stride = sizeof(Vertex), .inputRate = vk::VertexInputRate::eVertex};
}
constexpr static eastl::array<vk::VertexInputAttributeDescription, 2>
GetAttributes(const u32 binding)
static eastl::vector<systems::AttributeInfo>
GetAttributes()
{
return {
vk::VertexInputAttributeDescription{
.location = 0,
.binding = binding,
.format = vk::Format::eR32G32B32Sfloat,
.offset = offsetof(Vertex, m_Position),
{
.m_Location = 0,
.m_Offset = offsetof(Vertex, m_Position),
.m_Format = systems::AttributeInfo::Format::eFloat32X3,
},
vk::VertexInputAttributeDescription{
.location = 1,
.binding = binding,
.format = vk::Format::eR32G32B32Sfloat,
.offset = offsetof(Vertex, m_Color),
{
.m_Location = 1,
.m_Offset = offsetof(Vertex, m_Color),
.m_Format = systems::AttributeInfo::Format::eFloat32X3,
},
};
}
};
struct Frame
{
const Device *m_Device;
vk::CommandPool m_Pool;
vk::CommandBuffer m_CommandBuffer;
vk::Fence m_FrameAvailableFence;
vk::Semaphore m_ImageAcquireSem;
vk::Semaphore m_RenderFinishSem;
Frame(const Device *device, u32 queueFamilyIndex, u32 frameCount);
~Frame();
};
int
main(int, char **)
{
MIN_LOG_LEVEL(Logger::LogType::eInfo);
Window window = {"Triangle (Aster)", {640, 480}};
Instance context = {"Triangle", VERSION};
Surface surface = {&context, &window, "Primary"};
systems::Device device{{
.m_Window = window,
.m_Features = {.m_Vulkan12Features = {.bufferDeviceAddress = true},
.m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = true}},
.m_AppName = "Triangle",
.m_ShaderSearchPaths = {"shader/"},
.m_UseBindless = false,
.m_Name = "Primary",
}};
PhysicalDevices physicalDevices = {&surface, &context};
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
Features enabledDeviceFeatures = {
.m_Vulkan12Features = {.bufferDeviceAddress = true},
.m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = true},
};
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
Pipeline pipeline = CreatePipeline(&device, &swapchain);
systems::ResourceManager resourceManager{&device};
vk::CommandPool copyPool;
vk::CommandBuffer copyBuffer;
{
vk::CommandPoolCreateInfo poolCreateInfo = {
.flags = vk::CommandPoolCreateFlagBits::eTransient,
.queueFamilyIndex = queueAllocation.m_Family,
};
auto result = device.m_Device.createCommandPool(&poolCreateInfo, nullptr, &copyPool);
ERROR_IF(Failed(result), "Copy command pool creation failed. Cause: {}", result) THEN_ABORT(result);
vk::CommandBufferAllocateInfo bufferAllocateInfo = {
.commandPool = copyPool,
.level = vk::CommandBufferLevel::ePrimary,
.commandBufferCount = 1,
};
result = device.m_Device.allocateCommandBuffers(&bufferAllocateInfo, &copyBuffer);
ERROR_IF(Failed(result), "Copy command buffer allocation failed. Cause: {}", result) THEN_ABORT(result);
}
Pipeline pipeline;
auto pipelineError = device.CreatePipeline(pipeline, {
.m_VertexInputs = {{
.m_Attribute = Vertex::GetAttributes(),
.m_Stride = sizeof(Vertex),
}},
.m_Shaders = {{
.m_ShaderFile = SHADER_MODULE,
.m_EntryPoints = {"vsmain", "fsmain"},
}},
});
ERROR_IF(pipelineError, "Error creating pipeline. Cause: {}", pipelineError.What());
// eastl::array<Vertex, 3> vertices{};
eastl::array vertices = {
@ -119,23 +80,10 @@ main(int, char **)
Vertex{.m_Position = {0.5f, -0.5f, 0.0f}, .m_Color = {0.0f, 1.0f, 0.0f}},
Vertex{.m_Position = {0.0f, 0.5f, 0.0f}, .m_Color = {0.0f, 0.0f, 1.0f}},
};
auto vbo = resourceManager.Buffers().CreateVertexBuffer(vertices.size() * sizeof vertices[0], "VBO");
auto vbo = device.CreateVertexBuffer(vertices.size() * sizeof vertices[0], "VBO");
vbo->Write(0, vertices.size() * sizeof vertices[0], vertices.data());
// Persistent variables
vk::Viewport viewport = {
.x = 0,
.y = Cast<f32>(swapchain.m_Extent.height),
.width = Cast<f32>(swapchain.m_Extent.width),
.height = -Cast<f32>(swapchain.m_Extent.height),
.minDepth = 0.0,
.maxDepth = 1.0,
};
vk::Rect2D scissor = {
.offset = {0, 0},
.extent = swapchain.m_Extent,
};
vk::ImageSubresourceRange subresourceRange = {
.aspectMask = vk::ImageAspectFlagBits::eColor,
@ -151,8 +99,8 @@ main(int, char **)
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.subresourceRange = subresourceRange,
};
vk::DependencyInfo topOfThePipeDependency = {
@ -166,8 +114,8 @@ main(int, char **)
.dstAccessMask = vk::AccessFlagBits2::eNone,
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
.newLayout = vk::ImageLayout::ePresentSrcKHR,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.subresourceRange = subresourceRange,
};
vk::DependencyInfo renderToPresentDependency = {
@ -175,70 +123,39 @@ main(int, char **)
.pImageMemoryBarriers = &renderToPresentBarrier,
};
// Frames
eastl::fixed_vector<Frame, MAX_FRAMES_IN_FLIGHT> frames;
for (u32 i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
{
frames.emplace_back(&device, queueAllocation.m_Family, i);
}
INFO("Starting loop");
u32 frameIndex = 0;
while (window.Poll())
{
Frame *currentFrame = &frames[frameIndex];
systems::Frame &currentFrame = device.GetNextFrame();
auto result = device.m_Device.waitForFences(1, &currentFrame->m_FrameAvailableFence, true, MaxValue<u64>);
ERROR_IF(Failed(result), "Waiting for fence {} failed. Cause: {}", frameIndex, result)
THEN_ABORT(result);
Size2D swapchainSize = currentFrame.m_SwapchainSize;
u32 imageIndex;
result = device.m_Device.acquireNextImageKHR(swapchain.m_Swapchain, MaxValue<u64>,
currentFrame->m_ImageAcquireSem, nullptr, &imageIndex);
if (Failed(result))
{
switch (result)
{
case vk::Result::eErrorOutOfDateKHR:
case vk::Result::eSuboptimalKHR:
INFO("Recreating Swapchain. Cause: {}", result);
swapchain.Create(&surface, window.GetSize());
viewport.y = Cast<f32>(swapchain.m_Extent.height);
viewport.width = Cast<f32>(swapchain.m_Extent.width);
viewport.height = -Cast<f32>(swapchain.m_Extent.height);
scissor.extent = swapchain.m_Extent;
continue; // Image acquire has failed. We move to the next frame.
default:
ERROR("Waiting for swapchain image {} failed. Cause: {}", frameIndex, result)
THEN_ABORT(result);
}
}
// Reset fences here. In case swapchain was out of date, we leave the fences signalled.
result = device.m_Device.resetFences(1, &currentFrame->m_FrameAvailableFence);
ERROR_IF(Failed(result), "Fence {} reset failed. Cause: {}", frameIndex, result)
THEN_ABORT(result);
vk::Viewport viewport = {
.x = 0,
.y = static_cast<f32>(swapchainSize.m_Height),
.width = static_cast<f32>(swapchainSize.m_Width),
.height = -static_cast<f32>(swapchainSize.m_Height),
.minDepth = 0.0,
.maxDepth = 1.0,
};
result = device.m_Device.resetCommandPool(currentFrame->m_Pool, {});
ERROR_IF(Failed(result), "Command pool {} reset failed. Cause: {}", frameIndex, result)
THEN_ABORT(result);
vk::Rect2D scissor = {
.offset = {0, 0},
.extent = static_cast<vk::Extent2D>(swapchainSize),
};
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
vk::Image currentImage = swapchain.m_Images[imageIndex];
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
auto context = currentFrame.CreateGraphicsContext();
topOfThePipeBarrier.image = currentImage;
renderToPresentBarrier.image = currentImage;
topOfThePipeBarrier.image = currentFrame.m_SwapchainImage;
renderToPresentBarrier.image = currentFrame.m_SwapchainImage;
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
result = cmd.begin(&beginInfo);
ERROR_IF(Failed(result), "Command buffer begin failed. Cause: {}", result)
THEN_ABORT(result);
context.Begin();
cmd.pipelineBarrier2(&topOfThePipeDependency);
context.Dependency(topOfThePipeDependency);
// Render
vk::RenderingAttachmentInfo attachmentInfo = {
.imageView = currentImageView,
.imageView = currentFrame.m_SwapchainImageView,
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
.resolveMode = vk::ResolveModeFlagBits::eNone,
.loadOp = vk::AttachmentLoadOp::eClear,
@ -247,264 +164,29 @@ main(int, char **)
};
vk::RenderingInfo renderingInfo = {
.renderArea = {.extent = swapchain.m_Extent},
.renderArea = scissor,
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &attachmentInfo,
};
cmd.beginRendering(&renderingInfo);
context.BeginRendering(renderingInfo);
cmd.setViewport(0, 1, &viewport);
cmd.setScissor(0, 1, &scissor);
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
usize offsets = 0;
cmd.bindVertexBuffers(0, 1, &vbo->m_Buffer, &offsets);
cmd.draw(3, 1, 0, 0);
context.SetViewport(viewport);
context.BindPipeline(pipeline);
context.BindVertexBuffer(vbo);
context.Draw(3);
cmd.endRendering();
context.EndRendering();
cmd.pipelineBarrier2(&renderToPresentDependency);
context.Dependency(renderToPresentDependency);
result = cmd.end();
ERROR_IF(Failed(result), "Command buffer end failed. Cause: {}", result)
THEN_ABORT(result);
context.End();
vk::PipelineStageFlags waitDstStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
vk::SubmitInfo submitInfo = {
.waitSemaphoreCount = 1,
.pWaitSemaphores = &currentFrame->m_ImageAcquireSem,
.pWaitDstStageMask = &waitDstStage,
.commandBufferCount = 1,
.pCommandBuffers = &cmd,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &currentFrame->m_RenderFinishSem,
};
result = commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence);
ERROR_IF(Failed(result), "Command queue submit failed. Cause: {}", result)
THEN_ABORT(result);
vk::PresentInfoKHR presentInfo = {
.waitSemaphoreCount = 1,
.pWaitSemaphores = &currentFrame->m_RenderFinishSem,
.swapchainCount = 1,
.pSwapchains = &swapchain.m_Swapchain,
.pImageIndices = &imageIndex,
.pResults = nullptr,
};
result = commandQueue.presentKHR(&presentInfo);
if (Failed(result))
{
switch (result)
{
case vk::Result::eErrorOutOfDateKHR:
case vk::Result::eSuboptimalKHR:
INFO("Recreating Swapchain. Cause: {}", result);
swapchain.Create(&surface, window.GetSize());
viewport.y = Cast<f32>(swapchain.m_Extent.height);
viewport.width = Cast<f32>(swapchain.m_Extent.width);
viewport.height = -Cast<f32>(swapchain.m_Extent.height);
scissor.extent = swapchain.m_Extent;
break; // Present failed. We redo the frame.
default:
ERROR("Command queue present failed. Cause: {}", result)
THEN_ABORT(result);
}
}
frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT;
device.Present(currentFrame, context);
}
device.WaitIdle();
device.m_Device.destroy(copyPool, nullptr);
return 0;
}
Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCount)
{
m_Device = device;
const vk::CommandPoolCreateInfo commandPoolCreateInfo = {
.flags = vk::CommandPoolCreateFlagBits::eTransient,
.queueFamilyIndex = queueFamilyIndex,
};
vk::Result result = device->m_Device.createCommandPool(&commandPoolCreateInfo, nullptr, &m_Pool);
ERROR_IF(Failed(result), "Could not command pool for frame {}. Cause: {}", frameCount, result)
THEN_ABORT(result);
constexpr vk::FenceCreateInfo fenceCreateInfo = {.flags = vk::FenceCreateFlagBits::eSignaled};
result = device->m_Device.createFence(&fenceCreateInfo, nullptr, &m_FrameAvailableFence);
ERROR_IF(Failed(result), "Could not create a fence for frame {}. Cause: {}", frameCount, result)
THEN_ABORT(result);
constexpr vk::SemaphoreCreateInfo semaphoreCreateInfo = {};
result = device->m_Device.createSemaphore(&semaphoreCreateInfo, nullptr, &m_ImageAcquireSem);
ERROR_IF(Failed(result), "Could not create IA semaphore for frame {}. Cause: {}", frameCount, result)
THEN_ABORT(result);
result = device->m_Device.createSemaphore(&semaphoreCreateInfo, nullptr, &m_RenderFinishSem);
ERROR_IF(Failed(result), "Could not create RF semaphore for frame {}. Cause: {}", frameCount, result)
THEN_ABORT(result);
const vk::CommandBufferAllocateInfo allocateInfo = {
.commandPool = m_Pool, .level = vk::CommandBufferLevel::ePrimary, .commandBufferCount = 1};
result = m_Device->m_Device.allocateCommandBuffers(&allocateInfo, &m_CommandBuffer);
ERROR_IF(Failed(result), "Command buffer allocation failed. Cause: {}", result)
THEN_ABORT(result);
DEBUG("Frame {} created successfully.", frameCount);
}
Pipeline
CreatePipeline(const Device *device, const Swapchain *swapchain)
{
// Pipeline Setup
auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE);
auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE);
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
{
.stage = vk::ShaderStageFlagBits::eVertex,
.module = vertexShaderModule,
.pName = "main",
},
{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = fragmentShaderModule,
.pName = "main",
},
}};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = 0,
.pSetLayouts = nullptr,
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
};
vk::PipelineLayout pipelineLayout;
vk::Result result = device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout);
ERROR_IF(Failed(result), "Could not create a pipeline layout. Cause: {}", result) THEN_ABORT(result);
device->SetName(pipelineLayout, "Triangle Layout");
vk::VertexInputBindingDescription inputBindingDescription = Vertex::GetBinding(0);
auto inputAttributeDescription = Vertex::GetAttributes(0);
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &inputBindingDescription,
.vertexAttributeDescriptionCount = Cast<u32>(inputAttributeDescription.size()),
.pVertexAttributeDescriptions = inputAttributeDescription.data(),
};
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
.topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = false,
};
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = {
.viewportCount = 1,
.scissorCount = 1,
};
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
.depthClampEnable = false,
.rasterizerDiscardEnable = false,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eNone,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = false,
.lineWidth = 1.0,
};
vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
.depthTestEnable = false,
.depthWriteEnable = false,
};
vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = {
.blendEnable = false,
.srcColorBlendFactor = vk::BlendFactor::eSrcColor,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
.logicOpEnable = false,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachmentState,
};
eastl::array dynamicStates = {
vk::DynamicState::eScissor,
vk::DynamicState::eViewport,
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &swapchain->m_Format,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
.pViewportState = &viewportStateCreateInfo,
.pRasterizationState = &rasterizationStateCreateInfo,
.pMultisampleState = &multisampleStateCreateInfo,
.pDepthStencilState = &depthStencilStateCreateInfo,
.pColorBlendState = &colorBlendStateCreateInfo,
.pDynamicState = &dynamicStateCreateInfo,
.layout = pipelineLayout,
};
vk::Pipeline pipeline;
result = device->m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline);
ERROR_IF(Failed(result), "Could not create a graphics pipeline. Cause: {}", result)
THEN_ABORT(result);
device->SetName(pipeline, "Triangle Pipeline");
device->m_Device.destroy(vertexShaderModule, nullptr);
device->m_Device.destroy(fragmentShaderModule, nullptr);
return {device, pipelineLayout, pipeline, {}};
}
vk::ShaderModule
CreateShader(const Device *device, cstr shaderFile)
{
eastl::vector<u32> shaderCode = ReadFile(shaderFile);
const vk::ShaderModuleCreateInfo shaderModuleCreateInfo = {
.codeSize = shaderCode.size() * sizeof(u32),
.pCode = shaderCode.data(),
};
vk::ShaderModule shaderModule;
vk::Result result = device->m_Device.createShaderModule(&shaderModuleCreateInfo, nullptr, &shaderModule);
ERROR_IF(Failed(result), "Shader {} could not be created. Cause: {}", shaderFile, result)
THEN_ABORT(result);
return shaderModule;
}
Frame::~Frame()
{
m_Device->m_Device.destroy(m_RenderFinishSem, nullptr);
m_Device->m_Device.destroy(m_ImageAcquireSem, nullptr);
m_Device->m_Device.destroy(m_FrameAvailableFence, nullptr);
m_Device->m_Device.destroy(m_Pool, nullptr);
DEBUG("Destoryed Frame");
}

View File

@ -9,6 +9,8 @@ add_shader(box "shader/box.vert.glsl")
add_shader(box "shader/box.frag.glsl")
add_shader(box "shader/box.vs.hlsl")
add_shader(box "shader/box.ps.hlsl")
add_shader(box "shader/triangle.slang")
add_resource_dir(box "shader/")
target_link_libraries(box PRIVATE aster_core)
target_link_libraries(box PRIVATE util_helper)

View File

@ -7,30 +7,23 @@
#include "aster/core/buffer.h"
#include "aster/core/constants.h"
#include "aster/core/instance.h"
#include "aster/core/device.h"
#include "aster/core/image.h"
#include "aster/core/physical_device.h"
#include "aster/core/pipeline.h"
#include "aster/core/swapchain.h"
#include "aster/core/window.h"
#include "helpers.h"
#define STB_IMAGE_IMPLEMENTATION
#include "aster/systems/buffer_manager.h"
#include "aster/systems/commit_manager.h"
#include "aster/systems/image_manager.h"
#include "aster/systems/resource_manager.h"
#include "aster/systems/view_manager.h"
#include "frame.h"
#include "aster/systems/device.h"
#include "aster/util/files.h"
#include "stb_image.h"
#include <EASTL/array.h>
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv";
constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv";
constexpr auto SHADER_FILE = "triangle";
struct ImageFile
{
@ -66,7 +59,7 @@ ImageFile::Load(cstr fileName)
usize
ImageFile::GetSize() const
{
return Cast<usize>(m_Width) * m_Height * m_NumChannels;
return static_cast<usize>(m_Width) * m_Height * m_NumChannels;
}
ImageFile::~ImageFile()
@ -75,9 +68,6 @@ ImageFile::~ImageFile()
m_Data = nullptr;
}
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
Pipeline CreatePipeline(const systems::CommitManager *resourceManager, const Swapchain *swapchain);
struct Vertex
{
vec3 m_Position;
@ -99,13 +89,6 @@ main(int, char **)
MIN_LOG_LEVEL(Logger::LogType::eInfo);
Window window = {"Box (Aster)", {640, 480}};
Instance context = {"Box", VERSION};
Surface surface = {&context, &window, "Primary"};
PhysicalDevices physicalDevices = {&surface, &context};
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
Features enabledDeviceFeatures = {
.m_Vulkan10Features = {.samplerAnisotropy = true},
@ -121,47 +104,37 @@ main(int, char **)
.descriptorBindingStorageBufferUpdateAfterBind = true,
.descriptorBindingPartiallyBound = true,
.runtimeDescriptorArray = true,
.timelineSemaphore = true,
.bufferDeviceAddress = true,
.bufferDeviceAddressCaptureReplay = true,
},
.m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = true},
};
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
systems::ResourceManager resourceManager{&device};
systems::Device device{{
.m_Window = window,
.m_Features = enabledDeviceFeatures,
.m_AppName = "Box",
.m_AppVersion = VERSION,
.m_ShaderSearchPaths = {"shader/"},
}};
systems::CommitManager commitManager{&device, 12, 12, 12, resourceManager.Samplers().CreateSampler({})};
Pipeline pipeline = CreatePipeline(&commitManager, &swapchain);
Pipeline pipeline;
auto pipelineResult =
device.CreatePipeline(pipeline, {.m_Shaders = {
{.m_ShaderFile = SHADER_FILE, .m_EntryPoints = {"vsmain", "fsmain"}},
}});
ERROR_IF(pipelineResult, "Could not create pipeline. Cause: {}", pipelineResult.What())
THEN_ABORT(pipelineResult.uNone);
auto swapchainSize = device.GetSwapchainSize();
Camera camera = {
.m_Model = {1.0f},
.m_View = lookAt(vec3(0.0f, 2.0f, 2.0f), vec3(0.0f), vec3(0.0f, 1.0f, 0.0f)),
.m_Perspective = glm::perspective(
70_deg, Cast<f32>(swapchain.m_Extent.width) / Cast<f32>(swapchain.m_Extent.height), 0.1f, 100.0f),
70_deg, static_cast<f32>(swapchainSize.m_Width) / static_cast<f32>(swapchainSize.m_Height), 0.1f, 100.0f),
};
vk::CommandPool copyPool;
vk::CommandBuffer copyBuffer;
{
vk::CommandPoolCreateInfo poolCreateInfo = {
.flags = vk::CommandPoolCreateFlagBits::eTransient,
.queueFamilyIndex = queueAllocation.m_Family,
};
AbortIfFailedM(device.m_Device.createCommandPool(&poolCreateInfo, nullptr, &copyPool),
"Copy command pool creation failed.");
vk::CommandBufferAllocateInfo bufferAllocateInfo = {
.commandPool = copyPool,
.level = vk::CommandBufferLevel::ePrimary,
.commandBufferCount = 1,
};
AbortIfFailedM(device.m_Device.allocateCommandBuffers(&bufferAllocateInfo, &copyBuffer),
"Copy command buffer allocation failed.");
}
eastl::array vertices = {
Vertex{.m_Position = vec3(0.5f, 0.5f, -0.5f), .m_TexCoord0 = vec2(1.0f, 1.0f)},
Vertex{.m_Position = vec3(0.5f, -0.5f, -0.5f), .m_TexCoord0 = vec2(1.0f, 0.0f)},
@ -211,10 +184,10 @@ main(int, char **)
assert(loaded);
INFO("Image {}x{} : {} channels", imageFile.m_Width, imageFile.m_Height, imageFile.m_NumChannels);
auto vbo = resourceManager.Buffers().CreateStorageBuffer(vertices.size() * sizeof vertices[0], "Vertex Buffer");
auto vbo = device.CreateStorageBuffer(vertices.size() * sizeof vertices[0], "Vertex Buffer");
vbo->Write(0, vertices.size() * sizeof vertices[0], vertices.data());
auto crate = resourceManager.CombinedImageViews().CreateTexture2D({
auto crate = device.CreateTexture2DWithView({
.m_Format = vk::Format::eR8G8B8A8Srgb,
.m_Extent = {imageFile.m_Width, imageFile.m_Height},
.m_Name = "Crate Texture",
@ -222,7 +195,7 @@ main(int, char **)
{
auto imageStaging = resourceManager.Buffers().CreateStagingBuffer(imageFile.GetSize(), "Image Staging");
auto imageStaging = device.CreateStagingBuffer(imageFile.GetSize(), "Image Staging");
imageStaging->Write(0, imageFile.GetSize(), imageFile.m_Data);
vk::ImageMemoryBarrier2 imageReadyToWrite = {
@ -232,8 +205,8 @@ main(int, char **)
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eTransferDstOptimal,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.image = crate->GetImage(),
.subresourceRange =
{
@ -256,8 +229,8 @@ main(int, char **)
.dstAccessMask = vk::AccessFlagBits2::eShaderRead,
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.image = crate->GetImage(),
.subresourceRange =
{
@ -273,77 +246,25 @@ main(int, char **)
.pImageMemoryBarriers = &imageReadyToRead,
};
vk::Fence fence;
vk::FenceCreateInfo fenceCreateInfo = {};
AbortIfFailed(device.m_Device.createFence(&fenceCreateInfo, nullptr, &fence));
auto &context = device.CreateTransferContext();
context.Begin();
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
AbortIfFailed(copyBuffer.begin(&beginInfo));
context.Dependency(imageReadyToWriteDependency);
copyBuffer.pipelineBarrier2(&imageReadyToWriteDependency);
context.UploadTexture(crate->m_Image, {.m_Data = imageFile.m_Data, .m_NumBytes = imageFile.GetSize()});
vk::BufferImageCopy imageCopy = {
.bufferOffset = 0,
.bufferRowLength = imageFile.m_Width,
.bufferImageHeight = imageFile.m_Height,
.imageSubresource =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
},
.imageOffset = {},
.imageExtent = {imageFile.m_Width, imageFile.m_Height, 1},
};
copyBuffer.copyBufferToImage(imageStaging->m_Buffer, crate->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
&imageCopy);
context.Dependency(imageReadyToReadDependency);
copyBuffer.pipelineBarrier2(&imageReadyToReadDependency);
context.End();
AbortIfFailed(copyBuffer.end());
vk::SubmitInfo submitInfo = {
.commandBufferCount = 1,
.pCommandBuffers = &copyBuffer,
};
AbortIfFailed(commandQueue.submit(1, &submitInfo, fence));
INFO("Submit copy");
AbortIfFailed(device.m_Device.waitForFences(1, &fence, true, MaxValue<u64>));
INFO("Fence wait");
AbortIfFailedM(device.m_Device.resetCommandPool(copyPool, {}), "Couldn't reset command pool.");
device.m_Device.destroy(fence, nullptr);
auto recpt = device.Submit(context);
device.WaitOn(recpt);
}
auto ubo = resourceManager.Buffers().CreateStorageBuffer(sizeof camera, "Camera UBO");
auto ubo = device.CreateStorageBuffer(sizeof camera, "Camera UBO");
ubo->Write(0, sizeof camera, &camera);
// Persistent variables
vk::Viewport viewport = {
.x = 0,
.y = Cast<f32>(swapchain.m_Extent.height),
.width = Cast<f32>(swapchain.m_Extent.width),
.height = -Cast<f32>(swapchain.m_Extent.height),
.minDepth = 0.0,
.maxDepth = 1.0,
};
vk::Rect2D scissor = {
.offset = {0, 0},
.extent = swapchain.m_Extent,
};
auto resizeViewportScissor = [&viewport, &scissor](vk::Extent2D extent) {
viewport.y = Cast<f32>(extent.height);
viewport.width = Cast<f32>(extent.width);
viewport.height = -Cast<f32>(extent.height);
scissor.extent = extent;
};
swapchain.RegisterResizeCallback(resizeViewportScissor);
vk::ImageSubresourceRange subresourceRange = {
.aspectMask = vk::ImageAspectFlagBits::eColor,
@ -361,8 +282,8 @@ main(int, char **)
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.subresourceRange = subresourceRange,
};
vk::DependencyInfo topOfThePipeDependency = {
@ -376,8 +297,8 @@ main(int, char **)
.dstAccessMask = vk::AccessFlagBits2::eNone,
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
.newLayout = vk::ImageLayout::ePresentSrcKHR,
.srcQueueFamilyIndex = queueAllocation.m_Family,
.dstQueueFamilyIndex = queueAllocation.m_Family,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.subresourceRange = subresourceRange,
};
vk::DependencyInfo renderToPresentDependency = {
@ -385,64 +306,90 @@ main(int, char **)
.pImageMemoryBarriers = &renderToPresentBarrier,
};
FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT};
eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> depthImages;
auto initDepthImages = [&depthImages, &frameManager, &resourceManager](const vk::Extent2D extent) {
for (u32 i = 0; i < frameManager.m_FramesInFlight; ++i)
auto initDepthImages = [&depthImages, &device](const vk::Extent2D extent) {
for (u32 i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
{
depthImages.push_back(
resourceManager.CombinedImageViews().CreateDepthStencilImage({.m_Extent = extent, .m_Name = "Depth"}));
depthImages.push_back(device.CreateDepthStencilImageWithView({.m_Extent = extent, .m_Name = "Depth"}));
}
};
initDepthImages(swapchain.m_Extent);
initDepthImages(swapchainSize);
auto recreateDepthBuffers = [&depthImages, &initDepthImages](const vk::Extent2D extent) {
depthImages.clear();
initDepthImages(extent);
};
swapchain.RegisterResizeCallback(recreateDepthBuffers);
// TODO: Move to 64bit handles.
struct PCB
{
systems::ResId<Buffer> m_Camera;
systems::ResId<Buffer> m_VertexBuffer;
u32 m_Pad0 = 0;
systems::ResId<Buffer> m_Camera;
u32 m_Pad1 = 0;
systems::ResId<TextureView> m_Texture;
u32 m_Pad2 = 0;
};
static_assert(sizeof(PCB) == 24);
auto &commitManager = systems::CommitManager::Instance();
PCB pcb = {
.m_Camera = commitManager.CommitBuffer(ubo),
.m_VertexBuffer = commitManager.CommitBuffer(vbo),
.m_Camera = commitManager.CommitBuffer(ubo),
.m_Texture = commitManager.CommitTexture(crate),
};
Time::Init();
auto prevSwapchainSize = swapchainSize;
INFO("Starting loop");
while (window.Poll())
{
Time::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}, static_cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f));
ubo->Write(0, sizeof camera, &camera);
Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &surface, window.GetSize());
auto& currentFrame = device.GetNextFrame();
u32 imageIndex = currentFrame->m_ImageIdx;
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
vk::Image currentImage = swapchain.m_Images[imageIndex];
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
vk::ImageView currentDepthImageView = depthImages[currentFrame->m_FrameIdx]->m_View;
prevSwapchainSize = swapchainSize;
swapchainSize = currentFrame.m_SwapchainSize;
if (swapchainSize != prevSwapchainSize)
{
recreateDepthBuffers(swapchainSize);
}
vk::Viewport viewport = {
.x = 0,
.y = static_cast<f32>(swapchainSize.m_Height),
.width = static_cast<f32>(swapchainSize.m_Width),
.height = -static_cast<f32>(swapchainSize.m_Height),
.minDepth = 0.0,
.maxDepth = 1.0,
};
vk::Rect2D scissor = {
.offset = {0, 0},
.extent = static_cast<vk::Extent2D>(swapchainSize),
};
vk::ImageView currentImageView = currentFrame.m_SwapchainImageView;
vk::Image currentImage = currentFrame.m_SwapchainImage;
vk::ImageView currentDepthImageView = depthImages[currentFrame.m_FrameIdx]->m_View;
topOfThePipeBarrier.image = currentImage;
renderToPresentBarrier.image = currentImage;
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
AbortIfFailed(cmd.begin(&beginInfo));
auto context = currentFrame.CreateGraphicsContext();
cmd.pipelineBarrier2(&topOfThePipeDependency);
context.Begin();
context.Dependency(topOfThePipeDependency);
// Render
eastl::array attachmentInfos = {
@ -466,187 +413,30 @@ main(int, char **)
};
vk::RenderingInfo renderingInfo = {
.renderArea = {.extent = swapchain.m_Extent},
.renderArea = scissor,
.layerCount = 1,
.colorAttachmentCount = Cast<u32>(attachmentInfos.size()),
.colorAttachmentCount = static_cast<u32>(attachmentInfos.size()),
.pColorAttachments = attachmentInfos.data(),
.pDepthAttachment = &depthAttachment,
};
cmd.beginRendering(&renderingInfo);
context.BeginRendering(renderingInfo);
cmd.setViewport(0, 1, &viewport);
cmd.setScissor(0, 1, &scissor);
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1,
&commitManager.GetDescriptorSet(), 0, nullptr);
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAllGraphics, 0, 12, &pcb);
cmd.draw(Cast<u32>(vertices.size()), 1, 0, 0);
context.SetViewport(viewport);
context.BindPipeline(pipeline);
context.PushConstantBlock(pcb);
context.Draw(vertices.size());
cmd.endRendering();
context.EndRendering();
cmd.pipelineBarrier2(&renderToPresentDependency);
context.Dependency(renderToPresentDependency);
AbortIfFailed(cmd.end());
context.End();
vk::PipelineStageFlags waitDstStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
vk::SubmitInfo submitInfo = {
.waitSemaphoreCount = 1,
.pWaitSemaphores = &currentFrame->m_ImageAcquireSem,
.pWaitDstStageMask = &waitDstStage,
.commandBufferCount = 1,
.pCommandBuffers = &cmd,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &currentFrame->m_RenderFinishSem,
};
AbortIfFailed(commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence));
currentFrame->Present(commandQueue, &swapchain, &surface, window.GetSize());
device.Present(currentFrame, context);
}
device.WaitIdle();
device.m_Device.destroy(copyPool, nullptr);
return 0;
}
Pipeline
CreatePipeline(const systems::CommitManager *resourceManager, const Swapchain *swapchain)
{
// Pipeline Setup
auto *device = resourceManager->m_Device;
auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE);
auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE);
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{
{
.stage = vk::ShaderStageFlagBits::eVertex,
.module = vertexShaderModule,
.pName = "main",
},
{
.stage = vk::ShaderStageFlagBits::eFragment,
.module = fragmentShaderModule,
.pName = "main",
},
}};
auto descriptorSetLayout = resourceManager->GetDescriptorSetLayout();
vk::PushConstantRange pcr = {
.stageFlags = vk::ShaderStageFlagBits::eAllGraphics,
.offset = 0,
.size = 12,
};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = 1,
.pSetLayouts = &descriptorSetLayout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pcr,
};
vk::PipelineLayout pipelineLayout;
AbortIfFailed(device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
device->SetName(pipelineLayout, "Box Layout");
vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {};
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
.topology = vk::PrimitiveTopology::eTriangleList,
.primitiveRestartEnable = false,
};
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = {
.viewportCount = 1,
.scissorCount = 1,
};
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
.depthClampEnable = false,
.rasterizerDiscardEnable = false,
.polygonMode = vk::PolygonMode::eFill,
.cullMode = vk::CullModeFlagBits::eNone,
.frontFace = vk::FrontFace::eCounterClockwise,
.depthBiasEnable = false,
.lineWidth = 1.0,
};
vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
.rasterizationSamples = vk::SampleCountFlagBits::e1,
.sampleShadingEnable = false,
};
vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
.depthTestEnable = true,
.depthWriteEnable = true,
.depthCompareOp = vk::CompareOp::eLess,
};
vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = {
.blendEnable = false,
.srcColorBlendFactor = vk::BlendFactor::eSrcColor,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
};
vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
.logicOpEnable = false,
.attachmentCount = 1,
.pAttachments = &colorBlendAttachmentState,
};
eastl::array dynamicStates = {
vk::DynamicState::eScissor,
vk::DynamicState::eViewport,
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &swapchain->m_Format,
.depthAttachmentFormat = vk::Format::eD24UnormS8Uint,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
.pViewportState = &viewportStateCreateInfo,
.pRasterizationState = &rasterizationStateCreateInfo,
.pMultisampleState = &multisampleStateCreateInfo,
.pDepthStencilState = &depthStencilStateCreateInfo,
.pColorBlendState = &colorBlendStateCreateInfo,
.pDynamicState = &dynamicStateCreateInfo,
.layout = pipelineLayout,
};
vk::Pipeline pipeline;
AbortIfFailed(device->m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline));
device->SetName(pipeline, "Box Pipeline");
device->m_Device.destroy(vertexShaderModule, nullptr);
device->m_Device.destroy(fragmentShaderModule, nullptr);
return {device, pipelineLayout, pipeline, {}};
}
vk::ShaderModule
CreateShader(const Device *device, cstr shaderFile)
{
eastl::vector<u32> shaderCode = ReadFile(shaderFile);
const vk::ShaderModuleCreateInfo shaderModuleCreateInfo = {
.codeSize = shaderCode.size() * sizeof(u32),
.pCode = shaderCode.data(),
};
vk::ShaderModule shaderModule;
AbortIfFailedMV(device->m_Device.createShaderModule(&shaderModuleCreateInfo, nullptr, &shaderModule),
"Shader {} could not be created.", shaderFile);
return shaderModule;
}

View File

@ -0,0 +1,23 @@
[vk::binding(0, 0)] __DynamicResource<__DynamicResourceKind.General> gBuffers[];
[vk::binding(1, 0)] __DynamicResource<__DynamicResourceKind.Sampler> gSamplers[];
[vk::binding(2, 0)] __DynamicResource<__DynamicResourceKind.General> gStorageTextures[];
export T getDescriptorFromHandle<T>(DescriptorHandle<T> handle) where T : IOpaqueDescriptor
{
__target_switch
{
case spirv:
switch (T.kind) {
case DescriptorKind.Buffer:
return gBuffers[((uint2)handle).x].asOpaqueDescriptor<T>();
case DescriptorKind.CombinedTextureSampler:
return gSamplers[((uint2)handle).x].asOpaqueDescriptor<T>();
case DescriptorKind.Texture:
return gStorageTextures[((uint2)handle).x].asOpaqueDescriptor<T>();
default:
return defaultGetDescriptorFromHandle(handle);
}
default:
return defaultGetDescriptorFromHandle(handle);
}
}

View File

@ -0,0 +1,59 @@
import bindless;
struct VertexData
{
float4 position;
float2 texCoord0;
float2 _pad0;
};
struct CameraData
{
float4x4 model;
float4x4 view;
float4x4 projection;
};
struct PCB {
DescriptorHandle<StructuredBuffer<VertexData>> vertexBuffer;
DescriptorHandle<StructuredBuffer<CameraData>> cameraBuffer;
DescriptorHandle<Sampler2D> texture;
};
//uniform CameraData camera;
[vk::push_constant]
uniform PCB pcb;
struct VSIn {
uint vertexIndex : SV_VertexID;
};
struct VSOut
{
float4 position : SV_POSITION;
float2 texCoord0 : TEXCOORD0;
};
struct FSOut {
float4 Color;
};
[shader("vertex")]
func vsmain(VSIn input) -> VSOut {
VSOut output;
VertexData vd = pcb.vertexBuffer[input.vertexIndex];
output.position = mul(mul(mul(float4(vd.position.xyz, 1.0f), pcb.cameraBuffer[0].model), pcb.cameraBuffer[0].view), pcb.cameraBuffer[0].projection);
output.texCoord0 = vd.texCoord0;
return output;
}
[shader("fragment")]
func fsmain(VSOut input) -> FSOut {
FSOut outp;
outp.Color = pcb.vertexBuffer[0].position.rgba;
outp.Color = float4(pcb.texture.Sample(input.texCoord0).rgb, 1.0);
return outp;
}

View File

@ -62,8 +62,8 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
ERROR_IF(!data, "Could not load {}", path) THEN_ABORT(-1);
u32 width = Cast<u32>(x);
u32 height = Cast<u32>(y);
u32 width = static_cast<u32>(x);
u32 height = static_cast<u32>(y);
auto texture = m_ResourceManager->CombinedImageViews().CreateTexture2D<TextureView>({
.m_Format = vk::Format::eR32G32B32A32Sfloat,
@ -248,7 +248,7 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref<Texture> &texture, vk
}
vk::DependencyInfo imageStartDependency = {
.imageMemoryBarrierCount = Cast<u32>(startBarriers.size()),
.imageMemoryBarrierCount = static_cast<u32>(startBarriers.size()),
.pImageMemoryBarriers = startBarriers.data(),
};
@ -331,8 +331,8 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref<Texture> &texture, vk
commandBuffer.pipelineBarrier2(&imageStartDependency);
i32 prevMipWidth = Cast<i32>(texture->m_Extent.width);
i32 prevMipHeight = Cast<i32>(texture->m_Extent.height);
i32 prevMipWidth = static_cast<i32>(texture->m_Extent.width);
i32 prevMipHeight = static_cast<i32>(texture->m_Extent.height);
u32 maxPrevMip = texture->GetMipLevels() - 1;
for (u32 prevMipLevel = 0; prevMipLevel < maxPrevMip; ++prevMipLevel)
@ -382,8 +382,8 @@ AssetLoader::LoadImageToGpu(tinygltf::Image *image, bool isSrgb, cstr name) cons
#endif
u32 height = Cast<u32>(image->height);
u32 width = Cast<u32>(image->width);
u32 height = static_cast<u32>(image->height);
u32 width = static_cast<u32>(image->width);
vk::Format imageFormat = isSrgb ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm;
@ -465,8 +465,8 @@ AssetLoader::LoadImageToGpu(tinygltf::Image *image, bool isSrgb, cstr name) cons
vk::BufferImageCopy2 imageCopy = {
.bufferOffset = 0,
.bufferRowLength = Cast<u32>(image->width),
.bufferImageHeight = Cast<u32>(image->height),
.bufferRowLength = static_cast<u32>(image->width),
.bufferImageHeight = static_cast<u32>(image->height),
.imageSubresource =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
@ -583,8 +583,8 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
materials.push_back({
.m_AlbedoFactor = VectorToVec4(material.pbrMetallicRoughness.baseColorFactor),
.m_EmissionFactor = VectorToVec3(material.emissiveFactor),
.m_MetalFactor = Cast<f32>(material.pbrMetallicRoughness.metallicFactor),
.m_RoughFactor = Cast<f32>(material.pbrMetallicRoughness.roughnessFactor),
.m_MetalFactor = static_cast<f32>(material.pbrMetallicRoughness.metallicFactor),
.m_RoughFactor = static_cast<f32>(material.pbrMetallicRoughness.roughnessFactor),
.m_AlbedoTex = getTextureHandle(material.pbrMetallicRoughness.baseColorTexture.index, true),
.m_NormalTex = getTextureHandle(material.normalTexture.index, false),
.m_MetalRoughTex =
@ -643,17 +643,17 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
tinygltf::Buffer *posBuffer = &model.buffers[posBufferView->buffer];
usize byteOffset = (posAccessor->byteOffset + posBufferView->byteOffset);
vertexCount = Cast<u32>(posAccessor->count);
vertexCount = static_cast<u32>(posAccessor->count);
vertexPositions.reserve(vertexOffset + vertexCount);
if (posAccessor->type == TINYGLTF_TYPE_VEC4)
{
auto data = Recast<vec4 *>(posBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec4 *>(posBuffer->data.data() + byteOffset);
vertexPositions.insert(vertexPositions.end(), data, data + vertexCount);
}
else if (posAccessor->type == TINYGLTF_TYPE_VEC3)
{
auto data = Recast<vec3 *>(posBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec3 *>(posBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
vertexPositions.push_back(vec4(data[i], 1.0f));
@ -661,7 +661,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
}
else if (posAccessor->type == TINYGLTF_TYPE_VEC2)
{
auto data = Recast<vec2 *>(posBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec2 *>(posBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
vertexPositions.push_back(vec4(data[i], 0.0f, 1.0f));
@ -685,7 +685,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
if (normAccessor->type == TINYGLTF_TYPE_VEC4)
{
auto data = Recast<vec4 *>(normBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec4 *>(normBuffer->data.data() + byteOffset);
vec4 *end = data + vertexCount;
u32 idx = vertexOffset;
@ -697,7 +697,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
}
else if (normAccessor->type == TINYGLTF_TYPE_VEC3)
{
auto data = Recast<vec3 *>(normBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec3 *>(normBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
auto norm = vec4(data[i], 0.0f);
@ -706,7 +706,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
}
else if (normAccessor->type == TINYGLTF_TYPE_VEC2)
{
auto data = Recast<vec2 *>(normBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec2 *>(normBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
auto norm = vec4(data[i], 0.0f, 0.0f);
@ -729,7 +729,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
assert(uvAccessor->type == TINYGLTF_TYPE_VEC2 &&
uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT);
{
auto data = Recast<vec2 *>(uvBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec2 *>(uvBuffer->data.data() + byteOffset);
vec2 *end = data + vertexCount;
u32 idx = vertexOffset;
vec2 *it = data;
@ -752,7 +752,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
if (colorAccessor->type == TINYGLTF_TYPE_VEC4)
{
auto data = Recast<vec4 *>(colorBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec4 *>(colorBuffer->data.data() + byteOffset);
vec4 *end = data + vertexCount;
u32 idx = vertexOffset;
@ -764,7 +764,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
}
else if (colorAccessor->type == TINYGLTF_TYPE_VEC3)
{
auto data = Recast<vec3 *>(colorBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<vec3 *>(colorBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
auto color = vec4(data[i], 1.0f);
@ -785,22 +785,22 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
tinygltf::Buffer *indexBuffer = &model.buffers[indexBufferView->buffer];
usize byteOffset = (indexAccessor->byteOffset + indexBufferView->byteOffset);
indexCount = Cast<u32>(indexAccessor->count);
indexCount = static_cast<u32>(indexAccessor->count);
indices.reserve(indexOffset + indexCount);
if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT)
{
auto data = Recast<u32 *>(indexBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<u32 *>(indexBuffer->data.data() + byteOffset);
indices.insert(indices.end(), data, data + indexCount);
}
else if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
{
auto data = Recast<u16 *>(indexBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<u16 *>(indexBuffer->data.data() + byteOffset);
indices.insert(indices.end(), data, data + indexCount);
}
else if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)
{
auto data = Recast<u8 *>(indexBuffer->data.data() + byteOffset);
auto data = reinterpret_cast<u8 *>(indexBuffer->data.data() + byteOffset);
indices.insert(indices.end(), data, data + indexCount);
}
}
@ -861,7 +861,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
const mat4 transform = translate(mat4(1.0f), nodeTranslation) * mat4_cast(nodeRotation) *
scale(mat4(1.0f), nodeScale) * nodeMatrix;
const i32 nodeArrayIndex = Cast<i32>(nodes.Add(transform, parent));
const i32 nodeArrayIndex = static_cast<i32>(nodes.Add(transform, parent));
if (node->mesh >= 0)
{
auto [start, count] = meshPrimRanges[node->mesh];

View File

@ -132,7 +132,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
readyToWriteBarriers[3].subresourceRange = lutSubresRange;
vk::DependencyInfo readyToWriteDependency = {
.imageMemoryBarrierCount = Cast<u32>(readyToWriteBarriers.size()),
.imageMemoryBarrierCount = static_cast<u32>(readyToWriteBarriers.size()),
.pImageMemoryBarriers = readyToWriteBarriers.data(),
};
@ -209,7 +209,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
.stageFlags = vk::ShaderStageFlagBits::eCompute,
.offset = 0,
.size =
Cast<u32>(eastl::max(eastl::max(sizeof(SkyboxPushConstants), sizeof(BrdfLutPushConstants)),
static_cast<u32>(eastl::max(eastl::max(sizeof(SkyboxPushConstants), sizeof(BrdfLutPushConstants)),
eastl::max(sizeof(DiffuseIrradiancePushConstants), sizeof(PrefilterPushConstants)))),
};
@ -267,7 +267,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
eastl::array<vk::Pipeline, computePipelineCreateInfo.size()> pipelines;
AbortIfFailed(
pDevice->m_Device.createComputePipelines(pDevice->m_PipelineCache, Cast<u32>(computePipelineCreateInfo.size()),
pDevice->m_Device.createComputePipelines(pDevice->m_PipelineCache, static_cast<u32>(computePipelineCreateInfo.size()),
computePipelineCreateInfo.data(), nullptr, pipelines.data()));
vk::Pipeline eqRectToCubePipeline = pipelines[0];
@ -345,7 +345,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
{
prefilterPushConstants.m_OutputTexture = tex;
prefilterPushConstants.m_CubeSide = mipSize;
prefilterPushConstants.m_Roughness = Cast<f32>(mipCount) / Cast<f32>(prefilterMipCountMax - 1);
prefilterPushConstants.m_Roughness = static_cast<f32>(mipCount) / static_cast<f32>(prefilterMipCountMax - 1);
cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof prefilterPushConstants,
&prefilterPushConstants);
u32 groupCount = eastl::max(mipSize / 16u, 1u);

View File

@ -36,10 +36,10 @@ static_assert(Light::COLOR_MASK == 0xFFFFFF00);
inline u32
ToColor32(const vec4 &col)
{
const u32 r = Cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
const u32 g = Cast<u32>(eastl::min(col.g, 1.0f) * 255.99f);
const u32 b = Cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
const u32 a = Cast<u32>(eastl::min(col.a, 1.0f) * 255.99f);
const u32 r = static_cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
const u32 g = static_cast<u32>(eastl::min(col.g, 1.0f) * 255.99f);
const u32 b = static_cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
const u32 a = static_cast<u32>(eastl::min(col.a, 1.0f) * 255.99f);
return r << 24 | g << 16 | b << 8 | a;
}
@ -47,9 +47,9 @@ ToColor32(const vec4 &col)
inline u32
ToColor32(const vec3 &col)
{
const u32 r = Cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
const u32 g = Cast<u32>(eastl::min(col.g, 1.0f) * 255.99f);
const u32 b = Cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
const u32 r = static_cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
const u32 g = static_cast<u32>(eastl::min(col.g, 1.0f) * 255.99f);
const u32 b = static_cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
constexpr u32 a = 255;
return r << 24 | g << 16 | b << 8 | a;
@ -177,7 +177,7 @@ LightManager::AddPoint(const vec3 &position, const vec3 &color, const f32 radius
m_GpuBufferCapacity_ |= UPDATE_REQUIRED_BIT;
return {Light::TYPE_POINT, gen, Cast<u16>(index)};
return {Light::TYPE_POINT, gen, static_cast<u16>(index)};
}
++light;
}
@ -207,7 +207,7 @@ LightManager::AddPoint(const vec3 &position, const vec3 &color, const f32 radius
void
LightManager::Update()
{
const u16 requiredBufferCapacity = eastl::min(Cast<u16>(m_Lights.capacity()), MAX_LIGHTS);
const u16 requiredBufferCapacity = eastl::min(static_cast<u16>(m_Lights.capacity()), MAX_LIGHTS);
if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity)
{
auto newBuffer = m_ResourceManager->Buffers().CreateStorageBuffer(requiredBufferCapacity * sizeof m_Lights[0],

View File

@ -98,7 +98,7 @@ struct LightManager
// Using lower bit. Capacity can be directly a multiple of 2
// Thus, range is up to MaxValue<u16>
constexpr static u16 UPDATE_REQUIRED_BIT = 1;
constexpr static u16 CAPACITY_MASK = Cast<u16>(~UPDATE_REQUIRED_BIT);
constexpr static u16 CAPACITY_MASK = static_cast<u16>(~UPDATE_REQUIRED_BIT);
LightHandle AddDirectional(const vec3 &direction, const vec3 &color, f32 intensity);
LightHandle AddPoint(const vec3 &position, const vec3 &color, f32 radius, f32 intensity);

View File

@ -216,7 +216,7 @@ main(int, char **)
},
};
vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
.maxSets = 1, .poolSizeCount = Cast<u32>(poolSizes.size()), .pPoolSizes = poolSizes.data()};
.maxSets = 1, .poolSizeCount = static_cast<u32>(poolSizes.size()), .pPoolSizes = poolSizes.data()};
AbortIfFailed(device.m_Device.createDescriptorPool(&descriptorPoolCreateInfo, nullptr, &descriptorPool));
vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
@ -230,7 +230,7 @@ main(int, char **)
vk::Extent2D internalResolution = {1920, 1080};
CameraController cameraController = {vec3{0.0f, 0.0f, 2.0f}, vec3{0.0f}, 70_deg,
Cast<f32>(swapchain.m_Extent.width) / Cast<f32>(swapchain.m_Extent.height)};
static_cast<f32>(swapchain.m_Extent.width) / static_cast<f32>(swapchain.m_Extent.height)};
usize uboSize = 0;
usize cameraSize = sizeof cameraController.m_Camera;
@ -277,16 +277,16 @@ main(int, char **)
.pBufferInfo = &lightingBufferInfo,
},
};
device.m_Device.updateDescriptorSets(Cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
device.m_Device.updateDescriptorSets(static_cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
commitManager.Update();
// Persistent variables
vk::Viewport viewport = {
.x = 0,
.y = Cast<f32>(internalResolution.height),
.width = Cast<f32>(internalResolution.width),
.height = -Cast<f32>(internalResolution.height),
.y = static_cast<f32>(internalResolution.height),
.width = static_cast<f32>(internalResolution.width),
.height = -static_cast<f32>(internalResolution.height),
.minDepth = 0.0,
.maxDepth = 1.0,
};
@ -347,7 +347,7 @@ main(int, char **)
acquireToTransferDstBarrier,
};
vk::DependencyInfo postRenderDependencies = {
.imageMemoryBarrierCount = Cast<u32>(postRenderBarriers.size()),
.imageMemoryBarrierCount = static_cast<u32>(postRenderBarriers.size()),
.pImageMemoryBarriers = postRenderBarriers.data(),
};
@ -403,7 +403,7 @@ main(int, char **)
}));
}
gui::Init(&context, &device, &window, swapchain.m_Format, Cast<u32>(swapchain.m_ImageViews.size()),
gui::Init(&context, &device, &window, swapchain.m_Format, static_cast<u32>(swapchain.m_ImageViews.size()),
queueAllocation.m_Family, graphicsQueue);
bool rotating = false;
bool lockToScreen = true;
@ -417,14 +417,14 @@ main(int, char **)
constexpr static u32 SHOW_DIFFUSE_BIT = 1 << 2;
constexpr static u32 SHOW_PREFILTER_BIT = 1 << 3;
i32 height = Cast<i32>(internalResolution.height);
i32 height = static_cast<i32>(internalResolution.height);
f32 camPitch = glm::degrees(cameraController.m_Pitch);
f32 camYaw = glm::degrees(cameraController.m_Yaw);
vec3 camPosition = cameraController.m_Camera.m_Position;
vk::Extent2D inputResolution = internalResolution;
swapchain.RegisterResizeCallback([&cameraController](vk::Extent2D extent) {
cameraController.SetAspectRatio(Cast<f32>(extent.width) / Cast<f32>(extent.height));
cameraController.SetAspectRatio(static_cast<f32>(extent.width) / static_cast<f32>(extent.height));
});
Time::Init();
@ -449,7 +449,7 @@ main(int, char **)
}
inputResolution.height = height;
inputResolution.width = Cast<i32>(cameraController.m_AspectRatio * Cast<f32>(inputResolution.height));
inputResolution.width = static_cast<i32>(cameraController.m_AspectRatio * static_cast<f32>(inputResolution.height));
if (gui::Button("Change Resolution"))
{
@ -457,9 +457,9 @@ main(int, char **)
inputResolution.height != internalResolution.height)
{
internalResolution = inputResolution;
viewport.width = Cast<f32>(internalResolution.width);
viewport.height = -Cast<f32>(internalResolution.height);
viewport.y = Cast<f32>(internalResolution.height);
viewport.width = static_cast<f32>(internalResolution.width);
viewport.height = -static_cast<f32>(internalResolution.height);
viewport.y = static_cast<f32>(internalResolution.height);
scissor.extent = internalResolution;
}
}
@ -470,9 +470,9 @@ main(int, char **)
swapchain.m_Extent.height != internalResolution.height)
{
internalResolution = swapchain.m_Extent;
viewport.width = Cast<f32>(internalResolution.width);
viewport.height = -Cast<f32>(internalResolution.height);
viewport.y = Cast<f32>(internalResolution.height);
viewport.width = static_cast<f32>(internalResolution.width);
viewport.height = -static_cast<f32>(internalResolution.height);
viewport.y = static_cast<f32>(internalResolution.height);
scissor.extent = internalResolution;
}
}
@ -488,7 +488,7 @@ main(int, char **)
camYaw = camYaw - floor((camYaw + 180.0f) / 360.0f) * 360.0f;
cameraController.SetPitchYaw(glm::radians(camPitch), glm::radians(camYaw));
}
if (gui::InputFloat3("Camera Position", Recast<f32 *>(&camPosition)))
if (gui::InputFloat3("Camera Position", reinterpret_cast<f32 *>(&camPosition)))
{
cameraController.SetPosition(camPosition);
}
@ -512,7 +512,7 @@ main(int, char **)
if (rotating)
{
model.SetModelTransform(
rotate(model.GetModelTransform(), Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f)));
rotate(model.GetModelTransform(), static_cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f)));
}
model.Update();
cameraController.m_Camera.CalculateInverses();
@ -584,7 +584,7 @@ main(int, char **)
vk::RenderingInfo renderingInfo = {
.renderArea = {.extent = ToExtent2D(currentAttachment->m_Extent)},
.layerCount = 1,
.colorAttachmentCount = Cast<u32>(attachmentInfos.size()),
.colorAttachmentCount = static_cast<u32>(attachmentInfos.size()),
.pColorAttachments = attachmentInfos.data(),
.pDepthAttachment = &depthAttachment,
};
@ -637,7 +637,7 @@ main(int, char **)
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
innerPcbOffset += sizeof prim.m_TransformIdx;
cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast<i32>(prim.m_VertexOffset), 0);
cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, static_cast<i32>(prim.m_VertexOffset), 0);
}
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, backGroundPipeline.m_Pipeline);
@ -670,7 +670,7 @@ main(int, char **)
.dstOffsets =
std::array{
vk::Offset3D{0, 0, 0},
vk::Offset3D{Cast<i32>(swapchain.m_Extent.width), Cast<i32>(swapchain.m_Extent.height), 1},
vk::Offset3D{static_cast<i32>(swapchain.m_Extent.width), static_cast<i32>(swapchain.m_Extent.height), 1},
},
};
cmd.blitImage(currentImage, postRenderBarriers[0].newLayout, currentSwapchainImage,

View File

@ -49,7 +49,7 @@ Nodes::operator[](const u32 index)
u32
Nodes::Count() const
{
return Cast<u32>(m_Transforms.size());
return static_cast<u32>(m_Transforms.size());
}
usize

View File

@ -60,7 +60,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems:
},
};
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
.pBindings = descriptorSetLayoutBindings.data(),
};
vk::DescriptorSetLayout descriptorSetLayout;
@ -76,7 +76,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems:
};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
.pSetLayouts = descriptorSetLayouts.data(),
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange,
@ -139,7 +139,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems:
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
@ -152,7 +152,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems:
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(shaderStages.size()),
.stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
@ -221,7 +221,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
},
};
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
.pBindings = descriptorSetLayoutBindings.data(),
};
vk::DescriptorSetLayout descriptorSetLayout;
@ -237,7 +237,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
.pSetLayouts = descriptorSetLayouts.data(),
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange,
@ -300,7 +300,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
@ -313,7 +313,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(shaderStages.size()),
.stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,

View File

@ -102,8 +102,8 @@ AssetLoader::LoadHdrImage(Texture *texture, cstr path, cstr name) const
ERROR_IF(!data, "Could not load {}", path) THEN_ABORT(-1);
assert(nChannels == 3);
u32 width = Cast<u32>(x);
u32 height = Cast<u32>(y);
u32 width = static_cast<u32>(x);
u32 height = static_cast<u32>(y);
StagingBuffer stagingBuffer;
texture->Init(m_ResourceManager->m_Device, {width, height}, vk::Format::eR32G32B32A32Sfloat, false, path);
@ -279,7 +279,7 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, Texture *texture, vk::ImageLayo
}
vk::DependencyInfo imageStartDependency = {
.imageMemoryBarrierCount = Cast<u32>(startBarriers.size()),
.imageMemoryBarrierCount = static_cast<u32>(startBarriers.size()),
.pImageMemoryBarriers = startBarriers.data(),
};
@ -362,8 +362,8 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, Texture *texture, vk::ImageLayo
commandBuffer.pipelineBarrier2(&imageStartDependency);
i32 prevMipWidth = Cast<i32>(texture->m_Extent.width);
i32 prevMipHeight = Cast<i32>(texture->m_Extent.height);
i32 prevMipWidth = static_cast<i32>(texture->m_Extent.width);
i32 prevMipHeight = static_cast<i32>(texture->m_Extent.height);
u32 maxPrevMip = texture->GetMipLevels() - 1;
for (u32 prevMipLevel = 0; prevMipLevel < maxPrevMip; ++prevMipLevel)
@ -404,8 +404,8 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image
assert(image->component == 4);
assert(image->height > 0 && image->width > 0);
u32 height = Cast<u32>(image->height);
u32 width = Cast<u32>(image->width);
u32 height = static_cast<u32>(image->height);
u32 width = static_cast<u32>(image->width);
vk::Format imageFormat = isSrgb ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm;
@ -481,8 +481,8 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image
vk::BufferImageCopy2 imageCopy = {
.bufferOffset = 0,
.bufferRowLength = Cast<u32>(image->width),
.bufferImageHeight = Cast<u32>(image->height),
.bufferRowLength = static_cast<u32>(image->width),
.bufferImageHeight = static_cast<u32>(image->height),
.imageSubresource =
{
.aspectMask = vk::ImageAspectFlagBits::eColor,
@ -558,8 +558,8 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
if (node->mesh >= 0)
{
auto *mesh = &model->meshes[node->mesh];
u32 vertexOffset = Cast<u32>(vertexPositions->size());
u32 indexOffset = Cast<u32>(indices->size());
u32 vertexOffset = static_cast<u32>(vertexPositions->size());
u32 indexOffset = static_cast<u32>(indices->size());
for (auto &prim : mesh->primitives)
{
u32 vertexCount = 0;
@ -577,17 +577,17 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
tinygltf::Buffer *posBuffer = &model->buffers[posBufferView->buffer];
usize byteOffset = (posAccessor->byteOffset + posBufferView->byteOffset);
vertexCount = Cast<u32>(posAccessor->count);
vertexCount = static_cast<u32>(posAccessor->count);
vertexPositions->reserve(vertexOffset + vertexCount);
if (posAccessor->type == TINYGLTF_TYPE_VEC4)
{
vec4 *data = Recast<vec4 *>(posBuffer->data.data() + byteOffset);
vec4 *data = reinterpret_cast<vec4 *>(posBuffer->data.data() + byteOffset);
vertexPositions->insert(vertexPositions->end(), data, data + vertexCount);
}
else if (posAccessor->type == TINYGLTF_TYPE_VEC3)
{
vec3 *data = Recast<vec3 *>(posBuffer->data.data() + byteOffset);
vec3 *data = reinterpret_cast<vec3 *>(posBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
vertexPositions->push_back(vec4(data[i], 1.0f));
@ -595,7 +595,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
}
else if (posAccessor->type == TINYGLTF_TYPE_VEC2)
{
vec2 *data = Recast<vec2 *>(posBuffer->data.data() + byteOffset);
vec2 *data = reinterpret_cast<vec2 *>(posBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
vertexPositions->push_back(vec4(data[i], 0.0f, 1.0f));
@ -619,7 +619,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
if (normAccessor->type == TINYGLTF_TYPE_VEC4)
{
vec4 *data = Recast<vec4 *>(normBuffer->data.data() + byteOffset);
vec4 *data = reinterpret_cast<vec4 *>(normBuffer->data.data() + byteOffset);
vec4 *end = data + vertexCount;
u32 idx = vertexOffset;
@ -631,7 +631,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
}
else if (normAccessor->type == TINYGLTF_TYPE_VEC3)
{
vec3 *data = Recast<vec3 *>(normBuffer->data.data() + byteOffset);
vec3 *data = reinterpret_cast<vec3 *>(normBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
auto norm = vec4(data[i], 0.0f);
@ -640,7 +640,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
}
else if (normAccessor->type == TINYGLTF_TYPE_VEC2)
{
vec2 *data = Recast<vec2 *>(normBuffer->data.data() + byteOffset);
vec2 *data = reinterpret_cast<vec2 *>(normBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
auto norm = vec4(data[i], 0.0f, 0.0f);
@ -663,7 +663,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
assert(uvAccessor->type == TINYGLTF_TYPE_VEC2 &&
uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT);
{
vec2 *data = Recast<vec2 *>(uvBuffer->data.data() + byteOffset);
vec2 *data = reinterpret_cast<vec2 *>(uvBuffer->data.data() + byteOffset);
vec2 *end = data + vertexCount;
u32 idx = vertexOffset;
vec2 *it = data;
@ -686,7 +686,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
if (colorAccessor->type == TINYGLTF_TYPE_VEC4)
{
vec4 *data = Recast<vec4 *>(colorBuffer->data.data() + byteOffset);
vec4 *data = reinterpret_cast<vec4 *>(colorBuffer->data.data() + byteOffset);
vec4 *end = data + vertexCount;
u32 idx = vertexOffset;
@ -698,7 +698,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
}
else if (colorAccessor->type == TINYGLTF_TYPE_VEC3)
{
vec3 *data = Recast<vec3 *>(colorBuffer->data.data() + byteOffset);
vec3 *data = reinterpret_cast<vec3 *>(colorBuffer->data.data() + byteOffset);
for (u32 i = 0; i < vertexCount; ++i)
{
auto color = vec4(data[i], 1.0f);
@ -719,22 +719,22 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
tinygltf::Buffer *indexBuffer = &model->buffers[indexBufferView->buffer];
usize byteOffset = (indexAccessor->byteOffset + indexBufferView->byteOffset);
indexCount = Cast<u32>(indexAccessor->count);
indexCount = static_cast<u32>(indexAccessor->count);
indices->reserve(indexOffset + indexCount);
if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT)
{
u32 *data = Recast<u32 *>(indexBuffer->data.data() + byteOffset);
u32 *data = reinterpret_cast<u32 *>(indexBuffer->data.data() + byteOffset);
indices->insert(indices->end(), data, data + indexCount);
}
else if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
{
u16 *data = Recast<u16 *>(indexBuffer->data.data() + byteOffset);
u16 *data = reinterpret_cast<u16 *>(indexBuffer->data.data() + byteOffset);
indices->insert(indices->end(), data, data + indexCount);
}
else if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)
{
u8 *data = Recast<u8 *>(indexBuffer->data.data() + byteOffset);
u8 *data = reinterpret_cast<u8 *>(indexBuffer->data.data() + byteOffset);
indices->insert(indices->end(), data, data + indexCount);
}
}
@ -860,7 +860,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
return materialFind->second;
}
u32 index = Cast<u32>(materials.size());
u32 index = static_cast<u32>(materials.size());
auto *material = &model.materials[materialIdx];
f32 alphaBlendValue = -1;
@ -870,14 +870,14 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
}
else if (material->alphaMode == "MASK")
{
alphaBlendValue = Cast<f32>(material->alphaCutoff);
alphaBlendValue = static_cast<f32>(material->alphaCutoff);
}
materials.push_back({
.m_AlbedoFactor = VectorToVec4(material->pbrMetallicRoughness.baseColorFactor),
.m_EmissionFactor = VectorToVec3(material->emissiveFactor),
.m_MetalFactor = Cast<f32>(material->pbrMetallicRoughness.metallicFactor),
.m_RoughFactor = Cast<f32>(material->pbrMetallicRoughness.roughnessFactor),
.m_MetalFactor = static_cast<f32>(material->pbrMetallicRoughness.metallicFactor),
.m_RoughFactor = static_cast<f32>(material->pbrMetallicRoughness.roughnessFactor),
.m_AlbedoTex = getTextureHandle(material->pbrMetallicRoughness.baseColorTexture.index, true),
.m_NormalTex = getTextureHandle(material->normalTexture.index, false),
.m_MetalRoughTex = getTextureHandle(material->pbrMetallicRoughness.metallicRoughnessTexture.index, false),

View File

@ -121,7 +121,7 @@ CreateEnvironment(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cu
readyToWriteBarriers[3].subresourceRange = lutSubresRange;
vk::DependencyInfo readyToWriteDependency = {
.imageMemoryBarrierCount = Cast<u32>(readyToWriteBarriers.size()),
.imageMemoryBarrierCount = static_cast<u32>(readyToWriteBarriers.size()),
.pImageMemoryBarriers = readyToWriteBarriers.data(),
};
@ -197,7 +197,7 @@ CreateEnvironment(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cu
vk::PushConstantRange pcr = {
.stageFlags = vk::ShaderStageFlagBits::eCompute,
.offset = 0,
.size = Cast<u32>(eastl::max(eastl::max(sizeof(SkyboxPushConstants), sizeof(BrdfLutPushConstants)),
.size = static_cast<u32>(eastl::max(eastl::max(sizeof(SkyboxPushConstants), sizeof(BrdfLutPushConstants)),
eastl::max(sizeof(DiffuseIrradiancePushConstants), sizeof(PrefilterPushConstants)))),
};
@ -254,7 +254,7 @@ CreateEnvironment(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cu
};
eastl::array<vk::Pipeline, computePipelineCreateInfo.size()> pipelines;
AbortIfFailed(pDevice->m_Device.createComputePipelines(pDevice->m_PipelineCache, Cast<u32>(computePipelineCreateInfo.size()),
AbortIfFailed(pDevice->m_Device.createComputePipelines(pDevice->m_PipelineCache, static_cast<u32>(computePipelineCreateInfo.size()),
computePipelineCreateInfo.data(), nullptr,
pipelines.data()));
@ -331,7 +331,7 @@ CreateEnvironment(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cu
{
prefilterPushConstants.m_OutputTexture = tex;
prefilterPushConstants.m_CubeSide = mipSize;
prefilterPushConstants.m_Roughness = Cast<f32>(mipCount) / Cast<f32>(prefilterMipCountMax);
prefilterPushConstants.m_Roughness = static_cast<f32>(mipCount) / static_cast<f32>(prefilterMipCountMax);
cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof prefilterPushConstants,
&prefilterPushConstants);
u32 groupCount = eastl::max(mipSize / 16u, 1u);

View File

@ -56,10 +56,10 @@ static_assert(Light::COLOR_MASK == 0xFFFFFF00);
inline u32
ToColor32(const vec4 &col)
{
const u32 r = Cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
const u32 g = Cast<u32>(eastl::min(col.g, 1.0f) * 255.99f);
const u32 b = Cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
const u32 a = Cast<u32>(eastl::min(col.a, 1.0f) * 255.99f);
const u32 r = static_cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
const u32 g = static_cast<u32>(eastl::min(col.g, 1.0f) * 255.99f);
const u32 b = static_cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
const u32 a = static_cast<u32>(eastl::min(col.a, 1.0f) * 255.99f);
return r << 24 | g << 16 | b << 8 | a;
}
@ -67,9 +67,9 @@ ToColor32(const vec4 &col)
inline u32
ToColor32(const vec3 &col)
{
const u32 r = Cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
const u32 g = Cast<u32>(eastl::min(col.g, 1.0f) * 255.99f);
const u32 b = Cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
const u32 r = static_cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
const u32 g = static_cast<u32>(eastl::min(col.g, 1.0f) * 255.99f);
const u32 b = static_cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
constexpr u32 a = 255;
return r << 24 | g << 16 | b << 8 | a;
@ -206,7 +206,7 @@ LightManager::AddPoint(const vec3 &position, const vec3 &color, const f32 radius
m_GpuBufferCapacity_ |= UPDATE_REQUIRED_BIT;
return {Light::TYPE_POINT, gen, Cast<u16>(index)};
return {Light::TYPE_POINT, gen, static_cast<u16>(index)};
}
++light;
}
@ -236,7 +236,7 @@ LightManager::AddPoint(const vec3 &position, const vec3 &color, const f32 radius
void
LightManager::Update()
{
const u16 requiredBufferCapacity = eastl::min(Cast<u16>(m_Lights.capacity()), MAX_LIGHTS);
const u16 requiredBufferCapacity = eastl::min(static_cast<u16>(m_Lights.capacity()), MAX_LIGHTS);
if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity)
{
m_GpuBufferCapacity_ = requiredBufferCapacity | UPDATE_REQUIRED_BIT;

View File

@ -73,7 +73,7 @@ struct LightManager
// Using lower bit. Capacity can be directly a multiple of 2
// Thus, range is up to MaxValue<u16>
constexpr static u16 UPDATE_REQUIRED_BIT = 1;
constexpr static u16 CAPACITY_MASK = Cast<u16>(~UPDATE_REQUIRED_BIT);
constexpr static u16 CAPACITY_MASK = static_cast<u16>(~UPDATE_REQUIRED_BIT);
LightHandle AddDirectional(const vec3 &direction, const vec3 &color, f32 intensity);
LightHandle AddPoint(const vec3 &position, const vec3 &color, f32 radius, f32 intensity);

View File

@ -49,7 +49,7 @@ main(int, char *[])
internalResolution.width = (internalResolution.height * INIT_WIDTH) / INIT_HEIGHT;
CameraController cameraController = {vec3{0.0f, 1.0f, 4.0f}, vec3{0.0f, 0.0f, 0.0f}, 70_deg,
Cast<f32>(internalResolution.width) / Cast<f32>(internalResolution.height)};
static_cast<f32>(internalResolution.width) / static_cast<f32>(internalResolution.height)};
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
@ -138,7 +138,7 @@ main(int, char *[])
},
};
vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
.maxSets = 1, .poolSizeCount = Cast<u32>(poolSizes.size()), .pPoolSizes = poolSizes.data()};
.maxSets = 1, .poolSizeCount = static_cast<u32>(poolSizes.size()), .pPoolSizes = poolSizes.data()};
AbortIfFailed(device.m_Device.createDescriptorPool(&descriptorPoolCreateInfo, nullptr, &descriptorPool));
vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
@ -164,14 +164,14 @@ main(int, char *[])
.pBufferInfo = &camLightBufferInfo,
},
};
device.m_Device.updateDescriptorSets(Cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
device.m_Device.updateDescriptorSets(static_cast<u32>(writeDescriptors.size()), writeDescriptors.data(), 0, nullptr);
// Persistent variables
vk::Viewport viewport = {
.x = 0,
.y = Cast<f32>(internalResolution.height),
.width = Cast<f32>(internalResolution.width),
.height = -Cast<f32>(internalResolution.height),
.y = static_cast<f32>(internalResolution.height),
.width = static_cast<f32>(internalResolution.width),
.height = -static_cast<f32>(internalResolution.height),
.minDepth = 0.0,
.maxDepth = 1.0,
};
@ -232,7 +232,7 @@ main(int, char *[])
acquireToTransferDstBarrier,
};
vk::DependencyInfo postRenderDependencies = {
.imageMemoryBarrierCount = Cast<u32>(postRenderBarriers.size()),
.imageMemoryBarrierCount = static_cast<u32>(postRenderBarriers.size()),
.pImageMemoryBarriers = postRenderBarriers.data(),
};
@ -314,13 +314,13 @@ main(int, char *[])
swapchain.RegisterResizeCallback(
[&cameraController, &internalResolution, &viewport, &scissor](vk::Extent2D extent) {
cameraController.SetAspectRatio(Cast<f32>(extent.width) / Cast<f32>(extent.height));
cameraController.SetAspectRatio(static_cast<f32>(extent.width) / static_cast<f32>(extent.height));
internalResolution.width = Cast<u32>(Cast<f32>(internalResolution.height) * cameraController.m_AspectRatio);
internalResolution.width = static_cast<u32>(static_cast<f32>(internalResolution.height) * cameraController.m_AspectRatio);
viewport.y = Cast<f32>(internalResolution.height);
viewport.width = Cast<f32>(internalResolution.width);
viewport.height = -Cast<f32>(internalResolution.height);
viewport.y = static_cast<f32>(internalResolution.height);
viewport.width = static_cast<f32>(internalResolution.width);
viewport.height = -static_cast<f32>(internalResolution.height);
scissor.extent = internalResolution;
});
@ -354,7 +354,7 @@ main(int, char *[])
// for (auto [entity, dynTrans] : rootModel.each())
//{
// dynTrans.m_Rotation =
// glm::rotate(dynTrans.m_Rotation, Cast<f32>(30_deg * (++index) * Time::m_Delta), vec3{0.0f, 1.0f,
// glm::rotate(dynTrans.m_Rotation, static_cast<f32>(30_deg * (++index) * Time::m_Delta), vec3{0.0f, 1.0f,
// 0.0f});
// }
@ -417,7 +417,7 @@ main(int, char *[])
registry.get<CGlobalTransform>(parent.m_ParentEntity).m_Transform * translation * rotation * scale;
}
u32 objectCount = Cast<u32>(renderableObjectsGroup.size());
u32 objectCount = static_cast<u32>(renderableObjectsGroup.size());
nodeData.clear();
nodeDrawInfo.clear();
nodeData.reserve(objectCount);
@ -474,7 +474,7 @@ main(int, char *[])
vk::RenderingInfo renderingInfo = {
.renderArea = {.extent = ToExtent2D(currentAttachment->m_Extent)},
.layerCount = 1,
.colorAttachmentCount = Cast<u32>(attachmentInfos.size()),
.colorAttachmentCount = static_cast<u32>(attachmentInfos.size()),
.pColorAttachments = attachmentInfos.data(),
.pDepthAttachment = &depthAttachment,
};
@ -531,7 +531,7 @@ main(int, char *[])
.dstOffsets =
std::array{
vk::Offset3D{0, 0, 0},
vk::Offset3D{Cast<i32>(swapchain.m_Extent.width), Cast<i32>(swapchain.m_Extent.height), 1},
vk::Offset3D{static_cast<i32>(swapchain.m_Extent.width), static_cast<i32>(swapchain.m_Extent.height), 1},
},
};
cmd.blitImage(currentImage, postRenderBarriers[0].newLayout, currentSwapchainImage,

View File

@ -46,7 +46,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const RenderRe
},
};
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
.pBindings = descriptorSetLayoutBindings.data(),
};
vk::DescriptorSetLayout descriptorSetLayout;
@ -62,7 +62,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const RenderRe
};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
.pSetLayouts = descriptorSetLayouts.data(),
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange,
@ -125,7 +125,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const RenderRe
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
@ -138,7 +138,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const RenderRe
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(shaderStages.size()),
.stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
@ -197,7 +197,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
},
};
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
.pBindings = descriptorSetLayoutBindings.data(),
};
vk::DescriptorSetLayout descriptorSetLayout;
@ -213,7 +213,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
};
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
.pSetLayouts = descriptorSetLayouts.data(),
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange,
@ -276,7 +276,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
};
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
@ -289,7 +289,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(shaderStages.size()),
.stageCount = static_cast<u32>(shaderStages.size()),
.pStages = shaderStages.data(),
.pVertexInputState = &vertexInputStateCreateInfo,
.pInputAssemblyState = &inputAssemblyStateCreateInfo,

View File

@ -33,7 +33,7 @@ TextureManager::Commit(Texture *texture)
Texture *allocatedTexture = &m_Textures[index];
assert(!allocatedTexture->IsValid());
m_FreeHead = *Recast<u32 *>(allocatedTexture);
m_FreeHead = *reinterpret_cast<u32 *>(allocatedTexture);
// Ensure it is copyable.
static_assert(std::is_trivially_copyable_v<Texture>);
@ -45,7 +45,7 @@ TextureManager::Commit(Texture *texture)
return {index};
}
const u32 index = Cast<u32>(m_Textures.size());
const u32 index = static_cast<u32>(m_Textures.size());
if (index < m_MaxCapacity)
{
Texture *allocatedTexture = &m_Textures.push_back();
@ -79,7 +79,7 @@ TextureManager::Release(const Device *device, const TextureHandle handle)
allocatedTexture->Destroy(device);
assert(!allocatedTexture->IsValid());
*Recast<u32 *>(allocatedTexture) = m_FreeHead;
*reinterpret_cast<u32 *>(allocatedTexture) = m_FreeHead;
m_FreeHead = handle.m_Index;
}
@ -104,10 +104,10 @@ BufferManager::Init(const u32 maxCapacity)
Buffer *pIter = m_Buffers;
for (u32 i = 1; i < m_MaxCapacity; ++i)
{
*Recast<u32 *>(pIter) = i;
*reinterpret_cast<u32 *>(pIter) = i;
++pIter;
}
*Recast<u32 *>(pIter) = GpuResourceHandle::INVALID_HANDLE;
*reinterpret_cast<u32 *>(pIter) = GpuResourceHandle::INVALID_HANDLE;
}
BufferHandle
@ -132,7 +132,7 @@ BufferManager::Commit_(StorageBuffer *buffer)
Buffer *allocatedBuffer = &m_Buffers[index];
assert(!allocatedBuffer->IsValid());
m_FreeHead = *Recast<u32 *>(allocatedBuffer);
m_FreeHead = *reinterpret_cast<u32 *>(allocatedBuffer);
// Ensure it is copyable.
static_assert(std::is_trivially_copyable_v<StorageBuffer>);
@ -149,7 +149,7 @@ BufferManager::Fetch(const BufferHandle handle)
{
assert(!handle.IsInvalid());
return Recast<StorageBuffer *>(&m_Buffers[handle.m_Index]);
return reinterpret_cast<StorageBuffer *>(&m_Buffers[handle.m_Index]);
}
void
@ -161,7 +161,7 @@ BufferManager::Release(const Device *device, const BufferHandle handle)
allocatedBuffer->Destroy(device);
assert(!allocatedBuffer->IsValid());
*Recast<u32 *>(allocatedBuffer) = m_FreeHead;
*reinterpret_cast<u32 *>(allocatedBuffer) = m_FreeHead;
m_FreeHead = handle.m_Index;
}
@ -196,7 +196,7 @@ StorageTextureManager::Fetch(const StorageTextureHandle handle)
{
assert(!handle.IsInvalid());
return Recast<StorageTexture *>(&m_Textures[handle.m_Index]);
return reinterpret_cast<StorageTexture *>(&m_Textures[handle.m_Index]);
}
void
@ -215,15 +215,15 @@ HashSamplerCreateInfo(const vk::SamplerCreateInfo *createInfo)
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(static_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
HashAny(static_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(static_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)
HashAny(static_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));
@ -253,7 +253,7 @@ SamplerManager::Create(const Device *device, const vk::SamplerCreateInfo *create
vk::Sampler sampler;
AbortIfFailed(device->m_Device.createSampler(createInfo, nullptr, &sampler));
const u32 index = Cast<u32>(m_SamplerHashes.size());
const u32 index = static_cast<u32>(m_SamplerHashes.size());
m_SamplerHashes.push_back(hash);
m_Samplers.push_back(sampler);
return {index};
@ -293,7 +293,7 @@ VirtualizedBufferPool::InitStorage(const Device *device, usize bufferMaxSize)
const VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {
.size = bufferMaxSize,
};
AbortIfFailed(Cast<vk::Result>(vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_Block)));
AbortIfFailed(static_cast<vk::Result>(vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_Block)));
}
void
@ -311,7 +311,7 @@ VirtualizedBufferPool::InitIndex(const Device *device, usize bufferMaxSize)
const VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {
.size = bufferMaxSize,
};
AbortIfFailed(Cast<vk::Result>(vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_Block)));
AbortIfFailed(static_cast<vk::Result>(vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_Block)));
}
void
@ -343,11 +343,11 @@ VirtualizedBufferPool::Create(usize size, usize alignment)
index = m_FreeHead;
allocVBuf = &m_VirtualBuffers[index];
m_FreeHead = *Recast<u32 *>(allocVBuf);
m_FreeHead = *reinterpret_cast<u32 *>(allocVBuf);
}
else
{
index = Cast<u32>(m_VirtualBuffers.size());
index = static_cast<u32>(m_VirtualBuffers.size());
allocVBuf = &m_VirtualBuffers.push_back();
}
@ -374,7 +374,7 @@ VirtualizedBufferPool::Release(VirtualizedBufferHandle handle)
VirtualBuffer *virtualBuffer = &m_VirtualBuffers[handle.m_Index];
vmaVirtualFree(m_Block, virtualBuffer->m_Allocation);
*Recast<u32 *>(virtualBuffer) = m_FreeHead;
*reinterpret_cast<u32 *>(virtualBuffer) = m_FreeHead;
m_FreeHead = handle.m_Index;
}
@ -656,7 +656,7 @@ RenderResourceManager::Update()
// Descriptor Updates
if (!m_Writes.empty())
{
m_Device->m_Device.updateDescriptorSets(Cast<u32>(m_Writes.size()), m_Writes.data(), 0, nullptr);
m_Device->m_Device.updateDescriptorSets(static_cast<u32>(m_Writes.size()), m_Writes.data(), 0, nullptr);
m_Writes.clear();
m_WriteInfos.clear();
@ -674,10 +674,10 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
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 buffersCount = eastl::min(properties.limits.maxPerStageDescriptorStorageBuffers - 1024, static_cast<u32>(maxSize));
u32 texturesCount = eastl::min(properties.limits.maxPerStageDescriptorSampledImages - 1024, static_cast<u32>(maxSize));
u32 storageTexturesCount =
eastl::min(properties.limits.maxPerStageDescriptorStorageImages - 1024, Cast<u32>(maxSize));
eastl::min(properties.limits.maxPerStageDescriptorStorageImages - 1024, static_cast<u32>(maxSize));
INFO("Max Buffer Count: {}", buffersCount);
INFO("Max Texture Count: {}", texturesCount);
@ -728,7 +728,7 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
const vk::DescriptorPoolCreateInfo poolCreateInfo = {
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
.maxSets = 1,
.poolSizeCount = Cast<u32>(poolSizes.size()),
.poolSizeCount = static_cast<u32>(poolSizes.size()),
.pPoolSizes = poolSizes.data(),
};
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
@ -742,7 +742,7 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
};
vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo = {
.bindingCount = Cast<u32>(layoutBindingFlags.size()),
.bindingCount = static_cast<u32>(layoutBindingFlags.size()),
.pBindingFlags = layoutBindingFlags.data(),
};
@ -750,19 +750,19 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
vk::DescriptorSetLayoutBinding{
.binding = BUFFER_BINDING_INDEX,
.descriptorType = vk::DescriptorType::eStorageBuffer,
.descriptorCount = Cast<u32>(buffersCount),
.descriptorCount = static_cast<u32>(buffersCount),
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
vk::DescriptorSetLayoutBinding{
.binding = TEXTURE_BINDING_INDEX,
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
.descriptorCount = Cast<u32>(texturesCount),
.descriptorCount = static_cast<u32>(texturesCount),
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
vk::DescriptorSetLayoutBinding{
.binding = STORAGE_TEXTURE_BINDING_INDEX,
.descriptorType = vk::DescriptorType::eStorageImage,
.descriptorCount = Cast<u32>(storageTexturesCount),
.descriptorCount = static_cast<u32>(storageTexturesCount),
.stageFlags = vk::ShaderStageFlagBits::eAll,
},
};
@ -770,7 +770,7 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.pNext = &bindingFlagsCreateInfo,
.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
.bindingCount = Cast<u32>(descriptorLayoutBindings.size()),
.bindingCount = static_cast<u32>(descriptorLayoutBindings.size()),
.pBindings = descriptorLayoutBindings.data(),
};
AbortIfFailed(device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &m_SetLayout));
@ -960,7 +960,7 @@ RenderResourceManager::CreateIndexBuffer(usize size, usize alignment, u32 *first
u32
RenderResourceManager::FetchIndex(IndexHandle handle)
{
return Cast<u32>(m_Index.FetchOffset(handle) / sizeof(u32));
return static_cast<u32>(m_Index.FetchOffset(handle) / sizeof(u32));
}
void

View File

@ -5,5 +5,5 @@ cmake_minimum_required(VERSION 3.13)
add_subdirectory("00_util")
add_subdirectory("01_triangle")
add_subdirectory("02_box")
add_subdirectory("03_model_render")
# add_subdirectory("03_model_render")
# add_subdirectory("04_scenes")

View File

@ -1,7 +1,7 @@
{
"default-registry": {
"kind": "git",
"baseline": "b27651341123a59f7187b42ef2bc476284afb310",
"baseline": "41c447cc210dc39aa85d4a5f58b4a1b9e573b3dc",
"repository": "https://github.com/microsoft/vcpkg"
},
"registries": [

View File

@ -15,6 +15,7 @@
"scottt-debugbreak",
"tinygltf",
"vulkan-memory-allocator",
"entt"
"entt",
"shader-slang"
]
}