From 2b3241f3543c3ddac4aedbb3b8de99aa48389732 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 5 Mar 2020 20:35:31 +0100 Subject: [PATCH] Add RenderPipelineLayout --- examples/VulkanTest/main.cpp | 142 ++++++------------ include/Nazara/Core/Algorithm.hpp | 2 +- include/Nazara/Core/Algorithm.inl | 2 +- include/Nazara/Renderer.hpp | 1 + include/Nazara/Renderer/Enums.hpp | 1 + include/Nazara/Renderer/RenderDevice.hpp | 2 + include/Nazara/Renderer/RenderPipeline.hpp | 11 +- .../Nazara/Renderer/RenderPipelineLayout.hpp | 40 +++++ .../Nazara/Renderer/RenderPipelineLayout.inl | 13 ++ include/Nazara/Renderer/RenderStates.hpp | 9 -- include/Nazara/VulkanRenderer.hpp | 1 + include/Nazara/VulkanRenderer/Utils.hpp | 2 + include/Nazara/VulkanRenderer/Utils.inl | 29 +++- .../Nazara/VulkanRenderer/VulkanDevice.hpp | 1 + .../VulkanRenderer/VulkanRenderPipeline.hpp | 8 +- .../VulkanRenderPipelineLayout.hpp | 41 +++++ .../VulkanRenderPipelineLayout.inl | 21 +++ .../VulkanRenderer/Wrapper/PipelineLayout.hpp | 4 + .../VulkanRenderer/Wrapper/PipelineLayout.inl | 20 +++ src/Nazara/Renderer/RenderPipelineLayout.cpp | 11 ++ src/Nazara/VulkanRenderer/VkRenderWindow.cpp | 6 +- src/Nazara/VulkanRenderer/VulkanDevice.cpp | 10 ++ .../VulkanRenderer/VulkanRenderPipeline.cpp | 26 +++- .../VulkanRenderPipelineLayout.cpp | 39 +++++ src/Nazara/VulkanRenderer/VulkanRenderer.cpp | 14 +- 25 files changed, 330 insertions(+), 126 deletions(-) create mode 100644 include/Nazara/Renderer/RenderPipelineLayout.hpp create mode 100644 include/Nazara/Renderer/RenderPipelineLayout.inl create mode 100644 include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp create mode 100644 include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.inl create mode 100644 src/Nazara/Renderer/RenderPipelineLayout.cpp create mode 100644 src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp diff --git a/examples/VulkanTest/main.cpp b/examples/VulkanTest/main.cpp index a60dd2f07..bd121a9b1 100644 --- a/examples/VulkanTest/main.cpp +++ b/examples/VulkanTest/main.cpp @@ -66,24 +66,7 @@ int main() { std::cout << properties.layerName << ": \t" << properties.description << std::endl; } - /* - std::vector extensionProperties; - if (!Nz::Vk::Loader::EnumerateInstanceExtensionProperties(&extensionProperties)) - { - NazaraError("Failed to enumerate instance extension properties"); - return __LINE__; - } - for (const VkExtensionProperties& properties : extensionProperties) - std::cout << properties.extensionName << ": \t" << properties.specVersion << std::endl; - - std::vector devices; - if (!instance.EnumeratePhysicalDevices(&devices)) - { - NazaraError("Failed to enumerate physical devices"); - return __LINE__; - } - */ Nz::RenderWindow window; Nz::MeshParams meshParams; @@ -113,22 +96,6 @@ int main() return __LINE__; } - Nz::VkRenderWindow& vulkanWindow = *static_cast(window.GetImpl()); - - /*VkPhysicalDeviceFeatures features; - instance.GetPhysicalDeviceFeatures(physDevice, &features); - - VkPhysicalDeviceMemoryProperties memoryProperties; - instance.GetPhysicalDeviceMemoryProperties(physDevice, &memoryProperties); - - VkPhysicalDeviceProperties properties; - instance.GetPhysicalDeviceProperties(physDevice, &properties); - - std::vector queues; - instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &queues);*/ - - Nz::VulkanDevice& vulkanDevice = vulkanWindow.GetDevice(); - Nz::MeshRef drfreak = Nz::Mesh::LoadFromFile("resources/drfreak.md2", meshParams); if (!drfreak) @@ -145,27 +112,9 @@ int main() // Index buffer std::cout << "Index count: " << drfreakIB->GetIndexCount() << std::endl; - Nz::RenderBuffer* renderBufferIB = static_cast(drfreakIB->GetBuffer()->GetImpl()); - if (!renderBufferIB->Synchronize(&vulkanDevice)) - { - NazaraError("Failed to synchronize render buffer"); - return __LINE__; - } - - Nz::VulkanBuffer* indexBufferImpl = static_cast(renderBufferIB->GetHardwareBuffer(&vulkanDevice)); - // Vertex buffer std::cout << "Vertex count: " << drfreakVB->GetVertexCount() << std::endl; - Nz::RenderBuffer* renderBufferVB = static_cast(drfreakVB->GetBuffer()->GetImpl()); - if (!renderBufferVB->Synchronize(&vulkanDevice)) - { - NazaraError("Failed to synchronize render buffer"); - return __LINE__; - } - - Nz::VulkanBuffer* vertexBufferImpl = static_cast(renderBufferVB->GetHardwareBuffer(&vulkanDevice)); - struct { Nz::Matrix4f projectionMatrix; @@ -184,33 +133,26 @@ int main() Nz::UniformBuffer uniformBuffer(uniformSize, Nz::DataStorage_Hardware, Nz::BufferUsage_Dynamic); uniformBuffer.Fill(&ubo, 0, uniformSize); - Nz::RenderBuffer* renderBufferUB = static_cast(uniformBuffer.GetBuffer()->GetImpl()); - if (!renderBufferUB->Synchronize(&vulkanDevice)) - { - NazaraError("Failed to synchronize render buffer"); - return __LINE__; - } + Nz::RenderPipelineLayoutInfo pipelineLayoutInfo; + auto& bindingInfo = pipelineLayoutInfo.bindings.emplace_back(); + bindingInfo.index = 0; + bindingInfo.shaderStageFlags = Nz::ShaderStageType::Vertex; + bindingInfo.type = Nz::ShaderBindingType::UniformBuffer; - Nz::VulkanBuffer* uniformBufferImpl = static_cast(renderBufferUB->GetHardwareBuffer(&vulkanDevice)); + std::shared_ptr renderPipelineLayout = device->InstantiateRenderPipelineLayout(pipelineLayoutInfo); - VkDescriptorSetLayoutBinding layoutBinding = {}; - layoutBinding.binding = 0; - layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - layoutBinding.descriptorCount = 1; - layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - layoutBinding.pImmutableSamplers = nullptr; + Nz::VulkanRenderPipelineLayout* vkPipelineLayout = static_cast(renderPipelineLayout.get()); - Nz::Vk::DescriptorSetLayout descriptorLayout; - if (!descriptorLayout.Create(vulkanDevice.shared_from_this(), layoutBinding)) - { - NazaraError("Failed to create descriptor set layout"); - return __LINE__; - } + VkDescriptorSetLayout descriptorLayout = vkPipelineLayout->GetDescriptorSetLayout(); + VkPipelineLayout pipelineLayout = vkPipelineLayout->GetPipelineLayout(); VkDescriptorPoolSize poolSize; poolSize.descriptorCount = 1; poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + Nz::VkRenderWindow& vulkanWindow = *static_cast(window.GetImpl()); + Nz::VulkanDevice& vulkanDevice = vulkanWindow.GetDevice(); + Nz::Vk::DescriptorPool descriptorPool; if (!descriptorPool.Create(vulkanDevice.shared_from_this(), 1, poolSize, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) { @@ -220,9 +162,18 @@ int main() Nz::Vk::DescriptorSet descriptorSet = descriptorPool.AllocateDescriptorSet(descriptorLayout); + Nz::RenderBuffer* renderBufferUB = static_cast(uniformBuffer.GetBuffer()->GetImpl()); + if (!renderBufferUB->Synchronize(&vulkanDevice)) + { + NazaraError("Failed to synchronize render buffer"); + return __LINE__; + } + Nz::VulkanBuffer* uniformBufferImpl = static_cast(renderBufferUB->GetHardwareBuffer(&vulkanDevice)); descriptorSet.WriteUniformDescriptor(0, uniformBufferImpl->GetBufferHandle(), 0, uniformSize); Nz::RenderPipelineInfo pipelineInfo; + pipelineInfo.pipelineLayout = renderPipelineLayout; + pipelineInfo.depthBuffer = true; pipelineInfo.shaderStages.emplace_back(fragmentShader); pipelineInfo.shaderStages.emplace_back(vertexShader); @@ -231,35 +182,11 @@ int main() vertexBuffer.binding = 0; vertexBuffer.declaration = drfreakVB->GetVertexDeclaration(); - - //std::unique_ptr pipeline = device->InstantiateRenderPipeline(pipelineInfo); - - VkDescriptorSetLayout descriptorSetLayout = descriptorLayout; - - VkPipelineLayoutCreateInfo layout_create_info = { - VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType - nullptr, // const void *pNext - 0, // VkPipelineLayoutCreateFlags flags - 1U, // uint32_t setLayoutCount - &descriptorSetLayout, // const VkDescriptorSetLayout *pSetLayouts - 0, // uint32_t pushConstantRangeCount - nullptr // const VkPushConstantRange *pPushConstantRanges - }; - - Nz::Vk::PipelineLayout pipelineLayout; - pipelineLayout.Create(vulkanDevice.shared_from_this(), layout_create_info); + std::unique_ptr pipeline = device->InstantiateRenderPipeline(pipelineInfo); Nz::VulkanRenderPipeline::CreateInfo pipelineCreateInfo = Nz::VulkanRenderPipeline::BuildCreateInfo(pipelineInfo); - pipelineCreateInfo.pipelineInfo.layout = pipelineLayout; pipelineCreateInfo.pipelineInfo.renderPass = vulkanWindow.GetRenderPass(); - Nz::Vk::Pipeline vkPipeline; - if (!vkPipeline.CreateGraphics(vulkanDevice.shared_from_this(), pipelineCreateInfo.pipelineInfo)) - { - NazaraError("Failed to create pipeline"); - return __LINE__; - } - Nz::Vk::CommandPool cmdPool; if (!cmdPool.Create(vulkanDevice.shared_from_this(), 0, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)) { @@ -276,6 +203,26 @@ int main() Nz::UInt32 imageCount = vulkanWindow.GetFramebufferCount(); std::vector renderCmds = cmdPool.AllocateCommandBuffers(imageCount, VK_COMMAND_BUFFER_LEVEL_PRIMARY); + Nz::RenderBuffer* renderBufferIB = static_cast(drfreakIB->GetBuffer()->GetImpl()); + Nz::RenderBuffer* renderBufferVB = static_cast(drfreakVB->GetBuffer()->GetImpl()); + + if (!renderBufferIB->Synchronize(&vulkanDevice)) + { + NazaraError("Failed to synchronize render buffer"); + return __LINE__; + } + + if (!renderBufferVB->Synchronize(&vulkanDevice)) + { + NazaraError("Failed to synchronize render buffer"); + return __LINE__; + } + + Nz::VulkanBuffer* indexBufferImpl = static_cast(renderBufferIB->GetHardwareBuffer(&vulkanDevice)); + Nz::VulkanBuffer* vertexBufferImpl = static_cast(renderBufferVB->GetHardwareBuffer(&vulkanDevice)); + + Nz::VulkanRenderPipeline* vkPipeline = static_cast(pipeline.get()); + for (Nz::UInt32 i = 0; i < imageCount; ++i) { Nz::Vk::CommandBuffer& renderCmd = renderCmds[i]; @@ -307,7 +254,7 @@ int main() 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, vkPipeline); + renderCmd.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipeline->Get(vulkanWindow.GetRenderPass())); 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(drfreakIB->GetIndexCount()); @@ -352,6 +299,7 @@ int main() Nz::Clock updateClock; Nz::Clock secondClock; unsigned int fps = 0; + while (window.IsOpen()) { bool updateUniforms = false; @@ -410,8 +358,6 @@ int main() ubo.viewMatrix = Nz::Matrix4f::ViewMatrix(viewerPos, camAngles); uniformBuffer.Fill(&ubo, 0, uniformSize); - - Nz::RenderBuffer* renderBufferUB = static_cast(uniformBuffer.GetBuffer()->GetImpl()); if (!renderBufferUB->Synchronize(&vulkanDevice)) { NazaraError("Failed to synchronize render buffer"); diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index b1cef6a60..1a44940be 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -30,7 +30,7 @@ namespace Nz template std::size_t CountOf(const T& c); template void HashCombine(std::size_t& seed, const T& v); template T ReverseBits(T integer); - template auto UnderlyingCast(T value) -> std::underlying_type_t; + template constexpr auto UnderlyingCast(T value) -> std::underlying_type_t; template struct AlwaysFalse : std::false_type {}; diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index b6f10b37b..3a77759d3 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -196,7 +196,7 @@ namespace Nz } template - auto UnderlyingCast(T value) -> std::underlying_type_t + constexpr auto UnderlyingCast(T value) -> std::underlying_type_t { return static_cast>(value); } diff --git a/include/Nazara/Renderer.hpp b/include/Nazara/Renderer.hpp index 75c13cf0c..b043de0de 100644 --- a/include/Nazara/Renderer.hpp +++ b/include/Nazara/Renderer.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 5a6463ed3..4721662ff 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -60,6 +60,7 @@ namespace Nz Max = Vertex }; + template<> struct EnumAsFlags { static constexpr ShaderStageType max = ShaderStageType::Max; diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index b1716090f..739471ea4 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ namespace Nz virtual std::unique_ptr InstantiateBuffer(Buffer* parent, BufferType type) = 0; virtual std::unique_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; + virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; virtual std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0; std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const std::filesystem::path& sourcePath); }; diff --git a/include/Nazara/Renderer/RenderPipeline.hpp b/include/Nazara/Renderer/RenderPipeline.hpp index fd3350637..6e938eba7 100644 --- a/include/Nazara/Renderer/RenderPipeline.hpp +++ b/include/Nazara/Renderer/RenderPipeline.hpp @@ -8,6 +8,7 @@ #define NAZARA_RENDERPIPELINE_HPP #include +#include #include //#include @@ -15,7 +16,15 @@ namespace Nz { struct RenderPipelineInfo : RenderStates { - /*ShaderConstRef shader;*/ + struct VertexBufferData + { + std::size_t binding; + VertexDeclarationConstRef declaration; + }; + + std::shared_ptr pipelineLayout; + std::vector> shaderStages; + std::vector vertexBuffers; }; class NAZARA_RENDERER_API RenderPipeline diff --git a/include/Nazara/Renderer/RenderPipelineLayout.hpp b/include/Nazara/Renderer/RenderPipelineLayout.hpp new file mode 100644 index 000000000..13d6ab668 --- /dev/null +++ b/include/Nazara/Renderer/RenderPipelineLayout.hpp @@ -0,0 +1,40 @@ +// Copyright (C) 2020 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_RENDERPIPELINELAYOUT_HPP +#define NAZARA_RENDERPIPELINELAYOUT_HPP + +#include +#include +#include +#include + +namespace Nz +{ + struct RenderPipelineLayoutInfo + { + struct Binding + { + std::string name; //< FIXME: wtf is this? + ShaderBindingType type; + ShaderStageTypeFlags shaderStageFlags; + unsigned int index; + }; + + std::vector bindings; + }; + + class NAZARA_RENDERER_API RenderPipelineLayout + { + public: + RenderPipelineLayout() = default; + virtual ~RenderPipelineLayout(); + }; +} + +#include + +#endif // NAZARA_RENDERPIPELINELAYOUT_HPP diff --git a/include/Nazara/Renderer/RenderPipelineLayout.inl b/include/Nazara/Renderer/RenderPipelineLayout.inl new file mode 100644 index 000000000..71049528f --- /dev/null +++ b/include/Nazara/Renderer/RenderPipelineLayout.inl @@ -0,0 +1,13 @@ +// Copyright (C) 2020 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 + +#include +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Renderer/RenderStates.hpp b/include/Nazara/Renderer/RenderStates.hpp index 6d40197c2..dca3d4c7c 100644 --- a/include/Nazara/Renderer/RenderStates.hpp +++ b/include/Nazara/Renderer/RenderStates.hpp @@ -37,15 +37,6 @@ namespace Nz UInt32 writeMask = 0xFFFFFFFF; } stencilBack, stencilFront; - struct VertexBufferData - { - std::size_t binding; - VertexDeclarationConstRef declaration; - }; - - std::vector> shaderStages; - std::vector vertexBuffers; - bool blending = false; bool colorWrite = true; bool depthBuffer = false; diff --git a/include/Nazara/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer.hpp index 429629660..e93ca271d 100644 --- a/include/Nazara/VulkanRenderer.hpp +++ b/include/Nazara/VulkanRenderer.hpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/VulkanRenderer/Utils.hpp b/include/Nazara/VulkanRenderer/Utils.hpp index fcf092394..71c0af4c4 100644 --- a/include/Nazara/VulkanRenderer/Utils.hpp +++ b/include/Nazara/VulkanRenderer/Utils.hpp @@ -20,7 +20,9 @@ namespace Nz inline VkPolygonMode ToVulkan(FaceFilling faceFilling); inline VkPrimitiveTopology ToVulkan(PrimitiveMode primitiveMode); inline VkCompareOp ToVulkan(RendererComparison comparison); + inline VkDescriptorType ToVulkan(ShaderBindingType bindingType); inline VkShaderStageFlagBits ToVulkan(ShaderStageType stageType); + inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType); inline VkStencilOp ToVulkan(StencilOperation stencilOp); inline VkVertexInputRate ToVulkan(VertexInputRate inputRate); diff --git a/include/Nazara/VulkanRenderer/Utils.inl b/include/Nazara/VulkanRenderer/Utils.inl index 69c89d85d..4c9b5616d 100644 --- a/include/Nazara/VulkanRenderer/Utils.inl +++ b/include/Nazara/VulkanRenderer/Utils.inl @@ -95,6 +95,18 @@ namespace Nz return VK_COMPARE_OP_NEVER; } + VkDescriptorType ToVulkan(ShaderBindingType bindingType) + { + switch (bindingType) + { + case ShaderBindingType::Texture: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + case ShaderBindingType::UniformBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + } + + NazaraError("Unhandled ShaderBindingType 0x" + String::Number(UnderlyingCast(bindingType), 16)); + return VK_DESCRIPTOR_TYPE_SAMPLER; + } + VkShaderStageFlagBits ToVulkan(ShaderStageType stageType) { switch (stageType) @@ -103,10 +115,25 @@ namespace Nz case ShaderStageType::Vertex: return VK_SHADER_STAGE_VERTEX_BIT; } - NazaraError("Unhandled ShaderStageType 0x" + String::Number(static_cast(stageType), 16)); + NazaraError("Unhandled ShaderStageType 0x" + String::Number(UnderlyingCast(stageType), 16)); return {}; } + VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType) + { + VkShaderStageFlags shaderStageBits = 0; + + if (stageType.Test(ShaderStageType::Fragment)) + shaderStageBits |= VK_SHADER_STAGE_FRAGMENT_BIT; + + if (stageType.Test(ShaderStageType::Vertex)) + shaderStageBits |= VK_SHADER_STAGE_VERTEX_BIT; + + static_assert(UnderlyingCast(ShaderStageType::Max) + 1 == 2); + + return shaderStageBits; + } + VkStencilOp ToVulkan(StencilOperation stencilOp) { switch (stencilOp) diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 9d625d634..7fe07729a 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -25,6 +25,7 @@ namespace Nz std::unique_ptr InstantiateBuffer(Buffer* parent, BufferType type) override; std::unique_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; + std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override; VulkanDevice& operator=(const VulkanDevice&) = delete; diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp b/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp index a622c51ff..baa644c60 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderPipeline.hpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include namespace Nz @@ -23,6 +25,8 @@ namespace Nz VulkanRenderPipeline(Vk::DeviceHandle device, RenderPipelineInfo pipelineInfo); ~VulkanRenderPipeline() = default; + VkPipeline Get(const Vk::RenderPass& renderPass); + static std::vector BuildColorBlendAttachmentStateList(const RenderPipelineInfo& pipelineInfo); static VkPipelineColorBlendStateCreateInfo BuildColorBlendInfo(const RenderPipelineInfo& pipelineInfo, const std::vector& attachmentState); static VkPipelineDepthStencilStateCreateInfo BuildDepthStencilInfo(const RenderPipelineInfo& pipelineInfo); @@ -64,9 +68,9 @@ namespace Nz }; private: - - + std::unordered_map m_pipelines; Vk::DeviceHandle m_device; + CreateInfo m_pipelineCreateInfo; RenderPipelineInfo m_pipelineInfo; }; } diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp b/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp new file mode 100644 index 000000000..beac99148 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2020 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_VULKANRENDERER_VULKANRENDERPIPELINELAYOUT_HPP +#define NAZARA_VULKANRENDERER_VULKANRENDERPIPELINELAYOUT_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_VULKANRENDERER_API VulkanRenderPipelineLayout : public RenderPipelineLayout + { + public: + VulkanRenderPipelineLayout() = default; + ~VulkanRenderPipelineLayout() = default; + + bool Create(Vk::DeviceHandle device, RenderPipelineLayoutInfo layoutInfo); + + inline const Vk::DescriptorSetLayout& GetDescriptorSetLayout() const; + inline const Vk::PipelineLayout& GetPipelineLayout() const; + + private: + Vk::DeviceHandle m_device; + Vk::DescriptorSetLayout m_descriptorSetLayout; + Vk::PipelineLayout m_pipelineLayout; + RenderPipelineLayoutInfo m_layoutInfo; + }; +} + +#include + +#endif // NAZARA_VULKANRENDERER_VULKANRENDERPIPELINE_HPP diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.inl b/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.inl new file mode 100644 index 000000000..36cad5f4a --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.inl @@ -0,0 +1,21 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline const Vk::DescriptorSetLayout& VulkanRenderPipelineLayout::GetDescriptorSetLayout() const + { + return m_descriptorSetLayout; + } + + inline const Vk::PipelineLayout& VulkanRenderPipelineLayout::GetPipelineLayout() const + { + return m_pipelineLayout; + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/Wrapper/PipelineLayout.hpp b/include/Nazara/VulkanRenderer/Wrapper/PipelineLayout.hpp index 7e2af843e..1a27d40a4 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/PipelineLayout.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/PipelineLayout.hpp @@ -24,6 +24,10 @@ namespace Nz PipelineLayout(PipelineLayout&&) = default; ~PipelineLayout() = default; + using DeviceObject::Create; + bool Create(DeviceHandle device, VkDescriptorSetLayout layout, VkPipelineLayoutCreateFlags flags = 0); + bool Create(DeviceHandle device, UInt32 layoutCount, const VkDescriptorSetLayout* layouts, VkPipelineLayoutCreateFlags flags = 0); + PipelineLayout& operator=(const PipelineLayout&) = delete; PipelineLayout& operator=(PipelineLayout&&) = delete; diff --git a/include/Nazara/VulkanRenderer/Wrapper/PipelineLayout.inl b/include/Nazara/VulkanRenderer/Wrapper/PipelineLayout.inl index 333062780..3f0f52df1 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/PipelineLayout.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/PipelineLayout.inl @@ -9,6 +9,26 @@ namespace Nz { namespace Vk { + inline bool PipelineLayout::Create(DeviceHandle device, VkDescriptorSetLayout layout, VkPipelineLayoutCreateFlags flags) + { + return Create(std::move(device), 1U, &layout, flags); + } + + inline bool PipelineLayout::Create(DeviceHandle device, UInt32 layoutCount, const VkDescriptorSetLayout* layouts, VkPipelineLayoutCreateFlags flags) + { + VkPipelineLayoutCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + nullptr, + flags, + layoutCount, + layouts, + 0U, + nullptr + }; + + return Create(std::move(device), createInfo); + } + inline VkResult PipelineLayout::CreateHelper(const DeviceHandle& device, const VkPipelineLayoutCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkPipelineLayout* handle) { return device->vkCreatePipelineLayout(*device, createInfo, allocator, handle); diff --git a/src/Nazara/Renderer/RenderPipelineLayout.cpp b/src/Nazara/Renderer/RenderPipelineLayout.cpp new file mode 100644 index 000000000..ec26fad08 --- /dev/null +++ b/src/Nazara/Renderer/RenderPipelineLayout.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2015 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 + +#include +#include + +namespace Nz +{ + RenderPipelineLayout::~RenderPipelineLayout() = default; +} diff --git a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp index 6edaa6649..08b9b651e 100644 --- a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp +++ b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp @@ -137,7 +137,7 @@ namespace Nz return false; } - if (!SetupRenderPass(size)) + if (!SetupRenderPass()) { NazaraError("Failed to create render pass"); return false; @@ -245,8 +245,8 @@ namespace Nz return true; } - bool VkRenderWindow::SetupRenderPass(const Vector2ui& size) - { + bool VkRenderWindow::SetupRenderPass() +{ std::array attachments = { { { diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 827433a1c..f1c532846 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -21,6 +22,15 @@ namespace Nz return std::make_unique(shared_from_this(), std::move(pipelineInfo)); } + std::shared_ptr VulkanDevice::InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) + { + auto pipelineLayout = std::make_shared(); + if (!pipelineLayout->Create(shared_from_this(), std::move(pipelineLayoutInfo))) + return {}; + + return pipelineLayout; + } + std::shared_ptr VulkanDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) { auto stage = std::make_shared(); diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp index 47c133104..93a05ebcc 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp @@ -4,10 +4,10 @@ #include #include -#include #include +#include +#include #include -#include #include namespace Nz @@ -16,6 +16,24 @@ namespace Nz m_device(std::move(device)), m_pipelineInfo(std::move(pipelineInfo)) { + m_pipelineCreateInfo = BuildCreateInfo(m_pipelineInfo); + } + + VkPipeline VulkanRenderPipeline::Get(const Vk::RenderPass& renderPass) + { + if (auto it = m_pipelines.find(renderPass); it != m_pipelines.end()) + return it->second; + + // Copy create info to make Get re-entrant + VkGraphicsPipelineCreateInfo pipelineCreateInfo = m_pipelineCreateInfo.pipelineInfo; + pipelineCreateInfo.renderPass = renderPass; + + Vk::Pipeline newPipeline; + if (!newPipeline.CreateGraphics(m_device, pipelineCreateInfo)) + return VK_NULL_HANDLE; + + auto it = m_pipelines.emplace(renderPass, std::move(newPipeline)).first; + return it->second; } std::vector VulkanRenderPipeline::BuildColorBlendAttachmentStateList(const RenderPipelineInfo& pipelineInfo) @@ -235,7 +253,6 @@ namespace Nz createInfo.pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; createInfo.pipelineInfo.stageCount = std::uint32_t(createInfo.shaderStages.size()); createInfo.pipelineInfo.pStages = createInfo.shaderStages.data(); - createInfo.pipelineInfo.pColorBlendState = &createInfo.stateData->colorBlendState; createInfo.pipelineInfo.pDepthStencilState = &createInfo.stateData->depthStencilState; createInfo.pipelineInfo.pDynamicState = &createInfo.stateData->dynamicState; @@ -245,6 +262,9 @@ namespace Nz createInfo.pipelineInfo.pVertexInputState = &createInfo.stateData->vertexInputState; createInfo.pipelineInfo.pViewportState = &createInfo.stateData->viewportState; + VulkanRenderPipelineLayout& pipelineLayout = *static_cast(pipelineInfo.pipelineLayout.get()); + createInfo.pipelineInfo.layout = pipelineLayout.GetPipelineLayout(); + return createInfo; } } diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp new file mode 100644 index 000000000..d509ff043 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + bool VulkanRenderPipelineLayout::Create(Vk::DeviceHandle device, RenderPipelineLayoutInfo layoutInfo) + { + m_device = std::move(device); + m_layoutInfo = std::move(layoutInfo); + + StackVector layoutBindings = NazaraStackVector(VkDescriptorSetLayoutBinding, m_layoutInfo.bindings.size()); + + for (const auto& bindingInfo : m_layoutInfo.bindings) + { + VkDescriptorSetLayoutBinding& layoutBinding = layoutBindings.emplace_back(); + layoutBinding.binding = bindingInfo.index; + layoutBinding.descriptorCount = 1U; + layoutBinding.descriptorType = ToVulkan(bindingInfo.type); + layoutBinding.stageFlags = ToVulkan(bindingInfo.shaderStageFlags); + } + + if (!m_descriptorSetLayout.Create(m_device, layoutBindings.size(), layoutBindings.data())) + return false; + + if (!m_pipelineLayout.Create(m_device, m_descriptorSetLayout)) + return false; + + return true; + } +} diff --git a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp index 3900a0248..7e543c256 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp @@ -37,7 +37,7 @@ namespace Nz bool VulkanRenderer::IsBetterThan(const RendererImpl* other) const { - if (other->QueryAPI() == RenderAPI_Vulkan && QueryAPIVersion() < other->QueryAPIVersion()) + if (other->QueryAPI() == RenderAPI::Vulkan && QueryAPIVersion() < other->QueryAPIVersion()) return false; return true; //< Vulkan FTW @@ -50,7 +50,7 @@ namespace Nz RenderAPI VulkanRenderer::QueryAPI() const { - return RenderAPI_Vulkan; + return RenderAPI::Vulkan; } String VulkanRenderer::QueryAPIString() const @@ -79,25 +79,25 @@ namespace Nz switch (physDevice.properties.deviceType) { case VK_PHYSICAL_DEVICE_TYPE_CPU: - device.type = RenderDeviceType_Software; + device.type = RenderDeviceType::Software; break; case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: - device.type = RenderDeviceType_Dedicated; + device.type = RenderDeviceType::Dedicated; break; case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: - device.type = RenderDeviceType_Integrated; + device.type = RenderDeviceType::Integrated; break; case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: - device.type = RenderDeviceType_Virtual; + device.type = RenderDeviceType::Virtual; break; default: NazaraWarning("Device " + device.name + " has handled device type (0x" + String::Number(physDevice.properties.deviceType, 16) + ')'); case VK_PHYSICAL_DEVICE_TYPE_OTHER: - device.type = RenderDeviceType_Unknown; + device.type = RenderDeviceType::Unknown; break; }