From dd5e93864d0ab0693c15125df4b1269d51bfd551 Mon Sep 17 00:00:00 2001 From: Greg Wells Date: Fri, 30 May 2025 13:09:35 -0400 Subject: [PATCH] submitted command buffers + subpass depends --- include/gryphn/gryphn.h | 1 + .../vulkan_render_pass_descriptor.c | 16 +++++- .../vulkan/src/submit/vulkan_submit.c | 55 +++++++++++++++++++ src/core/gryphn_platform_functions.h | 3 + src/core/instance/init/gryphn_init.c | 1 + .../gryphn_render_pass_descriptor.h | 23 ++++++++ src/core/submit/gryphn_submit.c | 6 ++ src/core/submit/gryphn_submit.h | 20 +++++++ src/utils/gryphn_error_code.h | 4 +- 9 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 rendering_api/vulkan/src/submit/vulkan_submit.c create mode 100644 src/core/submit/gryphn_submit.c create mode 100644 src/core/submit/gryphn_submit.h diff --git a/include/gryphn/gryphn.h b/include/gryphn/gryphn.h index 8d462d8..ccd94a0 100644 --- a/include/gryphn/gryphn.h +++ b/include/gryphn/gryphn.h @@ -19,3 +19,4 @@ #include #include #include +#include diff --git a/rendering_api/vulkan/src/renderpass/vulkan_render_pass_descriptor.c b/rendering_api/vulkan/src/renderpass/vulkan_render_pass_descriptor.c index 7ca8713..fc880a2 100644 --- a/rendering_api/vulkan/src/renderpass/vulkan_render_pass_descriptor.c +++ b/rendering_api/vulkan/src/renderpass/vulkan_render_pass_descriptor.c @@ -57,12 +57,26 @@ gnReturnCode gnCreateRenderPassDescriptorFn(struct gnRenderPassDescriptor_t* ren subpasses[i].pColorAttachments = colorAttachments; } + VkSubpassDependency* dependencies = malloc(sizeof(VkSubpassDependency) * info.dependencyCount); + for (int i = 0; i < info.dependencyCount; i++) { + dependencies[i] = (VkSubpassDependency) { + .srcSubpass = (info.dependencies[i].source == GN_SUBPASS_EXTERNAL) ? VK_SUBPASS_EXTERNAL : info.dependencies[i].source, + .dstSubpass = (info.dependencies[i].destination == GN_SUBPASS_EXTERNAL) ? VK_SUBPASS_EXTERNAL : info.dependencies[i].destination, + .srcStageMask = info.dependencies[i].soruceStageMask, + .srcAccessMask = info.dependencies[i].sourceAccessMask, + .dstStageMask = info.dependencies[i].destinationStageMask, + .dstAccessMask = info.dependencies[i].destinationAccessMask + }; + } + VkRenderPassCreateInfo renderPassInfo = (VkRenderPassCreateInfo){ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .attachmentCount = info.attachmentCount, .pAttachments = attachments, .subpassCount = info.subpassCount, - .pSubpasses = subpasses + .pSubpasses = subpasses, + .dependencyCount = info.dependencyCount, + .pDependencies = dependencies }; if (vkCreateRenderPass(device->outputDevice->device, &renderPassInfo, NULL, &renderPass->renderPassDescriptor->renderPass) != VK_SUCCESS) { diff --git a/rendering_api/vulkan/src/submit/vulkan_submit.c b/rendering_api/vulkan/src/submit/vulkan_submit.c new file mode 100644 index 0000000..a75b684 --- /dev/null +++ b/rendering_api/vulkan/src/submit/vulkan_submit.c @@ -0,0 +1,55 @@ +#include +#include "core/submit/gryphn_submit.h" +#include "sync/semaphore/vulkan_semaphore.h" +#include "sync/fence/vulkan_fence.h" +#include "commands/command_buffer/vulkan_command_buffer.h" +#include "output_device/vulkan_output_devices.h" +#include "core/renderpass/gryphn_render_pass_descriptor.h" + +VkPipelineStageFlags vkGryphnWaitStage(enum gnRenderPassStage_e stage) { + switch(stage) { + case GN_COLOR_ATTACHMENT_OUTPUT: return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + } +} + +gnReturnCode gnSubmitFn(struct gnOutputDevice_t* device, struct gnSubmitInfo_t info) { + VK_SUBPASS_EXTERNAL; + + VkSemaphore* waitSemaphores = malloc(sizeof(VkSemaphore) * info.waitCount); + VkPipelineStageFlags* waitStages = malloc(sizeof(VkPipelineStageFlags) * info.waitCount); + for (int i = 0; i < info.waitCount; i++) waitSemaphores[i] = info.waitSemaphores[i].semaphore->semaphore; + for (int i = 0; i < info.waitCount; i++) waitStages[i] = vkGryphnWaitStage(info.waitStages[i]); + + VkCommandBuffer* commandBuffers = malloc(sizeof(VkCommandBuffer) * info.commandBufferCount); + for (int i = 0; i < info.commandBufferCount; i++) commandBuffers[i] = info.commandBuffers[i].commandBuffer->buffer; + + VkSemaphore* signalSemaphores = malloc(sizeof(VkSemaphore) * info.signalCount); + for (int i = 0; i < info.signalCount; i++) signalSemaphores[i] = info.signalSemaphores[i].semaphore->semaphore; + + VkSubmitInfo submitInfo = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .waitSemaphoreCount = info.waitCount, + .pWaitSemaphores = waitSemaphores, + .pWaitDstStageMask = waitStages, + .commandBufferCount = info.commandBufferCount, + .pCommandBuffers = commandBuffers, + .signalSemaphoreCount = info.signalCount, + .pSignalSemaphores = signalSemaphores + }; + + VkQueue queue; + vkGetDeviceQueue(device->outputDevice->device, info.queueIndex, 0, &queue); + + if (vkQueueSubmit(queue, 1, &submitInfo, info.fence->fence->fence) != VK_SUCCESS) { + free(waitSemaphores); + free(waitStages); + free(commandBuffers); + free(signalSemaphores); + return GN_FAILED_TO_SUBMIT_COMMAND_BUFFER; + } + free(waitSemaphores); + free(waitStages); + free(commandBuffers); + free(signalSemaphores); + return GN_SUCCESS; +} diff --git a/src/core/gryphn_platform_functions.h b/src/core/gryphn_platform_functions.h index e1d11f1..2cb0385 100644 --- a/src/core/gryphn_platform_functions.h +++ b/src/core/gryphn_platform_functions.h @@ -16,6 +16,7 @@ #include "renderpass/gryphn_render_pass.h" #include "sync/fence/gryphn_fence.h" #include "sync/semaphore/gryphn_semaphore.h" +#include "core/submit/gryphn_submit.h" typedef struct gnFunctions_t { gnReturnCode (*_gnCreateInstance)(gnInstance* instance, struct gnInstanceInfo_t info); @@ -84,6 +85,8 @@ typedef struct gnDeviceFunctions_t { void (*_gnWaitForFence)(struct gnFence_t* fence, uint64_t timeout); void (*_gnResetFence)(struct gnFence_t* fence); void (*_gnDestroyFence)(struct gnFence_t* fence); + + gnReturnCode (*_gnSubmit)(struct gnOutputDevice_t* device, struct gnSubmitInfo_t submit); } gnDeviceFunctions; typedef struct gnCommandFunctions_t { diff --git a/src/core/instance/init/gryphn_init.c b/src/core/instance/init/gryphn_init.c index eab3abe..b41d08b 100644 --- a/src/core/instance/init/gryphn_init.c +++ b/src/core/instance/init/gryphn_init.c @@ -89,6 +89,7 @@ void gnLoadDeviceFunctions(struct gnDynamicLibrary_t* lib, struct gnDeviceFuncti gnLoadDLLFunction(lib, functions->_gnWaitForFence, "gnWaitForFenceFn"); gnLoadDLLFunction(lib, functions->_gnResetFence, "gnResetFenceFn"); gnLoadDLLFunction(lib, functions->_gnDestroyFence, "gnDestroyFenceFn"); + gnLoadDLLFunction(lib, functions->_gnSubmit, "gnSubmitFn"); } void gnLoadCommandFunctions(struct gnDynamicLibrary_t* lib, struct gnCommandFunctions_t* functions) { diff --git a/src/core/renderpass/gryphn_render_pass_descriptor.h b/src/core/renderpass/gryphn_render_pass_descriptor.h index cb71b22..fa4c435 100644 --- a/src/core/renderpass/gryphn_render_pass_descriptor.h +++ b/src/core/renderpass/gryphn_render_pass_descriptor.h @@ -3,6 +3,14 @@ #include "stdint.h" #include "core/output_device/gryphn_output_device.h" +typedef enum gnRenderPassStage_e { + GN_COLOR_ATTACHMENT_OUTPUT = 0x00000400 +} gnRenderPassStage; // I stole these from vulkan to make that conversion easier + +typedef enum gnRenderPassAccess_e { + GN_COLOR_ATTACHMENT_WRITE = 0x00000100 +} gnRenderPassAccess; + typedef enum gnLoadOperation_e { GN_LOAD_OPERATION_LOAD, GN_LOAD_OPERATION_CLEAR, GN_LOAD_OPERATION_DONT_CARE } gnLoadOperation; @@ -33,12 +41,27 @@ typedef struct gnSubpassInfo_t { struct gnSubpassAttachmentInfo_t* colorAttachments; } gnSubpassInfo; +#define GN_SUBPASS_EXTERNAL -1 + +typedef struct gnSubpassDependencyInfo_t { + int source, destination; + + enum gnRenderPassStage_e soruceStageMask; + enum gnRenderPassAccess_e sourceAccessMask; + + enum gnRenderPassStage_e destinationStageMask; + enum gnRenderPassAccess_e destinationAccessMask; +} gnSubpassDependencyInfo; + typedef struct gnRenderPassDescriptorInfo_t { uint32_t attachmentCount; struct gnRenderPassAttachmentInfo_t* attachmentInfos; uint32_t subpassCount; struct gnSubpassInfo_t* subpassInfos; + + uint32_t dependencyCount; + struct gnSubpassDependencyInfo_t* dependencies; } gnRenderPassDescriptorInfo; struct gnPlatformRenderPassDescriptor_t; diff --git a/src/core/submit/gryphn_submit.c b/src/core/submit/gryphn_submit.c new file mode 100644 index 0000000..2496002 --- /dev/null +++ b/src/core/submit/gryphn_submit.c @@ -0,0 +1,6 @@ +#include "gryphn_submit.h" +#include "core/gryphn_platform_functions.h" + +gnReturnCode gnSubmit(struct gnOutputDevice_t* device, struct gnSubmitInfo_t info) { + return device->deviceFunctions->_gnSubmit(device, info); +} diff --git a/src/core/submit/gryphn_submit.h b/src/core/submit/gryphn_submit.h new file mode 100644 index 0000000..6e1fabe --- /dev/null +++ b/src/core/submit/gryphn_submit.h @@ -0,0 +1,20 @@ +#pragma once +#include "stdint.h" +#include "core/sync/semaphore/gryphn_semaphore.h" +#include "core/sync/fence/gryphn_fence.h" +#include "core/command/command_buffer/gryphn_command_buffer.h" +#include "core/output_device/gryphn_output_device.h" + +typedef struct gnSubmitInfo_t { + uint32_t waitCount; + enum gnRenderPassStage_e* waitStages; + struct gnSemaphore_t* waitSemaphores; + uint32_t signalCount; + struct gnSemaphore_t* signalSemaphores; + uint32_t commandBufferCount; + struct gnCommandBuffer_t* commandBuffers; + uint32_t queueIndex; + struct gnFence_t* fence; +} gnSubmitInfo; + +gnReturnCode gnSubmit(struct gnOutputDevice_t* device, struct gnSubmitInfo_t submit); diff --git a/src/utils/gryphn_error_code.h b/src/utils/gryphn_error_code.h index c204169..2bd846f 100644 --- a/src/utils/gryphn_error_code.h +++ b/src/utils/gryphn_error_code.h @@ -32,7 +32,8 @@ typedef enum gnReturnCode_t { GN_FAIELD_TO_END_RECORDING, GN_FAILED_TO_ALLOCATE_COMMAND_BUFFERS, GN_FAILED_TO_CREATE_FENCE, - GN_FAILED_TO_CREATE_SEMAPHORE + GN_FAILED_TO_CREATE_SEMAPHORE, + GN_FAILED_TO_SUBMIT_COMMAND_BUFFER } gnReturnCode; typedef gnReturnCode gnErrorCode; @@ -70,5 +71,6 @@ static const char* gnErrorCodeToCString(enum gnReturnCode_t returnCode) { case GN_FAILED_TO_ALLOCATE_COMMAND_BUFFERS: return "GN_FAILED_TO_ALLOCATE_COMMAND_BUFFERS"; case GN_FAILED_TO_CREATE_FENCE: return "GN_FAILED_TO_CREATE_FENCE"; case GN_FAILED_TO_CREATE_SEMAPHORE: return "GN_FAILED_TO_CREATE_SEMAPHORE"; + case GN_FAILED_TO_SUBMIT_COMMAND_BUFFER: return "GN_FAILED_TO_SUBMIT_COMMAND_BUFFER"; } }