Neuer Ansatz;
NEW ERROR: vkCreateComputePipeline(); VK_ERROR_OUT_OF_HOST_MEMORY
This commit is contained in:
parent
0815c8a5f2
commit
bf5f9df90f
@ -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} 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 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 vulkanMain.c ${PROJECT_SOURCES_VULKAN})
|
add_executable(Informatikprojekt_Vulkan newVulkan/vulkanMain.c ${PROJECT_SOURCES_VULKAN})
|
||||||
|
|
||||||
# Copy shader file to output directory
|
# Copy shader file to output directory
|
||||||
## OpenGL
|
## 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)
|
configure_file(./shaders/opengl/FragmentShader.glsl ./opengl/FragmentShader.glsl COPYONLY)
|
||||||
## Vulkan
|
## Vulkan
|
||||||
configure_file(./shaders/vulkan/ComputeShader.comp ./vulkan/ComputeShader.comp COPYONLY)
|
configure_file(./shaders/vulkan/ComputeShader.comp ./vulkan/ComputeShader.comp COPYONLY)
|
||||||
configure_file(./shaders/vulkan/VertexShader.vert ./vulkan/VertexShader.vert 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/FragmentShader.frag" ./vulkan/FragmentShader.frag COPYONLY)
|
||||||
configure_file(./shaders/vulkan/runCompiler.bat ./vulkan/runCompiler.bat COPYONLY)
|
configure_file(./shaders/vulkan/runCompiler.bat ./vulkan/runCompiler.bat COPYONLY)
|
||||||
execute_process(COMMAND runCompiler.bat WORKING_DIRECTORY ./vulkan)
|
execute_process(COMMAND runCompiler.bat WORKING_DIRECTORY ./vulkan)
|
||||||
|
|
||||||
|
@ -882,9 +882,9 @@ extern "C" {
|
|||||||
* Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS).
|
* Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS).
|
||||||
*/
|
*/
|
||||||
#define GLFW_ACCUM_ALPHA_BITS 0x0002100A
|
#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
|
#define GLFW_AUX_BUFFERS 0x0002100B
|
||||||
/*! @brief OpenGL stereoscopic rendering hint.
|
/*! @brief OpenGL stereoscopic rendering hint.
|
||||||
|
66
initVulkan.c
66
initVulkan.c
@ -177,6 +177,13 @@ void createImageViewInfo(VkImageViewCreateInfo *imageViewInfo, VkImage *swapChai
|
|||||||
imageViewInfo->subresourceRange = subresourceRange;
|
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)
|
void createAttachmentDescription(VkAttachmentDescription *attachmentDescription)
|
||||||
{
|
{
|
||||||
attachmentDescription->flags = 0;
|
attachmentDescription->flags = 0;
|
||||||
@ -276,19 +283,74 @@ void createCommandPoolInfo(VkCommandPoolCreateInfo *commandPoolInfo, uint32_t qu
|
|||||||
commandPoolInfo->queueFamilyIndex = queueFamilyIndex;
|
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,
|
void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain,
|
||||||
VkImageView *imageViews, uint32_t imageViewsSize, VkShaderModule *modules,
|
VkImageView *imageViews, uint32_t imageViewsSize, VkShaderModule *modules,
|
||||||
uint32_t shaderModulesSize, VkPipelineLayout *pipelineLayouts, uint32_t pipelineLayoutsSize,
|
uint32_t shaderModulesSize, VkPipelineLayout *pipelineLayouts, uint32_t pipelineLayoutsSize,
|
||||||
VkRenderPass *renderPasses, uint32_t renderPassesSize, VkPipeline *pipelines,
|
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);
|
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);
|
vkDestroyCommandPool(*device, *commandPool, NULL);
|
||||||
|
|
||||||
for (int i = 0; i < imageViewsSize; ++i)
|
for (int i = 0; i < imageViewsSize; ++i)
|
||||||
|
23
initVulkan.h
23
initVulkan.h
@ -1,5 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <stdint-gcc.h>
|
||||||
#include "vulkan/vulkan.h"
|
#include "vulkan/vulkan.h"
|
||||||
|
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
@ -14,16 +15,11 @@
|
|||||||
|
|
||||||
#define SUCCESS 0
|
#define SUCCESS 0
|
||||||
#define FAILURE -1
|
#define FAILURE -1
|
||||||
#define ASSERT_SUCCESS(res)\
|
#define ASSERT_SUCCESS(res) { if (res != SUCCESS) { printf("Error-Code: %d", res); return FAILURE; } }
|
||||||
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_VK_SUCCESS(res)\
|
#define ASSERT_GLFW_SUCCESS(res) { if (res != GLFW_TRUE) { printf("Error-Code: %d", res); return FAILURE; } }
|
||||||
if (res != VK_SUCCESS) { printf("Error-Code: %d", res); return FAILURE; }
|
#define BOOL_LITERAL(val) val ? "True" : "False"
|
||||||
#define ASSERT_GLFW_SUCCESS(res)\
|
#define HUMAN_READABLE(val) val * 9.313226e-10
|
||||||
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,
|
int initVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, GLFWwindow *window,
|
||||||
VkSwapchainKHR *swapChain, VkImageView **imageViews, uint32_t *amountImages);
|
VkSwapchainKHR *swapChain, VkImageView **imageViews, uint32_t *amountImages);
|
||||||
@ -53,6 +49,7 @@ void createSubpassDescription(VkSubpassDescription *subpassDescription, VkPipeli
|
|||||||
VkAttachmentReference *attachmentReference);
|
VkAttachmentReference *attachmentReference);
|
||||||
void createRenderPassInfo(VkRenderPassCreateInfo *renderPassInfo, VkAttachmentDescription *attachmentDescriptions,
|
void createRenderPassInfo(VkRenderPassCreateInfo *renderPassInfo, VkAttachmentDescription *attachmentDescriptions,
|
||||||
VkSubpassDescription *subpassDescriptions);
|
VkSubpassDescription *subpassDescriptions);
|
||||||
|
void createSemaphoreInfo(VkSemaphoreCreateInfo *semaphoreInfo);
|
||||||
void createGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo *graphicsPipelineInfo,
|
void createGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo *graphicsPipelineInfo,
|
||||||
VkPipelineShaderStageCreateInfo *shaderStages,
|
VkPipelineShaderStageCreateInfo *shaderStages,
|
||||||
VkPipelineVertexInputStateCreateInfo *vertexInputState,
|
VkPipelineVertexInputStateCreateInfo *vertexInputState,
|
||||||
@ -64,10 +61,14 @@ void createGraphicsPipelineInfo(VkGraphicsPipelineCreateInfo *graphicsPipelineIn
|
|||||||
VkRenderPass *renderPass);
|
VkRenderPass *renderPass);
|
||||||
void createFramebufferInfo(VkFramebufferCreateInfo *framebufferInfo, VkRenderPass *renderPass, VkImageView *imageView);
|
void createFramebufferInfo(VkFramebufferCreateInfo *framebufferInfo, VkRenderPass *renderPass, VkImageView *imageView);
|
||||||
void createCommandPoolInfo(VkCommandPoolCreateInfo *commandPoolInfo, uint32_t queueFamilyIndex);
|
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,
|
void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain,
|
||||||
VkImageView *imageViews, uint32_t imageViewsSize, VkShaderModule *modules,
|
VkImageView *imageViews, uint32_t imageViewsSize, VkShaderModule *modules,
|
||||||
uint32_t shaderModulesSize, VkPipelineLayout *pipelineLayouts, uint32_t pipelineLayoutsSize,
|
uint32_t shaderModulesSize, VkPipelineLayout *pipelineLayouts, uint32_t pipelineLayoutsSize,
|
||||||
VkRenderPass *renderPasses, uint32_t renderPassesSize, VkPipeline *pipelines,
|
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 shutdownGLFW(GLFWwindow *window);
|
||||||
void printStats(VkPhysicalDevice *physicalDevice, VkSurfaceKHR *surface);
|
void printStats(VkPhysicalDevice *physicalDevice, VkSurfaceKHR *surface);
|
||||||
|
477
newVulkan/initVulkan.c
Normal file
477
newVulkan/initVulkan.c
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
#include "initVulkan.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
116
newVulkan/initVulkan.h
Normal file
116
newVulkan/initVulkan.h
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#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 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);
|
77
newVulkan/vulkanMain.c
Normal file
77
newVulkan/vulkanMain.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
#include "initOpenGL.h"
|
#include "initOpenGL.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define PARTICLE_AMOUNT 10000000
|
#define PARTICLE_AMOUNT 15000000
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@ -107,6 +107,7 @@ int main()
|
|||||||
deleteShaders(computeShaders, 1);
|
deleteShaders(computeShaders, 1);
|
||||||
glDeleteProgram(computeShaderProgram);
|
glDeleteProgram(computeShaderProgram);
|
||||||
glDeleteBuffers(1, &particleBuffer);
|
glDeleteBuffers(1, &particleBuffer);
|
||||||
|
glDeleteVertexArrays(1, &vertexArray);
|
||||||
terminateGLFW(window);
|
terminateGLFW(window);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
83
vulkanMain.c
83
vulkanMain.c
@ -1,11 +1,41 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "initVulkan.h"
|
#include "initVulkan.h"
|
||||||
#include "particlesystem.h"
|
#include "particlesystem.h"
|
||||||
|
|
||||||
#define PARTICLE_AMOUNT 0
|
#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;
|
VkInstance vkInstance;
|
||||||
@ -19,6 +49,9 @@ int main()
|
|||||||
VkPipeline pipeline;
|
VkPipeline pipeline;
|
||||||
VkFramebuffer *framebuffers;
|
VkFramebuffer *framebuffers;
|
||||||
VkCommandPool commandPool;
|
VkCommandPool commandPool;
|
||||||
|
VkCommandBuffer *commandBuffers;
|
||||||
|
VkSemaphore imageAvailable;
|
||||||
|
VkSemaphore renderingFinished;
|
||||||
|
|
||||||
/************* INIT *************/
|
/************* INIT *************/
|
||||||
// GLFW
|
// GLFW
|
||||||
@ -59,7 +92,8 @@ int main()
|
|||||||
VkPipelineShaderStageCreateInfo fragmentShaderStageInfo;
|
VkPipelineShaderStageCreateInfo fragmentShaderStageInfo;
|
||||||
createShaderStageInfo(&fragmentShaderStageInfo, VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderModule, "main");
|
createShaderStageInfo(&fragmentShaderStageInfo, VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderModule, "main");
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo shaderStages[3] = { computeShaderStageInfo, vertexShaderStageInfo, fragmentShaderStageInfo };
|
VkPipelineShaderStageCreateInfo shaderStages[3] = {computeShaderStageInfo, vertexShaderStageInfo,
|
||||||
|
fragmentShaderStageInfo};
|
||||||
|
|
||||||
/************* PIPELINE *************/
|
/************* PIPELINE *************/
|
||||||
// Vertex input
|
// Vertex input
|
||||||
@ -133,18 +167,54 @@ int main()
|
|||||||
|
|
||||||
// Allocate info
|
// Allocate info
|
||||||
VkCommandBufferAllocateInfo commandBufferAllocateInfo;
|
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 *************/
|
||||||
while (!glfwWindowShouldClose(window))
|
while (!glfwWindowShouldClose(window))
|
||||||
{
|
{
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
drawFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown Vulkan
|
// 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,
|
shutdownVulkan(&vkInstance, &device, &surface, &swapChain, imageViews, imageViewsSize, modules, 3, &pipelineLayout,
|
||||||
1,
|
1,
|
||||||
&renderPass, 1, &pipeline, 1, framebuffers, &commandPool);
|
&renderPass, 1, &pipeline, 1, framebuffers, &commandPool, commandBuffers, semaphores, 2);
|
||||||
|
|
||||||
// Shutdown GLFW
|
// Shutdown GLFW
|
||||||
shutdownGLFW(window);
|
shutdownGLFW(window);
|
||||||
@ -152,4 +222,11 @@ int main()
|
|||||||
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