|
@@ -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() {
|