diff --git a/src/main.cpp b/src/main.cpp index 1e1ad53..ed7c820 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,6 +21,42 @@ constexpr i32 HEIGHT = 600; constexpr i32 MAX_FRAMES_IN_FLIGHT = 2; +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; + } +}; + +constexpr std::array vertices = { + { { { -0.5F, -0.5F }, { 1.0F, 0.0F, 0.0F } }, + { { 0.5F, -0.5F }, { 0.0F, 1.0F, 0.0F } }, + { { 0.5F, 0.5F }, { 0.0F, 0.0F, 1.0F } }, + { { -0.5F, 0.5F }, { 1.0F, 1.0F, 1.0F } } } +}; + +constexpr std::array indices = { 0, 1, 2, 2, 3, 0 }; + constexpr std::array validationLayers = { "VK_LAYER_KHRONOS_validation" }; #ifdef __APPLE__ @@ -79,43 +115,12 @@ class VulkanApp { vk::UniqueBuffer mVertexBuffer; vk::UniqueDeviceMemory mVertexBufferMemory; + vk::UniqueBuffer mIndexBuffer; + vk::UniqueDeviceMemory mIndexBufferMemory; 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; @@ -177,6 +182,7 @@ class VulkanApp { createFramebuffers(); createCommandPool(); createVertexBuffer(); + createIndexBuffer(); createCommandBuffers(); createSyncObjects(); } @@ -307,10 +313,11 @@ class VulkanApp { } fn createLogicalDevice() -> void { - QueueFamilyIndices indices = findQueueFamilies(mPhysicalDevice); + QueueFamilyIndices qfIndices = findQueueFamilies(mPhysicalDevice); std::vector queueCreateInfos; - std::set uniqueQueueFamilies = { indices.graphics_family.value(), indices.present_family.value() }; + std::set uniqueQueueFamilies = { qfIndices.graphics_family.value(), + qfIndices.present_family.value() }; f32 queuePriority = 1.0F; @@ -331,8 +338,8 @@ class VulkanApp { .pEnabledFeatures = &deviceFeatures }; mDevice = mPhysicalDevice.createDeviceUnique(createInfo); - mGraphicsQueue = mDevice->getQueue(indices.graphics_family.value(), 0); - mPresentQueue = mDevice->getQueue(indices.present_family.value(), 0); + mGraphicsQueue = mDevice->getQueue(qfIndices.graphics_family.value(), 0); + mPresentQueue = mDevice->getQueue(qfIndices.present_family.value(), 0); } fn createSwapChain() -> void { @@ -348,9 +355,9 @@ class VulkanApp { imageCount > swapChainSupport.capabilities.maxImageCount) imageCount = swapChainSupport.capabilities.maxImageCount; - QueueFamilyIndices indices = findQueueFamilies(mPhysicalDevice); - std::array queueFamilyIndices = { indices.graphics_family.value(), - indices.present_family.value() }; + QueueFamilyIndices qfIndices = findQueueFamilies(mPhysicalDevice); + std::array queueFamilyIndices = { qfIndices.graphics_family.value(), + qfIndices.present_family.value() }; vk::SwapchainCreateInfoKHR createInfo { .surface = mSurface.get(), @@ -360,11 +367,12 @@ class VulkanApp { .imageExtent = extent, .imageArrayLayers = 1, .imageUsage = vk::ImageUsageFlagBits::eColorAttachment, - .imageSharingMode = indices.graphics_family != indices.present_family ? vk::SharingMode::eConcurrent - : vk::SharingMode::eExclusive, - .queueFamilyIndexCount = static_cast(indices.graphics_family != indices.present_family ? 2 : 0), + .imageSharingMode = qfIndices.graphics_family != qfIndices.present_family ? vk::SharingMode::eConcurrent + : vk::SharingMode::eExclusive, + .queueFamilyIndexCount = + static_cast(qfIndices.graphics_family != qfIndices.present_family ? 2 : 0), .pQueueFamilyIndices = - indices.graphics_family != indices.present_family ? queueFamilyIndices.data() : nullptr, + qfIndices.graphics_family != qfIndices.present_family ? queueFamilyIndices.data() : nullptr, .preTransform = swapChainSupport.capabilities.currentTransform, .compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque, .presentMode = presentMode, @@ -578,7 +586,7 @@ class VulkanApp { } fn createVertexBuffer() -> void { - vk::DeviceSize bufferSize = sizeof(mVertices[0]) * mVertices.size(); + vk::DeviceSize bufferSize = sizeof(vertices[0]) * vertices.size(); vk::UniqueBuffer stagingBuffer; vk::UniqueDeviceMemory stagingBufferMemory; @@ -592,7 +600,7 @@ class VulkanApp { ); void* data = mDevice->mapMemory(stagingBufferMemory.get(), 0, bufferSize); - memcpy(data, mVertices.data(), static_cast(bufferSize)); + memcpy(data, vertices.data(), static_cast(bufferSize)); mDevice->unmapMemory(stagingBufferMemory.get()); createBuffer( @@ -609,6 +617,38 @@ class VulkanApp { stagingBufferMemory.reset(); } + fn createIndexBuffer() -> void { + vk::DeviceSize bufferSize = sizeof(indices[0]) * indices.size(); + + vk::UniqueBuffer stagingBuffer; + vk::UniqueDeviceMemory stagingBufferMemory; + + createBuffer( + bufferSize, + vk::BufferUsageFlagBits::eTransferSrc, + vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, + stagingBuffer, + stagingBufferMemory + ); + + void* data = mDevice->mapMemory(stagingBufferMemory.get(), 0, bufferSize); + memcpy(data, indices.data(), static_cast(bufferSize)); + mDevice->unmapMemory(stagingBufferMemory.get()); + + createBuffer( + bufferSize, + vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst, + vk::MemoryPropertyFlagBits::eDeviceLocal, + mIndexBuffer, + mIndexBufferMemory + ); + + copyBuffer(stagingBuffer.get(), mIndexBuffer.get(), bufferSize); + + stagingBuffer.reset(); + stagingBufferMemory.reset(); + } + fn createBuffer( vk::DeviceSize deviceSize, vk::BufferUsageFlags bufferUsageFlags, @@ -720,7 +760,9 @@ class VulkanApp { commandBuffer.bindVertexBuffers(0, mVertexBuffer.get(), { 0 }); - commandBuffer.draw(static_cast(mVertices.size()), 1, 0, 0); + commandBuffer.bindIndexBuffer(mIndexBuffer.get(), 0, vk::IndexType::eUint16); + + commandBuffer.drawIndexed(static_cast(indices.size()), 1, 0, 0, 0); commandBuffer.endRenderPass(); @@ -867,7 +909,7 @@ class VulkanApp { } fn isDeviceSuitable(vk::PhysicalDevice device) -> bool { - QueueFamilyIndices indices = findQueueFamilies(device); + QueueFamilyIndices qfIndices = findQueueFamilies(device); bool extensionsSupported = checkDeviceExtensionSupport(device); @@ -878,7 +920,7 @@ class VulkanApp { swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.present_modes.empty(); } - return indices.isComplete() && extensionsSupported && swapChainAdequate; + return qfIndices.isComplete() && extensionsSupported && swapChainAdequate; } static fn checkDeviceExtensionSupport(vk::PhysicalDevice device) -> bool { @@ -893,24 +935,24 @@ class VulkanApp { } fn findQueueFamilies(vk::PhysicalDevice device) -> QueueFamilyIndices { - QueueFamilyIndices indices; + QueueFamilyIndices qfIndices; std::vector queueFamilies = device.getQueueFamilyProperties(); for (u32 i = 0; i < queueFamilies.size(); i++) { if (queueFamilies[i].queueFlags & vk::QueueFlagBits::eGraphics) - indices.graphics_family = i; + qfIndices.graphics_family = i; vk::Bool32 queuePresentSupport = device.getSurfaceSupportKHR(i, mSurface.get()); if (queuePresentSupport) - indices.present_family = i; + qfIndices.present_family = i; - if (indices.isComplete()) + if (qfIndices.isComplete()) break; } - return indices; + return qfIndices; } static fn getRequiredExtensions() -> std::vector {