Compare commits

...

4 Commits

Author SHA1 Message Date
Anish Bhobe 564f6cc205 Merge buffer creation into BufferManager. 2025-02-02 17:56:03 +01:00
Anish Bhobe 466e4a4093 Annotate Memory Allocations. 2025-02-02 17:56:03 +01:00
Anish Bhobe 91010a448e Update triangle and box examples to separate swapchain. 2025-02-02 17:56:03 +01:00
Anish Bhobe 0462dc33f0 Window is now independent of vulkan. 2025-02-02 17:56:03 +01:00
22 changed files with 356 additions and 136 deletions

5
Folder.DotSettings.user Normal file
View File

@ -0,0 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/Housekeeping/Bookmarks/NumberedBookmarks/=Bookmark5/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/Housekeeping/Bookmarks/NumberedBookmarks/=Bookmark5/Coords/@EntryValue">(Doc Ln 10 Col 4)</s:String>
<s:String x:Key="/Default/Housekeeping/Bookmarks/NumberedBookmarks/=Bookmark5/FileId/@EntryValue">DB94C55F-6B9A-4AAE-80D7-29FD8153E6B5/d:aster/f:window.h</s:String>
<s:String x:Key="/Default/Housekeeping/Bookmarks/NumberedBookmarks/=Bookmark5/Owner/@EntryValue">NumberedBookmarkManager</s:String></wpf:ResourceDictionary>

View File

@ -22,7 +22,7 @@ set(HEADER_FILES
swapchain.h swapchain.h
pipeline.h pipeline.h
queue_allocation.h queue_allocation.h
buffer.h) buffer.h "surface.h" "size.h")
set(SOURCE_FILES set(SOURCE_FILES
logger.cpp logger.cpp
@ -35,7 +35,7 @@ set(SOURCE_FILES
pipeline.cpp pipeline.cpp
buffer.cpp buffer.cpp
image.cpp image.cpp
image.h) image.h "surface.cpp")
add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES}) add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES})
set_property(TARGET aster_core PROPERTY CXX_STANDARD 20) set_property(TARGET aster_core PROPERTY CXX_STANDARD 20)

View File

@ -42,14 +42,6 @@ Context::Context(const cstr appName, const Version version, bool enableValidatio
{ {
INFO_IF(enableValidation, "Validation Layers enabled"); INFO_IF(enableValidation, "Validation Layers enabled");
if (!glfwInit())
{
const char *error = nullptr;
const auto code = glfwGetError(&error);
ERROR("GLFW Init failed. Cause: ({}) {}", code, error)
THEN_ABORT(code);
}
// TODO Get/Check API Version // TODO Get/Check API Version
// Creating Instance // Creating Instance
@ -119,8 +111,6 @@ Context::~Context()
} }
m_Instance.destroy(nullptr); m_Instance.destroy(nullptr);
DEBUG("Instance destroyed"); DEBUG("Instance destroyed");
glfwTerminate();
} }
Context::Context(Context &&other) noexcept Context::Context(Context &&other) noexcept

View File

@ -14,16 +14,80 @@
// NOTE: Vulkan Dispatch Loader Storage - Should only appear once. // NOTE: Vulkan Dispatch Loader Storage - Should only appear once.
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
struct MemorySize
{
u16 m_Gigabytes;
u16 m_Megabytes;
u16 m_Kilobytes;
u16 m_Bytes;
MemorySize &
operator+=(usize bytes)
{
usize totalBytes = bytes + m_Bytes;
m_Bytes = totalBytes % 1024;
const usize totalKb = m_Kilobytes + totalBytes / 1024;
m_Kilobytes = totalKb % 1024;
const usize totalMb = m_Megabytes + totalKb / 1024;
m_Megabytes = totalMb % 1024;
m_Gigabytes += totalMb / 1024;
return *this;
}
};
MemorySize g_TotalAlloc = {};
template <>
struct fmt::formatter<MemorySize>
{
// ReSharper disable once CppInconsistentNaming
constexpr auto
parse(format_parse_context &ctx)
{
return ctx.begin();
}
template <typename Context>
// ReSharper disable once CppInconsistentNaming
constexpr auto
format(MemorySize const &mem, Context &ctx) const
{
// return format_to(ctx.out(), "({}, {})", foo.a, foo.b); // --== KEY LINE ==--
if (mem.m_Gigabytes > 0)
{
return v10::format_to(ctx.out(), "{}.{} GB", mem.m_Gigabytes,
Cast<u16>(mem.m_Megabytes / 1024.0));
}
if (mem.m_Megabytes > 0)
{
return v10::format_to(ctx.out(), "{}.{} MB", mem.m_Megabytes, Cast<u16>(mem.m_Kilobytes / 1024.0));
}
if (mem.m_Kilobytes > 0)
{
return v10::format_to(ctx.out(), "{}.{} KB", mem.m_Kilobytes, Cast<u16>(mem.m_Bytes / 1024.0));
}
return v10::format_to(ctx.out(), "{} Bytes", mem.m_Bytes);
}
};
void * void *
operator new[](size_t size, const char * /*pName*/, int /*flags*/, unsigned /*debugFlags*/, const char * /*file*/, operator new[](size_t size, const char * /*pName*/, int flags, unsigned /*debugFlags*/, const char * /*file*/,
int /*line*/) int /*line*/)
{ {
g_TotalAlloc += size;
VERBOSE("Total: {} - Allocated {} bytes. ({})", g_TotalAlloc, size, (flags & eastl::MEM_TEMP) ? "temp" : "perm");
return new u8[size]; return new u8[size];
} }
void * void *
operator new[](size_t size, size_t /*alignment*/, size_t /*alignmentOffset*/, const char * /*pName*/, int /*flags*/, operator new[](size_t size, size_t /*alignment*/, size_t /*alignmentOffset*/, const char * /*pName*/, int flags,
unsigned /*debugFlags*/, const char * /*file*/, int /*line*/) unsigned /*debugFlags*/, const char * /*file*/, int /*line*/)
{ {
g_TotalAlloc += size;
VERBOSE("Total: {} - Allocated {} bytes. ({})", g_TotalAlloc, size, (flags & eastl::MEM_TEMP) ? "temp" : "perm");
return new u8[size]; return new u8[size];
} }

View File

@ -6,6 +6,7 @@
#include "physical_device.h" #include "physical_device.h"
#include "context.h" #include "context.h"
#include "surface.h"
#include "window.h" #include "window.h"
[[nodiscard]] vk::SurfaceCapabilitiesKHR [[nodiscard]] vk::SurfaceCapabilitiesKHR
@ -154,12 +155,11 @@ EnumeratePhysicalDevices(const vk::Instance instance)
return physicalDevices; return physicalDevices;
} }
PhysicalDevices::PhysicalDevices(const Window *window, const Context *context) PhysicalDevices::PhysicalDevices(const Surface *surface, const Context *context)
{ {
auto surface = window->m_Surface;
auto physicalDevices = EnumeratePhysicalDevices(context->m_Instance); auto physicalDevices = EnumeratePhysicalDevices(context->m_Instance);
for (auto physicalDevice : physicalDevices) for (auto physicalDevice : physicalDevices)
{ {
this->emplace_back(surface, physicalDevice); this->emplace_back(surface->m_Surface, physicalDevice);
} }
} }

View File

@ -6,6 +6,8 @@
#pragma once #pragma once
#include "global.h" #include "global.h"
#include "surface.h"
#include <EASTL/fixed_vector.h> #include <EASTL/fixed_vector.h>
struct Window; struct Window;
@ -52,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 Window *window, const Context *context); PhysicalDevices(const Surface *surface, const Context *context);
}; };

20
aster/size.h Normal file
View File

@ -0,0 +1,20 @@
// =============================================
// Aster: size.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "global.h"
struct Size2D
{
u32 m_Width;
u32 m_Height;
explicit
operator vk::Extent2D() const
{
return {m_Width, m_Height};
}
};

51
aster/surface.cpp Normal file
View File

@ -0,0 +1,51 @@
// =============================================
// Aster: surface.cpp
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#include "surface.h"
#include "context.h"
#include "window.h"
Surface::Surface(Context *context, const Window *window, cstr name)
: m_Context(context)
{
VkSurfaceKHR surface;
auto result = Cast<vk::Result>(
glfwCreateWindowSurface(Cast<VkInstance>(m_Context->m_Instance), window->m_Window, nullptr, &surface));
ERROR_IF(Failed(result), "Failed to create Surface with {}", result)
THEN_ABORT(result)
ELSE_DEBUG("Surface {} Created", m_Name);
m_Surface = vk::SurfaceKHR(surface);
}
Surface::~Surface()
{
if (m_Context && m_Surface)
{
m_Context->m_Instance.destroy(m_Surface, nullptr);
DEBUG("Surface Destroyed");
m_Surface = nullptr;
m_Context = nullptr;
}
}
Surface::Surface(Surface &&other) noexcept
: m_Context(Take(other.m_Context))
, m_Surface(Take(other.m_Surface))
, m_Name(std::move(other.m_Name))
{
}
Surface &
Surface::operator=(Surface &&other) noexcept
{
if (this == &other)
return *this;
m_Context = Take(other.m_Context);
m_Surface = Take(other.m_Surface);
m_Name = std::move(other.m_Name);
return *this;
}

28
aster/surface.h Normal file
View File

@ -0,0 +1,28 @@
// =============================================
// Aster: surface.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "global.h"
struct Context;
struct Window;
struct Surface
{
Context *m_Context;
vk::SurfaceKHR m_Surface;
NameString m_Name;
// Ctor Dtor
Surface(Context *context, const Window *window, cstr name);
~Surface();
// Move
Surface(Surface &&other) noexcept;
Surface &operator=(Surface &&other) noexcept;
DISALLOW_COPY_AND_ASSIGN(Surface);
};

View File

@ -7,16 +7,17 @@
#include "device.h" #include "device.h"
#include "physical_device.h" #include "physical_device.h"
#include "surface.h"
#include "window.h" #include "window.h"
[[nodiscard]] vk::Extent2D GetExtent(const Window *window, vk::SurfaceCapabilitiesKHR *surfaceCapabilities); [[nodiscard]] vk::Extent2D GetExtent(Size2D size, vk::SurfaceCapabilitiesKHR *surfaceCapabilities);
Swapchain::Swapchain(const Window *window, const Device *device, NameString &&name) Swapchain::Swapchain(const Surface *surface, const Device *device, Size2D size, NameString &&name)
: m_Device(device) : m_Device(device)
, m_Name(std::move(name)) , m_Name(std::move(name))
, m_Format(vk::Format::eUndefined) , m_Format(vk::Format::eUndefined)
{ {
this->Create(window); this->Create(surface, size);
} }
Swapchain::~Swapchain() Swapchain::~Swapchain()
@ -51,20 +52,20 @@ Swapchain::operator=(Swapchain &&other) noexcept
} }
void void
Swapchain::Create(const Window *window) Swapchain::Create(const Surface *surface, Size2D size)
{ {
auto surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, window->m_Surface); auto surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, surface->m_Surface);
m_Extent = GetExtent(window, &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, window->m_Surface); surfaceCapabilities = GetSurfaceCapabilities(m_Device->m_PhysicalDevice, surface->m_Surface);
m_Extent = GetExtent(window, &surfaceCapabilities); m_Extent = GetExtent(size, &surfaceCapabilities);
} }
auto surfaceFormats = GetSurfaceFormats(m_Device->m_PhysicalDevice, window->m_Surface); auto surfaceFormats = GetSurfaceFormats(m_Device->m_PhysicalDevice, surface->m_Surface);
auto presentModes = GetSurfacePresentModes(m_Device->m_PhysicalDevice, window->m_Surface); auto presentModes = GetSurfacePresentModes(m_Device->m_PhysicalDevice, surface->m_Surface);
m_Format = vk::Format::eUndefined; m_Format = vk::Format::eUndefined;
vk::ColorSpaceKHR swapchainColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear; vk::ColorSpaceKHR swapchainColorSpace = vk::ColorSpaceKHR::eSrgbNonlinear;
@ -104,7 +105,7 @@ Swapchain::Create(const Window *window)
// 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 = window->m_Surface, .surface = surface->m_Surface,
.minImageCount = swapchainImageCount, .minImageCount = swapchainImageCount,
.imageFormat = m_Format, .imageFormat = m_Format,
.imageColorSpace = swapchainColorSpace, .imageColorSpace = swapchainColorSpace,
@ -206,14 +207,14 @@ Swapchain::Cleanup()
} }
vk::Extent2D vk::Extent2D
GetExtent(const Window *window, vk::SurfaceCapabilitiesKHR *surfaceCapabilities) GetExtent(Size2D size, vk::SurfaceCapabilitiesKHR *surfaceCapabilities)
{ {
if (surfaceCapabilities->currentExtent.width != MaxValue<u32>) if (surfaceCapabilities->currentExtent.width != MaxValue<u32>)
{ {
return surfaceCapabilities->currentExtent; return surfaceCapabilities->currentExtent;
} }
auto [width, height] = window->GetSize(); auto [width, height] = size;
auto [minWidth, minHeight] = surfaceCapabilities->minImageExtent; auto [minWidth, minHeight] = surfaceCapabilities->minImageExtent;
auto [maxWidth, maxHeight] = surfaceCapabilities->maxImageExtent; auto [maxWidth, maxHeight] = surfaceCapabilities->maxImageExtent;

View File

@ -7,10 +7,12 @@
#include "global.h" #include "global.h"
#include "size.h"
#include <EASTL/fixed_vector.h> #include <EASTL/fixed_vector.h>
struct PhysicalDevice; struct PhysicalDevice;
struct Window; struct Surface;
struct Device; struct Device;
struct Swapchain final struct Swapchain final
@ -27,11 +29,11 @@ struct Swapchain final
eastl::vector<FnResizeCallback> m_ResizeCallbacks; eastl::vector<FnResizeCallback> m_ResizeCallbacks;
void Create(const Window *window); void Create(const Surface *window, Size2D size);
void RegisterResizeCallback(FnResizeCallback &&callback); void RegisterResizeCallback(FnResizeCallback &&callback);
// Ctor/Dtor // Ctor/Dtor
Swapchain(const Window *window, const Device *device, NameString &&name); Swapchain(const Surface *window, const Device *device, Size2D size, NameString &&name);
~Swapchain(); ~Swapchain();
// Move // Move

View File

@ -8,6 +8,9 @@
#include "context.h" #include "context.h"
#include "logger.h" #include "logger.h"
std::atomic_uint64_t Window::m_WindowCount = 0;
std::atomic_bool Window::m_IsGlfwInit = false;
void void
Window::RequestExit() const noexcept Window::RequestExit() const noexcept
{ {
@ -26,7 +29,7 @@ Window::SetWindowSize(const u32 width, const u32 height) const noexcept
glfwSetWindowSize(m_Window, Cast<i32>(width), Cast<i32>(height)); glfwSetWindowSize(m_Window, Cast<i32>(width), Cast<i32>(height));
} }
vk::Extent2D Size2D
Window::GetSize() const Window::GetSize() const
{ {
int width; int width;
@ -35,11 +38,23 @@ Window::GetSize() const
return {Cast<u32>(width), Cast<u32>(height)}; return {Cast<u32>(width), Cast<u32>(height)};
} }
Window::Window(const cstr title, Context *context, vk::Extent2D extent, const b8 isFullScreen) Window::Window(const cstr title, Size2D extent, const b8 isFullScreen)
{ {
m_Context = context;
m_Name = title; m_Name = title;
if (!m_IsGlfwInit)
{
if (!glfwInit())
{
const char *error = nullptr;
const auto code = glfwGetError(&error);
ERROR("GLFW Init failed. Cause: ({}) {}", code, error)
THEN_ABORT(code);
}
m_WindowCount = 0;
m_IsGlfwInit = true;
}
GLFWmonitor *monitor = glfwGetPrimaryMonitor(); GLFWmonitor *monitor = glfwGetPrimaryMonitor();
ERROR_IF(!monitor, "No monitor found"); ERROR_IF(!monitor, "No monitor found");
@ -49,10 +64,10 @@ Window::Window(const cstr title, Context *context, vk::Extent2D extent, const b8
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.width), Cast<i32>(extent.height), m_Name.c_str(), m_Window = glfwCreateWindow(Cast<i32>(extent.m_Width), 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.width, extent.height); ELSE_DEBUG("Window '{}' created with resolution '{}x{}'", m_Name, extent.m_Width, extent.m_Height);
if (m_Window == nullptr) if (m_Window == nullptr)
{ {
const char *error = nullptr; const char *error = nullptr;
@ -63,41 +78,35 @@ Window::Window(const cstr title, Context *context, vk::Extent2D extent, const b8
if (isFullScreen == false) if (isFullScreen == false)
{ {
glfwSetWindowPos(m_Window, Cast<i32>(windowWidth - extent.width) / 2, glfwSetWindowPos(m_Window, Cast<i32>(windowWidth - extent.m_Width) / 2,
Cast<i32>(windowHeight - extent.height) / 2); Cast<i32>(windowHeight - extent.m_Height) / 2);
} }
glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
VkSurfaceKHR surface; ++m_WindowCount;
auto result =
Cast<vk::Result>(glfwCreateWindowSurface(Cast<VkInstance>(m_Context->m_Instance), m_Window, nullptr, &surface));
ERROR_IF(Failed(result), "Failed to create Surface with {}", result)
THEN_ABORT(result)
ELSE_DEBUG("Surface {} Created", m_Name);
m_Surface = vk::SurfaceKHR(surface);
} }
Window::~Window() Window::~Window()
{ {
if (m_Context && m_Surface)
{
m_Context->m_Instance.destroy(m_Surface, nullptr);
DEBUG("Surface Destroyed");
}
if (m_Window) if (m_Window)
{ {
glfwDestroyWindow(m_Window); glfwDestroyWindow(m_Window);
m_Window = nullptr; m_Window = nullptr;
--m_WindowCount;
}
if (m_WindowCount== 0 && m_IsGlfwInit)
{
glfwTerminate();
m_IsGlfwInit = false;
} }
DEBUG("Window '{}' Destroyed", m_Name); DEBUG("Window '{}' Destroyed", m_Name);
} }
Window::Window(Window &&other) noexcept Window::Window(Window &&other) noexcept
: m_Context(other.m_Context) : m_Window(Take(other.m_Window))
, m_Window(Take(other.m_Window))
, m_Surface(Take(other.m_Surface))
, m_Name(Take(other.m_Name)) , m_Name(Take(other.m_Name))
{ {
} }
@ -107,9 +116,7 @@ Window::operator=(Window &&other) noexcept
{ {
if (this == &other) if (this == &other)
return *this; return *this;
m_Context = other.m_Context;
m_Window = Take(other.m_Window); m_Window = Take(other.m_Window);
m_Surface = Take(other.m_Surface);
m_Name = Take(other.m_Name); m_Name = Take(other.m_Name);
return *this; return *this;
} }

View File

@ -6,18 +6,19 @@
#pragma once #pragma once
#include "global.h" #include "global.h"
#include <EASTL/fixed_string.h>
struct Context; #include "size.h"
#include <EASTL/fixed_string.h>
struct Window final struct Window final
{ {
// fields // fields
Context *m_Context{};
GLFWwindow *m_Window = nullptr; GLFWwindow *m_Window = nullptr;
vk::SurfaceKHR m_Surface; NameString m_Name;
eastl::fixed_string<char, 32> m_Name;
static std::atomic_uint64_t m_WindowCount;
static std::atomic_bool m_IsGlfwInit;
// Methods // Methods
[[nodiscard]] bool [[nodiscard]] bool
@ -31,10 +32,10 @@ struct Window final
void SetWindowSize(const vk::Extent2D &extent) const noexcept; void SetWindowSize(const vk::Extent2D &extent) const noexcept;
void SetWindowSize(u32 width, u32 height) const noexcept; void SetWindowSize(u32 width, u32 height) const noexcept;
/// Actual size of the framebuffer being used for the window render. /// Actual size of the framebuffer being used for the window render.
[[nodiscard]] vk::Extent2D GetSize() const; [[nodiscard]] Size2D GetSize() const;
// Ctor/Dtor // Ctor/Dtor
Window(cstr title, Context *context, vk::Extent2D extent, b8 isFullScreen = false); Window(cstr title, Size2D extent, b8 isFullScreen = false);
~Window(); ~Window();
// Move // Move

View File

@ -52,7 +52,7 @@ Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCo
} }
void void
Frame::Present(const vk::Queue commandQueue, Swapchain *swapchain, const Window *window) Frame::Present(const vk::Queue commandQueue, Swapchain *swapchain, const Surface *surface, Size2D size)
{ {
vk::PresentInfoKHR presentInfo = { vk::PresentInfoKHR presentInfo = {
@ -70,7 +70,7 @@ Frame::Present(const vk::Queue commandQueue, Swapchain *swapchain, const Window
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(window); 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.");
@ -128,7 +128,7 @@ FrameManager::FrameManager(const Device *device, u32 queueFamilyIndex, u32 frame
} }
Frame * Frame *
FrameManager::GetNextFrame(Swapchain *swapchain, const Window *window) FrameManager::GetNextFrame(Swapchain *swapchain, const Surface *surface, Size2D size)
{ {
Frame *currentFrame = &m_Frames[m_CurrentFrameIdx]; Frame *currentFrame = &m_Frames[m_CurrentFrameIdx];
@ -153,7 +153,7 @@ FrameManager::GetNextFrame(Swapchain *swapchain, const Window *window)
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(window); 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);

View File

@ -8,11 +8,14 @@
#include "global.h" #include "global.h"
#include "helpers.h" #include "helpers.h"
#include "size.h"
#include <EASTL/fixed_vector.h> #include <EASTL/fixed_vector.h>
struct Device; struct Device;
struct Window; struct Window;
struct Swapchain; struct Swapchain;
struct Surface;
struct Frame struct Frame
{ {
@ -28,7 +31,7 @@ struct Frame
// Transient // Transient
u32 m_ImageIdx; u32 m_ImageIdx;
void Present(vk::Queue commandQueue, Swapchain *swapchain, const Window *window); void Present(const vk::Queue commandQueue, Swapchain* swapchain, const Surface* surface, Size2D size);
Frame(const Device *device, u32 queueFamilyIndex, u32 frameCount); Frame(const Device *device, u32 queueFamilyIndex, u32 frameCount);
~Frame(); ~Frame();
@ -48,5 +51,5 @@ struct FrameManager
FrameManager(const Device *device, u32 queueFamilyIndex, u32 framesInFlight); FrameManager(const Device *device, u32 queueFamilyIndex, u32 framesInFlight);
Frame *GetNextFrame(Swapchain *swapchain, const Window *window); Frame *GetNextFrame(Swapchain *swapchain, const Surface *surface, Size2D size);
}; };

View File

@ -75,9 +75,10 @@ main(int, char **)
MIN_LOG_LEVEL(Logger::LogType::eInfo); MIN_LOG_LEVEL(Logger::LogType::eInfo);
Context context = {"Triangle", VERSION}; Context context = {"Triangle", VERSION};
Window window = {"Triangle (Aster)", &context, {640, 480}}; Window window = {"Triangle (Aster)", {640, 480}};
Surface surface = {&context, &window, "Primary"};
PhysicalDevices physicalDevices = {&window, &context}; PhysicalDevices physicalDevices = {&surface, &context};
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices); PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data()); INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
@ -86,7 +87,7 @@ main(int, char **)
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse); QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"}; Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0); vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&window, &device, "Primary Chain"}; Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
Pipeline pipeline = CreatePipeline(&device, &swapchain); Pipeline pipeline = CreatePipeline(&device, &swapchain);
vk::CommandPool copyPool; vk::CommandPool copyPool;
@ -217,7 +218,7 @@ main(int, char **)
case vk::Result::eErrorOutOfDateKHR: case vk::Result::eErrorOutOfDateKHR:
case vk::Result::eSuboptimalKHR: case vk::Result::eSuboptimalKHR:
INFO("Recreating Swapchain. Cause: {}", result); INFO("Recreating Swapchain. Cause: {}", result);
swapchain.Create(&window); swapchain.Create(&surface, window.GetSize());
viewport.y = Cast<f32>(swapchain.m_Extent.height); viewport.y = Cast<f32>(swapchain.m_Extent.height);
viewport.width = Cast<f32>(swapchain.m_Extent.width); viewport.width = Cast<f32>(swapchain.m_Extent.width);
viewport.height = -Cast<f32>(swapchain.m_Extent.height); viewport.height = -Cast<f32>(swapchain.m_Extent.height);
@ -317,7 +318,7 @@ main(int, char **)
case vk::Result::eErrorOutOfDateKHR: case vk::Result::eErrorOutOfDateKHR:
case vk::Result::eSuboptimalKHR: case vk::Result::eSuboptimalKHR:
INFO("Recreating Swapchain. Cause: {}", result); INFO("Recreating Swapchain. Cause: {}", result);
swapchain.Create(&window); swapchain.Create(&surface, window.GetSize());
viewport.y = Cast<f32>(swapchain.m_Extent.height); viewport.y = Cast<f32>(swapchain.m_Extent.height);
viewport.width = Cast<f32>(swapchain.m_Extent.width); viewport.width = Cast<f32>(swapchain.m_Extent.width);
viewport.height = -Cast<f32>(swapchain.m_Extent.height); viewport.height = -Cast<f32>(swapchain.m_Extent.height);

View File

@ -116,9 +116,10 @@ main(int, char **)
MIN_LOG_LEVEL(Logger::LogType::eInfo); MIN_LOG_LEVEL(Logger::LogType::eInfo);
Context context = {"Box", VERSION}; Context context = {"Box", VERSION};
Window window = {"Box (Aster)", &context, {640, 480}}; Window window = {"Box (Aster)", {640, 480}};
Surface surface = {&context, &window, "Primary"};
PhysicalDevices physicalDevices = {&window, &context}; PhysicalDevices physicalDevices = {&surface, &context};
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices); PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data()); INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data());
@ -130,7 +131,7 @@ main(int, char **)
QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse); QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse);
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"}; Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"};
vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0); vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&window, &device, "Primary Chain"}; Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
Pipeline pipeline = CreatePipeline(&device, &swapchain); Pipeline pipeline = CreatePipeline(&device, &swapchain);
Camera camera = { Camera camera = {
@ -453,7 +454,7 @@ main(int, char **)
camera.m_Model *= rotate(mat4{1.0f}, Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f)); camera.m_Model *= rotate(mat4{1.0f}, Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f));
ubo.Write(&device, 0, sizeof camera, &camera); ubo.Write(&device, 0, sizeof camera, &camera);
Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &window); Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &surface, window.GetSize());
u32 imageIndex = currentFrame->m_ImageIdx; u32 imageIndex = currentFrame->m_ImageIdx;
vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex]; vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex];
@ -528,7 +529,7 @@ main(int, char **)
}; };
AbortIfFailed(commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence)); AbortIfFailed(commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence));
currentFrame->Present(commandQueue, &swapchain, &window); currentFrame->Present(commandQueue, &swapchain, &surface, window.GetSize());
} }
device.WaitIdle(); device.WaitIdle();

View File

@ -134,9 +134,10 @@ main(int, char **)
MIN_LOG_LEVEL(Logger::LogType::eInfo); MIN_LOG_LEVEL(Logger::LogType::eInfo);
Context context = {"ModelRender", VERSION}; Context context = {"ModelRender", VERSION};
Window window = {"ModelRender (Aster)", &context, {INIT_WIDTH, INIT_HEIGHT}}; Window window = {"ModelRender (Aster)", {INIT_WIDTH, INIT_HEIGHT}};
Surface surface = {&context, &window, "Primary Surface"};
PhysicalDevices physicalDevices = {&window, &context}; PhysicalDevices physicalDevices = {&surface, &context};
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices); PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
usize physicalDeviceOffsetAlignment = deviceToUse.m_DeviceProperties.limits.minUniformBufferOffsetAlignment; usize physicalDeviceOffsetAlignment = deviceToUse.m_DeviceProperties.limits.minUniformBufferOffsetAlignment;
@ -173,7 +174,7 @@ main(int, char **)
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, Device device = {&context, &deviceToUse, &enabledDeviceFeatures,
{queueAllocation}, pipelineCacheData, "Primary Device"}; {queueAllocation}, pipelineCacheData, "Primary Device"};
vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0); vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&window, &device, "Primary Chain"}; Swapchain swapchain = {&surface, &device, window.GetSize(), "Primary Chain"};
GpuResourceManager resourceManager = {&device, 1000}; GpuResourceManager resourceManager = {&device, 1000};
AssetLoader assetLoader = {&resourceManager, graphicsQueue, queueAllocation.m_Family, queueAllocation.m_Family}; AssetLoader assetLoader = {&resourceManager, graphicsQueue, queueAllocation.m_Family, queueAllocation.m_Family};
@ -513,7 +514,7 @@ main(int, char **)
cameraController.m_Camera.CalculateInverses(); cameraController.m_Camera.CalculateInverses();
ubo.Write(&device, 0, sizeof cameraController.m_Camera, &cameraController.m_Camera); ubo.Write(&device, 0, sizeof cameraController.m_Camera, &cameraController.m_Camera);
Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &window); Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &surface, window.GetSize());
u32 imageIndex = currentFrame->m_ImageIdx; u32 imageIndex = currentFrame->m_ImageIdx;
vk::Image currentSwapchainImage = swapchain.m_Images[imageIndex]; vk::Image currentSwapchainImage = swapchain.m_Images[imageIndex];
@ -686,7 +687,7 @@ main(int, char **)
}; };
AbortIfFailed(graphicsQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence)); AbortIfFailed(graphicsQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence));
currentFrame->Present(graphicsQueue, &swapchain, &window); currentFrame->Present(graphicsQueue, &swapchain, &surface, window.GetSize());
} }
device.WaitIdle(); device.WaitIdle();

View File

@ -239,12 +239,11 @@ LightManager::Update()
const u16 requiredBufferCapacity = eastl::min(Cast<u16>(m_Lights.capacity()), MAX_LIGHTS); const u16 requiredBufferCapacity = eastl::min(Cast<u16>(m_Lights.capacity()), MAX_LIGHTS);
if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity) if ((m_GpuBufferCapacity_ & CAPACITY_MASK) < requiredBufferCapacity)
{ {
StorageBuffer newBuffer;
newBuffer.Init(m_ResourceManager->m_Device, requiredBufferCapacity * sizeof m_Lights[0], true, "Light Buffer");
m_GpuBufferCapacity_ = requiredBufferCapacity | UPDATE_REQUIRED_BIT; m_GpuBufferCapacity_ = requiredBufferCapacity | UPDATE_REQUIRED_BIT;
m_ResourceManager->Release(m_MetaInfo.m_LightBuffer); m_ResourceManager->Release(m_MetaInfo.m_LightBuffer);
m_MetaInfo.m_LightBuffer = m_ResourceManager->Commit(&newBuffer); m_MetaInfo.m_LightBuffer =
m_ResourceManager->CreateStorageBuffer(requiredBufferCapacity * sizeof m_Lights[0], "Light Buffer");
} }
if (m_GpuBufferCapacity_ & UPDATE_REQUIRED_BIT) if (m_GpuBufferCapacity_ & UPDATE_REQUIRED_BIT)
{ {

View File

@ -37,10 +37,11 @@ main(int, char *[])
{ {
MIN_LOG_LEVEL(Logger::LogType::eInfo); MIN_LOG_LEVEL(Logger::LogType::eInfo);
Window window = {"Scene Render [WIP] (Aster)", {INIT_WIDTH, INIT_HEIGHT}};
Context context = {"Scene Render [WIP]", VERSION}; Context context = {"Scene Render [WIP]", VERSION};
Window window = {"Scene Render [WIP] (Aster)", &context, {INIT_WIDTH, INIT_HEIGHT}}; Surface surface = {&context, &window, "Primary Surface"};
PhysicalDevices physicalDevices = {&window, &context}; PhysicalDevices physicalDevices = {&surface, &context};
PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices); PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices);
vk::Extent2D internalResolution = {1920, 1080}; vk::Extent2D internalResolution = {1920, 1080};
@ -91,7 +92,7 @@ main(int, char *[])
Device device = {&context, &deviceToUse, &enabledDeviceFeatures, Device device = {&context, &deviceToUse, &enabledDeviceFeatures,
{queueAllocation}, pipelineCacheData, "Primary Device"}; {queueAllocation}, pipelineCacheData, "Primary Device"};
vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0); vk::Queue graphicsQueue = device.GetQueue(queueAllocation.m_Family, 0);
Swapchain swapchain = {&window, &device, "Primary Chain"}; Swapchain swapchain = {&surface, &device, window.GetSize(),"Primary Chain"};
RenderResourceManager resourceManager = {&device, 1024}; RenderResourceManager resourceManager = {&device, 1024};
EcsRegistry registry; EcsRegistry registry;
@ -355,7 +356,7 @@ main(int, char *[])
// glm::rotate(dynTrans.m_Rotation, Cast<f32>(30_deg * (++index) * Time::m_Delta), vec3{0.0f, 1.0f, 0.0f}); // glm::rotate(dynTrans.m_Rotation, Cast<f32>(30_deg * (++index) * Time::m_Delta), vec3{0.0f, 1.0f, 0.0f});
//} //}
Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &window); Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &surface, window.GetSize());
u32 imageIndex = currentFrame->m_ImageIdx; u32 imageIndex = currentFrame->m_ImageIdx;
vk::Image currentSwapchainImage = swapchain.m_Images[imageIndex]; vk::Image currentSwapchainImage = swapchain.m_Images[imageIndex];
@ -552,7 +553,7 @@ main(int, char *[])
}; };
AbortIfFailed(graphicsQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence)); AbortIfFailed(graphicsQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence));
currentFrame->Present(graphicsQueue, &swapchain, &window); currentFrame->Present(graphicsQueue, &swapchain, &surface, window.GetSize());
} }
device.WaitIdle(); device.WaitIdle();

View File

@ -96,49 +96,51 @@ void
BufferManager::Init(const u32 maxCapacity) BufferManager::Init(const u32 maxCapacity)
{ {
m_MaxCapacity = maxCapacity; m_MaxCapacity = maxCapacity;
m_FreeHead = GpuResourceHandle::INVALID_HANDLE; m_FreeHead = 0;
m_Buffers = new Buffer[maxCapacity];
// Chaining Freeheads
Buffer *pIter = m_Buffers;
for (u32 i = 1; i < m_MaxCapacity; ++i)
{
*Recast<u32 *>(pIter) = i;
++pIter;
}
*Recast<u32 *>(pIter) = GpuResourceHandle::INVALID_HANDLE;
} }
BufferHandle BufferHandle
BufferManager::Commit(StorageBuffer *buffer) BufferManager::Allocate(const Device *device, const u32 bufferSize, const cstr name)
{
StorageBuffer sb;
sb.Init(device, bufferSize, true, true, name);
return Commit_(&sb);
}
BufferHandle
BufferManager::Commit_(StorageBuffer *buffer)
{ {
ERROR_IF(!buffer || !buffer->IsValid() || !buffer->IsOwned(), "Buffer must be valid and owned for commital") ERROR_IF(!buffer || !buffer->IsValid() || !buffer->IsOwned(), "Buffer must be valid and owned for commital")
THEN_ABORT(-1); THEN_ABORT(-1);
if (m_FreeHead != GpuResourceHandle::INVALID_HANDLE) ERROR_IF(m_FreeHead == GpuResourceHandle::INVALID_HANDLE, "Out of buffers")
{ THEN_ABORT(-1);
const u32 index = m_FreeHead;
StorageBuffer *allocatedBuffer = &m_Buffers[index]; const u32 index = m_FreeHead;
assert(!allocatedBuffer->IsValid()); Buffer *allocatedBuffer = &m_Buffers[index];
m_FreeHead = *Recast<u32 *>(allocatedBuffer);
// Ensure it is copyable. assert(!allocatedBuffer->IsValid());
static_assert(std::is_trivially_copyable_v<StorageBuffer>); m_FreeHead = *Recast<u32 *>(allocatedBuffer);
*allocatedBuffer = *buffer;
// Take ownership of the buffer. // Ensure it is copyable.
buffer->m_Size_ &= ~StorageBuffer::OWNED_BIT; static_assert(std::is_trivially_copyable_v<StorageBuffer>);
*allocatedBuffer = *buffer;
return {index}; // Take ownership of the buffer.
} buffer->m_Size_ &= ~StorageBuffer::OWNED_BIT;
const u32 index = Cast<u32>(m_Buffers.size()); return {index};
if (index < m_MaxCapacity)
{
StorageBuffer *allocatedBuffer = &m_Buffers.push_back();
// Ensure it is copyable.
static_assert(std::is_trivially_copyable_v<StorageBuffer>);
*allocatedBuffer = *buffer;
buffer->m_Size_ &= ~StorageBuffer::OWNED_BIT;
return {index};
}
ERROR("Out of Buffers") THEN_ABORT(-1);
} }
StorageBuffer * StorageBuffer *
@ -146,7 +148,7 @@ BufferManager::Fetch(const BufferHandle handle)
{ {
assert(!handle.IsInvalid()); assert(!handle.IsInvalid());
return &m_Buffers[handle.m_Index]; return Recast<StorageBuffer *>(&m_Buffers[handle.m_Index]);
} }
void void
@ -154,7 +156,7 @@ BufferManager::Release(const Device *device, const BufferHandle handle)
{ {
assert(!handle.IsInvalid()); assert(!handle.IsInvalid());
StorageBuffer *allocatedBuffer = &m_Buffers[handle.m_Index]; Buffer *allocatedBuffer = &m_Buffers[handle.m_Index];
allocatedBuffer->Destroy(device); allocatedBuffer->Destroy(device);
assert(!allocatedBuffer->IsValid()); assert(!allocatedBuffer->IsValid());
@ -166,10 +168,19 @@ BufferManager::Release(const Device *device, const BufferHandle handle)
void void
BufferManager::Destroy(const Device *device) BufferManager::Destroy(const Device *device)
{ {
for (auto &buffer : m_Buffers) if (!m_Buffers)
{ {
buffer.Destroy(device); WARN("Double Deletion");
return;
} }
Buffer *pBegin = m_Buffers;
const Buffer *pEnd = m_Buffers + m_MaxCapacity;
while (pBegin != pEnd)
{
(pBegin++)->Destroy(device);
}
delete[] Take(m_Buffers);
} }
StorageTextureHandle StorageTextureHandle
@ -405,9 +416,39 @@ RenderResourceManager::WriteInfo::WriteInfo(vk::BufferView info)
} }
BufferHandle BufferHandle
RenderResourceManager::Commit(StorageBuffer *storageBuffer) RenderResourceManager::Commit_(StorageBuffer *storageBuffer)
{ {
const BufferHandle handle = m_BufferManager.Commit(storageBuffer); const BufferHandle handle = m_BufferManager.Commit_(storageBuffer);
m_WriteInfos.emplace_back(vk::DescriptorBufferInfo{
.buffer = storageBuffer->m_Buffer,
.offset = 0,
.range = storageBuffer->GetSize(),
});
m_Writes.push_back({
.dstSet = m_DescriptorSet,
.dstBinding = BUFFER_BINDING_INDEX,
.dstArrayElement = handle.m_Index,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageBuffer,
.pBufferInfo = &m_WriteInfos.back().uBufferInfo,
});
m_WriteOwner.emplace_back(HandleType::eBuffer, handle.m_Index);
#if !defined(ASTER_NDEBUG)
++m_CommitedBufferCount;
#endif
return handle;
}
BufferHandle
RenderResourceManager::CreateStorageBuffer(const u32 bufferSize, const cstr name)
{
auto handle = m_BufferManager.Allocate(m_Device, bufferSize, name);
const auto storageBuffer = m_BufferManager.Fetch(handle);
m_WriteInfos.emplace_back(vk::DescriptorBufferInfo{ m_WriteInfos.emplace_back(vk::DescriptorBufferInfo{
.buffer = storageBuffer->m_Buffer, .buffer = storageBuffer->m_Buffer,
@ -748,7 +789,7 @@ RenderResourceManager::RenderResourceManager(Device *device, u16 maxSize, bool u
m_Device->SetName(m_DescriptorSet, "Bindless Set"); m_Device->SetName(m_DescriptorSet, "Bindless Set");
// NOTE: This needs to be synced with the destructor manually. // NOTE: This needs to be synced with the destructor manually.
assert(Commit(m_Geometry.m_BackingBuffer.get()).m_Index == UNIFIED_GEOMETRY_DATA_HANDLE_INDEX); // Making an assumption to avoid extra bindings. assert(Commit_(m_Geometry.m_BackingBuffer.get()).m_Index == UNIFIED_GEOMETRY_DATA_HANDLE_INDEX); // Making an assumption to avoid extra bindings.
} }
RenderResourceManager::~RenderResourceManager() RenderResourceManager::~RenderResourceManager()

View File

@ -75,12 +75,13 @@ struct TextureManager
struct BufferManager struct BufferManager
{ {
eastl::vector<StorageBuffer> m_Buffers; Buffer* m_Buffers;
u32 m_MaxCapacity; u32 m_MaxCapacity;
u32 m_FreeHead; u32 m_FreeHead;
void Init(u32 maxCapacity); void Init(u32 maxCapacity);
BufferHandle Commit(StorageBuffer *buffer); BufferHandle Allocate(const Device *device, u32 bufferSize, cstr name);
BufferHandle Commit_(StorageBuffer *buffer);
StorageBuffer *Fetch(BufferHandle handle); StorageBuffer *Fetch(BufferHandle handle);
void Release(const Device *device, BufferHandle handle); void Release(const Device *device, BufferHandle handle);
void Destroy(const Device *device); void Destroy(const Device *device);
@ -178,6 +179,7 @@ struct RenderResourceManager
SamplerManager m_SamplerManager; SamplerManager m_SamplerManager;
void EraseWrites(u32 handleIndex, HandleType handleType); void EraseWrites(u32 handleIndex, HandleType handleType);
BufferHandle Commit_(StorageBuffer *storageBuffer); // Commit to GPU and take Ownership
public: public:
Device *m_Device; Device *m_Device;
@ -198,7 +200,7 @@ struct RenderResourceManager
bool m_UseBufferAddr; bool m_UseBufferAddr;
BufferHandle Commit(StorageBuffer *storageBuffer); // Commit to GPU and take Ownership BufferHandle CreateStorageBuffer(u32 bufferSize, cstr name); // Allocate a new buffer and commit to GPU.
void Write(BufferHandle handle, usize offset, usize size, const void *data); // Write to buffer void Write(BufferHandle handle, usize offset, usize size, const void *data); // Write to buffer
void Release(BufferHandle handle); // Release and Destroy void Release(BufferHandle handle); // Release and Destroy
void Release(StorageBuffer *storageBuffer, BufferHandle handle); // Release and Return void Release(StorageBuffer *storageBuffer, BufferHandle handle); // Release and Return