Kajetan Johannes Hammerle 2 месяцев назад
Родитель
Сommit
2fc4ebf1ce
5 измененных файлов с 135 добавлено и 29 удалено
  1. 3 0
      include/core/VulkanBase.hpp
  2. 14 1
      include/core/VulkanWrapper.hpp
  3. 5 20
      shaders/vertex.vert.glsl
  4. 12 0
      src/VulkanBase.cpp
  5. 101 8
      src/VulkanWrapper.cpp

+ 3 - 0
include/core/VulkanBase.hpp

@@ -13,6 +13,7 @@
 
 namespace Core::Vulkan {
     [[maybe_unused]] constexpr u32 INVALID_QUEUE_FAMILY = 0xFFFF'FFFF;
+    [[maybe_unused]] constexpr u32 INVALID_MEMORY_TYPE = 0xFFFF'FFFF;
 
     struct DeviceQueueData {
         u32 queueFamilyIndex = 0;
@@ -87,6 +88,8 @@ namespace Core::Vulkan {
 
         void waitForIdle();
 
+        u32 findMemoryType(u32 typeFilter, VkMemoryPropertyFlags flags);
+
         operator VkDevice() {
             return device;
         }

+ 14 - 1
include/core/VulkanWrapper.hpp

@@ -138,7 +138,10 @@ namespace Core::Vulkan {
         Pipeline(Pipeline&&) = default;
         ~Pipeline();
         void updateSize(u32 width, u32 height);
-        bool init(PipelineLayout& pl, RenderPass& rp);
+        bool init(
+            PipelineLayout& pl, RenderPass& rp,
+            const List<VkVertexInputBindingDescription>& bd,
+            const List<VkVertexInputAttributeDescription>& ad);
     };
 
     struct CommandPool : public BaseWrapper<VkCommandPool> {
@@ -172,6 +175,16 @@ namespace Core::Vulkan {
         SwapchainResult present(Semaphore& signal, Swapchain& s, u32 index);
     };
 
+    struct VertexBuffer : public BaseWrapper<VkBuffer> {
+        VkDeviceMemory memory;
+
+        VertexBuffer();
+        VertexBuffer(const VertexBuffer&) = delete;
+        VertexBuffer(VertexBuffer&&) = default;
+        ~VertexBuffer();
+        VertexBuffer& operator=(const VertexBuffer&) = delete;
+        bool init(Base& base, size_t size, const void* data);
+    };
 }
 
 #endif

+ 5 - 20
shaders/vertex.vert.glsl

@@ -1,26 +1,11 @@
 #version 450
 
-layout(location = 0) out vec3 fragColor;
-
-vec2 positions[6] = vec2[](
-    vec2(0.0, -0.5),
-    vec2(0.5, 0.5),
-    vec2(-0.5, 0.5),
-    vec2(-1.0, -1.0),
-    vec2(-0.5, -1.0),
-    vec2(-1.0, -0.5)
-);
+layout(location = 0) in vec2 inPosition;
+layout(location = 1) in vec3 inColor;
 
-vec3 colors[6] = vec3[](
-    vec3(1.0, 0.0, 0.0),
-    vec3(0.0, 1.0, 0.0),
-    vec3(0.0, 0.0, 1.0),
-    vec3(1.0, 0.0, 0.0),
-    vec3(0.0, 1.0, 0.0),
-    vec3(0.0, 0.0, 1.0)
-);
+layout(location = 0) out vec3 fragColor;
 
 void main() {
-    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
-    fragColor = colors[gl_VertexIndex];
+    gl_Position = vec4(inPosition, 0.0, 1.0);
+    fragColor = inColor;
 }

+ 12 - 0
src/VulkanBase.cpp

@@ -291,3 +291,15 @@ void Base::waitForIdle() {
         vkDeviceWaitIdle(device);
     }
 }
+
+u32 Base::findMemoryType(u32 typeFilter, VkMemoryPropertyFlags flags) {
+    VkPhysicalDeviceMemoryProperties m;
+    vkGetPhysicalDeviceMemoryProperties(physicalDevice, &m);
+    for(u32 i = 0; i < m.memoryTypeCount; i++) {
+        if(typeFilter & (1u << i) &&
+           (m.memoryTypes[i].propertyFlags & flags) == flags) {
+            return i;
+        }
+    }
+    return INVALID_MEMORY_TYPE;
+}

+ 101 - 8
src/VulkanWrapper.cpp

@@ -8,6 +8,8 @@
 #include "core/WindowManager.hpp"
 
 namespace Vulkan = Core::Vulkan;
+using Core::List;
+using Core::Vulkan::VertexBuffer;
 using Vulkan::CommandBuffer;
 using Vulkan::Queue;
 using Vulkan::SwapchainImages;
@@ -237,7 +239,10 @@ void Pipeline::updateSize(u32 width, u32 height) {
     scissor.extent.height = height;
 }
 
-bool Pipeline::init(PipelineLayout& pl, RenderPass& rp) {
+bool Pipeline::init(
+    PipelineLayout& pl, RenderPass& rp,
+    const List<VkVertexInputBindingDescription>& bd,
+    const List<VkVertexInputAttributeDescription>& ad) {
     Pipeline::~Pipeline();
     ShaderModule vertexShaderModule;
     ShaderModule fragmentShaderModule;
@@ -256,7 +261,11 @@ bool Pipeline::init(PipelineLayout& pl, RenderPass& rp) {
          .pName = "main"}};
 
     VkPipelineVertexInputStateCreateInfo vertexInputState = {
-        .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO};
+        .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+        .vertexBindingDescriptionCount = static_cast<u32>(bd.getLength()),
+        .pVertexBindingDescriptions = &bd[0],
+        .vertexAttributeDescriptionCount = static_cast<u32>(ad.getLength()),
+        .pVertexAttributeDescriptions = &ad[0]};
 
     VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {
         .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
@@ -446,6 +455,45 @@ SwapchainResult Queue::present(Semaphore& signal, Swapchain& s, u32 index) {
     return SwapchainResult::SUCCESS;
 }
 
+VertexBuffer::VertexBuffer() : BaseWrapper<VkBuffer>(), memory(VK_NULL_HANDLE) {
+}
+
+VertexBuffer::~VertexBuffer() {
+    if(device != VK_NULL_HANDLE) {
+        vkDestroyBuffer(device, handle, nullptr);
+        vkFreeMemory(device, memory, nullptr);
+    }
+    device = VK_NULL_HANDLE;
+    handle = VK_NULL_HANDLE;
+}
+
+bool VertexBuffer::init(Base& b, size_t size, const void* data) {
+    VkBufferCreateInfo info = {
+        .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+        .size = size,
+        .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+        .sharingMode = VK_SHARING_MODE_EXCLUSIVE};
+    VK_CHECK_TRUE(vkCreateBuffer(b, &info, nullptr, &handle));
+    device = b;
+
+    VkMemoryRequirements m;
+    vkGetBufferMemoryRequirements(device, handle, &m);
+    VkMemoryAllocateInfo aInfo = {
+        .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+        .allocationSize = m.size,
+        .memoryTypeIndex = b.findMemoryType(
+            m.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                                  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)};
+    VK_CHECK_TRUE(vkAllocateMemory(device, &aInfo, nullptr, &memory));
+    VK_CHECK_TRUE(vkBindBufferMemory(device, handle, memory, 0));
+
+    void* destination = nullptr;
+    VK_CHECK_TRUE(vkMapMemory(device, memory, 0, size, 0, &destination));
+    memcpy(destination, data, size);
+    vkUnmapMemory(device, memory);
+    return false;
+}
+
 struct VulkanDummy {
     Core::Vulkan::Base base{};
 
@@ -465,7 +513,7 @@ struct VulkanDummy {
     PipelineLayout pipelineLayout{};
     RenderPass renderPass{};
     Pipeline pipeline{};
-    Core::List<Vulkan::Framebuffer> framebuffers{};
+    List<Vulkan::Framebuffer> framebuffers{};
     CommandPool commandPool{};
     size_t currentFrame = 0;
 
@@ -478,6 +526,34 @@ struct VulkanDummy {
 
     Core::Array<Frame, 2> frames{};
 
+    struct Vertex {
+        Core::Vector2 position;
+        Core::Vector3 color;
+
+        static auto getBindingDescription() {
+            VkVertexInputBindingDescription d = {
+                .binding = 0,
+                .stride = sizeof(Vertex),
+                .inputRate = VK_VERTEX_INPUT_RATE_VERTEX};
+            return d;
+        }
+
+        static auto getAttributeDescriptions() {
+            Core::Array<VkVertexInputAttributeDescription, 2> d = {
+                {{.location = 0,
+                  .binding = 0,
+                  .format = VK_FORMAT_R32G32_SFLOAT,
+                  .offset = offsetof(Vertex, position)},
+                 {.location = 1,
+                  .binding = 0,
+                  .format = VK_FORMAT_R32G32B32_SFLOAT,
+                  .offset = offsetof(Vertex, color)}}};
+            return d;
+        }
+    };
+
+    VertexBuffer vertexBuffer{};
+
     static int getSurfaceFormatPoints(const VkSurfaceFormatKHR& sf) {
         if(sf.format == VK_FORMAT_B8G8R8A8_UNORM &&
            sf.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
@@ -546,12 +622,12 @@ struct VulkanDummy {
 
     bool initDevice() {
         bool same = baseData.graphicsFamily == baseData.presentFamily;
-        Core::List<Vulkan::DeviceQueueData> data;
+        List<Vulkan::DeviceQueueData> data;
         data.add(baseData.graphicsFamily, 1.0f);
         if(!same) {
             data.add(baseData.presentFamily, 1.0f);
         };
-        Core::List<const char*> extensions;
+        List<const char*> extensions;
         extensions.add(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
         if(base.initDevice(data, extensions)) {
             return true;
@@ -630,7 +706,13 @@ struct VulkanDummy {
 
     bool initPipeline() {
         pipeline.updateSize(swapchainSize.width, swapchainSize.height);
-        return pipeline.init(pipelineLayout, renderPass);
+        List<VkVertexInputBindingDescription> bd;
+        bd.add(Vertex::getBindingDescription());
+        List<VkVertexInputAttributeDescription> ad;
+        for(auto a : Vertex::getAttributeDescriptions()) {
+            ad.add(a);
+        }
+        return pipeline.init(pipelineLayout, renderPass, bd, ad);
     }
 
     bool initFramebuffers() {
@@ -650,7 +732,9 @@ struct VulkanDummy {
         cb.begin();
         cb.beginRenderPass(renderPass, framebuffers[index], swapchainSize);
         cb.bindPipeline(pipeline);
-        cb.draw(6);
+        VkDeviceSize offset = 0;
+        vkCmdBindVertexBuffers(cb, 0, 1, vertexBuffer, &offset);
+        cb.draw(3);
         cb.endRenderPass();
         cb.end();
     }
@@ -667,13 +751,22 @@ struct VulkanDummy {
         return false;
     }
 
+    bool initVertexBuffer() {
+        List<Vertex> l;
+        l.add(Core::Vector2{-0.5f, -0.5f}, Core::Vector3{1.0, 1.0, 1.0});
+        l.add(Core::Vector2{0.5f, 0.0f}, Core::Vector3{0.0, 1.0, 1.0});
+        l.add(Core::Vector2{0.0f, 0.5f}, Core::Vector3{1.0, 1.0, 0.0});
+        return vertexBuffer.init(base, sizeof(l[0]) * l.getLength(), &l[0]);
+    }
+
     bool init() {
         return base.init() || initPhysicalDevice() || initDevice() ||
                initSwapchain() || initSwapchainImages() ||
                pipelineLayout.init(base) ||
                renderPass.init(base, baseData.surfaceFormat.format) ||
                initPipeline() || initFramebuffers() ||
-               commandPool.init(base, baseData.graphicsFamily) || initFrames();
+               commandPool.init(base, baseData.graphicsFamily) ||
+               initFrames() || initVertexBuffer();
     }
 
     bool recreateSwapchain() {