250 lines
7.2 KiB
C
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;
|
|
}
|