From 87fc0c3f108c538e7ee55c16e988b2917e1a6ac9 Mon Sep 17 00:00:00 2001 From: Shu Date: Tue, 29 Sep 2020 21:28:11 +0200 Subject: [PATCH] Vulkan uniform buffer object --- resource/content/shaders/Tris.vs.spv | 4 +- resource/content/shaders/Voxel.fs.geo.ins.spv | 4 +- resource/content/shaders/Voxel.fs.geo.spv | 4 +- resource/content/shaders/Voxel.fs.ins.spv | 4 +- resource/content/shaders/Voxel.fs.spv | 4 +- resource/content/shaders/Voxel.vs.geo.ins.spv | 4 +- resource/content/shaders/Voxel.vs.geo.spv | 4 +- resource/content/shaders/Voxel.vs.ins.spv | 4 +- resource/content/shaders/Voxel.vs.spv | 4 +- resource/shaders-src/Tris.vert | 8 +- resource/shaders-src/Voxel.frag | 14 +- resource/shaders-src/Voxel.vert | 19 +-- src/client/render/vk/Allocator.cpp | 71 +++------ src/client/render/vk/Allocator.hpp | 7 +- src/client/render/vk/CommandCenter.cpp | 147 ++++++++++++++++-- src/client/render/vk/CommandCenter.hpp | 18 ++- src/client/render/vk/Pipeline.cpp | 18 ++- src/client/render/vk/Pipeline.hpp | 6 +- src/client/render/vk/Renderer.cpp | 6 +- src/client/render/vk/buffer/VertexData.hpp | 17 ++ src/client/render/vk/forward.hpp | 2 - 21 files changed, 257 insertions(+), 112 deletions(-) diff --git a/resource/content/shaders/Tris.vs.spv b/resource/content/shaders/Tris.vs.spv index 7581a72..4421d80 100644 --- a/resource/content/shaders/Tris.vs.spv +++ b/resource/content/shaders/Tris.vs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b55f16f755a1ea2809ba5d3cb5401c07a2680cde6f412709a85f63e4b063c955 -size 1116 +oid sha256:38fcf9482521a5e4f20cc3c02fbf69c4e238512578e0e39c79cffe290218d9c7 +size 1712 diff --git a/resource/content/shaders/Voxel.fs.geo.ins.spv b/resource/content/shaders/Voxel.fs.geo.ins.spv index 66e4764..ae73ac2 100644 --- a/resource/content/shaders/Voxel.fs.geo.ins.spv +++ b/resource/content/shaders/Voxel.fs.geo.ins.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:790843dd8159e2f3fbf32c19ed467b8f9c73daa087ba2544509e570a51775129 -size 20704 +oid sha256:ae0afc141f00d35ba125fe9b3b8c3a485b95d40c7bf86cdcad5c5e5347b9061e +size 20828 diff --git a/resource/content/shaders/Voxel.fs.geo.spv b/resource/content/shaders/Voxel.fs.geo.spv index d697bad..47084c6 100644 --- a/resource/content/shaders/Voxel.fs.geo.spv +++ b/resource/content/shaders/Voxel.fs.geo.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a778d3b8d14791bfe7a5afe587894012c8079298402ae107f2fd45e157260ea -size 20784 +oid sha256:6a10d61fe025d3d53f5e4cc22e90ec69ec3b64838f268928ca2675d3c0d26297 +size 20908 diff --git a/resource/content/shaders/Voxel.fs.ins.spv b/resource/content/shaders/Voxel.fs.ins.spv index a7895a0..9ac2d8c 100644 --- a/resource/content/shaders/Voxel.fs.ins.spv +++ b/resource/content/shaders/Voxel.fs.ins.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d81ea2408908d3e86a5642b1deb24ed2aad26e8d04beac54d0a027fe20a71daa -size 17592 +oid sha256:25f64f888a26bae6db16da3e75630e29c07ec221a2fc664b3a9383d57092ee1c +size 17716 diff --git a/resource/content/shaders/Voxel.fs.spv b/resource/content/shaders/Voxel.fs.spv index 1725abe..d460d0f 100644 --- a/resource/content/shaders/Voxel.fs.spv +++ b/resource/content/shaders/Voxel.fs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ec30779731aa36d3583d05d4eaa543b98a4c63d1cf07a58b7e121cf3d3675fc -size 17672 +oid sha256:1ec14629c4675c4d78187733cfe04dff41706f92a45e27d1373cd0d2f9ee179a +size 17796 diff --git a/resource/content/shaders/Voxel.vs.geo.ins.spv b/resource/content/shaders/Voxel.vs.geo.ins.spv index 750637d..4da465b 100644 --- a/resource/content/shaders/Voxel.vs.geo.ins.spv +++ b/resource/content/shaders/Voxel.vs.geo.ins.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c84dbcc50fcfb569e6c5f5cef508b350e0e64bacd1e6076c15a4e8635cfe6a5a -size 5576 +oid sha256:36b8484857b9123797ef404267cf1da90bf8ce8b6a8e3bbae30db2f385f268e7 +size 5716 diff --git a/resource/content/shaders/Voxel.vs.geo.spv b/resource/content/shaders/Voxel.vs.geo.spv index f8cb822..da385fd 100644 --- a/resource/content/shaders/Voxel.vs.geo.spv +++ b/resource/content/shaders/Voxel.vs.geo.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78cd40dc708c52bfa43f216b21f7e7fddcfe174c3403ca123a1af0cdad058d21 -size 5700 +oid sha256:430d5380075d8ab8dd3cb78bbc74794b35b6f179c82ab286e63e5f792dac4f4d +size 5824 diff --git a/resource/content/shaders/Voxel.vs.ins.spv b/resource/content/shaders/Voxel.vs.ins.spv index 750637d..4da465b 100644 --- a/resource/content/shaders/Voxel.vs.ins.spv +++ b/resource/content/shaders/Voxel.vs.ins.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c84dbcc50fcfb569e6c5f5cef508b350e0e64bacd1e6076c15a4e8635cfe6a5a -size 5576 +oid sha256:36b8484857b9123797ef404267cf1da90bf8ce8b6a8e3bbae30db2f385f268e7 +size 5716 diff --git a/resource/content/shaders/Voxel.vs.spv b/resource/content/shaders/Voxel.vs.spv index f8cb822..da385fd 100644 --- a/resource/content/shaders/Voxel.vs.spv +++ b/resource/content/shaders/Voxel.vs.spv @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78cd40dc708c52bfa43f216b21f7e7fddcfe174c3403ca123a1af0cdad058d21 -size 5700 +oid sha256:430d5380075d8ab8dd3cb78bbc74794b35b6f179c82ab286e63e5f792dac4f4d +size 5824 diff --git a/resource/shaders-src/Tris.vert b/resource/shaders-src/Tris.vert index 92a086e..f758886 100644 --- a/resource/shaders-src/Tris.vert +++ b/resource/shaders-src/Tris.vert @@ -1,12 +1,18 @@ #version 450 #extension GL_ARB_separate_shader_objects : enable +layout(binding = 0) uniform UniformBufferObject { + mat4 model; + mat4 view; + mat4 proj; +} ubo; + layout(location = 0) in vec2 inPosition; layout(location = 1) in vec3 inColor; layout(location = 0) out vec3 fragColor; void main() { - gl_Position = vec4(inPosition, 0.0, 1.0); + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); fragColor = inColor; } \ No newline at end of file diff --git a/resource/shaders-src/Voxel.frag b/resource/shaders-src/Voxel.frag index 7d97fb7..33c8ef9 100644 --- a/resource/shaders-src/Voxel.frag +++ b/resource/shaders-src/Voxel.frag @@ -9,6 +9,12 @@ layout (constant_id = 4) const bool BLEND = true; // ... layout (constant_id = 16) const int UNIT_SIZE = 8; +layout (binding = 0) uniform UniformBufferObject { + vec3 FogColor; + float FogDepth; + + vec3 LightInvDirection_worldspace; +} UBO; layout (binding = 1) uniform sampler2DArray TextureAtlas; layout (binding = 2) uniform sampler2DArray NormalAtlas; layout (binding = 3) uniform sampler2DArray HOSAtlas; @@ -22,12 +28,6 @@ layout(push_constant) uniform PushConstants { vec4 SphereProj; float Curvature; - - //MAYBE: extract - vec3 FogColor; - float FogDepth; - - vec3 LightInvDirection_worldspace; } Push; #ifdef GEOMETRY @@ -234,7 +234,7 @@ if(PBR) { } if(FOG) { float ratio = exp(vs.Depth * 0.69)-1; - color = mix(color, pow(Push.FogColor, vec3(2.2)), clamp(ratio, 0, 1)); + color = mix(color, pow(UBO.FogColor, vec3(2.2)), clamp(ratio, 0, 1)); } color = pow(color, vec3(1.0 / 2.2)); if(color.r > 1 || color.g > 1 || color.b > 1) { diff --git a/resource/shaders-src/Voxel.vert b/resource/shaders-src/Voxel.vert index dd4627c..2a6fadb 100644 --- a/resource/shaders-src/Voxel.vert +++ b/resource/shaders-src/Voxel.vert @@ -7,8 +7,15 @@ layout (constant_id = 1) const bool PBR = true; layout (constant_id = 5) const bool DO_CURVATURE = false; layout (constant_id = 6) const bool CURV_DEPTH = true; +layout (binding = 0) uniform UniformBufferObject { + vec3 FogColor; + float FogDepth; + + vec3 LightInvDirection_worldspace; +} UBO; + layout(push_constant) uniform PushConstants { - mat4 Proj; + mat4 Proj; //MAYBE: move Proj View to UBO mat4 View; #ifndef INSTANCED mat4 Model; @@ -16,12 +23,6 @@ layout(push_constant) uniform PushConstants { vec4 SphereProj; float Curvature; - - //MAYBE: extract - vec3 FogColor; - float FogDepth; - - vec3 LightInvDirection_worldspace; } Push; layout (location = 0) in vec3 Position_modelspace; @@ -66,7 +67,7 @@ if(DO_CURVATURE) { gl_Position = Push.Proj * Position_cameraspace; if(FOG) { - vs.Depth = length(Position_cameraspace.xyz) / Push.FogDepth; + vs.Depth = length(Position_cameraspace.xyz) / UBO.FogDepth; } vs.Texture = Texture_model; @@ -81,6 +82,6 @@ if(PBR) { vs.EyeDirection_cameraspace = vec3(0,0,0) - Position_cameraspace.xyz; // Vector that goes from the vertex to the light, in camera space - vs.LightDirection_cameraspace = (Push.View * vec4(Push.LightInvDirection_worldspace,0)).xyz; + vs.LightDirection_cameraspace = (Push.View * vec4(UBO.LightInvDirection_worldspace,0)).xyz; } } diff --git a/src/client/render/vk/Allocator.cpp b/src/client/render/vk/Allocator.cpp index c95c981..7dd1ed9 100644 --- a/src/client/render/vk/Allocator.cpp +++ b/src/client/render/vk/Allocator.cpp @@ -2,15 +2,15 @@ #include "PhysicalDeviceInfo.hpp" #include -#include "buffer/VertexData.hpp" #include +#include using namespace render::vk; const auto NO_DELETER = Allocator::MemoryDeleter(nullptr); -Allocator::memory_ptr get_null_ptr() { return Allocator::memory_ptr(nullptr, NO_DELETER); } +Allocator::memory_ptr Allocator::GetNull() { return Allocator::memory_ptr(nullptr, NO_DELETER); } -Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info) : device(device), indexedBufferMemory(get_null_ptr()) { +Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info) : device(device) { vkGetPhysicalDeviceMemoryProperties(info.device, &properties); { @@ -39,39 +39,8 @@ Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info) : device(d vkAllocateCommandBuffers(device, &allocInfo, &transferBuffer); tracyCtx = TracyVkContext(info.device, device, transferQueue, transferBuffer); } - { - size_t vertexSize = sizeof(buffer::vk::vertices[0]) * buffer::vk::vertices.size(); - size_t indexSize = sizeof(buffer::vk::indices[0]) * buffer::vk::indices.size(); - size_t stagingSize = std::max(vertexSize, indexSize); - buffer_info stagingBuffer; - if(auto stagingMemory = createBuffer(stagingSize, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, stagingBuffer)) { - std::vector requirements = { - {indexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT}, - {vertexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT} - }; - if(std::vector out; indexedBufferMemory = createBuffers(requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, out)) { - indexBuffer = out[0]; - vertexBuffer = out[1]; - } else { - FATAL("Cannot allocate buffer memory"); - } - - stagingMemory->write(buffer::vk::vertices.data(), vertexSize); - copyBuffer(stagingBuffer, vertexBuffer, vertexSize); - stagingMemory->write(buffer::vk::indices.data(), indexSize); - copyBuffer(stagingBuffer, indexBuffer, indexSize); - - vkDestroyBuffer(device, stagingBuffer.buffer, ALLOC); //TODO: move to buffer - } else { - FATAL("Cannot allocate staging memory"); - } - } } Allocator::~Allocator() { - vkDestroyBuffer(device, indexBuffer.buffer, ALLOC); - vkDestroyBuffer(device, vertexBuffer.buffer, ALLOC); - indexedBufferMemory.reset(); - TracyVkDestroy(tracyCtx); vkFreeCommandBuffers(device, transferPool, 1, &transferBuffer); @@ -94,8 +63,9 @@ Allocator::memory_ptr Allocator::createBuffer(VkDeviceSize size, VkMemoryPropert if (vkCreateBuffer(device, &bufferInfo, ALLOC, &out.buffer) != VK_SUCCESS) { LOG_E("Failed to create buffer"); - return get_null_ptr(); + return GetNull(); } + out.offset = 0; VkMemoryRequirements memRequirements; vkGetBufferMemoryRequirements(device, out.buffer, &memRequirements); @@ -105,16 +75,16 @@ Allocator::memory_ptr Allocator::createBuffer(VkDeviceSize size, VkMemoryPropert return memory; } LOG_E("Failed to allocate buffer memory"); - return get_null_ptr(); + return GetNull(); } Allocator::memory_ptr Allocator::createBuffers(const std::vector& requirements, VkMemoryPropertyFlags properties, std::vector& out) { assert(!requirements.empty()); - out.resize(requirements.size()); + out.resize(requirements.size()+1); // Create buffers VkMemoryRequirements memRequirements = {0, 0, UINT32_MAX}; - std::vector> ranges; - ranges.resize(requirements.size()); + std::vector sizes; + sizes.resize(requirements.size()); for (size_t i = 0; i < requirements.size(); i++) { VkBufferCreateInfo bufferInfo{}; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; @@ -124,14 +94,14 @@ Allocator::memory_ptr Allocator::createBuffers(const std::vectorref, memory->offset + ranges[i].second) != VK_SUCCESS) { + if (vkBindBufferMemory(device, out[i].buffer, memory->ref, memory->offset + out[i].offset) != VK_SUCCESS) { LOG_E("Failed to bind buffer"); - return get_null_ptr(); + return GetNull(); } } return memory; } LOG_E("Failed to allocate buffers"); - return get_null_ptr(); + return GetNull(); } Allocator::memory_ptr Allocator::allocate(VkMemoryRequirements requirements, VkMemoryPropertyFlags properties) { @@ -172,13 +143,13 @@ Allocator::memory_ptr Allocator::allocate(VkMemoryRequirements requirements, VkM allocInfo.memoryTypeIndex = memIdx.value(); } else { LOG_E("No suitable memory heap"); - return get_null_ptr(); + return GetNull(); } VkDeviceMemory memory; if (vkAllocateMemory(device, &allocInfo, ALLOC, &memory) != VK_SUCCESS) { LOG_E("Failed to allocate memory!"); - return get_null_ptr(); + return GetNull(); } void *ptr = nullptr; diff --git a/src/client/render/vk/Allocator.hpp b/src/client/render/vk/Allocator.hpp index 2c746a4..f30762a 100644 --- a/src/client/render/vk/Allocator.hpp +++ b/src/client/render/vk/Allocator.hpp @@ -43,6 +43,7 @@ public: struct buffer_info { VkBuffer buffer = nullptr; + VkDeviceSize offset = 0; }; memory_ptr createBuffer(VkDeviceSize, VkMemoryPropertyFlags, VkBufferUsageFlags, buffer_info&); struct buffer_requirement { @@ -55,9 +56,10 @@ public: void copyBuffer(buffer_info srcBuffer, buffer_info dstBuffer, VkDeviceSize size); - std::pair getBuffer() { return {vertexBuffer.buffer, indexBuffer.buffer}; } void setTracyZone(const char* name); + static memory_ptr GetNull(); + private: std::optional findMemory(uint32_t, VkMemoryPropertyFlags, VkDeviceSize size = 0) const; @@ -84,9 +86,6 @@ private: VkCommandBuffer transferBuffer; // MAYBE: parallel upload TracyVkCtx tracyCtx; - buffer_info vertexBuffer; - buffer_info indexBuffer; - memory_ptr indexedBufferMemory; std::vector> allocations; }; } \ No newline at end of file diff --git a/src/client/render/vk/CommandCenter.cpp b/src/client/render/vk/CommandCenter.cpp index 974e44b..793efd9 100644 --- a/src/client/render/vk/CommandCenter.cpp +++ b/src/client/render/vk/CommandCenter.cpp @@ -1,14 +1,16 @@ #include "CommandCenter.hpp" #include "PhysicalDeviceInfo.hpp" +#include "Pipeline.hpp" #include "../Renderer.hpp" #include "buffer/VertexData.hpp" using namespace render::vk; -CommandCenter::CommandCenter(VkDevice device, const std::vector &views, PipelineRef pipe, - std::pair buffer, const PhysicalDeviceInfo &info, const renderOptions &opt) : device(device) { - { +CommandCenter::CommandCenter(VkDevice device, Allocator& alloc, const std::vector &views, + const Pipeline& pipe, const PhysicalDeviceInfo &info, const renderOptions &opt): +device(device), indexedBufferMemory(Allocator::GetNull()), uniformBuffersMemory(Allocator::GetNull()) { + { // Graphics command pool vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue); VkCommandPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; @@ -19,16 +21,47 @@ CommandCenter::CommandCenter(VkDevice device, const std::vector &vi FATAL("Failed to create graphics pool!"); } } + { // Vertex buffers (const) + size_t vertexSize = sizeof(buffer::vk::vertices[0]) * buffer::vk::vertices.size(); + size_t indexSize = sizeof(buffer::vk::indices[0]) * buffer::vk::indices.size(); + size_t stagingSize = std::max(vertexSize, indexSize); + Allocator::buffer_info stagingBuffer; + if(auto stagingMemory = alloc.createBuffer(stagingSize, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, stagingBuffer)) { + if(std::vector out; indexedBufferMemory = alloc.createBuffers({ + {indexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT}, + {vertexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT} + }, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, out)) { + indexBuffer = out[0]; + vertexBuffer = out[1]; + } else { + FATAL("Cannot allocate buffer memory"); + } - allocate(views, pipe, buffer, info.swapDetails.capabilities.currentExtent, opt); + stagingMemory->write(buffer::vk::vertices.data(), vertexSize); + alloc.copyBuffer(stagingBuffer, vertexBuffer, vertexSize); + stagingMemory->write(buffer::vk::indices.data(), indexSize); + alloc.copyBuffer(stagingBuffer, indexBuffer, indexSize); + + vkDestroyBuffer(device, stagingBuffer.buffer, ALLOC); //TODO: move to buffer + } else { + FATAL("Cannot allocate staging memory"); + } + } + + allocate(alloc, views, pipe, info.swapDetails.capabilities.currentExtent, opt); } CommandCenter::~CommandCenter() { if(!freed) free(); + vkDestroyBuffer(device, indexBuffer.buffer, ALLOC); + vkDestroyBuffer(device, vertexBuffer.buffer, ALLOC); + indexedBufferMemory.reset(); + vkDestroyCommandPool(device, graphicsPool, ALLOC); } -void CommandCenter::allocate(const std::vector& views, PipelineRef pipe, std::pair buffer, VkExtent2D extent, +#include +void CommandCenter::allocate(Allocator& alloc, const std::vector& views, const Pipeline& pipe, VkExtent2D extent, const renderOptions& opt) { assert(freed); @@ -40,7 +73,7 @@ void CommandCenter::allocate(const std::vector& views, PipelineRef VkFramebufferCreateInfo framebufferInfo{}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = pipe.first; + framebufferInfo.renderPass = pipe.getRenderPass(); framebufferInfo.attachmentCount = 1; framebufferInfo.pAttachments = attachments; framebufferInfo.width = extent.width; @@ -52,6 +85,68 @@ void CommandCenter::allocate(const std::vector& views, PipelineRef } } + { // Uniform buffers + VkDeviceSize bufferSize = sizeof(buffer::vk::UniformBufferObject); + + std::vector requirements; + requirements.resize(framebuffers.size(), Allocator::buffer_requirement{bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT}); + uniformBuffersMemory = alloc.createBuffers(requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers); + if (!uniformBuffersMemory) { + FATAL("Failed to allocate UBO"); + } + } + { // Descriptor pool + VkDescriptorPoolSize poolSize{}; + poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + poolSize.descriptorCount = framebuffers.size(); + + VkDescriptorPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.poolSizeCount = 1; + poolInfo.pPoolSizes = &poolSize; + poolInfo.maxSets = framebuffers.size(); + poolInfo.flags = 0; //VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT + + if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) { + FATAL("Failed to create descriptor pool!"); + } + } + { // Descriptor sets + std::vector layouts(framebuffers.size(), pipe.getDescriptorSet()); + VkDescriptorSetAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = descriptorPool; + allocInfo.descriptorSetCount = framebuffers.size(); + allocInfo.pSetLayouts = layouts.data(); + + descriptorSets.resize(framebuffers.size()); + if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) { + FATAL("Failed to allocate descriptor sets!"); + } + + for (size_t i = 0; i < descriptorSets.size(); i++) { + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.buffer = uniformBuffers[i].buffer; + bufferInfo.offset = 0; + bufferInfo.range = sizeof(buffer::vk::UniformBufferObject); + + VkWriteDescriptorSet descriptorWrite{}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSets[i]; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptorWrite.descriptorCount = 1; + + descriptorWrite.pBufferInfo = &bufferInfo; + descriptorWrite.pImageInfo = nullptr; + descriptorWrite.pTexelBufferView = nullptr; + + vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); + } + } + { graphicsBuffers.resize(framebuffers.size()); VkCommandBufferAllocateInfo allocInfo{}; @@ -77,7 +172,7 @@ void CommandCenter::allocate(const std::vector& views, PipelineRef VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = pipe.first; + renderPassInfo.renderPass = pipe.getRenderPass(); renderPassInfo.framebuffer = framebuffers[i]; renderPassInfo.renderArea.offset = {0, 0}; renderPassInfo.renderArea.extent = extent; @@ -87,11 +182,12 @@ void CommandCenter::allocate(const std::vector& views, PipelineRef renderPassInfo.pClearValues = &clearColor; vkCmdBeginRenderPass(graphicsBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second); - VkBuffer vertexBuffers[] = {buffer.first}; + vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.getPipeline()); + VkBuffer vertexBuffers[] = {vertexBuffer.buffer}; VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(graphicsBuffers[i], 0, 1, vertexBuffers, offsets); - vkCmdBindIndexBuffer(graphicsBuffers[i], buffer.second, 0, VK_INDEX_TYPE_UINT16); + vkCmdBindIndexBuffer(graphicsBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT16); + vkCmdBindDescriptorSets(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.getLayout(), 0, 1, &descriptorSets[i], 0, nullptr); vkCmdDrawIndexed(graphicsBuffers[i], static_cast(buffer::vk::indices.size()), 1, 0, 0, 0); vkCmdEndRenderPass(graphicsBuffers[i]); @@ -100,19 +196,46 @@ void CommandCenter::allocate(const std::vector& views, PipelineRef } } + proj = glm::perspective(glm::radians(45.0f), extent.width / (float) extent.height, 0.1f, 10.0f); + proj[1][1] *= -1; + freed = false; } void CommandCenter::free() { assert(!freed); + vkFreeCommandBuffers(device, graphicsPool, static_cast(graphicsBuffers.size()), graphicsBuffers.data()); + + vkDestroyDescriptorPool(device, descriptorPool, nullptr); + + for (size_t i = 0; i < uniformBuffers.size(); i++) { + vkDestroyBuffer(device, uniformBuffers[i].buffer, ALLOC); + } + uniformBuffersMemory.reset(); + + for (size_t i = 0; i < framebuffers.size(); i++) { vkDestroyFramebuffer(device, framebuffers[i], nullptr); } - vkFreeCommandBuffers(device, graphicsPool, static_cast(graphicsBuffers.size()), graphicsBuffers.data()); - freed = true; } +#include +#include + +void CommandCenter::updateUBO(uint32_t idx) { + static auto startTime = std::chrono::high_resolution_clock::now(); + + auto currentTime = std::chrono::high_resolution_clock::now(); + float time = std::chrono::duration(currentTime - startTime).count(); + buffer::vk::UniformBufferObject ubo{}; + ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); + ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); + ubo.proj = proj; + + memcpy(uniformBuffersMemory->ptr + uniformBuffers[idx].offset, &ubo, sizeof(ubo)); +} + void CommandCenter::submitGraphics(uint32_t idx, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) { assert(!freed); diff --git a/src/client/render/vk/CommandCenter.hpp b/src/client/render/vk/CommandCenter.hpp index 63975b0..207a07c 100644 --- a/src/client/render/vk/CommandCenter.hpp +++ b/src/client/render/vk/CommandCenter.hpp @@ -2,6 +2,8 @@ #include "forward.hpp" #include +#include "Allocator.hpp" +#include namespace render::vk { class SwapChain; @@ -9,12 +11,13 @@ class Pipeline; class CommandCenter { public: - CommandCenter(VkDevice, const std::vector&, PipelineRef, std::pair, const PhysicalDeviceInfo&, const renderOptions&); + CommandCenter(VkDevice, Allocator&, const std::vector&, const Pipeline&, const PhysicalDeviceInfo&, const renderOptions&); ~CommandCenter(); + void updateUBO(uint32_t idx); void submitGraphics(uint32_t, VkSemaphore, VkSemaphore, VkFence); - void allocate(const std::vector &, PipelineRef, std::pair, VkExtent2D, const renderOptions&); + void allocate(Allocator&, const std::vector &, const Pipeline&, VkExtent2D, const renderOptions&); void free(); private: @@ -26,6 +29,17 @@ private: VkCommandPool graphicsPool; std::vector graphicsBuffers; + VkDescriptorPool descriptorPool; + std::vector descriptorSets; + + Allocator::buffer_info vertexBuffer; + Allocator::buffer_info indexBuffer; + Allocator::memory_ptr indexedBufferMemory; + + glm::mat4 proj; + std::vector uniformBuffers; + Allocator::memory_ptr uniformBuffersMemory; + bool freed = true; }; } \ No newline at end of file diff --git a/src/client/render/vk/Pipeline.cpp b/src/client/render/vk/Pipeline.cpp index 12fb450..b88b547 100644 --- a/src/client/render/vk/Pipeline.cpp +++ b/src/client/render/vk/Pipeline.cpp @@ -57,11 +57,22 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render FATAL("Failed to create render pass!"); } } + { + VkDescriptorSetLayoutCreateInfo layoutInfo{}; + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layoutInfo.bindingCount = 1; + std::vector bindings = {buffer::vk::UniformBufferObject::getLayoutBinding()}; + layoutInfo.pBindings = bindings.data(); + + if (vkCreateDescriptorSetLayout(device, &layoutInfo, ALLOC, &descriptorSetLayout) != VK_SUCCESS) { + FATAL("Failed to create descriptor set layout!"); + } + } { VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.setLayoutCount = 0; // TODO: setup layouts - pipelineLayoutInfo.pSetLayouts = nullptr; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout; pipelineLayoutInfo.pushConstantRangeCount = 0; pipelineLayoutInfo.pPushConstantRanges = nullptr; @@ -151,7 +162,7 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render rasterizer.polygonMode = options.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL; rasterizer.lineWidth = 1.0f; rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizer.depthBiasEnable = VK_FALSE; rasterizer.depthBiasConstantFactor = 0.0f; rasterizer.depthBiasClamp = 0.0f; @@ -235,6 +246,7 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render Pipeline::~Pipeline() { vkDestroyPipeline(device, graphicsPipeline, ALLOC); vkDestroyPipelineLayout(device, pipelineLayout, ALLOC); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, ALLOC); vkDestroyRenderPass(device, renderPass, ALLOC); vkDestroyShaderModule(device, fsShader, ALLOC); diff --git a/src/client/render/vk/Pipeline.hpp b/src/client/render/vk/Pipeline.hpp index 602bf18..ba52c22 100644 --- a/src/client/render/vk/Pipeline.hpp +++ b/src/client/render/vk/Pipeline.hpp @@ -9,7 +9,10 @@ public: Pipeline(VkDevice, const PhysicalDeviceInfo&, const renderOptions&); ~Pipeline(); - PipelineRef getRef() { return std::make_pair(renderPass, graphicsPipeline); } + constexpr VkRenderPass getRenderPass() const { return renderPass; } + constexpr VkPipeline getPipeline() const { return graphicsPipeline; } + constexpr VkPipelineLayout getLayout() const { return pipelineLayout; } + constexpr VkDescriptorSetLayout getDescriptorSet() const { return descriptorSetLayout; } private: VkDevice device; @@ -18,6 +21,7 @@ private: VkShaderModule fsShader; VkRenderPass renderPass; + VkDescriptorSetLayout descriptorSetLayout; VkPipelineLayout pipelineLayout; VkPipeline graphicsPipeline; }; diff --git a/src/client/render/vk/Renderer.cpp b/src/client/render/vk/Renderer.cpp index 03d33d4..31404c5 100644 --- a/src/client/render/vk/Renderer.cpp +++ b/src/client/render/vk/Renderer.cpp @@ -27,7 +27,7 @@ Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInf allocator = std::make_unique(device, *physicalInfo.get()); swapChain = std::make_unique(device, *physicalInfo.get()); pipeline = std::make_unique(device, *physicalInfo.get(), options); - commandCenter = std::make_unique(device, swapChain->getImageViews(), pipeline->getRef(), allocator->getBuffer(), *physicalInfo.get(), options); + commandCenter = std::make_unique(device, *allocator.get(), swapChain->getImageViews(), *pipeline.get(), *physicalInfo.get(), options); { imageAvailableSemaphores.resize(opt.inFlightFrames); @@ -78,7 +78,7 @@ void Renderer::recreateSwapChain() { set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window); swapChain = std::make_unique(device, *physicalInfo.get()); pipeline = std::make_unique(device, *physicalInfo.get(), options); - commandCenter->allocate(swapChain->getImageViews(), pipeline->getRef(), allocator->getBuffer(), physicalInfo->swapDetails.capabilities.currentExtent, options); + commandCenter->allocate(*allocator.get(), swapChain->getImageViews(), *pipeline.get(), physicalInfo->swapDetails.capabilities.currentExtent, options); } void Renderer::destroySwapChain() { commandCenter->free(); @@ -342,9 +342,9 @@ void Renderer::beginFrame() { std::function Renderer::beginWorldPass() { assert(currentImage < swapChain->getImageViews().size()); + commandCenter->updateUBO(currentImage); commandCenter->submitGraphics(currentImage, imageAvailableSemaphores[currentFrame], renderFinishedSemaphores[currentFrame], inFlightFences[currentFrame]); - /*WorldPass->useIt(); WorldPass->start(this);*/ return [&](glm::mat4) { diff --git a/src/client/render/vk/buffer/VertexData.hpp b/src/client/render/vk/buffer/VertexData.hpp index fcabea6..c34d4c6 100644 --- a/src/client/render/vk/buffer/VertexData.hpp +++ b/src/client/render/vk/buffer/VertexData.hpp @@ -42,4 +42,21 @@ const std::vector indices = { 0, 1, 2, 2, 3, 0 }; + +struct UniformBufferObject { + alignas(16) glm::mat4 model; + alignas(16) glm::mat4 view; + alignas(16) glm::mat4 proj; + + static VkDescriptorSetLayoutBinding getLayoutBinding() { + VkDescriptorSetLayoutBinding uboLayoutBinding{}; + uboLayoutBinding.binding = 0; + uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uboLayoutBinding.descriptorCount = 1; + uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + uboLayoutBinding.pImmutableSamplers = nullptr; + return uboLayoutBinding; + } +}; + } \ No newline at end of file diff --git a/src/client/render/vk/forward.hpp b/src/client/render/vk/forward.hpp index f66bf15..1712637 100644 --- a/src/client/render/vk/forward.hpp +++ b/src/client/render/vk/forward.hpp @@ -1,10 +1,8 @@ #pragma once #include -#include namespace render { struct renderOptions; } namespace render::vk { struct PhysicalDeviceInfo; - using PipelineRef = std::pair; constexpr VkAllocationCallbacks *ALLOC = nullptr; } \ No newline at end of file