diff --git a/.clang-tidy b/.clang-tidy index 7005ab5..1346ff1 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -7,6 +7,7 @@ Checks: > -bugprone-implicit-widening-of-multiplication-result, -cert-env33-c, -concurrency-mt-unsafe, + -cppcoreguidelines-avoid-const-or-ref-data-members, -cppcoreguidelines-avoid-magic-numbers, -cppcoreguidelines-owning-memory, -cppcoreguidelines-pro-type-member-init, diff --git a/src/main.cpp b/src/main.cpp index 6e6249c..737acfb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -76,9 +77,45 @@ class VulkanApp { std::vector mRenderFinishedSemaphores; std::vector mInFlightFences; + vk::UniqueBuffer mVertexBuffer; + vk::UniqueDeviceMemory mVertexBufferMemory; + bool mFramebufferResized = false; u32 mCurrentFrame = 0; + struct Vertex { + glm::vec2 pos; + glm::vec3 color; + + static fn getBindingDescription() -> vk::VertexInputBindingDescription { + vk::VertexInputBindingDescription bindingDescription { .binding = 0, + .stride = sizeof(Vertex), + .inputRate = vk::VertexInputRate::eVertex }; + + return bindingDescription; + } + + static fn getAttributeDescriptions() -> std::array { + std::array attributeDescriptions {}; + + attributeDescriptions[0] = { + .location = 0, .binding = 0, .format = vk::Format::eR32G32Sfloat, .offset = offsetof(Vertex, pos) + }; + + attributeDescriptions[1] = { + .location = 1, .binding = 0, .format = vk::Format::eR32G32B32Sfloat, .offset = offsetof(Vertex, color) + }; + + return attributeDescriptions; + } + }; + + const std::vector mVertices = { + { { 0.0F, -0.5F }, { 1.0F, 1.0F, 1.0F } }, + { { 0.5F, 0.5F }, { 0.0F, 1.0F, 0.0F } }, + { { -0.5F, 0.5F }, { 0.0F, 0.0F, 1.0F } } + }; + struct QueueFamilyIndices { std::optional graphics_family; std::optional present_family; @@ -115,7 +152,6 @@ class VulkanApp { vkfw::WindowHints hints; hints.clientAPI = vkfw::ClientAPI::eNone; - // hints.resizable = false; mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints); mWindow->setUserPointer(this); @@ -140,6 +176,7 @@ class VulkanApp { createGraphicsPipeline(); createFramebuffers(); createCommandPool(); + createVertexBuffer(); createCommandBuffers(); createSyncObjects(); } @@ -422,11 +459,15 @@ class VulkanApp { std::array shaderStages = { vertShaderStageInfo, fragShaderStageInfo }; + vk::VertexInputBindingDescription bindingDescription = Vertex::getBindingDescription(); + std::array attributeDescriptions = + Vertex::getAttributeDescriptions(); + vk::PipelineVertexInputStateCreateInfo vertexInputInfo { - .vertexBindingDescriptionCount = 0, - .pVertexBindingDescriptions = nullptr, - .vertexAttributeDescriptionCount = 0, - .pVertexAttributeDescriptions = nullptr, + .vertexBindingDescriptionCount = 1, + .pVertexBindingDescriptions = &bindingDescription, + .vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()), + .pVertexAttributeDescriptions = attributeDescriptions.data(), }; vk::PipelineInputAssemblyStateCreateInfo inputAssembly { @@ -536,6 +577,45 @@ class VulkanApp { mCommandPool = mDevice->createCommandPoolUnique(poolInfo); } + fn createVertexBuffer() -> void { + vk::BufferCreateInfo bufferInfo { + .size = sizeof(mVertices[0]) * mVertices.size(), + .usage = vk::BufferUsageFlagBits::eVertexBuffer, + .sharingMode = vk::SharingMode::eExclusive, + }; + + mVertexBuffer = mDevice->createBufferUnique(bufferInfo, nullptr); + + vk::MemoryRequirements memRequirements = mDevice->getBufferMemoryRequirements(mVertexBuffer.get()); + + vk::MemoryAllocateInfo allocInfo { + .allocationSize = memRequirements.size, + .memoryTypeIndex = findMemoryType( + memRequirements.memoryTypeBits, + vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent + ), + }; + + mVertexBufferMemory = mDevice->allocateMemoryUnique(allocInfo); + + mDevice->bindBufferMemory(mVertexBuffer.get(), mVertexBufferMemory.get(), 0); + + void* data = mDevice->mapMemory(mVertexBufferMemory.get(), 0, bufferInfo.size); + memcpy(data, mVertices.data(), static_cast(bufferInfo.size)); + mDevice->unmapMemory(mVertexBufferMemory.get()); + } + + fn findMemoryType(u32 typeFilter, vk::MemoryPropertyFlags properties) -> u32 { + vk::PhysicalDeviceMemoryProperties memProperties = mPhysicalDevice.getMemoryProperties(); + + for (u32 i = 0; i < memProperties.memoryTypeCount; i++) + if ((typeFilter & (1 << i)) && + (memProperties.memoryTypes.at(i).propertyFlags & properties) == properties) + return i; + + throw std::runtime_error("Failed to find a suitable memory type!"); + } + fn createCommandBuffers() -> void { mCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT); @@ -573,6 +653,7 @@ class VulkanApp { .minDepth = 0.0F, .maxDepth = 1.0F, }; + vk::Rect2D scissor { .offset = { 0, 0 }, .extent = mSwapChainExtent, @@ -581,7 +662,9 @@ class VulkanApp { commandBuffer.setViewport(0, viewport); commandBuffer.setScissor(0, scissor); - commandBuffer.draw(3, 1, 0, 0); + commandBuffer.bindVertexBuffers(0, mVertexBuffer.get(), { 0 }); + + commandBuffer.draw(static_cast(mVertices.size()), 1, 0, 0); commandBuffer.endRenderPass(); diff --git a/src/shaders/shader.vert b/src/shaders/shader.vert index f5b2f8d..9f27f54 100644 --- a/src/shaders/shader.vert +++ b/src/shaders/shader.vert @@ -1,20 +1,11 @@ #version 450 +layout(location = 0) in vec2 inPosition; +layout(location = 1) in vec3 inColor; + layout(location = 0) out vec3 fragColor; -vec2 positions[3] = vec2[]( - vec2(0.0, -0.5), - vec2(0.5, 0.5), - vec2(-0.5, 0.5) -); - -vec3 colors[3] = vec3[]( - vec3(1.0, 0.0, 0.0), - vec3(0.0, 1.0, 0.0), - vec3(0.0, 0.0, 1.0) -); - 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; } diff --git a/src/shaders/vert.spv b/src/shaders/vert.spv index a41dd2c..1e4ce0c 100644 Binary files a/src/shaders/vert.spv and b/src/shaders/vert.spv differ