diff --git a/CMakeLists.txt b/CMakeLists.txt index 8766a46..15f9546 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,11 +4,11 @@ project(Informatikprojekt C) set(CMAKE_C_STANDARD 11) set(PROJECT_SOURCES particlesystem.h particlesystem.c utils.h utils.c) set(PROJECT_SOURCES_OPENGL ${PROJECT_SOURCES} initOpenGL.h initOpenGL.c utils.h glad/src/glad.c) -set(PROJECT_SOURCES_VULKAN ${PROJECT_SOURCES} initVulkan.h initVulkan.c) +set(PROJECT_SOURCES_VULKAN ${PROJECT_SOURCES} newVulkan/initVulkan.h newVulkan/initVulkan.c) add_executable(Informatikprojekt cpuMain.c ${PROJECT_SOURCES_OPENGL}) add_executable(Informatikprojekt_OpenGL openglMain.c ${PROJECT_SOURCES_OPENGL}) -add_executable(Informatikprojekt_Vulkan vulkanMain.c ${PROJECT_SOURCES_VULKAN}) +add_executable(Informatikprojekt_Vulkan newVulkan/vulkanMain.c ${PROJECT_SOURCES_VULKAN}) # Copy shader file to output directory ## OpenGL @@ -17,8 +17,8 @@ configure_file(./shaders/opengl/VertexShader.glsl ./opengl/VertexShader.glsl COP configure_file(./shaders/opengl/FragmentShader.glsl ./opengl/FragmentShader.glsl COPYONLY) ## Vulkan configure_file(./shaders/vulkan/ComputeShader.comp ./vulkan/ComputeShader.comp COPYONLY) -configure_file(./shaders/vulkan/VertexShader.vert ./vulkan/VertexShader.vert COPYONLY) -configure_file(./shaders/vulkan/FragmentShader.frag ./vulkan/FragmentShader.frag COPYONLY) +configure_file("shaders/vulkan/VertexShader.vert" ./vulkan/VertexShader.vert COPYONLY) +configure_file("shaders/vulkan/FragmentShader.frag" ./vulkan/FragmentShader.frag COPYONLY) configure_file(./shaders/vulkan/runCompiler.bat ./vulkan/runCompiler.bat COPYONLY) execute_process(COMMAND runCompiler.bat WORKING_DIRECTORY ./vulkan) diff --git a/glfw/include/GLFW/glfw3.h b/glfw/include/GLFW/glfw3.h index 66dff64..97914b6 100644 --- a/glfw/include/GLFW/glfw3.h +++ b/glfw/include/GLFW/glfw3.h @@ -882,9 +882,9 @@ extern "C" { * Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS). */ #define GLFW_ACCUM_ALPHA_BITS 0x0002100A -/*! @brief Framebuffer auxiliary buffer hint. +/*! @brief Framebuffer auxiliary Buffer hint. * - * Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS). + * Framebuffer auxiliary Buffer [hint](@ref GLFW_AUX_BUFFERS). */ #define GLFW_AUX_BUFFERS 0x0002100B /*! @brief OpenGL stereoscopic rendering hint. diff --git a/initVulkan.c b/initVulkan.c index c8e2635..5b3afa1 100644 --- a/initVulkan.c +++ b/initVulkan.c @@ -8,7 +8,7 @@ int initVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, createAppInfo(&appInfo); // VkInstanceCreateInfo - uint32_t amountOfLayers; + uint32_t amountOfLayers; vkEnumerateInstanceLayerProperties(&amountOfLayers, NULL); VkLayerProperties layers[amountOfLayers]; vkEnumerateInstanceLayerProperties(&amountOfLayers, layers); @@ -177,6 +177,13 @@ void createImageViewInfo(VkImageViewCreateInfo *imageViewInfo, VkImage *swapChai imageViewInfo->subresourceRange = subresourceRange; } +void createSemaphoreInfo(VkSemaphoreCreateInfo *semaphoreInfo) +{ + semaphoreInfo->sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO; + semaphoreInfo->pNext = NULL; + semaphoreInfo->flags = 0; +} + void createAttachmentDescription(VkAttachmentDescription *attachmentDescription) { attachmentDescription->flags = 0; @@ -276,19 +283,74 @@ void createCommandPoolInfo(VkCommandPoolCreateInfo *commandPoolInfo, uint32_t qu commandPoolInfo->queueFamilyIndex = queueFamilyIndex; } -void createCommandBufferAllocateInfo(VkCommandBufferAllocateInfo *commandBufferAllocateInfo) +void createCommandBufferAllocateInfo(VkCommandBufferAllocateInfo *commandBufferAllocateInfo, VkCommandPool *commandPool, uint32_t amountImages) { + commandBufferAllocateInfo->sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + commandBufferAllocateInfo->pNext = NULL; + commandBufferAllocateInfo->commandPool = *commandPool; + commandBufferAllocateInfo->level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + commandBufferAllocateInfo->commandBufferCount = amountImages; +} +void createCommandBufferBeginInfo(VkCommandBufferBeginInfo *commandBufferBeginInfo) +{ + commandBufferBeginInfo->sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + commandBufferBeginInfo->pNext = NULL; + commandBufferBeginInfo->flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; + commandBufferBeginInfo->pInheritanceInfo = NULL; +} + +void createRenderPassBeginInfo(VkRenderPassBeginInfo *renderPassBeginInfo, VkRenderPass *renderPass, VkFramebuffer *framebuffer) +{ + VkRect2D renderArea = { {0, 0}, {WIDTH, HEIGHT} }; + VkClearValue clearValue = {0, 0, 0, 1}; + + renderPassBeginInfo->sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassBeginInfo->pNext = NULL; + renderPassBeginInfo->renderPass = *renderPass; + renderPassBeginInfo->framebuffer = *framebuffer; + renderPassBeginInfo->renderArea = renderArea; + renderPassBeginInfo->clearValueCount = 1; + renderPassBeginInfo->pClearValues = &clearValue; +} + +void createBufferInfo(VkBufferCreateInfo *bufferCreateInfo, VkBufferUsageFlags usageFlags, VkDeviceSize size) +{ + bufferCreateInfo->sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferCreateInfo->pNext = NULL; + bufferCreateInfo->flags = 0; + bufferCreateInfo->size = size; + bufferCreateInfo->usage = usageFlags; + bufferCreateInfo->sharingMode = VK_SHARING_MODE_EXCLUSIVE; + bufferCreateInfo->queueFamilyIndexCount = 0; + bufferCreateInfo->pQueueFamilyIndices = NULL; +} + +void createMemoryAllocateInfo(VkMemoryAllocateInfo *memoryAllocateInfo, VkDeviceSize size, uint32_t memoryTypeIndex) +{ + memoryAllocateInfo->sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memoryAllocateInfo->pNext = NULL; + memoryAllocateInfo->allocationSize = size; + memoryAllocateInfo->memoryTypeIndex = memoryTypeIndex; } void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain, VkImageView *imageViews, uint32_t imageViewsSize, VkShaderModule *modules, uint32_t shaderModulesSize, VkPipelineLayout *pipelineLayouts, uint32_t pipelineLayoutsSize, VkRenderPass *renderPasses, uint32_t renderPassesSize, VkPipeline *pipelines, - uint32_t pipelinesSize, VkFramebuffer *framebuffers, VkCommandPool *commandPool) + uint32_t pipelinesSize, VkFramebuffer *framebuffers, VkCommandPool *commandPool, + VkCommandBuffer *commandBuffers, VkSemaphore *semaphores, uint32_t semaphoresSize) { vkDeviceWaitIdle(*device); + for (int i = 0; i < semaphoresSize; ++i) + { + vkDestroySemaphore(*device, semaphores[i], NULL); + } + + vkFreeCommandBuffers(*device, *commandPool, imageViewsSize, commandBuffers); + free(commandBuffers); + vkDestroyCommandPool(*device, *commandPool, NULL); for (int i = 0; i < imageViewsSize; ++i) diff --git a/initVulkan.h b/initVulkan.h index 3b686d0..2874103 100644 --- a/initVulkan.h +++ b/initVulkan.h @@ -1,5 +1,6 @@ #include #include +#include #include "vulkan/vulkan.h" #define GLFW_INCLUDE_VULKAN @@ -14,16 +15,11 @@ #define SUCCESS 0 #define FAILURE -1 -#define ASSERT_SUCCESS(res)\ - if (res != SUCCESS) { printf("Error-Code: %d", res); return FAILURE; } -#define ASSERT_VK_SUCCESS(res)\ - if (res != VK_SUCCESS) { printf("Error-Code: %d", res); return FAILURE; } -#define ASSERT_GLFW_SUCCESS(res)\ - if (res != GLFW_TRUE) { printf("Error-Code: %d", res); return FAILURE; } -#define BOOL_LITERAL(val)\ - val ? "True" : "False" -#define HUMAN_READABLE(val)\ - val * 9.313226e-10 +#define ASSERT_SUCCESS(res) { if (res != SUCCESS) { printf("Error-Code: %d", res); return FAILURE; } } +#define ASSERT_VK_SUCCESS(res) { if (res != VK_SUCCESS) { printf("Error-Code: %d", res); return FAILURE; } } +#define ASSERT_GLFW_SUCCESS(res) { if (res != GLFW_TRUE) { printf("Error-Code: %d", res); return FAILURE; } } +#define BOOL_LITERAL(val) val ? "True" : "False" +#define HUMAN_READABLE(val) val * 9.313226e-10 int initVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, GLFWwindow *window, VkSwapchainKHR *swapChain, VkImageView **imageViews, uint32_t *amountImages); @@ -53,6 +49,7 @@ void createSubpassDescription(VkSubpassDescription *subpassDescription, VkPipeli VkAttachmentReference *attachmentReference); void createRenderPassInfo(VkRenderPassCreateInfo *renderPassInfo, VkAttachmentDescription *attachmentDescriptions, VkSubpassDescription *subpassDescriptions); +void createSemaphoreInfo(VkSemaphoreCreateInfo *semaphoreInfo); void createGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo *graphicsPipelineInfo, VkPipelineShaderStageCreateInfo *shaderStages, VkPipelineVertexInputStateCreateInfo *vertexInputState, @@ -64,10 +61,14 @@ void createGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo *graphicsPipelineIn VkRenderPass *renderPass); void createFramebufferInfo(VkFramebufferCreateInfo *framebufferInfo, VkRenderPass *renderPass, VkImageView *imageView); void createCommandPoolInfo(VkCommandPoolCreateInfo *commandPoolInfo, uint32_t queueFamilyIndex); +void createCommandBufferAllocateInfo(VkCommandBufferAllocateInfo *commandBufferAllocateInfo, VkCommandPool *commandPool, uint32_t amountImages); +void createCommandBufferBeginInfo(VkCommandBufferBeginInfo *commandBufferBeginInfo); +void createRenderPassBeginInfo(VkRenderPassBeginInfo *renderPassBeginInfo, VkRenderPass *renderPass, VkFramebuffer *framebuffer); void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain, VkImageView *imageViews, uint32_t imageViewsSize, VkShaderModule *modules, uint32_t shaderModulesSize, VkPipelineLayout *pipelineLayouts, uint32_t pipelineLayoutsSize, VkRenderPass *renderPasses, uint32_t renderPassesSize, VkPipeline *pipelines, - uint32_t pipelinesSize, VkFramebuffer *framebuffers, VkCommandPool *commandPool); + uint32_t pipelinesSize, VkFramebuffer *framebuffers, VkCommandPool *commandPool, + VkCommandBuffer *commandBuffers, VkSemaphore *semaphores, uint32_t semaphoresSize); void shutdownGLFW(GLFWwindow *window); void printStats(VkPhysicalDevice *physicalDevice, VkSurfaceKHR *surface); diff --git a/newVulkan/initVulkan.c b/newVulkan/initVulkan.c new file mode 100644 index 0000000..019f1d6 --- /dev/null +++ b/newVulkan/initVulkan.c @@ -0,0 +1,477 @@ +#include "initVulkan.h" +#include + +void shutdownGLFW(GLFWwindow *window) +{ + glfwDestroyWindow(window); + glfwTerminate(); +} + +void createInstance(Compute *compute) +{ + GLuint glfwExtensionsSize; + const char **glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionsSize); + + VkApplicationInfo applicationInfo = {}; + applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + applicationInfo.pApplicationName = APP_NAME; + applicationInfo.applicationVersion = APP_VERSION; + applicationInfo.pEngineName = ENGINE_NAME; + applicationInfo.engineVersion = ENGINE_VERSION; + applicationInfo.apiVersion = VK_API_VERSION_1_2; + + VkInstanceCreateInfo instanceCreateInfo = {}; + instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instanceCreateInfo.flags = 0; + instanceCreateInfo.pApplicationInfo = &applicationInfo; + instanceCreateInfo.enabledLayerCount = 0; + instanceCreateInfo.ppEnabledLayerNames = NULL; + instanceCreateInfo.enabledExtensionCount = glfwExtensionsSize; + instanceCreateInfo.ppEnabledExtensionNames = glfwExtensions; + + ASSERT_VK(vkCreateInstance(&instanceCreateInfo, NULL, &(compute->instance))) +} + +void findPhysicalDevice(Compute *compute) +{ + uint32_t devicesSize; + vkEnumeratePhysicalDevices(compute->instance, &devicesSize, NULL); + + if (devicesSize <= 0) + { + printf("Fatal : No device found with Vulkan support!"); + assert(devicesSize > 0); + } + + VkPhysicalDevice physicalDevices[devicesSize]; + vkEnumeratePhysicalDevices(compute->instance, &devicesSize, physicalDevices); + + for (int i = 0; i < devicesSize; ++i) + { + VkPhysicalDeviceProperties deviceProperties = {}; + vkGetPhysicalDeviceProperties(physicalDevices[i], &deviceProperties); + + if (WORKGROUP_SIZE_X <= deviceProperties.limits.maxComputeWorkGroupSize[0] + && PARTICLE_AMOUNT / WORKGROUP_SIZE_X <= deviceProperties.limits.maxComputeWorkGroupCount[0] + && PARTICLE_SIZE * PARTICLE_AMOUNT <= deviceProperties.limits.maxStorageBufferRange) + { + compute->physicalDevice = physicalDevices[i]; + break; + } + } + + if (!compute->physicalDevice) + { + printf("Fatal : No device found with capable limits!"); + assert(compute->physicalDevice); + } +} + +uint32_t getQueueFamilyIndex(Compute *compute, VkQueueFlagBits queueFlagBits) +{ + uint32_t queueFamiliesSize; + vkGetPhysicalDeviceQueueFamilyProperties(compute->physicalDevice, &queueFamiliesSize, NULL); + VkQueueFamilyProperties queueFamilies[queueFamiliesSize]; + vkGetPhysicalDeviceQueueFamilyProperties(compute->physicalDevice, &queueFamiliesSize, queueFamilies); + + for (uint32_t i = 0; i < queueFamiliesSize; ++i) + { + if (queueFamilies[i].queueCount > 0 + && queueFamilies[i].queueFlags & queueFlagBits) + { + return i; + } + } + + return -1; +} + +void createDevice(Compute *compute) +{ + compute->queueFamilyIndex = getQueueFamilyIndex(compute, VK_QUEUE_COMPUTE_BIT); + + if (compute->queueFamilyIndex < 0) + { + printf("Fatal: Could not find a queue family with capability of computing!"); + assert(compute->queueFamilyIndex >= 0); + } + + VkDeviceQueueCreateInfo deviceQueueCreateInfo = {}; + deviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + deviceQueueCreateInfo.queueFamilyIndex = compute->queueFamilyIndex; + deviceQueueCreateInfo.queueCount = 1; + deviceQueueCreateInfo.pQueuePriorities = NULL; + + VkPhysicalDeviceFeatures physicalDeviceFeatures = {}; + + VkDeviceCreateInfo deviceCreateInfo = {}; + deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + deviceCreateInfo.pQueueCreateInfos = &deviceQueueCreateInfo; + deviceCreateInfo.queueCreateInfoCount = 1; + deviceCreateInfo.pEnabledFeatures = &physicalDeviceFeatures; + + ASSERT_VK(vkCreateDevice(compute->physicalDevice, &deviceCreateInfo, NULL, &(compute->device))) + + vkGetDeviceQueue(compute->device, compute->queueFamilyIndex, 0, &(compute->queue)); +} + +uint32_t findMemoryType(Compute *compute, uint32_t memoryTypeBits, VkMemoryPropertyFlags properties) +{ + VkPhysicalDeviceMemoryProperties memoryProperties; + vkGetPhysicalDeviceMemoryProperties(compute->physicalDevice, &memoryProperties); + + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) + { + if ((memoryTypeBits & (1u << i)) + && ((memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)) + return i; + } + + return -1; +} + +void createComputeBuffer(Compute *compute, uint32_t bufferSize, VkBufferUsageFlags usageFlags, VkBuffer *buffer, + VkDeviceMemory *bufferMemory, VkMemoryPropertyFlags memoryPropertyFlags) +{ + + VkBufferCreateInfo particleBufferCreateInfo = {}; + particleBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + particleBufferCreateInfo.size = bufferSize; + particleBufferCreateInfo.usage = usageFlags; + particleBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + ASSERT_VK(vkCreateBuffer(compute->device, &particleBufferCreateInfo, NULL, buffer)) + + VkMemoryRequirements particleBufferMemoryRequirements; + vkGetBufferMemoryRequirements(compute->device, *buffer, &particleBufferMemoryRequirements); + + VkMemoryAllocateInfo particleMemoryAllocateInfo = {}; + particleMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + particleMemoryAllocateInfo.allocationSize = particleBufferMemoryRequirements.size; + particleMemoryAllocateInfo.memoryTypeIndex = findMemoryType(compute, + particleBufferMemoryRequirements.memoryTypeBits, + memoryPropertyFlags); + + ASSERT_VK(vkAllocateMemory(compute->device, &particleMemoryAllocateInfo, NULL, bufferMemory)) + + ASSERT_VK(vkBindBufferMemory(compute->device, *buffer, *bufferMemory, 0)) +} + +void createComputeBuffers(Compute *compute) +{ + // Particle Buffer + createComputeBuffer(compute, compute->particleBufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + &(compute->particleBuffer), + &(compute->particleBufferMemory), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + // dt Uniform Buffer + createComputeBuffer(compute, compute->dtUniformBufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + &(compute->dtUniformBuffer), + &(compute->dtUniformBufferMemory), + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + // staticIn Uniform Buffer + createComputeBuffer(compute, compute->staticInUniformBufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + &(compute->staticInUniformBuffer), + &(compute->staticInUniformBufferMemory), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + +} + +void createComputeDescriptorSetLayout(Compute *compute, uint32_t binding, VkDescriptorType descriptorType, VkDescriptorSetLayout *descriptorSetLayout) +{ + VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {}; + descriptorSetLayoutBinding.binding = binding; + descriptorSetLayoutBinding.descriptorType = descriptorType; + descriptorSetLayoutBinding.descriptorCount = 1; + descriptorSetLayoutBinding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {}; + descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptorSetLayoutCreateInfo.bindingCount = 1; + descriptorSetLayoutCreateInfo.pBindings = &descriptorSetLayoutBinding; + + ASSERT_VK(vkCreateDescriptorSetLayout(compute->device, &descriptorSetLayoutCreateInfo, NULL, descriptorSetLayout)) +} + +void createComputeDescriptorSetLayouts(Compute *compute) +{ + // Particle Buffer + createComputeDescriptorSetLayout(compute, 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + &(compute->particleBufferDescriptorSetLayout)); + + // dt Uniform Buffer + createComputeDescriptorSetLayout(compute, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + &(compute->dtUniformBufferDescriptorSetLayout)); + + // staticIn Uniform Buffer + createComputeDescriptorSetLayout(compute, 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + &(compute->staticInUniformBufferDescriptorSetLayout)); +} + +void createComputeDescriptorSet(Compute *compute, VkDescriptorType descriptorType, VkDescriptorPool *descriptorPool, + VkDescriptorSetLayout *descriptorSetLayout, VkDescriptorSet *descriptorSet, + VkBuffer buffer, uint32_t bufferSize) +{ + VkDescriptorPoolSize descriptorPoolSize = {}; + descriptorPoolSize.type = descriptorType; + descriptorPoolSize.descriptorCount = 1; + + VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {}; + descriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptorPoolCreateInfo.maxSets = 1; + descriptorPoolCreateInfo.poolSizeCount = 1; + descriptorPoolCreateInfo.pPoolSizes = &descriptorPoolSize; + + ASSERT_VK(vkCreateDescriptorPool(compute->device, &descriptorPoolCreateInfo, NULL, descriptorPool)) + + VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {}; + descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + descriptorSetAllocateInfo.descriptorPool = *descriptorPool; + descriptorSetAllocateInfo.descriptorSetCount = 1; + descriptorSetAllocateInfo.pSetLayouts = descriptorSetLayout; + + ASSERT_VK(vkAllocateDescriptorSets(compute->device, &descriptorSetAllocateInfo, descriptorSet)) + + VkDescriptorBufferInfo descriptorBufferInfo = {}; + descriptorBufferInfo.buffer = buffer; + descriptorBufferInfo.offset = 0; + descriptorBufferInfo.range = bufferSize; + + VkWriteDescriptorSet writeDescriptorSet = {}; + writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSet.dstSet = *descriptorSet; + writeDescriptorSet.dstBinding = 0; + writeDescriptorSet.descriptorCount = 1; + writeDescriptorSet.descriptorType = descriptorType; + writeDescriptorSet.pBufferInfo = &descriptorBufferInfo; + + vkUpdateDescriptorSets(compute->device, 1, &writeDescriptorSet, 0, NULL); +} + +void createComputeDescriptorSets(Compute *compute) +{ + // Particle Buffer + createComputeDescriptorSet(compute, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &(compute->particleBufferDescriptorPool), + &(compute->particleBufferDescriptorSetLayout), &(compute->particleBufferDescriptorSet), + compute->particleBuffer, compute->particleBufferSize); + + // dt Uniform Buffer + createComputeDescriptorSet(compute, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &(compute->dtUniformBufferDescriptorPool), + &(compute->dtUniformBufferDescriptorSetLayout), &(compute->dtUniformBufferDescriptorSet), + compute->dtUniformBuffer, compute->dtUniformBufferSize); + + // staticIn Uniform Buffer + createComputeDescriptorSet(compute, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + &(compute->staticInUniformBufferDescriptorPool), + &(compute->staticInUniformBufferDescriptorSetLayout), + &(compute->staticInUniformBufferDescriptorSet), + compute->staticInUniformBuffer, compute->staticInUniformBufferSize); +} + +void createComputePipeline(Compute *compute) +{ + long computeShaderSourceSize; + char *computeShaderSource = readFile("./vulkan/comp.spv", "rb", &computeShaderSourceSize); + + VkShaderModuleCreateInfo shaderModuleCreateInfo = {}; + shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shaderModuleCreateInfo.pCode = (uint32_t *) computeShaderSource; + shaderModuleCreateInfo.codeSize = computeShaderSourceSize; + + ASSERT_VK(vkCreateShaderModule(compute->device, &shaderModuleCreateInfo, NULL, &(compute->shaderModule))) + + free(computeShaderSource); + + VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo = {}; + pipelineShaderStageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + pipelineShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + pipelineShaderStageCreateInfo.module = compute->shaderModule; + pipelineShaderStageCreateInfo.pName = "main"; + + VkDescriptorSetLayout descriptorSetLayouts[] = { + compute->particleBufferDescriptorSetLayout, + compute->dtUniformBufferDescriptorSetLayout, + compute->staticInUniformBufferDescriptorSetLayout + }; + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {}; + pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutCreateInfo.setLayoutCount = 3; + pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts; + + ASSERT_VK(vkCreatePipelineLayout(compute->device, &pipelineLayoutCreateInfo, NULL, &(compute->pipelineLayout))); + + VkComputePipelineCreateInfo pipelineCreateInfo = {}; + pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipelineCreateInfo.stage = pipelineShaderStageCreateInfo; + pipelineCreateInfo.layout = compute->pipelineLayout; + + ASSERT_VK(vkCreateComputePipelines(compute->device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, NULL, &(compute->pipeline))) +} + +void mapBufferMemory(Compute *compute, VkDeviceMemory memory, void *inputData, uint32_t dataSize) +{ + void *vkData; + vkMapMemory(compute->device, memory, 0, dataSize, 0, &vkData); + memcpy(vkData, inputData, dataSize); + vkUnmapMemory(compute->device, memory); +} + +void copyBuffer(Compute *compute, VkBuffer src, VkBuffer dst, VkDeviceSize size) +{ + uint32_t queueFamilyIndex = getQueueFamilyIndex(compute, VK_QUEUE_TRANSFER_BIT); + + VkCommandPoolCreateInfo commandPoolCreateInfo = {}; + commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + commandPoolCreateInfo.flags = 0; + commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex; + + VkCommandPool stagingCommandPool; + ASSERT_VK(vkCreateCommandPool(compute->device, &commandPoolCreateInfo, NULL, &stagingCommandPool)) + + VkCommandBufferAllocateInfo allocInfo = {}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandPool = stagingCommandPool; + allocInfo.commandBufferCount = 1; + + VkCommandBuffer stagingCommandBuffer; + ASSERT_VK(vkAllocateCommandBuffers(compute->device, &allocInfo, &stagingCommandBuffer)) + + VkCommandBufferBeginInfo beginInfo = {}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + ASSERT_VK(vkBeginCommandBuffer(stagingCommandBuffer, &beginInfo)) + + VkBufferCopy copyRegion = { .size = size }; + vkCmdCopyBuffer(stagingCommandBuffer, src, dst, 1, ©Region); + + ASSERT_VK(vkEndCommandBuffer(stagingCommandBuffer)) + + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &stagingCommandBuffer; + + VkQueue stagingQueue; + vkGetDeviceQueue(compute->device, queueFamilyIndex, 0, &stagingQueue); + + vkQueueSubmit(stagingQueue, 1, &submitInfo, VK_NULL_HANDLE); + vkQueueWaitIdle(stagingQueue); + + vkFreeCommandBuffers(compute->device, stagingCommandPool, 1, &stagingCommandBuffer); +} + +void fillComputeBuffer(Compute *compute, VkBuffer dst, void *data, uint32_t dataSize) +{ + VkBuffer stagingBuffer; + VkDeviceMemory stagingBuggerMemory; + createComputeBuffer(compute, compute->particleBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &stagingBuffer, &stagingBuggerMemory, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + mapBufferMemory(compute, stagingBuggerMemory, data, dataSize); + + copyBuffer(compute, stagingBuffer, dst, dataSize); +} + +void fillComputeBuffers(Compute *compute, float *particles, Dt *dtData, StaticIn *staticInData) +{ + // Particle Buffer + fillComputeBuffer(compute, compute->particleBuffer, particles, compute->particleBufferSize); + + // dt Buffer + mapBufferMemory(compute, compute->dtUniformBufferMemory, dtData, compute->dtUniformBufferSize); + + // staticIn Buffer + fillComputeBuffer(compute, compute->staticInUniformBuffer, staticInData, compute->staticInUniformBufferSize); +} + +void createComputeCommandBuffer(Compute *compute) +{ + VkCommandPoolCreateInfo commandPoolCreateInfo = {}; + commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + commandPoolCreateInfo.flags = 0; + commandPoolCreateInfo.queueFamilyIndex = compute->queueFamilyIndex; + + ASSERT_VK(vkCreateCommandPool(compute->device, &commandPoolCreateInfo, NULL, &(compute->commandPool))) + + VkCommandBufferAllocateInfo commandBufferAllocateInfo = {}; + commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + commandBufferAllocateInfo.commandPool = compute->commandPool; + commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + commandBufferAllocateInfo.commandBufferCount = 1; + + ASSERT_VK(vkAllocateCommandBuffers(compute->device, &commandBufferAllocateInfo, &(compute->commandBuffer))) + + VkCommandBufferBeginInfo beginInfo = {}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; + + ASSERT_VK(vkBeginCommandBuffer(compute->commandBuffer, &beginInfo)) + + vkCmdBindPipeline(compute->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute->pipeline); + VkDescriptorSet descriptorSets[] = { + compute->particleBufferDescriptorSet, + compute->dtUniformBufferDescriptorSet, + compute->staticInUniformBufferDescriptorSet, + }; + vkCmdBindDescriptorSets(compute->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute->pipelineLayout, 0, 3, + descriptorSets, 0, NULL); + + vkCmdDispatch(compute->commandBuffer, WORKGROUP_SIZE_X, WORKGROUP_SIZE_Y, WORKGROUP_SIZE_Z); + + ASSERT_VK(vkEndCommandBuffer(compute->commandBuffer)) +} + +void runComputeCommandBuffer(Compute *compute) +{ + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &(compute->commandBuffer); + + VkFence fence; + VkFenceCreateInfo fenceCreateInfo = {}; + fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceCreateInfo.flags = 0; + + ASSERT_VK(vkCreateFence(compute->device, &fenceCreateInfo, NULL, &fence)) + + ASSERT_VK(vkQueueSubmit(compute->queue, 1, &submitInfo, fence)) + + ASSERT_VK(vkWaitForFences(compute->device, 1, &fence, VK_TRUE, UINT64_MAX)); + + vkDestroyFence(compute->device, fence, NULL); +} + +void shutdownComputeVulkan(Compute *compute) +{ + vkFreeMemory(compute->device, compute->particleBufferMemory, NULL); + vkFreeMemory(compute->device, compute->dtUniformBufferMemory, NULL); + vkFreeMemory(compute->device, compute->staticInUniformBufferMemory, NULL); + + vkDestroyBuffer(compute->device, compute->particleBuffer, NULL); + vkDestroyBuffer(compute->device, compute->dtUniformBuffer, NULL); + vkDestroyBuffer(compute->device, compute->staticInUniformBuffer, NULL); + + vkDestroyShaderModule(compute->device, compute->shaderModule, NULL); + + vkDestroyDescriptorPool(compute->device, compute->particleBufferDescriptorPool, NULL); + vkDestroyDescriptorPool(compute->device, compute->dtUniformBufferDescriptorPool, NULL); + vkDestroyDescriptorPool(compute->device, compute->staticInUniformBufferDescriptorPool, NULL); + + vkDestroyDescriptorSetLayout(compute->device, compute->particleBufferDescriptorSetLayout, NULL); + vkDestroyDescriptorSetLayout(compute->device, compute->dtUniformBufferDescriptorSetLayout, NULL); + vkDestroyDescriptorSetLayout(compute->device, compute->staticInUniformBufferDescriptorSetLayout, NULL); + + vkDestroyPipelineLayout(compute->device, compute->pipelineLayout, NULL); + + vkDestroyPipeline(compute->device, compute->pipeline, NULL); + + vkDestroyCommandPool(compute->device, compute->commandPool, NULL); + + vkDestroyDevice(compute->device, NULL); + + vkDestroyInstance(compute->instance, NULL); +} diff --git a/newVulkan/initVulkan.h b/newVulkan/initVulkan.h new file mode 100644 index 0000000..4465157 --- /dev/null +++ b/newVulkan/initVulkan.h @@ -0,0 +1,116 @@ +#include +#include +#include +#include "vulkan/vulkan.h" + +#define GLFW_INCLUDE_VULKAN +#include "GLFW/glfw3.h" + +#include "../particlesystem.h" +#include "../utils.h" + +#define APP_NAME "Informatikprojekt - Vulkan" +#define APP_VERSION VK_MAKE_VERSION(0, 0, 0) +#define ENGINE_NAME "rwu_particles" +#define ENGINE_VERSION VK_MAKE_VERSION(0, 0, 0) + +#define PARTICLE_AMOUNT 10 +#define PARTICLE_SIZE (3 * sizeof(vector3f) + sizeof(float)) +#define WORKGROUP_SIZE_X 256 +#define WORKGROUP_SIZE_Y 1 +#define WORKGROUP_SIZE_Z 1 + +#define SUCCESS 0 +#define FAILURE -1 +#define ASSERT_VK(f) { \ + VkResult res = (f); \ + if (res != VK_SUCCESS) { \ + printf("Fatal : VkResult is %d in %s at line %d\n", res, __FILE__, __LINE__); \ + assert(res == VK_SUCCESS); \ + } \ +} +#define ASSERT_GLFW_SUCCESS(res) { if (res != GLFW_TRUE) { printf("Error-Code: %d", res); return FAILURE; } } + +typedef struct compute { + VkInstance instance; + + VkPhysicalDevice physicalDevice; + VkDevice device; + + VkPipeline pipeline; + VkPipelineLayout pipelineLayout; + VkShaderModule shaderModule; + + VkCommandPool commandPool; + VkCommandBuffer commandBuffer; + + VkDescriptorPool particleBufferDescriptorPool; + VkDescriptorSet particleBufferDescriptorSet; + VkDescriptorSetLayout particleBufferDescriptorSetLayout; + VkBuffer particleBuffer; + VkDeviceMemory particleBufferMemory; + uint32_t particleBufferSize; + + VkDescriptorPool dtUniformBufferDescriptorPool; + VkDescriptorSet dtUniformBufferDescriptorSet; + VkDescriptorSetLayout dtUniformBufferDescriptorSetLayout; + VkBuffer dtUniformBuffer; + VkDeviceMemory dtUniformBufferMemory; + uint32_t dtUniformBufferSize; + + VkDescriptorPool staticInUniformBufferDescriptorPool; + VkDescriptorSet staticInUniformBufferDescriptorSet; + VkDescriptorSetLayout staticInUniformBufferDescriptorSetLayout; + VkBuffer staticInUniformBuffer; + VkDeviceMemory staticInUniformBufferMemory; + uint32_t staticInUniformBufferSize; + + VkQueue queue; + uint32_t queueFamilyIndex; +} Compute; + +typedef struct graphics { + VkInstance instance; + + VkPhysicalDevice physicalDevice; + VkDevice device; + + VkPipeline pipeline; + VkPipelineLayout pipelineLayout; + VkShaderModule shaderModule; + + VkCommandPool commandPool; + VkCommandBuffer commandBuffer; + + VkQueue queue; + uint32_t queueFamilyIndex; +} Graphics; + +typedef struct dt { + float dt; +} Dt; + +typedef struct staticIn { + float x, y, z; + unsigned int maxParticles; +} StaticIn; + +// Shutdown +void shutdownGLFW(GLFWwindow *window); +void shutdownComputeVulkan(Compute *compute); + +void createInstance(Compute *compute); +void findPhysicalDevice(Compute *compute); +void createDevice(Compute *compute); + +// Compute +void createComputeBuffers(Compute *compute); +void createComputeDescriptorSetLayouts(Compute *compute); +void createComputeDescriptorSets(Compute *compute); +void createComputePipeline(Compute *compute); +void fillComputeBuffers(Compute *compute, float *particles, Dt *dtData, StaticIn *staticInData); +void createComputeCommandBuffer(Compute *compute); +void runComputeCommandBuffer(Compute *compute); + +// ELse +void mapBufferMemory(Compute *compute, VkDeviceMemory memory, void *inputData, uint32_t dataSize); diff --git a/newVulkan/vulkanMain.c b/newVulkan/vulkanMain.c new file mode 100644 index 0000000..3fe8474 --- /dev/null +++ b/newVulkan/vulkanMain.c @@ -0,0 +1,77 @@ +#include + +#include "initVulkan.h" + +int main() +{ + /************* PARTICLE SYSTEM *************/ + vector3f *epos1 = initVector3f(0, 0, 0); + emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT); + particle_system *ps = initParticleSystem(1); + (ps->emitters)[0] = e1; + initRandomParticles(e1); + float *particles = serializeParticlesystem(ps); + freeParticleSystem(ps); + + Dt dt = { 0.5f }; + StaticIn staticIn = { + e1->position->x, + e1->position->y, + e1->position->z, + PARTICLE_AMOUNT + }; + + /************* INIT GLFW *************/ + ASSERT_GLFW_SUCCESS(glfwInit()); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Informatikprojekt - Vulkan", NULL, NULL); + + /************* INIT VULKAN *************/ + // Compute + Compute compute = { + .particleBufferSize = PARTICLE_SIZE * PARTICLE_AMOUNT, + .staticInUniformBufferSize = sizeof(StaticIn), + .dtUniformBufferSize = sizeof(Dt) + }; + createInstance(&compute); + findPhysicalDevice(&compute); + createDevice(&compute); + createComputeBuffers(&compute); + createComputeDescriptorSetLayouts(&compute); + createComputeDescriptorSets(&compute); + createComputePipeline(&compute); + fillComputeBuffers(&compute, particles, &dt, &staticIn); + createComputeCommandBuffer(&compute); + + // Graphics + Graphics graphics = { + .instance = compute.instance, + .physicalDevice = compute.physicalDevice, + .device = compute.device, + }; + + /************* RENDER LOOP *************/ + double time, tLast = 0; + Dt tFrame = { 1.0f }; + while (!glfwWindowShouldClose(window)) + { + time = glfwGetTime(); + tFrame.dt = (float) (time - tLast); + tLast = time; + + // Update dt + mapBufferMemory(&compute, compute.dtUniformBufferMemory, &tFrame, sizeof(Dt)); + + /*** UPDATE ***/ + runComputeCommandBuffer(&compute); + + /*** RENDER ***/ + + glfwPollEvents(); + } + + shutdownComputeVulkan(&compute); + shutdownGLFW(window); +} + diff --git a/openglMain.c b/openglMain.c index cb26cb0..93541d6 100644 --- a/openglMain.c +++ b/openglMain.c @@ -3,7 +3,7 @@ #include "initOpenGL.h" #include "utils.h" -#define PARTICLE_AMOUNT 10000000 +#define PARTICLE_AMOUNT 15000000 int main() { @@ -107,6 +107,7 @@ int main() deleteShaders(computeShaders, 1); glDeleteProgram(computeShaderProgram); glDeleteBuffers(1, &particleBuffer); + glDeleteVertexArrays(1, &vertexArray); terminateGLFW(window); return 0; diff --git a/vulkanMain.c b/vulkanMain.c index 459c86d..5102ebe 100644 --- a/vulkanMain.c +++ b/vulkanMain.c @@ -1,11 +1,41 @@ #include -#include #include "initVulkan.h" #include "particlesystem.h" #define PARTICLE_AMOUNT 0 +void drawFrame(); + +typedef struct compute { + VkInstance instance; + VkDebugReportCallbackEXT debugReportCallback; + + VkPhysicalDevice physicalDevice; + VkDevice device; + + VkPipeline pipeline; + VkPipelineLayout pipelineLayout; + VkShaderModule shaderModule; + + VkCommandPool commandPool; + VkCommandBuffer commandBuffer; + + VkDescriptorPool descriptorPool; + VkDescriptorSet descriptorSet; + VkDescriptorSetLayout descriptorSetLayout; + + VkBuffer buffer; + VkDeviceMemory bufferMemory; + uint32_t bufferSize; + + const char **enabledLayer; + + VkQueue queue; + uint32_t queueFamilyIndex; +} Compute; + + int main() { VkInstance vkInstance; @@ -19,6 +49,9 @@ int main() VkPipeline pipeline; VkFramebuffer *framebuffers; VkCommandPool commandPool; + VkCommandBuffer *commandBuffers; + VkSemaphore imageAvailable; + VkSemaphore renderingFinished; /************* INIT *************/ // GLFW @@ -59,7 +92,8 @@ int main() VkPipelineShaderStageCreateInfo fragmentShaderStageInfo; createShaderStageInfo(&fragmentShaderStageInfo, VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderModule, "main"); - VkPipelineShaderStageCreateInfo shaderStages[3] = { computeShaderStageInfo, vertexShaderStageInfo, fragmentShaderStageInfo }; + VkPipelineShaderStageCreateInfo shaderStages[3] = {computeShaderStageInfo, vertexShaderStageInfo, + fragmentShaderStageInfo}; /************* PIPELINE *************/ // Vertex input @@ -133,18 +167,54 @@ int main() // Allocate info VkCommandBufferAllocateInfo commandBufferAllocateInfo; + createCommandBufferAllocateInfo(&commandBufferAllocateInfo, &commandPool, imageViewsSize); + // Command buffers + commandBuffers = malloc(imageViewsSize * sizeof(VkCommandBuffer)); + ASSERT_VK_SUCCESS(vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, commandBuffers)) + + // Begin Info command buffers + VkCommandBufferBeginInfo commandBufferBeginInfo; + createCommandBufferBeginInfo(&commandBufferBeginInfo); + + for (int i = 0; i < imageViewsSize; ++i) + { + ASSERT_VK_SUCCESS(vkBeginCommandBuffer(commandBuffers[i], &commandBufferBeginInfo)) + + VkRenderPassBeginInfo renderPassBeginInfo; + createRenderPassBeginInfo(&renderPassBeginInfo, &renderPass, &framebuffers[i]); + + vkCmdBeginRenderPass(commandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + vkCmdDraw(commandBuffers[i], 3, 1, 0, 0); + + vkCmdEndRenderPass(commandBuffers[i]); + + ASSERT_VK_SUCCESS(vkEndCommandBuffer(commandBuffers[i])) + } + + // Semaphores + VkSemaphoreCreateInfo semaphoreInfo; + createSemaphoreInfo(&semaphoreInfo); + + ASSERT_VK_SUCCESS(vkCreateSemaphore(device, &semaphoreInfo, NULL, &imageAvailable)) + ASSERT_VK_SUCCESS(vkCreateSemaphore(device, &semaphoreInfo, NULL, &renderingFinished)) /************* RENDER LOOP *************/ while (!glfwWindowShouldClose(window)) { glfwPollEvents(); + drawFrame(); } + // Shutdown Vulkan - VkShaderModule modules[3] = { computeShaderModule, vertexShaderModule, fragmentShaderModule }; + VkShaderModule modules[3] = {computeShaderModule, vertexShaderModule, fragmentShaderModule}; + VkSemaphore semaphores[2] = {imageAvailable, renderingFinished}; shutdownVulkan(&vkInstance, &device, &surface, &swapChain, imageViews, imageViewsSize, modules, 3, &pipelineLayout, 1, - &renderPass, 1, &pipeline, 1, framebuffers, &commandPool); + &renderPass, 1, &pipeline, 1, framebuffers, &commandPool, commandBuffers, semaphores, 2); // Shutdown GLFW shutdownGLFW(window); @@ -152,4 +222,11 @@ int main() return SUCCESS; } +void drawFrame(VkDevice *device, VkSwapchainKHR *swapchainKhr, VkSemaphore *imageAvailable, VkSemaphore *renderingFinished) +{ + uint32_t imageIndex; + vkAcquireNextImageKHR(*device, *swapchainKhr, UINT64_MAX, *imageAvailable, VK_NULL_HANDLE, &imageIndex); +} + +