diff --git a/build/scripts/actions/generateheaders.lua b/build/scripts/actions/generateheaders.lua index d9bbe3ea6..81536a706 100644 --- a/build/scripts/actions/generateheaders.lua +++ b/build/scripts/actions/generateheaders.lua @@ -43,7 +43,10 @@ ACTION.Function = function () end table.insert(paths, { - Excludes = {}, + Excludes = { + ["DeviceFunctions.hpp"] = true, + ["InstanceFunctions.hpp"] = true, + }, HeaderGuard = "NAZARA_GLOBAL_VULKANRENDERER_WRAPPER_HPP", Name = "Vulkan wrapper", SearchDir = "../include/Nazara/VulkanRenderer/Wrapper", diff --git a/examples/VulkanTest/main.cpp b/examples/VulkanTest/main.cpp index d85a2c85c..f71e98518 100644 --- a/examples/VulkanTest/main.cpp +++ b/examples/VulkanTest/main.cpp @@ -70,8 +70,8 @@ int main() Nz::RenderWindow window; Nz::MeshParams meshParams; - meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 180.f)); - meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ_Normal); + meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 180.f)) * Nz::Matrix4f::Scale(Nz::Vector3f(0.002f)); + meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ_Normal_UV); Nz::String windowTitle = "Vulkan Test"; if (!window.Create(Nz::VideoMode(800, 600, 32), windowTitle)) @@ -96,7 +96,7 @@ int main() return __LINE__; } - Nz::MeshRef drfreak = Nz::Mesh::LoadFromFile("resources/drfreak.md2", meshParams); + Nz::MeshRef drfreak = Nz::Mesh::LoadFromFile("resources/Spaceship/spaceship.obj", meshParams); if (!drfreak) { @@ -115,6 +115,153 @@ int main() // Vertex buffer std::cout << "Vertex count: " << drfreakVB->GetVertexCount() << std::endl; + Nz::VkRenderWindow& vulkanWindow = *static_cast(window.GetImpl()); + Nz::VulkanDevice& vulkanDevice = vulkanWindow.GetDevice(); + + Nz::Vk::CommandPool cmdPool; + if (!cmdPool.Create(vulkanDevice, 0, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)) + { + NazaraError("Failed to create rendering cmd pool"); + return __LINE__; + } + + Nz::Vk::QueueHandle graphicsQueue = vulkanDevice.GetQueue(0, 0); + + // Texture + Nz::ImageRef drfreakImage = Nz::Image::LoadFromFile("resources/Spaceship/Texture/diffuse.png"); + if (!drfreakImage || !drfreakImage->Convert(Nz::PixelFormatType_RGBA8)) + { + NazaraError("Failed to load image"); + return __LINE__; + } + + VkImageCreateInfo imageInfo = {}; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.extent.width = static_cast(drfreakImage->GetWidth()); + imageInfo.extent.height = static_cast(drfreakImage->GetHeight()); + imageInfo.extent.depth = 1; + imageInfo.mipLevels = 1; + imageInfo.arrayLayers = 1; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + Nz::Vk::Image vkImage; + if (!vkImage.Create(vulkanDevice, imageInfo)) + { + NazaraError("Failed to create vulkan image"); + return __LINE__; + } + + VkMemoryRequirements imageMemRequirement = vkImage.GetMemoryRequirements(); + + Nz::Vk::DeviceMemory imageMemory; + if (!imageMemory.Create(vulkanDevice, imageMemRequirement.size, imageMemRequirement.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) + { + NazaraError("Failed to create vulkan image memory"); + return __LINE__; + } + + vkImage.BindImageMemory(imageMemory); + + // Update texture + { + Nz::Vk::Buffer stagingImageBuffer; + if (!stagingImageBuffer.Create(vulkanDevice, 0, drfreakImage->GetMemoryUsage(), VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) + { + NazaraError("Failed to create staging buffer"); + return __LINE__; + } + + VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + + Nz::Vk::DeviceMemory stagingImageMemory; + + VkMemoryRequirements memRequirement = stagingImageBuffer.GetMemoryRequirements(); + if (!stagingImageMemory.Create(vulkanDevice, memRequirement.size, memRequirement.memoryTypeBits, memoryProperties)) + { + NazaraError("Failed to allocate vertex buffer memory"); + return __LINE__; + } + + if (!stagingImageBuffer.BindBufferMemory(stagingImageMemory)) + { + NazaraError("Failed to bind vertex buffer to its memory"); + return __LINE__; + } + + if (!stagingImageMemory.Map(0, memRequirement.size)) + return __LINE__; + + std::memcpy(stagingImageMemory.GetMappedPointer(), drfreakImage->GetPixels(), drfreakImage->GetMemoryUsage()); + + stagingImageMemory.FlushMemory(); + stagingImageMemory.Unmap(); + + Nz::Vk::CommandBuffer copyCommand = cmdPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY); + copyCommand.Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + copyCommand.SetImageLayout(vkImage, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + copyCommand.CopyBufferToImage(stagingImageBuffer, vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, drfreakImage->GetWidth(), drfreakImage->GetHeight()); + copyCommand.SetImageLayout(vkImage, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + if (!copyCommand.End()) + return __LINE__; + + if (!graphicsQueue.Submit(copyCommand)) + return __LINE__; + + graphicsQueue.WaitIdle(); + } + + // Create image view + + VkImageViewCreateInfo imageViewInfo = {}; + imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + imageViewInfo.components = { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }; + imageViewInfo.format = VK_FORMAT_R8G8B8A8_SRGB; + imageViewInfo.image = vkImage; + imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + imageViewInfo.subresourceRange = { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + 1, + 0, + 1 + }; + + Nz::Vk::ImageView imageView; + if (!imageView.Create(vulkanDevice, imageViewInfo)) + return __LINE__; + + // Sampler + + VkSamplerCreateInfo samplerInfo = {}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.magFilter = VK_FILTER_LINEAR; + samplerInfo.minFilter = VK_FILTER_LINEAR; + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerInfo.anisotropyEnable = VK_FALSE; + samplerInfo.maxAnisotropy = 16; + samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + samplerInfo.unnormalizedCoordinates = VK_FALSE; + samplerInfo.compareEnable = VK_FALSE; + samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; + samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + + Nz::Vk::Sampler imageSampler; + if (!imageSampler.Create(vulkanDevice, samplerInfo)) + return __LINE__; + struct { Nz::Matrix4f projectionMatrix; @@ -131,33 +278,21 @@ int main() Nz::UInt32 uniformSize = sizeof(ubo); Nz::RenderPipelineLayoutInfo pipelineLayoutInfo; - auto& bindingInfo = pipelineLayoutInfo.bindings.emplace_back(); - bindingInfo.index = 0; - bindingInfo.shaderStageFlags = Nz::ShaderStageType::Vertex; - bindingInfo.type = Nz::ShaderBindingType::UniformBuffer; + auto& uboBinding = pipelineLayoutInfo.bindings.emplace_back(); + uboBinding.index = 0; + uboBinding.shaderStageFlags = Nz::ShaderStageType::Vertex; + uboBinding.type = Nz::ShaderBindingType::UniformBuffer; + + auto& textureBinding = pipelineLayoutInfo.bindings.emplace_back(); + textureBinding.index = 1; + textureBinding.shaderStageFlags = Nz::ShaderStageType::Fragment; + textureBinding.type = Nz::ShaderBindingType::Texture; std::shared_ptr renderPipelineLayout = device->InstantiateRenderPipelineLayout(pipelineLayoutInfo); Nz::VulkanRenderPipelineLayout* vkPipelineLayout = static_cast(renderPipelineLayout.get()); - 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, 1, poolSize, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) - { - NazaraError("Failed to create descriptor pool"); - return __LINE__; - } - - Nz::Vk::DescriptorSet descriptorSet = descriptorPool.AllocateDescriptorSet(descriptorLayout); + Nz::Vk::DescriptorSet descriptorSet = vkPipelineLayout->AllocateDescriptorSet(); std::unique_ptr uniformBuffer = device->InstantiateBuffer(Nz::BufferType_Uniform); if (!uniformBuffer->Initialize(uniformSize, Nz::BufferUsage_DeviceLocal)) @@ -168,6 +303,7 @@ int main() Nz::VulkanBuffer* uniformBufferImpl = static_cast(uniformBuffer.get()); descriptorSet.WriteUniformDescriptor(0, uniformBufferImpl->GetBufferHandle(), 0, uniformSize); + descriptorSet.WriteCombinedImageSamplerDescriptor(1, imageSampler, imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); Nz::RenderPipelineInfo pipelineInfo; pipelineInfo.pipelineLayout = renderPipelineLayout; @@ -185,19 +321,10 @@ int main() Nz::VulkanRenderPipeline::CreateInfo pipelineCreateInfo = Nz::VulkanRenderPipeline::BuildCreateInfo(pipelineInfo); pipelineCreateInfo.pipelineInfo.renderPass = vulkanWindow.GetRenderPass(); - Nz::Vk::CommandPool cmdPool; - if (!cmdPool.Create(vulkanDevice, 0, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)) - { - NazaraError("Failed to create rendering cmd pool"); - return __LINE__; - } - std::array clearValues; - clearValues[0].color = {1.0f, 0.8f, 0.4f, 0.0f}; + clearValues[0].color = {0.0f, 0.0f, 0.0f, 0.0f}; clearValues[1].depthStencil = {1.f, 0}; - Nz::Vk::QueueHandle graphicsQueue = vulkanDevice.GetQueue(0, 0); - Nz::UInt32 imageCount = vulkanWindow.GetFramebufferCount(); std::vector renderCmds = cmdPool.AllocateCommandBuffers(imageCount, VK_COMMAND_BUFFER_LEVEL_PRIMARY); @@ -251,7 +378,7 @@ int main() renderCmd.BeginRenderPass(render_pass_begin_info); 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.BindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipelineLayout->GetPipelineLayout(), 0, descriptorSet); 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); diff --git a/examples/bin/resources/shaders/triangle.frag b/examples/bin/resources/shaders/triangle.frag index 404919ccd..58a4eff89 100644 --- a/examples/bin/resources/shaders/triangle.frag +++ b/examples/bin/resources/shaders/triangle.frag @@ -3,11 +3,14 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable +layout(binding = 1) uniform sampler2D texSampler; + layout (location = 0) in vec3 inColor; +layout (location = 1) in vec2 outTexCoords; layout (location = 0) out vec4 outFragColor; void main() { - outFragColor = vec4(inColor, 1.0); -} \ No newline at end of file + outFragColor = texture(texSampler, outTexCoords); +} diff --git a/examples/bin/resources/shaders/triangle.frag.spv b/examples/bin/resources/shaders/triangle.frag.spv index 3804e0ca0..c163dc05a 100644 Binary files a/examples/bin/resources/shaders/triangle.frag.spv and b/examples/bin/resources/shaders/triangle.frag.spv differ diff --git a/examples/bin/resources/shaders/triangle.vert b/examples/bin/resources/shaders/triangle.vert index e91270122..8884074ee 100644 --- a/examples/bin/resources/shaders/triangle.vert +++ b/examples/bin/resources/shaders/triangle.vert @@ -5,6 +5,7 @@ layout (location = 0) in vec3 inPos; layout (location = 1) in vec3 inColor; +layout (location = 2) in vec2 inTexCoord; layout (binding = 0) uniform UBO { @@ -14,6 +15,7 @@ layout (binding = 0) uniform UBO } ubo; layout (location = 0) out vec3 outColor; +layout (location = 1) out vec2 outTexCoords; out gl_PerVertex { @@ -24,5 +26,6 @@ out gl_PerVertex void main() { outColor = inColor; + outTexCoords = inTexCoord; gl_Position = ubo.projectionMatrix * ubo.viewMatrix * ubo.modelMatrix * vec4(inPos, 1.0); } diff --git a/examples/bin/resources/shaders/triangle.vert.spv b/examples/bin/resources/shaders/triangle.vert.spv index 05a949806..d7f5cd1ff 100644 Binary files a/examples/bin/resources/shaders/triangle.vert.spv and b/examples/bin/resources/shaders/triangle.vert.spv differ diff --git a/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp b/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp index 98911226c..80c530b9e 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp @@ -10,9 +10,11 @@ #include #include #include +#include +#include +#include #include #include -#include #include namespace Nz @@ -23,13 +25,21 @@ namespace Nz VulkanRenderPipelineLayout() = default; ~VulkanRenderPipelineLayout() = default; + Vk::DescriptorSet AllocateDescriptorSet(); + bool Create(Vk::Device& device, RenderPipelineLayoutInfo layoutInfo); inline const Vk::DescriptorSetLayout& GetDescriptorSetLayout() const; inline const Vk::PipelineLayout& GetPipelineLayout() const; private: + struct DescriptorPool + { + Vk::DescriptorPool descriptorPool; + }; + MovablePtr m_device; + std::vector m_descriptorPools; Vk::DescriptorSetLayout m_descriptorSetLayout; Vk::PipelineLayout m_pipelineLayout; RenderPipelineLayoutInfo m_layoutInfo; diff --git a/include/Nazara/VulkanRenderer/Wrapper.hpp b/include/Nazara/VulkanRenderer/Wrapper.hpp index 8f360d652..1ae7ed140 100644 --- a/include/Nazara/VulkanRenderer/Wrapper.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp b/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp index ab5f54eae..52e457236 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp @@ -52,6 +52,7 @@ namespace Nz inline void ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, UInt32 rangeCount, const VkImageSubresourceRange* ranges); inline void CopyBuffer(VkBuffer source, VkBuffer target, UInt32 size, UInt32 sourceOffset = 0, UInt32 targetOffset = 0); + inline void CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, UInt32 width, UInt32 height); inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0); inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, Int32 vertexOffset = 0, UInt32 firstInstance = 0); diff --git a/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.inl b/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.inl index 574cb90a5..00f3c9f31 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.inl @@ -203,6 +203,29 @@ namespace Nz return m_pool->GetDevice()->vkCmdCopyBuffer(m_handle, source, target, 1, ®ion); } + inline void CommandBuffer::CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, UInt32 width, UInt32 height) + { + VkBufferImageCopy region = { + 0, + 0, + 0, + { // imageSubresource + VK_IMAGE_ASPECT_COLOR_BIT, //< aspectMask + 0, + 0, + 1 + }, + { // imageOffset + 0, 0, 0 + }, + { // imageExtent + width, height, 1U + } + }; + + return m_pool->GetDevice()->vkCmdCopyBufferToImage(m_handle, source, target, targetLayout, 1, ®ion); + } + inline void CommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance) { return m_pool->GetDevice()->vkCmdDraw(m_handle, vertexCount, instanceCount, firstVertex, firstInstance); diff --git a/include/Nazara/VulkanRenderer/Wrapper/DescriptorSet.hpp b/include/Nazara/VulkanRenderer/Wrapper/DescriptorSet.hpp index 42bc26721..24eb8c6ed 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/DescriptorSet.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/DescriptorSet.hpp @@ -30,6 +30,13 @@ namespace Nz inline bool IsValid() const; + inline void WriteCombinedImageSamplerDescriptor(UInt32 binding, VkSampler sampler, VkImageView imageView, VkImageLayout imageLayout); + inline void WriteCombinedImageSamplerDescriptor(UInt32 binding, const VkDescriptorImageInfo& imageInfo); + inline void WriteCombinedImageSamplerDescriptor(UInt32 binding, UInt32 arrayElement, VkSampler sampler, VkImageView imageView, VkImageLayout imageLayout); + inline void WriteCombinedImageSamplerDescriptor(UInt32 binding, UInt32 arrayElement, const VkDescriptorImageInfo& imageInfo); + inline void WriteCombinedImageSamplerDescriptors(UInt32 binding, UInt32 descriptorCount, const VkDescriptorImageInfo* imageInfo); + inline void WriteCombinedImageSamplerDescriptors(UInt32 binding, UInt32 arrayElement, UInt32 descriptorCount, const VkDescriptorImageInfo* imageInfo); + inline void WriteUniformDescriptor(UInt32 binding, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range); inline void WriteUniformDescriptor(UInt32 binding, const VkDescriptorBufferInfo& bufferInfo); inline void WriteUniformDescriptor(UInt32 binding, UInt32 arrayElement, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range); diff --git a/include/Nazara/VulkanRenderer/Wrapper/DescriptorSet.inl b/include/Nazara/VulkanRenderer/Wrapper/DescriptorSet.inl index 5e5943bd3..3932fdfcf 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/DescriptorSet.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/DescriptorSet.inl @@ -50,6 +50,55 @@ namespace Nz return m_handle != VK_NULL_HANDLE; } + inline void DescriptorSet::WriteCombinedImageSamplerDescriptor(UInt32 binding, VkSampler sampler, VkImageView imageView, VkImageLayout imageLayout) + { + return WriteCombinedImageSamplerDescriptor(binding, 0, sampler, imageView, imageLayout); + } + + inline void DescriptorSet::WriteCombinedImageSamplerDescriptor(UInt32 binding, const VkDescriptorImageInfo& imageInfo) + { + return WriteCombinedImageSamplerDescriptor(binding, 0, imageInfo); + } + + inline void DescriptorSet::WriteCombinedImageSamplerDescriptor(UInt32 binding, UInt32 arrayElement, VkSampler sampler, VkImageView imageView, VkImageLayout imageLayout) + { + VkDescriptorImageInfo imageInfo = { + sampler, + imageView, + imageLayout + }; + + return WriteCombinedImageSamplerDescriptors(binding, arrayElement, 1U, &imageInfo); + } + + inline void DescriptorSet::WriteCombinedImageSamplerDescriptor(UInt32 binding, UInt32 arrayElement, const VkDescriptorImageInfo& imageInfo) + { + return WriteCombinedImageSamplerDescriptors(binding, arrayElement, 1U, &imageInfo); + } + + inline void DescriptorSet::WriteCombinedImageSamplerDescriptors(UInt32 binding, UInt32 descriptorCount, const VkDescriptorImageInfo* imageInfo) + { + return WriteCombinedImageSamplerDescriptors(binding, 0U, descriptorCount, imageInfo); + } + + inline void DescriptorSet::WriteCombinedImageSamplerDescriptors(UInt32 binding, UInt32 arrayElement, UInt32 descriptorCount, const VkDescriptorImageInfo* imageInfo) + { + VkWriteDescriptorSet writeDescriptorSet = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + nullptr, + m_handle, + binding, + arrayElement, + descriptorCount, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + imageInfo, + nullptr, + nullptr + }; + + return m_pool->GetDevice()->vkUpdateDescriptorSets(*m_pool->GetDevice(), 1U, &writeDescriptorSet, 0U, nullptr); + } + inline void DescriptorSet::WriteUniformDescriptor(UInt32 binding, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range) { return WriteUniformDescriptor(binding, 0U, buffer, offset, range); diff --git a/include/Nazara/VulkanRenderer/Wrapper/Sampler.hpp b/include/Nazara/VulkanRenderer/Wrapper/Sampler.hpp new file mode 100644 index 000000000..8cbde84d1 --- /dev/null +++ b/include/Nazara/VulkanRenderer/Wrapper/Sampler.hpp @@ -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 + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKSAMPLER_HPP +#define NAZARA_VULKANRENDERER_VKSAMPLER_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class Sampler : public DeviceObject + { + friend DeviceObject; + + public: + Sampler() = default; + Sampler(const Sampler&) = delete; + Sampler(Sampler&&) = default; + ~Sampler() = default; + + Sampler& operator=(const Sampler&) = delete; + Sampler& operator=(Sampler&&) = delete; + + private: + static inline VkResult CreateHelper(Device& device, const VkSamplerCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkSampler* handle); + static inline void DestroyHelper(Device& device, VkSampler handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKSAMPLER_HPP diff --git a/include/Nazara/VulkanRenderer/Wrapper/Sampler.inl b/include/Nazara/VulkanRenderer/Wrapper/Sampler.inl new file mode 100644 index 000000000..7835bdce0 --- /dev/null +++ b/include/Nazara/VulkanRenderer/Wrapper/Sampler.inl @@ -0,0 +1,24 @@ +// 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 +{ + namespace Vk + { + inline VkResult Sampler::CreateHelper(Device& device, const VkSamplerCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkSampler* handle) + { + return device.vkCreateSampler(device, createInfo, allocator, handle); + } + + inline void Sampler::DestroyHelper(Device& device, VkSampler handle, const VkAllocationCallbacks* allocator) + { + return device.vkDestroySampler(device, handle, allocator); + } + } +} + +#include diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp index b8d4704de..8eaf5d268 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPipelineLayout.cpp @@ -12,6 +12,35 @@ namespace Nz { + Vk::DescriptorSet VulkanRenderPipelineLayout::AllocateDescriptorSet() + { + // TODO: Watch descriptor set count for each pool + for (auto& pool : m_descriptorPools) + { + Vk::DescriptorSet descriptorSet = pool.descriptorPool.AllocateDescriptorSet(m_descriptorSetLayout); + if (descriptorSet) + return descriptorSet; + } + + // Allocate a new descriptor pool + StackVector poolSizes = NazaraStackVector(VkDescriptorPoolSize, m_layoutInfo.bindings.size()); + + constexpr UInt32 MaxSet = 100; + + for (const auto& bindingInfo : m_layoutInfo.bindings) + { + VkDescriptorPoolSize& poolSize = poolSizes.emplace_back(); + poolSize.descriptorCount = MaxSet; + poolSize.type = ToVulkan(bindingInfo.type); + } + + DescriptorPool pool; + if (!pool.descriptorPool.Create(*m_device, MaxSet, UInt32(poolSizes.size()), poolSizes.data(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) + return {}; + + return m_descriptorPools.emplace_back(std::move(pool)).descriptorPool.AllocateDescriptorSet(m_descriptorSetLayout); + } + bool VulkanRenderPipelineLayout::Create(Vk::Device& device, RenderPipelineLayoutInfo layoutInfo) { m_device = &device;