Compare commits
10 Commits
a790c26f1c
...
3a7a2b4ab7
| Author | SHA1 | Date |
|---|---|---|
|
|
3a7a2b4ab7 | |
|
|
63282c3587 | |
|
|
7351415ebf | |
|
|
1db942f1a9 | |
|
|
3dc6501246 | |
|
|
5d6ddbb158 | |
|
|
7507394af9 | |
|
|
2facb3e6c1 | |
|
|
d683de3181 | |
|
|
d82e81d104 |
|
|
@ -5,3 +5,4 @@ build/
|
||||||
.direnv/
|
.direnv/
|
||||||
.ccls-cache/
|
.ccls-cache/
|
||||||
*.user
|
*.user
|
||||||
|
/vcpkg_installed
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
project(Aster VERSION 0.1.0)
|
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_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
if (MSVC)
|
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")
|
set(CMAKE_CXX_FLAGS_RELEASE "/O3")
|
||||||
add_compile_definitions(_HAS_EXCEPTIONS=0)
|
add_compile_definitions(_HAS_EXCEPTIONS=0)
|
||||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
function(add_shader TARGET SHADER)
|
function(add_shader TARGET SHADER)
|
||||||
find_package(Vulkan REQUIRED COMPONENTS dxc)
|
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-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-shader-path ${CMAKE_CURRENT_SOURCE_DIR}/${SHADER})
|
||||||
set(current-output-path ${CMAKE_CURRENT_BINARY_DIR}/${SHADER}.spv)
|
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")
|
if (Vulkan_dxc_exe_FOUND AND ${shader-ext} STREQUAL ".hlsl")
|
||||||
message("Marked as hlsl file. ${current-output-path}")
|
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(
|
add_custom_command(
|
||||||
OUTPUT ${current-output-path}
|
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}
|
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}
|
DEPENDS ${current-shader-path}
|
||||||
IMPLICIT_DEPENDS CXX ${current-shader-path}
|
IMPLICIT_DEPENDS CXX ${current-shader-path}
|
||||||
VERBATIM)
|
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 ()
|
endif ()
|
||||||
|
|
||||||
# Make sure our build depends on this output.
|
# Make sure our build depends on this output.
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,14 @@ find_package(Vulkan REQUIRED)
|
||||||
find_package(fmt CONFIG REQUIRED)
|
find_package(fmt CONFIG REQUIRED)
|
||||||
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
||||||
find_package(EASTL CONFIG REQUIRED)
|
find_package(EASTL CONFIG REQUIRED)
|
||||||
|
find_library(slang NAMES "slang" CONFIG REQUIRED)
|
||||||
|
|
||||||
add_library(aster_core STATIC)
|
add_library(aster_core STATIC)
|
||||||
|
|
||||||
add_subdirectory("include")
|
add_subdirectory("include")
|
||||||
add_subdirectory("src")
|
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 PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/aster")
|
||||||
target_include_directories(aster_core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
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 fmt::fmt)
|
||||||
target_link_libraries(aster_core PRIVATE EASTL)
|
target_link_libraries(aster_core PRIVATE EASTL)
|
||||||
target_link_libraries(aster_core PUBLIC Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
|
target_link_libraries(aster_core PUBLIC Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
|
||||||
|
target_link_libraries(aster_core PUBLIC ${slang})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ concept AnyBuffer = std::derived_from<T, Buffer>;
|
||||||
|
|
||||||
template <typename T, typename TInto>
|
template <typename T, typename TInto>
|
||||||
concept BufferInto = std::derived_from<T, Buffer> and std::derived_from<TInto, Buffer> and
|
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>
|
template <typename T>
|
||||||
concept AnyBufferRef = Deref<T> and AnyBuffer<DerefType<T>>;
|
concept AnyBufferRef = Deref<T> and AnyBuffer<DerefType<T>>;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
#define VULKAN_HPP_DISABLE_ENHANCED_MODE 1
|
#define VULKAN_HPP_DISABLE_ENHANCED_MODE 1
|
||||||
#define VULKAN_HPP_NO_EXCEPTIONS 1
|
#define VULKAN_HPP_NO_EXCEPTIONS 1
|
||||||
#define VULKAN_HPP_NO_SMART_HANDLE 1
|
#define VULKAN_HPP_NO_SMART_HANDLE 1
|
||||||
|
#define VULKAN_HPP_NO_STRUCT_SETTERS 1
|
||||||
|
|
||||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||||
|
|
|
||||||
|
|
@ -44,42 +44,28 @@ constexpr auto White = "\u001b[37m";
|
||||||
constexpr auto Reset = "\u001b[0m";
|
constexpr auto Reset = "\u001b[0m";
|
||||||
} // namespace ansi_color
|
} // 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
|
constexpr f32
|
||||||
operator""_deg(long double degrees)
|
operator""_deg(long double degrees)
|
||||||
{
|
{
|
||||||
return glm::radians<f32>(Cast<f32>(degrees));
|
return glm::radians<f32>(static_cast<f32>(degrees));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr f32
|
constexpr f32
|
||||||
operator""_deg(unsigned long long int degrees)
|
operator""_deg(unsigned long long int degrees)
|
||||||
{
|
{
|
||||||
return glm::radians<f32>(Cast<f32>(degrees));
|
return glm::radians<f32>(static_cast<f32>(degrees));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr f32
|
constexpr f32
|
||||||
operator""_rad(long double rads)
|
operator""_rad(long double rads)
|
||||||
{
|
{
|
||||||
return Cast<f32>(rads);
|
return static_cast<f32>(rads);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr f32
|
constexpr f32
|
||||||
operator""_rad(unsigned long long int rads)
|
operator""_rad(unsigned long long int rads)
|
||||||
{
|
{
|
||||||
return Cast<f32>(rads);
|
return static_cast<f32>(rads);
|
||||||
}
|
}
|
||||||
|
|
||||||
using glm::ivec2;
|
using glm::ivec2;
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,22 @@ struct Device final
|
||||||
|
|
||||||
void WaitIdle() const;
|
void WaitIdle() const;
|
||||||
|
|
||||||
|
vk::Device *
|
||||||
|
operator->()
|
||||||
|
{
|
||||||
|
return &m_Device;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vk::Device *
|
||||||
|
operator->() const
|
||||||
|
{
|
||||||
|
return &m_Device;
|
||||||
|
}
|
||||||
|
|
||||||
// Ctor/Dtor
|
// Ctor/Dtor
|
||||||
Device(const Instance *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
|
Device() = default;
|
||||||
const eastl::vector<QueueAllocation> &queueAllocations, NameString &&name);
|
Device(const Instance &context, PhysicalDevice &physicalDevice, Features &enabledFeatures,
|
||||||
Device(const Instance *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
|
const eastl::span<QueueAllocation> &queueAllocations, const eastl::span<u8> &pipelineCacheData,
|
||||||
const eastl::vector<QueueAllocation> &queueAllocations, eastl::span<u8> &&pipelineCacheData,
|
|
||||||
NameString &&name);
|
NameString &&name);
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
|
|
@ -61,7 +72,7 @@ Device::SetName(const T &object, cstr name) const
|
||||||
if (!m_ValidationEnabled || !name || !object)
|
if (!m_ValidationEnabled || !name || !object)
|
||||||
return;
|
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 = {
|
const vk::DebugUtilsObjectNameInfoEXT objectNameInfo = {
|
||||||
.objectType = object.objectType,
|
.objectType = object.objectType,
|
||||||
.objectHandle = handle,
|
.objectHandle = handle,
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,29 @@ constexpr u32 ASTER_API_VERSION = VK_API_VERSION_1_3;
|
||||||
#define TODO(MSG) assert(false && ("Unimplemented: " MSG))
|
#define TODO(MSG) assert(false && ("Unimplemented: " MSG))
|
||||||
#define FIX(MSG) static_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
|
[[nodiscard]] inline bool
|
||||||
Failed(const vk::Result result)
|
Failed(const vk::Result result)
|
||||||
{
|
{
|
||||||
|
|
@ -75,7 +98,7 @@ struct eastl::hash<vk::Flags<TFlagBits>> // NOLINT(*-dcl58-cpp)
|
||||||
[[nodiscard]] usize
|
[[nodiscard]] usize
|
||||||
operator()(const vk::Flags<TFlagBits> &val)
|
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
|
format(vk::Result result, format_context &ctx) const
|
||||||
{
|
{
|
||||||
return write_padded(ctx,
|
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
|
// ReSharper disable once CppInconsistentNaming
|
||||||
format(const eastl::fixed_string<TType, TCount, TOverflow> &str, format_context &ctx) const
|
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())); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,13 @@ ToExtent3D(const vk::Extent2D &extent, const u32 depth)
|
||||||
[[nodiscard]] inline vk::Offset2D
|
[[nodiscard]] inline vk::Offset2D
|
||||||
ToOffset2D(const vk::Extent3D &extent)
|
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
|
[[nodiscard]] inline vk::Offset3D
|
||||||
ToOffset3D(const vk::Extent3D &extent)
|
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
|
struct Image
|
||||||
|
|
@ -121,7 +121,7 @@ concept AnyImage = std::derived_from<T, Image>;
|
||||||
|
|
||||||
template <typename T, typename TInto>
|
template <typename T, typename TInto>
|
||||||
concept ImageInto = std::derived_from<T, Image> and std::derived_from<TInto, Image> and
|
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>
|
template <typename T>
|
||||||
concept AnyImageRef = Deref<T> and AnyImage<DerefType<T>>;
|
concept AnyImageRef = Deref<T> and AnyImage<DerefType<T>>;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ struct View
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
IsValid() const
|
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(Ref<Image> image, const vk::ImageView view, const vk::Extent3D extent, const u8 baseLayer, const u8 layerCount,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ struct Instance final
|
||||||
vk::DebugUtilsMessengerEXT m_DebugMessenger = nullptr;
|
vk::DebugUtilsMessengerEXT m_DebugMessenger = nullptr;
|
||||||
|
|
||||||
// Ctor/Dtor
|
// Ctor/Dtor
|
||||||
|
Instance() = default;
|
||||||
Instance(cstr appName, Version version, bool enableValidation = ENABLE_LAYER_MESSAGES_DEFAULT_VALUE);
|
Instance(cstr appName, Version version, bool enableValidation = ENABLE_LAYER_MESSAGES_DEFAULT_VALUE);
|
||||||
~Instance();
|
~Instance();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,5 +54,5 @@ struct PhysicalDevice final
|
||||||
class PhysicalDevices : public eastl::fixed_vector<PhysicalDevice, 4>
|
class PhysicalDevices : public eastl::fixed_vector<PhysicalDevice, 4>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PhysicalDevices(const Surface *surface, const Instance *context);
|
PhysicalDevices(const Surface &surface, const Instance &context);
|
||||||
};
|
};
|
||||||
|
|
@ -18,7 +18,30 @@ struct Pipeline
|
||||||
vk::Pipeline m_Pipeline;
|
vk::Pipeline m_Pipeline;
|
||||||
eastl::vector<vk::DescriptorSetLayout> m_SetLayouts;
|
eastl::vector<vk::DescriptorSetLayout> m_SetLayouts;
|
||||||
|
|
||||||
|
Pipeline() = default;
|
||||||
Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline,
|
Pipeline(const Device *device, vk::PipelineLayout layout, vk::Pipeline pipeline,
|
||||||
eastl::vector<vk::DescriptorSetLayout> &&setLayouts);
|
eastl::vector<vk::DescriptorSetLayout> &&setLayouts);
|
||||||
~Pipeline();
|
~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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -9,10 +9,33 @@
|
||||||
|
|
||||||
struct Size2D
|
struct Size2D
|
||||||
{
|
{
|
||||||
u32 m_Width;
|
u32 m_Width = 0;
|
||||||
u32 m_Height;
|
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
|
operator vk::Extent2D() const
|
||||||
{
|
{
|
||||||
return {m_Width, m_Height};
|
return {m_Width, m_Height};
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ struct Surface
|
||||||
NameString m_Name;
|
NameString m_Name;
|
||||||
|
|
||||||
// Ctor Dtor
|
// Ctor Dtor
|
||||||
Surface(Instance *context, const Window *window, cstr name);
|
Surface() = default;
|
||||||
|
Surface(Instance &context, const Window &window);
|
||||||
~Surface();
|
~Surface();
|
||||||
|
|
||||||
// Move
|
// Move
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ struct Swapchain final
|
||||||
|
|
||||||
const Device *m_Device;
|
const Device *m_Device;
|
||||||
vk::SwapchainKHR m_Swapchain;
|
vk::SwapchainKHR m_Swapchain;
|
||||||
NameString m_Name;
|
|
||||||
vk::Extent2D m_Extent;
|
vk::Extent2D m_Extent;
|
||||||
vk::Format m_Format;
|
vk::Format m_Format;
|
||||||
eastl::fixed_vector<vk::Image, 4> m_Images;
|
eastl::fixed_vector<vk::Image, 4> m_Images;
|
||||||
|
|
@ -29,11 +28,12 @@ struct Swapchain final
|
||||||
|
|
||||||
eastl::vector<FnResizeCallback> m_ResizeCallbacks;
|
eastl::vector<FnResizeCallback> m_ResizeCallbacks;
|
||||||
|
|
||||||
void Create(const Surface *window, Size2D size);
|
void Create(const Surface &surface, Size2D size);
|
||||||
void RegisterResizeCallback(FnResizeCallback &&callback);
|
void RegisterResizeCallback(FnResizeCallback &&callback);
|
||||||
|
|
||||||
// Ctor/Dtor
|
// 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();
|
~Swapchain();
|
||||||
|
|
||||||
// Move
|
// Move
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ struct Window final
|
||||||
|
|
||||||
static std::atomic_uint64_t m_WindowCount;
|
static std::atomic_uint64_t m_WindowCount;
|
||||||
static std::atomic_bool m_IsGlfwInit;
|
static std::atomic_bool m_IsGlfwInit;
|
||||||
|
static void SetupLibrary();
|
||||||
|
static cstr *GetInstanceExtensions(u32 *extensionCount);
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,6 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
target_sources(aster_core
|
target_sources(aster_core
|
||||||
INTERFACE
|
INTERFACE
|
||||||
"buffer_manager.h"
|
"device.h"
|
||||||
"image_manager.h"
|
|
||||||
"view_manager.h"
|
|
||||||
"sampler_manager.h"
|
|
||||||
"resource.h"
|
"resource.h"
|
||||||
"resource_manager.h"
|
|
||||||
"commit_manager.h")
|
"commit_manager.h")
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -7,19 +7,20 @@
|
||||||
|
|
||||||
#include "aster/aster.h"
|
#include "aster/aster.h"
|
||||||
|
|
||||||
#include "buffer_manager.h"
|
|
||||||
#include "sampler_manager.h"
|
|
||||||
#include "view_manager.h"
|
|
||||||
|
|
||||||
#include "aster/util/freelist.h"
|
#include "aster/util/freelist.h"
|
||||||
|
|
||||||
#include "EASTL/deque.h"
|
#include "EASTL/deque.h"
|
||||||
#include "EASTL/intrusive_hash_map.h"
|
#include "EASTL/intrusive_hash_map.h"
|
||||||
|
|
||||||
#include "resource.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
|
namespace systems
|
||||||
{
|
{
|
||||||
|
class Device;
|
||||||
|
|
||||||
class CommitManager
|
class CommitManager
|
||||||
{
|
{
|
||||||
|
|
@ -63,7 +64,7 @@ class CommitManager
|
||||||
Entry *
|
Entry *
|
||||||
Next()
|
Next()
|
||||||
{
|
{
|
||||||
return Recast<Entry *>(this->mpNext);
|
return reinterpret_cast<Entry *>(this->mpNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -174,7 +175,7 @@ class CommitManager
|
||||||
u32
|
u32
|
||||||
GetIndex(const Entry &entry)
|
GetIndex(const Entry &entry)
|
||||||
{
|
{
|
||||||
return Cast<u32>(&entry - m_Data.begin());
|
return static_cast<u32>(&entry - m_Data.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -286,6 +287,11 @@ class CommitManager
|
||||||
return *m_Instance;
|
return *m_Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsInit()
|
||||||
|
{
|
||||||
|
return static_cast<bool>(m_Instance);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vk::DescriptorPool m_DescriptorPool;
|
vk::DescriptorPool m_DescriptorPool;
|
||||||
vk::DescriptorSetLayout m_SetLayout;
|
vk::DescriptorSetLayout m_SetLayout;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -5,11 +5,63 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "aster/core/buffer.h"
|
||||||
|
#include "aster/core/image.h"
|
||||||
|
#include "aster/core/image_view.h"
|
||||||
|
|
||||||
#include <EASTL/intrusive_ptr.h>
|
#include <EASTL/intrusive_ptr.h>
|
||||||
|
|
||||||
namespace systems
|
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.
|
* ResId manages the lifetime of the committed resource.
|
||||||
* @tparam T Type of the committed resource.
|
* @tparam T Type of the committed resource.
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -5,4 +5,5 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
target_sources(aster_core
|
target_sources(aster_core
|
||||||
INTERFACE
|
INTERFACE
|
||||||
"logger.h"
|
"logger.h"
|
||||||
"freelist.h")
|
"freelist.h"
|
||||||
|
"files.h")
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -61,7 +61,7 @@ struct FreeList
|
||||||
Pop()
|
Pop()
|
||||||
{
|
{
|
||||||
assert(m_Top);
|
assert(m_Top);
|
||||||
Reference ref = *Recast<Pointer>(m_Top);
|
Reference ref = *reinterpret_cast<Pointer>(m_Top);
|
||||||
m_Top = m_Top->m_Next;
|
m_Top = m_Top->m_Next;
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ struct FreeList
|
||||||
void
|
void
|
||||||
Push(Reference ref)
|
Push(Reference ref)
|
||||||
{
|
{
|
||||||
auto next = Recast<FreeListNode *>(&ref);
|
auto next = reinterpret_cast<FreeListNode *>(&ref);
|
||||||
next->m_Next = m_Top;
|
next->m_Next = m_Top;
|
||||||
m_Top = next;
|
m_Top = next;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,12 @@ struct Logger
|
||||||
eVerbose,
|
eVerbose,
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 m_MinimumLoggingLevel{Cast<u32>(LogType::eDebug)};
|
u32 m_MinimumLoggingLevel{static_cast<u32>(LogType::eDebug)};
|
||||||
|
|
||||||
void
|
void
|
||||||
SetMinimumLoggingLevel(LogType logType)
|
SetMinimumLoggingLevel(LogType logType)
|
||||||
{
|
{
|
||||||
m_MinimumLoggingLevel = Cast<u32>(logType);
|
m_MinimumLoggingLevel = static_cast<u32>(logType);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <LogType TLogLevel>
|
template <LogType TLogLevel>
|
||||||
|
|
@ -64,7 +64,7 @@ struct Logger
|
||||||
void
|
void
|
||||||
Log(const std::string_view &message, const char *loc, u32 line) const
|
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(),
|
fmt::println("{}{} {} {} at {}:{}{}", ToColorCstr<TLogLevel>(), ToCstr<TLogLevel>(), message.data(),
|
||||||
ansi_color::Black, loc, line, ansi_color::Reset);
|
ansi_color::Black, loc, line, ansi_color::Reset);
|
||||||
|
|
@ -81,7 +81,7 @@ struct Logger
|
||||||
void
|
void
|
||||||
LogCond(const char *exprStr, const std::string_view &message, const char *loc, u32 line) const
|
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,
|
fmt::println("{}{} ({}) {} {} at {}:{}{}", ToColorCstr<TLogLevel>(), ToCstr<TLogLevel>(), exprStr,
|
||||||
message.data(), ansi_color::Black, loc, line, ansi_color::Reset);
|
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 INFO(...) g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#define ERROR_IF(expr, ...) \
|
#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__)
|
g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define WARN_IF(expr, ...) \
|
#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__)
|
g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define INFO_IF(expr, ...) \
|
#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__)
|
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#define ELSE_IF_ERROR(expr, ...) \
|
#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__)
|
[[unlikely]] g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_IF_WARN(expr, ...) \
|
#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__)
|
[[unlikely]] g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_IF_INFO(expr, ...) \
|
#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__)
|
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
|
|
||||||
#define ELSE_ERROR(...) \
|
#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(...) g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define DEBUG_IF(expr, ...) \
|
#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__)
|
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_IF_DEBUG(expr, ...) \
|
#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__)
|
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_DEBUG(...) \
|
#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(...) g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define VERBOSE_IF(expr, ...) \
|
#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__)
|
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_IF_VERBOSE(expr, ...) \
|
#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__)
|
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
|
||||||
#define ELSE_VERBOSE(...) \
|
#define ELSE_VERBOSE(...) \
|
||||||
; \
|
; \
|
||||||
|
|
@ -207,5 +207,5 @@ extern Logger g_Logger;
|
||||||
#endif // !defined(VERBOSE_LOG_DISABLED)
|
#endif // !defined(VERBOSE_LOG_DISABLED)
|
||||||
|
|
||||||
#define DO(code) , code
|
#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)
|
#define THEN_ABORT(code) , ABORT(code)
|
||||||
|
|
@ -27,7 +27,7 @@ Buffer::Buffer(const Device *device, const usize size, const vk::BufferUsageFlag
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
VmaAllocationInfo allocationInfo;
|
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));
|
&allocationCreateInfo, &buffer, &allocation, &allocationInfo));
|
||||||
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
|
ERROR_IF(Failed(result), "Could not allocate buffer. Cause: {}", result) THEN_ABORT(result);
|
||||||
|
|
||||||
|
|
@ -35,12 +35,12 @@ Buffer::Buffer(const Device *device, const usize size, const vk::BufferUsageFlag
|
||||||
// vmaGetAllocationMemoryProperties(device->m_Allocator, allocation, Recast<VkMemoryPropertyFlags
|
// vmaGetAllocationMemoryProperties(device->m_Allocator, allocation, Recast<VkMemoryPropertyFlags
|
||||||
// *>(&memoryPropertyFlags));
|
// *>(&memoryPropertyFlags));
|
||||||
// TODO: Actually track Host Access
|
// 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_Buffer = buffer;
|
||||||
m_Size = size;
|
m_Size = size;
|
||||||
m_Allocation = allocation;
|
m_Allocation = allocation;
|
||||||
m_Mapped = Cast<u8 *>(allocationInfo.pMappedData);
|
m_Mapped = static_cast<u8 *>(allocationInfo.pMappedData);
|
||||||
m_Flags = {};
|
m_Flags = {};
|
||||||
if (bufferUsage & vk::BufferUsageFlagBits::eTransferSrc)
|
if (bufferUsage & vk::BufferUsageFlagBits::eTransferSrc)
|
||||||
m_Flags |= FlagBits::eStaging;
|
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);
|
memcpy(m_Mapped + offset, data, size);
|
||||||
|
|
||||||
// TODO: Debug this.
|
// TODO: Debug this.
|
||||||
// auto result = Cast<vk::Result>(vmaCopyMemoryToAllocation(device->m_Allocator, &data, m_Allocation, 0, size));
|
// auto result = 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);
|
// ERROR_IF(Failed(result), "Writing to buffer failed. Cause: {}", result) THEN_ABORT(result);
|
||||||
}
|
}
|
||||||
|
|
@ -17,18 +17,12 @@ constexpr eastl::array DEVICE_EXTENSIONS = {
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features *enabledFeatures,
|
Device::Device(const Instance &context, PhysicalDevice &physicalDevice, Features &enabledFeatures,
|
||||||
const eastl::vector<QueueAllocation> &queueAllocations, NameString &&name)
|
const eastl::span<QueueAllocation> &queueAllocations, const eastl::span<u8> &pipelineCacheData,
|
||||||
: 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,
|
|
||||||
NameString &&name)
|
NameString &&name)
|
||||||
: m_Name(std::move(name))
|
: m_Name(std::move(name))
|
||||||
, m_PhysicalDevice(physicalDevice->m_PhysicalDevice)
|
, m_PhysicalDevice(physicalDevice.m_PhysicalDevice)
|
||||||
, m_ValidationEnabled(context->m_DebugMessenger != nullptr)
|
, m_ValidationEnabled(context.m_DebugMessenger != nullptr)
|
||||||
{
|
{
|
||||||
// Shouldn't have more than 4 deviceQueueFamilies in use anyway. Else we can heap
|
// Shouldn't have more than 4 deviceQueueFamilies in use anyway. Else we can heap
|
||||||
eastl::fixed_vector<vk::DeviceQueueCreateInfo, 4> deviceQueueCreateInfos;
|
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::PhysicalDeviceFeatures *deviceFeatures = &enabledFeatures.m_Vulkan10Features;
|
||||||
vk::PhysicalDeviceVulkan11Features *vulkan11Features = &enabledFeatures->m_Vulkan11Features;
|
vk::PhysicalDeviceVulkan11Features *vulkan11Features = &enabledFeatures.m_Vulkan11Features;
|
||||||
vk::PhysicalDeviceVulkan12Features *vulkan12Features = &enabledFeatures->m_Vulkan12Features;
|
vk::PhysicalDeviceVulkan12Features *vulkan12Features = &enabledFeatures.m_Vulkan12Features;
|
||||||
vk::PhysicalDeviceVulkan13Features *vulkan13Features = &enabledFeatures->m_Vulkan13Features;
|
vk::PhysicalDeviceVulkan13Features *vulkan13Features = &enabledFeatures.m_Vulkan13Features;
|
||||||
|
|
||||||
vulkan11Features->pNext = vulkan12Features;
|
vulkan11Features->pNext = vulkan12Features;
|
||||||
vulkan12Features->pNext = vulkan13Features;
|
vulkan12Features->pNext = vulkan13Features;
|
||||||
|
|
||||||
vk::DeviceCreateInfo deviceCreateInfo = {
|
vk::DeviceCreateInfo deviceCreateInfo = {
|
||||||
.pNext = vulkan11Features,
|
.pNext = vulkan11Features,
|
||||||
.queueCreateInfoCount = Cast<u32>(deviceQueueCreateInfos.size()),
|
.queueCreateInfoCount = static_cast<u32>(deviceQueueCreateInfos.size()),
|
||||||
.pQueueCreateInfos = deviceQueueCreateInfos.data(),
|
.pQueueCreateInfos = deviceQueueCreateInfos.data(),
|
||||||
.enabledExtensionCount = Cast<u32>(DEVICE_EXTENSIONS.size()),
|
.enabledExtensionCount = static_cast<u32>(DEVICE_EXTENSIONS.size()),
|
||||||
.ppEnabledExtensionNames = DEVICE_EXTENSIONS.data(),
|
.ppEnabledExtensionNames = DEVICE_EXTENSIONS.data(),
|
||||||
.pEnabledFeatures = deviceFeatures,
|
.pEnabledFeatures = deviceFeatures,
|
||||||
};
|
};
|
||||||
|
|
@ -71,13 +65,13 @@ Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features
|
||||||
vk::Result result = m_PhysicalDevice.createDevice(&deviceCreateInfo, nullptr, &m_Device);
|
vk::Result result = m_PhysicalDevice.createDevice(&deviceCreateInfo, nullptr, &m_Device);
|
||||||
ERROR_IF(Failed(result), "Could not initialize Vulkan Device. Cause: {}", result)
|
ERROR_IF(Failed(result), "Could not initialize Vulkan Device. Cause: {}", result)
|
||||||
THEN_ABORT(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());
|
SetName(m_Device, m_Name.data());
|
||||||
|
|
||||||
VmaVulkanFunctions vmaVulkanFunctions = {
|
VmaVulkanFunctions vmaVulkanFunctions = {
|
||||||
.vkGetInstanceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
|
.vkGetInstanceProcAddr = vk::detail::defaultDispatchLoaderDynamic.vkGetInstanceProcAddr,
|
||||||
.vkGetDeviceProcAddr = vk::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
|
.vkGetDeviceProcAddr = vk::detail::defaultDispatchLoaderDynamic.vkGetDeviceProcAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
const VmaAllocatorCreateInfo allocatorCreateInfo = {
|
const VmaAllocatorCreateInfo allocatorCreateInfo = {
|
||||||
|
|
@ -85,11 +79,11 @@ Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features
|
||||||
.physicalDevice = m_PhysicalDevice,
|
.physicalDevice = m_PhysicalDevice,
|
||||||
.device = m_Device,
|
.device = m_Device,
|
||||||
.pVulkanFunctions = &vmaVulkanFunctions,
|
.pVulkanFunctions = &vmaVulkanFunctions,
|
||||||
.instance = context->m_Instance,
|
.instance = context.m_Instance,
|
||||||
.vulkanApiVersion = ASTER_API_VERSION,
|
.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)
|
ERROR_IF(Failed(result), "Memory allocator creation failed. Cause: {}", result)
|
||||||
DO(m_Device.destroy(nullptr))
|
DO(m_Device.destroy(nullptr))
|
||||||
THEN_ABORT(result)
|
THEN_ABORT(result)
|
||||||
|
|
@ -110,6 +104,9 @@ Device::Device(const Instance *context, PhysicalDevice *physicalDevice, Features
|
||||||
|
|
||||||
Device::~Device()
|
Device::~Device()
|
||||||
{
|
{
|
||||||
|
if (!m_Device)
|
||||||
|
return;
|
||||||
|
|
||||||
m_Device.destroy(m_PipelineCache, nullptr);
|
m_Device.destroy(m_PipelineCache, nullptr);
|
||||||
if (m_Allocator)
|
if (m_Allocator)
|
||||||
{
|
{
|
||||||
|
|
@ -156,6 +153,7 @@ Device::Device(Device &&other) noexcept
|
||||||
, m_PhysicalDevice(Take(other.m_PhysicalDevice))
|
, m_PhysicalDevice(Take(other.m_PhysicalDevice))
|
||||||
, m_Device(Take(other.m_Device))
|
, m_Device(Take(other.m_Device))
|
||||||
, m_Allocator(Take(other.m_Allocator))
|
, 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_PhysicalDevice = Take(other.m_PhysicalDevice);
|
||||||
m_Device = Take(other.m_Device);
|
m_Device = Take(other.m_Device);
|
||||||
m_Allocator = Take(other.m_Allocator);
|
m_Allocator = Take(other.m_Allocator);
|
||||||
|
m_PipelineCache = Take(other.m_PipelineCache);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ struct MemorySize
|
||||||
m_Kilobytes = totalKb % 1024;
|
m_Kilobytes = totalKb % 1024;
|
||||||
const usize totalMb = m_Megabytes + totalKb / 1024;
|
const usize totalMb = m_Megabytes + totalKb / 1024;
|
||||||
m_Megabytes = totalMb % 1024;
|
m_Megabytes = totalMb % 1024;
|
||||||
m_Gigabytes += Cast<u16>(totalMb / 1024);
|
m_Gigabytes += static_cast<u16>(totalMb / 1024);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -56,18 +56,18 @@ struct fmt::formatter<MemorySize>
|
||||||
// return format_to(ctx.out(), "({}, {})", foo.a, foo.b); // --== KEY LINE ==--
|
// return format_to(ctx.out(), "({}, {})", foo.a, foo.b); // --== KEY LINE ==--
|
||||||
if (mem.m_Gigabytes > 0)
|
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)
|
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)
|
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)",
|
// WARN_IF(!IsPowerOfTwo(extent.width) || !IsPowerOfTwo(extent.width), "Image {2} is {0}x{1} (Non Power of Two)",
|
||||||
// extent.width, extent.height, name ? name : "<unnamed>");
|
// extent.width, extent.height, name ? name : "<unnamed>");
|
||||||
//
|
//
|
||||||
// const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
|
// const u8 mipLevels = isMipMapped ? 1 + static_cast<u8>(floor(log2(eastl::max(extent.width, extent.height)))) : 1;
|
||||||
//
|
//
|
||||||
// auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
|
// auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
|
||||||
// if (isMipMapped)
|
// if (isMipMapped)
|
||||||
|
|
@ -75,7 +75,7 @@ Image::DestroyView(const vk::ImageView imageView) const
|
||||||
//
|
//
|
||||||
// VkImage image;
|
// VkImage image;
|
||||||
// VmaAllocation allocation;
|
// 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));
|
// &allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
||||||
//
|
//
|
||||||
|
|
@ -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,
|
// WARN_IF(!IsPowerOfTwo(cubeSide), "Image Cube {1} has side {0}x{0} (Non Power of Two)", cubeSide,
|
||||||
// name ? name : "<unnamed>");
|
// name ? name : "<unnamed>");
|
||||||
//
|
//
|
||||||
// const u8 mipLevels = isMipMapped ? 1 + Cast<u8>(floor(log2(cubeSide))) : 1;
|
// const u8 mipLevels = isMipMapped ? 1 + static_cast<u8>(floor(log2(cubeSide))) : 1;
|
||||||
//
|
//
|
||||||
// auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
|
// auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst;
|
||||||
// if (isMipMapped)
|
// if (isMipMapped)
|
||||||
|
|
@ -162,7 +162,7 @@ Image::DestroyView(const vk::ImageView imageView) const
|
||||||
//
|
//
|
||||||
// VkImage image;
|
// VkImage image;
|
||||||
// VmaAllocation allocation;
|
// 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));
|
// &allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
||||||
//
|
//
|
||||||
|
|
@ -217,7 +217,7 @@ Image::DestroyView(const vk::ImageView imageView) const
|
||||||
//
|
//
|
||||||
// VkImage image;
|
// VkImage image;
|
||||||
// VmaAllocation allocation;
|
// 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));
|
// &allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
// ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result);
|
// ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result);
|
||||||
//
|
//
|
||||||
|
|
@ -274,7 +274,7 @@ Image::DestroyView(const vk::ImageView imageView) const
|
||||||
//
|
//
|
||||||
// VkImage image;
|
// VkImage image;
|
||||||
// VmaAllocation allocation;
|
// 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));
|
// &allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
// ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result);
|
// ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result);
|
||||||
//
|
//
|
||||||
|
|
@ -344,7 +344,7 @@ Image::DestroyView(const vk::ImageView imageView) const
|
||||||
//
|
//
|
||||||
// VkImage image;
|
// VkImage image;
|
||||||
// VmaAllocation allocation;
|
// 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));
|
// &allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
||||||
//
|
//
|
||||||
|
|
@ -395,7 +395,7 @@ Image::DestroyView(const vk::ImageView imageView) const
|
||||||
// usage |= vk::ImageUsageFlagBits::eSampled;
|
// 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 = {
|
// vk::ImageCreateInfo imageCreateInfo = {
|
||||||
// .flags = vk::ImageCreateFlagBits::eCubeCompatible,
|
// .flags = vk::ImageCreateFlagBits::eCubeCompatible,
|
||||||
|
|
@ -417,7 +417,7 @@ Image::DestroyView(const vk::ImageView imageView) const
|
||||||
//
|
//
|
||||||
// VkImage image;
|
// VkImage image;
|
||||||
// VmaAllocation allocation;
|
// 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));
|
// &allocationCreateInfo, &image, &allocation, nullptr));
|
||||||
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
// ERROR_IF(Failed(result), "Could not allocate image {}. Cause: {}", name, result) THEN_ABORT(result);
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -5,30 +5,28 @@
|
||||||
|
|
||||||
#include "core/instance.h"
|
#include "core/instance.h"
|
||||||
|
|
||||||
|
#include "core/window.h"
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
#include <EASTL/fixed_vector.h>
|
#include <EASTL/fixed_vector.h>
|
||||||
|
|
||||||
VKAPI_ATTR b32 VKAPI_CALL
|
VKAPI_ATTR b32 VKAPI_CALL
|
||||||
DebugCallback(const VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
DebugCallback(const vk::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||||
const VkDebugUtilsMessageTypeFlagsEXT messageType,
|
const vk::DebugUtilsMessageTypeFlagsEXT messageType,
|
||||||
const VkDebugUtilsMessengerCallbackDataEXT *callbackData, [[maybe_unused]] void *userData)
|
const vk::DebugUtilsMessengerCallbackDataEXT *callbackData, [[maybe_unused]] void *userData)
|
||||||
{
|
{
|
||||||
using Severity = vk::DebugUtilsMessageSeverityFlagsEXT;
|
|
||||||
using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT;
|
using SeverityBits = vk::DebugUtilsMessageSeverityFlagBitsEXT;
|
||||||
using MessageType = vk::DebugUtilsMessageTypeFlagsEXT;
|
|
||||||
using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT;
|
using MessageTypeBits = vk::DebugUtilsMessageTypeFlagBitsEXT;
|
||||||
|
|
||||||
const auto severity = Severity(messageSeverity);
|
if (messageType & MessageTypeBits::eValidation)
|
||||||
|
|
||||||
if (MessageType(messageType) & MessageTypeBits::eValidation)
|
|
||||||
{
|
{
|
||||||
if (severity & SeverityBits::eError)
|
if (messageSeverity & SeverityBits::eError)
|
||||||
ERROR("{}", callbackData->pMessage);
|
ERROR("{}", callbackData->pMessage);
|
||||||
if (severity & SeverityBits::eWarning)
|
if (messageSeverity & SeverityBits::eWarning)
|
||||||
WARN("{}", callbackData->pMessage);
|
WARN("{}", callbackData->pMessage);
|
||||||
if (severity & SeverityBits::eInfo)
|
if (messageSeverity & SeverityBits::eInfo)
|
||||||
INFO("{}", callbackData->pMessage);
|
INFO("{}", callbackData->pMessage);
|
||||||
if (severity & SeverityBits::eVerbose)
|
if (messageSeverity & SeverityBits::eVerbose)
|
||||||
VERBOSE("{}", callbackData->pMessage);
|
VERBOSE("{}", callbackData->pMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,15 +59,15 @@ Instance::Instance(const cstr appName, const Version version, bool enableValidat
|
||||||
.pUserData = nullptr,
|
.pUserData = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 glfwExtensionCount = 0;
|
u32 windowExtensionCount = 0;
|
||||||
cstr *glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
cstr *windowExtensions = Window::GetInstanceExtensions(&windowExtensionCount);
|
||||||
eastl::fixed_vector<cstr, 3> instanceExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
|
eastl::fixed_vector<cstr, 3> instanceExtensions(windowExtensions, windowExtensions + windowExtensionCount);
|
||||||
if (enableValidation)
|
if (enableValidation)
|
||||||
{
|
{
|
||||||
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::DynamicLoader dl;
|
const vk::detail::DynamicLoader dl;
|
||||||
// ReSharper disable once CppInconsistentNaming
|
// ReSharper disable once CppInconsistentNaming
|
||||||
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
const auto vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
|
||||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(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{
|
const auto instanceCreateInfo = vk::InstanceCreateInfo{
|
||||||
.pNext = enableValidation ? &debugUtilsMessengerCreateInfo : nullptr,
|
.pNext = enableValidation ? &debugUtilsMessengerCreateInfo : nullptr,
|
||||||
.pApplicationInfo = &appInfo,
|
.pApplicationInfo = &appInfo,
|
||||||
.enabledExtensionCount = Cast<u32>(instanceExtensions.size()),
|
.enabledExtensionCount = static_cast<u32>(instanceExtensions.size()),
|
||||||
.ppEnabledExtensionNames = instanceExtensions.data(),
|
.ppEnabledExtensionNames = instanceExtensions.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -99,6 +97,9 @@ Instance::Instance(const cstr appName, const Version version, bool enableValidat
|
||||||
|
|
||||||
Instance::~Instance()
|
Instance::~Instance()
|
||||||
{
|
{
|
||||||
|
if (!m_Instance)
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_DebugMessenger)
|
if (m_DebugMessenger)
|
||||||
{
|
{
|
||||||
m_Instance.destroy(m_DebugMessenger, nullptr);
|
m_Instance.destroy(m_DebugMessenger, nullptr);
|
||||||
|
|
|
||||||
|
|
@ -154,11 +154,10 @@ EnumeratePhysicalDevices(const vk::Instance instance)
|
||||||
return physicalDevices;
|
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 physicalDevices = EnumeratePhysicalDevices(context.m_Instance); auto physicalDevice : physicalDevices)
|
||||||
for (auto physicalDevice : physicalDevices)
|
|
||||||
{
|
{
|
||||||
this->emplace_back(surface->m_Surface, physicalDevice);
|
this->emplace_back(surface.m_Surface, physicalDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,13 +8,12 @@
|
||||||
#include "core/instance.h"
|
#include "core/instance.h"
|
||||||
#include "core/window.h"
|
#include "core/window.h"
|
||||||
|
|
||||||
Surface::Surface(Instance *context, const Window *window, cstr name)
|
Surface::Surface(Instance &context, const Window &window)
|
||||||
: m_Context(context)
|
: m_Context(&context)
|
||||||
, m_Name(name)
|
|
||||||
{
|
{
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
auto result = Cast<vk::Result>(
|
auto result = static_cast<vk::Result>(
|
||||||
glfwCreateWindowSurface(Cast<VkInstance>(m_Context->m_Instance), window->m_Window, nullptr, &surface));
|
glfwCreateWindowSurface(static_cast<VkInstance>(m_Context->m_Instance), window.m_Window, nullptr, &surface));
|
||||||
ERROR_IF(Failed(result), "Failed to create Surface with {}", result)
|
ERROR_IF(Failed(result), "Failed to create Surface with {}", result)
|
||||||
THEN_ABORT(result)
|
THEN_ABORT(result)
|
||||||
ELSE_DEBUG("Surface {} Created", m_Name);
|
ELSE_DEBUG("Surface {} Created", m_Name);
|
||||||
|
|
@ -23,14 +22,14 @@ Surface::Surface(Instance *context, const Window *window, cstr name)
|
||||||
|
|
||||||
Surface::~Surface()
|
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->m_Instance.destroy(m_Surface, nullptr);
|
||||||
m_Context = nullptr;
|
DEBUG("Surface Destroyed");
|
||||||
}
|
|
||||||
|
m_Surface = nullptr;
|
||||||
|
m_Context = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface::Surface(Surface &&other) noexcept
|
Surface::Surface(Surface &&other) noexcept
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,8 @@
|
||||||
|
|
||||||
[[nodiscard]] vk::Extent2D GetExtent(Size2D size, vk::SurfaceCapabilitiesKHR *surfaceCapabilities);
|
[[nodiscard]] vk::Extent2D GetExtent(Size2D size, vk::SurfaceCapabilitiesKHR *surfaceCapabilities);
|
||||||
|
|
||||||
Swapchain::Swapchain(const Surface *surface, const Device *device, Size2D size, NameString &&name)
|
Swapchain::Swapchain(const Surface &surface, const Device &device, Size2D size)
|
||||||
: m_Device(device)
|
: m_Device(&device)
|
||||||
, m_Name(std::move(name))
|
|
||||||
, m_Format(vk::Format::eUndefined)
|
, m_Format(vk::Format::eUndefined)
|
||||||
{
|
{
|
||||||
this->Create(surface, size);
|
this->Create(surface, size);
|
||||||
|
|
@ -27,11 +26,11 @@ Swapchain::~Swapchain()
|
||||||
Swapchain::Swapchain(Swapchain &&other) noexcept
|
Swapchain::Swapchain(Swapchain &&other) noexcept
|
||||||
: m_Device(other.m_Device)
|
: m_Device(other.m_Device)
|
||||||
, m_Swapchain(Take(other.m_Swapchain))
|
, m_Swapchain(Take(other.m_Swapchain))
|
||||||
, m_Name(std::move(other.m_Name))
|
|
||||||
, m_Extent(other.m_Extent)
|
, m_Extent(other.m_Extent)
|
||||||
, m_Format(other.m_Format)
|
, m_Format(other.m_Format)
|
||||||
, m_Images(std::move(other.m_Images))
|
, m_Images(std::move(other.m_Images))
|
||||||
, m_ImageViews(std::move(other.m_ImageViews))
|
, 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;
|
return *this;
|
||||||
m_Device = other.m_Device;
|
m_Device = other.m_Device;
|
||||||
m_Swapchain = Take(other.m_Swapchain);
|
m_Swapchain = Take(other.m_Swapchain);
|
||||||
m_Name = std::move(other.m_Name);
|
|
||||||
m_Extent = other.m_Extent;
|
m_Extent = other.m_Extent;
|
||||||
m_Format = other.m_Format;
|
m_Format = other.m_Format;
|
||||||
m_Images = std::move(other.m_Images);
|
m_Images = std::move(other.m_Images);
|
||||||
m_ImageViews = std::move(other.m_ImageViews);
|
m_ImageViews = std::move(other.m_ImageViews);
|
||||||
|
m_ResizeCallbacks = std::move(other.m_ResizeCallbacks);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
m_Extent = GetExtent(size, &surfaceCapabilities);
|
||||||
|
|
||||||
while (m_Extent.width == 0 || m_Extent.height == 0)
|
while (m_Extent.width == 0 || m_Extent.height == 0)
|
||||||
{
|
{
|
||||||
glfwWaitEvents();
|
glfwWaitEvents();
|
||||||
surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, surface->m_Surface);
|
surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, surface.m_Surface);
|
||||||
m_Extent = GetExtent(size, &surfaceCapabilities);
|
m_Extent = GetExtent(size, &surfaceCapabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto surfaceFormats = GetSurfaceFormats(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);
|
auto presentModes = GetSurfacePresentModes(m_Device->m_PhysicalDevice, surface.m_Surface);
|
||||||
|
|
||||||
m_Format = vk::Format::eUndefined;
|
m_Format = vk::Format::eUndefined;
|
||||||
auto swapchainColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
|
auto swapchainColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
|
||||||
|
|
@ -95,16 +94,14 @@ Swapchain::Create(const Surface *surface, Size2D size)
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 swapchainImageCount = 3;
|
u32 swapchainImageCount = 3;
|
||||||
if (surfaceCapabilities.maxImageCount > 0)
|
u32 maxImageCount =
|
||||||
{
|
glm::max(swapchainImageCount, glm::max(surfaceCapabilities.maxImageCount, surfaceCapabilities.minImageCount));
|
||||||
swapchainImageCount =
|
swapchainImageCount = glm::clamp(swapchainImageCount, surfaceCapabilities.minImageCount, maxImageCount);
|
||||||
glm::clamp(swapchainImageCount, surfaceCapabilities.minImageCount, surfaceCapabilities.maxImageCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Note that different queues might need the images to be shared.
|
// TODO: Note that different queues might need the images to be shared.
|
||||||
|
|
||||||
const vk::SwapchainCreateInfoKHR swapchainCreateInfo = {
|
const vk::SwapchainCreateInfoKHR swapchainCreateInfo = {
|
||||||
.surface = surface->m_Surface,
|
.surface = surface.m_Surface,
|
||||||
.minImageCount = swapchainImageCount,
|
.minImageCount = swapchainImageCount,
|
||||||
.imageFormat = m_Format,
|
.imageFormat = m_Format,
|
||||||
.imageColorSpace = swapchainColorSpace,
|
.imageColorSpace = swapchainColorSpace,
|
||||||
|
|
@ -120,28 +117,30 @@ Swapchain::Create(const Surface *surface, Size2D size)
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::Device device = m_Device->m_Device;
|
vk::Device device = m_Device->m_Device;
|
||||||
|
NameString name = "Swapchain of ";
|
||||||
|
name += m_Device->m_Name;
|
||||||
|
|
||||||
vk::SwapchainKHR swapchain;
|
vk::SwapchainKHR swapchain;
|
||||||
vk::Result result = device.createSwapchainKHR(&swapchainCreateInfo, nullptr, &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)
|
THEN_ABORT(result)
|
||||||
ELSE_DEBUG("Created Swapchain '{}'", m_Name);
|
ELSE_DEBUG("Created '{}'", name);
|
||||||
|
|
||||||
// Irrelevant on the first run. Required for re-creation.
|
// Irrelevant on the first run. Required for re-creation.
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
|
||||||
m_Swapchain = swapchain;
|
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);
|
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);
|
THEN_ABORT(result);
|
||||||
|
|
||||||
// Managed by the Swapchain.
|
// Managed by the Swapchain.
|
||||||
m_Images.resize(swapchainImageCount);
|
m_Images.resize(swapchainImageCount, nullptr);
|
||||||
result = device.getSwapchainImagesKHR(m_Swapchain, &swapchainImageCount, m_Images.data());
|
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);
|
THEN_ABORT(result);
|
||||||
|
|
||||||
vk::ImageViewCreateInfo viewCreateInfo = {
|
vk::ImageViewCreateInfo viewCreateInfo = {
|
||||||
|
|
@ -165,7 +164,7 @@ Swapchain::Create(const Surface *surface, Size2D size)
|
||||||
|
|
||||||
vk::ImageView imageView;
|
vk::ImageView imageView;
|
||||||
result = device.createImageView(&viewCreateInfo, nullptr, &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);
|
THEN_ABORT(result);
|
||||||
|
|
||||||
m_ImageViews.push_back(imageView);
|
m_ImageViews.push_back(imageView);
|
||||||
|
|
@ -173,7 +172,7 @@ Swapchain::Create(const Surface *surface, Size2D size)
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG("Swapchain {} Image Views created.", m_Name);
|
DEBUG("{} Image Views created.", name);
|
||||||
|
|
||||||
for (auto &callback : m_ResizeCallbacks)
|
for (auto &callback : m_ResizeCallbacks)
|
||||||
{
|
{
|
||||||
|
|
@ -184,24 +183,31 @@ Swapchain::Create(const Surface *surface, Size2D size)
|
||||||
void
|
void
|
||||||
Swapchain::RegisterResizeCallback(FnResizeCallback &&callback)
|
Swapchain::RegisterResizeCallback(FnResizeCallback &&callback)
|
||||||
{
|
{
|
||||||
m_ResizeCallbacks.emplace_back(callback);
|
m_ResizeCallbacks.emplace_back(std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Swapchain::Cleanup()
|
Swapchain::Cleanup()
|
||||||
{
|
{
|
||||||
if (!m_ImageViews.empty()) // Don't want the condition in the logs.
|
if (!m_Swapchain)
|
||||||
DEBUG("Swapchain {} Image Views destroyed.", m_Name);
|
return;
|
||||||
|
|
||||||
|
NameString name = "Swapchain of ";
|
||||||
|
name += m_Device->m_Name;
|
||||||
|
|
||||||
for (const auto imageView : m_ImageViews)
|
for (const auto imageView : m_ImageViews)
|
||||||
{
|
{
|
||||||
m_Device->m_Device.destroy(imageView, nullptr);
|
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_ImageViews.clear();
|
||||||
|
m_Images.clear();
|
||||||
if (m_Swapchain)
|
if (m_Swapchain)
|
||||||
{
|
{
|
||||||
m_Device->m_Device.destroy(m_Swapchain, nullptr);
|
m_Device->m_Device.destroy(m_Swapchain, nullptr);
|
||||||
m_Swapchain = nullptr;
|
m_Swapchain = nullptr;
|
||||||
DEBUG("Swapchain '{}' destroyed.", m_Name);
|
DEBUG("Swapchain '{}' destroyed.", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,30 @@
|
||||||
std::atomic_uint64_t Window::m_WindowCount = 0;
|
std::atomic_uint64_t Window::m_WindowCount = 0;
|
||||||
std::atomic_bool Window::m_IsGlfwInit = false;
|
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
|
void
|
||||||
Window::RequestExit() const noexcept
|
Window::RequestExit() const noexcept
|
||||||
{
|
{
|
||||||
|
|
@ -26,7 +50,7 @@ Window::SetWindowSize(const vk::Extent2D &extent) const noexcept
|
||||||
void
|
void
|
||||||
Window::SetWindowSize(const u32 width, const u32 height) const noexcept
|
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
|
Size2D
|
||||||
|
|
@ -35,25 +59,14 @@ Window::GetSize() const
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
glfwGetFramebufferSize(m_Window, &width, &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)
|
Window::Window(const cstr title, Size2D extent, const b8 isFullScreen)
|
||||||
{
|
{
|
||||||
m_Name = title;
|
m_Name = title;
|
||||||
|
|
||||||
if (!m_IsGlfwInit)
|
SetupLibrary();
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||||
ERROR_IF(!monitor, "No monitor found");
|
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_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE);
|
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);
|
isFullScreen ? monitor : nullptr, nullptr);
|
||||||
ERROR_IF(m_Window == nullptr, "Window creation failed")
|
ERROR_IF(m_Window == nullptr, "Window creation failed")
|
||||||
ELSE_DEBUG("Window '{}' created with resolution '{}x{}'", m_Name, extent.m_Width, extent.m_Height);
|
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)
|
if (isFullScreen == false)
|
||||||
{
|
{
|
||||||
glfwSetWindowPos(m_Window, Cast<i32>(windowWidth - extent.m_Width) / 2,
|
glfwSetWindowPos(m_Window, static_cast<i32>(windowWidth - extent.m_Width) / 2,
|
||||||
Cast<i32>(windowHeight - extent.m_Height) / 2);
|
static_cast<i32>(windowHeight - extent.m_Height) / 2);
|
||||||
}
|
}
|
||||||
glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
target_sources(aster_core
|
target_sources(aster_core
|
||||||
PRIVATE
|
PRIVATE
|
||||||
"buffer_manager.cpp"
|
"device.cpp"
|
||||||
"image_manager.cpp"
|
"commit_manager.cpp"
|
||||||
"view_manager.cpp"
|
"sync_server.cpp")
|
||||||
"sampler_manager.cpp"
|
|
||||||
"commit_manager.cpp")
|
|
||||||
|
|
|
||||||
|
|
@ -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}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -8,29 +8,7 @@
|
||||||
#include "EASTL/array.h"
|
#include "EASTL/array.h"
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
#include "core/image_view.h"
|
#include "core/image_view.h"
|
||||||
|
#include "systems/device.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)
|
|
||||||
|
|
||||||
using namespace systems;
|
using namespace systems;
|
||||||
|
|
||||||
|
|
@ -64,28 +42,28 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
|
||||||
const vk::DescriptorPoolCreateInfo poolCreateInfo = {
|
const vk::DescriptorPoolCreateInfo poolCreateInfo = {
|
||||||
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
|
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
|
||||||
.maxSets = 1,
|
.maxSets = 1,
|
||||||
.poolSizeCount = Cast<u32>(poolSizes.size()),
|
.poolSizeCount = static_cast<u32>(poolSizes.size()),
|
||||||
.pPoolSizes = poolSizes.data(),
|
.pPoolSizes = poolSizes.data(),
|
||||||
};
|
};
|
||||||
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
AbortIfFailed(device->m_Device->createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
||||||
|
|
||||||
eastl::array descriptorLayoutBindings = {
|
eastl::array descriptorLayoutBindings = {
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = BUFFER_BINDING_INDEX,
|
.binding = BUFFER_BINDING_INDEX,
|
||||||
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||||
.descriptorCount = Cast<u32>(maxBuffers),
|
.descriptorCount = static_cast<u32>(maxBuffers),
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
},
|
},
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = IMAGE_BINDING_INDEX,
|
.binding = IMAGE_BINDING_INDEX,
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
.descriptorCount = Cast<u32>(maxImages),
|
.descriptorCount = static_cast<u32>(maxImages),
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
},
|
},
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = STORAGE_IMAGE_BINDING_INDEX,
|
.binding = STORAGE_IMAGE_BINDING_INDEX,
|
||||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||||
.descriptorCount = Cast<u32>(maxStorageImages),
|
.descriptorCount = static_cast<u32>(maxStorageImages),
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -93,11 +71,11 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
|
||||||
vk::DescriptorBindingFlags bindingFlags =
|
vk::DescriptorBindingFlags bindingFlags =
|
||||||
vk::DescriptorBindingFlagBits::ePartiallyBound | vk::DescriptorBindingFlagBits::eUpdateAfterBind;
|
vk::DescriptorBindingFlagBits::ePartiallyBound | vk::DescriptorBindingFlagBits::eUpdateAfterBind;
|
||||||
|
|
||||||
eastl::array<vk::DescriptorBindingFlags, decltype(descriptorLayoutBindings)::count> layoutBindingFlags;
|
eastl::array<vk::DescriptorBindingFlags, descriptorLayoutBindings.size()> layoutBindingFlags;
|
||||||
layoutBindingFlags.fill(bindingFlags);
|
layoutBindingFlags.fill(bindingFlags);
|
||||||
|
|
||||||
vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo = {
|
vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo = {
|
||||||
.bindingCount = Cast<u32>(layoutBindingFlags.size()),
|
.bindingCount = static_cast<u32>(layoutBindingFlags.size()),
|
||||||
.pBindingFlags = layoutBindingFlags.data(),
|
.pBindingFlags = layoutBindingFlags.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -105,10 +83,10 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
|
||||||
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
.pNext = &bindingFlagsCreateInfo,
|
.pNext = &bindingFlagsCreateInfo,
|
||||||
.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
|
.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
|
||||||
.bindingCount = Cast<u32>(descriptorLayoutBindings.size()),
|
.bindingCount = static_cast<u32>(descriptorLayoutBindings.size()),
|
||||||
.pBindings = descriptorLayoutBindings.data(),
|
.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)
|
// One descriptor is enough. Updating it at any time is safe. (Update until submit, data held when pending)
|
||||||
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_descriptor_indexing.html
|
// https://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,
|
.descriptorSetCount = 1,
|
||||||
.pSetLayouts = &m_SetLayout,
|
.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_SetLayout, "Bindless Layout");
|
||||||
device->SetName(m_DescriptorPool, "Bindless Pool");
|
device->SetName(m_DescriptorPool, "Bindless Pool");
|
||||||
|
|
@ -129,8 +107,8 @@ CommitManager::CommitManager(const Device *device, const u32 maxBuffers, const u
|
||||||
|
|
||||||
CommitManager::~CommitManager()
|
CommitManager::~CommitManager()
|
||||||
{
|
{
|
||||||
m_Device->m_Device.destroy(m_SetLayout, nullptr);
|
m_Device->m_Device->destroy(m_SetLayout, nullptr);
|
||||||
m_Device->m_Device.destroy(m_DescriptorPool, nullptr);
|
m_Device->m_Device->destroy(m_DescriptorPool, nullptr);
|
||||||
|
|
||||||
#if !defined(ASTER_NDEBUG)
|
#if !defined(ASTER_NDEBUG)
|
||||||
u32 bufferCount = 0;
|
u32 bufferCount = 0;
|
||||||
|
|
@ -250,7 +228,7 @@ CommitManager::Update()
|
||||||
// Descriptor Updates
|
// Descriptor Updates
|
||||||
if (!m_Writes.empty())
|
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_Writes.clear();
|
||||||
m_WriteInfos.clear();
|
m_WriteInfos.clear();
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
target_sources(aster_core PRIVATE "logger.cpp" )
|
target_sources(aster_core PRIVATE "logger.cpp" "files.cpp")
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
@ -17,7 +17,7 @@ Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCo
|
||||||
m_Device = device;
|
m_Device = device;
|
||||||
|
|
||||||
eastl::fixed_string<char, 50, false> name = "Frame ";
|
eastl::fixed_string<char, 50, false> name = "Frame ";
|
||||||
name += Cast<char>('0' + frameCount);
|
name += static_cast<char>('0' + frameCount);
|
||||||
const vk::CommandPoolCreateInfo commandPoolCreateInfo = {
|
const vk::CommandPoolCreateInfo commandPoolCreateInfo = {
|
||||||
.flags = vk::CommandPoolCreateFlagBits::eTransient,
|
.flags = vk::CommandPoolCreateFlagBits::eTransient,
|
||||||
.queueFamilyIndex = queueFamilyIndex,
|
.queueFamilyIndex = queueFamilyIndex,
|
||||||
|
|
@ -71,7 +71,7 @@ Frame::Present(const vk::Queue commandQueue, Swapchain *swapchain, const Surface
|
||||||
case vk::Result::eErrorOutOfDateKHR:
|
case vk::Result::eErrorOutOfDateKHR:
|
||||||
case vk::Result::eSuboptimalKHR:
|
case vk::Result::eSuboptimalKHR:
|
||||||
DEBUG("Recreating Swapchain. Cause: {}", result);
|
DEBUG("Recreating Swapchain. Cause: {}", result);
|
||||||
swapchain->Create(surface, size);
|
swapchain->Create(*surface, size);
|
||||||
break; // Present failed. We do nothing. Frame is skipped.
|
break; // Present failed. We do nothing. Frame is skipped.
|
||||||
default:
|
default:
|
||||||
AbortIfFailedM(result, "Swapchain Present failed.");
|
AbortIfFailedM(result, "Swapchain Present failed.");
|
||||||
|
|
@ -154,7 +154,7 @@ FrameManager::GetNextFrame(Swapchain *swapchain, const Surface *surface, Size2D
|
||||||
break; // Image acquired. Break out of loop.
|
break; // Image acquired. Break out of loop.
|
||||||
case vk::Result::eErrorOutOfDateKHR:
|
case vk::Result::eErrorOutOfDateKHR:
|
||||||
DEBUG("Recreating Swapchain. Cause: {}", result);
|
DEBUG("Recreating Swapchain. Cause: {}", result);
|
||||||
swapchain->Create(surface, size);
|
swapchain->Create(*surface, size);
|
||||||
break; // Image acquire has failed. We move to the next frame.
|
break; // Image acquire has failed. We move to the next frame.
|
||||||
default:
|
default:
|
||||||
AbortIfFailedMV(result, "Waiting for swapchain image {} failed.", frameIndex);
|
AbortIfFailedMV(result, "Waiting for swapchain image {} failed.", frameIndex);
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ Init(const Instance *context, const Device *device, const Window *window, vk::Fo
|
||||||
const vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
|
const vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
|
||||||
.flags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
|
.flags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
|
||||||
.maxSets = 1000,
|
.maxSets = 1000,
|
||||||
.poolSizeCount = Cast<u32>(poolSizes.size()),
|
.poolSizeCount = static_cast<u32>(poolSizes.size()),
|
||||||
.pPoolSizes = poolSizes.data(),
|
.pPoolSizes = poolSizes.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,76 +62,3 @@ FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
|
||||||
ERROR("No suitable queue family on the GPU.")
|
ERROR("No suitable queue family on the GPU.")
|
||||||
THEN_ABORT(vk::Result::eErrorUnknown);
|
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();
|
|
||||||
}
|
|
||||||
|
|
@ -18,9 +18,6 @@ class PhysicalDevices;
|
||||||
|
|
||||||
PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices);
|
PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices);
|
||||||
QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice);
|
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>
|
template <usize TSize>
|
||||||
using StackString = eastl::fixed_string<char, TSize, false>;
|
using StackString = eastl::fixed_string<char, TSize, false>;
|
||||||
|
|
@ -29,7 +26,7 @@ using StackString = eastl::fixed_string<char, TSize, false>;
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
vk::Result _checkResultValue_; \
|
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_); \
|
THEN_ABORT(_checkResultValue_); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
|
|
@ -37,13 +34,13 @@ using StackString = eastl::fixed_string<char, TSize, false>;
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
vk::Result _checkResultValue_; \
|
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_); \
|
THEN_ABORT(_checkResultValue_); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
#define AbortIfFailedM(RESULT, MSG) \
|
#define AbortIfFailedM(RESULT, MSG) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
auto _checkResultValue_ = Cast<vk::Result>(RESULT); \
|
auto _checkResultValue_ = static_cast<vk::Result>(RESULT); \
|
||||||
ERROR_IF(Failed(_checkResultValue_), MSG " Cause: {}", _checkResultValue_) THEN_ABORT(_checkResultValue_); \
|
ERROR_IF(Failed(_checkResultValue_), MSG " Cause: {}", _checkResultValue_) THEN_ABORT(_checkResultValue_); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
add_executable(triangle "triangle.cpp")
|
add_executable(triangle "triangle.cpp")
|
||||||
add_shader(triangle "shader/triangle.vert.glsl")
|
add_shader(triangle "shader/triangle.slang")
|
||||||
add_shader(triangle "shader/triangle.frag.glsl")
|
add_resource_dir(triangle "shader")
|
||||||
|
|
||||||
target_link_libraries(triangle PRIVATE aster_core)
|
target_link_libraries(triangle PRIVATE aster_core)
|
||||||
target_link_libraries(triangle PRIVATE util_helper)
|
target_link_libraries(triangle PRIVATE util_helper)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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); //*/
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -8,110 +8,71 @@
|
||||||
#include "aster/core/buffer.h"
|
#include "aster/core/buffer.h"
|
||||||
#include "aster/core/constants.h"
|
#include "aster/core/constants.h"
|
||||||
#include "aster/core/instance.h"
|
#include "aster/core/instance.h"
|
||||||
#include "aster/core/device.h"
|
|
||||||
#include "aster/core/physical_device.h"
|
#include "aster/core/physical_device.h"
|
||||||
#include "aster/core/pipeline.h"
|
#include "aster/core/pipeline.h"
|
||||||
#include "aster/core/swapchain.h"
|
#include "aster/core/swapchain.h"
|
||||||
#include "aster/core/window.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 "helpers.h"
|
||||||
#include "aster/systems/resource_manager.h"
|
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
|
|
||||||
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
constexpr auto SHADER_MODULE = "triangle.slang";
|
||||||
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);
|
|
||||||
|
|
||||||
struct Vertex
|
struct Vertex
|
||||||
{
|
{
|
||||||
vec3 m_Position;
|
vec3 m_Position;
|
||||||
vec3 m_Color;
|
vec3 m_Color;
|
||||||
|
|
||||||
constexpr static vk::VertexInputBindingDescription
|
static eastl::vector<systems::AttributeInfo>
|
||||||
GetBinding(const u32 binding)
|
GetAttributes()
|
||||||
{
|
|
||||||
return {.binding = binding, .stride = sizeof(Vertex), .inputRate = vk::VertexInputRate::eVertex};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr static eastl::array<vk::VertexInputAttributeDescription, 2>
|
|
||||||
GetAttributes(const u32 binding)
|
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
vk::VertexInputAttributeDescription{
|
{
|
||||||
.location = 0,
|
.m_Location = 0,
|
||||||
.binding = binding,
|
.m_Offset = offsetof(Vertex, m_Position),
|
||||||
.format = vk::Format::eR32G32B32Sfloat,
|
.m_Format = systems::AttributeInfo::Format::eFloat32X3,
|
||||||
.offset = offsetof(Vertex, m_Position),
|
|
||||||
},
|
},
|
||||||
vk::VertexInputAttributeDescription{
|
{
|
||||||
.location = 1,
|
.m_Location = 1,
|
||||||
.binding = binding,
|
.m_Offset = offsetof(Vertex, m_Color),
|
||||||
.format = vk::Format::eR32G32B32Sfloat,
|
.m_Format = systems::AttributeInfo::Format::eFloat32X3,
|
||||||
.offset = offsetof(Vertex, m_Color),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
int
|
||||||
main(int, char **)
|
main(int, char **)
|
||||||
{
|
{
|
||||||
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
||||||
|
|
||||||
Window window = {"Triangle (Aster)", {640, 480}};
|
Window window = {"Triangle (Aster)", {640, 480}};
|
||||||
Instance context = {"Triangle", VERSION};
|
systems::Device device{{
|
||||||
Surface surface = {&context, &window, "Primary"};
|
.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};
|
Pipeline pipeline;
|
||||||
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
|
auto pipelineError = device.CreatePipeline(pipeline, {
|
||||||
|
.m_VertexInputs = {{
|
||||||
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
|
.m_Attribute = Vertex::GetAttributes(),
|
||||||
|
.m_Stride = sizeof(Vertex),
|
||||||
Features enabledDeviceFeatures = {
|
}},
|
||||||
.m_Vulkan12Features = {.bufferDeviceAddress = true},
|
.m_Shaders = {{
|
||||||
.m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = true},
|
.m_ShaderFile = SHADER_MODULE,
|
||||||
};
|
.m_EntryPoints = {"vsmain", "fsmain"},
|
||||||
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
|
}},
|
||||||
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
|
});
|
||||||
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
|
ERROR_IF(pipelineError, "Error creating pipeline. Cause: {}", pipelineError.What());
|
||||||
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, ©Pool);
|
|
||||||
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, ©Buffer);
|
|
||||||
ERROR_IF(Failed(result), "Copy command buffer allocation failed. Cause: {}", result) THEN_ABORT(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// eastl::array<Vertex, 3> vertices{};
|
// eastl::array<Vertex, 3> vertices{};
|
||||||
eastl::array 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.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}},
|
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());
|
vbo->Write(0, vertices.size() * sizeof vertices[0], vertices.data());
|
||||||
|
|
||||||
// Persistent variables
|
// 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 = {
|
vk::ImageSubresourceRange subresourceRange = {
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
|
@ -151,8 +99,8 @@ main(int, char **)
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
||||||
.oldLayout = vk::ImageLayout::eUndefined,
|
.oldLayout = vk::ImageLayout::eUndefined,
|
||||||
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.subresourceRange = subresourceRange,
|
.subresourceRange = subresourceRange,
|
||||||
};
|
};
|
||||||
vk::DependencyInfo topOfThePipeDependency = {
|
vk::DependencyInfo topOfThePipeDependency = {
|
||||||
|
|
@ -166,8 +114,8 @@ main(int, char **)
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eNone,
|
.dstAccessMask = vk::AccessFlagBits2::eNone,
|
||||||
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.subresourceRange = subresourceRange,
|
.subresourceRange = subresourceRange,
|
||||||
};
|
};
|
||||||
vk::DependencyInfo renderToPresentDependency = {
|
vk::DependencyInfo renderToPresentDependency = {
|
||||||
|
|
@ -175,70 +123,39 @@ main(int, char **)
|
||||||
.pImageMemoryBarriers = &renderToPresentBarrier,
|
.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");
|
INFO("Starting loop");
|
||||||
u32 frameIndex = 0;
|
|
||||||
while (window.Poll())
|
while (window.Poll())
|
||||||
{
|
{
|
||||||
Frame *currentFrame = &frames[frameIndex];
|
systems::Frame ¤tFrame = device.GetNextFrame();
|
||||||
|
|
||||||
auto result = device.m_Device.waitForFences(1, ¤tFrame->m_FrameAvailableFence, true, MaxValue<u64>);
|
Size2D swapchainSize = currentFrame.m_SwapchainSize;
|
||||||
ERROR_IF(Failed(result), "Waiting for fence {} failed. Cause: {}", frameIndex, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
u32 imageIndex;
|
vk::Viewport viewport = {
|
||||||
result = device.m_Device.acquireNextImageKHR(swapchain.m_Swapchain, MaxValue<u64>,
|
.x = 0,
|
||||||
currentFrame->m_ImageAcquireSem, nullptr, &imageIndex);
|
.y = static_cast<f32>(swapchainSize.m_Height),
|
||||||
if (Failed(result))
|
.width = static_cast<f32>(swapchainSize.m_Width),
|
||||||
{
|
.height = -static_cast<f32>(swapchainSize.m_Height),
|
||||||
switch (result)
|
.minDepth = 0.0,
|
||||||
{
|
.maxDepth = 1.0,
|
||||||
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, ¤tFrame->m_FrameAvailableFence);
|
|
||||||
ERROR_IF(Failed(result), "Fence {} reset failed. Cause: {}", frameIndex, result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
result = device.m_Device.resetCommandPool(currentFrame->m_Pool, {});
|
vk::Rect2D scissor = {
|
||||||
ERROR_IF(Failed(result), "Command pool {} reset failed. Cause: {}", frameIndex, result)
|
.offset = {0, 0},
|
||||||
THEN_ABORT(result);
|
.extent = static_cast<vk::Extent2D>(swapchainSize),
|
||||||
|
};
|
||||||
|
|
||||||
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
|
auto context = currentFrame.CreateGraphicsContext();
|
||||||
vk::Image currentImage = swapchain.m_Images[imageIndex];
|
|
||||||
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
|
|
||||||
|
|
||||||
topOfThePipeBarrier.image = currentImage;
|
topOfThePipeBarrier.image = currentFrame.m_SwapchainImage;
|
||||||
renderToPresentBarrier.image = currentImage;
|
renderToPresentBarrier.image = currentFrame.m_SwapchainImage;
|
||||||
|
|
||||||
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
context.Begin();
|
||||||
result = cmd.begin(&beginInfo);
|
|
||||||
ERROR_IF(Failed(result), "Command buffer begin failed. Cause: {}", result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
cmd.pipelineBarrier2(&topOfThePipeDependency);
|
context.Dependency(topOfThePipeDependency);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
vk::RenderingAttachmentInfo attachmentInfo = {
|
vk::RenderingAttachmentInfo attachmentInfo = {
|
||||||
.imageView = currentImageView,
|
.imageView = currentFrame.m_SwapchainImageView,
|
||||||
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
.resolveMode = vk::ResolveModeFlagBits::eNone,
|
.resolveMode = vk::ResolveModeFlagBits::eNone,
|
||||||
.loadOp = vk::AttachmentLoadOp::eClear,
|
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||||
|
|
@ -247,264 +164,29 @@ main(int, char **)
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::RenderingInfo renderingInfo = {
|
vk::RenderingInfo renderingInfo = {
|
||||||
.renderArea = {.extent = swapchain.m_Extent},
|
.renderArea = scissor,
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
.colorAttachmentCount = 1,
|
.colorAttachmentCount = 1,
|
||||||
.pColorAttachments = &attachmentInfo,
|
.pColorAttachments = &attachmentInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
cmd.beginRendering(&renderingInfo);
|
context.BeginRendering(renderingInfo);
|
||||||
|
|
||||||
cmd.setViewport(0, 1, &viewport);
|
context.SetViewport(viewport);
|
||||||
cmd.setScissor(0, 1, &scissor);
|
context.BindPipeline(pipeline);
|
||||||
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
|
context.BindVertexBuffer(vbo);
|
||||||
usize offsets = 0;
|
context.Draw(3);
|
||||||
cmd.bindVertexBuffers(0, 1, &vbo->m_Buffer, &offsets);
|
|
||||||
cmd.draw(3, 1, 0, 0);
|
|
||||||
|
|
||||||
cmd.endRendering();
|
context.EndRendering();
|
||||||
|
|
||||||
cmd.pipelineBarrier2(&renderToPresentDependency);
|
context.Dependency(renderToPresentDependency);
|
||||||
|
|
||||||
result = cmd.end();
|
context.End();
|
||||||
ERROR_IF(Failed(result), "Command buffer end failed. Cause: {}", result)
|
|
||||||
THEN_ABORT(result);
|
|
||||||
|
|
||||||
vk::PipelineStageFlags waitDstStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
device.Present(currentFrame, context);
|
||||||
vk::SubmitInfo submitInfo = {
|
|
||||||
.waitSemaphoreCount = 1,
|
|
||||||
.pWaitSemaphores = ¤tFrame->m_ImageAcquireSem,
|
|
||||||
.pWaitDstStageMask = &waitDstStage,
|
|
||||||
.commandBufferCount = 1,
|
|
||||||
.pCommandBuffers = &cmd,
|
|
||||||
.signalSemaphoreCount = 1,
|
|
||||||
.pSignalSemaphores = ¤tFrame->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 = ¤tFrame->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.WaitIdle();
|
device.WaitIdle();
|
||||||
|
|
||||||
device.m_Device.destroy(copyPool, nullptr);
|
|
||||||
|
|
||||||
return 0;
|
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");
|
|
||||||
}
|
|
||||||
|
|
@ -9,6 +9,8 @@ add_shader(box "shader/box.vert.glsl")
|
||||||
add_shader(box "shader/box.frag.glsl")
|
add_shader(box "shader/box.frag.glsl")
|
||||||
add_shader(box "shader/box.vs.hlsl")
|
add_shader(box "shader/box.vs.hlsl")
|
||||||
add_shader(box "shader/box.ps.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 aster_core)
|
||||||
target_link_libraries(box PRIVATE util_helper)
|
target_link_libraries(box PRIVATE util_helper)
|
||||||
|
|
|
||||||
|
|
@ -7,30 +7,23 @@
|
||||||
|
|
||||||
#include "aster/core/buffer.h"
|
#include "aster/core/buffer.h"
|
||||||
#include "aster/core/constants.h"
|
#include "aster/core/constants.h"
|
||||||
#include "aster/core/instance.h"
|
|
||||||
#include "aster/core/device.h"
|
|
||||||
#include "aster/core/image.h"
|
#include "aster/core/image.h"
|
||||||
#include "aster/core/physical_device.h"
|
#include "aster/core/physical_device.h"
|
||||||
#include "aster/core/pipeline.h"
|
#include "aster/core/pipeline.h"
|
||||||
#include "aster/core/swapchain.h"
|
#include "aster/core/swapchain.h"
|
||||||
#include "aster/core/window.h"
|
#include "aster/core/window.h"
|
||||||
|
|
||||||
#include "helpers.h"
|
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "aster/systems/buffer_manager.h"
|
|
||||||
#include "aster/systems/commit_manager.h"
|
#include "aster/systems/commit_manager.h"
|
||||||
#include "aster/systems/image_manager.h"
|
#include "aster/systems/device.h"
|
||||||
#include "aster/systems/resource_manager.h"
|
#include "aster/util/files.h"
|
||||||
#include "aster/systems/view_manager.h"
|
|
||||||
#include "frame.h"
|
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
|
|
||||||
#include <EASTL/array.h>
|
#include <EASTL/array.h>
|
||||||
|
|
||||||
constexpr u32 MAX_FRAMES_IN_FLIGHT = 3;
|
|
||||||
constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv";
|
constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv";
|
||||||
constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv";
|
constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv";
|
||||||
|
constexpr auto SHADER_FILE = "triangle";
|
||||||
|
|
||||||
struct ImageFile
|
struct ImageFile
|
||||||
{
|
{
|
||||||
|
|
@ -66,7 +59,7 @@ ImageFile::Load(cstr fileName)
|
||||||
usize
|
usize
|
||||||
ImageFile::GetSize() const
|
ImageFile::GetSize() const
|
||||||
{
|
{
|
||||||
return Cast<usize>(m_Width) * m_Height * m_NumChannels;
|
return static_cast<usize>(m_Width) * m_Height * m_NumChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageFile::~ImageFile()
|
ImageFile::~ImageFile()
|
||||||
|
|
@ -75,9 +68,6 @@ ImageFile::~ImageFile()
|
||||||
m_Data = nullptr;
|
m_Data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::ShaderModule CreateShader(const Device *device, cstr shaderFile);
|
|
||||||
Pipeline CreatePipeline(const systems::CommitManager *resourceManager, const Swapchain *swapchain);
|
|
||||||
|
|
||||||
struct Vertex
|
struct Vertex
|
||||||
{
|
{
|
||||||
vec3 m_Position;
|
vec3 m_Position;
|
||||||
|
|
@ -99,13 +89,6 @@ main(int, char **)
|
||||||
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
||||||
|
|
||||||
Window window = {"Box (Aster)", {640, 480}};
|
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 = {
|
Features enabledDeviceFeatures = {
|
||||||
.m_Vulkan10Features = {.samplerAnisotropy = true},
|
.m_Vulkan10Features = {.samplerAnisotropy = true},
|
||||||
|
|
@ -121,47 +104,37 @@ main(int, char **)
|
||||||
.descriptorBindingStorageBufferUpdateAfterBind = true,
|
.descriptorBindingStorageBufferUpdateAfterBind = true,
|
||||||
.descriptorBindingPartiallyBound = true,
|
.descriptorBindingPartiallyBound = true,
|
||||||
.runtimeDescriptorArray = true,
|
.runtimeDescriptorArray = true,
|
||||||
|
.timelineSemaphore = true,
|
||||||
.bufferDeviceAddress = true,
|
.bufferDeviceAddress = true,
|
||||||
.bufferDeviceAddressCaptureReplay = true,
|
.bufferDeviceAddressCaptureReplay = true,
|
||||||
},
|
},
|
||||||
.m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = 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;
|
||||||
|
auto pipelineResult =
|
||||||
Pipeline pipeline = CreatePipeline(&commitManager, &swapchain);
|
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 = {
|
Camera camera = {
|
||||||
.m_Model = {1.0f},
|
.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_View = lookAt(vec3(0.0f, 2.0f, 2.0f), vec3(0.0f), vec3(0.0f, 1.0f, 0.0f)),
|
||||||
.m_Perspective = glm::perspective(
|
.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, ©Pool),
|
|
||||||
"Copy command pool creation failed.");
|
|
||||||
vk::CommandBufferAllocateInfo bufferAllocateInfo = {
|
|
||||||
.commandPool = copyPool,
|
|
||||||
.level = vk::CommandBufferLevel::ePrimary,
|
|
||||||
.commandBufferCount = 1,
|
|
||||||
};
|
|
||||||
AbortIfFailedM(device.m_Device.allocateCommandBuffers(&bufferAllocateInfo, ©Buffer),
|
|
||||||
"Copy command buffer allocation failed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
eastl::array vertices = {
|
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, 1.0f)},
|
||||||
Vertex{.m_Position = vec3(0.5f, -0.5f, -0.5f), .m_TexCoord0 = vec2(1.0f, 0.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);
|
assert(loaded);
|
||||||
INFO("Image {}x{} : {} channels", imageFile.m_Width, imageFile.m_Height, imageFile.m_NumChannels);
|
INFO("Image {}x{} : {} channels", imageFile.m_Width, imageFile.m_Height, imageFile.m_NumChannels);
|
||||||
|
|
||||||
auto vbo = 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());
|
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_Format = vk::Format::eR8G8B8A8Srgb,
|
||||||
.m_Extent = {imageFile.m_Width, imageFile.m_Height},
|
.m_Extent = {imageFile.m_Width, imageFile.m_Height},
|
||||||
.m_Name = "Crate Texture",
|
.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);
|
imageStaging->Write(0, imageFile.GetSize(), imageFile.m_Data);
|
||||||
|
|
||||||
vk::ImageMemoryBarrier2 imageReadyToWrite = {
|
vk::ImageMemoryBarrier2 imageReadyToWrite = {
|
||||||
|
|
@ -232,8 +205,8 @@ main(int, char **)
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
.oldLayout = vk::ImageLayout::eUndefined,
|
.oldLayout = vk::ImageLayout::eUndefined,
|
||||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.image = crate->GetImage(),
|
.image = crate->GetImage(),
|
||||||
.subresourceRange =
|
.subresourceRange =
|
||||||
{
|
{
|
||||||
|
|
@ -256,8 +229,8 @@ main(int, char **)
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eShaderRead,
|
.dstAccessMask = vk::AccessFlagBits2::eShaderRead,
|
||||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.image = crate->GetImage(),
|
.image = crate->GetImage(),
|
||||||
.subresourceRange =
|
.subresourceRange =
|
||||||
{
|
{
|
||||||
|
|
@ -273,77 +246,25 @@ main(int, char **)
|
||||||
.pImageMemoryBarriers = &imageReadyToRead,
|
.pImageMemoryBarriers = &imageReadyToRead,
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::Fence fence;
|
auto &context = device.CreateTransferContext();
|
||||||
vk::FenceCreateInfo fenceCreateInfo = {};
|
context.Begin();
|
||||||
AbortIfFailed(device.m_Device.createFence(&fenceCreateInfo, nullptr, &fence));
|
|
||||||
|
|
||||||
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
context.Dependency(imageReadyToWriteDependency);
|
||||||
AbortIfFailed(copyBuffer.begin(&beginInfo));
|
|
||||||
|
|
||||||
copyBuffer.pipelineBarrier2(&imageReadyToWriteDependency);
|
context.UploadTexture(crate->m_Image, {.m_Data = imageFile.m_Data, .m_NumBytes = imageFile.GetSize()});
|
||||||
|
|
||||||
vk::BufferImageCopy imageCopy = {
|
context.Dependency(imageReadyToReadDependency);
|
||||||
.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);
|
|
||||||
|
|
||||||
copyBuffer.pipelineBarrier2(&imageReadyToReadDependency);
|
context.End();
|
||||||
|
|
||||||
AbortIfFailed(copyBuffer.end());
|
auto recpt = device.Submit(context);
|
||||||
|
device.WaitOn(recpt);
|
||||||
vk::SubmitInfo submitInfo = {
|
|
||||||
.commandBufferCount = 1,
|
|
||||||
.pCommandBuffers = ©Buffer,
|
|
||||||
};
|
|
||||||
|
|
||||||
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 ubo = resourceManager.Buffers().CreateStorageBuffer(sizeof camera, "Camera UBO");
|
auto ubo = device.CreateStorageBuffer(sizeof camera, "Camera UBO");
|
||||||
ubo->Write(0, sizeof camera, &camera);
|
ubo->Write(0, sizeof camera, &camera);
|
||||||
|
|
||||||
// Persistent variables
|
// 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 = {
|
vk::ImageSubresourceRange subresourceRange = {
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
|
@ -361,8 +282,8 @@ main(int, char **)
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
||||||
.oldLayout = vk::ImageLayout::eUndefined,
|
.oldLayout = vk::ImageLayout::eUndefined,
|
||||||
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.subresourceRange = subresourceRange,
|
.subresourceRange = subresourceRange,
|
||||||
};
|
};
|
||||||
vk::DependencyInfo topOfThePipeDependency = {
|
vk::DependencyInfo topOfThePipeDependency = {
|
||||||
|
|
@ -376,8 +297,8 @@ main(int, char **)
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eNone,
|
.dstAccessMask = vk::AccessFlagBits2::eNone,
|
||||||
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
.newLayout = vk::ImageLayout::ePresentSrcKHR,
|
||||||
.srcQueueFamilyIndex = queueAllocation.m_Family,
|
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.dstQueueFamilyIndex = queueAllocation.m_Family,
|
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||||
.subresourceRange = subresourceRange,
|
.subresourceRange = subresourceRange,
|
||||||
};
|
};
|
||||||
vk::DependencyInfo renderToPresentDependency = {
|
vk::DependencyInfo renderToPresentDependency = {
|
||||||
|
|
@ -385,64 +306,90 @@ main(int, char **)
|
||||||
.pImageMemoryBarriers = &renderToPresentBarrier,
|
.pImageMemoryBarriers = &renderToPresentBarrier,
|
||||||
};
|
};
|
||||||
|
|
||||||
FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT};
|
|
||||||
eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> depthImages;
|
eastl::fixed_vector<Ref<ImageView>, MAX_FRAMES_IN_FLIGHT> depthImages;
|
||||||
|
|
||||||
auto initDepthImages = [&depthImages, &frameManager, &resourceManager](const vk::Extent2D extent) {
|
auto initDepthImages = [&depthImages, &device](const vk::Extent2D extent) {
|
||||||
for (u32 i = 0; i < frameManager.m_FramesInFlight; ++i)
|
for (u32 i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
|
||||||
{
|
{
|
||||||
depthImages.push_back(
|
depthImages.push_back(device.CreateDepthStencilImageWithView({.m_Extent = extent, .m_Name = "Depth"}));
|
||||||
resourceManager.CombinedImageViews().CreateDepthStencilImage({.m_Extent = extent, .m_Name = "Depth"}));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
initDepthImages(swapchain.m_Extent);
|
initDepthImages(swapchainSize);
|
||||||
|
|
||||||
auto recreateDepthBuffers = [&depthImages, &initDepthImages](const vk::Extent2D extent) {
|
auto recreateDepthBuffers = [&depthImages, &initDepthImages](const vk::Extent2D extent) {
|
||||||
depthImages.clear();
|
depthImages.clear();
|
||||||
initDepthImages(extent);
|
initDepthImages(extent);
|
||||||
};
|
};
|
||||||
swapchain.RegisterResizeCallback(recreateDepthBuffers);
|
|
||||||
|
|
||||||
|
// TODO: Move to 64bit handles.
|
||||||
struct PCB
|
struct PCB
|
||||||
{
|
{
|
||||||
systems::ResId<Buffer> m_Camera;
|
|
||||||
systems::ResId<Buffer> m_VertexBuffer;
|
systems::ResId<Buffer> m_VertexBuffer;
|
||||||
|
u32 m_Pad0 = 0;
|
||||||
|
systems::ResId<Buffer> m_Camera;
|
||||||
|
u32 m_Pad1 = 0;
|
||||||
systems::ResId<TextureView> m_Texture;
|
systems::ResId<TextureView> m_Texture;
|
||||||
|
u32 m_Pad2 = 0;
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(PCB) == 24);
|
||||||
|
|
||||||
|
auto &commitManager = systems::CommitManager::Instance();
|
||||||
|
|
||||||
PCB pcb = {
|
PCB pcb = {
|
||||||
.m_Camera = commitManager.CommitBuffer(ubo),
|
|
||||||
.m_VertexBuffer = commitManager.CommitBuffer(vbo),
|
.m_VertexBuffer = commitManager.CommitBuffer(vbo),
|
||||||
|
.m_Camera = commitManager.CommitBuffer(ubo),
|
||||||
.m_Texture = commitManager.CommitTexture(crate),
|
.m_Texture = commitManager.CommitTexture(crate),
|
||||||
};
|
};
|
||||||
|
|
||||||
Time::Init();
|
Time::Init();
|
||||||
|
|
||||||
|
auto prevSwapchainSize = swapchainSize;
|
||||||
|
|
||||||
INFO("Starting loop");
|
INFO("Starting loop");
|
||||||
while (window.Poll())
|
while (window.Poll())
|
||||||
{
|
{
|
||||||
Time::Update();
|
Time::Update();
|
||||||
commitManager.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);
|
ubo->Write(0, sizeof camera, &camera);
|
||||||
|
|
||||||
Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &surface, window.GetSize());
|
auto& currentFrame = device.GetNextFrame();
|
||||||
|
|
||||||
u32 imageIndex = currentFrame->m_ImageIdx;
|
prevSwapchainSize = swapchainSize;
|
||||||
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
|
swapchainSize = currentFrame.m_SwapchainSize;
|
||||||
vk::Image currentImage = swapchain.m_Images[imageIndex];
|
if (swapchainSize != prevSwapchainSize)
|
||||||
vk::CommandBuffer cmd = currentFrame->m_CommandBuffer;
|
{
|
||||||
vk::ImageView currentDepthImageView = depthImages[currentFrame->m_FrameIdx]->m_View;
|
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;
|
topOfThePipeBarrier.image = currentImage;
|
||||||
renderToPresentBarrier.image = currentImage;
|
renderToPresentBarrier.image = currentImage;
|
||||||
|
|
||||||
vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit};
|
auto context = currentFrame.CreateGraphicsContext();
|
||||||
AbortIfFailed(cmd.begin(&beginInfo));
|
|
||||||
|
|
||||||
cmd.pipelineBarrier2(&topOfThePipeDependency);
|
context.Begin();
|
||||||
|
|
||||||
|
context.Dependency(topOfThePipeDependency);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
eastl::array attachmentInfos = {
|
eastl::array attachmentInfos = {
|
||||||
|
|
@ -466,187 +413,30 @@ main(int, char **)
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::RenderingInfo renderingInfo = {
|
vk::RenderingInfo renderingInfo = {
|
||||||
.renderArea = {.extent = swapchain.m_Extent},
|
.renderArea = scissor,
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
.colorAttachmentCount = Cast<u32>(attachmentInfos.size()),
|
.colorAttachmentCount = static_cast<u32>(attachmentInfos.size()),
|
||||||
.pColorAttachments = attachmentInfos.data(),
|
.pColorAttachments = attachmentInfos.data(),
|
||||||
.pDepthAttachment = &depthAttachment,
|
.pDepthAttachment = &depthAttachment,
|
||||||
};
|
};
|
||||||
|
|
||||||
cmd.beginRendering(&renderingInfo);
|
context.BeginRendering(renderingInfo);
|
||||||
|
|
||||||
cmd.setViewport(0, 1, &viewport);
|
context.SetViewport(viewport);
|
||||||
cmd.setScissor(0, 1, &scissor);
|
context.BindPipeline(pipeline);
|
||||||
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline);
|
context.PushConstantBlock(pcb);
|
||||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.m_Layout, 0, 1,
|
context.Draw(vertices.size());
|
||||||
&commitManager.GetDescriptorSet(), 0, nullptr);
|
|
||||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAllGraphics, 0, 12, &pcb);
|
|
||||||
cmd.draw(Cast<u32>(vertices.size()), 1, 0, 0);
|
|
||||||
|
|
||||||
cmd.endRendering();
|
context.EndRendering();
|
||||||
|
|
||||||
cmd.pipelineBarrier2(&renderToPresentDependency);
|
context.Dependency(renderToPresentDependency);
|
||||||
|
|
||||||
AbortIfFailed(cmd.end());
|
context.End();
|
||||||
|
|
||||||
vk::PipelineStageFlags waitDstStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
device.Present(currentFrame, context);
|
||||||
vk::SubmitInfo submitInfo = {
|
|
||||||
.waitSemaphoreCount = 1,
|
|
||||||
.pWaitSemaphores = ¤tFrame->m_ImageAcquireSem,
|
|
||||||
.pWaitDstStageMask = &waitDstStage,
|
|
||||||
.commandBufferCount = 1,
|
|
||||||
.pCommandBuffers = &cmd,
|
|
||||||
.signalSemaphoreCount = 1,
|
|
||||||
.pSignalSemaphores = ¤tFrame->m_RenderFinishSem,
|
|
||||||
};
|
|
||||||
AbortIfFailed(commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence));
|
|
||||||
|
|
||||||
currentFrame->Present(commandQueue, &swapchain, &surface, window.GetSize());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
device.WaitIdle();
|
device.WaitIdle();
|
||||||
device.m_Device.destroy(copyPool, nullptr);
|
|
||||||
|
|
||||||
return 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -62,8 +62,8 @@ AssetLoader::LoadHdrImage(cstr path, cstr name) const
|
||||||
|
|
||||||
ERROR_IF(!data, "Could not load {}", path) THEN_ABORT(-1);
|
ERROR_IF(!data, "Could not load {}", path) THEN_ABORT(-1);
|
||||||
|
|
||||||
u32 width = Cast<u32>(x);
|
u32 width = static_cast<u32>(x);
|
||||||
u32 height = Cast<u32>(y);
|
u32 height = static_cast<u32>(y);
|
||||||
|
|
||||||
auto texture = m_ResourceManager->CombinedImageViews().CreateTexture2D<TextureView>({
|
auto texture = m_ResourceManager->CombinedImageViews().CreateTexture2D<TextureView>({
|
||||||
.m_Format = vk::Format::eR32G32B32A32Sfloat,
|
.m_Format = vk::Format::eR32G32B32A32Sfloat,
|
||||||
|
|
@ -248,7 +248,7 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref<Texture> &texture, vk
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DependencyInfo imageStartDependency = {
|
vk::DependencyInfo imageStartDependency = {
|
||||||
.imageMemoryBarrierCount = Cast<u32>(startBarriers.size()),
|
.imageMemoryBarrierCount = static_cast<u32>(startBarriers.size()),
|
||||||
.pImageMemoryBarriers = startBarriers.data(),
|
.pImageMemoryBarriers = startBarriers.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -331,8 +331,8 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, const Ref<Texture> &texture, vk
|
||||||
|
|
||||||
commandBuffer.pipelineBarrier2(&imageStartDependency);
|
commandBuffer.pipelineBarrier2(&imageStartDependency);
|
||||||
|
|
||||||
i32 prevMipWidth = Cast<i32>(texture->m_Extent.width);
|
i32 prevMipWidth = static_cast<i32>(texture->m_Extent.width);
|
||||||
i32 prevMipHeight = Cast<i32>(texture->m_Extent.height);
|
i32 prevMipHeight = static_cast<i32>(texture->m_Extent.height);
|
||||||
|
|
||||||
u32 maxPrevMip = texture->GetMipLevels() - 1;
|
u32 maxPrevMip = texture->GetMipLevels() - 1;
|
||||||
for (u32 prevMipLevel = 0; prevMipLevel < maxPrevMip; ++prevMipLevel)
|
for (u32 prevMipLevel = 0; prevMipLevel < maxPrevMip; ++prevMipLevel)
|
||||||
|
|
@ -382,8 +382,8 @@ AssetLoader::LoadImageToGpu(tinygltf::Image *image, bool isSrgb, cstr name) cons
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
u32 height = Cast<u32>(image->height);
|
u32 height = static_cast<u32>(image->height);
|
||||||
u32 width = Cast<u32>(image->width);
|
u32 width = static_cast<u32>(image->width);
|
||||||
|
|
||||||
vk::Format imageFormat = isSrgb ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm;
|
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 = {
|
vk::BufferImageCopy2 imageCopy = {
|
||||||
.bufferOffset = 0,
|
.bufferOffset = 0,
|
||||||
.bufferRowLength = Cast<u32>(image->width),
|
.bufferRowLength = static_cast<u32>(image->width),
|
||||||
.bufferImageHeight = Cast<u32>(image->height),
|
.bufferImageHeight = static_cast<u32>(image->height),
|
||||||
.imageSubresource =
|
.imageSubresource =
|
||||||
{
|
{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
|
@ -583,8 +583,8 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
materials.push_back({
|
materials.push_back({
|
||||||
.m_AlbedoFactor = VectorToVec4(material.pbrMetallicRoughness.baseColorFactor),
|
.m_AlbedoFactor = VectorToVec4(material.pbrMetallicRoughness.baseColorFactor),
|
||||||
.m_EmissionFactor = VectorToVec3(material.emissiveFactor),
|
.m_EmissionFactor = VectorToVec3(material.emissiveFactor),
|
||||||
.m_MetalFactor = Cast<f32>(material.pbrMetallicRoughness.metallicFactor),
|
.m_MetalFactor = static_cast<f32>(material.pbrMetallicRoughness.metallicFactor),
|
||||||
.m_RoughFactor = Cast<f32>(material.pbrMetallicRoughness.roughnessFactor),
|
.m_RoughFactor = static_cast<f32>(material.pbrMetallicRoughness.roughnessFactor),
|
||||||
.m_AlbedoTex = getTextureHandle(material.pbrMetallicRoughness.baseColorTexture.index, true),
|
.m_AlbedoTex = getTextureHandle(material.pbrMetallicRoughness.baseColorTexture.index, true),
|
||||||
.m_NormalTex = getTextureHandle(material.normalTexture.index, false),
|
.m_NormalTex = getTextureHandle(material.normalTexture.index, false),
|
||||||
.m_MetalRoughTex =
|
.m_MetalRoughTex =
|
||||||
|
|
@ -643,17 +643,17 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
tinygltf::Buffer *posBuffer = &model.buffers[posBufferView->buffer];
|
tinygltf::Buffer *posBuffer = &model.buffers[posBufferView->buffer];
|
||||||
usize byteOffset = (posAccessor->byteOffset + posBufferView->byteOffset);
|
usize byteOffset = (posAccessor->byteOffset + posBufferView->byteOffset);
|
||||||
|
|
||||||
vertexCount = Cast<u32>(posAccessor->count);
|
vertexCount = static_cast<u32>(posAccessor->count);
|
||||||
vertexPositions.reserve(vertexOffset + vertexCount);
|
vertexPositions.reserve(vertexOffset + vertexCount);
|
||||||
|
|
||||||
if (posAccessor->type == TINYGLTF_TYPE_VEC4)
|
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);
|
vertexPositions.insert(vertexPositions.end(), data, data + vertexCount);
|
||||||
}
|
}
|
||||||
else if (posAccessor->type == TINYGLTF_TYPE_VEC3)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
vertexPositions.push_back(vec4(data[i], 1.0f));
|
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)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
vertexPositions.push_back(vec4(data[i], 0.0f, 1.0f));
|
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)
|
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;
|
vec4 *end = data + vertexCount;
|
||||||
u32 idx = vertexOffset;
|
u32 idx = vertexOffset;
|
||||||
|
|
@ -697,7 +697,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
}
|
}
|
||||||
else if (normAccessor->type == TINYGLTF_TYPE_VEC3)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
auto norm = vec4(data[i], 0.0f);
|
auto norm = vec4(data[i], 0.0f);
|
||||||
|
|
@ -706,7 +706,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
}
|
}
|
||||||
else if (normAccessor->type == TINYGLTF_TYPE_VEC2)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
auto norm = vec4(data[i], 0.0f, 0.0f);
|
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 &&
|
assert(uvAccessor->type == TINYGLTF_TYPE_VEC2 &&
|
||||||
uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT);
|
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;
|
vec2 *end = data + vertexCount;
|
||||||
u32 idx = vertexOffset;
|
u32 idx = vertexOffset;
|
||||||
vec2 *it = data;
|
vec2 *it = data;
|
||||||
|
|
@ -752,7 +752,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
|
|
||||||
if (colorAccessor->type == TINYGLTF_TYPE_VEC4)
|
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;
|
vec4 *end = data + vertexCount;
|
||||||
u32 idx = vertexOffset;
|
u32 idx = vertexOffset;
|
||||||
|
|
@ -764,7 +764,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
}
|
}
|
||||||
else if (colorAccessor->type == TINYGLTF_TYPE_VEC3)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
auto color = vec4(data[i], 1.0f);
|
auto color = vec4(data[i], 1.0f);
|
||||||
|
|
@ -785,22 +785,22 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
tinygltf::Buffer *indexBuffer = &model.buffers[indexBufferView->buffer];
|
tinygltf::Buffer *indexBuffer = &model.buffers[indexBufferView->buffer];
|
||||||
usize byteOffset = (indexAccessor->byteOffset + indexBufferView->byteOffset);
|
usize byteOffset = (indexAccessor->byteOffset + indexBufferView->byteOffset);
|
||||||
|
|
||||||
indexCount = Cast<u32>(indexAccessor->count);
|
indexCount = static_cast<u32>(indexAccessor->count);
|
||||||
indices.reserve(indexOffset + indexCount);
|
indices.reserve(indexOffset + indexCount);
|
||||||
|
|
||||||
if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT)
|
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);
|
indices.insert(indices.end(), data, data + indexCount);
|
||||||
}
|
}
|
||||||
else if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
|
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);
|
indices.insert(indices.end(), data, data + indexCount);
|
||||||
}
|
}
|
||||||
else if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)
|
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);
|
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) *
|
const mat4 transform = translate(mat4(1.0f), nodeTranslation) * mat4_cast(nodeRotation) *
|
||||||
scale(mat4(1.0f), nodeScale) * nodeMatrix;
|
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)
|
if (node->mesh >= 0)
|
||||||
{
|
{
|
||||||
auto [start, count] = meshPrimRanges[node->mesh];
|
auto [start, count] = meshPrimRanges[node->mesh];
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
|
||||||
readyToWriteBarriers[3].subresourceRange = lutSubresRange;
|
readyToWriteBarriers[3].subresourceRange = lutSubresRange;
|
||||||
|
|
||||||
vk::DependencyInfo readyToWriteDependency = {
|
vk::DependencyInfo readyToWriteDependency = {
|
||||||
.imageMemoryBarrierCount = Cast<u32>(readyToWriteBarriers.size()),
|
.imageMemoryBarrierCount = static_cast<u32>(readyToWriteBarriers.size()),
|
||||||
.pImageMemoryBarriers = readyToWriteBarriers.data(),
|
.pImageMemoryBarriers = readyToWriteBarriers.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -209,7 +209,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size =
|
.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)))),
|
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;
|
eastl::array<vk::Pipeline, computePipelineCreateInfo.size()> pipelines;
|
||||||
AbortIfFailed(
|
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()));
|
computePipelineCreateInfo.data(), nullptr, pipelines.data()));
|
||||||
|
|
||||||
vk::Pipeline eqRectToCubePipeline = pipelines[0];
|
vk::Pipeline eqRectToCubePipeline = pipelines[0];
|
||||||
|
|
@ -345,7 +345,7 @@ CreateCubeFromHdrEnv(AssetLoader *assetLoader, vk::Queue computeQueue, const u32
|
||||||
{
|
{
|
||||||
prefilterPushConstants.m_OutputTexture = tex;
|
prefilterPushConstants.m_OutputTexture = tex;
|
||||||
prefilterPushConstants.m_CubeSide = mipSize;
|
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,
|
cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof prefilterPushConstants,
|
||||||
&prefilterPushConstants);
|
&prefilterPushConstants);
|
||||||
u32 groupCount = eastl::max(mipSize / 16u, 1u);
|
u32 groupCount = eastl::max(mipSize / 16u, 1u);
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,10 @@ static_assert(Light::COLOR_MASK == 0xFFFFFF00);
|
||||||
inline u32
|
inline u32
|
||||||
ToColor32(const vec4 &col)
|
ToColor32(const vec4 &col)
|
||||||
{
|
{
|
||||||
const u32 r = Cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
|
const u32 r = static_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 g = static_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 b = static_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 a = static_cast<u32>(eastl::min(col.a, 1.0f) * 255.99f);
|
||||||
|
|
||||||
return r << 24 | g << 16 | b << 8 | a;
|
return r << 24 | g << 16 | b << 8 | a;
|
||||||
}
|
}
|
||||||
|
|
@ -47,9 +47,9 @@ ToColor32(const vec4 &col)
|
||||||
inline u32
|
inline u32
|
||||||
ToColor32(const vec3 &col)
|
ToColor32(const vec3 &col)
|
||||||
{
|
{
|
||||||
const u32 r = Cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
|
const u32 r = static_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 g = static_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 b = static_cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
|
||||||
constexpr u32 a = 255;
|
constexpr u32 a = 255;
|
||||||
|
|
||||||
return r << 24 | g << 16 | b << 8 | a;
|
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;
|
m_GpuBufferCapacity_ |= UPDATE_REQUIRED_BIT;
|
||||||
|
|
||||||
return {Light::TYPE_POINT, gen, Cast<u16>(index)};
|
return {Light::TYPE_POINT, gen, static_cast<u16>(index)};
|
||||||
}
|
}
|
||||||
++light;
|
++light;
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +207,7 @@ LightManager::AddPoint(const vec3 &position, const vec3 &color, const f32 radius
|
||||||
void
|
void
|
||||||
LightManager::Update()
|
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)
|
if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity)
|
||||||
{
|
{
|
||||||
auto newBuffer = m_ResourceManager->Buffers().CreateStorageBuffer(requiredBufferCapacity * sizeof m_Lights[0],
|
auto newBuffer = m_ResourceManager->Buffers().CreateStorageBuffer(requiredBufferCapacity * sizeof m_Lights[0],
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ struct LightManager
|
||||||
// Using lower bit. Capacity can be directly a multiple of 2
|
// Using lower bit. Capacity can be directly a multiple of 2
|
||||||
// Thus, range is up to MaxValue<u16>
|
// Thus, range is up to MaxValue<u16>
|
||||||
constexpr static u16 UPDATE_REQUIRED_BIT = 1;
|
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 AddDirectional(const vec3 &direction, const vec3 &color, f32 intensity);
|
||||||
LightHandle AddPoint(const vec3 &position, const vec3 &color, f32 radius, f32 intensity);
|
LightHandle AddPoint(const vec3 &position, const vec3 &color, f32 radius, f32 intensity);
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ main(int, char **)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
|
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));
|
AbortIfFailed(device.m_Device.createDescriptorPool(&descriptorPoolCreateInfo, nullptr, &descriptorPool));
|
||||||
|
|
||||||
vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
|
vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
|
||||||
|
|
@ -230,7 +230,7 @@ main(int, char **)
|
||||||
vk::Extent2D internalResolution = {1920, 1080};
|
vk::Extent2D internalResolution = {1920, 1080};
|
||||||
|
|
||||||
CameraController cameraController = {vec3{0.0f, 0.0f, 2.0f}, vec3{0.0f}, 70_deg,
|
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 uboSize = 0;
|
||||||
usize cameraSize = sizeof cameraController.m_Camera;
|
usize cameraSize = sizeof cameraController.m_Camera;
|
||||||
|
|
@ -277,16 +277,16 @@ main(int, char **)
|
||||||
.pBufferInfo = &lightingBufferInfo,
|
.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();
|
commitManager.Update();
|
||||||
|
|
||||||
// Persistent variables
|
// Persistent variables
|
||||||
vk::Viewport viewport = {
|
vk::Viewport viewport = {
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = Cast<f32>(internalResolution.height),
|
.y = static_cast<f32>(internalResolution.height),
|
||||||
.width = Cast<f32>(internalResolution.width),
|
.width = static_cast<f32>(internalResolution.width),
|
||||||
.height = -Cast<f32>(internalResolution.height),
|
.height = -static_cast<f32>(internalResolution.height),
|
||||||
.minDepth = 0.0,
|
.minDepth = 0.0,
|
||||||
.maxDepth = 1.0,
|
.maxDepth = 1.0,
|
||||||
};
|
};
|
||||||
|
|
@ -347,7 +347,7 @@ main(int, char **)
|
||||||
acquireToTransferDstBarrier,
|
acquireToTransferDstBarrier,
|
||||||
};
|
};
|
||||||
vk::DependencyInfo postRenderDependencies = {
|
vk::DependencyInfo postRenderDependencies = {
|
||||||
.imageMemoryBarrierCount = Cast<u32>(postRenderBarriers.size()),
|
.imageMemoryBarrierCount = static_cast<u32>(postRenderBarriers.size()),
|
||||||
.pImageMemoryBarriers = postRenderBarriers.data(),
|
.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);
|
queueAllocation.m_Family, graphicsQueue);
|
||||||
bool rotating = false;
|
bool rotating = false;
|
||||||
bool lockToScreen = true;
|
bool lockToScreen = true;
|
||||||
|
|
@ -417,14 +417,14 @@ main(int, char **)
|
||||||
constexpr static u32 SHOW_DIFFUSE_BIT = 1 << 2;
|
constexpr static u32 SHOW_DIFFUSE_BIT = 1 << 2;
|
||||||
constexpr static u32 SHOW_PREFILTER_BIT = 1 << 3;
|
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 camPitch = glm::degrees(cameraController.m_Pitch);
|
||||||
f32 camYaw = glm::degrees(cameraController.m_Yaw);
|
f32 camYaw = glm::degrees(cameraController.m_Yaw);
|
||||||
vec3 camPosition = cameraController.m_Camera.m_Position;
|
vec3 camPosition = cameraController.m_Camera.m_Position;
|
||||||
vk::Extent2D inputResolution = internalResolution;
|
vk::Extent2D inputResolution = internalResolution;
|
||||||
|
|
||||||
swapchain.RegisterResizeCallback([&cameraController](vk::Extent2D extent) {
|
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();
|
Time::Init();
|
||||||
|
|
@ -449,7 +449,7 @@ main(int, char **)
|
||||||
}
|
}
|
||||||
|
|
||||||
inputResolution.height = height;
|
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"))
|
if (gui::Button("Change Resolution"))
|
||||||
{
|
{
|
||||||
|
|
@ -457,9 +457,9 @@ main(int, char **)
|
||||||
inputResolution.height != internalResolution.height)
|
inputResolution.height != internalResolution.height)
|
||||||
{
|
{
|
||||||
internalResolution = inputResolution;
|
internalResolution = inputResolution;
|
||||||
viewport.width = Cast<f32>(internalResolution.width);
|
viewport.width = static_cast<f32>(internalResolution.width);
|
||||||
viewport.height = -Cast<f32>(internalResolution.height);
|
viewport.height = -static_cast<f32>(internalResolution.height);
|
||||||
viewport.y = Cast<f32>(internalResolution.height);
|
viewport.y = static_cast<f32>(internalResolution.height);
|
||||||
scissor.extent = internalResolution;
|
scissor.extent = internalResolution;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -470,9 +470,9 @@ main(int, char **)
|
||||||
swapchain.m_Extent.height != internalResolution.height)
|
swapchain.m_Extent.height != internalResolution.height)
|
||||||
{
|
{
|
||||||
internalResolution = swapchain.m_Extent;
|
internalResolution = swapchain.m_Extent;
|
||||||
viewport.width = Cast<f32>(internalResolution.width);
|
viewport.width = static_cast<f32>(internalResolution.width);
|
||||||
viewport.height = -Cast<f32>(internalResolution.height);
|
viewport.height = -static_cast<f32>(internalResolution.height);
|
||||||
viewport.y = Cast<f32>(internalResolution.height);
|
viewport.y = static_cast<f32>(internalResolution.height);
|
||||||
scissor.extent = internalResolution;
|
scissor.extent = internalResolution;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -488,7 +488,7 @@ main(int, char **)
|
||||||
camYaw = camYaw - floor((camYaw + 180.0f) / 360.0f) * 360.0f;
|
camYaw = camYaw - floor((camYaw + 180.0f) / 360.0f) * 360.0f;
|
||||||
cameraController.SetPitchYaw(glm::radians(camPitch), glm::radians(camYaw));
|
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);
|
cameraController.SetPosition(camPosition);
|
||||||
}
|
}
|
||||||
|
|
@ -512,7 +512,7 @@ main(int, char **)
|
||||||
if (rotating)
|
if (rotating)
|
||||||
{
|
{
|
||||||
model.SetModelTransform(
|
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();
|
model.Update();
|
||||||
cameraController.m_Camera.CalculateInverses();
|
cameraController.m_Camera.CalculateInverses();
|
||||||
|
|
@ -584,7 +584,7 @@ main(int, char **)
|
||||||
vk::RenderingInfo renderingInfo = {
|
vk::RenderingInfo renderingInfo = {
|
||||||
.renderArea = {.extent = ToExtent2D(currentAttachment->m_Extent)},
|
.renderArea = {.extent = ToExtent2D(currentAttachment->m_Extent)},
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
.colorAttachmentCount = Cast<u32>(attachmentInfos.size()),
|
.colorAttachmentCount = static_cast<u32>(attachmentInfos.size()),
|
||||||
.pColorAttachments = attachmentInfos.data(),
|
.pColorAttachments = attachmentInfos.data(),
|
||||||
.pDepthAttachment = &depthAttachment,
|
.pDepthAttachment = &depthAttachment,
|
||||||
};
|
};
|
||||||
|
|
@ -637,7 +637,7 @@ main(int, char **)
|
||||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
|
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
|
||||||
sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
|
sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
|
||||||
innerPcbOffset += sizeof 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);
|
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, backGroundPipeline.m_Pipeline);
|
||||||
|
|
@ -670,7 +670,7 @@ main(int, char **)
|
||||||
.dstOffsets =
|
.dstOffsets =
|
||||||
std::array{
|
std::array{
|
||||||
vk::Offset3D{0, 0, 0},
|
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,
|
cmd.blitImage(currentImage, postRenderBarriers[0].newLayout, currentSwapchainImage,
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ Nodes::operator[](const u32 index)
|
||||||
u32
|
u32
|
||||||
Nodes::Count() const
|
Nodes::Count() const
|
||||||
{
|
{
|
||||||
return Cast<u32>(m_Transforms.size());
|
return static_cast<u32>(m_Transforms.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
usize
|
usize
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems:
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
|
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
|
||||||
.pBindings = descriptorSetLayoutBindings.data(),
|
.pBindings = descriptorSetLayoutBindings.data(),
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayout descriptorSetLayout;
|
vk::DescriptorSetLayout descriptorSetLayout;
|
||||||
|
|
@ -76,7 +76,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems:
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
||||||
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
|
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
|
||||||
.pSetLayouts = descriptorSetLayouts.data(),
|
.pSetLayouts = descriptorSetLayouts.data(),
|
||||||
.pushConstantRangeCount = 1,
|
.pushConstantRangeCount = 1,
|
||||||
.pPushConstantRanges = &pushConstantRange,
|
.pPushConstantRanges = &pushConstantRange,
|
||||||
|
|
@ -139,7 +139,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems:
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
||||||
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
|
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
|
||||||
.pDynamicStates = dynamicStates.data(),
|
.pDynamicStates = dynamicStates.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -152,7 +152,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const systems:
|
||||||
|
|
||||||
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
||||||
.pNext = &renderingCreateInfo,
|
.pNext = &renderingCreateInfo,
|
||||||
.stageCount = Cast<u32>(shaderStages.size()),
|
.stageCount = static_cast<u32>(shaderStages.size()),
|
||||||
.pStages = shaderStages.data(),
|
.pStages = shaderStages.data(),
|
||||||
.pVertexInputState = &vertexInputStateCreateInfo,
|
.pVertexInputState = &vertexInputStateCreateInfo,
|
||||||
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
||||||
|
|
@ -221,7 +221,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
|
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
|
||||||
.pBindings = descriptorSetLayoutBindings.data(),
|
.pBindings = descriptorSetLayoutBindings.data(),
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayout descriptorSetLayout;
|
vk::DescriptorSetLayout descriptorSetLayout;
|
||||||
|
|
@ -237,7 +237,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
||||||
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
|
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
|
||||||
.pSetLayouts = descriptorSetLayouts.data(),
|
.pSetLayouts = descriptorSetLayouts.data(),
|
||||||
.pushConstantRangeCount = 1,
|
.pushConstantRangeCount = 1,
|
||||||
.pPushConstantRanges = &pushConstantRange,
|
.pPushConstantRanges = &pushConstantRange,
|
||||||
|
|
@ -300,7 +300,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
||||||
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
|
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
|
||||||
.pDynamicStates = dynamicStates.data(),
|
.pDynamicStates = dynamicStates.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -313,7 +313,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
|
||||||
|
|
||||||
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
||||||
.pNext = &renderingCreateInfo,
|
.pNext = &renderingCreateInfo,
|
||||||
.stageCount = Cast<u32>(shaderStages.size()),
|
.stageCount = static_cast<u32>(shaderStages.size()),
|
||||||
.pStages = shaderStages.data(),
|
.pStages = shaderStages.data(),
|
||||||
.pVertexInputState = &vertexInputStateCreateInfo,
|
.pVertexInputState = &vertexInputStateCreateInfo,
|
||||||
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
||||||
|
|
|
||||||
|
|
@ -102,8 +102,8 @@ AssetLoader::LoadHdrImage(Texture *texture, cstr path, cstr name) const
|
||||||
ERROR_IF(!data, "Could not load {}", path) THEN_ABORT(-1);
|
ERROR_IF(!data, "Could not load {}", path) THEN_ABORT(-1);
|
||||||
assert(nChannels == 3);
|
assert(nChannels == 3);
|
||||||
|
|
||||||
u32 width = Cast<u32>(x);
|
u32 width = static_cast<u32>(x);
|
||||||
u32 height = Cast<u32>(y);
|
u32 height = static_cast<u32>(y);
|
||||||
|
|
||||||
StagingBuffer stagingBuffer;
|
StagingBuffer stagingBuffer;
|
||||||
texture->Init(m_ResourceManager->m_Device, {width, height}, vk::Format::eR32G32B32A32Sfloat, false, path);
|
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 = {
|
vk::DependencyInfo imageStartDependency = {
|
||||||
.imageMemoryBarrierCount = Cast<u32>(startBarriers.size()),
|
.imageMemoryBarrierCount = static_cast<u32>(startBarriers.size()),
|
||||||
.pImageMemoryBarriers = startBarriers.data(),
|
.pImageMemoryBarriers = startBarriers.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -362,8 +362,8 @@ GenerateMipMaps(vk::CommandBuffer commandBuffer, Texture *texture, vk::ImageLayo
|
||||||
|
|
||||||
commandBuffer.pipelineBarrier2(&imageStartDependency);
|
commandBuffer.pipelineBarrier2(&imageStartDependency);
|
||||||
|
|
||||||
i32 prevMipWidth = Cast<i32>(texture->m_Extent.width);
|
i32 prevMipWidth = static_cast<i32>(texture->m_Extent.width);
|
||||||
i32 prevMipHeight = Cast<i32>(texture->m_Extent.height);
|
i32 prevMipHeight = static_cast<i32>(texture->m_Extent.height);
|
||||||
|
|
||||||
u32 maxPrevMip = texture->GetMipLevels() - 1;
|
u32 maxPrevMip = texture->GetMipLevels() - 1;
|
||||||
for (u32 prevMipLevel = 0; prevMipLevel < maxPrevMip; ++prevMipLevel)
|
for (u32 prevMipLevel = 0; prevMipLevel < maxPrevMip; ++prevMipLevel)
|
||||||
|
|
@ -404,8 +404,8 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image
|
||||||
assert(image->component == 4);
|
assert(image->component == 4);
|
||||||
assert(image->height > 0 && image->width > 0);
|
assert(image->height > 0 && image->width > 0);
|
||||||
|
|
||||||
u32 height = Cast<u32>(image->height);
|
u32 height = static_cast<u32>(image->height);
|
||||||
u32 width = Cast<u32>(image->width);
|
u32 width = static_cast<u32>(image->width);
|
||||||
|
|
||||||
vk::Format imageFormat = isSrgb ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm;
|
vk::Format imageFormat = isSrgb ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm;
|
||||||
|
|
||||||
|
|
@ -481,8 +481,8 @@ AssetLoader::LoadImageToGpu(StagingBuffer *stagingBuffer, tinygltf::Image *image
|
||||||
|
|
||||||
vk::BufferImageCopy2 imageCopy = {
|
vk::BufferImageCopy2 imageCopy = {
|
||||||
.bufferOffset = 0,
|
.bufferOffset = 0,
|
||||||
.bufferRowLength = Cast<u32>(image->width),
|
.bufferRowLength = static_cast<u32>(image->width),
|
||||||
.bufferImageHeight = Cast<u32>(image->height),
|
.bufferImageHeight = static_cast<u32>(image->height),
|
||||||
.imageSubresource =
|
.imageSubresource =
|
||||||
{
|
{
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||||
|
|
@ -558,8 +558,8 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
|
||||||
if (node->mesh >= 0)
|
if (node->mesh >= 0)
|
||||||
{
|
{
|
||||||
auto *mesh = &model->meshes[node->mesh];
|
auto *mesh = &model->meshes[node->mesh];
|
||||||
u32 vertexOffset = Cast<u32>(vertexPositions->size());
|
u32 vertexOffset = static_cast<u32>(vertexPositions->size());
|
||||||
u32 indexOffset = Cast<u32>(indices->size());
|
u32 indexOffset = static_cast<u32>(indices->size());
|
||||||
for (auto &prim : mesh->primitives)
|
for (auto &prim : mesh->primitives)
|
||||||
{
|
{
|
||||||
u32 vertexCount = 0;
|
u32 vertexCount = 0;
|
||||||
|
|
@ -577,17 +577,17 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
|
||||||
tinygltf::Buffer *posBuffer = &model->buffers[posBufferView->buffer];
|
tinygltf::Buffer *posBuffer = &model->buffers[posBufferView->buffer];
|
||||||
usize byteOffset = (posAccessor->byteOffset + posBufferView->byteOffset);
|
usize byteOffset = (posAccessor->byteOffset + posBufferView->byteOffset);
|
||||||
|
|
||||||
vertexCount = Cast<u32>(posAccessor->count);
|
vertexCount = static_cast<u32>(posAccessor->count);
|
||||||
vertexPositions->reserve(vertexOffset + vertexCount);
|
vertexPositions->reserve(vertexOffset + vertexCount);
|
||||||
|
|
||||||
if (posAccessor->type == TINYGLTF_TYPE_VEC4)
|
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);
|
vertexPositions->insert(vertexPositions->end(), data, data + vertexCount);
|
||||||
}
|
}
|
||||||
else if (posAccessor->type == TINYGLTF_TYPE_VEC3)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
vertexPositions->push_back(vec4(data[i], 1.0f));
|
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)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
vertexPositions->push_back(vec4(data[i], 0.0f, 1.0f));
|
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)
|
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;
|
vec4 *end = data + vertexCount;
|
||||||
u32 idx = vertexOffset;
|
u32 idx = vertexOffset;
|
||||||
|
|
@ -631,7 +631,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
|
||||||
}
|
}
|
||||||
else if (normAccessor->type == TINYGLTF_TYPE_VEC3)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
auto norm = vec4(data[i], 0.0f);
|
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)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
auto norm = vec4(data[i], 0.0f, 0.0f);
|
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 &&
|
assert(uvAccessor->type == TINYGLTF_TYPE_VEC2 &&
|
||||||
uvAccessor->componentType == TINYGLTF_COMPONENT_TYPE_FLOAT);
|
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;
|
vec2 *end = data + vertexCount;
|
||||||
u32 idx = vertexOffset;
|
u32 idx = vertexOffset;
|
||||||
vec2 *it = data;
|
vec2 *it = data;
|
||||||
|
|
@ -686,7 +686,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
|
||||||
|
|
||||||
if (colorAccessor->type == TINYGLTF_TYPE_VEC4)
|
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;
|
vec4 *end = data + vertexCount;
|
||||||
u32 idx = vertexOffset;
|
u32 idx = vertexOffset;
|
||||||
|
|
@ -698,7 +698,7 @@ AssetLoader::ProcessNode(tinygltf::Model *model, eastl::vector<vec4> *vertexPosi
|
||||||
}
|
}
|
||||||
else if (colorAccessor->type == TINYGLTF_TYPE_VEC3)
|
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)
|
for (u32 i = 0; i < vertexCount; ++i)
|
||||||
{
|
{
|
||||||
auto color = vec4(data[i], 1.0f);
|
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];
|
tinygltf::Buffer *indexBuffer = &model->buffers[indexBufferView->buffer];
|
||||||
usize byteOffset = (indexAccessor->byteOffset + indexBufferView->byteOffset);
|
usize byteOffset = (indexAccessor->byteOffset + indexBufferView->byteOffset);
|
||||||
|
|
||||||
indexCount = Cast<u32>(indexAccessor->count);
|
indexCount = static_cast<u32>(indexAccessor->count);
|
||||||
indices->reserve(indexOffset + indexCount);
|
indices->reserve(indexOffset + indexCount);
|
||||||
|
|
||||||
if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT)
|
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);
|
indices->insert(indices->end(), data, data + indexCount);
|
||||||
}
|
}
|
||||||
else if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
|
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);
|
indices->insert(indices->end(), data, data + indexCount);
|
||||||
}
|
}
|
||||||
else if (indexAccessor->componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)
|
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);
|
indices->insert(indices->end(), data, data + indexCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -860,7 +860,7 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
return materialFind->second;
|
return materialFind->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 index = Cast<u32>(materials.size());
|
u32 index = static_cast<u32>(materials.size());
|
||||||
auto *material = &model.materials[materialIdx];
|
auto *material = &model.materials[materialIdx];
|
||||||
|
|
||||||
f32 alphaBlendValue = -1;
|
f32 alphaBlendValue = -1;
|
||||||
|
|
@ -870,14 +870,14 @@ AssetLoader::LoadModelToGpu(cstr path, cstr name)
|
||||||
}
|
}
|
||||||
else if (material->alphaMode == "MASK")
|
else if (material->alphaMode == "MASK")
|
||||||
{
|
{
|
||||||
alphaBlendValue = Cast<f32>(material->alphaCutoff);
|
alphaBlendValue = static_cast<f32>(material->alphaCutoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
materials.push_back({
|
materials.push_back({
|
||||||
.m_AlbedoFactor = VectorToVec4(material->pbrMetallicRoughness.baseColorFactor),
|
.m_AlbedoFactor = VectorToVec4(material->pbrMetallicRoughness.baseColorFactor),
|
||||||
.m_EmissionFactor = VectorToVec3(material->emissiveFactor),
|
.m_EmissionFactor = VectorToVec3(material->emissiveFactor),
|
||||||
.m_MetalFactor = Cast<f32>(material->pbrMetallicRoughness.metallicFactor),
|
.m_MetalFactor = static_cast<f32>(material->pbrMetallicRoughness.metallicFactor),
|
||||||
.m_RoughFactor = Cast<f32>(material->pbrMetallicRoughness.roughnessFactor),
|
.m_RoughFactor = static_cast<f32>(material->pbrMetallicRoughness.roughnessFactor),
|
||||||
.m_AlbedoTex = getTextureHandle(material->pbrMetallicRoughness.baseColorTexture.index, true),
|
.m_AlbedoTex = getTextureHandle(material->pbrMetallicRoughness.baseColorTexture.index, true),
|
||||||
.m_NormalTex = getTextureHandle(material->normalTexture.index, false),
|
.m_NormalTex = getTextureHandle(material->normalTexture.index, false),
|
||||||
.m_MetalRoughTex = getTextureHandle(material->pbrMetallicRoughness.metallicRoughnessTexture.index, false),
|
.m_MetalRoughTex = getTextureHandle(material->pbrMetallicRoughness.metallicRoughnessTexture.index, false),
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ CreateEnvironment(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cu
|
||||||
readyToWriteBarriers[3].subresourceRange = lutSubresRange;
|
readyToWriteBarriers[3].subresourceRange = lutSubresRange;
|
||||||
|
|
||||||
vk::DependencyInfo readyToWriteDependency = {
|
vk::DependencyInfo readyToWriteDependency = {
|
||||||
.imageMemoryBarrierCount = Cast<u32>(readyToWriteBarriers.size()),
|
.imageMemoryBarrierCount = static_cast<u32>(readyToWriteBarriers.size()),
|
||||||
.pImageMemoryBarriers = readyToWriteBarriers.data(),
|
.pImageMemoryBarriers = readyToWriteBarriers.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -197,7 +197,7 @@ CreateEnvironment(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cu
|
||||||
vk::PushConstantRange pcr = {
|
vk::PushConstantRange pcr = {
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
.stageFlags = vk::ShaderStageFlagBits::eCompute,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = Cast<u32>(eastl::max(eastl::max(sizeof(SkyboxPushConstants), sizeof(BrdfLutPushConstants)),
|
.size = static_cast<u32>(eastl::max(eastl::max(sizeof(SkyboxPushConstants), sizeof(BrdfLutPushConstants)),
|
||||||
eastl::max(sizeof(DiffuseIrradiancePushConstants), sizeof(PrefilterPushConstants)))),
|
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;
|
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,
|
computePipelineCreateInfo.data(), nullptr,
|
||||||
pipelines.data()));
|
pipelines.data()));
|
||||||
|
|
||||||
|
|
@ -331,7 +331,7 @@ CreateEnvironment(AssetLoader *assetLoader, vk::Queue computeQueue, const u32 cu
|
||||||
{
|
{
|
||||||
prefilterPushConstants.m_OutputTexture = tex;
|
prefilterPushConstants.m_OutputTexture = tex;
|
||||||
prefilterPushConstants.m_CubeSide = mipSize;
|
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,
|
cmd.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof prefilterPushConstants,
|
||||||
&prefilterPushConstants);
|
&prefilterPushConstants);
|
||||||
u32 groupCount = eastl::max(mipSize / 16u, 1u);
|
u32 groupCount = eastl::max(mipSize / 16u, 1u);
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,10 @@ static_assert(Light::COLOR_MASK == 0xFFFFFF00);
|
||||||
inline u32
|
inline u32
|
||||||
ToColor32(const vec4 &col)
|
ToColor32(const vec4 &col)
|
||||||
{
|
{
|
||||||
const u32 r = Cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
|
const u32 r = static_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 g = static_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 b = static_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 a = static_cast<u32>(eastl::min(col.a, 1.0f) * 255.99f);
|
||||||
|
|
||||||
return r << 24 | g << 16 | b << 8 | a;
|
return r << 24 | g << 16 | b << 8 | a;
|
||||||
}
|
}
|
||||||
|
|
@ -67,9 +67,9 @@ ToColor32(const vec4 &col)
|
||||||
inline u32
|
inline u32
|
||||||
ToColor32(const vec3 &col)
|
ToColor32(const vec3 &col)
|
||||||
{
|
{
|
||||||
const u32 r = Cast<u32>(eastl::min(col.r, 1.0f) * 255.99f);
|
const u32 r = static_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 g = static_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 b = static_cast<u32>(eastl::min(col.b, 1.0f) * 255.99f);
|
||||||
constexpr u32 a = 255;
|
constexpr u32 a = 255;
|
||||||
|
|
||||||
return r << 24 | g << 16 | b << 8 | a;
|
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;
|
m_GpuBufferCapacity_ |= UPDATE_REQUIRED_BIT;
|
||||||
|
|
||||||
return {Light::TYPE_POINT, gen, Cast<u16>(index)};
|
return {Light::TYPE_POINT, gen, static_cast<u16>(index)};
|
||||||
}
|
}
|
||||||
++light;
|
++light;
|
||||||
}
|
}
|
||||||
|
|
@ -236,7 +236,7 @@ LightManager::AddPoint(const vec3 &position, const vec3 &color, const f32 radius
|
||||||
void
|
void
|
||||||
LightManager::Update()
|
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)
|
if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity)
|
||||||
{
|
{
|
||||||
m_GpuBufferCapacity_ = requiredBufferCapacity | UPDATE_REQUIRED_BIT;
|
m_GpuBufferCapacity_ = requiredBufferCapacity | UPDATE_REQUIRED_BIT;
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ struct LightManager
|
||||||
// Using lower bit. Capacity can be directly a multiple of 2
|
// Using lower bit. Capacity can be directly a multiple of 2
|
||||||
// Thus, range is up to MaxValue<u16>
|
// Thus, range is up to MaxValue<u16>
|
||||||
constexpr static u16 UPDATE_REQUIRED_BIT = 1;
|
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 AddDirectional(const vec3 &direction, const vec3 &color, f32 intensity);
|
||||||
LightHandle AddPoint(const vec3 &position, const vec3 &color, f32 radius, f32 intensity);
|
LightHandle AddPoint(const vec3 &position, const vec3 &color, f32 radius, f32 intensity);
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ main(int, char *[])
|
||||||
internalResolution.width = (internalResolution.height * INIT_WIDTH) / INIT_HEIGHT;
|
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,
|
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());
|
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ main(int, char *[])
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
|
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));
|
AbortIfFailed(device.m_Device.createDescriptorPool(&descriptorPoolCreateInfo, nullptr, &descriptorPool));
|
||||||
|
|
||||||
vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
|
vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
|
||||||
|
|
@ -164,14 +164,14 @@ main(int, char *[])
|
||||||
.pBufferInfo = &camLightBufferInfo,
|
.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
|
// Persistent variables
|
||||||
vk::Viewport viewport = {
|
vk::Viewport viewport = {
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = Cast<f32>(internalResolution.height),
|
.y = static_cast<f32>(internalResolution.height),
|
||||||
.width = Cast<f32>(internalResolution.width),
|
.width = static_cast<f32>(internalResolution.width),
|
||||||
.height = -Cast<f32>(internalResolution.height),
|
.height = -static_cast<f32>(internalResolution.height),
|
||||||
.minDepth = 0.0,
|
.minDepth = 0.0,
|
||||||
.maxDepth = 1.0,
|
.maxDepth = 1.0,
|
||||||
};
|
};
|
||||||
|
|
@ -232,7 +232,7 @@ main(int, char *[])
|
||||||
acquireToTransferDstBarrier,
|
acquireToTransferDstBarrier,
|
||||||
};
|
};
|
||||||
vk::DependencyInfo postRenderDependencies = {
|
vk::DependencyInfo postRenderDependencies = {
|
||||||
.imageMemoryBarrierCount = Cast<u32>(postRenderBarriers.size()),
|
.imageMemoryBarrierCount = static_cast<u32>(postRenderBarriers.size()),
|
||||||
.pImageMemoryBarriers = postRenderBarriers.data(),
|
.pImageMemoryBarriers = postRenderBarriers.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -314,13 +314,13 @@ main(int, char *[])
|
||||||
|
|
||||||
swapchain.RegisterResizeCallback(
|
swapchain.RegisterResizeCallback(
|
||||||
[&cameraController, &internalResolution, &viewport, &scissor](vk::Extent2D extent) {
|
[&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.y = static_cast<f32>(internalResolution.height);
|
||||||
viewport.width = Cast<f32>(internalResolution.width);
|
viewport.width = static_cast<f32>(internalResolution.width);
|
||||||
viewport.height = -Cast<f32>(internalResolution.height);
|
viewport.height = -static_cast<f32>(internalResolution.height);
|
||||||
scissor.extent = internalResolution;
|
scissor.extent = internalResolution;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -354,7 +354,7 @@ main(int, char *[])
|
||||||
// for (auto [entity, dynTrans] : rootModel.each())
|
// for (auto [entity, dynTrans] : rootModel.each())
|
||||||
//{
|
//{
|
||||||
// dynTrans.m_Rotation =
|
// 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});
|
// 0.0f});
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
@ -417,7 +417,7 @@ main(int, char *[])
|
||||||
registry.get<CGlobalTransform>(parent.m_ParentEntity).m_Transform * translation * rotation * scale;
|
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();
|
nodeData.clear();
|
||||||
nodeDrawInfo.clear();
|
nodeDrawInfo.clear();
|
||||||
nodeData.reserve(objectCount);
|
nodeData.reserve(objectCount);
|
||||||
|
|
@ -474,7 +474,7 @@ main(int, char *[])
|
||||||
vk::RenderingInfo renderingInfo = {
|
vk::RenderingInfo renderingInfo = {
|
||||||
.renderArea = {.extent = ToExtent2D(currentAttachment->m_Extent)},
|
.renderArea = {.extent = ToExtent2D(currentAttachment->m_Extent)},
|
||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
.colorAttachmentCount = Cast<u32>(attachmentInfos.size()),
|
.colorAttachmentCount = static_cast<u32>(attachmentInfos.size()),
|
||||||
.pColorAttachments = attachmentInfos.data(),
|
.pColorAttachments = attachmentInfos.data(),
|
||||||
.pDepthAttachment = &depthAttachment,
|
.pDepthAttachment = &depthAttachment,
|
||||||
};
|
};
|
||||||
|
|
@ -531,7 +531,7 @@ main(int, char *[])
|
||||||
.dstOffsets =
|
.dstOffsets =
|
||||||
std::array{
|
std::array{
|
||||||
vk::Offset3D{0, 0, 0},
|
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,
|
cmd.blitImage(currentImage, postRenderBarriers[0].newLayout, currentSwapchainImage,
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const RenderRe
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
|
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
|
||||||
.pBindings = descriptorSetLayoutBindings.data(),
|
.pBindings = descriptorSetLayoutBindings.data(),
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayout descriptorSetLayout;
|
vk::DescriptorSetLayout descriptorSetLayout;
|
||||||
|
|
@ -62,7 +62,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const RenderRe
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
||||||
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
|
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
|
||||||
.pSetLayouts = descriptorSetLayouts.data(),
|
.pSetLayouts = descriptorSetLayouts.data(),
|
||||||
.pushConstantRangeCount = 1,
|
.pushConstantRangeCount = 1,
|
||||||
.pPushConstantRanges = &pushConstantRange,
|
.pPushConstantRanges = &pushConstantRange,
|
||||||
|
|
@ -125,7 +125,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const RenderRe
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
||||||
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
|
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
|
||||||
.pDynamicStates = dynamicStates.data(),
|
.pDynamicStates = dynamicStates.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ CreatePipeline(const Device *device, vk::Format attachmentFormat, const RenderRe
|
||||||
|
|
||||||
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
||||||
.pNext = &renderingCreateInfo,
|
.pNext = &renderingCreateInfo,
|
||||||
.stageCount = Cast<u32>(shaderStages.size()),
|
.stageCount = static_cast<u32>(shaderStages.size()),
|
||||||
.pStages = shaderStages.data(),
|
.pStages = shaderStages.data(),
|
||||||
.pVertexInputState = &vertexInputStateCreateInfo,
|
.pVertexInputState = &vertexInputStateCreateInfo,
|
||||||
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
||||||
|
|
@ -197,7 +197,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
.bindingCount = Cast<u32>(descriptorSetLayoutBindings.size()),
|
.bindingCount = static_cast<u32>(descriptorSetLayoutBindings.size()),
|
||||||
.pBindings = descriptorSetLayoutBindings.data(),
|
.pBindings = descriptorSetLayoutBindings.data(),
|
||||||
};
|
};
|
||||||
vk::DescriptorSetLayout descriptorSetLayout;
|
vk::DescriptorSetLayout descriptorSetLayout;
|
||||||
|
|
@ -213,7 +213,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
||||||
.setLayoutCount = Cast<u32>(descriptorSetLayouts.size()),
|
.setLayoutCount = static_cast<u32>(descriptorSetLayouts.size()),
|
||||||
.pSetLayouts = descriptorSetLayouts.data(),
|
.pSetLayouts = descriptorSetLayouts.data(),
|
||||||
.pushConstantRangeCount = 1,
|
.pushConstantRangeCount = 1,
|
||||||
.pPushConstantRanges = &pushConstantRange,
|
.pPushConstantRanges = &pushConstantRange,
|
||||||
|
|
@ -276,7 +276,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
|
||||||
.dynamicStateCount = Cast<u32>(dynamicStates.size()),
|
.dynamicStateCount = static_cast<u32>(dynamicStates.size()),
|
||||||
.pDynamicStates = dynamicStates.data(),
|
.pDynamicStates = dynamicStates.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -289,7 +289,7 @@ CreateBackgroundPipeline(const Device *device, vk::Format attachmentFormat, cons
|
||||||
|
|
||||||
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
|
||||||
.pNext = &renderingCreateInfo,
|
.pNext = &renderingCreateInfo,
|
||||||
.stageCount = Cast<u32>(shaderStages.size()),
|
.stageCount = static_cast<u32>(shaderStages.size()),
|
||||||
.pStages = shaderStages.data(),
|
.pStages = shaderStages.data(),
|
||||||
.pVertexInputState = &vertexInputStateCreateInfo,
|
.pVertexInputState = &vertexInputStateCreateInfo,
|
||||||
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
.pInputAssemblyState = &inputAssemblyStateCreateInfo,
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ TextureManager::Commit(Texture *texture)
|
||||||
Texture *allocatedTexture = &m_Textures[index];
|
Texture *allocatedTexture = &m_Textures[index];
|
||||||
|
|
||||||
assert(!allocatedTexture->IsValid());
|
assert(!allocatedTexture->IsValid());
|
||||||
m_FreeHead = *Recast<u32 *>(allocatedTexture);
|
m_FreeHead = *reinterpret_cast<u32 *>(allocatedTexture);
|
||||||
|
|
||||||
// Ensure it is copyable.
|
// Ensure it is copyable.
|
||||||
static_assert(std::is_trivially_copyable_v<Texture>);
|
static_assert(std::is_trivially_copyable_v<Texture>);
|
||||||
|
|
@ -45,7 +45,7 @@ TextureManager::Commit(Texture *texture)
|
||||||
return {index};
|
return {index};
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 index = Cast<u32>(m_Textures.size());
|
const u32 index = static_cast<u32>(m_Textures.size());
|
||||||
if (index < m_MaxCapacity)
|
if (index < m_MaxCapacity)
|
||||||
{
|
{
|
||||||
Texture *allocatedTexture = &m_Textures.push_back();
|
Texture *allocatedTexture = &m_Textures.push_back();
|
||||||
|
|
@ -79,7 +79,7 @@ TextureManager::Release(const Device *device, const TextureHandle handle)
|
||||||
allocatedTexture->Destroy(device);
|
allocatedTexture->Destroy(device);
|
||||||
|
|
||||||
assert(!allocatedTexture->IsValid());
|
assert(!allocatedTexture->IsValid());
|
||||||
*Recast<u32 *>(allocatedTexture) = m_FreeHead;
|
*reinterpret_cast<u32 *>(allocatedTexture) = m_FreeHead;
|
||||||
|
|
||||||
m_FreeHead = handle.m_Index;
|
m_FreeHead = handle.m_Index;
|
||||||
}
|
}
|
||||||
|
|
@ -104,10 +104,10 @@ BufferManager::Init(const u32 maxCapacity)
|
||||||
Buffer *pIter = m_Buffers;
|
Buffer *pIter = m_Buffers;
|
||||||
for (u32 i = 1; i < m_MaxCapacity; ++i)
|
for (u32 i = 1; i < m_MaxCapacity; ++i)
|
||||||
{
|
{
|
||||||
*Recast<u32 *>(pIter) = i;
|
*reinterpret_cast<u32 *>(pIter) = i;
|
||||||
++pIter;
|
++pIter;
|
||||||
}
|
}
|
||||||
*Recast<u32 *>(pIter) = GpuResourceHandle::INVALID_HANDLE;
|
*reinterpret_cast<u32 *>(pIter) = GpuResourceHandle::INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferHandle
|
BufferHandle
|
||||||
|
|
@ -132,7 +132,7 @@ BufferManager::Commit_(StorageBuffer *buffer)
|
||||||
Buffer *allocatedBuffer = &m_Buffers[index];
|
Buffer *allocatedBuffer = &m_Buffers[index];
|
||||||
|
|
||||||
assert(!allocatedBuffer->IsValid());
|
assert(!allocatedBuffer->IsValid());
|
||||||
m_FreeHead = *Recast<u32 *>(allocatedBuffer);
|
m_FreeHead = *reinterpret_cast<u32 *>(allocatedBuffer);
|
||||||
|
|
||||||
// Ensure it is copyable.
|
// Ensure it is copyable.
|
||||||
static_assert(std::is_trivially_copyable_v<StorageBuffer>);
|
static_assert(std::is_trivially_copyable_v<StorageBuffer>);
|
||||||
|
|
@ -149,7 +149,7 @@ BufferManager::Fetch(const BufferHandle handle)
|
||||||
{
|
{
|
||||||
assert(!handle.IsInvalid());
|
assert(!handle.IsInvalid());
|
||||||
|
|
||||||
return Recast<StorageBuffer *>(&m_Buffers[handle.m_Index]);
|
return reinterpret_cast<StorageBuffer *>(&m_Buffers[handle.m_Index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -161,7 +161,7 @@ BufferManager::Release(const Device *device, const BufferHandle handle)
|
||||||
allocatedBuffer->Destroy(device);
|
allocatedBuffer->Destroy(device);
|
||||||
|
|
||||||
assert(!allocatedBuffer->IsValid());
|
assert(!allocatedBuffer->IsValid());
|
||||||
*Recast<u32 *>(allocatedBuffer) = m_FreeHead;
|
*reinterpret_cast<u32 *>(allocatedBuffer) = m_FreeHead;
|
||||||
|
|
||||||
m_FreeHead = handle.m_Index;
|
m_FreeHead = handle.m_Index;
|
||||||
}
|
}
|
||||||
|
|
@ -196,7 +196,7 @@ StorageTextureManager::Fetch(const StorageTextureHandle handle)
|
||||||
{
|
{
|
||||||
assert(!handle.IsInvalid());
|
assert(!handle.IsInvalid());
|
||||||
|
|
||||||
return Recast<StorageTexture *>(&m_Textures[handle.m_Index]);
|
return reinterpret_cast<StorageTexture *>(&m_Textures[handle.m_Index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -215,15 +215,15 @@ HashSamplerCreateInfo(const vk::SamplerCreateInfo *createInfo)
|
||||||
hash = HashCombine(hash, HashAny(createInfo->addressModeU));
|
hash = HashCombine(hash, HashAny(createInfo->addressModeU));
|
||||||
hash = HashCombine(hash, HashAny(createInfo->addressModeV));
|
hash = HashCombine(hash, HashAny(createInfo->addressModeV));
|
||||||
hash = HashCombine(hash, HashAny(createInfo->addressModeW));
|
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(createInfo->anisotropyEnable));
|
||||||
hash = HashCombine(hash,
|
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->compareEnable));
|
||||||
hash = HashCombine(hash, HashAny(createInfo->compareOp));
|
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,
|
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->borderColor));
|
||||||
hash = HashCombine(hash, HashAny(createInfo->unnormalizedCoordinates));
|
hash = HashCombine(hash, HashAny(createInfo->unnormalizedCoordinates));
|
||||||
|
|
||||||
|
|
@ -253,7 +253,7 @@ SamplerManager::Create(const Device *device, const vk::SamplerCreateInfo *create
|
||||||
|
|
||||||
vk::Sampler sampler;
|
vk::Sampler sampler;
|
||||||
AbortIfFailed(device->m_Device.createSampler(createInfo, nullptr, &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_SamplerHashes.push_back(hash);
|
||||||
m_Samplers.push_back(sampler);
|
m_Samplers.push_back(sampler);
|
||||||
return {index};
|
return {index};
|
||||||
|
|
@ -293,7 +293,7 @@ VirtualizedBufferPool::InitStorage(const Device *device, usize bufferMaxSize)
|
||||||
const VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {
|
const VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {
|
||||||
.size = bufferMaxSize,
|
.size = bufferMaxSize,
|
||||||
};
|
};
|
||||||
AbortIfFailed(Cast<vk::Result>(vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_Block)));
|
AbortIfFailed(static_cast<vk::Result>(vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_Block)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -311,7 +311,7 @@ VirtualizedBufferPool::InitIndex(const Device *device, usize bufferMaxSize)
|
||||||
const VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {
|
const VmaVirtualBlockCreateInfo virtualBlockCreateInfo = {
|
||||||
.size = bufferMaxSize,
|
.size = bufferMaxSize,
|
||||||
};
|
};
|
||||||
AbortIfFailed(Cast<vk::Result>(vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_Block)));
|
AbortIfFailed(static_cast<vk::Result>(vmaCreateVirtualBlock(&virtualBlockCreateInfo, &m_Block)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -343,11 +343,11 @@ VirtualizedBufferPool::Create(usize size, usize alignment)
|
||||||
index = m_FreeHead;
|
index = m_FreeHead;
|
||||||
allocVBuf = &m_VirtualBuffers[index];
|
allocVBuf = &m_VirtualBuffers[index];
|
||||||
|
|
||||||
m_FreeHead = *Recast<u32 *>(allocVBuf);
|
m_FreeHead = *reinterpret_cast<u32 *>(allocVBuf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
index = Cast<u32>(m_VirtualBuffers.size());
|
index = static_cast<u32>(m_VirtualBuffers.size());
|
||||||
allocVBuf = &m_VirtualBuffers.push_back();
|
allocVBuf = &m_VirtualBuffers.push_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,7 +374,7 @@ VirtualizedBufferPool::Release(VirtualizedBufferHandle handle)
|
||||||
VirtualBuffer *virtualBuffer = &m_VirtualBuffers[handle.m_Index];
|
VirtualBuffer *virtualBuffer = &m_VirtualBuffers[handle.m_Index];
|
||||||
vmaVirtualFree(m_Block, virtualBuffer->m_Allocation);
|
vmaVirtualFree(m_Block, virtualBuffer->m_Allocation);
|
||||||
|
|
||||||
*Recast<u32 *>(virtualBuffer) = m_FreeHead;
|
*reinterpret_cast<u32 *>(virtualBuffer) = m_FreeHead;
|
||||||
|
|
||||||
m_FreeHead = handle.m_Index;
|
m_FreeHead = handle.m_Index;
|
||||||
}
|
}
|
||||||
|
|
@ -656,7 +656,7 @@ RenderResourceManager::Update()
|
||||||
// Descriptor Updates
|
// Descriptor Updates
|
||||||
if (!m_Writes.empty())
|
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_Writes.clear();
|
||||||
m_WriteInfos.clear();
|
m_WriteInfos.clear();
|
||||||
|
|
@ -674,10 +674,10 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
|
||||||
vk::PhysicalDeviceProperties properties;
|
vk::PhysicalDeviceProperties properties;
|
||||||
m_Device->m_PhysicalDevice.getProperties(&properties);
|
m_Device->m_PhysicalDevice.getProperties(&properties);
|
||||||
|
|
||||||
u32 buffersCount = eastl::min(properties.limits.maxPerStageDescriptorStorageBuffers - 1024, Cast<u32>(maxSize));
|
u32 buffersCount = eastl::min(properties.limits.maxPerStageDescriptorStorageBuffers - 1024, static_cast<u32>(maxSize));
|
||||||
u32 texturesCount = eastl::min(properties.limits.maxPerStageDescriptorSampledImages - 1024, Cast<u32>(maxSize));
|
u32 texturesCount = eastl::min(properties.limits.maxPerStageDescriptorSampledImages - 1024, static_cast<u32>(maxSize));
|
||||||
u32 storageTexturesCount =
|
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 Buffer Count: {}", buffersCount);
|
||||||
INFO("Max Texture Count: {}", texturesCount);
|
INFO("Max Texture Count: {}", texturesCount);
|
||||||
|
|
@ -728,7 +728,7 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
|
||||||
const vk::DescriptorPoolCreateInfo poolCreateInfo = {
|
const vk::DescriptorPoolCreateInfo poolCreateInfo = {
|
||||||
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
|
.flags = vk::DescriptorPoolCreateFlagBits::eUpdateAfterBind,
|
||||||
.maxSets = 1,
|
.maxSets = 1,
|
||||||
.poolSizeCount = Cast<u32>(poolSizes.size()),
|
.poolSizeCount = static_cast<u32>(poolSizes.size()),
|
||||||
.pPoolSizes = poolSizes.data(),
|
.pPoolSizes = poolSizes.data(),
|
||||||
};
|
};
|
||||||
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
AbortIfFailed(device->m_Device.createDescriptorPool(&poolCreateInfo, nullptr, &m_DescriptorPool));
|
||||||
|
|
@ -742,7 +742,7 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo = {
|
vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsCreateInfo = {
|
||||||
.bindingCount = Cast<u32>(layoutBindingFlags.size()),
|
.bindingCount = static_cast<u32>(layoutBindingFlags.size()),
|
||||||
.pBindingFlags = layoutBindingFlags.data(),
|
.pBindingFlags = layoutBindingFlags.data(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -750,19 +750,19 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = BUFFER_BINDING_INDEX,
|
.binding = BUFFER_BINDING_INDEX,
|
||||||
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
.descriptorType = vk::DescriptorType::eStorageBuffer,
|
||||||
.descriptorCount = Cast<u32>(buffersCount),
|
.descriptorCount = static_cast<u32>(buffersCount),
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
},
|
},
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = TEXTURE_BINDING_INDEX,
|
.binding = TEXTURE_BINDING_INDEX,
|
||||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||||
.descriptorCount = Cast<u32>(texturesCount),
|
.descriptorCount = static_cast<u32>(texturesCount),
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
},
|
},
|
||||||
vk::DescriptorSetLayoutBinding{
|
vk::DescriptorSetLayoutBinding{
|
||||||
.binding = STORAGE_TEXTURE_BINDING_INDEX,
|
.binding = STORAGE_TEXTURE_BINDING_INDEX,
|
||||||
.descriptorType = vk::DescriptorType::eStorageImage,
|
.descriptorType = vk::DescriptorType::eStorageImage,
|
||||||
.descriptorCount = Cast<u32>(storageTexturesCount),
|
.descriptorCount = static_cast<u32>(storageTexturesCount),
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -770,7 +770,7 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
|
||||||
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
const vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||||
.pNext = &bindingFlagsCreateInfo,
|
.pNext = &bindingFlagsCreateInfo,
|
||||||
.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
|
.flags = vk::DescriptorSetLayoutCreateFlagBits::eUpdateAfterBindPool,
|
||||||
.bindingCount = Cast<u32>(descriptorLayoutBindings.size()),
|
.bindingCount = static_cast<u32>(descriptorLayoutBindings.size()),
|
||||||
.pBindings = descriptorLayoutBindings.data(),
|
.pBindings = descriptorLayoutBindings.data(),
|
||||||
};
|
};
|
||||||
AbortIfFailed(device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &m_SetLayout));
|
AbortIfFailed(device->m_Device.createDescriptorSetLayout(&descriptorSetLayoutCreateInfo, nullptr, &m_SetLayout));
|
||||||
|
|
@ -960,7 +960,7 @@ RenderResourceManager::CreateIndexBuffer(usize size, usize alignment, u32 *first
|
||||||
u32
|
u32
|
||||||
RenderResourceManager::FetchIndex(IndexHandle handle)
|
RenderResourceManager::FetchIndex(IndexHandle handle)
|
||||||
{
|
{
|
||||||
return Cast<u32>(m_Index.FetchOffset(handle) / sizeof(u32));
|
return static_cast<u32>(m_Index.FetchOffset(handle) / sizeof(u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,5 @@ cmake_minimum_required(VERSION 3.13)
|
||||||
add_subdirectory("00_util")
|
add_subdirectory("00_util")
|
||||||
add_subdirectory("01_triangle")
|
add_subdirectory("01_triangle")
|
||||||
add_subdirectory("02_box")
|
add_subdirectory("02_box")
|
||||||
add_subdirectory("03_model_render")
|
# add_subdirectory("03_model_render")
|
||||||
# add_subdirectory("04_scenes")
|
# add_subdirectory("04_scenes")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"default-registry": {
|
"default-registry": {
|
||||||
"kind": "git",
|
"kind": "git",
|
||||||
"baseline": "b27651341123a59f7187b42ef2bc476284afb310",
|
"baseline": "41c447cc210dc39aa85d4a5f58b4a1b9e573b3dc",
|
||||||
"repository": "https://github.com/microsoft/vcpkg"
|
"repository": "https://github.com/microsoft/vcpkg"
|
||||||
},
|
},
|
||||||
"registries": [
|
"registries": [
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
"scottt-debugbreak",
|
"scottt-debugbreak",
|
||||||
"tinygltf",
|
"tinygltf",
|
||||||
"vulkan-memory-allocator",
|
"vulkan-memory-allocator",
|
||||||
"entt"
|
"entt",
|
||||||
|
"shader-slang"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue