diff --git a/examples/VulkanTest/main.cpp b/examples/VulkanTest/main.cpp index 7fc74f32b..b34574245 100644 --- a/examples/VulkanTest/main.cpp +++ b/examples/VulkanTest/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -112,13 +113,7 @@ int main() Nz::MeshParams meshParams; meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 180.f)); - - Nz::Mesh drfreak; - if (!drfreak.LoadFromFile("resources/drfreak.md2", meshParams)) - { - NazaraError("Failed to load Dr. Freak"); - return __LINE__; - } + meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ_Normal); Nz::String windowTitle = "Vulkan Test"; if (!window.Create(Nz::VideoMode(800, 600, 32), windowTitle)) @@ -141,23 +136,28 @@ int main() std::vector queues; instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &queues);*/ - Nz::Vk::DeviceHandle device = vulkanWindow.GetDevice(); + Nz::VulkanDevice& device = vulkanWindow.GetDevice(); Nz::Vk::ShaderModule vertexShader; - if (!vertexShader.Create(device, reinterpret_cast(vertexShaderCode.data()), vertexShaderCode.size())) + if (!vertexShader.Create(device.CreateHandle(), reinterpret_cast(vertexShaderCode.data()), vertexShaderCode.size())) { NazaraError("Failed to create vertex shader"); return __LINE__; } Nz::Vk::ShaderModule fragmentShader; - if (!fragmentShader.Create(device, reinterpret_cast(fragmentShaderCode.data()), fragmentShaderCode.size())) + if (!fragmentShader.Create(device.CreateHandle(), reinterpret_cast(fragmentShaderCode.data()), fragmentShaderCode.size())) { NazaraError("Failed to create fragment shader"); return __LINE__; } - VkMemoryRequirements memRequirement; + Nz::Mesh drfreak; + if (!drfreak.LoadFromFile("resources/OILTANK1.md2", meshParams)) + { + NazaraError("Failed to load model"); + return __LINE__; + } Nz::StaticMesh* drfreakMesh = static_cast(drfreak.GetSubMesh(0)); @@ -165,134 +165,28 @@ int main() const Nz::IndexBuffer* drfreakIB = drfreakMesh->GetIndexBuffer(); // Vertex buffer - struct Vertex { - Nz::Vector4f pos; - Nz::Vector3f col; - }; + std::cout << "Index count: " << drfreakIB->GetIndexCount() << std::endl; - /*std::vector vertexBufferData = { - {{-1.f, 1.f, 0.0f}, {1.0f, 0.0f, 0.0f}}, - {{1.f, 1.f, 0.0f}, {0.0f, 1.0f, 0.0f}}, - {{0.0f, -1.f, 0.0f}, {0.0f, 0.0f, 1.0f}} - }; - - Nz::Matrix4f projection = Nz::Matrix4f::Perspective(70.f, float(windowSize.x) / windowSize.y, 1.f, 1000.f); - Nz::Matrix4f world = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 5.f); - - for (unsigned int i = 0; i < 3; ++i) + Nz::RenderBuffer* renderBufferIB = static_cast(drfreakIB->GetBuffer()->GetImpl()); + if (!renderBufferIB->Synchronize(&device)) { - Nz::Vector4f pos = vertexBufferData[i].pos; - vertexBufferData[i].pos = projection * (world * pos); - }*/ - - Nz::BufferMapper vertexMapper(drfreakVB, Nz::BufferAccess_ReadOnly); - Nz::MeshVertex* meshVertices = static_cast(vertexMapper.GetPointer()); - - std::size_t vertexCount = drfreakVB->GetVertexCount(); - - Nz::Image meshImage; - if (!meshImage.LoadFromFile("resources/drfreak.tga")) - { - NazaraError("Failed to load texture"); + NazaraError("Failed to synchronize render buffer"); return __LINE__; } - std::vector vertexBufferData; - vertexBufferData.reserve(vertexCount); - for (std::size_t i = 0; i < vertexCount; ++i) - { - std::size_t texX = meshVertices[i].uv.x * meshImage.GetWidth(); - std::size_t texY = meshVertices[i].uv.y * meshImage.GetHeight(); - - Nz::Color c = meshImage.GetPixelColor(texX, texY); - - Vertex vertex = { - meshVertices[i].position, - {c.r / 255.f, c.g / 255.f, c.b / 255.f} - }; - - vertexBufferData.push_back(vertex); - } - - Nz::UInt32 vertexBufferSize = static_cast(vertexBufferData.size() * sizeof(Vertex)); - - Nz::Vk::Buffer vertexBuffer; - if (!vertexBuffer.Create(device, 0, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)) - { - NazaraError("Failed to create vertex buffer"); - return __LINE__; - } - - memRequirement = vertexBuffer.GetMemoryRequirements(); - - Nz::Vk::DeviceMemory vertexBufferMemory; - if (!vertexBufferMemory.Create(device, memRequirement.size, memRequirement.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) - { - NazaraError("Failed to allocate vertex buffer memory"); - return __LINE__; - } - - if (!vertexBufferMemory.Map(0, vertexBufferSize)) - { - NazaraError("Failed to map vertex buffer"); - return __LINE__; - } - - std::memcpy(vertexBufferMemory.GetMappedPointer(), vertexBufferData.data(), vertexBufferSize); - - vertexBufferMemory.Unmap(); - - if (!vertexBuffer.BindBufferMemory(vertexBufferMemory)) - { - NazaraError("Failed to bind vertex buffer to its memory"); - return __LINE__; - } + Nz::VulkanBuffer* indexBufferImpl = static_cast(renderBufferIB->GetHardwareBuffer(&device)); // Index buffer - Nz::IndexMapper indexMapper(drfreakIB); + std::cout << "Vertex count: " << drfreakVB->GetVertexCount() << std::endl; - std::size_t indexCount = indexMapper.GetIndexCount(); - std::vector indexBufferData; - indexBufferData.reserve(indexCount); - - for (std::size_t i = 0; i < indexCount; ++i) + Nz::RenderBuffer* renderBufferVB = static_cast(drfreakVB->GetBuffer()->GetImpl()); + if (!renderBufferVB->Synchronize(&device)) { - indexBufferData.push_back(indexMapper.Get(i)); - } - - Nz::UInt32 indexBufferSize = indexBufferData.size() * sizeof(Nz::UInt32); - - Nz::Vk::Buffer indexBuffer; - if (!indexBuffer.Create(device, 0, indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT)) - { - NazaraError("Failed to create vertex buffer"); + NazaraError("Failed to synchronize render buffer"); return __LINE__; } - memRequirement = indexBuffer.GetMemoryRequirements(); - - Nz::Vk::DeviceMemory indexBufferMemory; - if (!indexBufferMemory.Create(device, memRequirement.size, memRequirement.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) - { - NazaraError("Failed to allocate vertex buffer memory"); - return __LINE__; - } - - if (!indexBufferMemory.Map(0, indexBufferSize)) - { - NazaraError("Failed to map vertex buffer"); - return __LINE__; - } - - std::memcpy(indexBufferMemory.GetMappedPointer(), indexBufferData.data(), indexBufferSize); - - indexBufferMemory.Unmap(); - - if (!indexBuffer.BindBufferMemory(indexBufferMemory)) - { - NazaraError("Failed to bind vertex buffer to its memory"); - return __LINE__; - } + Nz::VulkanBuffer* vertexBufferImpl = static_cast(renderBufferVB->GetHardwareBuffer(&device)); struct { @@ -310,16 +204,16 @@ int main() Nz::UInt32 uniformSize = sizeof(ubo); Nz::Vk::Buffer uniformBuffer; - if (!uniformBuffer.Create(device, 0, uniformSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) + if (!uniformBuffer.Create(device.CreateHandle(), 0, uniformSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) { NazaraError("Failed to create vertex buffer"); return __LINE__; } - memRequirement = uniformBuffer.GetMemoryRequirements(); + VkMemoryRequirements memRequirement = uniformBuffer.GetMemoryRequirements(); Nz::Vk::DeviceMemory uniformBufferMemory; - if (!uniformBufferMemory.Create(device, memRequirement.size, memRequirement.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) + if (!uniformBufferMemory.Create(device.CreateHandle(), memRequirement.size, memRequirement.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { NazaraError("Failed to allocate vertex buffer memory"); return __LINE__; @@ -350,7 +244,7 @@ int main() layoutBinding.pImmutableSamplers = nullptr; Nz::Vk::DescriptorSetLayout descriptorLayout; - if (!descriptorLayout.Create(device, layoutBinding)) + if (!descriptorLayout.Create(device.CreateHandle(), layoutBinding)) { NazaraError("Failed to create descriptor set layout"); return __LINE__; @@ -361,7 +255,7 @@ int main() poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; Nz::Vk::DescriptorPool descriptorPool; - if (!descriptorPool.Create(device, 1, poolSize, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) + if (!descriptorPool.Create(device.CreateHandle(), 1, poolSize, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) { NazaraError("Failed to create descriptor pool"); return __LINE__; @@ -396,7 +290,7 @@ int main() VkVertexInputBindingDescription bindingDescription = { 0, - sizeof(Vertex), + drfreakVB->GetStride(), VK_VERTEX_INPUT_RATE_VERTEX }; @@ -406,14 +300,14 @@ int main() { 0, // uint32_t location 0, // uint32_t binding; - VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format; 0 // uint32_t offset; }, { 1, // uint32_t location 0, // uint32_t binding; VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format; - sizeof(float) * 4 // uint32_t offset; + sizeof(float) * 3 // uint32_t offset; } } }; @@ -510,7 +404,7 @@ int main() }; Nz::Vk::PipelineLayout pipelineLayout; - pipelineLayout.Create(device, layout_create_info); + pipelineLayout.Create(device.CreateHandle(), layout_create_info); std::array dynamicStates = { VK_DYNAMIC_STATE_SCISSOR, @@ -563,14 +457,14 @@ int main() }; Nz::Vk::Pipeline pipeline; - if (!pipeline.CreateGraphics(device, pipeline_create_info)) + if (!pipeline.CreateGraphics(device.CreateHandle(), pipeline_create_info)) { NazaraError("Failed to create pipeline"); return __LINE__; } Nz::Vk::CommandPool cmdPool; - if (!cmdPool.Create(device, 0, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)) + if (!cmdPool.Create(device.CreateHandle(), 0, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)) { NazaraError("Failed to create rendering cmd pool"); return __LINE__; @@ -580,7 +474,7 @@ int main() clearValues[0].color = {1.0f, 0.8f, 0.4f, 0.0f}; clearValues[1].depthStencil = {1.f, 0}; - Nz::Vk::Queue graphicsQueue(device, device->GetEnabledQueues()[0].queues[0].queue); + Nz::Vk::Queue graphicsQueue(device.CreateHandle(), device.GetEnabledQueues()[0].queues[0].queue); Nz::UInt32 imageCount = vulkanWindow.GetFramebufferCount(); std::vector renderCmds = cmdPool.AllocateCommandBuffers(imageCount, VK_COMMAND_BUFFER_LEVEL_PRIMARY); @@ -634,13 +528,13 @@ int main() renderCmd.BeginRenderPass(render_pass_begin_info); //renderCmd.ClearAttachment(clearAttachment, clearRect); //renderCmd.ClearAttachment(clearAttachmentDepth, clearRect); - renderCmd.BindIndexBuffer(indexBuffer, 0, VK_INDEX_TYPE_UINT32); - renderCmd.BindVertexBuffer(0, vertexBuffer, 0); + renderCmd.BindIndexBuffer(indexBufferImpl->GetBufferHandle(), 0, VK_INDEX_TYPE_UINT16); + renderCmd.BindVertexBuffer(0, vertexBufferImpl->GetBufferHandle(), 0); renderCmd.BindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet); renderCmd.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); renderCmd.SetScissor(Nz::Recti{0, 0, int(windowSize.x), int(windowSize.y)}); renderCmd.SetViewport({0.f, 0.f, float(windowSize.x), float(windowSize.y)}, 0.f, 1.f); - renderCmd.DrawIndexed(indexCount); + renderCmd.DrawIndexed(drfreakIB->GetIndexCount()); renderCmd.EndRenderPass(); vulkanWindow.BuildPostRenderCommands(i, renderCmd); @@ -675,21 +569,21 @@ int main() window.Close(); break; - case Nz::WindowEventType_MouseMoved: // La souris a bougé + case Nz::WindowEventType_MouseMoved: // La souris a bougé { - // Gestion de la caméra free-fly (Rotation) - float sensitivity = 0.3f; // Sensibilité de la souris + // Gestion de la caméra free-fly (Rotation) + float sensitivity = 0.3f; // Sensibilité de la souris - // On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris + // On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris camAngles.yaw = Nz::NormalizeAngle(camAngles.yaw - event.mouseMove.deltaX*sensitivity); - // Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles + // Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles camAngles.pitch = Nz::Clamp(camAngles.pitch + event.mouseMove.deltaY*sensitivity, -89.f, 89.f); camQuat = camAngles; - // Pour éviter que le curseur ne sorte de l'écran, nous le renvoyons au centre de la fenêtre - // Cette fonction est codée de sorte à ne pas provoquer d'évènement MouseMoved + // Pour éviter que le curseur ne sorte de l'écran, nous le renvoyons au centre de la fenêtre + // Cette fonction est codée de sorte à ne pas provoquer d'évènement MouseMoved Nz::Mouse::SetPosition(windowSize.x / 2, windowSize.y / 2, window); updateUniforms = true; break; @@ -758,25 +652,25 @@ int main() vulkanWindow.Present(imageIndex); - // On incrémente le compteur de FPS improvisé + // On incrémente le compteur de FPS improvisé fps++; if (secondClock.GetMilliseconds() >= 1000) // Toutes les secondes { - // Et on insère ces données dans le titre de la fenêtre + // Et on insère ces données dans le titre de la fenêtre window.SetTitle(windowTitle + " - " + Nz::String::Number(fps) + " FPS"); /* - Note: En C++11 il est possible d'insérer de l'Unicode de façon standard, quel que soit l'encodage du fichier, - via quelque chose de similaire à u8"Cha\u00CEne de caract\u00E8res". - Cependant, si le code source est encodé en UTF-8 (Comme c'est le cas dans ce fichier), - cela fonctionnera aussi comme ceci : "Chaîne de caractères". + Note: En C++11 il est possible d'insérer de l'Unicode de façon standard, quel que soit l'encodage du fichier, + via quelque chose de similaire à u8"Cha\u00CEne de caract\u00E8res". + Cependant, si le code source est encodé en UTF-8 (Comme c'est le cas dans ce fichier), + cela fonctionnera aussi comme ceci : "Chaîne de caractères". */ - // Et on réinitialise le compteur de FPS + // Et on réinitialise le compteur de FPS fps = 0; - // Et on relance l'horloge pour refaire ça dans une seconde + // Et on relance l'horloge pour refaire ça dans une seconde secondClock.Restart(); } } @@ -784,4 +678,4 @@ int main() // instance.vkDestroyDebugReportCallbackEXT(instance, callback, nullptr); return EXIT_SUCCESS; -} \ No newline at end of file +} diff --git a/include/Nazara/Renderer.hpp b/include/Nazara/Renderer.hpp index d733c1032..d64926f30 100644 --- a/include/Nazara/Renderer.hpp +++ b/include/Nazara/Renderer.hpp @@ -36,8 +36,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/include/Nazara/Renderer/RenderBuffer.hpp b/include/Nazara/Renderer/RenderBuffer.hpp index ac1c8391d..a0a49159f 100644 --- a/include/Nazara/Renderer/RenderBuffer.hpp +++ b/include/Nazara/Renderer/RenderBuffer.hpp @@ -7,31 +7,56 @@ #ifndef NAZARA_RENDERBUFFER_HPP #define NAZARA_RENDERBUFFER_HPP +#include #include +#include #include #include +#include +#include namespace Nz { + class RenderDevice; + class NAZARA_RENDERER_API RenderBuffer : public AbstractBuffer { public: - RenderBuffer() = default; + inline RenderBuffer(Buffer* parent, BufferType type); + RenderBuffer(const RenderBuffer&) = delete; + RenderBuffer(RenderBuffer&&) = default; ~RenderBuffer() = default; - virtual bool Fill(const void* data, UInt32 offset, UInt32 size) = 0; + bool Fill(const void* data, UInt32 offset, UInt32 size) override final; bool Initialize(UInt32 size, BufferUsageFlags usage) override; + AbstractBuffer* GetHardwareBuffer(RenderDevice* device); DataStorage GetStorage() const override; - virtual void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) = 0; - virtual bool Unmap() = 0; + void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) override final; + bool Unmap() override final; + + RenderBuffer& operator=(const RenderBuffer&) = delete; + RenderBuffer& operator=(RenderBuffer&&) = default; + + public: //< temp + bool Synchronize(RenderDevice* device); private: - SoftwareBuffer m_softwareBuffer; - }; + struct HardwareBuffer + { + std::unique_ptr buffer; + bool synchronized = false; + }; + BufferUsageFlags m_usage; + SoftwareBuffer m_softwareBuffer; + Buffer* m_parent; + BufferType m_type; + std::size_t m_size; + std::unordered_map m_hardwareBuffers; + }; } #include diff --git a/include/Nazara/Renderer/RenderBuffer.inl b/include/Nazara/Renderer/RenderBuffer.inl index 6a207825e..ecd250f63 100644 --- a/include/Nazara/Renderer/RenderBuffer.inl +++ b/include/Nazara/Renderer/RenderBuffer.inl @@ -2,11 +2,18 @@ // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp +#include #include #include namespace Nz { + inline RenderBuffer::RenderBuffer(Buffer* parent, BufferType type) : + m_softwareBuffer(parent, type), + m_parent(parent), + m_type(type) + { + } } #include diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index 4b1991085..f01ea5ec5 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -4,20 +4,28 @@ #pragma once -#ifndef NAZARA_RENDERDEVICE_HPP -#define NAZARA_RENDERDEVICE_HPP +#ifndef NAZARA_RENDERDEVICEINSTANCE_HPP +#define NAZARA_RENDERDEVICEINSTANCE_HPP -#include -#include -#include +#include +#include +#include +#include namespace Nz { - struct RenderDevice + class Buffer; + + class NAZARA_RENDERER_API RenderDevice { - RenderDeviceType type; - String name; + public: + RenderDevice() = default; + virtual ~RenderDevice(); + + virtual std::unique_ptr InstantiateBuffer(Buffer* parent, BufferType type) = 0; }; } -#endif // NAZARA_RENDERER_HPP +#include + +#endif // NAZARA_RENDERDEVICEINSTANCE_HPP diff --git a/include/Nazara/Renderer/RenderDeviceInstance.inl b/include/Nazara/Renderer/RenderDevice.inl similarity index 84% rename from include/Nazara/Renderer/RenderDeviceInstance.inl rename to include/Nazara/Renderer/RenderDevice.inl index 68ffbd5cd..7a62a60ea 100644 --- a/include/Nazara/Renderer/RenderDeviceInstance.inl +++ b/include/Nazara/Renderer/RenderDevice.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz diff --git a/include/Nazara/Renderer/RenderDeviceInfo.hpp b/include/Nazara/Renderer/RenderDeviceInfo.hpp new file mode 100644 index 000000000..a1e379c18 --- /dev/null +++ b/include/Nazara/Renderer/RenderDeviceInfo.hpp @@ -0,0 +1,23 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERDEVICE_HPP +#define NAZARA_RENDERDEVICE_HPP + +#include +#include +#include + +namespace Nz +{ + struct RenderDeviceInfo + { + RenderDeviceType type; + String name; + }; +} + +#endif // NAZARA_RENDERER_HPP diff --git a/include/Nazara/Renderer/RenderDeviceInstance.hpp b/include/Nazara/Renderer/RenderDeviceInstance.hpp deleted file mode 100644 index 3c019fc20..000000000 --- a/include/Nazara/Renderer/RenderDeviceInstance.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2016 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_RENDERDEVICEINSTANCE_HPP -#define NAZARA_RENDERDEVICEINSTANCE_HPP - -#include -#include - -namespace Nz -{ - ///TODO: Rename - class NAZARA_RENDERER_API RenderDeviceInstance - { - public: - RenderDeviceInstance() = default; - virtual ~RenderDeviceInstance(); - }; -} - -#include - -#endif // NAZARA_RENDERDEVICEINSTANCE_HPP diff --git a/include/Nazara/Renderer/RenderWindowImpl.hpp b/include/Nazara/Renderer/RenderWindowImpl.hpp index eb1bb8282..e5abd0c98 100644 --- a/include/Nazara/Renderer/RenderWindowImpl.hpp +++ b/include/Nazara/Renderer/RenderWindowImpl.hpp @@ -16,6 +16,7 @@ namespace Nz { + class RendererImpl; class RenderSurface; class NAZARA_RENDERER_API RenderWindowImpl @@ -24,7 +25,7 @@ namespace Nz RenderWindowImpl() = default; virtual ~RenderWindowImpl(); - virtual bool Create(RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) = 0; + virtual bool Create(RendererImpl* renderer, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) = 0; }; } diff --git a/include/Nazara/Renderer/RendererImpl.hpp b/include/Nazara/Renderer/RendererImpl.hpp index c57b41781..f9b5f4d10 100644 --- a/include/Nazara/Renderer/RendererImpl.hpp +++ b/include/Nazara/Renderer/RendererImpl.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -21,7 +21,7 @@ namespace Nz { class Buffer; class RendererImpl; - class RenderDeviceInstance; + class RenderDevice; class RenderSurface; class RenderWindowImpl; @@ -33,11 +33,10 @@ namespace Nz RendererImpl() = default; virtual ~RendererImpl(); - virtual std::unique_ptr CreateHardwareBufferImpl(Buffer* parent, BufferType type) = 0; virtual std::unique_ptr CreateRenderSurfaceImpl() = 0; virtual std::unique_ptr CreateRenderWindowImpl() = 0; - virtual std::unique_ptr InstanciateRenderDevice(std::size_t deviceIndex) = 0; + virtual std::shared_ptr InstanciateRenderDevice(std::size_t deviceIndex) = 0; virtual bool IsBetterThan(const RendererImpl* other) const = 0; @@ -45,7 +44,7 @@ namespace Nz virtual String QueryAPIString() const = 0; virtual UInt32 QueryAPIVersion() const = 0; - virtual std::vector QueryRenderDevices() const = 0; + virtual std::vector QueryRenderDevices() const = 0; virtual bool Prepare(const ParameterList& parameters) = 0; }; diff --git a/include/Nazara/Utility/SoftwareBuffer.hpp b/include/Nazara/Utility/SoftwareBuffer.hpp index 0c792a4c2..d460eba4c 100644 --- a/include/Nazara/Utility/SoftwareBuffer.hpp +++ b/include/Nazara/Utility/SoftwareBuffer.hpp @@ -25,6 +25,7 @@ namespace Nz bool Initialize(UInt32 size, BufferUsageFlags usage) override; + const UInt8* GetData() const; DataStorage GetStorage() const override; void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) override; diff --git a/include/Nazara/VulkanRenderer/VkRenderWindow.hpp b/include/Nazara/VulkanRenderer/VkRenderWindow.hpp index 186287703..e1cdf3622 100644 --- a/include/Nazara/VulkanRenderer/VkRenderWindow.hpp +++ b/include/Nazara/VulkanRenderer/VkRenderWindow.hpp @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -39,11 +41,12 @@ namespace Nz void BuildPreRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) override; void BuildPostRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) override; - bool Create(RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) override; + bool Create(RendererImpl* renderer, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) override; inline const Vk::Framebuffer& GetFrameBuffer(UInt32 imageIndex) const override; - inline UInt32 GetFramebufferCount() const; - inline const Vk::DeviceHandle& GetDevice() const; + inline UInt32 GetFramebufferCount() const override; + inline VulkanDevice& GetDevice(); + inline const VulkanDevice& GetDevice() const; inline UInt32 GetPresentableFamilyQueue() const; inline const Vk::Swapchain& GetSwapchain() const; @@ -62,8 +65,8 @@ namespace Nz VkFormat m_colorFormat; VkFormat m_depthStencilFormat; VkPhysicalDevice m_physicalDevice; + std::shared_ptr m_device; std::vector m_frameBuffers; - Vk::DeviceHandle m_device; Vk::DeviceMemory m_depthBufferMemory; Vk::Image m_depthBuffer; Vk::ImageView m_depthBufferView; diff --git a/include/Nazara/VulkanRenderer/VkRenderWindow.inl b/include/Nazara/VulkanRenderer/VkRenderWindow.inl index e207cc89a..0721f4762 100644 --- a/include/Nazara/VulkanRenderer/VkRenderWindow.inl +++ b/include/Nazara/VulkanRenderer/VkRenderWindow.inl @@ -7,9 +7,14 @@ namespace Nz { - inline const Vk::DeviceHandle& VkRenderWindow::GetDevice() const + inline VulkanDevice& VkRenderWindow::GetDevice() { - return m_device; + return *m_device; + } + + inline const VulkanDevice& VkRenderWindow::GetDevice() const + { + return *m_device; } inline const Vk::Framebuffer& VkRenderWindow::GetFrameBuffer(UInt32 imageIndex) const diff --git a/include/Nazara/VulkanRenderer/Vulkan.hpp b/include/Nazara/VulkanRenderer/Vulkan.hpp index 7701a95b0..69ada9a7b 100644 --- a/include/Nazara/VulkanRenderer/Vulkan.hpp +++ b/include/Nazara/VulkanRenderer/Vulkan.hpp @@ -16,17 +16,28 @@ #include #include #include +#include #include namespace Nz { + class VulkanDevice; + class NAZARA_VULKANRENDERER_API Vulkan { public: + struct QueueFamily + { + UInt32 familyIndex; + float priority; + }; + Vulkan() = delete; ~Vulkan() = delete; - static Vk::DeviceHandle CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue); + static std::shared_ptr CreateDevice(VkPhysicalDevice gpu); + static std::shared_ptr CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue); + static std::shared_ptr CreateDevice(VkPhysicalDevice gpu, const QueueFamily* queueFamilies, std::size_t queueFamilyCount); static Vk::Instance& GetInstance(); @@ -37,12 +48,13 @@ namespace Nz static bool IsInitialized(); - static Vk::DeviceHandle SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue); + static std::shared_ptr SelectDevice(VkPhysicalDevice gpu); + static std::shared_ptr SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue); static void Uninitialize(); private: - static std::list s_devices; + static std::vector> s_devices; static std::vector s_physDevices; static Vk::Instance s_instance; static ParameterList s_initializationParameters; diff --git a/include/Nazara/VulkanRenderer/VulkanBuffer.hpp b/include/Nazara/VulkanRenderer/VulkanBuffer.hpp index e44406152..04ee709dd 100644 --- a/include/Nazara/VulkanRenderer/VulkanBuffer.hpp +++ b/include/Nazara/VulkanRenderer/VulkanBuffer.hpp @@ -9,25 +9,26 @@ #include #include -#include #include #include +#include #include namespace Nz { - //TODO: Move all the software stuff to the Renderer + class Buffer; class NAZARA_VULKANRENDERER_API VulkanBuffer : public AbstractBuffer { public: - inline VulkanBuffer(Buffer* parent, BufferType type); + inline VulkanBuffer(const Vk::DeviceHandle& device, Buffer* parent, BufferType type); VulkanBuffer(const VulkanBuffer&) = delete; VulkanBuffer(VulkanBuffer&&) = delete; ///TODO virtual ~VulkanBuffer(); bool Fill(const void* data, UInt32 offset, UInt32 size) override; + inline Nz::Vk::Buffer& GetBufferHandle(); bool Initialize(UInt32 size, BufferUsageFlags usage) override; DataStorage GetStorage() const override; @@ -39,8 +40,11 @@ namespace Nz VulkanBuffer& operator=(VulkanBuffer&&) = delete; ///TODO private: - BufferUsageFlags m_usage; - SoftwareBuffer m_softwareData; + Buffer* m_parent; + BufferType m_type; + Nz::Vk::Buffer m_buffer; + Nz::Vk::DeviceHandle m_device; + Nz::Vk::DeviceMemory m_memory; }; } diff --git a/include/Nazara/VulkanRenderer/VulkanBuffer.inl b/include/Nazara/VulkanRenderer/VulkanBuffer.inl index 7638ebb80..d2360055a 100644 --- a/include/Nazara/VulkanRenderer/VulkanBuffer.inl +++ b/include/Nazara/VulkanRenderer/VulkanBuffer.inl @@ -7,10 +7,17 @@ namespace Nz { - inline VulkanBuffer::VulkanBuffer(Buffer* parent, BufferType type) : - m_softwareData(parent, type) + inline VulkanBuffer::VulkanBuffer(const Vk::DeviceHandle& device, Buffer* parent, BufferType type) : + m_device(device), + m_parent(parent), + m_type(type) { } + + inline Nz::Vk::Buffer& Nz::VulkanBuffer::GetBufferHandle() + { + return m_buffer; + } } #include diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 151caa80f..5ec2a891c 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -7,26 +7,26 @@ #ifndef NAZARA_VULKANRENDERER_VULKANDEVICE_HPP #define NAZARA_VULKANRENDERER_VULKANDEVICE_HPP -#include #include +#include +#include #include #include namespace Nz { - //TODO: Move all the software stuff to the Renderer - - class NAZARA_VULKANRENDERER_API VulkanDevice : public RenderDeviceInstance + class NAZARA_VULKANRENDERER_API VulkanDevice : public RenderDevice, public Vk::Device { public: - VulkanDevice(Vk::DeviceHandle device); + using Device::Device; + VulkanDevice(const VulkanDevice&) = delete; + VulkanDevice(VulkanDevice&&) = delete; ///TODO? ~VulkanDevice(); - VulkanDevice& operator=(const VulkanDevice&) = delete; - VulkanDevice& operator=(VulkanDevice&&) = delete; ///TODO + std::unique_ptr InstantiateBuffer(Buffer* parent, BufferType type) override; - private: - Vk::DeviceHandle m_device; + VulkanDevice& operator=(const VulkanDevice&) = delete; + VulkanDevice& operator=(VulkanDevice&&) = delete; ///TODO? }; } diff --git a/src/Nazara/Renderer/RenderBuffer.cpp b/src/Nazara/Renderer/RenderBuffer.cpp index d0338112a..470faf839 100644 --- a/src/Nazara/Renderer/RenderBuffer.cpp +++ b/src/Nazara/Renderer/RenderBuffer.cpp @@ -3,18 +3,87 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz { + bool RenderBuffer::Fill(const void* data, UInt32 offset, UInt32 size) + { + if (m_softwareBuffer.Fill(data, offset, size)) + { + for (auto& bufferPair : m_hardwareBuffers) + bufferPair.second.synchronized = false; + + return true; + } + else + return false; + } + bool RenderBuffer::Initialize(UInt32 size, BufferUsageFlags usage) { + m_size = size; m_softwareBuffer.Initialize(size, usage); + return true; } - DataStorage Nz::RenderBuffer::GetStorage() const + AbstractBuffer* RenderBuffer::GetHardwareBuffer(RenderDevice* device) + { + auto it = m_hardwareBuffers.find(device); + if (it == m_hardwareBuffers.end()) + return nullptr; + + return it->second.buffer.get(); + } + + DataStorage RenderBuffer::GetStorage() const { return DataStorage::DataStorage_Hardware; } + + void* RenderBuffer::Map(BufferAccess access, UInt32 offset, UInt32 size) + { + if (void* ptr = m_softwareBuffer.Map(access, offset, size)) + { + if (access != BufferAccess_ReadOnly) + { + for (auto& bufferPair : m_hardwareBuffers) + bufferPair.second.synchronized = false; + } + + return ptr; + } + else + return nullptr; + } + + bool RenderBuffer::Unmap() + { + return m_softwareBuffer.Unmap(); + } + + bool RenderBuffer::Synchronize(RenderDevice* device) + { + auto it = m_hardwareBuffers.find(device); + if (it == m_hardwareBuffers.end()) + { + HardwareBuffer hwBuffer; + hwBuffer.buffer = device->InstantiateBuffer(m_parent, m_type); + if (!hwBuffer.buffer->Initialize(m_size, m_usage)) + { + NazaraError("Failed to initialize hardware buffer"); + return false; + } + + it = m_hardwareBuffers.emplace(device, std::move(hwBuffer)).first; + } + + HardwareBuffer& hwBuffer = it->second; + if (hwBuffer.synchronized) + return true; + + return hwBuffer.buffer->Fill(m_softwareBuffer.GetData(), 0, m_size); + } } diff --git a/src/Nazara/Renderer/RenderDeviceInstance.cpp b/src/Nazara/Renderer/RenderDevice.cpp similarity index 68% rename from src/Nazara/Renderer/RenderDeviceInstance.cpp rename to src/Nazara/Renderer/RenderDevice.cpp index 6d8078cfb..de5e5f82d 100644 --- a/src/Nazara/Renderer/RenderDeviceInstance.cpp +++ b/src/Nazara/Renderer/RenderDevice.cpp @@ -2,10 +2,10 @@ // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz { - RenderDeviceInstance::~RenderDeviceInstance() = default; + RenderDevice::~RenderDevice() = default; } diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index 6b4ca5400..cc643747d 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -29,15 +29,16 @@ namespace Nz bool RenderWindow::OnWindowCreated() { - auto surface = Renderer::GetRendererImpl()->CreateRenderSurfaceImpl(); + RendererImpl* rendererImpl = Renderer::GetRendererImpl(); + auto surface = rendererImpl->CreateRenderSurfaceImpl(); if (!surface->Create(GetHandle())) { NazaraError("Failed to create render surface: " + Error::GetLastError()); return false; } - auto impl = Renderer::GetRendererImpl()->CreateRenderWindowImpl(); - if (!impl->Create(surface.get(), GetSize(), m_parameters)) + auto impl = rendererImpl->CreateRenderWindowImpl(); + if (!impl->Create(rendererImpl, surface.get(), GetSize(), m_parameters)) { NazaraError("Failed to create render window implementation: " + Error::GetLastError()); return false; diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index ab9b07f13..737b63b08 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -135,9 +136,9 @@ namespace Nz Utility::Uninitialize(); } - AbstractBuffer* Renderer::CreateHardwareBufferImpl(Buffer * parent, BufferType type) + AbstractBuffer* Renderer::CreateHardwareBufferImpl(Buffer* parent, BufferType type) { - return s_rendererImpl->CreateHardwareBufferImpl(parent, type).release(); + return new RenderBuffer(parent, type); } std::unique_ptr Renderer::s_rendererImpl; diff --git a/src/Nazara/Utility/SoftwareBuffer.cpp b/src/Nazara/Utility/SoftwareBuffer.cpp index c76f20784..15147bd97 100644 --- a/src/Nazara/Utility/SoftwareBuffer.cpp +++ b/src/Nazara/Utility/SoftwareBuffer.cpp @@ -44,6 +44,11 @@ namespace Nz return true; } + const UInt8* SoftwareBuffer::GetData() const + { + return m_buffer.data(); + } + DataStorage SoftwareBuffer::GetStorage() const { return DataStorage_Software; diff --git a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp index fe33b3183..7f7928954 100644 --- a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp +++ b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp @@ -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; diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index 17a1171ec..f45555110 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -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 Vulkan::CreateDevice(VkPhysicalDevice gpu) + { + Nz::ErrorFlags errFlags(ErrorFlag_ThrowException, true); + + std::vector 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 queuesFamilies = { + { + { graphicsQueueNodeIndex, 1.f }, + { transfertQueueNodeFamily, 1.f } + } + }; + + return CreateDevice(gpu, queuesFamilies.data(), queuesFamilies.size()); + } + + std::shared_ptr Vulkan::CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue) { Nz::ErrorFlags errFlags(ErrorFlag_ThrowException, true); @@ -267,15 +306,31 @@ namespace Nz } } - std::array usedQueueFamilies = {graphicsQueueNodeIndex, presentQueueNodeIndex, transfertQueueNodeFamily}; - std::array priorities = {1.f, 1.f, 1.f}; - - std::vector queueCreateInfos; - for (UInt32 queueFamily : usedQueueFamilies) - { - auto it = std::find_if(queueCreateInfos.begin(), queueCreateInfos.end(), [queueFamily] (const VkDeviceQueueCreateInfo& createInfo) + std::array 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 Vulkan::CreateDevice(VkPhysicalDevice gpu, const QueueFamily* queueFamilies, std::size_t queueFamilyCount) + { + std::vector 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 enabledLayers; std::vector enabledExtensions; @@ -356,25 +410,51 @@ namespace Nz nullptr }; - ///TODO: First create then move - s_devices.emplace_back(s_instance); + std::shared_ptr device = std::make_shared(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 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 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& queueFamilyInfo = device.GetEnabledQueues(); + it = s_devices.erase(it); + continue; + } + + if (devicePtr->GetPhysicalDevice() == gpu) + { + const std::vector& 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 Vulkan::s_devices; + std::vector> Vulkan::s_devices; std::vector Vulkan::s_physDevices; Vk::Instance Vulkan::s_instance; ParameterList Vulkan::s_initializationParameters; diff --git a/src/Nazara/VulkanRenderer/VulkanBuffer.cpp b/src/Nazara/VulkanRenderer/VulkanBuffer.cpp index 530c345b4..08c9469a9 100644 --- a/src/Nazara/VulkanRenderer/VulkanBuffer.cpp +++ b/src/Nazara/VulkanRenderer/VulkanBuffer.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include 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; } } diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index bec1b3adb..2557f28b0 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -8,4 +8,9 @@ namespace Nz { VulkanDevice::~VulkanDevice() = default; + + std::unique_ptr VulkanDevice::InstantiateBuffer(Buffer* parent, BufferType type) + { + return std::make_unique(CreateHandle(), parent, type); + } } diff --git a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp index 57db953d4..db44df280 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp @@ -4,11 +4,12 @@ #include #include -#include +#include #include #include #include #include +#include #include namespace Nz @@ -18,11 +19,6 @@ namespace Nz Vulkan::Uninitialize(); } - std::unique_ptr VulkanRenderer::CreateHardwareBufferImpl(Buffer* parent, BufferType type) - { - return std::make_unique(parent, type); //< TODO - } - std::unique_ptr VulkanRenderer::CreateRenderSurfaceImpl() { return std::make_unique(); @@ -33,9 +29,10 @@ namespace Nz return std::make_unique(); } - std::unique_ptr VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex) + std::shared_ptr VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex) { - return std::unique_ptr(); + 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 VulkanRenderer::QueryRenderDevices() const + std::vector VulkanRenderer::QueryRenderDevices() const { - std::vector devices; + std::vector 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;