#include #include #include #define GLFW_INCLUDE_NONE #include evstring PROJECT_NAME = evstr("evk"); float vertexPositions[] = { 0.f,-.5f, .5f, .5f, -.5f, .5f }; int main(void) { u32 width = 1024; u32 height = 1024; evkInstance instance = evkCreateInstance((evkInstanceCreateInfo){ .applicationInfo = EV_DEFAULT(evkApplicationInfo), .layers = svec_init(evstring, { evstr("VK_LAYER_KHRONOS_validation"), }), .extensions = svec_init(evstring, { evstr("VK_KHR_surface"), evstr("VK_KHR_win32_surface"), }), }); if(instance.vk == EV_INVALID(VkInstance)) { puts("Instance creation failed."); goto InstanceCreationFailed; } puts("Instance was created successfully."); evkDevice device = evkCreateDevice((evkDeviceCreateInfo) { .instance = instance, .physicalDeviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, .queueRequirements = svec_init(evkDeviceQueueRequirement, { { VK_QUEUE_GRAPHICS_BIT, 1 }, { VK_QUEUE_COMPUTE_BIT , 1 }, }), .deviceExtensions = svec_init(evstring, { evstr("VK_KHR_swapchain"), evstr("VK_KHR_dynamic_rendering"), evstr("VK_KHR_depth_stencil_resolve"), evstr("VK_KHR_create_renderpass2"), evstr("VK_KHR_synchronization2"), evstr("VK_KHR_buffer_device_address"), evstr("VK_EXT_descriptor_indexing"), }), }); if(device.vk == EV_INVALID(VkDevice)) { puts("Couldn't create a VkDevice"); goto DeviceCreationFailed; } puts("Logical Device created successfully."); VkQueue graphicsQueue; vkGetDeviceQueue(device.vk, device.queueFamilies[VK_QUEUE_GRAPHICS_BIT].familyIndex, 0, &graphicsQueue); if (!glfwInit()) { puts("GLFW Initialization failed."); goto GLFWInitFailed; } glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); GLFWwindow* window = glfwCreateWindow(1024,1024, "evk", NULL, NULL); if(!window) { puts("Window Creation Failed."); goto WindowCreationFailed; } VkSurfaceKHR surface; VkResult err = glfwCreateWindowSurface(instance.vk, window, NULL, &surface); if (err) { goto VKSurfaceCreationFailed; puts("Surface creation failed."); } evkSwapChain swapChain = evkCreateSwapChain((evkSwapChainCreateInfo){ .device = device, .surface = surface, .width = width, .height = height, .imageCount = 3, }); evkCommandPool commandPool = evkCreateCommandPool((evkCommandPoolCreateInfo) { .device = device, .queueFlags = VK_QUEUE_GRAPHICS_BIT, .poolFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT }); vec(VkCommandBuffer) commandBuffers = evkAllocateCommandBuffers(device, commandPool, vec_len(&swapChain.images), true); evkShaderCompiler compiler = evkCreateShaderCompiler(); evkShader vertShader = evkInitShaderFromFile(device, compiler, "shaders/tri.vert"); evkShader fragShader = evkInitShaderFromFile(device, compiler, "shaders/tri.frag"); evkDestroyShaderCompiler(compiler); evkColorAttachment colorAttachment0 = { swapChain.surfaceFormat.format, EV_DEFAULT(VkPipelineColorBlendAttachmentState) }; evkPipelineCreateInfo pipelineCreateInfo = EV_DEFAULT(evkPipelineCreateInfo, dynamicStates = svec_init(VkDynamicState, { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, }), shaderStages = svec_init(evkShader, { vertShader, fragShader, }), colorAttachments = svec_init(evkColorAttachment, { colorAttachment0, }), viewportCountOverride = 1, ); VkViewport viewport = EV_DEFAULT(VkViewport, width=width, height=height); VkRect2D scissor = EV_DEFAULT(VkRect2D,extent.width=width, extent.height=height); evkPipeline graphicsPipeline = evkCreatePipeline(device, pipelineCreateInfo); VkFence drawFence = evkCreateFence(device, false); VkSemaphore imageAcquiredSemaphore = evkCreateSemaphore(device); VkSemaphore drawFinishedSemaphore = evkCreateSemaphore(device); while(!glfwWindowShouldClose(window)) { u32 imageIdx; vkAcquireNextImageKHR(device.vk, swapChain.vk, UInt64.MAX, imageAcquiredSemaphore, VK_NULL_HANDLE, &imageIdx); VkCommandBuffer cmdbuf = commandBuffers[imageIdx]; VkRenderingAttachmentInfoKHR colorAttachment = EV_DEFAULT(VkRenderingAttachmentInfoKHR, imageView = swapChain.imageViews[imageIdx].vk, loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, storeOp= VK_ATTACHMENT_STORE_OP_STORE, ); VkRenderingInfo renderingInfo = EV_DEFAULT(VkRenderingInfo, renderArea.extent = ((VkExtent2D){width, height}), pColorAttachments = &colorAttachment, colorAttachmentCount = 1, ); evkBeginPrimaryCommandBuffer(cmdbuf); vkCmdSetScissor(cmdbuf, 0, 1, &scissor); vkCmdSetViewport(cmdbuf, 0, 1, &viewport); vkCmdBeginRenderingKHR(cmdbuf, &renderingInfo); vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.vk); vkCmdDraw(cmdbuf, 3, 1, 0, 0); vkCmdEndRenderingKHR(cmdbuf); VkImageMemoryBarrier imageMemoryBarrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .image = swapChain.images[imageIdx].vk, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .layerCount = 1, .levelCount = 1, }, }; vkCmdPipelineBarrier(cmdbuf, 0, 0, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier); evkEndCommandBuffer(cmdbuf); VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; VkSubmitInfo submitInfo = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pCommandBuffers = &cmdbuf, .commandBufferCount = 1, .waitSemaphoreCount = 1, .pWaitSemaphores = &imageAcquiredSemaphore, .pWaitDstStageMask = waitStages, .signalSemaphoreCount = 1, .pSignalSemaphores = &drawFinishedSemaphore, }; vkQueueSubmit(graphicsQueue, 1, &submitInfo, drawFence); vkWaitForFences(device.vk, 1, &drawFence, VK_TRUE, UInt64.MAX); vkResetFences(device.vk, 1, &drawFence); VkPresentInfoKHR presentInfo = { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .waitSemaphoreCount = 1, .pWaitSemaphores = &drawFinishedSemaphore, .swapchainCount = 1, .pSwapchains = &swapChain.vk, .pImageIndices = &imageIdx, }; vkQueuePresentKHR(graphicsQueue, &presentInfo); vkResetCommandBuffer(cmdbuf,VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); // Main Loop glfwPollEvents(); } vkQueueWaitIdle(graphicsQueue); vkDestroyFence(device.vk, drawFence, NULL); vkDestroySemaphore(device.vk, imageAcquiredSemaphore, NULL); vkDestroySemaphore(device.vk, drawFinishedSemaphore, NULL); evkDestroyPipeline(graphicsPipeline); evkDestroyShader(device, vertShader); evkDestroyShader(device, fragShader); vkFreeCommandBuffers(device.vk, commandPool.vk, vec_len(&commandBuffers), commandBuffers); evkDestroyCommandPool(device, commandPool); evkDestroySwapChain(device, swapChain); SwapchainCreationFailed: vkDestroySurfaceKHR(instance.vk, swapChain.surface, NULL); VKSurfaceCreationFailed: WindowCreationFailed: glfwTerminate(); GLFWInitFailed: evkDestroyDevice(device); DeviceCreationFailed: evkDestroyInstance(instance); InstanceCreationFailed: return 0; }