diff --git a/main.c b/main.c index b5053c3..aad6d9a 100644 --- a/main.c +++ b/main.c @@ -46,11 +46,17 @@ typedef struct Vertex { Vec3 color; } Vertex; -#define VERTEX_COUNT 3 +#define VERTEX_COUNT 4 const Vertex vertices[VERTEX_COUNT] = { - {{0.0f, -0.5f}, {0.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, 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}} +}; + +#define INDEX_COUNT 6 +const uint16_t indices[INDEX_COUNT] = { + 0, 1, 2, 2, 3, 0 }; struct VulkanData { @@ -82,6 +88,8 @@ struct VulkanData { bool framebufferResized; VkBuffer vertexBuffer; VkDeviceMemory vertexBufferMemory; + VkBuffer indexBuffer; + VkDeviceMemory indexBufferMemory; }; struct SwapChainSupportDetails { @@ -352,7 +360,7 @@ static struct SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice dev } static struct QueueFamilyIndices findQueueFamilies(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface) { - struct QueueFamilyIndices indices = { + struct QueueFamilyIndices familyIndices = { .graphicsFamily.v = 0, .graphicsFamily.is_some = 0, @@ -372,33 +380,33 @@ static struct QueueFamilyIndices findQueueFamilies(VkPhysicalDevice physicalDevi VkQueueFamilyProperties queueFamily = queueFamilies[i]; if (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT && !(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)) { - indices.transferFamily.v = i; - indices.transferFamily.is_some = true; + familyIndices.transferFamily.v = i; + familyIndices.transferFamily.is_some = true; } if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphicsFamily.v = i; - indices.graphicsFamily.is_some = true; + familyIndices.graphicsFamily.v = i; + familyIndices.graphicsFamily.is_some = true; } VkBool32 presentSupport = 0; vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, &presentSupport); if (presentSupport) { - indices.presentFamily.v = i; - indices.presentFamily.is_some = true; + familyIndices.presentFamily.v = i; + familyIndices.presentFamily.is_some = true; } - if (indices.presentFamily.is_some && indices.graphicsFamily.is_some && indices.transferFamily.is_some) { + if (familyIndices.presentFamily.is_some && familyIndices.graphicsFamily.is_some && familyIndices.transferFamily.is_some) { break; } } - return indices; + return familyIndices; } static bool isDeviceSuitable(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface) { // One could pick the device based on a score. - struct QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface); + struct QueueFamilyIndices familyIndices = findQueueFamilies(physicalDevice, surface); VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); @@ -424,7 +432,7 @@ static bool isDeviceSuitable(VkPhysicalDevice physicalDevice, VkSurfaceKHR surfa deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && deviceFeatures.geometryShader && swapChainAdequate && - indices.graphicsFamily.is_some && indices.presentFamily.is_some && indices.transferFamily.is_some; + familyIndices.graphicsFamily.is_some && familyIndices.presentFamily.is_some && familyIndices.transferFamily.is_some; } static void pickPhysicalDevice(struct VulkanData* data) { @@ -453,12 +461,12 @@ static void pickPhysicalDevice(struct VulkanData* data) { } static void createLogicalDevice(struct VulkanData* data) { - struct QueueFamilyIndices indices = findQueueFamilies(data->physicalDevice, data->surface); + struct QueueFamilyIndices familyIndices = findQueueFamilies(data->physicalDevice, data->surface); float queuePriority = 1.0f; int queueCount = 3; VkDeviceQueueCreateInfo queueCreateInfos[queueCount]; - uint32_t uniqueQueueFamilies[] = {indices.graphicsFamily.v, indices.transferFamily.v, indices.presentFamily.v}; + uint32_t uniqueQueueFamilies[] = {familyIndices.graphicsFamily.v, familyIndices.transferFamily.v, familyIndices.presentFamily.v}; for (int i = 0; i < queueCount; i++) { uint32_t queueFamily = uniqueQueueFamilies[i]; @@ -471,7 +479,7 @@ static void createLogicalDevice(struct VulkanData* data) { queueCreateInfos[i] = queueCreateInfo; } - if (indices.graphicsFamily.v == indices.presentFamily.v) { + if (familyIndices.graphicsFamily.v == familyIndices.presentFamily.v) { queueCount--; } @@ -514,15 +522,15 @@ static void createLogicalDevice(struct VulkanData* data) { printf("ERROR: Failed to create logical device\n"); exit(1); } - if (!indices.transferFamily.is_some) { + if (!familyIndices.transferFamily.is_some) { printf("no graphics\n"); } - if (!indices.presentFamily.is_some) { + if (!familyIndices.presentFamily.is_some) { printf("no present\n"); } - vkGetDeviceQueue(data->device, indices.graphicsFamily.v, 0, &data->graphicsQueue); - vkGetDeviceQueue(data->device, indices.presentFamily.v, 0, &data->presentQueue); - vkGetDeviceQueue(data->device, indices.transferFamily.v, 0, &data->transferQueue); + vkGetDeviceQueue(data->device, familyIndices.graphicsFamily.v, 0, &data->graphicsQueue); + vkGetDeviceQueue(data->device, familyIndices.presentFamily.v, 0, &data->presentQueue); + vkGetDeviceQueue(data->device, familyIndices.transferFamily.v, 0, &data->transferQueue); } static VkExtent2D chooseSwapExtent(VkSurfaceCapabilitiesKHR* capabilities, GLFWwindow* window) { @@ -577,9 +585,9 @@ static void createSwapChain(struct VulkanData* data, GLFWwindow* window) { imageCount = swapChainSupport.capabilities.maxImageCount; } - struct QueueFamilyIndices indices = findQueueFamilies(data->physicalDevice, data->surface); - uint32_t queueFamilyIndices[] = {indices.graphicsFamily.v, indices.presentFamily.v}; - uint32_t otherFamilyIndices[] = {indices.transferFamily.v, indices.graphicsFamily.v}; + struct QueueFamilyIndices familyIndices = findQueueFamilies(data->physicalDevice, data->surface); + uint32_t queueFamilyIndices[] = {familyIndices.graphicsFamily.v, familyIndices.presentFamily.v}; + uint32_t otherFamilyIndices[] = {familyIndices.transferFamily.v, familyIndices.graphicsFamily.v}; VkSwapchainCreateInfoKHR createInfo = { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, @@ -600,7 +608,7 @@ static void createSwapChain(struct VulkanData* data, GLFWwindow* window) { .oldSwapchain = VK_NULL_HANDLE, }; - if (indices.graphicsFamily.v != indices.presentFamily.v) { + if (familyIndices.graphicsFamily.v != familyIndices.presentFamily.v) { createInfo.pQueueFamilyIndices = queueFamilyIndices; } @@ -1001,6 +1009,7 @@ static void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageInd VkBuffer vertexBuffers[] = {data->vertexBuffer}; VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); + vkCmdBindIndexBuffer(commandBuffer, data->indexBuffer, 0, VK_INDEX_TYPE_UINT16); VkViewport viewport = { .x = 0.0f, @@ -1017,7 +1026,7 @@ static void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageInd .extent = data->swapChainExtent, }; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - vkCmdDraw(commandBuffer, VERTEX_COUNT, 1, 0, 0); + vkCmdDrawIndexed(commandBuffer, INDEX_COUNT, 1, 0, 0, 0); vkCmdEndRenderPass(commandBuffer); if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { fprintf(stderr, "ERROR: Failed to record command buffer\n"); @@ -1141,8 +1150,8 @@ static uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags proper } static void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer* buffer, VkDeviceMemory* bufferMemory, struct VulkanData* data) { - struct QueueFamilyIndices indices = findQueueFamilies(data->physicalDevice, data->surface); - uint32_t otherFamilyIndices[] = {indices.transferFamily.v, indices.graphicsFamily.v}; + struct QueueFamilyIndices familyIndices = findQueueFamilies(data->physicalDevice, data->surface); + uint32_t otherFamilyIndices[] = {familyIndices.transferFamily.v, familyIndices.graphicsFamily.v}; VkBufferCreateInfo bufferInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .size = size, @@ -1209,6 +1218,26 @@ static void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size vkFreeCommandBuffers(data->device, data->transferCommandPool, 1, &commandBuffer); } +static void createIndexBuffer(struct VulkanData* data) { + VkDeviceSize bufferSize = sizeof(indices[0]) * INDEX_COUNT; + + VkBuffer stagingBuffer; + VkDeviceMemory stagingBufferMemory; + createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, &stagingBufferMemory, data); + + void* indexData; + vkMapMemory(data->device, stagingBufferMemory, 0, bufferSize, 0, &indexData); + memcpy(indexData, indices, bufferSize); + vkUnmapMemory(data->device, stagingBufferMemory); + + createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &data->indexBuffer, &data->indexBufferMemory, data); + + copyBuffer(stagingBuffer, data->indexBuffer, bufferSize, data); + + vkDestroyBuffer(data->device, stagingBuffer, NULL); + vkFreeMemory(data->device, stagingBufferMemory, NULL); +} + static void createVertexBuffer(struct VulkanData* data) { VkDeviceSize bufferSize = sizeof(vertices[0]) * VERTEX_COUNT; @@ -1241,6 +1270,7 @@ static struct VulkanData initVulkan(GLFWwindow* window) { createGraphicsPipeline(&data); createFramebuffers(&data); createCommandPool(&data); + createIndexBuffer(&data); createVertexBuffer(&data); createCommandBuffers(&data); createSyncObjects(&data); @@ -1265,6 +1295,9 @@ static void cleanup(GLFWwindow* window, struct VulkanData* data) { cleanupSwapChain(data); vkDestroyBuffer(data->device, data->vertexBuffer, NULL); vkFreeMemory(data->device, data->vertexBufferMemory, NULL); + vkDestroyBuffer(data->device, data->indexBuffer, NULL); + vkFreeMemory(data->device, data->indexBufferMemory, NULL); + vkDestroyPipeline(data->device, data->graphicsPipeline, NULL); vkDestroyPipelineLayout(data->device, data->pipelineLayout, NULL); vkDestroyRenderPass(data->device, data->renderPass, NULL);