Cleaned up
This commit is contained in:
parent
8c77f36f6a
commit
1ba5d33634
@ -4,11 +4,11 @@ project(Informatikprojekt C)
|
|||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(PROJECT_SOURCES particlesystem.h particlesystem.c utils.h utils.c)
|
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_OPENGL ${PROJECT_SOURCES} initOpenGL.h initOpenGL.c utils.h glad/src/glad.c)
|
||||||
set(PROJECT_SOURCES_VULKAN ${PROJECT_SOURCES} newVulkan/initVulkan.h newVulkan/initVulkan.c)
|
set(PROJECT_SOURCES_VULKAN ${PROJECT_SOURCES} initVulkan.h initVulkan.c)
|
||||||
|
|
||||||
add_executable(Informatikprojekt cpuMain.c ${PROJECT_SOURCES_OPENGL})
|
add_executable(Informatikprojekt cpuMain.c ${PROJECT_SOURCES_OPENGL})
|
||||||
add_executable(Informatikprojekt_OpenGL openglMain.c ${PROJECT_SOURCES_OPENGL})
|
add_executable(Informatikprojekt_OpenGL openglMain.c ${PROJECT_SOURCES_OPENGL})
|
||||||
add_executable(Informatikprojekt_Vulkan newVulkan/vulkanMain.c ${PROJECT_SOURCES_VULKAN})
|
add_executable(Informatikprojekt_Vulkan vulkanMain.c ${PROJECT_SOURCES_VULKAN})
|
||||||
|
|
||||||
# Copy shader file to output directory
|
# Copy shader file to output directory
|
||||||
## OpenGL
|
## OpenGL
|
||||||
|
1358
initVulkan.c
1358
initVulkan.c
File diff suppressed because it is too large
Load Diff
183
initVulkan.h
183
initVulkan.h
@ -1,11 +1,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdint-gcc.h>
|
#include <assert.h>
|
||||||
#include "vulkan/vulkan.h"
|
#include "vulkan/vulkan.h"
|
||||||
|
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
#include "GLFW/glfw3.h"
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
|
#include "particlesystem.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define APP_NAME "Informatikprojekt - Vulkan"
|
#define APP_NAME "Informatikprojekt - Vulkan"
|
||||||
@ -13,62 +14,134 @@
|
|||||||
#define ENGINE_NAME "rwu_particles"
|
#define ENGINE_NAME "rwu_particles"
|
||||||
#define ENGINE_VERSION VK_MAKE_VERSION(0, 0, 0)
|
#define ENGINE_VERSION VK_MAKE_VERSION(0, 0, 0)
|
||||||
|
|
||||||
|
#define PARTICLE_AMOUNT 1000000
|
||||||
|
#define PARTICLE_SIZE (3 * sizeof(vector3f) + sizeof(float))
|
||||||
|
#define WORKGROUP_SIZE_X 1024
|
||||||
|
#define WORKGROUP_SIZE_Y 1
|
||||||
|
#define WORKGROUP_SIZE_Z 1
|
||||||
|
|
||||||
#define SUCCESS 0
|
#define SUCCESS 0
|
||||||
#define FAILURE -1
|
#define FAILURE -1
|
||||||
#define ASSERT_SUCCESS(res) { if (res != SUCCESS) { printf("Error-Code: %d", res); return FAILURE; } }
|
#define ASSERT_VK(f) { \
|
||||||
#define ASSERT_VK_SUCCESS(res) { if (res != VK_SUCCESS) { printf("Error-Code: %d", res); return FAILURE; } }
|
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; } }
|
#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,
|
typedef struct dt {
|
||||||
VkSwapchainKHR *swapChain, VkImageView **imageViews, uint32_t *amountImages);
|
float dt;
|
||||||
void createAppInfo(VkApplicationInfo *appInfo);
|
} Dt;
|
||||||
void createInstanceInfo(VkApplicationInfo *appInfo, VkInstanceCreateInfo *instanceInfo);
|
|
||||||
void createQueueInfo(VkDeviceQueueCreateInfo *queueInfo);
|
typedef struct staticIn {
|
||||||
void createDeviceInfo(VkDeviceQueueCreateInfo *queueInfo, VkDeviceCreateInfo *deviceInfo,
|
float x;
|
||||||
VkPhysicalDeviceFeatures *features);
|
float y;
|
||||||
void createImageViewInfo(VkImageViewCreateInfo *imageViewInfo, VkImage *swapChainImages, int index);
|
float z;
|
||||||
void createSwapChainInfo(VkSwapchainCreateInfoKHR *swapChainCreateInfo, VkSurfaceKHR *surface);
|
unsigned int maxParticles;
|
||||||
void createShaderStageInfo(VkPipelineShaderStageCreateInfo *shaderStageInfo, VkShaderStageFlagBits shaderStageBit,
|
} StaticIn;
|
||||||
VkShaderModule shaderModule, const char *entryPointName);
|
|
||||||
int createShaderModule(VkDevice device, VkShaderModule *shaderModule, const char *shaderSource, long sourceSize);
|
typedef struct compute {
|
||||||
void createPipelineVertexInputStateInfo(VkPipelineVertexInputStateCreateInfo *vertexInputStateInfo,
|
VkInstance instance;
|
||||||
VkVertexInputAttributeDescription *attributes, uint32_t atrributesSize);
|
|
||||||
void createInputAssemblyStateInfo(VkPipelineInputAssemblyStateCreateInfo *inputAssemblyStateInfo, VkPrimitiveTopology topology);
|
VkPhysicalDevice physicalDevice;
|
||||||
void createViewportStateInfo(VkPipelineViewportStateCreateInfo *viewportStateInfo, float width, float height);
|
VkDevice device;
|
||||||
void createRasterizationStateInfo(VkPipelineRasterizationStateCreateInfo *rasterizationStateInfo, VkPolygonMode polygonMode);
|
|
||||||
void createMultisampleStateInfo(VkPipelineMultisampleStateCreateInfo *multisampleStateInfo);
|
VkPipeline pipeline;
|
||||||
void createColorBlendAttachmentStateInfo(VkPipelineColorBlendAttachmentState *colorBlendAttachmentState);
|
VkPipelineLayout pipelineLayout;
|
||||||
void createColorBlendStateInfo(VkPipelineColorBlendStateCreateInfo *colorBlendStateInfo,
|
VkShaderModule shaderModule;
|
||||||
VkPipelineColorBlendAttachmentState *blendAttachments, uint32_t blendAttachmentsSize);
|
|
||||||
void createLayoutInfo(VkPipelineLayoutCreateInfo *layoutInfo, VkDescriptorSetLayout *setLayouts, uint32_t setLayoutSize);
|
VkCommandPool commandPool;
|
||||||
void createAttachmentDescription(VkAttachmentDescription *attachmentDescription);
|
VkCommandBuffer commandBuffer;
|
||||||
void createAttachmentReference(VkAttachmentReference *attachmentReference, uint32_t attachment);
|
|
||||||
void createSubpassDescription(VkSubpassDescription *subpassDescription, VkPipelineBindPoint bindPoint,
|
VkDescriptorSetLayout particleBufferDescriptorSetLayout;
|
||||||
VkAttachmentReference *attachmentReference);
|
VkDescriptorPool particleBufferDescriptorPool;
|
||||||
void createRenderPassInfo(VkRenderPassCreateInfo *renderPassInfo, VkAttachmentDescription *attachmentDescriptions,
|
VkDescriptorSet particleBufferDescriptorSet;
|
||||||
VkSubpassDescription *subpassDescriptions);
|
VkBuffer particleBuffer;
|
||||||
void createSemaphoreInfo(VkSemaphoreCreateInfo *semaphoreInfo);
|
VkDeviceMemory particleBufferMemory;
|
||||||
void createGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo *graphicsPipelineInfo,
|
uint32_t particleBufferSize;
|
||||||
VkPipelineShaderStageCreateInfo *shaderStages,
|
|
||||||
VkPipelineVertexInputStateCreateInfo *vertexInputState,
|
VkDescriptorSetLayout dtUniformBufferDescriptorSetLayout;
|
||||||
VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState,
|
VkDescriptorPool dtUniformBufferDescriptorPool;
|
||||||
VkPipelineViewportStateCreateInfo *viewportState,
|
VkDescriptorSet dtUniformBufferDescriptorSet;
|
||||||
VkPipelineRasterizationStateCreateInfo *rasterizationState,
|
VkBuffer dtUniformBuffer;
|
||||||
VkPipelineMultisampleStateCreateInfo *multisampleState,
|
VkDeviceMemory dtUniformBufferMemory;
|
||||||
VkPipelineColorBlendStateCreateInfo *colorBlendState, VkPipelineLayout *pipelineLayout,
|
uint32_t dtUniformBufferSize;
|
||||||
VkRenderPass *renderPass);
|
|
||||||
void createFramebufferInfo(VkFramebufferCreateInfo *framebufferInfo, VkRenderPass *renderPass, VkImageView *imageView);
|
VkDescriptorSetLayout staticInUniformBufferDescriptorSetLayout;
|
||||||
void createCommandPoolInfo(VkCommandPoolCreateInfo *commandPoolInfo, uint32_t queueFamilyIndex);
|
VkDescriptorPool staticInUniformBufferDescriptorPool;
|
||||||
void createCommandBufferAllocateInfo(VkCommandBufferAllocateInfo *commandBufferAllocateInfo, VkCommandPool *commandPool, uint32_t amountImages);
|
VkDescriptorSet staticInUniformBufferDescriptorSet;
|
||||||
void createCommandBufferBeginInfo(VkCommandBufferBeginInfo *commandBufferBeginInfo);
|
VkBuffer staticInUniformBuffer;
|
||||||
void createRenderPassBeginInfo(VkRenderPassBeginInfo *renderPassBeginInfo, VkRenderPass *renderPass, VkFramebuffer *framebuffer);
|
VkDeviceMemory staticInUniformBufferMemory;
|
||||||
void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain,
|
uint32_t staticInUniformBufferSize;
|
||||||
VkImageView *imageViews, uint32_t imageViewsSize, VkShaderModule *modules,
|
|
||||||
uint32_t shaderModulesSize, VkPipelineLayout *pipelineLayouts, uint32_t pipelineLayoutsSize,
|
VkQueue queue;
|
||||||
VkRenderPass *renderPasses, uint32_t renderPassesSize, VkPipeline *pipelines,
|
uint32_t queueFamilyIndex;
|
||||||
uint32_t pipelinesSize, VkFramebuffer *framebuffers, VkCommandPool *commandPool,
|
|
||||||
VkCommandBuffer *commandBuffers, VkSemaphore *semaphores, uint32_t semaphoresSize);
|
VkSemaphore semaphore;
|
||||||
|
} Compute;
|
||||||
|
|
||||||
|
typedef struct graphics {
|
||||||
|
VkInstance instance;
|
||||||
|
|
||||||
|
VkPhysicalDevice physicalDevice;
|
||||||
|
VkDevice device;
|
||||||
|
|
||||||
|
VkSurfaceKHR surface;
|
||||||
|
VkSwapchainKHR swapChain;
|
||||||
|
|
||||||
|
VkImageView *imageViews;
|
||||||
|
uint32_t imageViewsSize;
|
||||||
|
|
||||||
|
VkRenderPass renderPass;
|
||||||
|
VkFramebuffer *framebuffers;
|
||||||
|
|
||||||
|
VkPipeline pipeline;
|
||||||
|
VkPipelineLayout pipelineLayout;
|
||||||
|
VkShaderModule vertexShaderModule;
|
||||||
|
VkShaderModule fragmentShaderModule;
|
||||||
|
|
||||||
|
VkCommandPool commandPool;
|
||||||
|
VkCommandBuffer *commandBuffers;
|
||||||
|
|
||||||
|
VkBuffer particleBuffer;
|
||||||
|
uint32_t particleBufferSize;
|
||||||
|
|
||||||
|
VkQueue queue;
|
||||||
|
uint32_t queueFamilyIndex;
|
||||||
|
|
||||||
|
VkSemaphore renderComplete;
|
||||||
|
VkSemaphore presentComplete;
|
||||||
|
VkSemaphore semaphore;
|
||||||
|
} Graphics;
|
||||||
|
|
||||||
|
// Shutdown
|
||||||
void shutdownGLFW(GLFWwindow *window);
|
void shutdownGLFW(GLFWwindow *window);
|
||||||
void printStats(VkPhysicalDevice *physicalDevice, VkSurfaceKHR *surface);
|
void shutdownComputeVulkan(Compute *compute);
|
||||||
|
void shutdownGraphicsVulkan(Graphics *graphics);
|
||||||
|
|
||||||
|
// General
|
||||||
|
void createInstance(Compute *compute, Graphics *graphics);
|
||||||
|
void findPhysicalDevice(Compute *compute, Graphics *graphics);
|
||||||
|
void createDevice(Compute *compute, Graphics *graphics);
|
||||||
|
void createParticleBuffer(Compute *compute, Graphics *graphics);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Graphics
|
||||||
|
void createGraphicsSurface(Graphics *graphics, GLFWwindow *window);
|
||||||
|
void createSwapchain(Graphics *graphics);
|
||||||
|
void createGraphicsPipeline(Graphics *graphics);
|
||||||
|
void createFramebuffer(Graphics *graphics);
|
||||||
|
void createGraphicsCommandBuffers(Graphics *graphics);
|
||||||
|
|
||||||
|
// ELse
|
||||||
|
void mapBufferMemory(Compute *compute, VkDeviceMemory memory, void *inputData, uint32_t dataSize);
|
||||||
|
void createSemaphore(VkDevice device, VkSemaphore *semaphore);
|
||||||
|
@ -1,896 +0,0 @@
|
|||||||
#include "initVulkan.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void shutdownGLFW(GLFWwindow *window)
|
|
||||||
{
|
|
||||||
glfwDestroyWindow(window);
|
|
||||||
glfwTerminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void createInstance(Compute *compute, Graphics *graphics)
|
|
||||||
{
|
|
||||||
GLuint enabledLayerSize = 0;
|
|
||||||
const char **enabledLayer;
|
|
||||||
GLuint extensionsSize;
|
|
||||||
const char **glfwExtensions = glfwGetRequiredInstanceExtensions(&extensionsSize);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
enabledLayerSize = 1;
|
|
||||||
enabledLayer = malloc(sizeof(char *));
|
|
||||||
enabledLayer[0] = "VK_LAYER_LUNARG_standard_validation";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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 = enabledLayerSize;
|
|
||||||
instanceCreateInfo.ppEnabledLayerNames = enabledLayer;
|
|
||||||
instanceCreateInfo.enabledExtensionCount = extensionsSize;
|
|
||||||
instanceCreateInfo.ppEnabledExtensionNames = glfwExtensions;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateInstance(&instanceCreateInfo, NULL, &(compute->instance)))
|
|
||||||
|
|
||||||
graphics->instance = compute->instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findPhysicalDevice(Compute *compute, Graphics *graphics)
|
|
||||||
{
|
|
||||||
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]
|
|
||||||
&& (uint32_t) (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);
|
|
||||||
}
|
|
||||||
|
|
||||||
graphics->physicalDevice = compute->physicalDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getQueueFamilyIndex(VkPhysicalDevice physicalDevice, VkQueueFlagBits queueFlagBits, int noGraphics)
|
|
||||||
{
|
|
||||||
uint32_t queueFamiliesSize;
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamiliesSize, NULL);
|
|
||||||
VkQueueFamilyProperties queueFamilies[queueFamiliesSize];
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamiliesSize, queueFamilies);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < queueFamiliesSize; ++i)
|
|
||||||
{
|
|
||||||
if (noGraphics && (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if ((queueFamilies[i].queueFlags & queueFlagBits) == queueFlagBits)
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return UINT32_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
void createDevice(Compute *compute, Graphics *graphics)
|
|
||||||
{
|
|
||||||
compute->queueFamilyIndex = getQueueFamilyIndex(compute->physicalDevice, VK_QUEUE_COMPUTE_BIT, 1);
|
|
||||||
if (compute->queueFamilyIndex == UINT32_MAX)
|
|
||||||
{
|
|
||||||
printf("ERROR: No Queue family found with desired capabilities!\n");
|
|
||||||
assert( compute->queueFamilyIndex < UINT32_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
float queuePriority = 1.0f;
|
|
||||||
VkDeviceQueueCreateInfo computeDeviceQueueCreateInfo = {};
|
|
||||||
computeDeviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
||||||
computeDeviceQueueCreateInfo.queueFamilyIndex = compute->queueFamilyIndex;
|
|
||||||
computeDeviceQueueCreateInfo.queueCount = 1;
|
|
||||||
computeDeviceQueueCreateInfo.pQueuePriorities = &queuePriority;
|
|
||||||
|
|
||||||
graphics->queueFamilyIndex = getQueueFamilyIndex(graphics->physicalDevice, VK_QUEUE_GRAPHICS_BIT, 0);
|
|
||||||
if (graphics->queueFamilyIndex == UINT32_MAX)
|
|
||||||
{
|
|
||||||
printf("ERROR: No Queue family found with desired capabilities!\n");
|
|
||||||
assert( compute->queueFamilyIndex < UINT32_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDeviceQueueCreateInfo graphicsDeviceQueueCreateInfo = {};
|
|
||||||
graphicsDeviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
||||||
graphicsDeviceQueueCreateInfo.queueFamilyIndex = graphics->queueFamilyIndex;
|
|
||||||
graphicsDeviceQueueCreateInfo.queueCount = 1;
|
|
||||||
graphicsDeviceQueueCreateInfo.pQueuePriorities = &queuePriority;
|
|
||||||
|
|
||||||
VkDeviceQueueCreateInfo deviceQueueCreateInfos[2] = {
|
|
||||||
computeDeviceQueueCreateInfo,
|
|
||||||
graphicsDeviceQueueCreateInfo
|
|
||||||
};
|
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures physicalDeviceFeatures = {};
|
|
||||||
const char *swapchainExtension = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
|
|
||||||
const char **extensions = &swapchainExtension;
|
|
||||||
|
|
||||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
|
||||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
|
||||||
deviceCreateInfo.queueCreateInfoCount = 2;
|
|
||||||
deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfos;
|
|
||||||
deviceCreateInfo.pEnabledFeatures = &physicalDeviceFeatures;
|
|
||||||
deviceCreateInfo.enabledExtensionCount = 1;
|
|
||||||
deviceCreateInfo.ppEnabledExtensionNames = extensions;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateDevice(compute->physicalDevice, &deviceCreateInfo, NULL, &(compute->device)))
|
|
||||||
|
|
||||||
graphics->device = compute->device;
|
|
||||||
|
|
||||||
vkGetDeviceQueue(compute->device, compute->queueFamilyIndex, 0, &(compute->queue));
|
|
||||||
vkGetDeviceQueue(graphics->device, graphics->queueFamilyIndex, 0, &(graphics->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 UINT32_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
void createParticleBuffer(Compute *compute, Graphics *graphics)
|
|
||||||
{
|
|
||||||
uint32_t queueFamilyIndices[2] = {
|
|
||||||
compute->queueFamilyIndex,
|
|
||||||
graphics->queueFamilyIndex
|
|
||||||
};
|
|
||||||
|
|
||||||
VkBufferCreateInfo particleBufferCreateInfo = {};
|
|
||||||
particleBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
||||||
particleBufferCreateInfo.size = compute->particleBufferSize;
|
|
||||||
particleBufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
|
||||||
particleBufferCreateInfo.sharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
||||||
particleBufferCreateInfo.queueFamilyIndexCount = 2;
|
|
||||||
particleBufferCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateBuffer(compute->device, &particleBufferCreateInfo, NULL, &(compute->particleBuffer)))
|
|
||||||
|
|
||||||
VkMemoryRequirements particleBufferMemoryRequirements;
|
|
||||||
vkGetBufferMemoryRequirements(compute->device, compute->particleBuffer, &particleBufferMemoryRequirements);
|
|
||||||
|
|
||||||
VkMemoryAllocateInfo particleMemoryAllocateInfo = {};
|
|
||||||
particleMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
||||||
particleMemoryAllocateInfo.allocationSize = particleBufferMemoryRequirements.size;
|
|
||||||
particleMemoryAllocateInfo.memoryTypeIndex = findMemoryType(compute,
|
|
||||||
particleBufferMemoryRequirements.memoryTypeBits,
|
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
||||||
|
|
||||||
ASSERT_VK(vkAllocateMemory(compute->device, &particleMemoryAllocateInfo, NULL, &(compute->particleBufferMemory)))
|
|
||||||
|
|
||||||
ASSERT_VK(vkBindBufferMemory(compute->device, compute->particleBuffer, compute->particleBufferMemory, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
void createComputeBuffer(Compute *compute, uint32_t bufferSize, VkBufferUsageFlags usageFlags, VkBuffer *buffer,
|
|
||||||
VkDeviceMemory *bufferMemory, VkMemoryPropertyFlags memoryPropertyFlags)
|
|
||||||
{
|
|
||||||
VkBufferCreateInfo bufferCreateInfo = {};
|
|
||||||
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
||||||
bufferCreateInfo.size = bufferSize;
|
|
||||||
bufferCreateInfo.usage = usageFlags;
|
|
||||||
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateBuffer(compute->device, &bufferCreateInfo, NULL, buffer))
|
|
||||||
|
|
||||||
VkMemoryRequirements bufferMemoryRequirements;
|
|
||||||
vkGetBufferMemoryRequirements(compute->device, *buffer, &bufferMemoryRequirements);
|
|
||||||
|
|
||||||
VkMemoryAllocateInfo memoryAllocateInfo = {};
|
|
||||||
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
||||||
memoryAllocateInfo.allocationSize = bufferMemoryRequirements.size;
|
|
||||||
memoryAllocateInfo.memoryTypeIndex = findMemoryType(compute,
|
|
||||||
bufferMemoryRequirements.memoryTypeBits,
|
|
||||||
memoryPropertyFlags);
|
|
||||||
|
|
||||||
ASSERT_VK(vkAllocateMemory(compute->device, &memoryAllocateInfo, NULL, bufferMemory))
|
|
||||||
|
|
||||||
ASSERT_VK(vkBindBufferMemory(compute->device, *buffer, *bufferMemory, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
void createComputeBuffers(Compute *compute)
|
|
||||||
{
|
|
||||||
// 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_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
|
||||||
&(compute->staticInUniformBuffer),
|
|
||||||
&(compute->staticInUniformBufferMemory), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void createComputeDescriptorSetLayout(Compute *compute, VkDescriptorType descriptorType, VkDescriptorSetLayout *descriptorSetLayout)
|
|
||||||
{
|
|
||||||
VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {};
|
|
||||||
descriptorSetLayoutBinding.binding = 0;
|
|
||||||
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, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
|
||||||
&(compute->particleBufferDescriptorSetLayout));
|
|
||||||
|
|
||||||
// dt Uniform Buffer
|
|
||||||
createComputeDescriptorSetLayout(compute, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
&(compute->dtUniformBufferDescriptorSetLayout));
|
|
||||||
|
|
||||||
// staticIn Uniform Buffer
|
|
||||||
createComputeDescriptorSetLayout(compute, 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 createShaderModule(VkDevice device, char *filename, VkShaderModule *shaderModule)
|
|
||||||
{
|
|
||||||
long shaderSourceSize;
|
|
||||||
char *shaderSource = readFile(filename, "rb", &shaderSourceSize);
|
|
||||||
|
|
||||||
VkShaderModuleCreateInfo shaderModuleInfo;
|
|
||||||
shaderModuleInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
||||||
shaderModuleInfo.pNext = NULL;
|
|
||||||
shaderModuleInfo.flags = 0;
|
|
||||||
shaderModuleInfo.codeSize = shaderSourceSize;
|
|
||||||
shaderModuleInfo.pCode = (uint32_t *) shaderSource;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateShaderModule(device, &shaderModuleInfo, NULL, shaderModule))
|
|
||||||
|
|
||||||
free(shaderSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
void createComputePipeline(Compute *compute)
|
|
||||||
{
|
|
||||||
createShaderModule(compute->device, "./vulkan/comp.spv", &(compute->shaderModule));
|
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
VkPushConstantRange dtPushConstantRange = {};
|
|
||||||
dtPushConstantRange.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
||||||
dtPushConstantRange.offset = 0;
|
|
||||||
dtPushConstantRange.size = sizeof(Dt);
|
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {};
|
|
||||||
pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
||||||
pipelineLayoutCreateInfo.setLayoutCount = 3;
|
|
||||||
pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts;
|
|
||||||
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
|
||||||
pipelineLayoutCreateInfo.pPushConstantRanges = &dtPushConstantRange;
|
|
||||||
|
|
||||||
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;
|
|
||||||
pipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
|
|
||||||
pipelineCreateInfo.basePipelineIndex = -1;
|
|
||||||
|
|
||||||
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->physicalDevice, VK_QUEUE_TRANSFER_BIT, 0);
|
|
||||||
|
|
||||||
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 createSemaphore(VkDevice device, VkSemaphore *semaphore)
|
|
||||||
{
|
|
||||||
VkSemaphoreCreateInfo semaphoreCreateInfo = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
|
|
||||||
ASSERT_VK(vkCreateSemaphore(device, &semaphoreCreateInfo, NULL, semaphore));
|
|
||||||
}
|
|
||||||
|
|
||||||
void shutdownComputeVulkan(Compute *compute)
|
|
||||||
{
|
|
||||||
vkDeviceWaitIdle(compute->device);
|
|
||||||
|
|
||||||
vkDestroySemaphore(compute->device, compute->semaphore, NULL);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
vkDestroyPipelineLayout(compute->device, compute->pipelineLayout, 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);
|
|
||||||
|
|
||||||
vkDestroyPipeline(compute->device, compute->pipeline, NULL);
|
|
||||||
|
|
||||||
vkDestroyShaderModule(compute->device, compute->shaderModule, NULL);
|
|
||||||
|
|
||||||
vkFreeCommandBuffers(compute->device, compute->commandPool, 1, &(compute->commandBuffer));
|
|
||||||
|
|
||||||
vkDestroyCommandPool(compute->device, compute->commandPool, NULL);
|
|
||||||
|
|
||||||
vkDestroyDevice(compute->device, NULL);
|
|
||||||
|
|
||||||
vkDestroyInstance(compute->instance, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void createGraphicsSurface(Graphics *graphics, GLFWwindow *window)
|
|
||||||
{
|
|
||||||
ASSERT_VK(glfwCreateWindowSurface(graphics->instance, window, NULL, &(graphics->surface)))
|
|
||||||
}
|
|
||||||
|
|
||||||
void createSwapchain(Graphics *graphics)
|
|
||||||
{
|
|
||||||
VkBool32 swapChainSupport;
|
|
||||||
ASSERT_VK(vkGetPhysicalDeviceSurfaceSupportKHR(graphics->physicalDevice, 0, graphics->surface, &swapChainSupport))
|
|
||||||
if (!swapChainSupport)
|
|
||||||
{
|
|
||||||
printf("ERROR: Swap chain not supported!");
|
|
||||||
assert(!swapChainSupport);
|
|
||||||
}
|
|
||||||
|
|
||||||
VkExtent2D imageExtent = { WIDTH, HEIGHT };
|
|
||||||
VkSwapchainCreateInfoKHR swapChainCreateInfo = {};
|
|
||||||
swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
|
||||||
swapChainCreateInfo.surface = graphics->surface;
|
|
||||||
swapChainCreateInfo.minImageCount = 1;
|
|
||||||
swapChainCreateInfo.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
|
||||||
swapChainCreateInfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
|
||||||
swapChainCreateInfo.imageExtent = imageExtent;
|
|
||||||
swapChainCreateInfo.imageArrayLayers = 1;
|
|
||||||
swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
||||||
swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
swapChainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
|
||||||
swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
|
||||||
swapChainCreateInfo.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
|
||||||
swapChainCreateInfo.clipped = VK_FALSE;
|
|
||||||
swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateSwapchainKHR(graphics->device, &swapChainCreateInfo, NULL, &(graphics->swapChain)))
|
|
||||||
|
|
||||||
vkGetSwapchainImagesKHR(graphics->device, graphics->swapChain, &(graphics->imageViewsSize), NULL);
|
|
||||||
VkImage swapChainImages[graphics->imageViewsSize];
|
|
||||||
ASSERT_VK(vkGetSwapchainImagesKHR(graphics->device, graphics->swapChain, &(graphics->imageViewsSize), swapChainImages))
|
|
||||||
|
|
||||||
graphics->imageViews = malloc(graphics->imageViewsSize * sizeof(VkImageView));
|
|
||||||
|
|
||||||
for (int i = 0; i < graphics->imageViewsSize; i++)
|
|
||||||
{
|
|
||||||
VkImageViewCreateInfo imageViewInfo = {};
|
|
||||||
VkComponentMapping componentMapping = {
|
|
||||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
||||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
||||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
||||||
VK_COMPONENT_SWIZZLE_IDENTITY
|
|
||||||
};
|
|
||||||
VkImageSubresourceRange subresourceRange = {
|
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT,0, 1, 0, 1
|
|
||||||
};
|
|
||||||
|
|
||||||
imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
||||||
imageViewInfo.image = swapChainImages[i];
|
|
||||||
imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
||||||
imageViewInfo.format = VK_FORMAT_B8G8R8A8_UNORM;
|
|
||||||
imageViewInfo.components = componentMapping;
|
|
||||||
imageViewInfo.subresourceRange = subresourceRange;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateImageView(graphics->device, &imageViewInfo, NULL, &(graphics->imageViews[i])))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void createShaderStageInfo(VkPipelineShaderStageCreateInfo *shaderStageCreateInfo, VkShaderStageFlagBits shaderStageFlagBits,
|
|
||||||
VkShaderModule shaderModule)
|
|
||||||
{
|
|
||||||
shaderStageCreateInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
||||||
shaderStageCreateInfo->stage = shaderStageFlagBits;
|
|
||||||
shaderStageCreateInfo->module = shaderModule;
|
|
||||||
shaderStageCreateInfo->pName = "main";
|
|
||||||
}
|
|
||||||
|
|
||||||
void createGraphicsPipeline(Graphics *graphics)
|
|
||||||
{
|
|
||||||
VkVertexInputBindingDescription vertexInputBindingDescription;
|
|
||||||
vertexInputBindingDescription.binding = 0;
|
|
||||||
vertexInputBindingDescription.stride = PARTICLE_SIZE;
|
|
||||||
vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription positionVertexInputAttributeDescription;
|
|
||||||
positionVertexInputAttributeDescription.binding = 0;
|
|
||||||
positionVertexInputAttributeDescription.location = 0;
|
|
||||||
positionVertexInputAttributeDescription.format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
||||||
positionVertexInputAttributeDescription.offset = 0;
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription colInVertexInputAttributeDescription;
|
|
||||||
colInVertexInputAttributeDescription.binding = 0;
|
|
||||||
colInVertexInputAttributeDescription.location = 1;
|
|
||||||
colInVertexInputAttributeDescription.format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
||||||
colInVertexInputAttributeDescription.offset = 24;
|
|
||||||
|
|
||||||
VkVertexInputAttributeDescription vertexInputAttributeDescription[2] = {
|
|
||||||
positionVertexInputAttributeDescription,
|
|
||||||
colInVertexInputAttributeDescription
|
|
||||||
};
|
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {};
|
|
||||||
vertexInputStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
|
||||||
vertexInputStateInfo.vertexBindingDescriptionCount = 1;
|
|
||||||
vertexInputStateInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;
|
|
||||||
vertexInputStateInfo.vertexAttributeDescriptionCount = 2;
|
|
||||||
vertexInputStateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescription;
|
|
||||||
|
|
||||||
createShaderModule(graphics->device, "./vulkan/vert.spv", &(graphics->vertexShaderModule));
|
|
||||||
createShaderModule(graphics->device, "./vulkan/frag.spv", &(graphics->fragmentShaderModule));
|
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo vertexShaderStageInfo = {};
|
|
||||||
createShaderStageInfo(&vertexShaderStageInfo, VK_SHADER_STAGE_VERTEX_BIT, graphics->vertexShaderModule);
|
|
||||||
VkPipelineShaderStageCreateInfo fragmentShaderStageInfo = {};
|
|
||||||
createShaderStageInfo(&fragmentShaderStageInfo, VK_SHADER_STAGE_FRAGMENT_BIT, graphics->fragmentShaderModule);
|
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo shaderStages[] = {
|
|
||||||
vertexShaderStageInfo,
|
|
||||||
fragmentShaderStageInfo
|
|
||||||
};
|
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo = {};
|
|
||||||
inputAssemblyStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
|
||||||
inputAssemblyStateInfo.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
|
|
||||||
inputAssemblyStateInfo.primitiveRestartEnable = VK_FALSE;
|
|
||||||
|
|
||||||
VkViewport viewport = {};
|
|
||||||
viewport.x = 0.0f;
|
|
||||||
viewport.y = 0.0f;
|
|
||||||
viewport.width = WIDTH;
|
|
||||||
viewport.height = HEIGHT;
|
|
||||||
viewport.minDepth = 0.0f;
|
|
||||||
viewport.maxDepth = 1.0f;
|
|
||||||
|
|
||||||
VkRect2D scissor = { {0, 0}, {WIDTH, HEIGHT} };
|
|
||||||
|
|
||||||
VkPipelineViewportStateCreateInfo viewportStateInfo = {};
|
|
||||||
viewportStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
|
||||||
viewportStateInfo.viewportCount = 1;
|
|
||||||
viewportStateInfo.pViewports = &viewport;
|
|
||||||
viewportStateInfo.scissorCount = 1;
|
|
||||||
viewportStateInfo.pScissors = &scissor;
|
|
||||||
|
|
||||||
VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = {};
|
|
||||||
rasterizationStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
|
||||||
rasterizationStateInfo.depthClampEnable = VK_FALSE;
|
|
||||||
rasterizationStateInfo.rasterizerDiscardEnable = VK_FALSE;
|
|
||||||
rasterizationStateInfo.polygonMode = VK_POLYGON_MODE_FILL;
|
|
||||||
rasterizationStateInfo.cullMode = VK_CULL_MODE_BACK_BIT;
|
|
||||||
rasterizationStateInfo.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
|
||||||
rasterizationStateInfo.depthBiasEnable = VK_FALSE;
|
|
||||||
rasterizationStateInfo.depthBiasConstantFactor = 0.0f;
|
|
||||||
rasterizationStateInfo.depthBiasClamp = 0.0f;
|
|
||||||
rasterizationStateInfo.depthBiasSlopeFactor = 0.0f;
|
|
||||||
rasterizationStateInfo.lineWidth = 1.0f;
|
|
||||||
|
|
||||||
VkPipelineMultisampleStateCreateInfo multisampleStateInfo = {};
|
|
||||||
multisampleStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
|
||||||
multisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
multisampleStateInfo.sampleShadingEnable = VK_FALSE;
|
|
||||||
multisampleStateInfo.minSampleShading = 1.0f;
|
|
||||||
multisampleStateInfo.alphaToCoverageEnable = VK_FALSE;
|
|
||||||
multisampleStateInfo.alphaToOneEnable = VK_FALSE;
|
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {};
|
|
||||||
colorBlendAttachmentState.blendEnable = VK_FALSE;
|
|
||||||
colorBlendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
|
||||||
colorBlendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
|
||||||
colorBlendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
|
|
||||||
colorBlendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
|
||||||
colorBlendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
|
||||||
colorBlendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
|
||||||
colorBlendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
|
||||||
|
|
||||||
VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = {};
|
|
||||||
colorBlendStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
|
||||||
colorBlendStateInfo.logicOpEnable = VK_FALSE;
|
|
||||||
colorBlendStateInfo.logicOp = VK_LOGIC_OP_NO_OP;
|
|
||||||
colorBlendStateInfo.attachmentCount = 1;
|
|
||||||
colorBlendStateInfo.pAttachments = &colorBlendAttachmentState;
|
|
||||||
colorBlendStateInfo.blendConstants[0] = 0.0f;
|
|
||||||
colorBlendStateInfo.blendConstants[1] = 0.0f;
|
|
||||||
colorBlendStateInfo.blendConstants[2] = 0.0f;
|
|
||||||
colorBlendStateInfo.blendConstants[3] = 0.0f;
|
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo layoutInfo = {};
|
|
||||||
layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreatePipelineLayout(graphics->device, &layoutInfo, NULL, &(graphics->pipelineLayout)))
|
|
||||||
|
|
||||||
VkAttachmentDescription attachmentDescription = {};
|
|
||||||
attachmentDescription.format = VK_FORMAT_B8G8R8A8_UNORM;
|
|
||||||
attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
||||||
attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
||||||
attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
||||||
attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
||||||
attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
|
||||||
|
|
||||||
VkAttachmentReference attachmentReference = {};
|
|
||||||
attachmentReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
VkSubpassDescription subpassDescription = {};
|
|
||||||
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
||||||
subpassDescription.colorAttachmentCount = 1;
|
|
||||||
subpassDescription.pColorAttachments = &attachmentReference;
|
|
||||||
|
|
||||||
VkSubpassDependency subpassDependency = {};
|
|
||||||
subpassDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
|
||||||
subpassDependency.dstSubpass = 0;
|
|
||||||
subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
subpassDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
subpassDependency.srcAccessMask = 0;
|
|
||||||
subpassDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
|
|
||||||
VkRenderPassCreateInfo renderPassInfo = {};
|
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
||||||
renderPassInfo.attachmentCount = 1;
|
|
||||||
renderPassInfo.pAttachments = &attachmentDescription;
|
|
||||||
renderPassInfo.subpassCount = 1;
|
|
||||||
renderPassInfo.pSubpasses = &subpassDescription;
|
|
||||||
renderPassInfo.dependencyCount = 1;
|
|
||||||
renderPassInfo.pDependencies = &subpassDependency;
|
|
||||||
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateRenderPass(graphics->device, &renderPassInfo, NULL, &(graphics->renderPass)))
|
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo graphicsPipelineInfo = {};
|
|
||||||
graphicsPipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
|
||||||
graphicsPipelineInfo.stageCount = 2;
|
|
||||||
graphicsPipelineInfo.pStages = shaderStages;
|
|
||||||
graphicsPipelineInfo.pVertexInputState = &vertexInputStateInfo;
|
|
||||||
graphicsPipelineInfo.pInputAssemblyState = &inputAssemblyStateInfo;
|
|
||||||
graphicsPipelineInfo.pViewportState = &viewportStateInfo;
|
|
||||||
graphicsPipelineInfo.pRasterizationState = &rasterizationStateInfo;
|
|
||||||
graphicsPipelineInfo.pMultisampleState = &multisampleStateInfo;
|
|
||||||
graphicsPipelineInfo.pColorBlendState = &colorBlendStateInfo;
|
|
||||||
graphicsPipelineInfo.layout = graphics->pipelineLayout;
|
|
||||||
graphicsPipelineInfo.renderPass = graphics->renderPass;
|
|
||||||
graphicsPipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
|
||||||
graphicsPipelineInfo.basePipelineIndex = -1;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateGraphicsPipelines(graphics->device, VK_NULL_HANDLE, 1, &graphicsPipelineInfo, NULL, &(graphics->pipeline)))
|
|
||||||
}
|
|
||||||
|
|
||||||
void createFramebuffer(Graphics *graphics)
|
|
||||||
{
|
|
||||||
graphics->framebuffers = malloc(graphics->imageViewsSize * sizeof(VkFramebuffer));
|
|
||||||
for (int i = 0; i < graphics->imageViewsSize; ++i)
|
|
||||||
{
|
|
||||||
VkFramebufferCreateInfo framebufferInfo = {};
|
|
||||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
|
||||||
framebufferInfo.renderPass = graphics->renderPass;
|
|
||||||
framebufferInfo.attachmentCount = 1;
|
|
||||||
framebufferInfo.pAttachments = &(graphics->imageViews[i]);
|
|
||||||
framebufferInfo.width = WIDTH;
|
|
||||||
framebufferInfo.height = HEIGHT;
|
|
||||||
framebufferInfo.layers = 1;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateFramebuffer(graphics->device, &framebufferInfo, NULL, &(graphics->framebuffers[i])))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void createGraphicsCommandBuffers(Graphics *graphics)
|
|
||||||
{
|
|
||||||
VkCommandPoolCreateInfo commandPoolInfo = {};
|
|
||||||
commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
|
||||||
commandPoolInfo.queueFamilyIndex = graphics->queueFamilyIndex;
|
|
||||||
|
|
||||||
ASSERT_VK(vkCreateCommandPool(graphics->device, &commandPoolInfo, NULL, &(graphics->commandPool)))
|
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo commandBufferAllocateInfo = {};
|
|
||||||
commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
||||||
commandBufferAllocateInfo.commandPool = graphics->commandPool;
|
|
||||||
commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
||||||
commandBufferAllocateInfo.commandBufferCount = graphics->imageViewsSize;
|
|
||||||
|
|
||||||
graphics->commandBuffers = malloc(graphics->imageViewsSize * sizeof(VkCommandBuffer));
|
|
||||||
|
|
||||||
ASSERT_VK(vkAllocateCommandBuffers(graphics->device, &commandBufferAllocateInfo, graphics->commandBuffers))
|
|
||||||
|
|
||||||
VkCommandBufferBeginInfo commandBufferBeginInfo = {};
|
|
||||||
commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
||||||
commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
|
||||||
|
|
||||||
VkRect2D renderArea = { {0, 0}, {WIDTH, HEIGHT} };
|
|
||||||
VkClearValue clearValue = {0, 0, 0, 1};
|
|
||||||
|
|
||||||
for (int i = 0; i < graphics->imageViewsSize; i++)
|
|
||||||
{
|
|
||||||
ASSERT_VK(vkBeginCommandBuffer(graphics->commandBuffers[i], &commandBufferBeginInfo))
|
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassBeginInfo = {};
|
|
||||||
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
|
||||||
renderPassBeginInfo.renderPass = graphics->renderPass;
|
|
||||||
renderPassBeginInfo.framebuffer = graphics->framebuffers[i];
|
|
||||||
renderPassBeginInfo.renderArea = renderArea;
|
|
||||||
renderPassBeginInfo.clearValueCount = 1;
|
|
||||||
renderPassBeginInfo.pClearValues = &clearValue;
|
|
||||||
|
|
||||||
vkCmdBeginRenderPass(graphics->commandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
|
|
||||||
vkCmdBindPipeline(graphics->commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics->pipeline);
|
|
||||||
|
|
||||||
VkDeviceSize offsets[1] = { 0 };
|
|
||||||
vkCmdBindVertexBuffers(graphics->commandBuffers[i], 0, 1, &(graphics->particleBuffer), offsets);
|
|
||||||
|
|
||||||
vkCmdDraw(graphics->commandBuffers[i], PARTICLE_AMOUNT, 1, 0, 0);
|
|
||||||
|
|
||||||
vkCmdEndRenderPass(graphics->commandBuffers[i]);
|
|
||||||
|
|
||||||
ASSERT_VK(vkEndCommandBuffer(graphics->commandBuffers[i]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void shutdownGraphicsVulkan(Graphics *graphics)
|
|
||||||
{
|
|
||||||
vkDeviceWaitIdle(graphics->device);
|
|
||||||
|
|
||||||
for (int i = 0; i < graphics->imageViewsSize; ++i)
|
|
||||||
{
|
|
||||||
vkDestroyFramebuffer(graphics->device, graphics->framebuffers[i], NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkDestroyCommandPool(graphics->device, graphics->commandPool, NULL);
|
|
||||||
|
|
||||||
vkDestroySemaphore(graphics->device, graphics->semaphore, NULL);
|
|
||||||
vkDestroySemaphore(graphics->device, graphics->renderComplete, NULL);
|
|
||||||
vkDestroySemaphore(graphics->device, graphics->presentComplete, NULL);
|
|
||||||
|
|
||||||
vkDestroyPipelineLayout(graphics->device, graphics->pipelineLayout, NULL);
|
|
||||||
|
|
||||||
vkDestroyRenderPass(graphics->device, graphics->renderPass, NULL);
|
|
||||||
|
|
||||||
vkDestroyPipeline(graphics->device, graphics->pipeline, NULL);
|
|
||||||
|
|
||||||
vkDestroyShaderModule(graphics->device, graphics->fragmentShaderModule, NULL);
|
|
||||||
vkDestroyShaderModule(graphics->device, graphics->vertexShaderModule, NULL);
|
|
||||||
|
|
||||||
for (int i = 0; i < graphics->imageViewsSize; ++i)
|
|
||||||
{
|
|
||||||
vkDestroyImageView(graphics->device, graphics->imageViews[i], NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkDestroySwapchainKHR(graphics->device, graphics->swapChain, NULL);
|
|
||||||
|
|
||||||
vkDestroySurfaceKHR(graphics->instance, graphics->surface, NULL);
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#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 1000000
|
|
||||||
#define PARTICLE_SIZE (3 * sizeof(vector3f) + sizeof(float))
|
|
||||||
#define WORKGROUP_SIZE_X 1024
|
|
||||||
#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 dt {
|
|
||||||
float dt;
|
|
||||||
} Dt;
|
|
||||||
|
|
||||||
typedef struct staticIn {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
unsigned int maxParticles;
|
|
||||||
} StaticIn;
|
|
||||||
|
|
||||||
typedef struct compute {
|
|
||||||
VkInstance instance;
|
|
||||||
|
|
||||||
VkPhysicalDevice physicalDevice;
|
|
||||||
VkDevice device;
|
|
||||||
|
|
||||||
VkPipeline pipeline;
|
|
||||||
VkPipelineLayout pipelineLayout;
|
|
||||||
VkShaderModule shaderModule;
|
|
||||||
|
|
||||||
VkCommandPool commandPool;
|
|
||||||
VkCommandBuffer commandBuffer;
|
|
||||||
|
|
||||||
VkDescriptorSetLayout particleBufferDescriptorSetLayout;
|
|
||||||
VkDescriptorPool particleBufferDescriptorPool;
|
|
||||||
VkDescriptorSet particleBufferDescriptorSet;
|
|
||||||
VkBuffer particleBuffer;
|
|
||||||
VkDeviceMemory particleBufferMemory;
|
|
||||||
uint32_t particleBufferSize;
|
|
||||||
|
|
||||||
VkDescriptorSetLayout dtUniformBufferDescriptorSetLayout;
|
|
||||||
VkDescriptorPool dtUniformBufferDescriptorPool;
|
|
||||||
VkDescriptorSet dtUniformBufferDescriptorSet;
|
|
||||||
VkBuffer dtUniformBuffer;
|
|
||||||
VkDeviceMemory dtUniformBufferMemory;
|
|
||||||
uint32_t dtUniformBufferSize;
|
|
||||||
|
|
||||||
VkDescriptorSetLayout staticInUniformBufferDescriptorSetLayout;
|
|
||||||
VkDescriptorPool staticInUniformBufferDescriptorPool;
|
|
||||||
VkDescriptorSet staticInUniformBufferDescriptorSet;
|
|
||||||
VkBuffer staticInUniformBuffer;
|
|
||||||
VkDeviceMemory staticInUniformBufferMemory;
|
|
||||||
uint32_t staticInUniformBufferSize;
|
|
||||||
|
|
||||||
VkQueue queue;
|
|
||||||
uint32_t queueFamilyIndex;
|
|
||||||
|
|
||||||
VkSemaphore semaphore;
|
|
||||||
} Compute;
|
|
||||||
|
|
||||||
typedef struct graphics {
|
|
||||||
VkInstance instance;
|
|
||||||
|
|
||||||
VkPhysicalDevice physicalDevice;
|
|
||||||
VkDevice device;
|
|
||||||
|
|
||||||
VkSurfaceKHR surface;
|
|
||||||
VkSwapchainKHR swapChain;
|
|
||||||
|
|
||||||
VkImageView *imageViews;
|
|
||||||
uint32_t imageViewsSize;
|
|
||||||
|
|
||||||
VkRenderPass renderPass;
|
|
||||||
VkFramebuffer *framebuffers;
|
|
||||||
|
|
||||||
VkPipeline pipeline;
|
|
||||||
VkPipelineLayout pipelineLayout;
|
|
||||||
VkShaderModule vertexShaderModule;
|
|
||||||
VkShaderModule fragmentShaderModule;
|
|
||||||
|
|
||||||
VkCommandPool commandPool;
|
|
||||||
VkCommandBuffer *commandBuffers;
|
|
||||||
|
|
||||||
VkBuffer particleBuffer;
|
|
||||||
uint32_t particleBufferSize;
|
|
||||||
|
|
||||||
VkQueue queue;
|
|
||||||
uint32_t queueFamilyIndex;
|
|
||||||
|
|
||||||
VkSemaphore renderComplete;
|
|
||||||
VkSemaphore presentComplete;
|
|
||||||
VkSemaphore semaphore;
|
|
||||||
} Graphics;
|
|
||||||
|
|
||||||
// Shutdown
|
|
||||||
void shutdownGLFW(GLFWwindow *window);
|
|
||||||
void shutdownComputeVulkan(Compute *compute);
|
|
||||||
void shutdownGraphicsVulkan(Graphics *graphics);
|
|
||||||
|
|
||||||
// General
|
|
||||||
void createInstance(Compute *compute, Graphics *graphics);
|
|
||||||
void findPhysicalDevice(Compute *compute, Graphics *graphics);
|
|
||||||
void createDevice(Compute *compute, Graphics *graphics);
|
|
||||||
void createParticleBuffer(Compute *compute, Graphics *graphics);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Graphics
|
|
||||||
void createGraphicsSurface(Graphics *graphics, GLFWwindow *window);
|
|
||||||
void createSwapchain(Graphics *graphics);
|
|
||||||
void createGraphicsPipeline(Graphics *graphics);
|
|
||||||
void createFramebuffer(Graphics *graphics);
|
|
||||||
void createGraphicsCommandBuffers(Graphics *graphics);
|
|
||||||
|
|
||||||
// ELse
|
|
||||||
void mapBufferMemory(Compute *compute, VkDeviceMemory memory, void *inputData, uint32_t dataSize);
|
|
||||||
void createSemaphore(VkDevice device, VkSemaphore *semaphore);
|
|
@ -1,146 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
Dt dt = { 0.5f };
|
|
||||||
StaticIn staticIn = {
|
|
||||||
e1->position->x,
|
|
||||||
e1->position->y,
|
|
||||||
e1->position->z,
|
|
||||||
PARTICLE_AMOUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
freeParticleSystem(ps);
|
|
||||||
|
|
||||||
/************* 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 = {
|
|
||||||
.particleBufferSize = PARTICLE_SIZE * PARTICLE_AMOUNT,
|
|
||||||
.staticInUniformBufferSize = sizeof(StaticIn),
|
|
||||||
.dtUniformBufferSize = sizeof(Dt)
|
|
||||||
};
|
|
||||||
Graphics graphics = {};
|
|
||||||
|
|
||||||
// General
|
|
||||||
createInstance(&compute, &graphics);
|
|
||||||
findPhysicalDevice(&compute, &graphics);
|
|
||||||
createDevice(&compute, &graphics);
|
|
||||||
createParticleBuffer(&compute, &graphics);
|
|
||||||
|
|
||||||
// Compute
|
|
||||||
createComputeBuffers(&compute);
|
|
||||||
createComputeDescriptorSetLayouts(&compute);
|
|
||||||
createComputeDescriptorSets(&compute);
|
|
||||||
createComputePipeline(&compute);
|
|
||||||
fillComputeBuffers(&compute, particles, &dt, &staticIn);
|
|
||||||
|
|
||||||
createSemaphore(compute.device, &(compute.semaphore));
|
|
||||||
VkSubmitInfo submitInfo = {};
|
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
||||||
submitInfo.signalSemaphoreCount = 1;
|
|
||||||
submitInfo.pSignalSemaphores = &compute.semaphore;
|
|
||||||
ASSERT_VK(vkQueueSubmit(compute.queue, 1, &submitInfo, VK_NULL_HANDLE));
|
|
||||||
ASSERT_VK(vkQueueWaitIdle(compute.queue));
|
|
||||||
|
|
||||||
createComputeCommandBuffer(&compute);
|
|
||||||
|
|
||||||
// Graphics
|
|
||||||
graphics.particleBuffer = compute.particleBuffer;
|
|
||||||
graphics.particleBufferSize = compute.particleBufferSize;
|
|
||||||
createGraphicsSurface(&graphics, window);
|
|
||||||
createSwapchain(&graphics);
|
|
||||||
createGraphicsPipeline(&graphics);
|
|
||||||
createFramebuffer(&graphics);
|
|
||||||
createGraphicsCommandBuffers(&graphics);
|
|
||||||
createSemaphore(graphics.device, &(graphics.presentComplete));
|
|
||||||
createSemaphore(graphics.device, &(graphics.renderComplete));
|
|
||||||
createSemaphore(graphics.device, &(graphics.semaphore));
|
|
||||||
|
|
||||||
/************* RENDER LOOP *************/
|
|
||||||
// Graphics preparation
|
|
||||||
VkPipelineStageFlags graphicsWaitStageMasks[] = {
|
|
||||||
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
|
|
||||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
|
||||||
};
|
|
||||||
VkSemaphore graphicsWaitSemaphores[] = { compute.semaphore, graphics.presentComplete };
|
|
||||||
VkSemaphore graphicsSignalSemaphores[] = { graphics.semaphore, graphics.renderComplete };
|
|
||||||
|
|
||||||
VkSubmitInfo graphicsSubmitInfo = {};
|
|
||||||
graphicsSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
||||||
graphicsSubmitInfo.commandBufferCount = 1;
|
|
||||||
graphicsSubmitInfo.waitSemaphoreCount = 2;
|
|
||||||
graphicsSubmitInfo.pWaitSemaphores = graphicsWaitSemaphores;
|
|
||||||
graphicsSubmitInfo.pWaitDstStageMask = graphicsWaitStageMasks;
|
|
||||||
graphicsSubmitInfo.signalSemaphoreCount = 2;
|
|
||||||
graphicsSubmitInfo.pSignalSemaphores = graphicsSignalSemaphores;
|
|
||||||
|
|
||||||
VkPresentInfoKHR graphicsPresentInfo = {};
|
|
||||||
graphicsPresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
|
||||||
graphicsPresentInfo.waitSemaphoreCount = 1;
|
|
||||||
graphicsPresentInfo.pWaitSemaphores = &(graphics.renderComplete);
|
|
||||||
graphicsPresentInfo.swapchainCount = 1;
|
|
||||||
graphicsPresentInfo.pSwapchains = &(graphics.swapChain);
|
|
||||||
|
|
||||||
|
|
||||||
// Compute preparation
|
|
||||||
VkPipelineStageFlags computeWaitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
|
||||||
|
|
||||||
VkSubmitInfo computeSubmitInfo = {};
|
|
||||||
computeSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
||||||
computeSubmitInfo.commandBufferCount = 1;
|
|
||||||
computeSubmitInfo.pCommandBuffers = &(compute.commandBuffer);
|
|
||||||
computeSubmitInfo.waitSemaphoreCount = 1;
|
|
||||||
computeSubmitInfo.pWaitSemaphores = &graphics.semaphore;
|
|
||||||
computeSubmitInfo.pWaitDstStageMask = &computeWaitStageMask;
|
|
||||||
computeSubmitInfo.signalSemaphoreCount = 1;
|
|
||||||
computeSubmitInfo.pSignalSemaphores = &compute.semaphore;
|
|
||||||
|
|
||||||
// Loop
|
|
||||||
double time, tLast = 0;
|
|
||||||
Dt tFrame = {};
|
|
||||||
uint32_t imageIndex;
|
|
||||||
while (!glfwWindowShouldClose(window))
|
|
||||||
{
|
|
||||||
time = glfwGetTime();
|
|
||||||
tFrame.dt = (float) (time - tLast);
|
|
||||||
tLast = time;
|
|
||||||
|
|
||||||
/*** RENDER ***/
|
|
||||||
ASSERT_VK(vkAcquireNextImageKHR(graphics.device, graphics.swapChain, UINT64_MAX, graphics.presentComplete, VK_NULL_HANDLE, &imageIndex))
|
|
||||||
|
|
||||||
graphicsSubmitInfo.pCommandBuffers = &(graphics.commandBuffers[imageIndex]);
|
|
||||||
ASSERT_VK(vkQueueSubmit(graphics.queue, 1, &graphicsSubmitInfo, VK_NULL_HANDLE))
|
|
||||||
|
|
||||||
graphicsPresentInfo.pImageIndices = &imageIndex;
|
|
||||||
ASSERT_VK(vkQueuePresentKHR(graphics.queue, &graphicsPresentInfo))
|
|
||||||
|
|
||||||
/*** UPDATE ***/
|
|
||||||
// Update dt
|
|
||||||
mapBufferMemory(&compute, compute.dtUniformBufferMemory, &tFrame, sizeof(Dt));
|
|
||||||
ASSERT_VK(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE))
|
|
||||||
|
|
||||||
glfwPollEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
shutdownGraphicsVulkan(&graphics);
|
|
||||||
shutdownComputeVulkan(&compute);
|
|
||||||
shutdownGLFW(window);
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
312
vulkanMain.c
312
vulkanMain.c
@ -1,232 +1,146 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "initVulkan.h"
|
#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()
|
int main()
|
||||||
{
|
{
|
||||||
VkInstance vkInstance;
|
|
||||||
VkDevice device;
|
|
||||||
VkSurfaceKHR surface;
|
|
||||||
VkSwapchainKHR swapChain;
|
|
||||||
VkImageView *imageViews = NULL;
|
|
||||||
uint32_t imageViewsSize;
|
|
||||||
VkPipelineLayout pipelineLayout;
|
|
||||||
VkRenderPass renderPass;
|
|
||||||
VkPipeline pipeline;
|
|
||||||
VkFramebuffer *framebuffers;
|
|
||||||
VkCommandPool commandPool;
|
|
||||||
VkCommandBuffer *commandBuffers;
|
|
||||||
VkSemaphore imageAvailable;
|
|
||||||
VkSemaphore renderingFinished;
|
|
||||||
|
|
||||||
/************* 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
|
|
||||||
ASSERT_SUCCESS(initVulkan(&vkInstance, &device, &surface, window, &swapChain, &imageViews, &imageViewsSize))
|
|
||||||
|
|
||||||
/************* PARTICLE SYSTEM *************/
|
/************* PARTICLE SYSTEM *************/
|
||||||
vector3f *epos1 = initVector3f(0, 0, 0);
|
vector3f *epos1 = initVector3f(0, 0, 0);
|
||||||
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
|
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
|
||||||
particle_system *ps = initParticleSystem(1);
|
particle_system *ps = initParticleSystem(1);
|
||||||
(ps->emitters)[0] = e1;
|
(ps->emitters)[0] = e1;
|
||||||
initRandomParticles(e1);
|
initRandomParticles(e1);
|
||||||
|
float *particles = serializeParticlesystem(ps);
|
||||||
|
|
||||||
/************* SHADER *************/
|
Dt dt = { 0.5f };
|
||||||
// Shader Modules
|
StaticIn staticIn = {
|
||||||
long computeShaderSourceSize, vertexShaderSourceSize, fragmentShaderSourceSize;
|
e1->position->x,
|
||||||
char *computeShaderSource = readFile("./vulkan/comp.spv", "rb", &computeShaderSourceSize);
|
e1->position->y,
|
||||||
char *vertexShaderSource = readFile("./vulkan/vert.spv", "rb", &vertexShaderSourceSize);
|
e1->position->z,
|
||||||
char *fragmentShaderSource = readFile("./vulkan/frag.spv", "rb", &fragmentShaderSourceSize);
|
PARTICLE_AMOUNT
|
||||||
|
};
|
||||||
|
|
||||||
VkShaderModule computeShaderModule;
|
freeParticleSystem(ps);
|
||||||
createShaderModule(device, &computeShaderModule, computeShaderSource, computeShaderSourceSize);
|
|
||||||
VkShaderModule vertexShaderModule;
|
|
||||||
createShaderModule(device, &vertexShaderModule, vertexShaderSource, vertexShaderSourceSize);
|
|
||||||
VkShaderModule fragmentShaderModule;
|
|
||||||
createShaderModule(device, &fragmentShaderModule, fragmentShaderSource, fragmentShaderSourceSize);
|
|
||||||
|
|
||||||
// Shader stages
|
/************* INIT GLFW *************/
|
||||||
VkPipelineShaderStageCreateInfo computeShaderStageInfo;
|
ASSERT_GLFW_SUCCESS(glfwInit());
|
||||||
createShaderStageInfo(&computeShaderStageInfo, VK_SHADER_STAGE_COMPUTE_BIT, computeShaderModule, "main");
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
VkPipelineShaderStageCreateInfo vertexShaderStageInfo;
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
createShaderStageInfo(&vertexShaderStageInfo, VK_SHADER_STAGE_VERTEX_BIT, vertexShaderModule, "main");
|
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Informatikprojekt - Vulkan", NULL, NULL);
|
||||||
VkPipelineShaderStageCreateInfo fragmentShaderStageInfo;
|
|
||||||
createShaderStageInfo(&fragmentShaderStageInfo, VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderModule, "main");
|
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo shaderStages[3] = {computeShaderStageInfo, vertexShaderStageInfo,
|
/************* INIT VULKAN *************/
|
||||||
fragmentShaderStageInfo};
|
Compute compute = {
|
||||||
|
.particleBufferSize = PARTICLE_SIZE * PARTICLE_AMOUNT,
|
||||||
|
.staticInUniformBufferSize = sizeof(StaticIn),
|
||||||
|
.dtUniformBufferSize = sizeof(Dt)
|
||||||
|
};
|
||||||
|
Graphics graphics = {};
|
||||||
|
|
||||||
/************* PIPELINE *************/
|
// General
|
||||||
// Vertex input
|
createInstance(&compute, &graphics);
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputStateInfo;
|
findPhysicalDevice(&compute, &graphics);
|
||||||
createPipelineVertexInputStateInfo(&vertexInputStateInfo, NULL, 0);
|
createDevice(&compute, &graphics);
|
||||||
|
createParticleBuffer(&compute, &graphics);
|
||||||
|
|
||||||
// Input assembly
|
// Compute
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo;
|
createComputeBuffers(&compute);
|
||||||
createInputAssemblyStateInfo(&inputAssemblyStateInfo, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
|
createComputeDescriptorSetLayouts(&compute);
|
||||||
|
createComputeDescriptorSets(&compute);
|
||||||
|
createComputePipeline(&compute);
|
||||||
|
fillComputeBuffers(&compute, particles, &dt, &staticIn);
|
||||||
|
|
||||||
// Viewport
|
createSemaphore(compute.device, &(compute.semaphore));
|
||||||
VkPipelineViewportStateCreateInfo viewportStateInfo;
|
VkSubmitInfo submitInfo = {};
|
||||||
createViewportStateInfo(&viewportStateInfo, WIDTH, HEIGHT);
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.signalSemaphoreCount = 1;
|
||||||
|
submitInfo.pSignalSemaphores = &compute.semaphore;
|
||||||
|
ASSERT_VK(vkQueueSubmit(compute.queue, 1, &submitInfo, VK_NULL_HANDLE));
|
||||||
|
ASSERT_VK(vkQueueWaitIdle(compute.queue));
|
||||||
|
|
||||||
// Rasterization
|
createComputeCommandBuffer(&compute);
|
||||||
VkPipelineRasterizationStateCreateInfo rasterizationStateInfo;
|
|
||||||
createRasterizationStateInfo(&rasterizationStateInfo, VK_POLYGON_MODE_POINT);
|
|
||||||
|
|
||||||
// Multisampling
|
// Graphics
|
||||||
VkPipelineMultisampleStateCreateInfo multisampleStateInfo;
|
graphics.particleBuffer = compute.particleBuffer;
|
||||||
createMultisampleStateInfo(&multisampleStateInfo);
|
graphics.particleBufferSize = compute.particleBufferSize;
|
||||||
|
createGraphicsSurface(&graphics, window);
|
||||||
// Blending
|
createSwapchain(&graphics);
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
|
createGraphicsPipeline(&graphics);
|
||||||
createColorBlendAttachmentStateInfo(&colorBlendAttachmentState);
|
createFramebuffer(&graphics);
|
||||||
VkPipelineColorBlendStateCreateInfo colorBlendStateInfo;
|
createGraphicsCommandBuffers(&graphics);
|
||||||
createColorBlendStateInfo(&colorBlendStateInfo, &colorBlendAttachmentState, 1);
|
createSemaphore(graphics.device, &(graphics.presentComplete));
|
||||||
|
createSemaphore(graphics.device, &(graphics.renderComplete));
|
||||||
// Layout
|
createSemaphore(graphics.device, &(graphics.semaphore));
|
||||||
VkPipelineLayoutCreateInfo layoutInfo;
|
|
||||||
createLayoutInfo(&layoutInfo, NULL, 0);
|
|
||||||
ASSERT_VK_SUCCESS(vkCreatePipelineLayout(device, &layoutInfo, NULL, &pipelineLayout))
|
|
||||||
|
|
||||||
// Attachments
|
|
||||||
VkAttachmentDescription attachmentDescription;
|
|
||||||
createAttachmentDescription(&attachmentDescription);
|
|
||||||
|
|
||||||
VkAttachmentReference attachmentReference;
|
|
||||||
createAttachmentReference(&attachmentReference, 0);
|
|
||||||
|
|
||||||
// Subpasses
|
|
||||||
VkSubpassDescription subpassDescription;
|
|
||||||
createSubpassDescription(&subpassDescription, VK_PIPELINE_BIND_POINT_GRAPHICS, &attachmentReference);
|
|
||||||
|
|
||||||
// Renderpass
|
|
||||||
VkRenderPassCreateInfo renderPassInfo;
|
|
||||||
createRenderPassInfo(&renderPassInfo, &attachmentDescription, &subpassDescription);
|
|
||||||
ASSERT_VK_SUCCESS(vkCreateRenderPass(device, &renderPassInfo, NULL, &renderPass))
|
|
||||||
|
|
||||||
// Graphics pipeline
|
|
||||||
VkGraphicsPipelineCreateInfo graphicsPipelineInfo;
|
|
||||||
createGraphicsPipelineInfo(&graphicsPipelineInfo, shaderStages, &vertexInputStateInfo, &inputAssemblyStateInfo,
|
|
||||||
&viewportStateInfo, &rasterizationStateInfo, &multisampleStateInfo, &colorBlendStateInfo,
|
|
||||||
&pipelineLayout, &renderPass);
|
|
||||||
ASSERT_VK_SUCCESS(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineInfo, NULL, &pipeline))
|
|
||||||
|
|
||||||
// Framebuffers
|
|
||||||
framebuffers = malloc(imageViewsSize * sizeof(VkFramebuffer));
|
|
||||||
for (int i = 0; i < imageViewsSize; ++i)
|
|
||||||
{
|
|
||||||
VkFramebufferCreateInfo framebufferInfo;
|
|
||||||
createFramebufferInfo(&framebufferInfo, &renderPass, &imageViews[i]);
|
|
||||||
|
|
||||||
ASSERT_VK_SUCCESS(vkCreateFramebuffer(device, &framebufferInfo, NULL, &framebuffers[i]))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command pool
|
|
||||||
VkCommandPoolCreateInfo commandPoolInfo;
|
|
||||||
createCommandPoolInfo(&commandPoolInfo, 0);
|
|
||||||
ASSERT_VK_SUCCESS(vkCreateCommandPool(device, &commandPoolInfo, NULL, &commandPool))
|
|
||||||
|
|
||||||
// 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 *************/
|
/************* RENDER LOOP *************/
|
||||||
|
// Graphics preparation
|
||||||
|
VkPipelineStageFlags graphicsWaitStageMasks[] = {
|
||||||
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
|
||||||
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
||||||
|
};
|
||||||
|
VkSemaphore graphicsWaitSemaphores[] = { compute.semaphore, graphics.presentComplete };
|
||||||
|
VkSemaphore graphicsSignalSemaphores[] = { graphics.semaphore, graphics.renderComplete };
|
||||||
|
|
||||||
|
VkSubmitInfo graphicsSubmitInfo = {};
|
||||||
|
graphicsSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
graphicsSubmitInfo.commandBufferCount = 1;
|
||||||
|
graphicsSubmitInfo.waitSemaphoreCount = 2;
|
||||||
|
graphicsSubmitInfo.pWaitSemaphores = graphicsWaitSemaphores;
|
||||||
|
graphicsSubmitInfo.pWaitDstStageMask = graphicsWaitStageMasks;
|
||||||
|
graphicsSubmitInfo.signalSemaphoreCount = 2;
|
||||||
|
graphicsSubmitInfo.pSignalSemaphores = graphicsSignalSemaphores;
|
||||||
|
|
||||||
|
VkPresentInfoKHR graphicsPresentInfo = {};
|
||||||
|
graphicsPresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
|
graphicsPresentInfo.waitSemaphoreCount = 1;
|
||||||
|
graphicsPresentInfo.pWaitSemaphores = &(graphics.renderComplete);
|
||||||
|
graphicsPresentInfo.swapchainCount = 1;
|
||||||
|
graphicsPresentInfo.pSwapchains = &(graphics.swapChain);
|
||||||
|
|
||||||
|
|
||||||
|
// Compute preparation
|
||||||
|
VkPipelineStageFlags computeWaitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
|
|
||||||
|
VkSubmitInfo computeSubmitInfo = {};
|
||||||
|
computeSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
computeSubmitInfo.commandBufferCount = 1;
|
||||||
|
computeSubmitInfo.pCommandBuffers = &(compute.commandBuffer);
|
||||||
|
computeSubmitInfo.waitSemaphoreCount = 1;
|
||||||
|
computeSubmitInfo.pWaitSemaphores = &graphics.semaphore;
|
||||||
|
computeSubmitInfo.pWaitDstStageMask = &computeWaitStageMask;
|
||||||
|
computeSubmitInfo.signalSemaphoreCount = 1;
|
||||||
|
computeSubmitInfo.pSignalSemaphores = &compute.semaphore;
|
||||||
|
|
||||||
|
// Loop
|
||||||
|
double time, tLast = 0;
|
||||||
|
Dt tFrame = {};
|
||||||
|
uint32_t imageIndex;
|
||||||
while (!glfwWindowShouldClose(window))
|
while (!glfwWindowShouldClose(window))
|
||||||
{
|
{
|
||||||
|
time = glfwGetTime();
|
||||||
|
tFrame.dt = (float) (time - tLast);
|
||||||
|
tLast = time;
|
||||||
|
|
||||||
|
/*** RENDER ***/
|
||||||
|
ASSERT_VK(vkAcquireNextImageKHR(graphics.device, graphics.swapChain, UINT64_MAX, graphics.presentComplete, VK_NULL_HANDLE, &imageIndex))
|
||||||
|
|
||||||
|
graphicsSubmitInfo.pCommandBuffers = &(graphics.commandBuffers[imageIndex]);
|
||||||
|
ASSERT_VK(vkQueueSubmit(graphics.queue, 1, &graphicsSubmitInfo, VK_NULL_HANDLE))
|
||||||
|
|
||||||
|
graphicsPresentInfo.pImageIndices = &imageIndex;
|
||||||
|
ASSERT_VK(vkQueuePresentKHR(graphics.queue, &graphicsPresentInfo))
|
||||||
|
|
||||||
|
/*** UPDATE ***/
|
||||||
|
// Update dt
|
||||||
|
mapBufferMemory(&compute, compute.dtUniformBufferMemory, &tFrame, sizeof(Dt));
|
||||||
|
ASSERT_VK(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE))
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
drawFrame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown Vulkan
|
shutdownGraphicsVulkan(&graphics);
|
||||||
VkShaderModule modules[3] = {computeShaderModule, vertexShaderModule, fragmentShaderModule};
|
shutdownComputeVulkan(&compute);
|
||||||
VkSemaphore semaphores[2] = {imageAvailable, renderingFinished};
|
|
||||||
shutdownVulkan(&vkInstance, &device, &surface, &swapChain, imageViews, imageViewsSize, modules, 3, &pipelineLayout,
|
|
||||||
1,
|
|
||||||
&renderPass, 1, &pipeline, 1, framebuffers, &commandPool, commandBuffers, semaphores, 2);
|
|
||||||
|
|
||||||
// Shutdown GLFW
|
|
||||||
shutdownGLFW(window);
|
shutdownGLFW(window);
|
||||||
|
|
||||||
return SUCCESS;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user