diff --git a/src/gpu/gpu.h b/src/gpu/gpu.h index 3122268..b8803f3 100644 --- a/src/gpu/gpu.h +++ b/src/gpu/gpu.h @@ -129,20 +129,20 @@ typedef enum GpuFormat { typedef enum GpuColorspace { GPU_COLOR_SPACE_SRGB_NONLINEAR, - GPU_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT, - GPU_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT, - GPU_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, - GPU_COLOR_SPACE_DCI_P3_NONLINEAR_EXT, - GPU_COLOR_SPACE_BT709_LINEAR_EXT, - GPU_COLOR_SPACE_BT709_NONLINEAR_EXT, - GPU_COLOR_SPACE_BT2020_LINEAR_EXT, - GPU_COLOR_SPACE_HDR10_ST2084_EXT, - GPU_COLOR_SPACE_DOLBYVISION_EXT, - GPU_COLOR_SPACE_HDR10_HLG_EXT, - GPU_COLOR_SPACE_ADOBERGB_LINEAR_EXT, - GPU_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT, - GPU_COLOR_SPACE_PASS_THROUGH_EXT, - GPU_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT, + GPU_COLOR_SPACE_DISPLAY_P3_NONLINEAR, + GPU_COLOR_SPACE_EXTENDED_SRGB_LINEAR, + GPU_COLOR_SPACE_DISPLAY_P3_LINEAR, + GPU_COLOR_SPACE_DCI_P3_NONLINEAR, + GPU_COLOR_SPACE_BT709_LINEAR, + GPU_COLOR_SPACE_BT709_NONLINEAR, + GPU_COLOR_SPACE_BT2020_LINEAR, + GPU_COLOR_SPACE_HDR10_ST2084, + GPU_COLOR_SPACE_DOLBYVISION, + GPU_COLOR_SPACE_HDR10_HLG, + GPU_COLOR_SPACE_ADOBERGB_LINEAR, + GPU_COLOR_SPACE_ADOBERGB_NONLINEAR, + GPU_COLOR_SPACE_PASS_THROUGH, + GPU_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR, GPU_COLORSPACE_SRGB_NONLINEAR, } GpuColorspace; @@ -348,8 +348,21 @@ typedef struct GpuBufferCreateRequest { } GpuBufferCreateRequest; typedef struct GpuFence GpuFence; +typedef GpuFence **GpuFencePtrArray; + +typedef struct GpuResetFencesRequest { + GpuDevice *device; + GpuFencePtrArray fences; +} GpuResetFencesRequest; + +typedef struct GpuWaitForFencesRequest { + GpuDevice *device; + GpuFencePtrArray fences; + u64 timeout; +} GpuWaitForFencesRequest; typedef struct GpuSemaphore GpuSemaphore; +typedef struct GpuSemaphore **GpuSemaphorePtrArray; typedef struct GpuSwapchainAcquireImageRequest { GpuSwapchain *swapchain; @@ -358,6 +371,38 @@ typedef struct GpuSwapchainAcquireImageRequest { u64 timeout; } GpuSwapchainAcquireImageRequest; +typedef struct GpuSwapchainGetColorImageRequest { + GpuSwapchain *swapchain; + u64 index; +} GpuSwapchainGetColorImageRequest; + +typedef struct GpuSwapchainAcquireImageResult { + u64 image_index; + b32 swapchain_out_of_date; +} GpuSwapchainAcquireImageResult; + +typedef struct GpuSwpachainPresentInfo { + GpuSwapchain *swapchain; + u32 image_index; +} GpuSwpachainPresentInfo; +typedef GpuSwpachainPresentInfo *GpuSwpachainPresentInfoArray; + +typedef struct GpuSwapchainsPresentRequest { + GpuDevice *device; + GpuSemaphorePtrArray wait_semaphores; + GpuSwpachainPresentInfoArray swapchain_infos; +} GpuSwapchainsPresentRequest; + +typedef enum GpuSwapchainPresentError { + GPU_SWAPCHAIN_PRESENT_ERROR_NONE, + GPU_SWAPCHAIN_PRESENT_ERROR_OUT_OF_DATE, +} GpuSwapchainPresentError; +typedef GpuSwapchainPresentError *GpuSwapchainPresentErrorArray; + +typedef struct GpuSwapchainsPresentResult { + GpuSwapchainPresentErrorArray errors; +} GpuSwapchainsPresentResult; + typedef struct GpuCommandPool GpuCommandPool; typedef struct GpuCommandBuffer GpuCommandBuffer; @@ -369,6 +414,7 @@ typedef struct GpuCommandBufferAllocateRequest { } GpuCommandBufferAllocateRequest; typedef u64 GpuPipelineStageFlags; +typedef GpuPipelineStageFlags *GpuPipelineStageFlagsArray; typedef u64 GpuPipelineStageFlagsBits; wp_intern const GpuPipelineStageFlagsBits GPU_PIPELINE_STAGE_NONE = wpU64Const(0); wp_intern const GpuPipelineStageFlagsBits GPU_PIPELINE_STAGE_TOP_OF_PIPE = wpU64Const(1) << 1; @@ -463,10 +509,18 @@ typedef struct GpuCommandBufferBeginRequest { b32 one_time_submit; } GpuCommandBufferBeginRequest; +typedef struct GpuSemaphoreSubmitInfo { + GpuSemaphore *semaphore; + GpuPipelineStageFlags stage_mask; +} GpuSemaphoreSubmitInfo; +typedef GpuSemaphoreSubmitInfo *GpuSemaphoreSubmitInfoArray; + typedef struct GpuCommandBuffersSubmitRequest { - GpuDevice *device; - GpuFence *fence; - GpuCommandBufferPtrArray command_buffers; + GpuDevice *device; + GpuFence *fence; + GpuSemaphoreSubmitInfoArray wait_semaphore_infos; + GpuCommandBufferPtrArray command_buffers; + GpuSemaphoreSubmitInfoArray signal_semaphore_infos; } GpuCommandBuffersSubmitRequest; typedef enum GpuDescriptorType { @@ -1050,6 +1104,14 @@ typedef struct GpuCmdDrawIndexedRequest { u32 first_instance; } GpuCmdDrawIndexedRequest; +typedef struct GpuCmdDrawRequest { + GpuCommandBuffer *command_buffer; + u32 vertex_count; + u32 instance_count; + u32 first_vertex; + u32 first_instance; +} GpuCmdDrawRequest; + typedef struct GpuCmdDispatchRequest { GpuCommandBuffer *command_buffer; u32 group_count_x; @@ -1067,76 +1129,88 @@ typedef struct GpuCmdDispatchBaseRequest { u32 group_count_z; } GpuCmdDispatchBaseRequest; -GpuInstance *gpuInit(const WpAllocator *allocator, GpuInitRequest request); -GpuPhysicalDevice gpuFindPhysicalDevice(const WpAllocator *allocator, const WpAllocator *temp, - GpuPhysicalDeviceFindRequest request); -GpuSurface *gpuCreateSurface(const WpAllocator *allocator, GpuSurfaceCreateRequest request); -void gpuDestroySurface(GpuSurface *surface); -GpuDevice *gpuCreateDevice(const WpAllocator *allocator, GpuPhysicalDevice physical_device); -void gpuDestroyDevice(GpuDevice *device); -GpuSwapchain *gpuCreateSwapchain(const WpAllocator *allocator, const WpAllocator *temp, - GpuSwapchainCreateRequest request); -void gpuDestroySwapchain(GpuSwapchain *swapchain); -u64 gpuGetSwapchainImageCount(GpuSwapchain *swapchain); -GpuFormat gpuGetSwapchainImageFormat(GpuSwapchain *swapchain); -GpuFormat gpuGetSwapchainDepthFormat(GpuSwapchain *swapchain); -u64 gpuAcquireNextSwapchainImage(GpuSwapchainAcquireImageRequest request); -GpuSampler *gpuCreateSampler(const WpAllocator *allocator, GpuSamplerCreateRequest request); -void gpuDestroySampler(GpuSampler *sampler); -GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest request); -void gpuDestroyImage(GpuImage *image); -ivec3s gpuImageGetSize(GpuImage *image); -GpuBuffer gpuCreateBuffer(const WpAllocator *allocator, GpuBufferCreateRequest request); -void gpuDestroyBuffer(GpuBuffer *buffer); -GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device); -void gpuDestroyFence(GpuFence *fence); -void gpuResetFence(GpuFence *fence); -GpuSemaphore *gpuCreateSemaphore(const WpAllocator *allocator, GpuDevice *device); -void gpuDestroySemaphore(GpuSemaphore *semaphore); -GpuCommandPool *gpuCreateCommandPool(const WpAllocator *allocator, GpuDevice *device); -void gpuDestroyCommandPool(GpuCommandPool *pool); -void gpuResetCommandPool(GpuCommandPool *pool); -GpuCommandBufferPtrArray gpuAllocateCommandBuffers(const WpAllocator *allocator, const WpAllocator *temp, - GpuCommandBufferAllocateRequest request); -void gpuBeginCommandBuffer(GpuCommandBufferBeginRequest request); -void gpuEndCommandBuffer(GpuCommandBuffer *buffer); -void gpuSubmitCommandBuffers(const WpAllocator *temp, GpuCommandBuffersSubmitRequest request); -void gpuResetCommandBuffer(GpuCommandBuffer *buffer); -GpuDescriptorPool *gpuCreateDescriptorPool(const WpAllocator *allocator, GpuDescriptorPoolCreateRequest request); -void gpuDestroyDescriptorPool(GpuDescriptorPool *pool); -void gpuResetDescriptorPool(GpuDescriptorPool *pool); -GpuDescriptorSetLayout *gpuCreateDescriptorSetLayout(const WpAllocator *allocator, const WpAllocator *temp, - GpuDescriptorSetLayoutCreateRequest request); -void gpuDestroyDescriptorSetLayout(GpuDescriptorSetLayout *layout); -GpuDescriptorSetPtrArray gpuAllocateDescriptorSets(const WpAllocator *allocator, const WpAllocator *temp, - GpuDescriptorSetAllocateRequest request); -void gpuWriteDescriptorSets(const WpAllocator *temp, GpuDescriptorSetWriteRequest request); -GpuShader *gpuCreateShader(const WpAllocator *allocator, GpuShaderCreateRequest request); -void gpuDestroyShader(GpuShader *shader); -GpuPipelineLayout *gpuCreatePipelineLayout(const WpAllocator *allocator, const WpAllocator *temp, - GpuPipelineLayoutCreateRequest request); -void gpuDestroyPipelineLayout(GpuPipelineLayout *layout); -GpuPipelinePtrArray gpuCreateGraphicsPipelines(const WpAllocator *allocator, const WpAllocator *temp, - GpuGraphicsPipelinesCreateRequest request); -GpuPipelinePtrArray gpuCreateComputePipelines(const WpAllocator *allocator, const WpAllocator *temp, - GpuComputePipelinesCreateRequest request); -void gpuDestroyPipeline(GpuPipeline *pipeline); -void gpuDeviceWaitIdle(GpuDevice *device); +typedef struct GpuQueueSubmitRequest { + GpuSemaphorePtrArray wait_semaphores; + GpuPipelineStageFlagsArray wait_dst_stage_masks; + GpuCommandBufferPtrArray command_buffers; + GpuSemaphorePtrArray signal_semaphores; +} GpuQueueSubmitRequest; + +GpuInstance *gpuInit(const WpAllocator *allocator, GpuInitRequest request); +GpuPhysicalDevice gpuFindPhysicalDevice(const WpAllocator *allocator, const WpAllocator *temp, + GpuPhysicalDeviceFindRequest request); +GpuSurface *gpuCreateSurface(const WpAllocator *allocator, GpuSurfaceCreateRequest request); +void gpuDestroySurface(GpuSurface *surface); +GpuDevice *gpuCreateDevice(const WpAllocator *allocator, GpuPhysicalDevice physical_device); +void gpuDestroyDevice(GpuDevice *device); +GpuSwapchain *gpuCreateSwapchain(const WpAllocator *allocator, const WpAllocator *temp, + GpuSwapchainCreateRequest request); +void gpuDestroySwapchain(GpuSwapchain *swapchain); +u64 gpuGetSwapchainImageCount(GpuSwapchain *swapchain); +GpuFormat gpuGetSwapchainImageFormat(GpuSwapchain *swapchain); +GpuFormat gpuGetSwapchainDepthFormat(GpuSwapchain *swapchain); +GpuSwapchainAcquireImageResult gpuAcquireNextSwapchainImage(GpuSwapchainAcquireImageRequest request); +GpuImage *gpuGetSwapchainColorImage(GpuSwapchainGetColorImageRequest request); +GpuImage *gpuGetSwapchainDepthImage(GpuSwapchain *swapchain); +GpuSwapchainsPresentResult gpuPresentSwapchains(const WpAllocator *temp, GpuSwapchainsPresentRequest request); +GpuSampler *gpuCreateSampler(const WpAllocator *allocator, GpuSamplerCreateRequest request); +void gpuDestroySampler(GpuSampler *sampler); +GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest request); +void gpuDestroyImage(GpuImage *image); +ivec3s gpuImageGetSize(GpuImage *image); +GpuBuffer gpuCreateBuffer(const WpAllocator *allocator, GpuBufferCreateRequest request); +void gpuDestroyBuffer(GpuBuffer *buffer); +GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device); +void gpuDestroyFence(GpuFence *fence); +void gpuResetFences(const WpAllocator *temp, GpuResetFencesRequest request); +void gpuWaitForFences(const WpAllocator *temp, GpuWaitForFencesRequest request); +GpuSemaphore *gpuCreateSemaphore(const WpAllocator *allocator, GpuDevice *device); +void gpuDestroySemaphore(GpuSemaphore *semaphore); +GpuCommandPool *gpuCreateCommandPool(const WpAllocator *allocator, GpuDevice *device); +void gpuDestroyCommandPool(GpuCommandPool *pool); +void gpuResetCommandPool(GpuCommandPool *pool); +GpuCommandBufferPtrArray gpuAllocateCommandBuffers(const WpAllocator *allocator, const WpAllocator *temp, + GpuCommandBufferAllocateRequest request); +void gpuBeginCommandBuffer(GpuCommandBufferBeginRequest request); +void gpuEndCommandBuffer(GpuCommandBuffer *buffer); +void gpuSubmitCommandBuffers(const WpAllocator *temp, GpuCommandBuffersSubmitRequest request); +void gpuResetCommandBuffer(GpuCommandBuffer *buffer); +GpuDescriptorPool *gpuCreateDescriptorPool(const WpAllocator *allocator, GpuDescriptorPoolCreateRequest request); +void gpuDestroyDescriptorPool(GpuDescriptorPool *pool); +void gpuResetDescriptorPool(GpuDescriptorPool *pool); +GpuDescriptorSetLayout *gpuCreateDescriptorSetLayout(const WpAllocator *allocator, const WpAllocator *temp, + GpuDescriptorSetLayoutCreateRequest request); +void gpuDestroyDescriptorSetLayout(GpuDescriptorSetLayout *layout); +GpuDescriptorSetPtrArray gpuAllocateDescriptorSets(const WpAllocator *allocator, const WpAllocator *temp, + GpuDescriptorSetAllocateRequest request); +void gpuWriteDescriptorSets(const WpAllocator *temp, GpuDescriptorSetWriteRequest request); +GpuShader *gpuCreateShader(const WpAllocator *allocator, GpuShaderCreateRequest request); +void gpuDestroyShader(GpuShader *shader); +GpuPipelineLayout *gpuCreatePipelineLayout(const WpAllocator *allocator, const WpAllocator *temp, + GpuPipelineLayoutCreateRequest request); +void gpuDestroyPipelineLayout(GpuPipelineLayout *layout); +GpuPipelinePtrArray gpuCreateGraphicsPipelines(const WpAllocator *allocator, const WpAllocator *temp, + GpuGraphicsPipelinesCreateRequest request); +GpuPipelinePtrArray gpuCreateComputePipelines(const WpAllocator *allocator, const WpAllocator *temp, + GpuComputePipelinesCreateRequest request); +void gpuDestroyPipeline(GpuPipeline *pipeline); +void gpuDeviceWaitIdle(GpuDevice *device); // COMMANDS -void gpuCmdPipelineBarrier(const WpAllocator *temp, GpuCmdPipelineBarrierRequest request); -void gpuCmdBeginRendering(const WpAllocator *temp, GpuCmdBeginRenderingRequest request); -void gpuCmdEndRendering(GpuCommandBuffer *buffer); -void gpuCmdSetViewport(const WpAllocator *temp, GpuCmdSetViewportRequest request); -void gpuCmdSetScissor(const WpAllocator *temp, GpuCmdSetScissorRequest request); -void gpuCmdBindPipeline(GpuCmdBindPipelineRequest request); -void gpuCmdBindDescriptorSets(const WpAllocator *temp, GpuCmdBindDescriptorSetsRequest request); -void gpuCmdBindVertexBuffers(const WpAllocator *temp, GpuCmdBindVertexBuffersRequest request); -void gpuCmdBindIndexBuffer(GpuCmdBindIndexBufferRequest request); -void gpuCmdPushConstants(GpuCmdPushConstantsRequest request); -void gpuCmdDrawIndexed(GpuCmdDrawIndexedRequest request); -void gpuCmdDispatch(GpuCmdDispatchRequest request); -void gpuCmdDispatchBase(GpuCmdDispatchBaseRequest request); +void gpuCmdPipelineBarrier(const WpAllocator *temp, GpuCmdPipelineBarrierRequest request); +void gpuCmdBeginRendering(const WpAllocator *temp, GpuCmdBeginRenderingRequest request); +void gpuCmdEndRendering(GpuCommandBuffer *buffer); +void gpuCmdSetViewport(const WpAllocator *temp, GpuCmdSetViewportRequest request); +void gpuCmdSetScissor(const WpAllocator *temp, GpuCmdSetScissorRequest request); +void gpuCmdBindPipeline(GpuCmdBindPipelineRequest request); +void gpuCmdBindDescriptorSets(const WpAllocator *temp, GpuCmdBindDescriptorSetsRequest request); +void gpuCmdBindVertexBuffers(const WpAllocator *temp, GpuCmdBindVertexBuffersRequest request); +void gpuCmdBindIndexBuffer(GpuCmdBindIndexBufferRequest request); +void gpuCmdPushConstants(GpuCmdPushConstantsRequest request); +void gpuCmdDraw(GpuCmdDrawRequest request); +void gpuCmdDrawIndexed(GpuCmdDrawIndexedRequest request); +void gpuCmdDispatch(GpuCmdDispatchRequest request); +void gpuCmdDispatchBase(GpuCmdDispatchBaseRequest request); #ifdef WP_PLATFORM_CPP END_C_LINKAGE diff --git a/src/gpu/vulkan/vk_gpu.c b/src/gpu/vulkan/vk_gpu.c index 7d4cf7b..40c0664 100644 --- a/src/gpu/vulkan/vk_gpu.c +++ b/src/gpu/vulkan/vk_gpu.c @@ -25,13 +25,17 @@ wp_intern WpLogger logger = wpLogMakeLogger(wpStr8LitRo("Vulkan Wrapper")); +typedef VkResult *VkResultArray; typedef VkPhysicalDevice *VkPhysicalDeviceArray; typedef VkQueueFamilyProperties2 *VkQueueFamilyProperties2Array; +typedef VkSwapchainKHR *VkSwapchainKHRArray; typedef VkBuffer *VkBufferArray; typedef VkImage *VkImageArray; typedef VkImageView *VkImageViewArray; typedef VkFormat *VkFormatArray; typedef VkSurfaceFormat2KHR *VkSurfaceFormat2KHRArray; +typedef VkFence *VkFenceArray; +typedef VkSemaphore *VkSemaphoreArray; typedef VkCommandBuffer *VkCommandBufferArray; typedef VkDescriptorPoolSize *VkDescriptorPoolSizeArray; typedef VkDescriptorBindingFlags *VkDescriptorBindingFlagsArray; @@ -67,6 +71,8 @@ typedef VkMemoryBarrier2 *VkMemoryBarrier2Arra typedef VkBufferMemoryBarrier2 *VkBufferMemoryBarrier2Array; typedef VkImageMemoryBarrier2 *VkImageMemoryBarrier2Array; typedef VkRenderingAttachmentInfo *VkRenderingAttachmentInfoArray; +typedef VkSemaphoreSubmitInfo *VkSemaphoreSubmitInfoArray; +typedef VkCommandBufferSubmitInfo *VkCommandBufferSubmitInfoArray; struct GpuInstance { VkInstance vk_instance; @@ -712,23 +718,98 @@ GpuFormat gpuGetSwapchainDepthFormat(GpuSwapchain *swapchain) { return gpuFormatFromVkFormat(swapchain->depth.format); } -u64 gpuAcquireNextSwapchainImage(GpuSwapchainAcquireImageRequest request) { - u32 output = 0; +GpuSwapchainAcquireImageResult gpuAcquireNextSwapchainImage(GpuSwapchainAcquireImageRequest request) { + u32 image_index = 0; VkAcquireNextImageInfoKHR info = { - .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR, - .swapchain = request.swapchain->vk_swapchain, - .timeout = request.timeout, - .semaphore = request.semaphore != NULL ? request.semaphore->vk_semaphore : VK_NULL_HANDLE, - .fence = request.fence != NULL ? request.fence->vk_fence : VK_NULL_HANDLE, + .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR, + .swapchain = request.swapchain->vk_swapchain, + .timeout = request.timeout, + .semaphore = request.semaphore != NULL ? request.semaphore->vk_semaphore : VK_NULL_HANDLE, + .fence = request.fence != NULL ? request.fence->vk_fence : VK_NULL_HANDLE, + .deviceMask = 1, }; - VkResult vk_result = vkAcquireNextImage2KHR(request.swapchain->device->vk_device, &info, &output); - assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to acquire next swapchain image"); + VkResult vk_result = vkAcquireNextImage2KHR(request.swapchain->device->vk_device, &info, &image_index); + b32 failed = vk_result != VK_SUCCESS && vk_result != VK_SUBOPTIMAL_KHR && + vk_result != VK_ERROR_OUT_OF_DATE_KHR; + assertWithLogger(!failed, &logger, "Failed to acquire next swapchain image"); WpStr8 msg = wpStr8Buf(4096); - wpStr8Format(&msg, "Acquired swapchain image #%" PRIu32, output); + wpStr8Format(&msg, "Acquired swapchain image #%" PRIu32, image_index); wpLogDebug(&logger, msg); + return (GpuSwapchainAcquireImageResult){ + .image_index = image_index, + .swapchain_out_of_date = vk_result != VK_SUCCESS, + }; +} + +GpuImage *gpuGetSwapchainColorImage(GpuSwapchainGetColorImageRequest request) { + return wpArrayGet(GpuImage, request.swapchain->images, request.index); +} + +GpuImage *gpuGetSwapchainDepthImage(GpuSwapchain *swapchain) { + return &swapchain->depth; +} + +GpuSwapchainsPresentResult gpuPresentSwapchains(const WpAllocator *temp, GpuSwapchainsPresentRequest request) { + GpuSwapchainsPresentResult output = {0}; + + u64 swapchain_count = wpArrayCount(request.swapchain_infos); + VkSwapchainKHRArray swapchains = wpArrayAllocCapacity(VkSwapchainKHR, temp, swapchain_count, + WP_ARRAY_INIT_FILLED); + WpU32Array image_indices = wpArrayAllocCapacity(u32, temp, swapchain_count, WP_ARRAY_INIT_FILLED); + VkResultArray vk_results = wpArrayAllocCapacity(VkResult, temp, swapchain_count, + WP_ARRAY_INIT_FILLED); + assertWithLogger(swapchains != NULL && image_indices != NULL && vk_results != NULL, &logger, + "Failed to allocate swapchain present temp arrays"); + + for (u64 i = 0; i < swapchain_count; ++i) { + assertWithLogger(request.swapchain_infos[i].swapchain->device->vk_device == request.device->vk_device, + &logger, "Swapchain was created using a different device than the one in the request"); + swapchains[i] = request.swapchain_infos[i].swapchain->vk_swapchain; + image_indices[i] = request.swapchain_infos[i].image_index; + } + + VkSemaphoreArray wait_semaphores = VK_NULL_HANDLE; + u64 wait_semaphore_count = 0; + if (request.wait_semaphores != NULL) { + wait_semaphore_count = wpArrayCount(request.wait_semaphores); + wait_semaphores = wpArrayAllocCapacity(VkSemaphore, temp, wait_semaphore_count, + WP_ARRAY_INIT_FILLED); + assertWithLogger(wait_semaphores != NULL, &logger, "Failed to allocate wait semaphores temp array"); + + for (u64 i = 0; i < wait_semaphore_count; ++i) { + assertWithLogger(request.wait_semaphores[i]->device->vk_device == request.device->vk_device, + &logger, "Semaphore was created using a different device than the one in the request"); + wait_semaphores[i] = request.wait_semaphores[i]->vk_semaphore; + } + } + + output.errors = wpArrayAllocCapacity(GpuSwapchainPresentError, temp, swapchain_count, + WP_ARRAY_INIT_FILLED); + assertWithLogger(output.errors != NULL, &logger, "Failed to allocate swapchain present output array"); + + VkPresentInfoKHR info = { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .waitSemaphoreCount = wait_semaphore_count, + .pWaitSemaphores = wait_semaphores, + .swapchainCount = swapchain_count, + .pSwapchains = swapchains, + .pImageIndices = image_indices, + .pResults = vk_results, + }; + VkResult vk_result = vkQueuePresentKHR(request.device->vk_queue, &info); + b32 failed = vk_result != VK_SUCCESS && vk_result != VK_SUBOPTIMAL_KHR && + vk_result != VK_ERROR_OUT_OF_DATE_KHR; + assertWithLogger(!failed, &logger, "Failed to present swapchains"); + + for (u64 i = 0; i < swapchain_count; ++i) { + output.errors[i] = vk_results[i] == VK_SUCCESS ? + GPU_SWAPCHAIN_PRESENT_ERROR_NONE : + GPU_SWAPCHAIN_PRESENT_ERROR_OUT_OF_DATE; + } + return output; } @@ -905,9 +986,35 @@ void gpuDestroyFence(GpuFence *fence) { vkDestroyFence(fence->device->vk_device, fence->vk_fence, NULL); } -void gpuResetFence(GpuFence *fence) { - VkResult vk_result = vkResetFences(fence->device->vk_device, 1, &fence->vk_fence); - assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to reset fence"); +void gpuResetFences(const WpAllocator *temp, GpuResetFencesRequest request) { + u64 fence_count = wpArrayCount(request.fences); + VkFenceArray fences = wpArrayAllocCapacity(VkFence, temp, fence_count, WP_ARRAY_INIT_FILLED); + assertWithLogger(fences != NULL, &logger, "Failed to allocate reset fences temp array"); + + for (u64 i = 0; i < fence_count; ++i) { + assertWithLogger(request.device->vk_device == request.fences[i]->device->vk_device, &logger, + "Fence was created using a different VkDevice"); + fences[i] = request.fences[i]->vk_fence; + } + + VkResult vk_result = vkResetFences(request.device->vk_device, fence_count, fences); + assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to reset fences"); +} + +void gpuWaitForFences(const WpAllocator *temp, GpuWaitForFencesRequest request) { + u64 fence_count = wpArrayCount(request.fences); + VkFenceArray fences = wpArrayAllocCapacity(VkFence, temp, fence_count, WP_ARRAY_INIT_FILLED); + assertWithLogger(fences != NULL, &logger, "Failed to allocate wait for fences temp array"); + + for (u64 i = 0; i < fence_count; ++i) { + assertWithLogger(request.device->vk_device == request.fences[i]->device->vk_device, &logger, + "Fence was created using a different VkDevice"); + fences[i] = request.fences[i]->vk_fence; + } + + VkResult vk_result = vkWaitForFences(request.device->vk_device, fence_count, fences, VK_TRUE, + request.timeout); + assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to wait for fences"); } GpuSemaphore *gpuCreateSemaphore(const WpAllocator *allocator, GpuDevice *device) { @@ -1009,31 +1116,70 @@ void gpuEndCommandBuffer(GpuCommandBuffer *buffer) { } void gpuSubmitCommandBuffers(const WpAllocator *temp, GpuCommandBuffersSubmitRequest request) { - u64 buffer_count = wpArrayCount(request.command_buffers); + u64 command_buffer_count = wpArrayCount(request.command_buffers); + VkCommandBufferSubmitInfoArray command_buffer_infos = wpArrayAllocCapacity(VkCommandBufferSubmitInfo, + temp, command_buffer_count, + WP_ARRAY_INIT_FILLED); + assertWithLogger(command_buffer_infos != NULL, &logger, "Failed to allocate temp command buffers"); - VkCommandBufferArray vk_buffers = wpArrayAllocCapacity(VkCommandBuffer, temp, buffer_count, - WP_ARRAY_INIT_FILLED); - assertWithLogger(vk_buffers != NULL, &logger, "Failed to allocate temp buffers"); - - for (u64 i = 0; i < buffer_count; ++i) { - vk_buffers[i] = request.command_buffers[i]->vk_buffer; + for (u64 i = 0; i < command_buffer_count; ++i) { + command_buffer_infos[i] = (VkCommandBufferSubmitInfo){ + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, + .commandBuffer = request.command_buffers[i]->vk_buffer, + }; } - VkSubmitInfo info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = buffer_count, - .pCommandBuffers = vk_buffers, + VkSemaphoreSubmitInfoArray wait_semaphore_infos = VK_NULL_HANDLE; + u64 wait_semaphore_count = 0; + if (request.wait_semaphore_infos != NULL) { + wait_semaphore_count = wpArrayCount(request.wait_semaphore_infos); + wait_semaphore_infos = wpArrayAllocCapacity(VkSemaphoreSubmitInfo, temp, wait_semaphore_count, + WP_ARRAY_INIT_FILLED); + assertWithLogger(wait_semaphore_infos != NULL, &logger, "Failed to allocate temp wait semaphores"); + + for (u64 i = 0; i < wait_semaphore_count; ++i) { + wait_semaphore_infos[i] = (VkSemaphoreSubmitInfo){ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .semaphore = request.wait_semaphore_infos[i].semaphore->vk_semaphore, + .stageMask = vkPipelineStagesFromGpuPipelineStages(request.wait_semaphore_infos[i].stage_mask), + }; + } + } + + VkSemaphoreSubmitInfoArray signal_semaphore_infos = VK_NULL_HANDLE; + u64 signal_semaphore_count = 0; + if (request.signal_semaphore_infos != NULL) { + signal_semaphore_count = wpArrayCount(request.signal_semaphore_infos); + signal_semaphore_infos = wpArrayAllocCapacity(VkSemaphoreSubmitInfo, temp, signal_semaphore_count, + WP_ARRAY_INIT_FILLED); + assertWithLogger(signal_semaphore_infos != NULL, &logger, "Failed to allocate temp signal semaphores"); + + for (u64 i = 0; i < signal_semaphore_count; ++i) { + signal_semaphore_infos[i] = (VkSemaphoreSubmitInfo){ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, + .semaphore = request.signal_semaphore_infos[i].semaphore->vk_semaphore, + .stageMask = vkPipelineStagesFromGpuPipelineStages(request.signal_semaphore_infos[i].stage_mask), + }; + } + } + + VkFence fence = VK_NULL_HANDLE; + if (request.fence != NULL) { + fence = request.fence->vk_fence; + } + + VkSubmitInfo2 info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + .waitSemaphoreInfoCount = wait_semaphore_count, + .pWaitSemaphoreInfos = wait_semaphore_infos, + .commandBufferInfoCount = command_buffer_count, + .pCommandBufferInfos = command_buffer_infos, + .signalSemaphoreInfoCount = signal_semaphore_count, + .pSignalSemaphoreInfos = signal_semaphore_infos, }; - VkResult vk_result = VK_SUCCESS; - - gpuResetFence(request.fence); - - vk_result = vkQueueSubmit(request.device->vk_queue, 1, &info, request.fence->vk_fence); - assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to submit command buffers"); - - vk_result = vkWaitForFences(request.device->vk_device, 1, &request.fence->vk_fence, VK_TRUE, UINT64_MAX); - assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to wait for fences"); + VkResult vk_result = vkQueueSubmit2(request.device->vk_queue, 1, &info, fence); + assertWithLogger(vk_result == VK_SUCCESS, &logger, "Faild to submit command buffers"); } void gpuResetCommandBuffer(GpuCommandBuffer *buffer) { @@ -1303,29 +1449,36 @@ GpuPipelineLayout *gpuCreatePipelineLayout(const WpAllocator *allocator, const W GpuPipelineLayout *output = wpMemAllocatorAlloc(allocator, sizeof(GpuPipelineLayout)); assertWithLogger(output != NULL, &logger, "Failed to allocate pipeline layout internal"); - u64 layout_count = wpArrayCount(request.descriptor_set_layouts); - u64 push_constant_count = wpArrayCount(request.push_constants); + VkDescriptorSetLayoutArray layouts = 0; + u64 layout_count = 0; + if (request.descriptor_set_layouts != NULL) { + layout_count = wpArrayCount(request.descriptor_set_layouts); + layouts = wpArrayAllocCapacity(VkDescriptorSetLayout, temp, layout_count, WP_ARRAY_INIT_FILLED); - VkDescriptorSetLayoutArray layouts = wpArrayAllocCapacity(VkDescriptorSetLayout, temp, - layout_count, WP_ARRAY_INIT_FILLED); - VkPushConstantRangeArray push_constants = wpArrayAllocCapacity(VkPushConstantRange, temp, - push_constant_count, WP_ARRAY_INIT_FILLED); - - for (u64 i = 0; i < layout_count; ++i) { - layouts[i] = request.descriptor_set_layouts[i]->vk_layout; + for (u64 i = 0; i < layout_count; ++i) { + layouts[i] = request.descriptor_set_layouts[i]->vk_layout; + } } - for (u64 i = 0; i < push_constant_count; ++i) { - push_constants[i].stageFlags = vkShaderStageFromGpuShaderStage(request.push_constants[i].stages); - push_constants[i].offset = request.push_constants[i].offset; - push_constants[i].size = request.push_constants[i].size; + VkPushConstantRangeArray push_constants = VK_NULL_HANDLE; + u64 push_constant_count = 0; + if (request.push_constants != NULL) { + push_constant_count = wpArrayCount(request.push_constants); + push_constants = wpArrayAllocCapacity(VkPushConstantRange, temp, push_constant_count, + WP_ARRAY_INIT_FILLED); + + for (u64 i = 0; i < push_constant_count; ++i) { + push_constants[i].stageFlags = vkShaderStageFromGpuShaderStage(request.push_constants[i].stages); + push_constants[i].offset = request.push_constants[i].offset; + push_constants[i].size = request.push_constants[i].size; + } } VkPipelineLayoutCreateInfo info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = wpArrayCount(layouts), + .setLayoutCount = layout_count, .pSetLayouts = layouts, - .pushConstantRangeCount = wpArrayCount(push_constants), + .pushConstantRangeCount = push_constant_count, .pPushConstantRanges = push_constants, }; @@ -1708,12 +1861,15 @@ void gpuCmdBeginRendering(const WpAllocator *temp, GpuCmdBeginRenderingRequest r assertWithLogger(color_attachments != NULL, &logger, "Failed to allocate temp color attachments array"); for (u64 i = 0; i < color_attachment_count; ++i) { + VkImageView resolve_image_view = request.color_attachments[i].resolve_image != NULL ? + request.color_attachments[i].resolve_image->vk_view : + VK_NULL_HANDLE; color_attachments[i] = (VkRenderingAttachmentInfo){ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, .imageView = request.color_attachments[i].image->vk_view, .imageLayout = vkImageLayoutFromGpuImageLayout(request.color_attachments[i].layout), .resolveMode = vkResolveModeFlagsFromGpuResolveModeFlags(request.color_attachments[i].resolve_mode), - .resolveImageView = request.color_attachments[i].resolve_image->vk_view, + .resolveImageView = resolve_image_view, .resolveImageLayout = vkImageLayoutFromGpuImageLayout(request.color_attachments[i].resolve_image_layout), .loadOp = vkAttachmentLoadOpFromGpuAttachmentLoadOp(request.color_attachments[i].load_op), .storeOp = vkAttachmentStoreOpFromGpuAttachmentStoreOp(request.color_attachments[i].store_op), @@ -1728,12 +1884,15 @@ void gpuCmdBeginRendering(const WpAllocator *temp, GpuCmdBeginRenderingRequest r VkRenderingAttachmentInfo depth_attachment = {0}; if (request.depth_attachment != NULL) { + VkImageView resolve_image_view = request.depth_attachment->resolve_image != NULL ? + request.depth_attachment->resolve_image->vk_view : + VK_NULL_HANDLE; depth_attachment = (VkRenderingAttachmentInfo){ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, .imageView = request.depth_attachment->image->vk_view, .imageLayout = vkImageLayoutFromGpuImageLayout(request.depth_attachment->layout), .resolveMode = vkResolveModeFlagsFromGpuResolveModeFlags(request.depth_attachment->resolve_mode), - .resolveImageView = request.depth_attachment->resolve_image->vk_view, + .resolveImageView = resolve_image_view, .resolveImageLayout = vkImageLayoutFromGpuImageLayout(request.depth_attachment->resolve_image_layout), .loadOp = vkAttachmentLoadOpFromGpuAttachmentLoadOp(request.depth_attachment->load_op), .storeOp = vkAttachmentStoreOpFromGpuAttachmentStoreOp(request.depth_attachment->store_op), @@ -1872,6 +2031,11 @@ void gpuCmdPushConstants(GpuCmdPushConstantsRequest request) { request.total_size_in_bytes, request.values); } +void gpuCmdDraw(GpuCmdDrawRequest request) { + vkCmdDraw(request.command_buffer->vk_buffer, request.vertex_count, request.instance_count, + request.first_vertex, request.first_instance); +} + void gpuCmdDrawIndexed(GpuCmdDrawIndexedRequest request) { vkCmdDrawIndexed(request.command_buffer->vk_buffer, request.index_count, request.instance_count, request.first_index, request.vertex_offset, request.first_instance); @@ -2114,40 +2278,40 @@ wp_intern GpuFormat gpuFormatFromVkFormat(VkFormat format) { wp_intern VkColorSpaceKHR vkColorspaceFromGpuColorspace(GpuColorspace colorspace) { switch (colorspace) { case GPU_COLOR_SPACE_SRGB_NONLINEAR: return VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - case GPU_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT: return VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT; - case GPU_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT: return VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT; - case GPU_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT: return VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT; - case GPU_COLOR_SPACE_DCI_P3_NONLINEAR_EXT: return VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT; - case GPU_COLOR_SPACE_BT709_LINEAR_EXT: return VK_COLOR_SPACE_BT709_LINEAR_EXT; - case GPU_COLOR_SPACE_BT709_NONLINEAR_EXT: return VK_COLOR_SPACE_BT709_NONLINEAR_EXT; - case GPU_COLOR_SPACE_BT2020_LINEAR_EXT: return VK_COLOR_SPACE_BT2020_LINEAR_EXT; - case GPU_COLOR_SPACE_HDR10_ST2084_EXT: return VK_COLOR_SPACE_HDR10_ST2084_EXT; - case GPU_COLOR_SPACE_DOLBYVISION_EXT: return VK_COLOR_SPACE_DOLBYVISION_EXT; - case GPU_COLOR_SPACE_HDR10_HLG_EXT: return VK_COLOR_SPACE_HDR10_HLG_EXT; - case GPU_COLOR_SPACE_ADOBERGB_LINEAR_EXT: return VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT; - case GPU_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT: return VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT; - case GPU_COLOR_SPACE_PASS_THROUGH_EXT: return VK_COLOR_SPACE_PASS_THROUGH_EXT; - case GPU_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT: return VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT; - case GPU_COLORSPACE_SRGB_NONLINEAR: return VK_COLORSPACE_SRGB_NONLINEAR_KHR; + case GPU_COLOR_SPACE_DISPLAY_P3_NONLINEAR: return VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT; + case GPU_COLOR_SPACE_EXTENDED_SRGB_LINEAR: return VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT; + case GPU_COLOR_SPACE_DISPLAY_P3_LINEAR: return VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT; + case GPU_COLOR_SPACE_DCI_P3_NONLINEAR: return VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT; + case GPU_COLOR_SPACE_BT709_LINEAR: return VK_COLOR_SPACE_BT709_LINEAR_EXT; + case GPU_COLOR_SPACE_BT709_NONLINEAR: return VK_COLOR_SPACE_BT709_NONLINEAR_EXT; + case GPU_COLOR_SPACE_BT2020_LINEAR: return VK_COLOR_SPACE_BT2020_LINEAR_EXT; + case GPU_COLOR_SPACE_HDR10_ST2084: return VK_COLOR_SPACE_HDR10_ST2084_EXT; + case GPU_COLOR_SPACE_DOLBYVISION: return VK_COLOR_SPACE_DOLBYVISION_EXT; + case GPU_COLOR_SPACE_HDR10_HLG: return VK_COLOR_SPACE_HDR10_HLG_EXT; + case GPU_COLOR_SPACE_ADOBERGB_LINEAR: return VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT; + case GPU_COLOR_SPACE_ADOBERGB_NONLINEAR: return VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT; + case GPU_COLOR_SPACE_PASS_THROUGH: return VK_COLOR_SPACE_PASS_THROUGH_EXT; + case GPU_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR: return VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT; + case GPU_COLORSPACE_SRGB_NONLINEAR: return VK_COLORSPACE_SRGB_NONLINEAR_KHR; } } wp_intern GpuColorspace gpuColorspaceFromVkColorspace(VkColorSpaceKHR colorspace) { switch (colorspace) { - case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT: return GPU_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT; - case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT: return GPU_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT; - case VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT: return GPU_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT; - case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT: return GPU_COLOR_SPACE_DCI_P3_NONLINEAR_EXT; - case VK_COLOR_SPACE_BT709_LINEAR_EXT: return GPU_COLOR_SPACE_BT709_LINEAR_EXT; - case VK_COLOR_SPACE_BT709_NONLINEAR_EXT: return GPU_COLOR_SPACE_BT709_NONLINEAR_EXT; - case VK_COLOR_SPACE_BT2020_LINEAR_EXT: return GPU_COLOR_SPACE_BT2020_LINEAR_EXT; - case VK_COLOR_SPACE_HDR10_ST2084_EXT: return GPU_COLOR_SPACE_HDR10_ST2084_EXT; - case VK_COLOR_SPACE_DOLBYVISION_EXT: return GPU_COLOR_SPACE_DOLBYVISION_EXT; - case VK_COLOR_SPACE_HDR10_HLG_EXT: return GPU_COLOR_SPACE_HDR10_HLG_EXT; - case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT: return GPU_COLOR_SPACE_ADOBERGB_LINEAR_EXT; - case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT: return GPU_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT; - case VK_COLOR_SPACE_PASS_THROUGH_EXT: return GPU_COLOR_SPACE_PASS_THROUGH_EXT; - case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT: return GPU_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT; + case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT: return GPU_COLOR_SPACE_DISPLAY_P3_NONLINEAR; + case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT: return GPU_COLOR_SPACE_EXTENDED_SRGB_LINEAR; + case VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT: return GPU_COLOR_SPACE_DISPLAY_P3_LINEAR; + case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT: return GPU_COLOR_SPACE_DCI_P3_NONLINEAR; + case VK_COLOR_SPACE_BT709_LINEAR_EXT: return GPU_COLOR_SPACE_BT709_LINEAR; + case VK_COLOR_SPACE_BT709_NONLINEAR_EXT: return GPU_COLOR_SPACE_BT709_NONLINEAR; + case VK_COLOR_SPACE_BT2020_LINEAR_EXT: return GPU_COLOR_SPACE_BT2020_LINEAR; + case VK_COLOR_SPACE_HDR10_ST2084_EXT: return GPU_COLOR_SPACE_HDR10_ST2084; + case VK_COLOR_SPACE_DOLBYVISION_EXT: return GPU_COLOR_SPACE_DOLBYVISION; + case VK_COLOR_SPACE_HDR10_HLG_EXT: return GPU_COLOR_SPACE_HDR10_HLG; + case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT: return GPU_COLOR_SPACE_ADOBERGB_LINEAR; + case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT: return GPU_COLOR_SPACE_ADOBERGB_NONLINEAR; + case VK_COLOR_SPACE_PASS_THROUGH_EXT: return GPU_COLOR_SPACE_PASS_THROUGH; + case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT: return GPU_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR; case VK_COLORSPACE_SRGB_NONLINEAR_KHR: return GPU_COLORSPACE_SRGB_NONLINEAR; default: return GPU_COLOR_SPACE_SRGB_NONLINEAR; }