Merge pull request 'resource_management' (#66) from resource_management into master
Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/66
This commit is contained in:
@@ -98,6 +98,15 @@ namespace OpenVulkano
|
|||||||
Fill(defaultValue);
|
Fill(defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename... ARGS>
|
||||||
|
Array(size_t size, ARGS... args) : size(size), data(MakeBuffer(size))
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
new (&data[i]) T(args...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~Array() noexcept
|
~Array() noexcept
|
||||||
{
|
{
|
||||||
ClearData();
|
ClearData();
|
||||||
|
|||||||
@@ -253,7 +253,11 @@ namespace OpenVulkano::GLFW
|
|||||||
vk::SurfaceKHR WindowGLFW::CreateSurface(const vk::Instance& instance, const vk::AllocationCallbacks* pAllocator)
|
vk::SurfaceKHR WindowGLFW::CreateSurface(const vk::Instance& instance, const vk::AllocationCallbacks* pAllocator)
|
||||||
{
|
{
|
||||||
VkSurfaceKHR rawSurface;
|
VkSurfaceKHR rawSurface;
|
||||||
const auto result = static_cast<vk::Result>(glfwCreateWindowSurface(static_cast<VkInstance>(instance), window, reinterpret_cast<const VkAllocationCallbacks*>(pAllocator), &rawSurface));
|
const vk::Result result = static_cast<vk::Result>(glfwCreateWindowSurface(static_cast<VkInstance>(instance), window, reinterpret_cast<const VkAllocationCallbacks*>(pAllocator), &rawSurface));
|
||||||
|
if (result != vk::Result::eSuccess) [[unlikely]]
|
||||||
|
{
|
||||||
|
Logger::WINDOW->error("Failed to create vulkan surface. Result: {}", vk::to_string(result));
|
||||||
|
}
|
||||||
return rawSurface;//createResultValue(result, rawSurface, "vk::CommandBuffer::begin");
|
return rawSurface;//createResultValue(result, rawSurface, "vk::CommandBuffer::begin");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,19 +286,19 @@ namespace OpenVulkano::GLFW
|
|||||||
|
|
||||||
void WindowGLFW::OnFocusLost()
|
void WindowGLFW::OnFocusLost()
|
||||||
{
|
{
|
||||||
Logger::WINDOW->debug("Window (id: {0}) focus lost", GetWindowId());
|
Logger::WINDOW->trace("Window (id: {0}) focus lost", GetWindowId());
|
||||||
handler->OnWindowFocusLost(this);
|
handler->OnWindowFocusLost(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowGLFW::OnFocusGained()
|
void WindowGLFW::OnFocusGained()
|
||||||
{
|
{
|
||||||
Logger::WINDOW->debug("Window (id: {0}) focus gained", GetWindowId());
|
Logger::WINDOW->trace("Window (id: {0}) focus gained", GetWindowId());
|
||||||
handler->OnWindowFocusGained(this);
|
handler->OnWindowFocusGained(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowGLFW::OnMove(const int posX, const int posY)
|
void WindowGLFW::OnMove(const int posX, const int posY)
|
||||||
{
|
{
|
||||||
Logger::WINDOW->debug("Window (id: {0}) moved (x: {1}, y: {2})", GetWindowId(), posX, posY);
|
Logger::WINDOW->trace("Window (id: {0}) moved (x: {1}, y: {2})", GetWindowId(), posX, posY);
|
||||||
if (windowConfig.windowMode == WINDOWED || windowConfig.windowMode == BORDERLESS)
|
if (windowConfig.windowMode == WINDOWED || windowConfig.windowMode == BORDERLESS)
|
||||||
{ // Don't save window position for fullscreen
|
{ // Don't save window position for fullscreen
|
||||||
windowConfig.position.x = posX;
|
windowConfig.position.x = posX;
|
||||||
|
|||||||
@@ -132,36 +132,40 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void NamedEventProcessor::Notify(const std::string& eventName, const std::vector<Parameters>& parameters) const
|
void NamedEventProcessor::Notify(const std::string& eventName, const std::vector<Parameters>& parameters) const
|
||||||
{
|
{
|
||||||
if (Class eventClass = FindGenericEventClass(m_classNamePrefixes, m_classNameSuffixes, eventName))
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
if (SEL init = GetInitForClass(eventClass, BuildTypeName(parameters)))
|
if (Class eventClass = FindGenericEventClass(m_classNamePrefixes, m_classNameSuffixes, eventName))
|
||||||
{
|
{
|
||||||
NSObject* event = [eventClass alloc];
|
if (SEL init = GetInitForClass(eventClass, BuildTypeName(parameters)))
|
||||||
auto inv = [NSInvocation invocationWithMethodSignature:[event methodSignatureForSelector:init]];
|
|
||||||
[inv setTarget:event];
|
|
||||||
[inv setSelector:init];
|
|
||||||
for (int i = 0; i < parameters.size(); i++)
|
|
||||||
{
|
{
|
||||||
auto arg = std::visit([](auto&& arg) { return CreateValue(arg); }, parameters[i]);
|
NSObject* event = [eventClass alloc];
|
||||||
[inv setArgument:&arg atIndex:(i + 2)];
|
auto inv = [NSInvocation invocationWithMethodSignature:[event methodSignatureForSelector:init]];
|
||||||
|
[inv setTarget:event];
|
||||||
|
[inv setSelector:init];
|
||||||
|
for (int i = 0; i < parameters.size(); i++)
|
||||||
|
{
|
||||||
|
auto arg = std::visit([](auto&& arg) { return CreateValue(arg); }, parameters[i]);
|
||||||
|
[inv setArgument:&arg atIndex:(i + 2)];
|
||||||
|
}
|
||||||
|
[inv invoke];
|
||||||
|
for (Class clazz = eventClass; clazz && clazz != NSObject.class; clazz = class_getSuperclass(clazz))
|
||||||
|
{
|
||||||
|
NSString* notificationName;
|
||||||
|
if (m_useClassNameAsEventName) notificationName = NSStringFromClass(clazz);
|
||||||
|
else notificationName = [NSString stringWithUTF8String:eventName.c_str()];
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:event userInfo:nil];
|
||||||
|
}
|
||||||
|
[event release];
|
||||||
}
|
}
|
||||||
[inv invoke];
|
else
|
||||||
for (Class clazz = eventClass; clazz && clazz != NSObject.class; clazz = class_getSuperclass(clazz))
|
|
||||||
{
|
{
|
||||||
NSString* notificationName;
|
Logger::MANAGER->error("Cannot find constructor for named event %s", eventName);
|
||||||
if (m_useClassNameAsEventName) notificationName = NSStringFromClass(clazz);
|
|
||||||
else notificationName = [NSString stringWithUTF8String:eventName.c_str()];
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:event userInfo:nil];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger::MANAGER->error("Cannot find constructor for named event %s", eventName);
|
Logger::MANAGER->debug("Cannot find implementation for named event %s", eventName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger::MANAGER->debug("Cannot find implementation for named event %s", eventName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#import "OpenVulkanoView.h"
|
#import "OpenVulkanoView.h"
|
||||||
|
|
||||||
|
#include "Base/Logger.hpp"
|
||||||
#include "Input/Touch/InputDeviceTouch.hpp"
|
#include "Input/Touch/InputDeviceTouch.hpp"
|
||||||
#include "Input/InputManager.hpp"
|
#include "Input/InputManager.hpp"
|
||||||
#include "MetalViewWindow.h"
|
#include "MetalViewWindow.h"
|
||||||
@@ -113,6 +114,7 @@ using namespace OpenVulkano;
|
|||||||
m_touchDevice.Close();
|
m_touchDevice.Close();
|
||||||
[m_displayLink release];
|
[m_displayLink release];
|
||||||
[m_mtdelegate release];
|
[m_mtdelegate release];
|
||||||
|
OpenVulkano::Logger::WINDOW->info("Destroyed OpenVulkanoView");
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ using namespace OpenVulkano;
|
|||||||
|
|
||||||
-(void) dealloc {
|
-(void) dealloc {
|
||||||
manager->ShutDown();
|
manager->ShutDown();
|
||||||
|
delete manager;
|
||||||
|
app = nullptr;
|
||||||
|
//TODO figure out where these two references are held
|
||||||
|
[_openVulkanoView release];
|
||||||
|
[_openVulkanoView release];
|
||||||
|
_openVulkanoView = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ namespace OpenVulkano::Vulkan
|
|||||||
//TODO
|
//TODO
|
||||||
|
|
||||||
if (enableValidationLayer) Debug::CloseValidationLayers(instance);
|
if (enableValidationLayer) Debug::CloseValidationLayers(instance);
|
||||||
|
|
||||||
|
instance.destroy();
|
||||||
initialized = false;
|
initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ namespace OpenVulkano::Vulkan
|
|||||||
void Device::Close()
|
void Device::Close()
|
||||||
{
|
{
|
||||||
device.destroyCommandPool(graphicsCommandPool);
|
device.destroyCommandPool(graphicsCommandPool);
|
||||||
|
device.destroyPipelineCache(pipelineCache);
|
||||||
|
device.destroy();
|
||||||
//TODO fill
|
//TODO fill
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ namespace OpenVulkano
|
|||||||
public:
|
public:
|
||||||
Device(vk::PhysicalDevice& physicalDevice);
|
Device(vk::PhysicalDevice& physicalDevice);
|
||||||
|
|
||||||
|
~Device() { if (device) Close(); }
|
||||||
|
|
||||||
[[nodiscard]] std::string GetDeviceName() const
|
[[nodiscard]] std::string GetDeviceName() const
|
||||||
{
|
{
|
||||||
return properties.deviceName.data();
|
return properties.deviceName.data();
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ namespace OpenVulkano::Vulkan
|
|||||||
Init(instance);
|
Init(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
~DeviceManager() = default;
|
~DeviceManager()
|
||||||
|
{
|
||||||
|
if (!devices.empty()) Close();
|
||||||
|
}
|
||||||
|
|
||||||
void Init(const vk::Instance& instance);
|
void Init(const vk::Instance& instance);
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ namespace OpenVulkano::Vulkan
|
|||||||
for (int i = 0; i < context.swapChain.GetImageCount(); i++)
|
for (int i = 0; i < context.swapChain.GetImageCount(); i++)
|
||||||
{
|
{
|
||||||
waitSemaphores.emplace_back();
|
waitSemaphores.emplace_back();
|
||||||
waitSemaphores[i].renderComplete.push_back(context.device->device.createSemaphore({}));
|
vk::Semaphore sema = context.device->device.createSemaphore({});
|
||||||
|
semaphores.push_back(sema);
|
||||||
|
waitSemaphores[i].renderComplete.push_back(sema);
|
||||||
waitSemaphores[i].renderReady.resize(2);
|
waitSemaphores[i].renderReady.resize(2);
|
||||||
}
|
}
|
||||||
resourceManager.Init(&context, context.swapChain.GetImageCount());
|
resourceManager.Init(&context, context.swapChain.GetImageCount());
|
||||||
@@ -72,9 +74,15 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
void Renderer::Close()
|
void Renderer::Close()
|
||||||
{
|
{
|
||||||
|
context.device->WaitIdle();
|
||||||
|
for (auto& sema : semaphores)
|
||||||
|
{
|
||||||
|
context.device->device.destroySemaphore(sema);
|
||||||
|
}
|
||||||
|
uiRenderer.Close();
|
||||||
resourceManager.Close();
|
resourceManager.Close();
|
||||||
context.Close();
|
context.Close();
|
||||||
uiRenderer.Close();
|
scene = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Renderer::GetMainRenderDeviceName()
|
std::string Renderer::GetMainRenderDeviceName()
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
{
|
{
|
||||||
Context context;
|
Context context;
|
||||||
std::shared_ptr<spdlog::logger> logger;
|
std::shared_ptr<spdlog::logger> logger;
|
||||||
|
std::vector<vk::Semaphore> semaphores;
|
||||||
std::vector<WaitSemaphores> waitSemaphores;
|
std::vector<WaitSemaphores> waitSemaphores;
|
||||||
Scene::Scene* scene = nullptr;
|
Scene::Scene* scene = nullptr;
|
||||||
ResourceManager resourceManager;
|
ResourceManager resourceManager;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
struct VulkanShader;
|
class VulkanShader;
|
||||||
|
|
||||||
class IShaderOwner
|
class IShaderOwner
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,100 +8,17 @@
|
|||||||
|
|
||||||
#define CRASH_ON_MULTIPLE_MAPPINGS_TO_SAME_ALLOCATION
|
#define CRASH_ON_MULTIPLE_MAPPINGS_TO_SAME_ALLOCATION
|
||||||
|
|
||||||
|
#include "MemoryAllocation.hpp"
|
||||||
|
#include "MemoryPool.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vulkan/vulkan.hpp>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "Base/Utils.hpp"
|
|
||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
struct MemoryAllocation
|
class ManagedBuffer
|
||||||
{
|
{
|
||||||
vk::DeviceMemory memory;
|
|
||||||
size_t used;
|
|
||||||
const size_t size;
|
|
||||||
const uint32_t type;
|
|
||||||
const vk::Device device;
|
|
||||||
void* mapped;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t mappedCount;
|
|
||||||
static constexpr uint32_t CHILD_MAPPED_FLAG = 1u << 31;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryAllocation(size_t size, uint32_t type, vk::Device device):
|
using Ptr = std::unique_ptr<ManagedBuffer, ManagedBufferDeleter>;
|
||||||
memory(nullptr), used(0), size(size), type(type), device(device), mapped(nullptr), mappedCount(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~MemoryAllocation()
|
|
||||||
{
|
|
||||||
if (device && memory)
|
|
||||||
device.free(memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] size_t FreeSpace() const
|
|
||||||
{
|
|
||||||
return size - used;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] size_t FreeSpace(size_t alignment) const
|
|
||||||
{
|
|
||||||
return size - Utils::Align(used, alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleChildMappingValidation() const;
|
|
||||||
|
|
||||||
void* Map()
|
|
||||||
{
|
|
||||||
HandleChildMappingValidation();
|
|
||||||
if (!mapped)
|
|
||||||
{
|
|
||||||
mapped = device.mapMemory(memory, 0, size, vk::MemoryMapFlags());
|
|
||||||
}
|
|
||||||
mappedCount++;
|
|
||||||
return mapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnMap()
|
|
||||||
{
|
|
||||||
if (mappedCount > 0)
|
|
||||||
{
|
|
||||||
mappedCount--;
|
|
||||||
if (mappedCount == 0)
|
|
||||||
{
|
|
||||||
device.unmapMemory(memory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsChildMapped() const
|
|
||||||
{
|
|
||||||
return mappedCount & CHILD_MAPPED_FLAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* MapChild(size_t offset, vk::DeviceSize size)
|
|
||||||
{
|
|
||||||
HandleChildMappingValidation();
|
|
||||||
mappedCount |= CHILD_MAPPED_FLAG;
|
|
||||||
mappedCount++;
|
|
||||||
return device.mapMemory(memory, offset, size, vk::MemoryMapFlags());
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnMapChild()
|
|
||||||
{
|
|
||||||
mappedCount &= ~CHILD_MAPPED_FLAG;
|
|
||||||
mappedCount--;
|
|
||||||
if (mappedCount == 0)
|
|
||||||
{
|
|
||||||
device.unmapMemory(memory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ManagedBuffer
|
|
||||||
{
|
|
||||||
using Ptr = std::unique_ptr<ManagedBuffer, std::function<void(ManagedBuffer*)>>;
|
|
||||||
|
|
||||||
MemoryAllocation* allocation;
|
MemoryAllocation* allocation;
|
||||||
vk::DeviceSize offset, size;
|
vk::DeviceSize offset, size;
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ManagedResource.hpp"
|
#include "ManagedBuffer.hpp"
|
||||||
#include "Base/Logger.hpp"
|
#include "Base/Logger.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
97
openVulkanoCpp/Vulkan/Resources/MemoryAllocation.hpp
Normal file
97
openVulkanoCpp/Vulkan/Resources/MemoryAllocation.hpp
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Base/Utils.hpp"
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
namespace OpenVulkano::Vulkan
|
||||||
|
{
|
||||||
|
struct MemoryAllocation
|
||||||
|
{
|
||||||
|
vk::DeviceMemory memory;
|
||||||
|
size_t used;
|
||||||
|
const size_t size;
|
||||||
|
const uint32_t type;
|
||||||
|
const vk::Device device;
|
||||||
|
void* mapped;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t mappedCount;
|
||||||
|
static constexpr uint32_t CHILD_MAPPED_FLAG = 1u << 31;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MemoryAllocation(size_t size, uint32_t type, vk::Device device):
|
||||||
|
memory(nullptr), used(0), size(size), type(type), device(device), mapped(nullptr), mappedCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~MemoryAllocation()
|
||||||
|
{
|
||||||
|
if (device && memory)
|
||||||
|
device.free(memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] size_t FreeSpace() const
|
||||||
|
{
|
||||||
|
return size - used;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] size_t FreeSpace(size_t alignment) const
|
||||||
|
{
|
||||||
|
return size - Utils::Align(used, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleChildMappingValidation() const;
|
||||||
|
|
||||||
|
void* Map()
|
||||||
|
{
|
||||||
|
HandleChildMappingValidation();
|
||||||
|
if (!mapped)
|
||||||
|
{
|
||||||
|
mapped = device.mapMemory(memory, 0, size, vk::MemoryMapFlags());
|
||||||
|
}
|
||||||
|
mappedCount++;
|
||||||
|
return mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnMap()
|
||||||
|
{
|
||||||
|
if (mappedCount > 0)
|
||||||
|
{
|
||||||
|
mappedCount--;
|
||||||
|
if (mappedCount == 0)
|
||||||
|
{
|
||||||
|
device.unmapMemory(memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsChildMapped() const
|
||||||
|
{
|
||||||
|
return mappedCount & CHILD_MAPPED_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MapChild(size_t offset, vk::DeviceSize size)
|
||||||
|
{
|
||||||
|
HandleChildMappingValidation();
|
||||||
|
mappedCount |= CHILD_MAPPED_FLAG;
|
||||||
|
mappedCount++;
|
||||||
|
return device.mapMemory(memory, offset, size, vk::MemoryMapFlags());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnMapChild()
|
||||||
|
{
|
||||||
|
mappedCount &= ~CHILD_MAPPED_FLAG;
|
||||||
|
mappedCount--;
|
||||||
|
if (mappedCount == 0)
|
||||||
|
{
|
||||||
|
device.unmapMemory(memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
153
openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp
Normal file
153
openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MemoryPool.hpp"
|
||||||
|
#include "ManagedBuffer.hpp"
|
||||||
|
#include "Vulkan/Device.hpp"
|
||||||
|
#include "Base/Logger.hpp"
|
||||||
|
#include "Math/ByteSize.hpp"
|
||||||
|
|
||||||
|
namespace OpenVulkano::Vulkan
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::vector<MemoryPool*> MEM_POOLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryPool::ReleaseBuffer(OpenVulkano::Vulkan::ManagedBuffer* buffer)
|
||||||
|
{
|
||||||
|
for (MemoryPool* memPool : MEM_POOLS)
|
||||||
|
{
|
||||||
|
if (memPool->FreeBuffer(buffer)) return;
|
||||||
|
}
|
||||||
|
delete buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryPool::~MemoryPool()
|
||||||
|
{
|
||||||
|
if (!allocations.empty()) Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryPool::Close()
|
||||||
|
{
|
||||||
|
Utils::Remove(MEM_POOLS, this);
|
||||||
|
for(ManagedBuffer* buffer : recycleBuffers)
|
||||||
|
{
|
||||||
|
delete buffer;
|
||||||
|
}
|
||||||
|
recycleBuffers.clear();
|
||||||
|
for(auto& fF : toFree)
|
||||||
|
{
|
||||||
|
for(ManagedBuffer* buffer : fF)
|
||||||
|
{
|
||||||
|
delete buffer;
|
||||||
|
}
|
||||||
|
fF.clear();
|
||||||
|
}
|
||||||
|
allocations.clear();
|
||||||
|
Logger::RENDER->info("Destroyed gpu memory pool");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryPool::Init(Device* dev, int bufferCount)
|
||||||
|
{
|
||||||
|
device = dev;
|
||||||
|
toFree = decltype(toFree)(bufferCount);
|
||||||
|
MEM_POOLS.push_back(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryPool::StartFrame(uint64_t bufferId)
|
||||||
|
{
|
||||||
|
currentBuffer = bufferId;
|
||||||
|
for (ManagedBuffer* i : toFree[currentBuffer])
|
||||||
|
{
|
||||||
|
DoFree(i);
|
||||||
|
}
|
||||||
|
toFree[currentBuffer].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryPool::DoFree(ManagedBuffer* buffer)
|
||||||
|
{
|
||||||
|
if (buffer->IsLast())
|
||||||
|
{
|
||||||
|
device->device.destroyBuffer(buffer->buffer);
|
||||||
|
buffer->allocation->used -= buffer->size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recycleBuffers.push_back(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryPool::FreeBuffer(ManagedBuffer* buffer)
|
||||||
|
{
|
||||||
|
if (buffer) toFree[currentBuffer].push_back(buffer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAllocation* MemoryPool::CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache)
|
||||||
|
{
|
||||||
|
MemoryAllocation* alloc = new MemoryAllocation(size, type, device->device);
|
||||||
|
const vk::MemoryAllocateInfo allocInfo = { size, type };
|
||||||
|
alloc->memory = device->device.allocateMemory(allocInfo);
|
||||||
|
if (addToCache) allocations.emplace_back(alloc);
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryAllocation* MemoryPool::GetFreeMemoryAllocation(size_t size, vk::DeviceSize alignment, uint32_t type, bool createIfAllFull)
|
||||||
|
{
|
||||||
|
MemoryAllocation* alloc = nullptr;
|
||||||
|
for (auto& allocation : allocations)
|
||||||
|
{
|
||||||
|
if (allocation->type == type && allocation->FreeSpace(alignment) >= size)
|
||||||
|
{
|
||||||
|
alloc = allocation.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!alloc && createIfAllFull) alloc = CreateMemoryAllocation(64_MiB, type, true);
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryPool::ManagedBufferPtr MemoryPool::CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties)
|
||||||
|
{
|
||||||
|
size = Utils::Align(size, 16);
|
||||||
|
vk::BufferCreateInfo bufferCreateInfo = { {}, size, usage, vk::SharingMode::eExclusive };
|
||||||
|
vk::Buffer buffer = device->device.createBuffer(bufferCreateInfo);
|
||||||
|
const vk::MemoryRequirements memoryRequirements = device->device.getBufferMemoryRequirements(buffer);
|
||||||
|
uint32_t memtype = device->GetMemoryType(memoryRequirements.memoryTypeBits, properties);
|
||||||
|
if (memoryRequirements.size != size)
|
||||||
|
{
|
||||||
|
Logger::DATA->debug("Memory Requirement Size ({0}) != Size ({1})", memoryRequirements.size, size);
|
||||||
|
size = memoryRequirements.size;
|
||||||
|
device->device.destroy(buffer);
|
||||||
|
bufferCreateInfo.size = size;
|
||||||
|
buffer = device->device.createBuffer(bufferCreateInfo);
|
||||||
|
}
|
||||||
|
MemoryAllocation* allocation = GetFreeMemoryAllocation(size, memoryRequirements.alignment, memtype);
|
||||||
|
uint32_t offset = Utils::Align(allocation->used, memoryRequirements.alignment);
|
||||||
|
device->device.bindBufferMemory(buffer, allocation->memory, offset);
|
||||||
|
allocation->used += size + (offset - allocation->used);
|
||||||
|
return ManagedBufferPtr{ new ManagedBuffer({allocation, offset, size, buffer, usage, properties, nullptr}) };
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryPool::ManagedBufferPtr MemoryPool::CreateSharedMemoryBuffer(size_t size)
|
||||||
|
{
|
||||||
|
if (!recycleBuffers.empty())
|
||||||
|
{
|
||||||
|
for(auto buff : recycleBuffers)
|
||||||
|
{
|
||||||
|
if (buff->size == size)
|
||||||
|
{
|
||||||
|
Logger::DATA->info("Recycle Buffer");
|
||||||
|
Utils::Remove(recycleBuffers, buff);
|
||||||
|
return ManagedBufferPtr{ buff };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent/* | vk::MemoryPropertyFlagBits::eDeviceLocal*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
66
openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp
Normal file
66
openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Data/Containers/Array.hpp"
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
namespace OpenVulkano::Vulkan
|
||||||
|
{
|
||||||
|
class Device;
|
||||||
|
class MemoryAllocation;
|
||||||
|
class ManagedBuffer;
|
||||||
|
struct ManagedBufferDeleter;
|
||||||
|
|
||||||
|
class MemoryPool
|
||||||
|
{
|
||||||
|
Device* device;
|
||||||
|
std::vector<std::unique_ptr<MemoryAllocation>> allocations;
|
||||||
|
Array<std::vector<ManagedBuffer*>> toFree;
|
||||||
|
std::vector<ManagedBuffer*> recycleBuffers;
|
||||||
|
std::function<void(ManagedBuffer*)> freeFunction;
|
||||||
|
|
||||||
|
uint64_t currentBuffer = 0;
|
||||||
|
|
||||||
|
void DoFree(ManagedBuffer* buffer);
|
||||||
|
|
||||||
|
bool FreeBuffer(ManagedBuffer* buffer);
|
||||||
|
public:
|
||||||
|
using ManagedBufferPtr = std::unique_ptr<ManagedBuffer, ManagedBufferDeleter>;
|
||||||
|
|
||||||
|
MemoryPool() = default;
|
||||||
|
|
||||||
|
~MemoryPool();
|
||||||
|
|
||||||
|
void Init(Device* dev, int bufferCount);
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
void StartFrame(uint64_t bufferId);
|
||||||
|
|
||||||
|
MemoryAllocation* CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache = true);
|
||||||
|
|
||||||
|
MemoryAllocation* GetFreeMemoryAllocation(size_t size, vk::DeviceSize alignment, uint32_t type, bool createIfAllFull = true);
|
||||||
|
|
||||||
|
ManagedBufferPtr CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties);
|
||||||
|
|
||||||
|
ManagedBufferPtr CreateSharedMemoryBuffer(size_t size);
|
||||||
|
|
||||||
|
static void ReleaseBuffer(ManagedBuffer* buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ManagedBufferDeleter
|
||||||
|
{
|
||||||
|
void operator()(ManagedBuffer* buffer)
|
||||||
|
{
|
||||||
|
MemoryPool::ReleaseBuffer(buffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -5,10 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ResourceManager.hpp"
|
#include "ResourceManager.hpp"
|
||||||
|
#include "ManagedBuffer.hpp"
|
||||||
|
#include "MemoryAllocation.hpp"
|
||||||
#include "Scene/Vertex.hpp"
|
#include "Scene/Vertex.hpp"
|
||||||
#include "Scene/Geometry.hpp"
|
#include "Scene/Geometry.hpp"
|
||||||
#include "Scene/Material.hpp"
|
#include "Scene/Material.hpp"
|
||||||
#include "Scene/UniformBuffer.hpp"
|
#include "Scene/UniformBuffer.hpp"
|
||||||
|
#include "Scene/Camera.hpp"
|
||||||
#include "Math/ByteSize.hpp"
|
#include "Math/ByteSize.hpp"
|
||||||
#include "Vulkan/Context.hpp"
|
#include "Vulkan/Context.hpp"
|
||||||
#include "Vulkan/Image.hpp"
|
#include "Vulkan/Image.hpp"
|
||||||
@@ -23,10 +26,33 @@ namespace OpenVulkano::Vulkan
|
|||||||
{
|
{
|
||||||
ResourceManager* ResourceManager::INSTANCE;
|
ResourceManager* ResourceManager::INSTANCE;
|
||||||
|
|
||||||
|
struct ResourceManager::FrameResources
|
||||||
|
{
|
||||||
|
vk::Device device;
|
||||||
|
vk::CommandPool cmdPool;
|
||||||
|
vk::CommandBuffer cmdBuffer;
|
||||||
|
vk::Semaphore semaphore;
|
||||||
|
|
||||||
|
FrameResources(Device* device)
|
||||||
|
{
|
||||||
|
this->device = device->device;
|
||||||
|
cmdPool = this->device.createCommandPool({ {}, device->queueIndices.transfer });
|
||||||
|
cmdBuffer = this->device.allocateCommandBuffers({ cmdPool, vk::CommandBufferLevel::ePrimary, 1 })[0];
|
||||||
|
semaphore = this->device.createSemaphore({});
|
||||||
|
}
|
||||||
|
|
||||||
|
~FrameResources()
|
||||||
|
{
|
||||||
|
device.freeCommandBuffers(cmdPool, 1, &cmdBuffer);
|
||||||
|
device.destroyCommandPool(cmdPool);
|
||||||
|
device.destroy(semaphore);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
ResourceManager::ResourceManager()
|
ResourceManager::ResourceManager()
|
||||||
{
|
{
|
||||||
static_assert(sizeof(DescriptorSetLayoutBinding) == sizeof(vk::DescriptorSetLayoutBinding));
|
static_assert(sizeof(DescriptorSetLayoutBinding) == sizeof(vk::DescriptorSetLayoutBinding));
|
||||||
freeFunction = [this](ManagedBuffer* buffer) { this->FreeBuffer(buffer); };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceManager::~ResourceManager() noexcept
|
ResourceManager::~ResourceManager() noexcept
|
||||||
@@ -37,21 +63,13 @@ namespace OpenVulkano::Vulkan
|
|||||||
void ResourceManager::Init(Context* context, int buffers)
|
void ResourceManager::Init(Context* context, int buffers)
|
||||||
{
|
{
|
||||||
this->context = context;
|
this->context = context;
|
||||||
this->device = context->device->device;
|
device = context->device->device;
|
||||||
this->buffers = buffers;
|
|
||||||
|
|
||||||
uniformBufferAlignment = context->device->properties.limits.minUniformBufferOffsetAlignment;
|
uniformBufferAlignment = context->device->properties.limits.minUniformBufferOffsetAlignment;
|
||||||
|
|
||||||
|
frameResources = Array<FrameResources>(static_cast<size_t>(buffers), context->device.get());
|
||||||
|
|
||||||
cmdPools = new vk::CommandPool[buffers];
|
memPool.Init(context->device.get(), buffers);
|
||||||
cmdBuffers = new vk::CommandBuffer[buffers];
|
|
||||||
semaphores = new vk::Semaphore[buffers];
|
|
||||||
for (int i = 0; i < buffers; i++)
|
|
||||||
{
|
|
||||||
cmdPools[i] = this->device.createCommandPool({ {}, context->device->queueIndices.transfer });
|
|
||||||
cmdBuffers[i] = this->device.allocateCommandBuffers({ cmdPools[i], vk::CommandBufferLevel::ePrimary, 1 })[0];
|
|
||||||
semaphores[i] = this->device.createSemaphore({});
|
|
||||||
}
|
|
||||||
toFree.resize(buffers);
|
|
||||||
|
|
||||||
transferQueue = this->device.getQueue(context->device->queueIndices.transfer, 0);
|
transferQueue = this->device.getQueue(context->device->queueIndices.transfer, 0);
|
||||||
|
|
||||||
@@ -78,49 +96,44 @@ namespace OpenVulkano::Vulkan
|
|||||||
void ResourceManager::Close()
|
void ResourceManager::Close()
|
||||||
{
|
{
|
||||||
transferQueue.waitIdle();
|
transferQueue.waitIdle();
|
||||||
for (int i = 0; i < buffers; i++)
|
transferQueue = nullptr;
|
||||||
{
|
|
||||||
device.freeCommandBuffers(cmdPools[i], 1, &cmdBuffers[i]);
|
|
||||||
device.destroyCommandPool(cmdPools[i]);
|
|
||||||
device.destroy(semaphores[i]);
|
|
||||||
}
|
|
||||||
cmdPools = nullptr;
|
|
||||||
cmdBuffers = nullptr;
|
|
||||||
semaphores = nullptr;
|
|
||||||
geometries.clear();
|
geometries.clear();
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
|
textures.clear();
|
||||||
|
cameras.clear();
|
||||||
|
uniforms.clear();
|
||||||
device.destroyDescriptorPool(descriptorPool);
|
device.destroyDescriptorPool(descriptorPool);
|
||||||
allocations.clear();
|
|
||||||
lastAllocation = nullptr;
|
|
||||||
toFree.clear();
|
|
||||||
recycleBuffers.clear();
|
|
||||||
descriptorSetLayoutCache.clear();
|
|
||||||
for (auto& sampler : samplerCache)
|
for (auto& sampler : samplerCache)
|
||||||
{
|
{
|
||||||
device.destroy(sampler.second);
|
device.destroy(sampler.second);
|
||||||
}
|
}
|
||||||
samplerCache.clear();
|
samplerCache.clear();
|
||||||
|
for(auto& layout : descriptorSetLayoutCache)
|
||||||
|
{
|
||||||
|
device.destroy(layout.second);
|
||||||
|
}
|
||||||
|
descriptorSetLayoutCache.clear();
|
||||||
shaders.clear();
|
shaders.clear();
|
||||||
cmdBuffers = nullptr;
|
memPool.Close();
|
||||||
cmdPools = nullptr;
|
|
||||||
transferQueue = nullptr;
|
|
||||||
device = nullptr;
|
device = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vk::CommandBuffer& ResourceManager::GetCmdBuffer() { return frameResources[currentBuffer].cmdBuffer; }
|
||||||
|
|
||||||
void ResourceManager::StartFrame(uint64_t frameId)
|
void ResourceManager::StartFrame(uint64_t frameId)
|
||||||
{
|
{
|
||||||
currentBuffer = frameId;
|
currentBuffer = frameId;
|
||||||
FreeBuffers();
|
memPool.StartFrame(frameId);
|
||||||
device.resetCommandPool(cmdPools[currentBuffer], {});
|
device.resetCommandPool(frameResources[currentBuffer].cmdPool, {});
|
||||||
cmdBuffers[currentBuffer].begin({ vk::CommandBufferUsageFlagBits::eOneTimeSubmit });
|
GetCmdBuffer().begin({ vk::CommandBufferUsageFlagBits::eOneTimeSubmit });
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::Semaphore ResourceManager::EndFrame()
|
vk::Semaphore ResourceManager::EndFrame()
|
||||||
{
|
{
|
||||||
cmdBuffers[currentBuffer].end();
|
GetCmdBuffer().end();
|
||||||
vk::SubmitInfo si = { 0, nullptr, nullptr, 1, &cmdBuffers[currentBuffer], 1, &semaphores[currentBuffer] };
|
vk::SubmitInfo si = { 0, nullptr, nullptr, 1, &frameResources[currentBuffer].cmdBuffer, 1, &frameResources[currentBuffer].semaphore };
|
||||||
transferQueue.submit(1, &si, vk::Fence());
|
transferQueue.submit(1, &si, vk::Fence());
|
||||||
return semaphores[currentBuffer];
|
return frameResources[currentBuffer].semaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::Resize()
|
void ResourceManager::Resize()
|
||||||
@@ -136,12 +149,10 @@ namespace OpenVulkano::Vulkan
|
|||||||
const std::unique_lock lock(mutex);
|
const std::unique_lock lock(mutex);
|
||||||
if(!geometry->renderGeo)
|
if(!geometry->renderGeo)
|
||||||
{
|
{
|
||||||
ManagedBuffer::Ptr vertexBuffer(
|
ManagedBuffer::Ptr vertexBuffer =
|
||||||
CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices()),
|
CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices());
|
||||||
freeFunction);
|
ManagedBuffer::Ptr indexBuffer =
|
||||||
ManagedBuffer::Ptr indexBuffer(
|
CreateDeviceOnlyBufferWithData(Utils::EnumAsInt(geometry->indexType) * geometry->GetIndexCount(), vk::BufferUsageFlagBits::eIndexBuffer, geometry->GetIndices());
|
||||||
CreateDeviceOnlyBufferWithData(Utils::EnumAsInt(geometry->indexType) * geometry->GetIndexCount(), vk::BufferUsageFlagBits::eIndexBuffer, geometry->GetIndices()),
|
|
||||||
freeFunction);
|
|
||||||
VulkanGeometry* vkGeo = new VulkanGeometry(geometry, vertexBuffer, indexBuffer);
|
VulkanGeometry* vkGeo = new VulkanGeometry(geometry, vertexBuffer, indexBuffer);
|
||||||
geometries.emplace_back(vkGeo);
|
geometries.emplace_back(vkGeo);
|
||||||
geometry->renderGeo = vkGeo;
|
geometry->renderGeo = vkGeo;
|
||||||
@@ -164,7 +175,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
if (!node->renderNode)
|
if (!node->renderNode)
|
||||||
{
|
{
|
||||||
UniformBuffer* uBuffer = new UniformBuffer();
|
UniformBuffer* uBuffer = new UniformBuffer();
|
||||||
ManagedBuffer* buffer;
|
ManagedBuffer::Ptr buffer;
|
||||||
VulkanNode* vkNode;
|
VulkanNode* vkNode;
|
||||||
const vk::DeviceSize allocSize = Utils::Align(sizeof(Math::Matrix4f), uniformBufferAlignment);
|
const vk::DeviceSize allocSize = Utils::Align(sizeof(Math::Matrix4f), uniformBufferAlignment);
|
||||||
vk::DeviceSize frameSize = 0;
|
vk::DeviceSize frameSize = 0;
|
||||||
@@ -173,7 +184,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
frameSize = allocSize;
|
frameSize = allocSize;
|
||||||
vkNode = new VulkanNodeDynamic();
|
vkNode = new VulkanNodeDynamic();
|
||||||
const uint32_t imgs = context->swapChain.GetImageCount();
|
const uint32_t imgs = context->swapChain.GetImageCount();
|
||||||
buffer = CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
buffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
buffer->Map();
|
buffer->Map();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -182,7 +193,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
buffer = CreateDeviceOnlyBufferWithData(Scene::Node::SIZE, vk::BufferUsageFlagBits::eUniformBuffer, &node->worldMat);
|
buffer = CreateDeviceOnlyBufferWithData(Scene::Node::SIZE, vk::BufferUsageFlagBits::eUniformBuffer, &node->worldMat);
|
||||||
}
|
}
|
||||||
|
|
||||||
uBuffer->Init(buffer, frameSize, allocSize, GetDescriptorLayoutSet(Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING, 0);
|
uBuffer->Init(std::move(buffer), frameSize, allocSize, GetDescriptorLayoutSet(Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING, 0);
|
||||||
vkNode->Init(node, uBuffer);
|
vkNode->Init(node, uBuffer);
|
||||||
node->renderNode = vkNode;
|
node->renderNode = vkNode;
|
||||||
nodes.emplace_back(vkNode);
|
nodes.emplace_back(vkNode);
|
||||||
@@ -197,12 +208,13 @@ namespace OpenVulkano::Vulkan
|
|||||||
{
|
{
|
||||||
const vk::DeviceSize allocSize = Utils::Align(Scene::Camera::SIZE, uniformBufferAlignment);
|
const vk::DeviceSize allocSize = Utils::Align(Scene::Camera::SIZE, uniformBufferAlignment);
|
||||||
const uint32_t imgs = context->swapChain.GetImageCount();
|
const uint32_t imgs = context->swapChain.GetImageCount();
|
||||||
ManagedBuffer* buffer = CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
ManagedBuffer::Ptr buffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
buffer->Map();
|
buffer->Map();
|
||||||
UniformBuffer* uBuffer = new UniformBuffer();
|
UniformBuffer* uBuffer = new UniformBuffer();
|
||||||
uBuffer->Init(buffer, allocSize, allocSize, GetDescriptorLayoutSet(Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING, 1);
|
uBuffer->Init(std::move(buffer), allocSize, allocSize, GetDescriptorLayoutSet(Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING, 1);
|
||||||
VulkanCamera* vkCam = new VulkanCamera();
|
VulkanCamera* vkCam = new VulkanCamera();
|
||||||
vkCam->Init(camera, uBuffer);
|
vkCam->Init(camera, uBuffer);
|
||||||
|
cameras.emplace_back(vkCam);
|
||||||
camera->renderCamera = vkCam;
|
camera->renderCamera = vkCam;
|
||||||
}
|
}
|
||||||
return static_cast<VulkanCamera*>(camera->renderCamera);
|
return static_cast<VulkanCamera*>(camera->renderCamera);
|
||||||
@@ -216,7 +228,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
auto buffer = CreateDeviceOnlyBufferWithData(allocSize, vk::BufferUsageFlagBits::eUniformBuffer, data);
|
auto buffer = CreateDeviceOnlyBufferWithData(allocSize, vk::BufferUsageFlagBits::eUniformBuffer, data);
|
||||||
|
|
||||||
UniformBuffer* uBuffer = new UniformBuffer();
|
UniformBuffer* uBuffer = new UniformBuffer();
|
||||||
uBuffer->Init(buffer, 0, allocSize, GetDescriptorLayoutSet(binding), binding, setId);
|
uBuffer->Init(std::move(buffer), 0, allocSize, GetDescriptorLayoutSet(binding), binding, setId);
|
||||||
return uBuffer;
|
return uBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,28 +243,15 @@ namespace OpenVulkano::Vulkan
|
|||||||
return &layout;
|
return &layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
ManagedBuffer* ResourceManager::CreateSharedMemoryBuffer(const size_t size)
|
MemoryPool::ManagedBufferPtr ResourceManager::CreateSharedMemoryBuffer(const size_t size)
|
||||||
{
|
{
|
||||||
const std::unique_lock lock(mutex);
|
const std::unique_lock lock(mutex);
|
||||||
if (!recycleBuffers.empty())
|
return memPool.CreateSharedMemoryBuffer(size);
|
||||||
{
|
|
||||||
for(auto buff : recycleBuffers)
|
|
||||||
{
|
|
||||||
if (buff->size == size)
|
|
||||||
{
|
|
||||||
Logger::DATA->info("Recycle Buffer");
|
|
||||||
Utils::Remove(recycleBuffers, buff);
|
|
||||||
return buff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ManagedBuffer* buffer = CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent/* | vk::MemoryPropertyFlagBits::eDeviceLocal*/);
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::RemoveShader(VulkanShader* shader)
|
void ResourceManager::RemoveShader(VulkanShader* shader)
|
||||||
{
|
{
|
||||||
if (!cmdPools) return;
|
if (!transferQueue) return;
|
||||||
const std::unique_lock lock(mutex);
|
const std::unique_lock lock(mutex);
|
||||||
std::vector<std::unique_ptr<VulkanShader>>::iterator object =
|
std::vector<std::unique_ptr<VulkanShader>>::iterator object =
|
||||||
find_if(shaders.begin(), shaders.end(),
|
find_if(shaders.begin(), shaders.end(),
|
||||||
@@ -261,121 +260,31 @@ namespace OpenVulkano::Vulkan
|
|||||||
shaders.erase(object);
|
shaders.erase(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::FreeBuffer(ManagedBuffer* buffer)
|
|
||||||
{
|
|
||||||
if (buffer)
|
|
||||||
toFree[currentBuffer].push_back(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::DoFreeBuffer(ManagedBuffer* buffer)
|
|
||||||
{
|
|
||||||
if (buffer->IsLast())
|
|
||||||
{
|
|
||||||
device.destroyBuffer(buffer->buffer);
|
|
||||||
buffer->allocation->used -= buffer->size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
recycleBuffers.push_back(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::FreeBuffers()
|
|
||||||
{
|
|
||||||
for (auto& i : toFree[currentBuffer])
|
|
||||||
{
|
|
||||||
DoFreeBuffer(i);
|
|
||||||
}
|
|
||||||
toFree[currentBuffer].clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResourceManager::CopyDataToImage(vk::DeviceSize size, void* data, Image* image)
|
void ResourceManager::CopyDataToImage(vk::DeviceSize size, void* data, Image* image)
|
||||||
{
|
{
|
||||||
ManagedBuffer* uploadBuffer = CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
ManagedBuffer::Ptr uploadBuffer = memPool.CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
uploadBuffer->Copy(data, size, 0);
|
uploadBuffer->Copy(data, size, 0);
|
||||||
|
|
||||||
image->SetLayout(cmdBuffers[currentBuffer], vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal);
|
image->SetLayout(GetCmdBuffer(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal);
|
||||||
|
|
||||||
vk::BufferImageCopy region(0, 0, 0, { vk::ImageAspectFlagBits::eColor, 0, 0, 1 }, { 0, 0, 0 }, image->extent);
|
vk::BufferImageCopy region(0, 0, 0, { vk::ImageAspectFlagBits::eColor, 0, 0, 1 }, { 0, 0, 0 }, image->extent);
|
||||||
cmdBuffers[currentBuffer].copyBufferToImage(uploadBuffer->buffer, image->image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
|
GetCmdBuffer().copyBufferToImage(uploadBuffer->buffer, image->image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
|
||||||
|
|
||||||
/*vk::ImageMemoryBarrier barrier {};
|
image->SetLayout(GetCmdBuffer(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eTransferDstOptimal);
|
||||||
barrier.oldLayout = vk::ImageLayout::eUndefined;
|
|
||||||
barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
|
|
||||||
barrier.image = image->image;
|
|
||||||
barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
|
|
||||||
barrier.subresourceRange.baseMipLevel = 0;
|
|
||||||
barrier.subresourceRange.levelCount = 1;
|
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
|
||||||
barrier.subresourceRange.layerCount = 1;
|
|
||||||
barrier.setSrcAccessMask({});
|
|
||||||
barrier.setDstAccessMask(vk::AccessFlagBits::eTransferWrite);*/
|
|
||||||
|
|
||||||
image->SetLayout(cmdBuffers[currentBuffer], vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eTransferDstOptimal);
|
|
||||||
|
|
||||||
// TODO set access masks for mip and array layers
|
// TODO set access masks for mip and array layers
|
||||||
//cmdBuffers[currentBuffer].pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr, 0, nullptr, 1, &barrier );
|
//GetCmdBuffer().pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr, 0, nullptr, 1, &barrier );
|
||||||
|
|
||||||
FreeBuffer(uploadBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ManagedBuffer* ResourceManager::CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data)
|
ManagedBuffer::Ptr ResourceManager::CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data)
|
||||||
{
|
{
|
||||||
ManagedBuffer* target = CreateBuffer(size, usage | vk::BufferUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal);
|
ManagedBuffer::Ptr target = memPool.CreateBuffer(size, usage | vk::BufferUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal);
|
||||||
ManagedBuffer* uploadBuffer = CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
ManagedBuffer::Ptr uploadBuffer = memPool.CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
uploadBuffer->Copy(data, size, 0);
|
uploadBuffer->Copy(data, size, 0);
|
||||||
RecordCopy(uploadBuffer->buffer, target->buffer, size);
|
RecordCopy(uploadBuffer->buffer, target->buffer, size);
|
||||||
FreeBuffer(uploadBuffer);
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
ManagedBuffer* ResourceManager::CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties)
|
|
||||||
{
|
|
||||||
size = Utils::Align(size, 16);
|
|
||||||
vk::BufferCreateInfo bufferCreateInfo = { {}, size, usage, vk::SharingMode::eExclusive };
|
|
||||||
vk::Buffer buffer = device.createBuffer(bufferCreateInfo);
|
|
||||||
const vk::MemoryRequirements memoryRequirements = device.getBufferMemoryRequirements(buffer);
|
|
||||||
uint32_t memtype = context->device->GetMemoryType(memoryRequirements.memoryTypeBits, properties);
|
|
||||||
if (memoryRequirements.size != size)
|
|
||||||
{
|
|
||||||
Logger::DATA->debug("Memory Requirement Size ({0}) != Size ({1})", memoryRequirements.size, size);
|
|
||||||
size = memoryRequirements.size;
|
|
||||||
device.destroy(buffer);
|
|
||||||
bufferCreateInfo.size = size;
|
|
||||||
buffer = device.createBuffer(bufferCreateInfo);
|
|
||||||
}
|
|
||||||
MemoryAllocation* allocation = GetFreeMemoryAllocation(size, memoryRequirements.alignment, memtype);
|
|
||||||
uint32_t offset = Utils::Align(allocation->used, memoryRequirements.alignment);
|
|
||||||
device.bindBufferMemory(buffer, allocation->memory, offset);
|
|
||||||
allocation->used += size + (offset - allocation->used);
|
|
||||||
return new ManagedBuffer{ allocation, offset, size, buffer, usage, properties, nullptr };
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryAllocation* ResourceManager::CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache)
|
|
||||||
{
|
|
||||||
MemoryAllocation* alloc = new MemoryAllocation(size, type, device);
|
|
||||||
const vk::MemoryAllocateInfo allocInfo = { size, type };
|
|
||||||
alloc->memory = device.allocateMemory(allocInfo);
|
|
||||||
if (addToCache) allocations.emplace_back(alloc);
|
|
||||||
return alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryAllocation* ResourceManager::GetFreeMemoryAllocation(size_t size, vk::DeviceSize alignment, uint32_t type, bool createIfAllFull)
|
|
||||||
{
|
|
||||||
MemoryAllocation* alloc = nullptr;
|
|
||||||
for (auto& allocation : allocations)
|
|
||||||
{
|
|
||||||
if (allocation->type == type && allocation->FreeSpace(alignment) >= size)
|
|
||||||
{
|
|
||||||
alloc = allocation.get();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!alloc && createIfAllFull) alloc = CreateMemoryAllocation(64_MiB, type, true);
|
|
||||||
if(alloc) lastAllocation = alloc;
|
|
||||||
return alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
VulkanShader* ResourceManager::CreateShader(Scene::Shader* shader)
|
VulkanShader* ResourceManager::CreateShader(Scene::Shader* shader)
|
||||||
{
|
{
|
||||||
const std::unique_lock lock(mutex);
|
const std::unique_lock lock(mutex);
|
||||||
@@ -398,6 +307,8 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
vkTexture->Init(this, texture, GetDescriptorLayoutSet(Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
vkTexture->Init(this, texture, GetDescriptorLayoutSet(Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
||||||
|
|
||||||
|
textures.emplace_back(vkTexture);
|
||||||
|
|
||||||
return vkTexture;
|
return vkTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,7 +318,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
if (buffer->renderBuffer) return static_cast<VulkanUniformBuffer*>(buffer->renderBuffer);
|
if (buffer->renderBuffer) return static_cast<VulkanUniformBuffer*>(buffer->renderBuffer);
|
||||||
|
|
||||||
VulkanUniformBuffer* vkBuffer;
|
VulkanUniformBuffer* vkBuffer;
|
||||||
ManagedBuffer* mBuffer;
|
ManagedBuffer::Ptr mBuffer;
|
||||||
const vk::DeviceSize allocSize = Utils::Align(buffer->size, uniformBufferAlignment);
|
const vk::DeviceSize allocSize = Utils::Align(buffer->size, uniformBufferAlignment);
|
||||||
vk::DeviceSize frameSize = 0;
|
vk::DeviceSize frameSize = 0;
|
||||||
if (buffer->GetUpdateFrequency() != Scene::UpdateFrequency::Never)
|
if (buffer->GetUpdateFrequency() != Scene::UpdateFrequency::Never)
|
||||||
@@ -415,7 +326,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
frameSize = allocSize;
|
frameSize = allocSize;
|
||||||
vkBuffer = new VulkanUniformBufferDynamic();
|
vkBuffer = new VulkanUniformBufferDynamic();
|
||||||
const uint32_t imgs = context->swapChain.GetImageCount();
|
const uint32_t imgs = context->swapChain.GetImageCount();
|
||||||
mBuffer = CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
mBuffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
|
||||||
mBuffer->Map();
|
mBuffer->Map();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -427,9 +338,11 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
|
|
||||||
UniformBuffer* uBuffer = new UniformBuffer();
|
UniformBuffer* uBuffer = new UniformBuffer();
|
||||||
uBuffer->Init(mBuffer, 0, mBuffer->size, GetDescriptorLayoutSet(buffer->binding), buffer->binding, buffer->setId);
|
const uint64_t s = mBuffer->size;
|
||||||
|
uBuffer->Init(std::move(mBuffer), 0, s, GetDescriptorLayoutSet(buffer->binding), buffer->binding, buffer->setId);
|
||||||
|
|
||||||
vkBuffer->Init(buffer, uBuffer);
|
vkBuffer->Init(buffer, uBuffer);
|
||||||
|
uniforms.emplace_back(vkBuffer);
|
||||||
return vkBuffer;
|
return vkBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,18 +7,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Workaround for libc++
|
// Workaround for libc++
|
||||||
|
#ifndef __cpp_lib_three_way_comparison
|
||||||
#define __cpp_lib_three_way_comparison 201907
|
#define __cpp_lib_three_way_comparison 201907
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "vulkan/vulkan.hpp"
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "IShaderOwner.hpp"
|
#include "IShaderOwner.hpp"
|
||||||
#include "ManagedResource.hpp"
|
#include "MemoryPool.hpp"
|
||||||
|
#include "Base/Wrapper.hpp"
|
||||||
#include "Vulkan/Image.hpp"
|
#include "Vulkan/Image.hpp"
|
||||||
#include "Scene/Shader/DescriptorInputDescription.hpp"
|
#include "Scene/Shader/DescriptorInputDescription.hpp"
|
||||||
#include "Scene/Camera.hpp"
|
#include <vulkan/vulkan.hpp>
|
||||||
#include <mutex>
|
|
||||||
#include <functional>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
{
|
{
|
||||||
@@ -29,6 +30,7 @@ namespace OpenVulkano
|
|||||||
class Material;
|
class Material;
|
||||||
class Texture;
|
class Texture;
|
||||||
class Shader;
|
class Shader;
|
||||||
|
class Camera;
|
||||||
class UniformBuffer;
|
class UniformBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,35 +41,39 @@ namespace OpenVulkano
|
|||||||
class VulkanTexture;
|
class VulkanTexture;
|
||||||
class VulkanCamera;
|
class VulkanCamera;
|
||||||
class VulkanNode;
|
class VulkanNode;
|
||||||
|
class VulkanShader;
|
||||||
class VulkanUniformBuffer;
|
class VulkanUniformBuffer;
|
||||||
class UniformBuffer;
|
class UniformBuffer;
|
||||||
|
class ManagedBuffer;
|
||||||
|
class MemoryAllocation;
|
||||||
|
|
||||||
class ResourceManager : public ICloseable, public IShaderOwner
|
class ResourceManager : public IShaderOwner
|
||||||
{
|
{
|
||||||
friend UniformBuffer;
|
friend UniformBuffer;
|
||||||
friend VulkanTexture;
|
friend VulkanTexture;
|
||||||
|
|
||||||
|
struct FrameResources;
|
||||||
|
|
||||||
Context* context;
|
Context* context;
|
||||||
vk::Device device = nullptr;
|
vk::Device device = nullptr;
|
||||||
vk::Queue transferQueue = nullptr;
|
vk::Queue transferQueue = nullptr;
|
||||||
vk::CommandPool* cmdPools = nullptr;
|
Array<FrameResources> frameResources;
|
||||||
vk::CommandBuffer* cmdBuffers = nullptr;
|
MemoryPool memPool;
|
||||||
vk::Semaphore* semaphores = nullptr;
|
std::vector<Unique<VulkanShader>> shaders;
|
||||||
std::vector<std::unique_ptr<MemoryAllocation>> allocations;
|
std::vector<Unique<VulkanGeometry>> geometries;
|
||||||
std::vector<std::unique_ptr<VulkanShader>> shaders;
|
std::vector<Unique<VulkanNode>> nodes;
|
||||||
std::vector<std::unique_ptr<VulkanGeometry>> geometries;
|
std::vector<Unique<VulkanTexture>> textures;
|
||||||
std::vector<std::unique_ptr<VulkanNode>> nodes;
|
std::vector<Unique<VulkanCamera>> cameras;
|
||||||
MemoryAllocation* lastAllocation = nullptr;
|
std::vector<Unique<VulkanUniformBuffer>> uniforms;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
vk::DeviceSize uniformBufferAlignment;
|
vk::DeviceSize uniformBufferAlignment;
|
||||||
std::vector<std::vector<ManagedBuffer*>> toFree;
|
|
||||||
std::vector<ManagedBuffer*> recycleBuffers;
|
|
||||||
std::function<void(ManagedBuffer*)> freeFunction;
|
|
||||||
vk::DescriptorPool descriptorPool;
|
vk::DescriptorPool descriptorPool;
|
||||||
std::map<DescriptorSetLayoutBinding, vk::DescriptorSetLayout> descriptorSetLayoutCache;
|
std::map<DescriptorSetLayoutBinding, vk::DescriptorSetLayout> descriptorSetLayoutCache;
|
||||||
std::map<vk::SamplerCreateInfo, vk::Sampler> samplerCache;
|
std::map<vk::SamplerCreateInfo, vk::Sampler> samplerCache;
|
||||||
|
|
||||||
int buffers = -1, currentBuffer = -1;
|
int currentBuffer = -1;
|
||||||
|
|
||||||
|
vk::CommandBuffer& GetCmdBuffer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static ResourceManager* INSTANCE;
|
static ResourceManager* INSTANCE;
|
||||||
@@ -78,7 +84,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void Init(Context* context, int buffers = 2);
|
void Init(Context* context, int buffers = 2);
|
||||||
|
|
||||||
void Close() override;
|
void Close();
|
||||||
|
|
||||||
void StartFrame(uint64_t frameId);
|
void StartFrame(uint64_t frameId);
|
||||||
|
|
||||||
@@ -102,9 +108,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void CopyDataToImage(vk::DeviceSize size, void* data, OpenVulkano::Vulkan::Image* image);
|
void CopyDataToImage(vk::DeviceSize size, void* data, OpenVulkano::Vulkan::Image* image);
|
||||||
|
|
||||||
ManagedBuffer* CreateSharedMemoryBuffer(size_t size);
|
MemoryPool::ManagedBufferPtr CreateSharedMemoryBuffer(size_t size);
|
||||||
|
|
||||||
void FreeBuffer(ManagedBuffer* buffer);
|
|
||||||
|
|
||||||
[[nodiscard]] Context* GetContext() const { return context; }
|
[[nodiscard]] Context* GetContext() const { return context; }
|
||||||
|
|
||||||
@@ -115,23 +119,13 @@ namespace OpenVulkano
|
|||||||
vk::Sampler CreateSampler(const vk::SamplerCreateInfo& samplerConfig);
|
vk::Sampler CreateSampler(const vk::SamplerCreateInfo& samplerConfig);
|
||||||
|
|
||||||
protected: // Allocation management
|
protected: // Allocation management
|
||||||
void DoFreeBuffer(ManagedBuffer* buffer);
|
MemoryPool::ManagedBufferPtr CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data);
|
||||||
|
|
||||||
void FreeBuffers();
|
inline void RecordCopy(vk::Buffer src, vk::Buffer dest, vk::DeviceSize size)
|
||||||
|
|
||||||
ManagedBuffer* CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data);
|
|
||||||
|
|
||||||
inline void RecordCopy(vk::Buffer src, vk::Buffer dest, vk::DeviceSize size) const
|
|
||||||
{
|
{
|
||||||
vk::BufferCopy copyRegion = { 0, 0, size };
|
vk::BufferCopy copyRegion = { 0, 0, size };
|
||||||
cmdBuffers[currentBuffer].copyBuffer(src, dest, 1, ©Region);
|
GetCmdBuffer().copyBuffer(src, dest, 1, ©Region);
|
||||||
}
|
}
|
||||||
|
|
||||||
ManagedBuffer* CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties);
|
|
||||||
|
|
||||||
MemoryAllocation* CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache = true);
|
|
||||||
|
|
||||||
MemoryAllocation* GetFreeMemoryAllocation(size_t size, vk::DeviceSize alignment, uint32_t type, bool createIfAllFull = true);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
vk::DescriptorSetLayout* GetDescriptorLayoutSet(const DescriptorSetLayoutBinding& descriptorSetLayoutBinding);
|
vk::DescriptorSetLayout* GetDescriptorLayoutSet(const DescriptorSetLayoutBinding& descriptorSetLayoutBinding);
|
||||||
|
|||||||
@@ -5,25 +5,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "UniformBuffer.hpp"
|
#include "UniformBuffer.hpp"
|
||||||
#include "ManagedResource.hpp"
|
#include "ManagedBuffer.hpp"
|
||||||
#include "ResourceManager.hpp"
|
#include "ResourceManager.hpp"
|
||||||
#include "Vulkan/VulkanDrawContext.hpp"
|
#include "Vulkan/VulkanDrawContext.hpp"
|
||||||
#include "Vulkan/Scene/VulkanShader.hpp"
|
#include "Vulkan/Scene/VulkanShader.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
void UniformBuffer::Init(ManagedBuffer* buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId)
|
void UniformBuffer::Init(ManagedBuffer::Ptr buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId)
|
||||||
{
|
{
|
||||||
m_buffer = buffer;
|
m_buffer = std::move(buffer);
|
||||||
m_frameOffset = frameOffset;
|
m_frameOffset = frameOffset;
|
||||||
|
|
||||||
const vk::DescriptorSetAllocateInfo descSetAllocInfo = { ResourceManager::INSTANCE->descriptorPool, 1, descriptorSetLayout };
|
const vk::DescriptorSetAllocateInfo descSetAllocInfo = { ResourceManager::INSTANCE->descriptorPool, 1, descriptorSetLayout };
|
||||||
m_descriptorSet = buffer->allocation->device.allocateDescriptorSets(descSetAllocInfo)[0];
|
m_descriptorSet = m_buffer->allocation->device.allocateDescriptorSets(descSetAllocInfo)[0];
|
||||||
vk::DescriptorBufferInfo bufferInfo = { buffer->buffer, 0, frameSize };
|
vk::DescriptorBufferInfo bufferInfo = { m_buffer->buffer, 0, frameSize };
|
||||||
vk::WriteDescriptorSet writeDescriptorSet = { m_descriptorSet, binding.bindingId, 0, 1 };
|
vk::WriteDescriptorSet writeDescriptorSet = { m_descriptorSet, binding.bindingId, 0, 1 };
|
||||||
writeDescriptorSet.descriptorType = static_cast<vk::DescriptorType>(binding.descriptorType);
|
writeDescriptorSet.descriptorType = static_cast<vk::DescriptorType>(binding.descriptorType);
|
||||||
writeDescriptorSet.pBufferInfo = &bufferInfo;
|
writeDescriptorSet.pBufferInfo = &bufferInfo;
|
||||||
buffer->allocation->device.updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
|
m_buffer->allocation->device.updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
|
||||||
m_setOffset = setId;
|
m_setOffset = setId;
|
||||||
m_dynamic = binding.descriptorType == DescriptorSetLayoutBinding::TYPE_UNIFORM_BUFFER_DYNAMIC || binding.descriptorType == DescriptorSetLayoutBinding::TYPE_STORAGE_BUFFER_DYNAMIC;
|
m_dynamic = binding.descriptorType == DescriptorSetLayoutBinding::TYPE_UNIFORM_BUFFER_DYNAMIC || binding.descriptorType == DescriptorSetLayoutBinding::TYPE_STORAGE_BUFFER_DYNAMIC;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
#include "Base/ICloseable.hpp"
|
||||||
|
#include "Vulkan/Resources/ManagedBuffer.hpp"
|
||||||
#include "Vulkan/Scene/IRecordable.hpp"
|
#include "Vulkan/Scene/IRecordable.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
struct ManagedBuffer;
|
class ManagedBuffer;
|
||||||
|
|
||||||
class UniformBuffer final : public IRecordable, public ICloseable
|
class UniformBuffer final : public IRecordable, public ICloseable
|
||||||
{
|
{
|
||||||
ManagedBuffer* m_buffer = nullptr;
|
ManagedBuffer::Ptr m_buffer = nullptr;
|
||||||
vk::DescriptorSet m_descriptorSet;
|
vk::DescriptorSet m_descriptorSet;
|
||||||
uint32_t m_frameOffset;
|
uint32_t m_frameOffset;
|
||||||
uint32_t m_setOffset, m_setCount = 1;
|
uint32_t m_setOffset, m_setCount = 1;
|
||||||
@@ -27,7 +28,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
if (m_buffer) Close();
|
if (m_buffer) Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(ManagedBuffer* buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId);
|
void Init(ManagedBuffer::Ptr buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId);
|
||||||
|
|
||||||
void Close() override;
|
void Close() override;
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ namespace OpenVulkano::Vulkan
|
|||||||
UniformBuffer* m_buffer = nullptr;
|
UniformBuffer* m_buffer = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
~VulkanCamera() override { if (m_camera) VulkanCamera::Close(); }
|
||||||
|
|
||||||
void Init(Scene::Camera* camera, UniformBuffer* uniformBuffer)
|
void Init(Scene::Camera* camera, UniformBuffer* uniformBuffer)
|
||||||
{
|
{
|
||||||
m_camera = camera;
|
m_camera = camera;
|
||||||
@@ -32,7 +34,10 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
void Close() override
|
void Close() override
|
||||||
{
|
{
|
||||||
|
m_camera->renderCamera = nullptr;
|
||||||
m_buffer->Close();
|
m_buffer->Close();
|
||||||
|
m_camera = nullptr;
|
||||||
|
delete m_buffer;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "IRecordable.hpp"
|
#include "IRecordable.hpp"
|
||||||
#include "Scene/Scene.hpp"
|
#include "Scene/Scene.hpp"
|
||||||
#include "Scene/Geometry.hpp"
|
#include "Scene/Geometry.hpp"
|
||||||
#include "Vulkan/Resources/ManagedResource.hpp"
|
#include "Vulkan/Resources/ManagedBuffer.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
@@ -22,8 +22,8 @@ namespace OpenVulkano::Vulkan
|
|||||||
vk::DeviceSize m_offsets = 0;
|
vk::DeviceSize m_offsets = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VulkanGeometry() : m_geometry(nullptr), m_vertexBuffer(nullptr, nullptr)
|
VulkanGeometry() : m_geometry(nullptr), m_vertexBuffer(nullptr)
|
||||||
, m_indexBuffer(nullptr, nullptr), m_indexType(vk::IndexType::eUint32)
|
, m_indexBuffer(nullptr), m_indexType(vk::IndexType::eUint32)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
VulkanGeometry(Scene::Geometry* geo, ManagedBuffer::Ptr& vertexBuffer, ManagedBuffer::Ptr& indexBuffer)
|
VulkanGeometry(Scene::Geometry* geo, ManagedBuffer::Ptr& vertexBuffer, ManagedBuffer::Ptr& indexBuffer)
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ namespace OpenVulkano
|
|||||||
class Context;
|
class Context;
|
||||||
class IShaderOwner;
|
class IShaderOwner;
|
||||||
|
|
||||||
struct VulkanShader final : public ICloseable, public IRecordable
|
class VulkanShader final : public ICloseable, public IRecordable
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
Scene::Shader* shader = nullptr;
|
Scene::Shader* shader = nullptr;
|
||||||
vk::Device device;
|
vk::Device device;
|
||||||
std::vector<vk::ShaderModule> shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs
|
std::vector<vk::ShaderModule> shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ namespace OpenVulkano::Vulkan
|
|||||||
texture->renderTexture = this;
|
texture->renderTexture = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~VulkanTexture() override
|
||||||
|
{
|
||||||
|
if (m_texture) Close();
|
||||||
|
}
|
||||||
|
|
||||||
void Close() override
|
void Close() override
|
||||||
{
|
{
|
||||||
Image::Close();
|
Image::Close();
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include "Base/UI/IVulkanWindow.hpp"
|
#include "Base/UI/IVulkanWindow.hpp"
|
||||||
#include "Base/EngineConfiguration.hpp"
|
#include "Base/EngineConfiguration.hpp"
|
||||||
#include "Scene/DataFormat.hpp"
|
#include "Scene/DataFormat.hpp"
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
@@ -25,13 +24,17 @@ namespace OpenVulkano::Vulkan
|
|||||||
CreateSwapChain({window->GetWidth(), window->GetHeight() });
|
CreateSwapChain({window->GetWidth(), window->GetHeight() });
|
||||||
|
|
||||||
FrameBuffer::Init(device, vk::Extent3D(size, 1));
|
FrameBuffer::Init(device, vk::Extent3D(size, 1));
|
||||||
|
|
||||||
|
Logger::RENDER->trace("Initialized swapchain");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapChain::Close()
|
void SwapChain::Close()
|
||||||
{
|
{
|
||||||
|
FrameBuffer::Close();
|
||||||
DestroySwapChain();
|
DestroySwapChain();
|
||||||
device = nullptr;
|
device = nullptr;
|
||||||
FrameBuffer::Close();
|
window = nullptr;
|
||||||
|
Logger::RENDER->trace("Closed swapchain");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapChain::Resize(const uint32_t newWidth, const uint32_t newHeight)
|
void SwapChain::Resize(const uint32_t newWidth, const uint32_t newHeight)
|
||||||
@@ -40,6 +43,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
CreateSwapChain({ newWidth, newHeight });
|
CreateSwapChain({ newWidth, newHeight });
|
||||||
FrameBuffer::Resize(vk::Extent3D(size, 1));
|
FrameBuffer::Resize(vk::Extent3D(size, 1));
|
||||||
|
Logger::RENDER->trace("Resized swapchain");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SwapChain::AcquireNextImage(const vk::Fence& fence)
|
uint32_t SwapChain::AcquireNextImage(const vk::Fence& fence)
|
||||||
@@ -141,6 +145,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
for (auto& semaphore : imageAvailableSemaphores)
|
for (auto& semaphore : imageAvailableSemaphores)
|
||||||
device->device.destroySemaphore(semaphore);
|
device->device.destroySemaphore(semaphore);
|
||||||
imageAvailableSemaphores.clear();
|
imageAvailableSemaphores.clear();
|
||||||
|
Logger::RENDER->trace("Destroyed swapchain");
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::PresentModeKHR SwapChain::ChosePresentMode()
|
vk::PresentModeKHR SwapChain::ChosePresentMode()
|
||||||
|
|||||||
Reference in New Issue
Block a user