svulc/test/device-creation.c
2024-12-26 23:51:12 +01:00

365 lines
11 KiB
C

#include "../include/svulc.h"
#include "../include/swapchain.h"
#include "../include/renderingpipeline.h"
#include "../include/commandpools.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <vulkan/vulkan_core.h>
#include <GLFW/glfw3.h>
#include "helpers.h"
VkShaderModule createShaderModule(sizedData shadercode, VkDevice device){
VkShaderModuleCreateInfo createinfo = {
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
NULL,
0,
shadercode.length,
shadercode.data
};
VkShaderModule module;
if(vkCreateShaderModule(device, &createinfo, NULL, &module)!= VK_SUCCESS){
printf("Couldn't create shader module!");
exit(EXIT_FAILURE);
}
return module;
}
int main(){
//------------------------GLFW----------------------
glfwInit();
GLFWwindow *window;
VkSurfaceKHR surface;
int window_width = 100,
window_height = 100;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
// create the window
window = glfwCreateWindow(window_width, window_height, "device-creation.c", NULL, NULL);
// get required extensions
unsigned int numExtensions;
const char **extensions = glfwGetRequiredInstanceExtensions(&numExtensions);
const char *devExtensions[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
const char *layers[] = {"VK_LAYER_KHRONOS_validation"};
//----------------------INSTANCE-------------------
VkInstance instace;
VkResult result;
result = svlk_createIinstance(layers, 1, extensions, numExtensions, &instace);
if (result != VK_SUCCESS){printf("createinstance failed with code %i\n", result); return 0;}
result = glfwCreateWindowSurface(instace, window, NULL, &surface);
if (result != VK_SUCCESS){printf("createwindowsurface failed with code %i\n", result); return 0;}
//--------------------PHYS-DEVICES-----------------
unsigned int physDeviceNum;
VkPhysicalDevice *physDevices;
result = svlk_getPhysDeviceList(instace, &physDeviceNum, &physDevices);
VkPhysicalDevice toUsePhysDevice;
for (int i=0; i<physDeviceNum; i++) {
if(svlk_deviceCompatable(physDevices[i], surface, VK_QUEUE_GRAPHICS_BIT, extensions, numExtensions)){
toUsePhysDevice = physDevices[i];
}
}
//-----------------------QUEUES--------------------
// Get the queues required for the application
int error = 0;
int graphicsQueue = svlk_getQueueFamilyIndex(toUsePhysDevice, VK_QUEUE_GRAPHICS_BIT, &error);
if(error) printf("can't get graphics queue.\n");
int presentQueue = svlk_getPresentQueueFamilyIndex(toUsePhysDevice, surface, &error);
if(error) printf("can't get present queue.\n");
unsigned int queueFamilies[] = {graphicsQueue, presentQueue};
//-------------------LOGIC-DEVICES-----------------
// Create the logical device and the queues
float queuePriority = 1.f;
VkDeviceQueueCreateInfo deviceQueues[] = {
svlk_createQueueInfo(graphicsQueue, 1, &queuePriority)
};
VkDevice device;
VkPhysicalDeviceFeatures devFeatures = {0};
result = svlk_createLogicalDevice(toUsePhysDevice, surface, deviceQueues, 1, devFeatures, devExtensions, sizeof(devExtensions)/sizeof(devExtensions[0]), &device);
//---------------------SWAPCHAIN------------------
VkSurfaceCapabilitiesKHR capabilities;
result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(toUsePhysDevice, surface, &capabilities);
VkSurfaceFormatKHR format = svlk_selectSwapchainFormat(toUsePhysDevice, surface, VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR);
// get the size of the swapchain
int w, h;
glfwGetFramebufferSize(window, &w, &h);
VkExtent2D swapchainExtent = svlk_checkSwapchainExtent(&capabilities, w, h);
// find optimum number of images for the swapchain
int numimgs = capabilities.minImageCount + 1;
if (numimgs > capabilities.maxImageCount && capabilities.maxImageCount != 0) numimgs = capabilities.maxImageCount;
VkSwapchainCreateInfoKHR swcreateinfo = svlk_createSwapchainCreateinfo(
numimgs,
surface,
format,
VK_PRESENT_MODE_FIFO_KHR,
swapchainExtent,
1,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
capabilities.currentTransform
);
svlk_selectSharingMode(&swcreateinfo, graphicsQueue != presentQueue, queueFamilies, 2);
VkSwapchainKHR swapchain;
result = vkCreateSwapchainKHR(device, &swcreateinfo, NULL, &swapchain);
unsigned int imageCount = 0;
VkImage *images = svlk_getSwapchainImages(device, swapchain, &imageCount);
//------------------IMAGE-VIEWS-------------------
unsigned int numImageViews = imageCount;
VkImageView *imageViews = malloc(numImageViews * sizeof(VkImageView));
for (int i = 0; i < numImageViews; i++){
if(svlk_createVkImageView(device, images[i], VK_IMAGE_VIEW_TYPE_2D, format.format, &imageViews[i]) != VK_SUCCESS){
printf("failed to create image view.\n");
exit(EXIT_FAILURE);
}
}
//------------------RENDER-PIPELINE---------------
sizedData vertshdcode = readFileR("shd/triangle.vert.spv");
sizedData fragshdcode = readFileR("shd/triangle.frag.spv");
VkShaderModule vertshdmod = createShaderModule(vertshdcode, device);
VkShaderModule fragshdmod = createShaderModule(fragshdcode, device);
VkPipelineShaderStageCreateInfo stageInfoVert = svlk_vertexShaderTemplate;
stageInfoVert.module = vertshdmod;
VkPipelineShaderStageCreateInfo stageInfoFrag = svlk_fragmentShaderTemplate;
stageInfoFrag.module = fragshdmod;
VkPipelineShaderStageCreateInfo shaderStages[] = {stageInfoVert, stageInfoFrag};
VkDynamicState dynamicStates[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState = {
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
NULL,
0,
2,
dynamicStates
};
VkPipelineViewportStateCreateInfo viewportState = {
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
NULL,
0,
1,
NULL,
1,
NULL
};
VkPipelineRasterizationStateCreateInfo rasterizer = svlk_rasterizationTemplate;
VkPipelineMultisampleStateCreateInfo multisample = svlk_noMultisample;
// no depth testing
VkPipelineColorBlendAttachmentState colorblendatt = svlk_colorBlendTemplate;
VkPipelineColorBlendStateCreateInfo colorblend = svlk_colorBlendCreateInfoTemplate;
colorblend.attachmentCount = 1;
colorblend.pAttachments = &colorblendatt;
VkPipelineLayoutCreateInfo pipelinelayoutcrinfo = svlk_pipelineLayoutCreateInfoTemplate;
VkPipelineLayout pipelinelayout;
if(vkCreatePipelineLayout(device, &pipelinelayoutcrinfo, NULL, &pipelinelayout) != VK_SUCCESS){
printf("couldn't create pipeline layout!\n");
exit(EXIT_FAILURE);
}
VkAttachmentDescription colorattachment = {
0,
format.format,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
};
VkAttachmentReference colorattachmentRef = {
0,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
};
VkSubpassDescription subpass = {
0,
VK_PIPELINE_BIND_POINT_GRAPHICS,
0,
NULL,
1,
&colorattachmentRef,
NULL,
NULL,
0,
NULL
};
VkRenderPassCreateInfo renderPassCreateinfo = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
NULL,
0,
1,
&colorattachment,
1,
&subpass,
0,
NULL
};
VkRenderPass renderPass;
result = vkCreateRenderPass(device, &renderPassCreateinfo, NULL, &renderPass);
if(result != VK_SUCCESS){
printf("vkCreateRenderPass failed\n");
exit(EXIT_FAILURE);
}
VkGraphicsPipelineCreateInfo pipelineCreateinfo = {
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
NULL,
0,
2,
shaderStages,
&svlk_noVertexData,
&svlk_inputAssemblyTemplate,
NULL,
&viewportState,
&rasterizer,
&multisample,
NULL,
&colorblend,
&dynamicState,
pipelinelayout,
renderPass,
0,
NULL,
-1
};
VkPipeline graphicsPipeline;
result = vkCreateGraphicsPipelines(device, NULL, 1, &pipelineCreateinfo, NULL, &graphicsPipeline);
if(result != VK_SUCCESS){
printf("vkCreateGraphicsPipeline failed\n");
exit(EXIT_FAILURE);
}
VkFramebuffer swapchainFramebuffers[numImageViews];
unsigned int swapchainFramebuffersNum;
for(int i = 0; i < swapchainFramebuffersNum; i++){
VkImageView attachment [] = {
imageViews[i]
};
VkFramebufferCreateInfo createInfo = {
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
NULL,
0,
renderPass,
1,
attachment,
swapchainExtent.width,
swapchainExtent.height,
1
};
result = vkCreateFramebuffer(device, &createInfo, NULL, &swapchainFramebuffers[i]);
if(result != VK_SUCCESS){
printf("vkCreateFramebuffer failed\n");
exit(EXIT_FAILURE);
}
}
//------------------COMMAND-POOLS-----------------
VkCommandPool commandPool;
result = svlk_createCommandPool(device, graphicsQueue, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, &commandPool);
if(result != VK_SUCCESS){
printf("createCommandPool failed\n");
exit(EXIT_FAILURE);
}
VkCommandBuffer commandBuffer;
result = svlk_allocateCommandBuffer(device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1, &commandBuffer);
if(result != VK_SUCCESS){
printf("failed to allocate command buffer\n");
exit(EXIT_FAILURE);
}
//---------------RENDERING------------------------
int imageindex = 0;
VkClearValue clearcolor = {{{0.f,0.f,0.f,1.f}}};
VkRenderPassBeginInfo rpbinfo = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
NULL,
renderPass,
swapchainFramebuffers[imageindex],
{{0,0}, swapchainExtent},
1,
&clearcolor
};
vkCmdBeginRenderPass(commandBuffer, &rpbinfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
VkViewport viewport = svlk_viewportTemplate;
viewport.width = swapchainExtent.width;
viewport.height = swapchainExtent.height;
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor = {
{0,0},
swapchainExtent
};
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
vkCmdEndRenderPass(commandBuffer);
}