Add buffer support
This commit is contained in:
parent
9b8e8042e4
commit
cd31e6c397
|
|
@ -1,5 +1,6 @@
|
||||||
#include <Nazara/Utility.hpp>
|
#include <Nazara/Utility.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderBuffer.hpp>
|
||||||
#include <Nazara/Renderer/RenderWindow.hpp>
|
#include <Nazara/Renderer/RenderWindow.hpp>
|
||||||
#include <Nazara/VulkanRenderer.hpp>
|
#include <Nazara/VulkanRenderer.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
@ -112,13 +113,7 @@ int main()
|
||||||
|
|
||||||
Nz::MeshParams meshParams;
|
Nz::MeshParams meshParams;
|
||||||
meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 180.f));
|
meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 180.f));
|
||||||
|
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ_Normal);
|
||||||
Nz::Mesh drfreak;
|
|
||||||
if (!drfreak.LoadFromFile("resources/drfreak.md2", meshParams))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to load Dr. Freak");
|
|
||||||
return __LINE__;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nz::String windowTitle = "Vulkan Test";
|
Nz::String windowTitle = "Vulkan Test";
|
||||||
if (!window.Create(Nz::VideoMode(800, 600, 32), windowTitle))
|
if (!window.Create(Nz::VideoMode(800, 600, 32), windowTitle))
|
||||||
|
|
@ -141,23 +136,28 @@ int main()
|
||||||
std::vector<VkQueueFamilyProperties> queues;
|
std::vector<VkQueueFamilyProperties> queues;
|
||||||
instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &queues);*/
|
instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &queues);*/
|
||||||
|
|
||||||
Nz::Vk::DeviceHandle device = vulkanWindow.GetDevice();
|
Nz::VulkanDevice& device = vulkanWindow.GetDevice();
|
||||||
|
|
||||||
Nz::Vk::ShaderModule vertexShader;
|
Nz::Vk::ShaderModule vertexShader;
|
||||||
if (!vertexShader.Create(device, reinterpret_cast<Nz::UInt32*>(vertexShaderCode.data()), vertexShaderCode.size()))
|
if (!vertexShader.Create(device.CreateHandle(), reinterpret_cast<Nz::UInt32*>(vertexShaderCode.data()), vertexShaderCode.size()))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create vertex shader");
|
NazaraError("Failed to create vertex shader");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::Vk::ShaderModule fragmentShader;
|
Nz::Vk::ShaderModule fragmentShader;
|
||||||
if (!fragmentShader.Create(device, reinterpret_cast<Nz::UInt32*>(fragmentShaderCode.data()), fragmentShaderCode.size()))
|
if (!fragmentShader.Create(device.CreateHandle(), reinterpret_cast<Nz::UInt32*>(fragmentShaderCode.data()), fragmentShaderCode.size()))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create fragment shader");
|
NazaraError("Failed to create fragment shader");
|
||||||
return __LINE__;
|
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<Nz::StaticMesh*>(drfreak.GetSubMesh(0));
|
Nz::StaticMesh* drfreakMesh = static_cast<Nz::StaticMesh*>(drfreak.GetSubMesh(0));
|
||||||
|
|
||||||
|
|
@ -165,134 +165,28 @@ int main()
|
||||||
const Nz::IndexBuffer* drfreakIB = drfreakMesh->GetIndexBuffer();
|
const Nz::IndexBuffer* drfreakIB = drfreakMesh->GetIndexBuffer();
|
||||||
|
|
||||||
// Vertex buffer
|
// Vertex buffer
|
||||||
struct Vertex {
|
std::cout << "Index count: " << drfreakIB->GetIndexCount() << std::endl;
|
||||||
Nz::Vector4f pos;
|
|
||||||
Nz::Vector3f col;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*std::vector<Vertex> vertexBufferData = {
|
Nz::RenderBuffer* renderBufferIB = static_cast<Nz::RenderBuffer*>(drfreakIB->GetBuffer()->GetImpl());
|
||||||
{{-1.f, 1.f, 0.0f}, {1.0f, 0.0f, 0.0f}},
|
if (!renderBufferIB->Synchronize(&device))
|
||||||
{{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::Vector4f pos = vertexBufferData[i].pos;
|
NazaraError("Failed to synchronize render buffer");
|
||||||
vertexBufferData[i].pos = projection * (world * pos);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
Nz::BufferMapper<Nz::VertexBuffer> vertexMapper(drfreakVB, Nz::BufferAccess_ReadOnly);
|
|
||||||
Nz::MeshVertex* meshVertices = static_cast<Nz::MeshVertex*>(vertexMapper.GetPointer());
|
|
||||||
|
|
||||||
std::size_t vertexCount = drfreakVB->GetVertexCount();
|
|
||||||
|
|
||||||
Nz::Image meshImage;
|
|
||||||
if (!meshImage.LoadFromFile("resources/drfreak.tga"))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to load texture");
|
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Vertex> vertexBufferData;
|
Nz::VulkanBuffer* indexBufferImpl = static_cast<Nz::VulkanBuffer*>(renderBufferIB->GetHardwareBuffer(&device));
|
||||||
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<Nz::UInt32>(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__;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Index buffer
|
// Index buffer
|
||||||
Nz::IndexMapper indexMapper(drfreakIB);
|
std::cout << "Vertex count: " << drfreakVB->GetVertexCount() << std::endl;
|
||||||
|
|
||||||
std::size_t indexCount = indexMapper.GetIndexCount();
|
Nz::RenderBuffer* renderBufferVB = static_cast<Nz::RenderBuffer*>(drfreakVB->GetBuffer()->GetImpl());
|
||||||
std::vector<Nz::UInt32> indexBufferData;
|
if (!renderBufferVB->Synchronize(&device))
|
||||||
indexBufferData.reserve(indexCount);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < indexCount; ++i)
|
|
||||||
{
|
{
|
||||||
indexBufferData.push_back(indexMapper.Get(i));
|
NazaraError("Failed to synchronize render buffer");
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
}
|
}
|
||||||
|
|
||||||
memRequirement = indexBuffer.GetMemoryRequirements();
|
Nz::VulkanBuffer* vertexBufferImpl = static_cast<Nz::VulkanBuffer*>(renderBufferVB->GetHardwareBuffer(&device));
|
||||||
|
|
||||||
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__;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
@ -310,16 +204,16 @@ int main()
|
||||||
Nz::UInt32 uniformSize = sizeof(ubo);
|
Nz::UInt32 uniformSize = sizeof(ubo);
|
||||||
|
|
||||||
Nz::Vk::Buffer uniformBuffer;
|
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");
|
NazaraError("Failed to create vertex buffer");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
}
|
}
|
||||||
|
|
||||||
memRequirement = uniformBuffer.GetMemoryRequirements();
|
VkMemoryRequirements memRequirement = uniformBuffer.GetMemoryRequirements();
|
||||||
|
|
||||||
Nz::Vk::DeviceMemory uniformBufferMemory;
|
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");
|
NazaraError("Failed to allocate vertex buffer memory");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
|
|
@ -350,7 +244,7 @@ int main()
|
||||||
layoutBinding.pImmutableSamplers = nullptr;
|
layoutBinding.pImmutableSamplers = nullptr;
|
||||||
|
|
||||||
Nz::Vk::DescriptorSetLayout descriptorLayout;
|
Nz::Vk::DescriptorSetLayout descriptorLayout;
|
||||||
if (!descriptorLayout.Create(device, layoutBinding))
|
if (!descriptorLayout.Create(device.CreateHandle(), layoutBinding))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create descriptor set layout");
|
NazaraError("Failed to create descriptor set layout");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
|
|
@ -361,7 +255,7 @@ int main()
|
||||||
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
|
||||||
Nz::Vk::DescriptorPool descriptorPool;
|
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");
|
NazaraError("Failed to create descriptor pool");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
|
|
@ -396,7 +290,7 @@ int main()
|
||||||
|
|
||||||
VkVertexInputBindingDescription bindingDescription = {
|
VkVertexInputBindingDescription bindingDescription = {
|
||||||
0,
|
0,
|
||||||
sizeof(Vertex),
|
drfreakVB->GetStride(),
|
||||||
VK_VERTEX_INPUT_RATE_VERTEX
|
VK_VERTEX_INPUT_RATE_VERTEX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -406,14 +300,14 @@ int main()
|
||||||
{
|
{
|
||||||
0, // uint32_t location
|
0, // uint32_t location
|
||||||
0, // uint32_t binding;
|
0, // uint32_t binding;
|
||||||
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
|
VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format;
|
||||||
0 // uint32_t offset;
|
0 // uint32_t offset;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
1, // uint32_t location
|
1, // uint32_t location
|
||||||
0, // uint32_t binding;
|
0, // uint32_t binding;
|
||||||
VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format;
|
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;
|
Nz::Vk::PipelineLayout pipelineLayout;
|
||||||
pipelineLayout.Create(device, layout_create_info);
|
pipelineLayout.Create(device.CreateHandle(), layout_create_info);
|
||||||
|
|
||||||
std::array<VkDynamicState, 2> dynamicStates = {
|
std::array<VkDynamicState, 2> dynamicStates = {
|
||||||
VK_DYNAMIC_STATE_SCISSOR,
|
VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
|
@ -563,14 +457,14 @@ int main()
|
||||||
};
|
};
|
||||||
|
|
||||||
Nz::Vk::Pipeline pipeline;
|
Nz::Vk::Pipeline pipeline;
|
||||||
if (!pipeline.CreateGraphics(device, pipeline_create_info))
|
if (!pipeline.CreateGraphics(device.CreateHandle(), pipeline_create_info))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create pipeline");
|
NazaraError("Failed to create pipeline");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::Vk::CommandPool cmdPool;
|
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");
|
NazaraError("Failed to create rendering cmd pool");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
|
|
@ -580,7 +474,7 @@ int main()
|
||||||
clearValues[0].color = {1.0f, 0.8f, 0.4f, 0.0f};
|
clearValues[0].color = {1.0f, 0.8f, 0.4f, 0.0f};
|
||||||
clearValues[1].depthStencil = {1.f, 0};
|
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();
|
Nz::UInt32 imageCount = vulkanWindow.GetFramebufferCount();
|
||||||
std::vector<Nz::Vk::CommandBuffer> renderCmds = cmdPool.AllocateCommandBuffers(imageCount, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
std::vector<Nz::Vk::CommandBuffer> renderCmds = cmdPool.AllocateCommandBuffers(imageCount, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
||||||
|
|
@ -634,13 +528,13 @@ int main()
|
||||||
renderCmd.BeginRenderPass(render_pass_begin_info);
|
renderCmd.BeginRenderPass(render_pass_begin_info);
|
||||||
//renderCmd.ClearAttachment(clearAttachment, clearRect);
|
//renderCmd.ClearAttachment(clearAttachment, clearRect);
|
||||||
//renderCmd.ClearAttachment(clearAttachmentDepth, clearRect);
|
//renderCmd.ClearAttachment(clearAttachmentDepth, clearRect);
|
||||||
renderCmd.BindIndexBuffer(indexBuffer, 0, VK_INDEX_TYPE_UINT32);
|
renderCmd.BindIndexBuffer(indexBufferImpl->GetBufferHandle(), 0, VK_INDEX_TYPE_UINT16);
|
||||||
renderCmd.BindVertexBuffer(0, vertexBuffer, 0);
|
renderCmd.BindVertexBuffer(0, vertexBufferImpl->GetBufferHandle(), 0);
|
||||||
renderCmd.BindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);
|
renderCmd.BindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, descriptorSet);
|
||||||
renderCmd.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
renderCmd.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
renderCmd.SetScissor(Nz::Recti{0, 0, int(windowSize.x), int(windowSize.y)});
|
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.SetViewport({0.f, 0.f, float(windowSize.x), float(windowSize.y)}, 0.f, 1.f);
|
||||||
renderCmd.DrawIndexed(indexCount);
|
renderCmd.DrawIndexed(drfreakIB->GetIndexCount());
|
||||||
renderCmd.EndRenderPass();
|
renderCmd.EndRenderPass();
|
||||||
|
|
||||||
vulkanWindow.BuildPostRenderCommands(i, renderCmd);
|
vulkanWindow.BuildPostRenderCommands(i, renderCmd);
|
||||||
|
|
@ -675,21 +569,21 @@ int main()
|
||||||
window.Close();
|
window.Close();
|
||||||
break;
|
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)
|
// Gestion de la caméra free-fly (Rotation)
|
||||||
float sensitivity = 0.3f; // Sensibilité de la souris
|
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);
|
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);
|
camAngles.pitch = Nz::Clamp(camAngles.pitch + event.mouseMove.deltaY*sensitivity, -89.f, 89.f);
|
||||||
|
|
||||||
camQuat = camAngles;
|
camQuat = camAngles;
|
||||||
|
|
||||||
// Pour éviter que le curseur ne sorte de l'écran, nous le renvoyons au centre de la fenêtre
|
// 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
|
// Cette fonction est codée de sorte à ne pas provoquer d'évènement MouseMoved
|
||||||
Nz::Mouse::SetPosition(windowSize.x / 2, windowSize.y / 2, window);
|
Nz::Mouse::SetPosition(windowSize.x / 2, windowSize.y / 2, window);
|
||||||
updateUniforms = true;
|
updateUniforms = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -758,25 +652,25 @@ int main()
|
||||||
|
|
||||||
vulkanWindow.Present(imageIndex);
|
vulkanWindow.Present(imageIndex);
|
||||||
|
|
||||||
// On incrémente le compteur de FPS improvisé
|
// On incrémente le compteur de FPS improvisé
|
||||||
fps++;
|
fps++;
|
||||||
|
|
||||||
if (secondClock.GetMilliseconds() >= 1000) // Toutes les secondes
|
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");
|
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,
|
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".
|
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),
|
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".
|
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;
|
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();
|
secondClock.Restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -784,4 +678,4 @@ int main()
|
||||||
// instance.vkDestroyDebugReportCallbackEXT(instance, callback, nullptr);
|
// instance.vkDestroyDebugReportCallbackEXT(instance, callback, nullptr);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@
|
||||||
#include <Nazara/Renderer/GlslWriter.hpp>
|
#include <Nazara/Renderer/GlslWriter.hpp>
|
||||||
#include <Nazara/Renderer/OpenGL.hpp>
|
#include <Nazara/Renderer/OpenGL.hpp>
|
||||||
#include <Nazara/Renderer/RenderBuffer.hpp>
|
#include <Nazara/Renderer/RenderBuffer.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderDeviceInfo.hpp>
|
||||||
#include <Nazara/Renderer/RenderDevice.hpp>
|
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||||
#include <Nazara/Renderer/RenderDeviceInstance.hpp>
|
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
#include <Nazara/Renderer/RendererImpl.hpp>
|
#include <Nazara/Renderer/RendererImpl.hpp>
|
||||||
#include <Nazara/Renderer/RenderPipeline.hpp>
|
#include <Nazara/Renderer/RenderPipeline.hpp>
|
||||||
|
|
|
||||||
|
|
@ -7,31 +7,56 @@
|
||||||
#ifndef NAZARA_RENDERBUFFER_HPP
|
#ifndef NAZARA_RENDERBUFFER_HPP
|
||||||
#define NAZARA_RENDERBUFFER_HPP
|
#define NAZARA_RENDERBUFFER_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Core/MovablePtr.hpp>
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||||
#include <Nazara/Utility/AbstractBuffer.hpp>
|
#include <Nazara/Utility/AbstractBuffer.hpp>
|
||||||
#include <Nazara/Utility/SoftwareBuffer.hpp>
|
#include <Nazara/Utility/SoftwareBuffer.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
class RenderDevice;
|
||||||
|
|
||||||
class NAZARA_RENDERER_API RenderBuffer : public AbstractBuffer
|
class NAZARA_RENDERER_API RenderBuffer : public AbstractBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderBuffer() = default;
|
inline RenderBuffer(Buffer* parent, BufferType type);
|
||||||
|
RenderBuffer(const RenderBuffer&) = delete;
|
||||||
|
RenderBuffer(RenderBuffer&&) = default;
|
||||||
~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;
|
bool Initialize(UInt32 size, BufferUsageFlags usage) override;
|
||||||
|
|
||||||
|
AbstractBuffer* GetHardwareBuffer(RenderDevice* device);
|
||||||
DataStorage GetStorage() const override;
|
DataStorage GetStorage() const override;
|
||||||
|
|
||||||
virtual void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) = 0;
|
void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) override final;
|
||||||
virtual bool Unmap() = 0;
|
bool Unmap() override final;
|
||||||
|
|
||||||
|
RenderBuffer& operator=(const RenderBuffer&) = delete;
|
||||||
|
RenderBuffer& operator=(RenderBuffer&&) = default;
|
||||||
|
|
||||||
|
public: //< temp
|
||||||
|
bool Synchronize(RenderDevice* device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SoftwareBuffer m_softwareBuffer;
|
struct HardwareBuffer
|
||||||
};
|
{
|
||||||
|
std::unique_ptr<AbstractBuffer> buffer;
|
||||||
|
bool synchronized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
BufferUsageFlags m_usage;
|
||||||
|
SoftwareBuffer m_softwareBuffer;
|
||||||
|
Buffer* m_parent;
|
||||||
|
BufferType m_type;
|
||||||
|
std::size_t m_size;
|
||||||
|
std::unordered_map<RenderDevice*, HardwareBuffer> m_hardwareBuffers;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Renderer/RenderBuffer.inl>
|
#include <Nazara/Renderer/RenderBuffer.inl>
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,18 @@
|
||||||
// This file is part of the "Nazara Engine - Utility module"
|
// This file is part of the "Nazara Engine - Utility module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/RenderBuffer.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
inline RenderBuffer::RenderBuffer(Buffer* parent, BufferType type) :
|
||||||
|
m_softwareBuffer(parent, type),
|
||||||
|
m_parent(parent),
|
||||||
|
m_type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Renderer/DebugOff.hpp>
|
#include <Nazara/Renderer/DebugOff.hpp>
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,28 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef NAZARA_RENDERDEVICE_HPP
|
#ifndef NAZARA_RENDERDEVICEINSTANCE_HPP
|
||||||
#define NAZARA_RENDERDEVICE_HPP
|
#define NAZARA_RENDERDEVICEINSTANCE_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Utility/AbstractBuffer.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
struct RenderDevice
|
class Buffer;
|
||||||
|
|
||||||
|
class NAZARA_RENDERER_API RenderDevice
|
||||||
{
|
{
|
||||||
RenderDeviceType type;
|
public:
|
||||||
String name;
|
RenderDevice() = default;
|
||||||
|
virtual ~RenderDevice();
|
||||||
|
|
||||||
|
virtual std::unique_ptr<AbstractBuffer> InstantiateBuffer(Buffer* parent, BufferType type) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_RENDERER_HPP
|
#include <Nazara/Renderer/RenderDevice.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_RENDERDEVICEINSTANCE_HPP
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// This file is part of the "Nazara Engine - Renderer module"
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Renderer/RenderDeviceInstance.hpp>
|
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -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 <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Core/String.hpp>
|
||||||
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
struct RenderDeviceInfo
|
||||||
|
{
|
||||||
|
RenderDeviceType type;
|
||||||
|
String name;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NAZARA_RENDERER_HPP
|
||||||
|
|
@ -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 <Nazara/Prerequesites.hpp>
|
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
|
||||||
|
|
||||||
namespace Nz
|
|
||||||
{
|
|
||||||
///TODO: Rename
|
|
||||||
class NAZARA_RENDERER_API RenderDeviceInstance
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RenderDeviceInstance() = default;
|
|
||||||
virtual ~RenderDeviceInstance();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <Nazara/Renderer/RenderDeviceInstance.inl>
|
|
||||||
|
|
||||||
#endif // NAZARA_RENDERDEVICEINSTANCE_HPP
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
class RendererImpl;
|
||||||
class RenderSurface;
|
class RenderSurface;
|
||||||
|
|
||||||
class NAZARA_RENDERER_API RenderWindowImpl
|
class NAZARA_RENDERER_API RenderWindowImpl
|
||||||
|
|
@ -24,7 +25,7 @@ namespace Nz
|
||||||
RenderWindowImpl() = default;
|
RenderWindowImpl() = default;
|
||||||
virtual ~RenderWindowImpl();
|
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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
#include <Nazara/Renderer/RenderDevice.hpp>
|
#include <Nazara/Renderer/RenderDeviceInfo.hpp>
|
||||||
#include <Nazara/Utility/AbstractBuffer.hpp>
|
#include <Nazara/Utility/AbstractBuffer.hpp>
|
||||||
#include <Nazara/Utility/Enums.hpp>
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
class Buffer;
|
class Buffer;
|
||||||
class RendererImpl;
|
class RendererImpl;
|
||||||
class RenderDeviceInstance;
|
class RenderDevice;
|
||||||
class RenderSurface;
|
class RenderSurface;
|
||||||
class RenderWindowImpl;
|
class RenderWindowImpl;
|
||||||
|
|
||||||
|
|
@ -33,11 +33,10 @@ namespace Nz
|
||||||
RendererImpl() = default;
|
RendererImpl() = default;
|
||||||
virtual ~RendererImpl();
|
virtual ~RendererImpl();
|
||||||
|
|
||||||
virtual std::unique_ptr<AbstractBuffer> CreateHardwareBufferImpl(Buffer* parent, BufferType type) = 0;
|
|
||||||
virtual std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() = 0;
|
virtual std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() = 0;
|
||||||
virtual std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl() = 0;
|
virtual std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl() = 0;
|
||||||
|
|
||||||
virtual std::unique_ptr<RenderDeviceInstance> InstanciateRenderDevice(std::size_t deviceIndex) = 0;
|
virtual std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex) = 0;
|
||||||
|
|
||||||
virtual bool IsBetterThan(const RendererImpl* other) const = 0;
|
virtual bool IsBetterThan(const RendererImpl* other) const = 0;
|
||||||
|
|
||||||
|
|
@ -45,7 +44,7 @@ namespace Nz
|
||||||
virtual String QueryAPIString() const = 0;
|
virtual String QueryAPIString() const = 0;
|
||||||
virtual UInt32 QueryAPIVersion() const = 0;
|
virtual UInt32 QueryAPIVersion() const = 0;
|
||||||
|
|
||||||
virtual std::vector<RenderDevice> QueryRenderDevices() const = 0;
|
virtual std::vector<RenderDeviceInfo> QueryRenderDevices() const = 0;
|
||||||
|
|
||||||
virtual bool Prepare(const ParameterList& parameters) = 0;
|
virtual bool Prepare(const ParameterList& parameters) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ namespace Nz
|
||||||
|
|
||||||
bool Initialize(UInt32 size, BufferUsageFlags usage) override;
|
bool Initialize(UInt32 size, BufferUsageFlags usage) override;
|
||||||
|
|
||||||
|
const UInt8* GetData() const;
|
||||||
DataStorage GetStorage() const override;
|
DataStorage GetStorage() const override;
|
||||||
|
|
||||||
void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) override;
|
void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) override;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@
|
||||||
#include <Nazara/Core/Clock.hpp>
|
#include <Nazara/Core/Clock.hpp>
|
||||||
#include <Nazara/Math/Rect.hpp>
|
#include <Nazara/Math/Rect.hpp>
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
|
#include <Nazara/Renderer/RendererImpl.hpp>
|
||||||
#include <Nazara/Renderer/RenderWindowImpl.hpp>
|
#include <Nazara/Renderer/RenderWindowImpl.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Config.hpp>
|
#include <Nazara/VulkanRenderer/Config.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VkRenderTarget.hpp>
|
#include <Nazara/VulkanRenderer/VkRenderTarget.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/CommandPool.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/CommandPool.hpp>
|
||||||
|
|
@ -39,11 +41,12 @@ namespace Nz
|
||||||
void BuildPreRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) override;
|
void BuildPreRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) override;
|
||||||
void BuildPostRenderCommands(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 const Vk::Framebuffer& GetFrameBuffer(UInt32 imageIndex) const override;
|
||||||
inline UInt32 GetFramebufferCount() const;
|
inline UInt32 GetFramebufferCount() const override;
|
||||||
inline const Vk::DeviceHandle& GetDevice() const;
|
inline VulkanDevice& GetDevice();
|
||||||
|
inline const VulkanDevice& GetDevice() const;
|
||||||
inline UInt32 GetPresentableFamilyQueue() const;
|
inline UInt32 GetPresentableFamilyQueue() const;
|
||||||
inline const Vk::Swapchain& GetSwapchain() const;
|
inline const Vk::Swapchain& GetSwapchain() const;
|
||||||
|
|
||||||
|
|
@ -62,8 +65,8 @@ namespace Nz
|
||||||
VkFormat m_colorFormat;
|
VkFormat m_colorFormat;
|
||||||
VkFormat m_depthStencilFormat;
|
VkFormat m_depthStencilFormat;
|
||||||
VkPhysicalDevice m_physicalDevice;
|
VkPhysicalDevice m_physicalDevice;
|
||||||
|
std::shared_ptr<VulkanDevice> m_device;
|
||||||
std::vector<Vk::Framebuffer> m_frameBuffers;
|
std::vector<Vk::Framebuffer> m_frameBuffers;
|
||||||
Vk::DeviceHandle m_device;
|
|
||||||
Vk::DeviceMemory m_depthBufferMemory;
|
Vk::DeviceMemory m_depthBufferMemory;
|
||||||
Vk::Image m_depthBuffer;
|
Vk::Image m_depthBuffer;
|
||||||
Vk::ImageView m_depthBufferView;
|
Vk::ImageView m_depthBufferView;
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,14 @@
|
||||||
|
|
||||||
namespace Nz
|
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
|
inline const Vk::Framebuffer& VkRenderWindow::GetFrameBuffer(UInt32 imageIndex) const
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,28 @@
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/PhysicalDevice.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/PhysicalDevice.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Surface.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Surface.hpp>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
class VulkanDevice;
|
||||||
|
|
||||||
class NAZARA_VULKANRENDERER_API Vulkan
|
class NAZARA_VULKANRENDERER_API Vulkan
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct QueueFamily
|
||||||
|
{
|
||||||
|
UInt32 familyIndex;
|
||||||
|
float priority;
|
||||||
|
};
|
||||||
|
|
||||||
Vulkan() = delete;
|
Vulkan() = delete;
|
||||||
~Vulkan() = delete;
|
~Vulkan() = delete;
|
||||||
|
|
||||||
static Vk::DeviceHandle CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
|
static std::shared_ptr<VulkanDevice> CreateDevice(VkPhysicalDevice gpu);
|
||||||
|
static std::shared_ptr<VulkanDevice> CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
|
||||||
|
static std::shared_ptr<VulkanDevice> CreateDevice(VkPhysicalDevice gpu, const QueueFamily* queueFamilies, std::size_t queueFamilyCount);
|
||||||
|
|
||||||
static Vk::Instance& GetInstance();
|
static Vk::Instance& GetInstance();
|
||||||
|
|
||||||
|
|
@ -37,12 +48,13 @@ namespace Nz
|
||||||
|
|
||||||
static bool IsInitialized();
|
static bool IsInitialized();
|
||||||
|
|
||||||
static Vk::DeviceHandle SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
|
static std::shared_ptr<VulkanDevice> SelectDevice(VkPhysicalDevice gpu);
|
||||||
|
static std::shared_ptr<VulkanDevice> SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
|
||||||
|
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::list<Vk::Device> s_devices;
|
static std::vector<std::weak_ptr<VulkanDevice>> s_devices;
|
||||||
static std::vector<Vk::PhysicalDevice> s_physDevices;
|
static std::vector<Vk::PhysicalDevice> s_physDevices;
|
||||||
static Vk::Instance s_instance;
|
static Vk::Instance s_instance;
|
||||||
static ParameterList s_initializationParameters;
|
static ParameterList s_initializationParameters;
|
||||||
|
|
|
||||||
|
|
@ -9,25 +9,26 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Utility/AbstractBuffer.hpp>
|
#include <Nazara/Utility/AbstractBuffer.hpp>
|
||||||
#include <Nazara/Utility/SoftwareBuffer.hpp>
|
|
||||||
#include <Nazara/VulkanRenderer/Config.hpp>
|
#include <Nazara/VulkanRenderer/Config.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Buffer.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Buffer.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Wrapper/DeviceMemory.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
//TODO: Move all the software stuff to the Renderer
|
class Buffer;
|
||||||
|
|
||||||
class NAZARA_VULKANRENDERER_API VulkanBuffer : public AbstractBuffer
|
class NAZARA_VULKANRENDERER_API VulkanBuffer : public AbstractBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline VulkanBuffer(Buffer* parent, BufferType type);
|
inline VulkanBuffer(const Vk::DeviceHandle& device, Buffer* parent, BufferType type);
|
||||||
VulkanBuffer(const VulkanBuffer&) = delete;
|
VulkanBuffer(const VulkanBuffer&) = delete;
|
||||||
VulkanBuffer(VulkanBuffer&&) = delete; ///TODO
|
VulkanBuffer(VulkanBuffer&&) = delete; ///TODO
|
||||||
virtual ~VulkanBuffer();
|
virtual ~VulkanBuffer();
|
||||||
|
|
||||||
bool Fill(const void* data, UInt32 offset, UInt32 size) override;
|
bool Fill(const void* data, UInt32 offset, UInt32 size) override;
|
||||||
|
|
||||||
|
inline Nz::Vk::Buffer& GetBufferHandle();
|
||||||
bool Initialize(UInt32 size, BufferUsageFlags usage) override;
|
bool Initialize(UInt32 size, BufferUsageFlags usage) override;
|
||||||
|
|
||||||
DataStorage GetStorage() const override;
|
DataStorage GetStorage() const override;
|
||||||
|
|
@ -39,8 +40,11 @@ namespace Nz
|
||||||
VulkanBuffer& operator=(VulkanBuffer&&) = delete; ///TODO
|
VulkanBuffer& operator=(VulkanBuffer&&) = delete; ///TODO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BufferUsageFlags m_usage;
|
Buffer* m_parent;
|
||||||
SoftwareBuffer m_softwareData;
|
BufferType m_type;
|
||||||
|
Nz::Vk::Buffer m_buffer;
|
||||||
|
Nz::Vk::DeviceHandle m_device;
|
||||||
|
Nz::Vk::DeviceMemory m_memory;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,17 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline VulkanBuffer::VulkanBuffer(Buffer* parent, BufferType type) :
|
inline VulkanBuffer::VulkanBuffer(const Vk::DeviceHandle& device, Buffer* parent, BufferType type) :
|
||||||
m_softwareData(parent, type)
|
m_device(device),
|
||||||
|
m_parent(parent),
|
||||||
|
m_type(type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Nz::Vk::Buffer& Nz::VulkanBuffer::GetBufferHandle()
|
||||||
|
{
|
||||||
|
return m_buffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/VulkanRenderer/DebugOff.hpp>
|
#include <Nazara/VulkanRenderer/DebugOff.hpp>
|
||||||
|
|
|
||||||
|
|
@ -7,26 +7,26 @@
|
||||||
#ifndef NAZARA_VULKANRENDERER_VULKANDEVICE_HPP
|
#ifndef NAZARA_VULKANRENDERER_VULKANDEVICE_HPP
|
||||||
#define NAZARA_VULKANRENDERER_VULKANDEVICE_HPP
|
#define NAZARA_VULKANRENDERER_VULKANDEVICE_HPP
|
||||||
|
|
||||||
#include <Nazara/Renderer/RenderDeviceInstance.hpp>
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Device.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Device.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
//TODO: Move all the software stuff to the Renderer
|
class NAZARA_VULKANRENDERER_API VulkanDevice : public RenderDevice, public Vk::Device
|
||||||
|
|
||||||
class NAZARA_VULKANRENDERER_API VulkanDevice : public RenderDeviceInstance
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VulkanDevice(Vk::DeviceHandle device);
|
using Device::Device;
|
||||||
|
VulkanDevice(const VulkanDevice&) = delete;
|
||||||
|
VulkanDevice(VulkanDevice&&) = delete; ///TODO?
|
||||||
~VulkanDevice();
|
~VulkanDevice();
|
||||||
|
|
||||||
VulkanDevice& operator=(const VulkanDevice&) = delete;
|
std::unique_ptr<AbstractBuffer> InstantiateBuffer(Buffer* parent, BufferType type) override;
|
||||||
VulkanDevice& operator=(VulkanDevice&&) = delete; ///TODO
|
|
||||||
|
|
||||||
private:
|
VulkanDevice& operator=(const VulkanDevice&) = delete;
|
||||||
Vk::DeviceHandle m_device;
|
VulkanDevice& operator=(VulkanDevice&&) = delete; ///TODO?
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,87 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Renderer/RenderBuffer.hpp>
|
#include <Nazara/Renderer/RenderBuffer.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
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)
|
bool RenderBuffer::Initialize(UInt32 size, BufferUsageFlags usage)
|
||||||
{
|
{
|
||||||
|
m_size = size;
|
||||||
m_softwareBuffer.Initialize(size, usage);
|
m_softwareBuffer.Initialize(size, usage);
|
||||||
|
|
||||||
return true;
|
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;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
// This file is part of the "Nazara Engine - Renderer module"
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Renderer/RenderDeviceInstance.hpp>
|
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
RenderDeviceInstance::~RenderDeviceInstance() = default;
|
RenderDevice::~RenderDevice() = default;
|
||||||
}
|
}
|
||||||
|
|
@ -29,15 +29,16 @@ namespace Nz
|
||||||
|
|
||||||
bool RenderWindow::OnWindowCreated()
|
bool RenderWindow::OnWindowCreated()
|
||||||
{
|
{
|
||||||
auto surface = Renderer::GetRendererImpl()->CreateRenderSurfaceImpl();
|
RendererImpl* rendererImpl = Renderer::GetRendererImpl();
|
||||||
|
auto surface = rendererImpl->CreateRenderSurfaceImpl();
|
||||||
if (!surface->Create(GetHandle()))
|
if (!surface->Create(GetHandle()))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create render surface: " + Error::GetLastError());
|
NazaraError("Failed to create render surface: " + Error::GetLastError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto impl = Renderer::GetRendererImpl()->CreateRenderWindowImpl();
|
auto impl = rendererImpl->CreateRenderWindowImpl();
|
||||||
if (!impl->Create(surface.get(), GetSize(), m_parameters))
|
if (!impl->Create(rendererImpl, surface.get(), GetSize(), m_parameters))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create render window implementation: " + Error::GetLastError());
|
NazaraError("Failed to create render window implementation: " + Error::GetLastError());
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <Nazara/Core/DynLib.hpp>
|
#include <Nazara/Core/DynLib.hpp>
|
||||||
#include <Nazara/Core/Log.hpp>
|
#include <Nazara/Core/Log.hpp>
|
||||||
#include <Nazara/Platform/Platform.hpp>
|
#include <Nazara/Platform/Platform.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderBuffer.hpp>
|
||||||
#include <Nazara/Utility/AbstractBuffer.hpp>
|
#include <Nazara/Utility/AbstractBuffer.hpp>
|
||||||
#include <Nazara/Utility/Buffer.hpp>
|
#include <Nazara/Utility/Buffer.hpp>
|
||||||
#include <Nazara/Utility/Utility.hpp>
|
#include <Nazara/Utility/Utility.hpp>
|
||||||
|
|
@ -135,9 +136,9 @@ namespace Nz
|
||||||
Utility::Uninitialize();
|
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<RendererImpl> Renderer::s_rendererImpl;
|
std::unique_ptr<RendererImpl> Renderer::s_rendererImpl;
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,11 @@ namespace Nz
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UInt8* SoftwareBuffer::GetData() const
|
||||||
|
{
|
||||||
|
return m_buffer.data();
|
||||||
|
}
|
||||||
|
|
||||||
DataStorage SoftwareBuffer::GetStorage() const
|
DataStorage SoftwareBuffer::GetStorage() const
|
||||||
{
|
{
|
||||||
return DataStorage_Software;
|
return DataStorage_Software;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ namespace Nz
|
||||||
|
|
||||||
VkRenderWindow::~VkRenderWindow()
|
VkRenderWindow::~VkRenderWindow()
|
||||||
{
|
{
|
||||||
m_device->WaitForIdle();
|
if (m_device)
|
||||||
|
m_device->WaitForIdle();
|
||||||
|
|
||||||
m_frameBuffers.clear();
|
m_frameBuffers.clear();
|
||||||
m_renderPass.Destroy();
|
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);
|
//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;
|
m_physicalDevice = Vulkan::GetPhysicalDevices()[0].device;
|
||||||
|
|
||||||
|
|
@ -184,14 +186,14 @@ namespace Nz
|
||||||
1U // uint32_t layers;
|
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));
|
NazaraError("Failed to create framebuffer for image #" + String::Number(i));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_imageReadySemaphore.Create(m_device);
|
m_imageReadySemaphore.Create(m_device->CreateHandle());
|
||||||
|
|
||||||
m_clock.Restart();
|
m_clock.Restart();
|
||||||
|
|
||||||
|
|
@ -218,14 +220,14 @@ namespace Nz
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
|
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");
|
NazaraError("Failed to create depth buffer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkMemoryRequirements memoryReq = m_depthBuffer.GetMemoryRequirements();
|
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");
|
NazaraError("Failed to allocate depth buffer memory");
|
||||||
return false;
|
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");
|
NazaraError("Failed to create depth buffer view");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -353,7 +355,7 @@ namespace Nz
|
||||||
dependencies.data() // const VkSubpassDependency* pDependencies;
|
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)
|
bool VkRenderWindow::SetupSwapchain(Vk::Surface& surface, const Vector2ui& size)
|
||||||
|
|
@ -418,7 +420,7 @@ namespace Nz
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!m_swapchain.Create(m_device, swapchainInfo))
|
if (!m_swapchain.Create(m_device->CreateHandle(), swapchainInfo))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create swapchain");
|
NazaraError("Failed to create swapchain");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <Nazara/Core/Log.hpp>
|
#include <Nazara/Core/Log.hpp>
|
||||||
#include <Nazara/Utility/Utility.hpp>
|
#include <Nazara/Utility/Utility.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Config.hpp>
|
#include <Nazara/VulkanRenderer/Config.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
|
|
@ -186,10 +187,8 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
s_physDevices.reserve(physDevices.size());
|
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;
|
Vk::PhysicalDevice deviceInfo;
|
||||||
if (!s_instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &deviceInfo.queues))
|
if (!s_instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &deviceInfo.queues))
|
||||||
{
|
{
|
||||||
|
|
@ -225,7 +224,47 @@ namespace Nz
|
||||||
return s_instance.IsValid();
|
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);
|
Nz::ErrorFlags errFlags(ErrorFlag_ThrowException, true);
|
||||||
|
|
||||||
|
|
@ -267,15 +306,31 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<UInt32, 3> usedQueueFamilies = {graphicsQueueNodeIndex, presentQueueNodeIndex, transfertQueueNodeFamily};
|
std::array<QueueFamily, 3> queuesFamilies = {
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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())
|
if (it == queueCreateInfos.end())
|
||||||
|
|
@ -284,16 +339,15 @@ namespace Nz
|
||||||
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
|
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
|
||||||
nullptr, // const void* pNext;
|
nullptr, // const void* pNext;
|
||||||
0, // VkDeviceQueueCreateFlags flags;
|
0, // VkDeviceQueueCreateFlags flags;
|
||||||
queueFamily, // uint32_t queueFamilyIndex;
|
queueFamily.familyIndex, // uint32_t queueFamilyIndex;
|
||||||
1, // uint32_t queueCount;
|
1, // uint32_t queueCount;
|
||||||
priorities.data() // const float* pQueuePriorities;
|
&queueFamily.priority // const float* pQueuePriorities;
|
||||||
};
|
};
|
||||||
|
|
||||||
queueCreateInfos.emplace_back(createInfo);
|
queueCreateInfos.emplace_back(createInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<const char*> enabledLayers;
|
std::vector<const char*> enabledLayers;
|
||||||
std::vector<const char*> enabledExtensions;
|
std::vector<const char*> enabledExtensions;
|
||||||
|
|
||||||
|
|
@ -356,25 +410,51 @@ namespace Nz
|
||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
///TODO: First create then move
|
std::shared_ptr<VulkanDevice> device = std::make_shared<VulkanDevice>(s_instance);
|
||||||
s_devices.emplace_back(s_instance);
|
if (!device->Create(gpu, createInfo))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create Vulkan Device: " + TranslateVulkanError(device->GetLastErrorCode()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Vk::Device& device = s_devices.back();
|
s_devices.emplace_back(device);
|
||||||
device.Create(gpu, createInfo);
|
|
||||||
|
|
||||||
*presentableFamilyQueue = presentQueueNodeIndex;
|
return device;
|
||||||
|
|
||||||
return device.CreateHandle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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;
|
UInt32 presentableQueueFamilyIndex = UINT32_MAX;
|
||||||
for (Vk::Device::QueueFamilyInfo queueInfo : queueFamilyInfo)
|
for (Vk::Device::QueueFamilyInfo queueInfo : queueFamilyInfo)
|
||||||
{
|
{
|
||||||
|
|
@ -393,9 +473,11 @@ namespace Nz
|
||||||
if (presentableQueueFamilyIndex != UINT32_MAX)
|
if (presentableQueueFamilyIndex != UINT32_MAX)
|
||||||
{
|
{
|
||||||
*presentableFamilyQueue = presentableQueueFamilyIndex;
|
*presentableFamilyQueue = presentableQueueFamilyIndex;
|
||||||
return device.CreateHandle();
|
return devicePtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No device had support for that surface, create one
|
// No device had support for that surface, create one
|
||||||
|
|
@ -411,7 +493,7 @@ namespace Nz
|
||||||
Vk::Loader::Uninitialize();
|
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;
|
std::vector<Vk::PhysicalDevice> Vulkan::s_physDevices;
|
||||||
Vk::Instance Vulkan::s_instance;
|
Vk::Instance Vulkan::s_instance;
|
||||||
ParameterList Vulkan::s_initializationParameters;
|
ParameterList Vulkan::s_initializationParameters;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
||||||
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -11,13 +12,40 @@ namespace Nz
|
||||||
|
|
||||||
bool VulkanBuffer::Fill(const void* data, UInt32 offset, UInt32 size)
|
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)
|
bool VulkanBuffer::Initialize(UInt32 size, BufferUsageFlags usage)
|
||||||
{
|
{
|
||||||
m_usage = 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))
|
||||||
return m_softwareData.Initialize(size, usage);
|
{
|
||||||
|
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
|
DataStorage VulkanBuffer::GetStorage() const
|
||||||
|
|
@ -25,13 +53,17 @@ namespace Nz
|
||||||
return DataStorage_Hardware;
|
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()
|
bool VulkanBuffer::Unmap()
|
||||||
{
|
{
|
||||||
return m_softwareData.Unmap();
|
m_memory.Unmap();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,9 @@
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
VulkanDevice::~VulkanDevice() = default;
|
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/VulkanRenderer/VulkanRenderer.hpp>
|
||||||
#include <Nazara/Core/ErrorFlags.hpp>
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
#include <Nazara/Renderer/RenderDeviceInstance.hpp>
|
#include <Nazara/Renderer/RenderDevice.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
|
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VkRenderWindow.hpp>
|
#include <Nazara/VulkanRenderer/VkRenderWindow.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
||||||
|
#include <cassert>
|
||||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -18,11 +19,6 @@ namespace Nz
|
||||||
Vulkan::Uninitialize();
|
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()
|
std::unique_ptr<RenderSurface> VulkanRenderer::CreateRenderSurfaceImpl()
|
||||||
{
|
{
|
||||||
return std::make_unique<VulkanSurface>();
|
return std::make_unique<VulkanSurface>();
|
||||||
|
|
@ -33,9 +29,10 @@ namespace Nz
|
||||||
return std::make_unique<VkRenderWindow>();
|
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
|
bool VulkanRenderer::IsBetterThan(const RendererImpl* other) const
|
||||||
|
|
@ -69,14 +66,14 @@ namespace Nz
|
||||||
return APIVersion;
|
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());
|
devices.reserve(m_physDevices.size());
|
||||||
|
|
||||||
for (const Vk::PhysicalDevice& physDevice : m_physDevices)
|
for (const Vk::PhysicalDevice& physDevice : m_physDevices)
|
||||||
{
|
{
|
||||||
RenderDevice device;
|
RenderDeviceInfo device;
|
||||||
device.name = physDevice.properties.deviceName;
|
device.name = physDevice.properties.deviceName;
|
||||||
|
|
||||||
switch (physDevice.properties.deviceType)
|
switch (physDevice.properties.deviceType)
|
||||||
|
|
@ -104,7 +101,7 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
devices.emplace_back(device);
|
devices.emplace_back(std::move(device));
|
||||||
}
|
}
|
||||||
|
|
||||||
return devices;
|
return devices;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue