Files
evk/main.c
2025-07-02 12:37:06 +03:00

250 lines
7.2 KiB
C

#include <evk/evk.h>
#include <ev_numeric.h>
#include <ev_helpers.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
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;
}