Add buffer support
This commit is contained in:
@@ -22,7 +22,9 @@ namespace Nz
|
||||
|
||||
VkRenderWindow::~VkRenderWindow()
|
||||
{
|
||||
m_device->WaitForIdle();
|
||||
if (m_device)
|
||||
m_device->WaitForIdle();
|
||||
|
||||
m_frameBuffers.clear();
|
||||
m_renderPass.Destroy();
|
||||
|
||||
@@ -64,7 +66,7 @@ namespace Nz
|
||||
//commandBuffer.SetImageLayout(m_swapchain.GetBuffer(imageIndex).image, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
}
|
||||
|
||||
bool VkRenderWindow::Create(RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters)
|
||||
bool VkRenderWindow::Create(RendererImpl* renderer, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters)
|
||||
{
|
||||
m_physicalDevice = Vulkan::GetPhysicalDevices()[0].device;
|
||||
|
||||
@@ -184,14 +186,14 @@ namespace Nz
|
||||
1U // uint32_t layers;
|
||||
};
|
||||
|
||||
if (!m_frameBuffers[i].Create(m_device, frameBufferCreate))
|
||||
if (!m_frameBuffers[i].Create(m_device->CreateHandle(), frameBufferCreate))
|
||||
{
|
||||
NazaraError("Failed to create framebuffer for image #" + String::Number(i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_imageReadySemaphore.Create(m_device);
|
||||
m_imageReadySemaphore.Create(m_device->CreateHandle());
|
||||
|
||||
m_clock.Restart();
|
||||
|
||||
@@ -218,14 +220,14 @@ namespace Nz
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
|
||||
};
|
||||
|
||||
if (!m_depthBuffer.Create(m_device, imageCreateInfo))
|
||||
if (!m_depthBuffer.Create(m_device->CreateHandle(), imageCreateInfo))
|
||||
{
|
||||
NazaraError("Failed to create depth buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
VkMemoryRequirements memoryReq = m_depthBuffer.GetMemoryRequirements();
|
||||
if (!m_depthBufferMemory.Create(m_device, memoryReq.size, memoryReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
|
||||
if (!m_depthBufferMemory.Create(m_device->CreateHandle(), memoryReq.size, memoryReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
|
||||
{
|
||||
NazaraError("Failed to allocate depth buffer memory");
|
||||
return false;
|
||||
@@ -259,7 +261,7 @@ namespace Nz
|
||||
}
|
||||
};
|
||||
|
||||
if (!m_depthBufferView.Create(m_device, imageViewCreateInfo))
|
||||
if (!m_depthBufferView.Create(m_device->CreateHandle(), imageViewCreateInfo))
|
||||
{
|
||||
NazaraError("Failed to create depth buffer view");
|
||||
return false;
|
||||
@@ -353,7 +355,7 @@ namespace Nz
|
||||
dependencies.data() // const VkSubpassDependency* pDependencies;
|
||||
};
|
||||
|
||||
return m_renderPass.Create(m_device, createInfo);
|
||||
return m_renderPass.Create(m_device->CreateHandle(), createInfo);
|
||||
}
|
||||
|
||||
bool VkRenderWindow::SetupSwapchain(Vk::Surface& surface, const Vector2ui& size)
|
||||
@@ -418,7 +420,7 @@ namespace Nz
|
||||
0
|
||||
};
|
||||
|
||||
if (!m_swapchain.Create(m_device, swapchainInfo))
|
||||
if (!m_swapchain.Create(m_device->CreateHandle(), swapchainInfo))
|
||||
{
|
||||
NazaraError("Failed to create swapchain");
|
||||
return false;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Utility/Utility.hpp>
|
||||
#include <Nazara/VulkanRenderer/Config.hpp>
|
||||
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
|
||||
#include <array>
|
||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||
|
||||
@@ -186,10 +187,8 @@ namespace Nz
|
||||
}
|
||||
|
||||
s_physDevices.reserve(physDevices.size());
|
||||
for (std::size_t i = 0; i < physDevices.size(); ++i)
|
||||
for (VkPhysicalDevice physDevice : physDevices)
|
||||
{
|
||||
VkPhysicalDevice physDevice = physDevices[i];
|
||||
|
||||
Vk::PhysicalDevice deviceInfo;
|
||||
if (!s_instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &deviceInfo.queues))
|
||||
{
|
||||
@@ -225,7 +224,47 @@ namespace Nz
|
||||
return s_instance.IsValid();
|
||||
}
|
||||
|
||||
Vk::DeviceHandle Vulkan::CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
|
||||
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(VkPhysicalDevice gpu)
|
||||
{
|
||||
Nz::ErrorFlags errFlags(ErrorFlag_ThrowException, true);
|
||||
|
||||
std::vector<VkQueueFamilyProperties> queueFamilies;
|
||||
s_instance.GetPhysicalDeviceQueueFamilyProperties(gpu, &queueFamilies);
|
||||
|
||||
// Find a queue that supports graphics operations
|
||||
UInt32 graphicsQueueNodeIndex = UINT32_MAX;
|
||||
UInt32 transfertQueueNodeFamily = UINT32_MAX;
|
||||
|
||||
for (UInt32 i = 0; i < queueFamilies.size(); i++)
|
||||
{
|
||||
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
{
|
||||
graphicsQueueNodeIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (UInt32 i = 0; i < queueFamilies.size(); i++)
|
||||
{
|
||||
if (queueFamilies[i].queueFlags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT)) //< Compute and graphics queue implicitly support transfer operations
|
||||
{
|
||||
transfertQueueNodeFamily = i;
|
||||
if (transfertQueueNodeFamily != graphicsQueueNodeIndex)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::array<QueueFamily, 2> queuesFamilies = {
|
||||
{
|
||||
{ graphicsQueueNodeIndex, 1.f },
|
||||
{ transfertQueueNodeFamily, 1.f }
|
||||
}
|
||||
};
|
||||
|
||||
return CreateDevice(gpu, queuesFamilies.data(), queuesFamilies.size());
|
||||
}
|
||||
|
||||
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
|
||||
{
|
||||
Nz::ErrorFlags errFlags(ErrorFlag_ThrowException, true);
|
||||
|
||||
@@ -267,15 +306,31 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
std::array<UInt32, 3> usedQueueFamilies = {graphicsQueueNodeIndex, presentQueueNodeIndex, transfertQueueNodeFamily};
|
||||
std::array<float, 3> priorities = {1.f, 1.f, 1.f};
|
||||
|
||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||
for (UInt32 queueFamily : usedQueueFamilies)
|
||||
{
|
||||
auto it = std::find_if(queueCreateInfos.begin(), queueCreateInfos.end(), [queueFamily] (const VkDeviceQueueCreateInfo& createInfo)
|
||||
std::array<QueueFamily, 3> queuesFamilies = {
|
||||
{
|
||||
return createInfo.queueFamilyIndex == queueFamily;
|
||||
{graphicsQueueNodeIndex, 1.f},
|
||||
{presentQueueNodeIndex, 1.f},
|
||||
{transfertQueueNodeFamily, 1.f}
|
||||
}
|
||||
};
|
||||
|
||||
*presentableFamilyQueue = presentQueueNodeIndex;
|
||||
|
||||
return CreateDevice(gpu, queuesFamilies.data(), queuesFamilies.size());
|
||||
}
|
||||
|
||||
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(VkPhysicalDevice gpu, const QueueFamily* queueFamilies, std::size_t queueFamilyCount)
|
||||
{
|
||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||
queueCreateInfos.reserve(queueFamilyCount);
|
||||
|
||||
for (std::size_t i = 0; i < queueFamilyCount; ++i)
|
||||
{
|
||||
const QueueFamily& queueFamily = queueFamilies[i];
|
||||
|
||||
auto it = std::find_if(queueCreateInfos.begin(), queueCreateInfos.end(), [&] (const VkDeviceQueueCreateInfo& createInfo)
|
||||
{
|
||||
return createInfo.queueFamilyIndex == queueFamily.familyIndex;
|
||||
});
|
||||
|
||||
if (it == queueCreateInfos.end())
|
||||
@@ -284,16 +339,15 @@ namespace Nz
|
||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
|
||||
nullptr, // const void* pNext;
|
||||
0, // VkDeviceQueueCreateFlags flags;
|
||||
queueFamily, // uint32_t queueFamilyIndex;
|
||||
queueFamily.familyIndex, // uint32_t queueFamilyIndex;
|
||||
1, // uint32_t queueCount;
|
||||
priorities.data() // const float* pQueuePriorities;
|
||||
&queueFamily.priority // const float* pQueuePriorities;
|
||||
};
|
||||
|
||||
queueCreateInfos.emplace_back(createInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<const char*> enabledLayers;
|
||||
std::vector<const char*> enabledExtensions;
|
||||
|
||||
@@ -356,25 +410,51 @@ namespace Nz
|
||||
nullptr
|
||||
};
|
||||
|
||||
///TODO: First create then move
|
||||
s_devices.emplace_back(s_instance);
|
||||
std::shared_ptr<VulkanDevice> device = std::make_shared<VulkanDevice>(s_instance);
|
||||
if (!device->Create(gpu, createInfo))
|
||||
{
|
||||
NazaraError("Failed to create Vulkan Device: " + TranslateVulkanError(device->GetLastErrorCode()));
|
||||
return {};
|
||||
}
|
||||
|
||||
Vk::Device& device = s_devices.back();
|
||||
device.Create(gpu, createInfo);
|
||||
s_devices.emplace_back(device);
|
||||
|
||||
*presentableFamilyQueue = presentQueueNodeIndex;
|
||||
|
||||
return device.CreateHandle();
|
||||
return device;
|
||||
}
|
||||
|
||||
Vk::DeviceHandle Vulkan::SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
|
||||
std::shared_ptr<VulkanDevice> Vulkan::SelectDevice(VkPhysicalDevice gpu)
|
||||
{
|
||||
for (auto it = s_devices.begin(); it != s_devices.end();)
|
||||
{
|
||||
auto devicePtr = it->lock();
|
||||
if (!devicePtr)
|
||||
{
|
||||
it = s_devices.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (devicePtr->GetPhysicalDevice() == gpu)
|
||||
return devicePtr;
|
||||
}
|
||||
|
||||
return CreateDevice(gpu);
|
||||
}
|
||||
|
||||
std::shared_ptr<VulkanDevice> Vulkan::SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
|
||||
{
|
||||
// First, try to find a device compatible with that surface
|
||||
for (Vk::Device& device : s_devices)
|
||||
for (auto it = s_devices.begin(); it != s_devices.end();)
|
||||
{
|
||||
if (device.GetPhysicalDevice() == gpu)
|
||||
auto devicePtr = it->lock();
|
||||
if (!devicePtr)
|
||||
{
|
||||
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = device.GetEnabledQueues();
|
||||
it = s_devices.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (devicePtr->GetPhysicalDevice() == gpu)
|
||||
{
|
||||
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = devicePtr->GetEnabledQueues();
|
||||
UInt32 presentableQueueFamilyIndex = UINT32_MAX;
|
||||
for (Vk::Device::QueueFamilyInfo queueInfo : queueFamilyInfo)
|
||||
{
|
||||
@@ -393,9 +473,11 @@ namespace Nz
|
||||
if (presentableQueueFamilyIndex != UINT32_MAX)
|
||||
{
|
||||
*presentableFamilyQueue = presentableQueueFamilyIndex;
|
||||
return device.CreateHandle();
|
||||
return devicePtr;
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
// No device had support for that surface, create one
|
||||
@@ -411,7 +493,7 @@ namespace Nz
|
||||
Vk::Loader::Uninitialize();
|
||||
}
|
||||
|
||||
std::list<Vk::Device> Vulkan::s_devices;
|
||||
std::vector<std::weak_ptr<VulkanDevice>> Vulkan::s_devices;
|
||||
std::vector<Vk::PhysicalDevice> Vulkan::s_physDevices;
|
||||
Vk::Instance Vulkan::s_instance;
|
||||
ParameterList Vulkan::s_initializationParameters;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -11,13 +12,40 @@ namespace Nz
|
||||
|
||||
bool VulkanBuffer::Fill(const void* data, UInt32 offset, UInt32 size)
|
||||
{
|
||||
return m_softwareData.Fill(data, offset, size);
|
||||
void* ptr = Map(BufferAccess_WriteOnly, offset, size);
|
||||
if (!ptr)
|
||||
return false;
|
||||
|
||||
Nz::CallOnExit unmapOnExit([this]() { Unmap(); });
|
||||
|
||||
std::memcpy(ptr, data, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VulkanBuffer::Initialize(UInt32 size, BufferUsageFlags usage)
|
||||
{
|
||||
m_usage = usage;
|
||||
return m_softwareData.Initialize(size, usage);
|
||||
if (!m_buffer.Create(m_device, 0, size, (m_type == BufferType_Index) ? VK_BUFFER_USAGE_INDEX_BUFFER_BIT : VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
|
||||
{
|
||||
NazaraError("Failed to create vertex buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
VkMemoryRequirements memRequirement = m_buffer.GetMemoryRequirements();
|
||||
|
||||
if (!m_memory.Create(m_device, memRequirement.size, memRequirement.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
|
||||
{
|
||||
NazaraError("Failed to allocate vertex buffer memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_buffer.BindBufferMemory(m_memory))
|
||||
{
|
||||
NazaraError("Failed to bind vertex buffer to its memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DataStorage VulkanBuffer::GetStorage() const
|
||||
@@ -25,13 +53,17 @@ namespace Nz
|
||||
return DataStorage_Hardware;
|
||||
}
|
||||
|
||||
void* VulkanBuffer::Map(BufferAccess access, UInt32 offset, UInt32 size)
|
||||
void* VulkanBuffer::Map(BufferAccess /*access*/, UInt32 offset, UInt32 size)
|
||||
{
|
||||
return m_softwareData.Map(access, offset, size);
|
||||
if (!m_memory.Map(offset, size))
|
||||
return nullptr;
|
||||
|
||||
return m_memory.GetMappedPointer();
|
||||
}
|
||||
|
||||
bool VulkanBuffer::Unmap()
|
||||
{
|
||||
return m_softwareData.Unmap();
|
||||
m_memory.Unmap();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,9 @@
|
||||
namespace Nz
|
||||
{
|
||||
VulkanDevice::~VulkanDevice() = default;
|
||||
|
||||
std::unique_ptr<AbstractBuffer> VulkanDevice::InstantiateBuffer(Buffer* parent, BufferType type)
|
||||
{
|
||||
return std::make_unique<VulkanBuffer>(CreateHandle(), parent, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
|
||||
#include <Nazara/VulkanRenderer/VulkanRenderer.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <Nazara/Renderer/RenderDeviceInstance.hpp>
|
||||
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
||||
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
|
||||
#include <Nazara/VulkanRenderer/VkRenderWindow.hpp>
|
||||
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
||||
#include <cassert>
|
||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -18,11 +19,6 @@ namespace Nz
|
||||
Vulkan::Uninitialize();
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractBuffer> VulkanRenderer::CreateHardwareBufferImpl(Buffer* parent, BufferType type)
|
||||
{
|
||||
return std::make_unique<VulkanBuffer>(parent, type); //< TODO
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderSurface> VulkanRenderer::CreateRenderSurfaceImpl()
|
||||
{
|
||||
return std::make_unique<VulkanSurface>();
|
||||
@@ -33,9 +29,10 @@ namespace Nz
|
||||
return std::make_unique<VkRenderWindow>();
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderDeviceInstance> VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex)
|
||||
std::shared_ptr<RenderDevice> VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex)
|
||||
{
|
||||
return std::unique_ptr<RenderDeviceInstance>();
|
||||
assert(deviceIndex < m_physDevices.size());
|
||||
return Vulkan::SelectDevice(m_physDevices[deviceIndex].device);
|
||||
}
|
||||
|
||||
bool VulkanRenderer::IsBetterThan(const RendererImpl* other) const
|
||||
@@ -69,14 +66,14 @@ namespace Nz
|
||||
return APIVersion;
|
||||
}
|
||||
|
||||
std::vector<RenderDevice> VulkanRenderer::QueryRenderDevices() const
|
||||
std::vector<RenderDeviceInfo> VulkanRenderer::QueryRenderDevices() const
|
||||
{
|
||||
std::vector<RenderDevice> devices;
|
||||
std::vector<RenderDeviceInfo> devices;
|
||||
devices.reserve(m_physDevices.size());
|
||||
|
||||
for (const Vk::PhysicalDevice& physDevice : m_physDevices)
|
||||
{
|
||||
RenderDevice device;
|
||||
RenderDeviceInfo device;
|
||||
device.name = physDevice.properties.deviceName;
|
||||
|
||||
switch (physDevice.properties.deviceType)
|
||||
@@ -104,7 +101,7 @@ namespace Nz
|
||||
break;
|
||||
}
|
||||
|
||||
devices.emplace_back(device);
|
||||
devices.emplace_back(std::move(device));
|
||||
}
|
||||
|
||||
return devices;
|
||||
|
||||
Reference in New Issue
Block a user