365 lines
11 KiB
C
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);
|
|
}
|