// vim:fileencoding=utf-8:foldmethod=marker #include "vulkan_profiles/vulkan_profiles.h" #include "../gpu.h" #include "../../config/config_inc.h" #include "../../utils/utils_inc.h" #include "../../window/window_inc.h" #include "../../wapp/wapp.h" #include "../../cglm/struct.h" #include #ifdef USE_SDL_WINDOW_BACKEND #include #else #error "No window backend selected" #endif #include #include #include #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #define clamp(value, minimum, maximum) (max((minimum), (min((value), (maximum))))) wp_intern WpLogger logger = wpLogMakeLogger(wpStr8LitRo("Vulkan Wrapper")); typedef VkPhysicalDevice *VkPhysicalDeviceArray; typedef VkQueueFamilyProperties2 *VkQueueFamilyProperties2Array; typedef VkImage *VkImageArray; typedef VkImageView *VkImageViewArray; typedef VkFormat *VkFormatArray; typedef VkSurfaceFormat2KHR *VkSurfaceFormat2KHRArray; typedef VkCommandBuffer *VkCommandBufferArray; typedef VkDescriptorPoolSize *VkDescriptorPoolSizeArray; typedef VkDescriptorBindingFlags *VkDescriptorBindingFlagsArray; typedef VkDescriptorSetLayoutBindingFlagsCreateInfo *VkDescriptorSetLayoutBindingFlagsCreateInfoArray; typedef VkDescriptorSetLayoutBinding *VkDescriptorSetLayoutBindingArray; typedef VkDescriptorSetLayout *VkDescriptorSetLayoutArray; typedef VkDescriptorSetVariableDescriptorCountAllocateInfo *VkDescriptorSetVariableDescriptorCountAllocateInfoArray; typedef VkDescriptorSet *VkDescriptorSetArray; typedef VkWriteDescriptorSet *VkWriteDescriptorSetArray; typedef VkDescriptorBufferInfo *VkDescriptorBufferInfoArray; typedef VkDescriptorImageInfo *VkDescriptorImageInfoArray; typedef VkPushConstantRange *VkPushConstantRangeArray; typedef VkGraphicsPipelineCreateInfo *VkGraphicsPipelineCreateInfoArray; typedef VkComputePipelineCreateInfo *VkComputePipelineCreateInfoArray; typedef VkPipeline *VkPipelineArray; typedef VkVertexInputBindingDescription *VkVertexInputBindingDescriptionArray; typedef VkVertexInputAttributeDescription *VkVertexInputAttributeDescriptionArray; typedef VkViewport *VkViewportArray; typedef VkRect2D *VkRect2DArray; typedef VkPipelineColorBlendAttachmentState *VkPipelineColorBlendAttachmentStateArray; typedef VkPipelineShaderStageCreateInfo *VkPipelineShaderStageCreateInfoArray; typedef VkPipelineVertexInputStateCreateInfo *VkPipelineVertexInputStateCreateInfoArray; typedef VkPipelineInputAssemblyStateCreateInfo *VkPipelineInputAssemblyStateCreateInfoArray; typedef VkPipelineTessellationStateCreateInfo *VkPipelineTessellationStateCreateInfoArray; typedef VkPipelineViewportStateCreateInfo *VkPipelineViewportStateCreateInfoArray; typedef VkPipelineRasterizationStateCreateInfo *VkPipelineRasterizationStateCreateInfoArray; typedef VkPipelineMultisampleStateCreateInfo *VkPipelineMultisampleStateCreateInfoArray; typedef VkPipelineDepthStencilStateCreateInfo *VkPipelineDepthStencilStateCreateInfoArray; typedef VkPipelineColorBlendStateCreateInfo *VkPipelineColorBlendStateCreateInfoArray; typedef VkPipelineRenderingCreateInfo *VkPipelineRenderingCreateInfoArray; typedef VkDynamicState *VkDynamicStateArray; struct GpuInstance { VkInstance vk_instance; VpProfileProperties profile; }; struct GpuPhysicalDeviceInternal { VkPhysicalDevice vk_physical_device; u32 queue_family_index; }; struct GpuSurface { VkSurfaceCapabilitiesKHR capabilities; const GpuInstance *instance; VkSurfaceKHR vk_surface; const Window *window; }; struct GpuDevice { GpuPhysicalDevice physical_device; VkDevice vk_device; VkQueue vk_queue; VmaAllocator allocator; }; struct GpuSampler { GpuDevice *device; VkSampler vk_sampler; }; struct GpuImage { GpuDevice *device; VmaAllocation allocation; VkImage vk_image; VkImageView vk_view; ivec3s size; VkFormat format; }; struct GpuSwapchain { GpuDevice *device; VkSwapchainKHR vk_swapchain; VkExtent2D extent; GpuImageArray images; GpuImage depth; }; struct GpuBufferInternal { VmaAllocationInfo allocation_info; VkBuffer vk_buffer; VmaAllocation allocation; }; struct GpuFence { GpuDevice *device; VkFence vk_fence; }; struct GpuSemaphore { GpuDevice *device; VkSemaphore vk_semaphore; }; struct GpuCommandPool { GpuDevice *device; VkCommandPool vk_pool; }; struct GpuCommandBuffer { GpuCommandPool *pool; VkCommandBuffer vk_buffer; }; struct GpuDescriptorPool { GpuDevice *device; VkDescriptorPool vk_pool; }; struct GpuDescriptorSetLayout { GpuDevice *device; VkDescriptorSetLayout vk_layout; u32 variable_descriptor_count; }; struct GpuDescriptorSet { GpuDescriptorPool *pool; GpuDescriptorSetLayout *layout; VkDescriptorSet vk_set; }; struct GpuShader { GpuDevice *device; VkShaderModule vk_shader; }; struct GpuPipelineLayout { GpuDevice *device; VkPipelineLayout vk_layout; }; struct GpuPipeline { GpuPipelineLayout *layout; VkPipeline vk_pipeline; }; typedef struct VkExtensions { const char *const *extensions; u32 count; } VkExtensions; typedef struct GraphicsPipelinesTotalCounts { u64 total_vertex_input_bindings_count; u64 total_vertex_input_attributes_count; u64 total_viewports_count; u64 total_scissors_count; u64 total_color_blend_attachments_count; u64 total_shader_stages_count; } GraphicsPipelinesTotalCounts; typedef struct GraphicsPipelinesTempArrays { VkPipelineVertexInputStateCreateInfoArray vertex_input_states; VkPipelineInputAssemblyStateCreateInfoArray input_assembly_states; VkPipelineTessellationStateCreateInfoArray tesselation_states; VkPipelineViewportStateCreateInfoArray viewport_states; VkPipelineRasterizationStateCreateInfoArray rasterization_states; VkPipelineMultisampleStateCreateInfoArray multisample_states; VkPipelineDepthStencilStateCreateInfoArray depth_stencil_states; VkPipelineColorBlendStateCreateInfoArray color_blend_states; VkPipelineRenderingCreateInfoArray dynamic_rendering_infos; VkFormatArray color_attachment_formats; VkVertexInputBindingDescriptionArray vertex_bindings; u64 vertex_bindings_offset; VkVertexInputAttributeDescriptionArray vertex_attributes; u64 vertex_attributes_offset; VkPipelineColorBlendAttachmentStateArray color_blend_attachments; u64 color_blend_attachments_offset; VkPipelineShaderStageCreateInfoArray shader_stages; u64 shader_stages_offset; } GraphicsPipelinesTempArrays; typedef enum GpuDescriptorCategory { GPU_DESCRIPTOR_CATEGORY_IMAGE, GPU_DESCRIPTOR_CATEGORY_BUFFER, GPU_DESCRIPTOR_CATEGORY_TEXEL_BUFFER, GPU_DESCRIPTOR_CATEGORY_UNIFORM_BLOCK, } GpuDescriptorCategory; wp_intern VkExtensions getInstanceExtensions(void); wp_intern GpuPhysicalDeviceType vkDeviceTypeToGpuDeviceType(VkPhysicalDeviceType type); wp_intern VkPhysicalDeviceType gpuDeviceTypeToVkDeviceType(GpuPhysicalDeviceType type); wp_intern i32 findQueueFamily(const WpAllocator *allocator, VkInstance instance, VkPhysicalDevice physical_device, GpuPhysicalDeviceOps ops); wp_intern VkQueueFlags queueFlagsFromOps(GpuPhysicalDeviceOps ops); wp_intern b8 presentationSupported(VkInstance instance, VkPhysicalDevice device, u32 queue_family_index); wp_intern b8 windowBackendCreateSurface(const Window *window, VkInstance instance, VkSurfaceKHR *surface); wp_intern VkFormat vkFormatFromGpuFormat(GpuFormat format); wp_intern GpuFormat gpuFormatFromVkFormat(VkFormat format); wp_intern VkColorSpaceKHR vkColorspaceFromGpuColorspace(GpuColorspace colorspace); wp_intern GpuColorspace gpuColorspaceFromVkColorspace(VkColorSpaceKHR colorspace); wp_intern VkPresentModeKHR vkPresentModeFromGpuPresentMode(GpuPresentMode mode); wp_intern GpuPresentMode gpuPresentModeFromVkPresentMode(VkPresentModeKHR mode); wp_intern VkImageType vkImageTypeFromGpuImageType(GpuImageType type); wp_intern GpuImageType gpuImageTypeFromVkImageType(VkImageType type); wp_intern VkImageViewType vkImageViewTypeFromGpuImageType(GpuImageType type); wp_intern GpuImageType gpuImageTypeFromVkImageViewType(VkImageViewType type); wp_intern VkSampleCountFlagBits vkSampleCountFromGpuSampleCount(GpuSampleCount samples); wp_intern GpuSampleCount gpuSampleCountFromVkSampleCount(VkSampleCountFlagBits samples); wp_intern VkImageTiling vkImageTilingFromGpuImageTiling(GpuImageTiling tiling); wp_intern GpuImageTiling gpuImageTilingFromVkImageTiling(VkImageTiling tiling); wp_intern VkImageUsageFlags vkImageUsageFromGpuImageUsage(GpuImageUsage usage); wp_intern GpuImageUsage gpuImageUsageFromVkImageUsage(VkImageUsageFlags usage); wp_intern VkImageLayout vkImageLayoutFromGpuImageLayout(GpuImageLayout layout); wp_intern GpuImageLayout gpuImageLayoutFromVkImageLayout(VkImageLayout layout); wp_intern VkImageAspectFlags vkImageAspectFromGpuImageAspect(GpuImageAspect aspect); wp_intern GpuImageAspect gpuImageAspectFromVkImageAspect(VkImageAspectFlags aspect); wp_intern VkBufferUsageFlags2 vkBufferUsageFromGpuBufferUsage(GpuBufferUsage usage); wp_intern GpuBufferUsage gpuBufferUsageFromVkBufferUsage(VkBufferUsageFlags2 usage); wp_intern VkPipelineStageFlags2 vkPipelineStagesFromGpuPipelineStages(GpuPipelineStageFlags stage); wp_intern GpuPipelineStageFlags gpuPipelineStagesFromVkPipelineStages(VkPipelineStageFlags2 stage); wp_intern VkAccessFlags2 vkAccessFlagsFromGpuAccessFlags(GpuAccessFlags access); wp_intern GpuAccessFlags gpuAccessFlagsFromVkAccessFlags(VkAccessFlags2 access); wp_intern VkFilter vkFilterFromGpuFilter(GpuFilter filter); wp_intern GpuFilter gpuFilterFromVkFilter(VkFilter filter); wp_intern VkSamplerMipmapMode vkSamplerMipmapModeFromGpuSamplerMipmapMode(GpuSamplerMipmapMode mode); wp_intern GpuSamplerMipmapMode gpuSamplerMipmapModeFromVkSamplerMipmapMode(VkSamplerMipmapMode mode); wp_intern VkSamplerAddressMode vkSamplerAddressModeFromGpuSamplerAddressMode(GpuSamplerAddressMode mode); wp_intern GpuSamplerAddressMode gpuSamplerAddressModeFromVkSamplerAddressMode(VkSamplerAddressMode mode); wp_intern VkCompareOp vkCompareOpFromGpuCompareOp(GpuCompareOp op); wp_intern GpuCompareOp gpuCompareOpFromVkCompareOp(VkCompareOp op); wp_intern VkDescriptorType vkDescriptorTypeFromGpuDescriptorType(GpuDescriptorType type); wp_intern GpuDescriptorType gpuDescriptorTypeFromVkDescriptorType(VkDescriptorType type); wp_intern VkShaderStageFlags vkShaderStageFromGpuShaderStage(GpuShaderStage stages); wp_intern GpuShaderStage gpuShaderStageFromVkShaderStage(VkShaderStageFlags stages); wp_intern GpuDescriptorCategory descriptorCategoryFromDescriptorType(GpuDescriptorType type); wp_intern u64 retrieveDescriptorImageInfos(const GpuDescriptorSetWriteInfo *info, VkWriteDescriptorSet *desc_set_write, VkDescriptorImageInfoArray desc_img_infos, u64 img_info_offset); wp_intern u64 retrieveDescriptorBufferInfos(const GpuDescriptorSetWriteInfo *info, VkWriteDescriptorSet *desc_set_write, VkDescriptorBufferInfoArray desc_buf_infos, u64 buf_info_offset); wp_intern GraphicsPipelinesTotalCounts queryGraphicsPipelinesRequestTotalCounts(GpuGraphicsPipelinesCreateRequest request); wp_intern GraphicsPipelinesTempArrays allocateGraphicsPipelinesTempArrays(const WpAllocator *allocator, GpuGraphicsPipelinesCreateRequest request); wp_intern VkVertexInputRate vkVertexInputRateFromGpuVertexInputRate(GpuVertexInputRate rate); wp_intern GpuVertexInputRate gpuVertexInputRateFromVkVertexInputRate(VkVertexInputRate rate); wp_intern VkPrimitiveTopology vkPrimitiveTopologyFromGpuPrimitiveTopology(GpuPrimitiveTopology topology); wp_intern GpuPrimitiveTopology gpuPrimitiveTopologyFromVkPrimitiveTopology(VkPrimitiveTopology topology); wp_intern VkPolygonMode vkPolygonModeFromGpuPolygonMode(GpuPolygonMode mode); wp_intern GpuPolygonMode gpuPolygonModeFromVkPolygonMode(VkPolygonMode mode); wp_intern VkCullModeFlags vkCullModeFromGpuCullMode(GpuCullMode mode); wp_intern GpuCullMode gpuCullModeFromVkCullMode(VkCullModeFlags mode); wp_intern VkFrontFace vkFrontFaceFromGpuFrontFace(GpuFrontFace front_face); wp_intern GpuFrontFace gpuFrontFaceFromVkFrontFace(VkFrontFace front_face); wp_intern VkStencilOp vkStencilOpFromGpuStencil(GpuStencilOp op); wp_intern GpuStencilOp gpuStencilOpFromVkStencil(VkStencilOp op); wp_intern VkBlendFactor vkBlendFactorFromGpuBlendFactor(GpuBlendFactor factor); wp_intern GpuBlendFactor gpuBlendFactorFromVkBlendFactor(VkBlendFactor factor); wp_intern VkBlendOp vkBlendOpFromGpuBlendOp(GpuBlendOp op); wp_intern GpuBlendOp gpuBlendOpFromVkBlendOp(VkBlendOp op); wp_intern VkColorComponentFlags vkColorComponentFlagsFromGpuColorComponentFlags(GpuColorComponentFlags flags); wp_intern GpuColorComponentFlags gpuColorComponentFlagsFromVkColorComponentFlags(VkColorComponentFlags flags); wp_intern VkLogicOp vkLogicOpFromGpuLogicOp(GpuLogicOp op); wp_intern GpuLogicOp gpuLogicOpFromVkLogicOp(VkLogicOp op); GpuInstance *gpuInit(const WpAllocator *allocator, GpuInitRequest request) { assertWithLogger(volkInitialize() == VK_SUCCESS, &logger, "Failed to initialise volk"); VpProfileProperties profile = { .profileName = VP_TEST_WINDOW_RENDERER_NAME, .specVersion = VP_TEST_WINDOW_RENDERER_SPEC_VERSION, }; VkExtensions instance_extensions = getInstanceExtensions(); VkBool32 supported = VK_FALSE; vpGetInstanceProfileSupport(NULL, &profile, &supported); assertWithLogger(supported, &logger, "Profile not supported"); GpuInstance *instance = wpMemAllocatorAlloc(allocator, sizeof(GpuInstance)); assertWithLogger(instance != NULL, &logger, "Failed to allocate instance"); VkApplicationInfo app_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .apiVersion = VP_TEST_WINDOW_RENDERER_MIN_API_VERSION, .pApplicationName = request.app_name, .applicationVersion = request.app_version, }; VkInstanceCreateInfo instance_info = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &app_info, .enabledExtensionCount = instance_extensions.count, .ppEnabledExtensionNames = instance_extensions.extensions, }; VpInstanceCreateInfo vp_instance_info = { .pCreateInfo = &instance_info, .enabledFullProfileCount = 1, .pEnabledFullProfiles = &profile, }; assertWithLogger(vpCreateInstance(&vp_instance_info, NULL, &instance->vk_instance) == VK_SUCCESS, &logger, "Failed to create Vulkan instance"); instance->profile = profile; volkLoadInstance(instance->vk_instance); wpLogInfo(&logger, wpStr8Lit("Initialised Vulkan GPU successfully")); return instance; } GpuPhysicalDevice gpuFindPhysicalDevice(const WpAllocator *allocator, const WpAllocator *temp, GpuPhysicalDeviceFindRequest request) { VkResult vk_result = VK_SUCCESS; u32 count = 0; vk_result = vkEnumeratePhysicalDevices(request.instance->vk_instance, &count, NULL); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to get physical device count"); VkPhysicalDeviceArray physical_devices = wpArrayAllocCapacity(VkPhysicalDevice, temp, count, WP_ARRAY_INIT_FILLED); assertWithLogger(physical_devices != NULL, &logger, "Failed to allocate physical devices"); vk_result = vkEnumeratePhysicalDevices(request.instance->vk_instance, &count, physical_devices); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to enumerate physical devices"); VkBool32 supported = VK_FALSE; WpStr8 msg = wpStr8Buf(4096); VkPhysicalDevice device = VK_NULL_HANDLE; i32 queue_family_index = -1; for (u32 i = 0; i < count; ++i) { VkPhysicalDeviceProperties2 properties = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 }; vkGetPhysicalDeviceProperties2(physical_devices[i], &properties); if (properties.properties.apiVersion < VP_TEST_WINDOW_RENDERER_MIN_API_VERSION) { continue; } VkResult profile_support = vpGetPhysicalDeviceProfileSupport(request.instance->vk_instance, physical_devices[i], &request.instance->profile, &supported); b8 device_type_match = gpuDeviceTypeToVkDeviceType(request.type) == properties.properties.deviceType; if (profile_support != VK_SUCCESS || !supported || !device_type_match) { continue; } queue_family_index = findQueueFamily(temp, request.instance->vk_instance, physical_devices[i], request.ops); if (queue_family_index == -1) { continue; } device = physical_devices[i]; wpStr8Format(&msg, "Found suitable physical device (Name: %s)", properties.properties.deviceName); wpLogDebug(&logger, msg); break; } GpuPhysicalDevice physical_device = {0}; assertWithLogger(device != NULL && queue_family_index > -1, &logger, "Failed to find a suitable physical device"); physical_device.internal = wpMemAllocatorAlloc(allocator, sizeof(GpuPhysicalDeviceInternal)); assertWithLogger(physical_device.internal != NULL, &logger, "Failed to allocate physical device internal"); physical_device.instance = request.instance; physical_device.internal->vk_physical_device = device; physical_device.internal->queue_family_index = (u32)queue_family_index; physical_device.type = request.type; return physical_device; } GpuSurface *gpuCreateSurface(const WpAllocator *allocator, GpuSurfaceCreateRequest request) { VkResult vk_result = VK_SUCCESS; GpuSurface *surface = wpMemAllocatorAlloc(allocator, sizeof(GpuSurface)); assertWithLogger(surface != NULL, &logger, "Failed to allocate surface"); b8 surface_created = windowBackendCreateSurface(request.window, request.physical_device.instance->vk_instance, &surface->vk_surface); assertWithLogger(surface_created, &logger, "Failed to create Vulkan surface"); vk_result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(request.physical_device.internal->vk_physical_device, surface->vk_surface, &surface->capabilities); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to get surface capabilities"); surface->instance = request.physical_device.instance; surface->window = request.window; WpStr8 msg = wpStr8Buf(4096); wpStr8Format(&msg, "Created Vulkan surface %p", surface->vk_surface); wpLogDebug(&logger, msg); return surface; } void gpuDestroySurface(GpuSurface *surface) { vkDestroySurfaceKHR(surface->instance->vk_instance, surface->vk_surface, NULL); } GpuDevice *gpuCreateDevice(const WpAllocator *allocator, GpuPhysicalDevice physical_device) { VkResult vk_result = VK_SUCCESS; GpuDevice *device = wpMemAllocatorAlloc(allocator, sizeof(GpuDevice)); assertWithLogger(device != NULL, &logger, "Failed to allocate device internal"); device->physical_device = physical_device; f32 queue_priority = 1.0f; VkDeviceQueueCreateInfo device_queue_create_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .queueCount = 1, .queueFamilyIndex = physical_device.internal->queue_family_index, .pQueuePriorities = &queue_priority, }; VkDeviceCreateInfo device_create_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .queueCreateInfoCount = 1, .pQueueCreateInfos = &device_queue_create_info, }; VpDeviceCreateInfo vp_device_create_info = { .pCreateInfo = &device_create_info, .enabledFullProfileCount = 1, .pEnabledFullProfiles = &physical_device.instance->profile, }; vk_result = vpCreateDevice(physical_device.internal->vk_physical_device, &vp_device_create_info, NULL, &device->vk_device); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create Vulkan device"); vkGetDeviceQueue(device->vk_device, device->physical_device.internal->queue_family_index, 0, &device->vk_queue); VmaVulkanFunctions vk_functions = { .vkGetInstanceProcAddr = vkGetInstanceProcAddr, .vkGetDeviceProcAddr = vkGetDeviceProcAddr, .vkCreateImage = vkCreateImage, }; VmaAllocatorCreateInfo allocator_create_info = { .flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT | VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT | VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT, .instance = physical_device.instance->vk_instance, .physicalDevice = physical_device.internal->vk_physical_device, .device = device->vk_device, .pVulkanFunctions = &vk_functions, }; vk_result = vmaCreateAllocator(&allocator_create_info, &device->allocator); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create Vulkan memory allocator"); WpStr8 msg = wpStr8Buf(4096); wpStr8Format(&msg, "Created Vulkan device %p", device->vk_device); wpLogDebug(&logger, msg); return device; } void gpuDestroyDevice(GpuDevice *device) { vmaDestroyAllocator(device->allocator); vkDestroyDevice(device->vk_device, NULL); } GpuSwapchain *gpuCreateSwapchain(const WpAllocator *allocator, const WpAllocator *temp, GpuSwapchainCreateRequest request) { VkResult vk_result = VK_SUCCESS; u32 surface_formats_count = 0; VkPhysicalDeviceSurfaceInfo2KHR surface_info = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, .surface = request.surface->vk_surface, }; vk_result = vkGetPhysicalDeviceSurfaceFormats2KHR(request.device->physical_device.internal->vk_physical_device, &surface_info, &surface_formats_count, NULL); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to query surface formats count"); VkSurfaceFormat2KHRArray format_pairs = wpArrayAllocCapacity(VkSurfaceFormat2KHR, temp, surface_formats_count, WP_ARRAY_INIT_FILLED); assertWithLogger(format_pairs != NULL, &logger, "Failed to allocate temp format array"); for (u32 i = 0; i < surface_formats_count; ++i) { format_pairs[i].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR; } vk_result = vkGetPhysicalDeviceSurfaceFormats2KHR(request.device->physical_device.internal->vk_physical_device, &surface_info, &surface_formats_count, format_pairs); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to get surface formats"); VkFormat requested_format = vkFormatFromGpuFormat(request.format); VkColorSpaceKHR requested_colorspace = vkColorspaceFromGpuColorspace(request.colorspace); b8 surface_format_supported = false; for (u32 i = 0; i < surface_formats_count; ++i) { if (requested_format == format_pairs[i].surfaceFormat.format && requested_colorspace == format_pairs[i].surfaceFormat.colorSpace) { surface_format_supported = true; break; } } assertWithLogger(surface_format_supported, &logger, "Requested surface format not supported"); GpuSwapchain *swapchain = wpMemAllocatorAlloc(allocator, sizeof(GpuSwapchain)); assertWithLogger(swapchain != NULL, &logger, "Failed to allocate swapchain internal"); swapchain->extent = request.surface->capabilities.currentExtent; // Handle Wayland's special value (0xffffffff), which indicate that the surface size will // basically be determined by the size of the surface if (swapchain->extent.width == 0xffffffff) { swapchain->extent.width = (u32)request.surface->window->size.x; swapchain->extent.height = (u32)request.surface->window->size.y; } u32 image_count = clamp(request.ideal_image_count, request.surface->capabilities.minImageCount, request.surface->capabilities.maxImageCount > 0 ? request.surface->capabilities.maxImageCount : request.ideal_image_count); VkSwapchainCreateInfoKHR swapchain_create_info = { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, .surface = request.surface->vk_surface, .minImageCount = image_count, .imageFormat = requested_format, .imageColorSpace = requested_colorspace, .imageExtent = swapchain->extent, .imageArrayLayers = 1, .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 1, .pQueueFamilyIndices = &request.device->physical_device.internal->queue_family_index, .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, .presentMode = vkPresentModeFromGpuPresentMode(request.present_mode), }; vk_result = vkCreateSwapchainKHR(request.device->vk_device, &swapchain_create_info, NULL, &swapchain->vk_swapchain); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create Vulkan swapchain"); u32 swapchain_image_count = 0; vk_result = vkGetSwapchainImagesKHR(request.device->vk_device, swapchain->vk_swapchain, &swapchain_image_count, NULL); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to retrieve swapchain image count"); VkImageArray images = wpArrayAllocCapacity(VkImage, temp, swapchain_image_count, WP_ARRAY_INIT_FILLED); swapchain->images = wpArrayAllocCapacity(GpuImage, allocator, swapchain_image_count, WP_ARRAY_INIT_FILLED); assertWithLogger(images != NULL && swapchain->images != NULL, &logger, "Failed to allocate swapchain images"); vk_result = vkGetSwapchainImagesKHR(request.device->vk_device, swapchain->vk_swapchain, &swapchain_image_count, images); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to retrieve swapchain images"); for (u32 i = 0; i < swapchain_image_count; ++i) { swapchain->images[i].vk_image = images[i]; swapchain->images[i].size = (ivec3s){ .x = swapchain->extent.width, .y = swapchain->extent.height, .z = 1 }; swapchain->images[i].format = vkFormatFromGpuFormat(request.format); swapchain->images[i].device = request.device; VkImageViewCreateInfo view_create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = swapchain->images[i].vk_image, .viewType = VK_IMAGE_VIEW_TYPE_2D, .format = requested_format, .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .subresourceRange.levelCount = 1, .subresourceRange.layerCount = 1, }; vk_result = vkCreateImageView(request.device->vk_device, &view_create_info, NULL, &swapchain->images[i].vk_view); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create swapchain image view"); } // NOTE (Abdelrahman): Favour 24-bit format for performance VkFormat depth_format = VK_FORMAT_UNDEFINED; VkFormatArray depth_formats = wpArray(VkFormat, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT); for (u32 i = 0; i < wpArrayCount(depth_formats); ++i) { VkFormatProperties2 format_properties = { VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 }; vkGetPhysicalDeviceFormatProperties2(request.device->physical_device.internal->vk_physical_device, depth_formats[i], &format_properties); if (format_properties.formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { depth_format = depth_formats[i]; break; } } assertWithLogger(depth_format != VK_FORMAT_UNDEFINED, &logger, "Failed to retrieve depth image format"); VkImageCreateInfo depth_image_create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .imageType = VK_IMAGE_TYPE_2D, .format = depth_format, .extent = (VkExtent3D){ .width = swapchain->extent.width, .height = swapchain->extent.height, .depth = 1 }, .mipLevels = 1, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_OPTIMAL, .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 1, .pQueueFamilyIndices = &request.device->physical_device.internal->queue_family_index, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, }; VmaAllocationCreateInfo depth_alloc_create_info = { .flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, .usage = VMA_MEMORY_USAGE_AUTO, }; vk_result = vmaCreateImage(request.device->allocator, &depth_image_create_info, &depth_alloc_create_info, &swapchain->depth.vk_image, &swapchain->depth.allocation, NULL); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create depth image"); VkImageViewCreateInfo depth_view_create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = swapchain->depth.vk_image, .viewType = VK_IMAGE_VIEW_TYPE_2D, .format = depth_format, .subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, .subresourceRange.levelCount = 1, .subresourceRange.layerCount = 1, }; vk_result = vkCreateImageView(request.device->vk_device, &depth_view_create_info, NULL, &swapchain->depth.vk_view); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create depth image view"); swapchain->depth.size = (ivec3s){ .x = swapchain->extent.width, .y = swapchain->extent.height, .z = 1 }; swapchain->depth.format = depth_format; swapchain->depth.device = request.device; swapchain->device = request.device; WpStr8 msg = wpStr8Buf(4096); wpStr8Format(&msg, "Created Vulkan swapchain %p", swapchain->vk_swapchain); wpLogDebug(&logger, msg); return swapchain; } void gpuDestroySwapchain(GpuSwapchain *swapchain) { vkDestroyImageView(swapchain->device->vk_device, swapchain->depth.vk_view, NULL); vmaDestroyImage(swapchain->device->allocator, swapchain->depth.vk_image, swapchain->depth.allocation); if (swapchain->images) { for (u64 i = 0; i < wpArrayCount(swapchain->images); ++i) { vkDestroyImageView(swapchain->device->vk_device, swapchain->images[i].vk_view, NULL); } } vkDestroySwapchainKHR(swapchain->device->vk_device, swapchain->vk_swapchain, NULL); } u64 gpuGetSwapchainImageCount(GpuSwapchain *swapchain) { return wpArrayCount(swapchain->images); } GpuFormat gpuGetSwapchainImageFormat(GpuSwapchain *swapchain) { return gpuFormatFromVkFormat(swapchain->images[0].format); } GpuFormat gpuGetSwapchainDepthFormat(GpuSwapchain *swapchain) { return gpuFormatFromVkFormat(swapchain->depth.format); } GpuSampler *gpuCreateSampler(const WpAllocator *allocator, GpuSamplerCreateRequest request) { GpuSampler *output = wpMemAllocatorAlloc(allocator, sizeof(GpuSampler)); assertWithLogger(output != NULL, &logger, "Failed to allocate sampler"); VkSamplerCreateInfo info = { .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, .magFilter = vkFilterFromGpuFilter(request.mag_filter), .minFilter = vkFilterFromGpuFilter(request.min_filter), .mipmapMode = vkSamplerMipmapModeFromGpuSamplerMipmapMode(request.mipmap_mode), .addressModeU = vkSamplerAddressModeFromGpuSamplerAddressMode(request.address_mode_u), .addressModeV = vkSamplerAddressModeFromGpuSamplerAddressMode(request.address_mode_v), .addressModeW = vkSamplerAddressModeFromGpuSamplerAddressMode(request.address_mode_w), .anisotropyEnable = VK_TRUE, .maxAnisotropy = 8.0f, .maxLod = VK_LOD_CLAMP_NONE, .compareEnable = request.compare_enable, .compareOp = vkCompareOpFromGpuCompareOp(request.compare_op), }; VkResult vk_result = vkCreateSampler(request.device->vk_device, &info, NULL, &output->vk_sampler); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create Vulkan sampler"); wpLogDebug(&logger, wpStr8Lit("Created Vulkan sampler")); return output; } void gpuDestroySampler(GpuSampler *sampler) { vkDestroySampler(sampler->device->vk_device, sampler->vk_sampler, NULL); } GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest request) { VkResult vk_result = VK_SUCCESS; GpuImage *output = wpMemAllocatorAlloc(allocator, sizeof(GpuImage)); assertWithLogger(output != NULL, &logger, "Failed to allocate image"); VkFormat format = vkFormatFromGpuFormat(request.format); VkImageCreateInfo image_create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .imageType = vkImageTypeFromGpuImageType(request.type), .format = format, .extent = (VkExtent3D){ .width = request.size.x, .height = request.size.y, .depth = request.size.z }, .mipLevels = request.subresource.level_count, .arrayLayers = request.subresource.layer_count, .samples = vkSampleCountFromGpuSampleCount(request.samples), .tiling = vkImageTilingFromGpuImageTiling(request.tiling), .usage = vkImageUsageFromGpuImageUsage(request.usage), .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 1, .pQueueFamilyIndices = &request.device->physical_device.internal->queue_family_index, .initialLayout = vkImageLayoutFromGpuImageLayout(request.layout), }; VmaAllocationCreateInfo alloc_create_info = { .flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, .usage = VMA_MEMORY_USAGE_AUTO, }; vk_result = vmaCreateImage(request.device->allocator, &image_create_info, &alloc_create_info, &output->vk_image, &output->allocation, NULL); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create depth image"); VkImageViewCreateInfo view_create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = output->vk_image, .viewType = vkImageViewTypeFromGpuImageType(request.type), .format = vkFormatFromGpuFormat(request.format), .subresourceRange.aspectMask = vkImageAspectFromGpuImageAspect(request.subresource.aspect), .subresourceRange.levelCount = 1, .subresourceRange.layerCount = 1, }; vk_result = vkCreateImageView(request.device->vk_device, &view_create_info, NULL, &output->vk_view); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create depth image view"); output->size = request.size; output->format = format; wpLogDebug(&logger, wpStr8Lit("Created Vulkan image")); return output; } void gpuDestroyImage(GpuImage *image) { vkDestroyImageView(image->device->vk_device, image->vk_view, NULL); vmaDestroyImage(image->device->allocator, image->vk_image, image->allocation); } ivec3s gpuImageGetSize(GpuImage *image) { return image->size; } GpuBuffer gpuCreateBuffer(const WpAllocator *allocator, GpuBufferCreateRequest request) { GpuBuffer buffer = {0}; VkResult vk_result = VK_SUCCESS; buffer.internal = wpMemAllocatorAlloc(allocator, sizeof(GpuBufferInternal)); assertWithLogger(buffer.internal != NULL, &logger, "Failed to allocate buffer internal"); VkBufferUsageFlags2CreateInfo buf_usage_flags = { .sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO, .usage = vkBufferUsageFromGpuBufferUsage(request.usage), }; VkBufferCreateInfo buf_create_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .size = request.size, .pNext = &buf_usage_flags, }; VmaAllocationCreateInfo buf_alloc_create_info = { .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT, .usage = VMA_MEMORY_USAGE_AUTO, }; vk_result = vmaCreateBuffer(request.device->allocator, &buf_create_info, &buf_alloc_create_info, &buffer.internal->vk_buffer, &buffer.internal->allocation, &buffer.internal->allocation_info); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create buffer"); if ((request.usage & GPU_BUFFER_USAGE_SHADER_DEVICE_ADDRESS) == GPU_BUFFER_USAGE_SHADER_DEVICE_ADDRESS) { VkBufferDeviceAddressInfo buf_dev_addr_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, .buffer = buffer.internal->vk_buffer, }; buffer.gpu_device_address = vkGetBufferDeviceAddress(request.device->vk_device, &buf_dev_addr_info); } buffer.device = request.device; buffer.cpu_mapping = buffer.internal->allocation_info.pMappedData; buffer.size = buffer.internal->allocation_info.size; wpLogDebug(&logger, wpStr8Lit("Created Vulkan buffer")); return buffer; } void gpuDestroyBuffer(GpuBuffer *buffer) { vmaDestroyBuffer(buffer->device->allocator, buffer->internal->vk_buffer, buffer->internal->allocation); buffer->device = NULL; buffer->cpu_mapping = NULL; buffer->gpu_device_address = 0; buffer->size = 0; } GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device) { GpuFence *fence = wpMemAllocatorAlloc(allocator, sizeof(GpuFence)); assertWithLogger(fence != NULL, &logger, "Failed to allocate fence internal"); VkFenceCreateInfo info = { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .flags = VK_FENCE_CREATE_SIGNALED_BIT, }; VkResult vk_result = vkCreateFence(device->vk_device, &info, NULL, &fence->vk_fence); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create fence"); fence->device = device; wpLogDebug(&logger, wpStr8Lit("Created Vulkan fence")); return fence; } 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"); } GpuSemaphore *gpuCreateSemaphore(const WpAllocator *allocator, GpuDevice *device) { GpuSemaphore *semaphore = wpMemAllocatorAlloc(allocator, sizeof(GpuSemaphore)); assertWithLogger(semaphore != NULL, &logger, "Failed to allocate semaphore internal"); VkSemaphoreCreateInfo info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, }; VkResult vk_result = vkCreateSemaphore(device->vk_device, &info, NULL, &semaphore->vk_semaphore); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create semaphore"); semaphore->device = device; wpLogDebug(&logger, wpStr8Lit("Created Vulkan semaphore")); return semaphore; } void gpuDestroySemaphore(GpuSemaphore *semaphore) { vkDestroySemaphore(semaphore->device->vk_device, semaphore->vk_semaphore, NULL); } GpuCommandPool *gpuCreateCommandPool(const WpAllocator *allocator, GpuDevice *device) { GpuCommandPool *pool = wpMemAllocatorAlloc(allocator, sizeof(GpuCommandPool)); assertWithLogger(pool != NULL, &logger, "Failed to allocate pool internal"); VkCommandPoolCreateInfo pool_create_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, .queueFamilyIndex = device->physical_device.internal->queue_family_index, }; VkResult vk_result = vkCreateCommandPool(device->vk_device, &pool_create_info, NULL, &pool->vk_pool); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create command pool"); pool->device = device; wpLogDebug(&logger, wpStr8Lit("Created Vulkan command pool")); return pool; } void gpuDestroyCommandPool(GpuCommandPool *pool) { vkDestroyCommandPool(pool->device->vk_device, pool->vk_pool, NULL); } void gpuResetCommandPool(GpuCommandPool *pool) { VkResult vk_result = vkResetCommandPool(pool->device->vk_device, pool->vk_pool, 0); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to reset command pool"); } GpuCommandBufferPtrArray gpuAllocateCommandBuffers(const WpAllocator *allocator, const WpAllocator *temp, GpuCommandBufferAllocateRequest request) { VkCommandBufferArray vk_buffers = wpArrayAllocCapacity(VkCommandBuffer, temp, request.buffer_count, WP_ARRAY_INIT_FILLED); GpuCommandBufferPtrArray buffers = wpArrayAllocCapacity(GpuCommandBuffer *, allocator, request.buffer_count, WP_ARRAY_INIT_FILLED); assertWithLogger(vk_buffers != NULL && buffers != NULL, &logger, "Failed to allocate command buffer arrays"); VkCommandBufferAllocateInfo info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .commandPool = request.pool->vk_pool, .commandBufferCount = request.buffer_count, }; VkResult vk_result = vkAllocateCommandBuffers(request.pool->device->vk_device, &info, vk_buffers); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to allocate command buffers"); for (u64 i = 0; i < request.buffer_count; ++i) { buffers[i] = wpMemAllocatorAlloc(allocator, sizeof(GpuCommandBuffer)); assertWithLogger(buffers[i] != NULL, &logger, "Failed to allocate command buffer internal"); buffers[i]->pool = request.pool; buffers[i]->vk_buffer = vk_buffers[i]; } WpStr8 msg = wpStr8Buf(4096); wpStr8Format(&msg, "Allocated %" PRIu32 " command buffers from pool %p", request.buffer_count, request.pool->vk_pool); wpLogDebug(&logger, msg); return buffers; } void gpuBeginCommandBuffer(GpuCommandBuffer *buffer) { VkCommandBufferBeginInfo info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, }; VkResult vk_result = vkBeginCommandBuffer(buffer->vk_buffer, &info); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to begin command buffer"); } void gpuEndCommandBuffer(GpuCommandBuffer *buffer) { VkResult vk_result = vkEndCommandBuffer(buffer->vk_buffer); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to end command buffer"); } void gpuSubmitCommandBuffers(const WpAllocator *temp, GpuCommandBuffersSubmitRequest request) { u64 buffer_count = wpArrayCount(request.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.buffers[i]->vk_buffer; } VkSubmitInfo info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .commandBufferCount = buffer_count, .pCommandBuffers = vk_buffers, }; 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"); } void gpuResetCommandBuffer(GpuCommandBuffer *buffer) { VkResult vk_result = vkResetCommandBuffer(buffer->vk_buffer, 0); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to reset command buffer"); } GpuDescriptorPool *gpuCreateDescriptorPool(const WpAllocator *allocator, GpuDescriptorPoolCreateRequest request) { GpuDescriptorPool *output = wpMemAllocatorAlloc(allocator, sizeof(GpuDescriptorPool)); assertWithLogger(output != NULL, &logger, "Failed to allocator descriptor pool internal"); VkDescriptorPoolSizeArray sizes = wpArrayWithCapacity(VkDescriptorPoolSize, GPU_DESCRIPTOR_TYPE_COUNT, WP_ARRAY_INIT_NONE); if (request.descriptor_pool_sizes != NULL) { for (u64 i = 0; i < wpArrayCount(request.descriptor_pool_sizes); ++i) { VkDescriptorPoolSize desc_pool_size = { .type = vkDescriptorTypeFromGpuDescriptorType(request.descriptor_pool_sizes[i].type), .descriptorCount = request.descriptor_pool_sizes[i].count, }; wpArrayAppendCapped(VkDescriptorPoolSize, sizes, &desc_pool_size); } } VkDescriptorPoolCreateInfo info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .maxSets = request.max_sets, .poolSizeCount = wpArrayCount(sizes), .pPoolSizes = sizes, }; VkResult vk_result = vkCreateDescriptorPool(request.device->vk_device, &info, NULL, &output->vk_pool); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create descriptor pool"); output->device = request.device; wpLogDebug(&logger, wpStr8Lit("Created Vulkan descriptor pool successfully")); return output; } void gpuDestroyDescriptorPool(GpuDescriptorPool *pool) { vkDestroyDescriptorPool(pool->device->vk_device, pool->vk_pool, NULL); } void gpuResetDescriptorPool(GpuDescriptorPool *pool) { VkResult vk_result = vkResetDescriptorPool(pool->device->vk_device, pool->vk_pool, 0); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to reset descriptor pool"); } GpuDescriptorSetLayout *gpuCreateDescriptorSetLayout(const WpAllocator *allocator, const WpAllocator *temp, GpuDescriptorSetLayoutCreateRequest request) { GpuDescriptorSetLayout *output = wpMemAllocatorAlloc(allocator, sizeof(GpuDescriptorSetLayout)); assertWithLogger(output != NULL, &logger, "Failed to allocator descriptor set layout internal"); output->variable_descriptor_count = 0; u64 bindings_count = wpArrayCount(request.bindings); VkDescriptorSetLayoutBindingArray vk_bindings = wpArrayAllocCapacity(VkDescriptorSetLayoutBinding, temp, bindings_count, WP_ARRAY_INIT_NONE); VkDescriptorBindingFlagsArray vk_binding_flags = wpArrayAllocCapacity(VkDescriptorBindingFlags, temp, bindings_count, WP_ARRAY_INIT_NONE); assertWithLogger(vk_bindings != NULL && vk_binding_flags != NULL, &logger, "Failed to allocate temp descriptor set bindings and flags"); VkDescriptorSetLayoutBindingFlagsCreateInfo binding_flags_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, .bindingCount = bindings_count, .pBindingFlags = vk_binding_flags, }; for (u64 i = 0; i < bindings_count; ++i) { GpuDescriptorSetBinding *binding = &request.bindings[i]; b32 has_variable_count = binding->variable_count; b32 is_last_binding = (i + 1) == bindings_count; VkDescriptorBindingFlags binding_flags = 0; if (has_variable_count) { assertWithLogger(is_last_binding, &logger, "Binding has variable count but it's not the last binding"); binding_flags |= VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT; output->variable_descriptor_count = binding->descriptor_count; } wpArrayAppendCapped(VkDescriptorBindingFlags, vk_binding_flags, &binding_flags); VkDescriptorSetLayoutBinding vk_binding = { .binding = binding->binding, .descriptorType = vkDescriptorTypeFromGpuDescriptorType(binding->type), .descriptorCount = binding->descriptor_count, .stageFlags = vkShaderStageFromGpuShaderStage(binding->stages), }; wpArrayAppendCapped(VkDescriptorSetLayoutBinding, vk_bindings, &vk_binding); } VkDescriptorSetLayoutCreateInfo layout_create_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, .pNext = &binding_flags_info, .bindingCount = wpArrayCount(vk_bindings), .pBindings = vk_bindings, }; VkResult vk_result = vkCreateDescriptorSetLayout(request.device->vk_device, &layout_create_info, NULL, &output->vk_layout); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create descriptor set layout"); output->device = request.device; wpLogDebug(&logger, wpStr8Lit("Created descriptor set layout successfully")); return output; } void gpuDestroyDescriptorSetLayout(GpuDescriptorSetLayout *layout) { vkDestroyDescriptorSetLayout(layout->device->vk_device, layout->vk_layout, NULL); } GpuDescriptorSetPtrArray gpuAllocateDescriptorSets(const WpAllocator *allocator, const WpAllocator *temp, GpuDescriptorSetAllocateRequest request) { VkResult vk_result = VK_SUCCESS; u64 set_count = wpArrayCount(request.layouts); GpuDescriptorSetPtrArray output = wpArrayAllocCapacity(GpuDescriptorSet *, allocator, set_count, WP_ARRAY_INIT_FILLED); assertWithLogger(output != NULL, &logger, "Failed to allocator descriptor set array"); VkDescriptorSetLayoutArray vk_layouts = wpArrayAllocCapacity(VkDescriptorSetLayout, temp, set_count, WP_ARRAY_INIT_FILLED); VkDescriptorSetVariableDescriptorCountAllocateInfoArray vk_var_alloc_infos = wpArrayAllocCapacity(VkDescriptorSetVariableDescriptorCountAllocateInfo, temp, set_count, WP_ARRAY_INIT_FILLED); VkDescriptorSetArray vk_sets = wpArrayAllocCapacity(VkDescriptorSet, temp, set_count, WP_ARRAY_INIT_FILLED); assertWithLogger(vk_layouts != NULL && vk_sets != NULL, &logger, "Failed to allocate temp sets and layouts"); for (u64 i = 0; i < set_count; ++i) { output[i] = wpMemAllocatorAlloc(allocator, sizeof(GpuDescriptorSet)); assertWithLogger(output[i] != NULL, &logger, "Failed to allocator descriptor set internal"); vk_var_alloc_infos[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO; if (request.layouts[i]->variable_descriptor_count > 0) { vk_var_alloc_infos[i].descriptorSetCount = 1; vk_var_alloc_infos[i].pDescriptorCounts = &(request.layouts[i]->variable_descriptor_count); } vk_layouts[i] = request.layouts[i]->vk_layout; } VkDescriptorSetAllocateInfo set_alloc_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .pNext = vk_var_alloc_infos, .descriptorPool = request.pool->vk_pool, .descriptorSetCount = set_count, .pSetLayouts = vk_layouts, }; vk_result = vkAllocateDescriptorSets(request.pool->device->vk_device, &set_alloc_info, vk_sets); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to allocate descriptor sets"); for (u64 i = 0; i < set_count; ++i) { output[i]->pool = request.pool; output[i]->layout = request.layouts[i]; output[i]->vk_set = vk_sets[i]; } WpStr8 msg = wpStr8Buf(4096); wpStr8Format(&msg, "Allocated %" PRIu64 " descriptor set(s) successfully", set_count); wpLogDebug(&logger, msg); return output; } void gpuWriteDescriptorSets(const WpAllocator *temp, GpuDescriptorSetWriteRequest request) { u64 info_count = wpArrayCount(request.write_infos); u64 image_info_count = 0; u64 buffer_info_count = 0; for (u64 i = 0; i < info_count; ++i) { GpuDescriptorSetWriteInfo *info = &request.write_infos[i]; image_info_count += info->image_infos != NULL ? wpArrayCount(info->image_infos) : 0; buffer_info_count += info->buffer_infos != NULL ? wpArrayCount(info->buffer_infos) : 0; } VkWriteDescriptorSetArray vk_desc_set_writes = wpArrayAllocCapacity(VkWriteDescriptorSet, temp, info_count, WP_ARRAY_INIT_NONE); assertWithLogger(vk_desc_set_writes != NULL, &logger, "Failed to allocate temp writes array"); VkDescriptorImageInfoArray vk_desc_img_infos = NULL; if (image_info_count > 0) { vk_desc_img_infos = wpArrayAllocCapacity(VkDescriptorImageInfo, temp, image_info_count, WP_ARRAY_INIT_NONE); assertWithLogger(vk_desc_img_infos != NULL, &logger, "Failed to allocate temp image info array"); } VkDescriptorBufferInfoArray vk_desc_buf_infos = NULL; if (buffer_info_count > 0) { vk_desc_buf_infos = wpArrayAllocCapacity(VkDescriptorBufferInfo, temp, buffer_info_count, WP_ARRAY_INIT_NONE); assertWithLogger(vk_desc_buf_infos != NULL, &logger, "Failed to allocate temp buffer info array"); } u64 image_info_offset = 0; u64 buffer_info_offset = 0; for (u64 i = 0; i < info_count; ++i) { GpuDescriptorSetWriteInfo *info = &request.write_infos[i]; VkWriteDescriptorSet desc_set_write = { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .dstSet = info->set->vk_set, .dstBinding = info->dst_binding, .dstArrayElement = info->dst_array_element, .descriptorType = vkDescriptorTypeFromGpuDescriptorType(info->descriptor_type), }; GpuDescriptorCategory category = descriptorCategoryFromDescriptorType(info->descriptor_type); switch (category) { case GPU_DESCRIPTOR_CATEGORY_IMAGE: { assertWithLogger(info->image_infos != NULL, &logger, "No image info provided for an image descriptor"); image_info_offset += retrieveDescriptorImageInfos(info, &desc_set_write, vk_desc_img_infos, image_info_offset); } break; case GPU_DESCRIPTOR_CATEGORY_BUFFER: { assertWithLogger(info->buffer_infos != NULL, &logger, "No buffer info provided for a buffer descriptor"); buffer_info_offset += retrieveDescriptorBufferInfos(info, &desc_set_write, vk_desc_buf_infos, buffer_info_offset); } break; case GPU_DESCRIPTOR_CATEGORY_TEXEL_BUFFER: case GPU_DESCRIPTOR_CATEGORY_UNIFORM_BLOCK: // TODO (Abdelrahman): Handle these cases assertWithLogger(0, &logger, "Texel buffer and uniform block descriptors are not yet supported"); } wpArrayAppendCapped(VkWriteDescriptorSet, vk_desc_set_writes, &desc_set_write); } WpStr8 msg = wpStr8Buf(4096); wpStr8Format(&msg, "Wrote to %" PRIu64 " descriptor set(s) successfully", info_count); wpLogDebug(&logger, msg); vkUpdateDescriptorSets(request.device->vk_device, wpArrayCount(vk_desc_set_writes), vk_desc_set_writes, 0, NULL); } GpuShader *gpuCreateShader(const WpAllocator *allocator, GpuShaderCreateRequest request) { GpuShader *output = wpMemAllocatorAlloc(allocator, sizeof(GpuShader)); assertWithLogger(output != NULL, &logger, "Failed to allocate shader internal"); VkShaderModuleCreateInfo info = { .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .codeSize = request.size, .pCode = (u32 *)request.code, }; VkResult vk_result = vkCreateShaderModule(request.device->vk_device, &info, NULL, &output->vk_shader); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create Vulkan shader module"); output->device = request.device; wpLogDebug(&logger, wpStr8Lit("Created Vulkan shader module successfully")); return output; } void gpuDestroyShader(GpuShader *shader) { vkDestroyShaderModule(shader->device->vk_device, shader->vk_shader, NULL); } GpuPipelineLayout *gpuCreatePipelineLayout(const WpAllocator *allocator, const WpAllocator *temp, GpuPipelineLayoutCreateRequest request) { 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 = 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 < 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), .pSetLayouts = layouts, .pushConstantRangeCount = wpArrayCount(push_constants), .pPushConstantRanges = push_constants, }; VkResult vk_result = vkCreatePipelineLayout(request.device->vk_device, &info, NULL, &output->vk_layout); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create Vulkan pipeline layout"); output->device = request.device; wpLogDebug(&logger, wpStr8Lit("Created Vulkan pipeline layout successfully")); return output; } void gpuDestroyPipelineLayout(GpuPipelineLayout *layout) { vkDestroyPipelineLayout(layout->device->vk_device, layout->vk_layout, NULL); } GpuPipelinePtrArray gpuCreateGraphicsPipelines(const WpAllocator *allocator, const WpAllocator *temp, GpuGraphicsPipelinesCreateRequest request) { u64 pipeline_count = wpArrayCount(request.infos); GpuPipelinePtrArray output = wpArrayAllocCapacity(GpuPipeline *, allocator, pipeline_count, WP_ARRAY_INIT_FILLED); assertWithLogger(output != NULL, &logger, "Failed to allocate pipeline internals"); VkGraphicsPipelineCreateInfoArray infos = wpArrayAllocCapacity(VkGraphicsPipelineCreateInfo, temp, pipeline_count, WP_ARRAY_INIT_NONE); assertWithLogger(infos != NULL, &logger, "Failed to allocate pipeline create infos"); VkPipelineArray pipelines = wpArrayAllocCapacity(VkPipeline, temp, pipeline_count, WP_ARRAY_INIT_FILLED); assertWithLogger(infos != NULL, &logger, "Failed to allocate temp pipelines"); GraphicsPipelinesTempArrays temp_arrays = allocateGraphicsPipelinesTempArrays(temp, request); VkDynamicStateArray dynamic_states = wpArray(VkDynamicState, VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR); VkPipelineDynamicStateCreateInfo dynamic_state_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .dynamicStateCount = wpArrayCount(dynamic_states), .pDynamicStates = dynamic_states, }; for (u64 i = 0; i < pipeline_count; ++i) { GpuGraphicsPipelineCreateInfo *info = &request.infos[i]; u64 shader_stages_count = wpArrayCount(info->shader_stages); for (u64 j = 0; j < shader_stages_count; ++j) { u64 idx = j + temp_arrays.shader_stages_offset; temp_arrays.shader_stages[idx] = (VkPipelineShaderStageCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .stage = vkShaderStageFromGpuShaderStage(info->shader_stages[j].stage), .module = info->shader_stages[j].shader->vk_shader, .pName = info->shader_stages[j].name, }; } u64 vert_input_bindings_count = wpArrayCount(info->vertex_input_state.bindings); for (u64 j = 0; j < vert_input_bindings_count; ++j) { u64 idx = j + temp_arrays.vertex_bindings_offset; temp_arrays.vertex_bindings[idx] = (VkVertexInputBindingDescription){ .binding = info->vertex_input_state.bindings[j].binding, .stride = info->vertex_input_state.bindings[j].stride, .inputRate = vkVertexInputRateFromGpuVertexInputRate(info->vertex_input_state.bindings[j].input_rate), }; } u64 vert_input_attributes_count = wpArrayCount(info->vertex_input_state.attributes); for (u64 j = 0; j < vert_input_attributes_count; ++j) { u64 idx = j + temp_arrays.vertex_attributes_offset; temp_arrays.vertex_attributes[idx] = (VkVertexInputAttributeDescription){ .location = info->vertex_input_state.attributes[j].location, .binding = info->vertex_input_state.attributes[j].binding, .offset = info->vertex_input_state.attributes[j].offset, .format = vkFormatFromGpuFormat(info->vertex_input_state.attributes[j].format), }; } u64 blend_attachments_count = wpArrayCount(info->color_blend_state.attachments); for (u64 j = 0; j < blend_attachments_count; ++j) { u64 idx = j + temp_arrays.color_blend_attachments_offset; temp_arrays.color_blend_attachments[idx] = (VkPipelineColorBlendAttachmentState){ .blendEnable = info->color_blend_state.attachments[j].blend_enable, .srcColorBlendFactor = vkBlendFactorFromGpuBlendFactor(info->color_blend_state.attachments[j].src_color_blend_factor), .dstColorBlendFactor = vkBlendFactorFromGpuBlendFactor(info->color_blend_state.attachments[j].dst_color_blend_factor), .colorBlendOp = vkBlendOpFromGpuBlendOp(info->color_blend_state.attachments[j].color_blend_op), .srcAlphaBlendFactor = vkBlendFactorFromGpuBlendFactor(info->color_blend_state.attachments[j].src_alpha_blend_factor), .dstAlphaBlendFactor = vkBlendFactorFromGpuBlendFactor(info->color_blend_state.attachments[j].dst_alpha_blend_factor), .alphaBlendOp = vkBlendOpFromGpuBlendOp(info->color_blend_state.attachments[j].alpha_blend_op), .colorWriteMask = vkColorComponentFlagsFromGpuColorComponentFlags(info->color_blend_state.attachments[j].color_write_mask), }; } // States temp_arrays.vertex_input_states[i] = (VkPipelineVertexInputStateCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .vertexBindingDescriptionCount = vert_input_bindings_count, .pVertexBindingDescriptions = &temp_arrays.vertex_bindings[temp_arrays.vertex_bindings_offset], .vertexAttributeDescriptionCount = vert_input_attributes_count, .pVertexAttributeDescriptions = &temp_arrays.vertex_attributes[temp_arrays.vertex_attributes_offset], }; temp_arrays.input_assembly_states[i] = (VkPipelineInputAssemblyStateCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .topology = vkPrimitiveTopologyFromGpuPrimitiveTopology(info->input_assembly_state.topology), }; temp_arrays.tesselation_states[i] = (VkPipelineTessellationStateCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, .patchControlPoints = info->tesselation_state.patch_control_points, }; temp_arrays.viewport_states[i] = (VkPipelineViewportStateCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, .viewportCount = info->viewport_state.viewport_count, .scissorCount = info->viewport_state.scissor_count, }; temp_arrays.rasterization_states[i] = (VkPipelineRasterizationStateCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .depthClampEnable = info->rasterization_state.depth_clamp_enable, .rasterizerDiscardEnable = info->rasterization_state.rasterizer_discard_enable, .polygonMode = vkPolygonModeFromGpuPolygonMode(info->rasterization_state.polygon_mode), .cullMode = vkCullModeFromGpuCullMode(info->rasterization_state.cull_mode), .frontFace = vkFrontFaceFromGpuFrontFace(info->rasterization_state.front_face), .depthBiasEnable = info->rasterization_state.depth_bias_enable, .depthBiasConstantFactor = info->rasterization_state.depth_bias_constant_factor, .depthBiasClamp = info->rasterization_state.depth_bias_clamp, .depthBiasSlopeFactor = info->rasterization_state.depth_bias_slope_factor, .lineWidth = info->rasterization_state.line_width, }; temp_arrays.multisample_states[i] = (VkPipelineMultisampleStateCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .rasterizationSamples = vkSampleCountFromGpuSampleCount(info->multisample_state.rasterization_samples), .sampleShadingEnable = info->multisample_state.sample_shading_enable, .minSampleShading = info->multisample_state.min_sample_shading, }; temp_arrays.depth_stencil_states[i] = (VkPipelineDepthStencilStateCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, .depthTestEnable = info->depth_stencil_state.depth_test_enable, .depthWriteEnable = info->depth_stencil_state.depth_write_enable, .depthCompareOp = vkCompareOpFromGpuCompareOp(info->depth_stencil_state.depth_compare_op), .depthBoundsTestEnable = info->depth_stencil_state.depth_bounds_test_enable, .stencilTestEnable = info->depth_stencil_state.stencil_test_enable, .front = (VkStencilOpState){ .failOp = vkStencilOpFromGpuStencil(info->depth_stencil_state.front.fail_op), .passOp = vkStencilOpFromGpuStencil(info->depth_stencil_state.front.pass_op), .depthFailOp = vkStencilOpFromGpuStencil(info->depth_stencil_state.front.depthFail_op), .compareOp = vkCompareOpFromGpuCompareOp(info->depth_stencil_state.front.compare_op), .compareMask = info->depth_stencil_state.front.compare_mask, .writeMask = info->depth_stencil_state.front.write_mask, .reference = info->depth_stencil_state.front.reference, }, .back = (VkStencilOpState){ .failOp = vkStencilOpFromGpuStencil(info->depth_stencil_state.back.fail_op), .passOp = vkStencilOpFromGpuStencil(info->depth_stencil_state.back.pass_op), .depthFailOp = vkStencilOpFromGpuStencil(info->depth_stencil_state.back.depthFail_op), .compareOp = vkCompareOpFromGpuCompareOp(info->depth_stencil_state.back.compare_op), .compareMask = info->depth_stencil_state.back.compare_mask, .writeMask = info->depth_stencil_state.back.write_mask, .reference = info->depth_stencil_state.back.reference, }, .minDepthBounds = info->depth_stencil_state.min_depth_bounds, .maxDepthBounds = info->depth_stencil_state.max_depth_bounds, }; temp_arrays.color_blend_states[i] = (VkPipelineColorBlendStateCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, .logicOpEnable = info->color_blend_state.logic_op_enable, .logicOp = vkLogicOpFromGpuLogicOp(info->color_blend_state.logic_op), .attachmentCount = blend_attachments_count, .pAttachments = &temp_arrays.color_blend_attachments[temp_arrays.color_blend_attachments_offset], .blendConstants = { [0] = info->color_blend_state.blend_constants[0], [1] = info->color_blend_state.blend_constants[1], [2] = info->color_blend_state.blend_constants[2], [3] = info->color_blend_state.blend_constants[3], }, }; temp_arrays.color_attachment_formats[i] = vkFormatFromGpuFormat(info->color_attachment_format); temp_arrays.dynamic_rendering_infos[i] = (VkPipelineRenderingCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .colorAttachmentCount = 1, .pColorAttachmentFormats = &temp_arrays.color_attachment_formats[i], .depthAttachmentFormat = vkFormatFromGpuFormat(info->depth_attachment_format), }; VkGraphicsPipelineCreateInfo vk_info = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = &temp_arrays.dynamic_rendering_infos[i], .stageCount = shader_stages_count, .pStages = &temp_arrays.shader_stages[temp_arrays.shader_stages_offset], .pVertexInputState = &temp_arrays.vertex_input_states[i], .pInputAssemblyState = &temp_arrays.input_assembly_states[i], .pTessellationState = &temp_arrays.tesselation_states[i], .pViewportState = &temp_arrays.viewport_states[i], .pRasterizationState = &temp_arrays.rasterization_states[i], .pMultisampleState = &temp_arrays.multisample_states[i], .pDepthStencilState = &temp_arrays.depth_stencil_states[i], .pColorBlendState = &temp_arrays.color_blend_states[i], .pDynamicState = &dynamic_state_info, .layout = info->layout->vk_layout, }; temp_arrays.shader_stages_offset += shader_stages_count; temp_arrays.vertex_bindings_offset += vert_input_bindings_count; temp_arrays.vertex_attributes_offset += vert_input_attributes_count; temp_arrays.color_blend_attachments_offset += blend_attachments_count; wpArrayAppendCapped(VkGraphicsPipelineCreateInfo, infos, &vk_info); } u64 infos_count = wpArrayCount(infos); // TODO (Abdelrahman): Create pipeline cache VkResult vk_result = vkCreateGraphicsPipelines(request.device->vk_device, VK_NULL_HANDLE, infos_count, infos, NULL, pipelines); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create Vulkan graphics pipelines"); for (u64 i = 0; i < infos_count; ++i) { output[i] = wpMemAllocatorAlloc(allocator, sizeof(GpuPipeline)); assertWithLogger(output[i] != NULL, &logger, "Failed to allocate pipeline internal"); output[i]->layout = request.infos[i].layout; output[i]->vk_pipeline = pipelines[i]; } WpStr8 msg = wpStr8Buf(4096); wpStr8Format(&msg, "Created %" PRIu64 " graphics pipeline(s) successfully", infos_count); wpLogDebug(&logger, msg); return output; } GpuPipelinePtrArray gpuCreateComputePipelines(const WpAllocator *allocator, const WpAllocator *temp, GpuComputePipelinesCreateRequest request) { u64 pipeline_count = wpArrayCount(request.infos); GpuPipelinePtrArray output = wpArrayAllocCapacity(GpuPipeline *, allocator, pipeline_count, WP_ARRAY_INIT_FILLED); assertWithLogger(output != NULL, &logger, "Failed to allocate pipeline array"); VkComputePipelineCreateInfoArray infos = wpArrayAllocCapacity(VkComputePipelineCreateInfo, temp, pipeline_count, WP_ARRAY_INIT_NONE); assertWithLogger(infos != NULL, &logger, "Failed to allocate pipeline create infos"); VkPipelineArray pipelines = wpArrayAllocCapacity(VkPipeline, temp, pipeline_count, WP_ARRAY_INIT_FILLED); assertWithLogger(infos != NULL, &logger, "Failed to allocate temp pipelines"); for (u64 i = 0; i < pipeline_count; ++i) { VkComputePipelineCreateInfo info = { .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, .stage = (VkPipelineShaderStageCreateInfo){ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .stage = vkShaderStageFromGpuShaderStage(request.infos[i].shader_stage.stage), .module = request.infos[i].shader_stage.shader->vk_shader, .pName = request.infos[i].shader_stage.name, }, .layout = request.infos[i].layout->vk_layout, }; wpArrayAppendCapped(VkComputePipelineCreateInfo, infos, &info); } u64 infos_count = wpArrayCount(infos); // TODO (Abdelrahman): Create pipeline cache VkResult vk_result = vkCreateComputePipelines(request.device->vk_device, VK_NULL_HANDLE, infos_count, infos, NULL, pipelines); assertWithLogger(vk_result == VK_SUCCESS, &logger, "Failed to create Vulkan compute pipelines"); for (u64 i = 0; i < infos_count; ++i) { output[i] = wpMemAllocatorAlloc(allocator, sizeof(GpuPipeline)); assertWithLogger(output[i] != NULL, &logger, "Failed to allocate pipeline internal"); output[i]->layout = request.infos[i].layout; output[i]->vk_pipeline = pipelines[i]; } WpStr8 msg = wpStr8Buf(4096); wpStr8Format(&msg, "Created %" PRIu64 " compute pipeline(s) successfully", infos_count); wpLogDebug(&logger, msg); return output; } void gpuDestroyPipeline(GpuPipeline *pipeline) { vkDestroyPipeline(pipeline->layout->device->vk_device, pipeline->vk_pipeline, NULL); } void gpuDeviceWaitIdle(GpuDevice *device) { vkDeviceWaitIdle(device->vk_device); } wp_intern VkExtensions getInstanceExtensions(void) { Config config = configGet(); VkExtensions output = {0}; switch (config.window_backend) { case WINDOW_BACKEND_SDL: { output.extensions = SDL_Vulkan_GetInstanceExtensions(&output.count); } break; default: break; } return output; } wp_intern GpuPhysicalDeviceType vkDeviceTypeToGpuDeviceType(VkPhysicalDeviceType type) { switch (type) { case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return GPU_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return GPU_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return GPU_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU; case VK_PHYSICAL_DEVICE_TYPE_CPU: return GPU_PHYSICAL_DEVICE_TYPE_CPU; default: return GPU_PHYSICAL_DEVICE_TYPE_UNKNOWN; } } wp_intern VkPhysicalDeviceType gpuDeviceTypeToVkDeviceType(GpuPhysicalDeviceType type) { switch (type) { case GPU_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; case GPU_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; case GPU_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU; case GPU_PHYSICAL_DEVICE_TYPE_CPU: return VK_PHYSICAL_DEVICE_TYPE_CPU; default: return VK_PHYSICAL_DEVICE_TYPE_OTHER; } } wp_intern i32 findQueueFamily(const WpAllocator *allocator, VkInstance instance, VkPhysicalDevice physical_device, GpuPhysicalDeviceOps ops) { i32 queue_family_index = -1; u32 queue_family_count = 0; vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_count, NULL); if (queue_family_count == 0) { goto FIND_QUEUE_FAMILY_RETURN; } VkQueueFamilyProperties2Array queue_family_properties = wpArrayAllocCapacity(VkQueueFamilyProperties2, allocator, queue_family_count, WP_ARRAY_INIT_FILLED); if (!queue_family_properties) { goto FIND_QUEUE_FAMILY_RETURN; } for (u32 i = 0; i < queue_family_count; ++i) { queue_family_properties[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; } vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &queue_family_count, queue_family_properties); VkQueueFlags requested_flags = queueFlagsFromOps(ops); b8 presentation_requested = (ops & GPU_PHYSICAL_DEVICE_OP_PRESENTATION) == GPU_PHYSICAL_DEVICE_OP_PRESENTATION; for (u32 i = 0; i < queue_family_count; ++i) { VkQueueFlags queue_flags = queue_family_properties[i].queueFamilyProperties.queueFlags; b8 presentation_supported = presentationSupported(instance, physical_device, i); b8 ops_supported = (queue_flags & requested_flags) == requested_flags; if (ops_supported && (!presentation_requested || presentation_supported)) { queue_family_index = i; break; } } FIND_QUEUE_FAMILY_RETURN: return queue_family_index; } wp_intern VkQueueFlags queueFlagsFromOps(GpuPhysicalDeviceOps ops) { VkQueueFlags flags = 0; flags |= (ops & GPU_PHYSICAL_DEVICE_OP_GRAPHICS) != 0 ? VK_QUEUE_GRAPHICS_BIT : 0; flags |= (ops & GPU_PHYSICAL_DEVICE_OP_COMPUTE) != 0 ? VK_QUEUE_COMPUTE_BIT : 0; flags |= (ops & GPU_PHYSICAL_DEVICE_OP_TRANSFER) != 0 ? VK_QUEUE_TRANSFER_BIT : 0; flags |= (ops & GPU_PHYSICAL_DEVICE_OP_VIDEO_DECODE) != 0 ? VK_QUEUE_VIDEO_DECODE_BIT_KHR : 0; flags |= (ops & GPU_PHYSICAL_DEVICE_OP_VIDEO_ENCODE) != 0 ? VK_QUEUE_VIDEO_ENCODE_BIT_KHR : 0; return flags; } wp_intern b8 presentationSupported(VkInstance instance, VkPhysicalDevice device, u32 queue_family_index) { Config config = configGet(); switch (config.window_backend) { case WINDOW_BACKEND_SDL: return SDL_Vulkan_GetPresentationSupport(instance, device, queue_family_index); default: return false; } } wp_intern b8 windowBackendCreateSurface(const Window *window, VkInstance instance, VkSurfaceKHR *surface) { Config config = configGet(); switch (config.window_backend) { case WINDOW_BACKEND_SDL: return SDL_Vulkan_CreateSurface((SDL_Window *)window->internal.window, instance, NULL, surface); default: return false; } } wp_intern VkFormat vkFormatFromGpuFormat(GpuFormat format) { switch (format) { case GPU_FORMAT_R8_UINT: return VK_FORMAT_R8_UINT; case GPU_FORMAT_R8_SINT: return VK_FORMAT_R8_SINT; case GPU_FORMAT_R8_SRGB: return VK_FORMAT_R8_SRGB; case GPU_FORMAT_R8G8_UINT: return VK_FORMAT_R8G8_UINT; case GPU_FORMAT_R8G8_SINT: return VK_FORMAT_R8G8_SINT; case GPU_FORMAT_R8G8_SRGB: return VK_FORMAT_R8G8_SRGB; case GPU_FORMAT_R8G8B8_UINT: return VK_FORMAT_R8G8B8_UINT; case GPU_FORMAT_R8G8B8_SINT: return VK_FORMAT_R8G8B8_SINT; case GPU_FORMAT_R8G8B8_SRGB: return VK_FORMAT_R8G8B8_SRGB; case GPU_FORMAT_B8G8R8_UINT: return VK_FORMAT_B8G8R8_UINT; case GPU_FORMAT_B8G8R8_SINT: return VK_FORMAT_B8G8R8_SINT; case GPU_FORMAT_B8G8R8_SRGB: return VK_FORMAT_B8G8R8_SRGB; case GPU_FORMAT_R8G8B8A8_UINT: return VK_FORMAT_R8G8B8A8_UINT; case GPU_FORMAT_R8G8B8A8_SINT: return VK_FORMAT_R8G8B8A8_SINT; case GPU_FORMAT_R8G8B8A8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB; case GPU_FORMAT_B8G8R8A8_UINT: return VK_FORMAT_B8G8R8A8_UINT; case GPU_FORMAT_B8G8R8A8_SINT: return VK_FORMAT_B8G8R8A8_SINT; case GPU_FORMAT_B8G8R8A8_SRGB: return VK_FORMAT_B8G8R8A8_SRGB; case GPU_FORMAT_R16_UINT: return VK_FORMAT_R16_UINT; case GPU_FORMAT_R16_SINT: return VK_FORMAT_R16_SINT; case GPU_FORMAT_R16_SFLOAT: return VK_FORMAT_R16_SFLOAT; case GPU_FORMAT_R16G16_UINT: return VK_FORMAT_R16G16_UINT; case GPU_FORMAT_R16G16_SINT: return VK_FORMAT_R16G16_SINT; case GPU_FORMAT_R16G16_SFLOAT: return VK_FORMAT_R16G16_SFLOAT; case GPU_FORMAT_R16G16B16_UINT: return VK_FORMAT_R16G16B16_UINT; case GPU_FORMAT_R16G16B16_SINT: return VK_FORMAT_R16G16B16_SINT; case GPU_FORMAT_R16G16B16_SFLOAT: return VK_FORMAT_R16G16B16_SFLOAT; case GPU_FORMAT_R16G16B16A16_UINT: return VK_FORMAT_R16G16B16A16_UINT; case GPU_FORMAT_R16G16B16A16_SINT: return VK_FORMAT_R16G16B16A16_SINT; case GPU_FORMAT_R16G16B16A16_SFLOAT: return VK_FORMAT_R16G16B16A16_SFLOAT; case GPU_FORMAT_R32_UINT: return VK_FORMAT_R32_UINT; case GPU_FORMAT_R32_SINT: return VK_FORMAT_R32_SINT; case GPU_FORMAT_R32_SFLOAT: return VK_FORMAT_R32_SFLOAT; case GPU_FORMAT_R32G32_UINT: return VK_FORMAT_R32G32_UINT; case GPU_FORMAT_R32G32_SINT: return VK_FORMAT_R32G32_SINT; case GPU_FORMAT_R32G32_SFLOAT: return VK_FORMAT_R32G32_SFLOAT; case GPU_FORMAT_R32G32B32_UINT: return VK_FORMAT_R32G32B32_UINT; case GPU_FORMAT_R32G32B32_SINT: return VK_FORMAT_R32G32B32_SINT; case GPU_FORMAT_R32G32B32_SFLOAT: return VK_FORMAT_R32G32B32_SFLOAT; case GPU_FORMAT_R32G32B32A32_UINT: return VK_FORMAT_R32G32B32A32_UINT; case GPU_FORMAT_R32G32B32A32_SINT: return VK_FORMAT_R32G32B32A32_SINT; case GPU_FORMAT_R32G32B32A32_SFLOAT: return VK_FORMAT_R32G32B32A32_SFLOAT; case GPU_FORMAT_R64_UINT: return VK_FORMAT_R64_UINT; case GPU_FORMAT_R64_SINT: return VK_FORMAT_R64_SINT; case GPU_FORMAT_R64_SFLOAT: return VK_FORMAT_R64_SFLOAT; case GPU_FORMAT_R64G64_UINT: return VK_FORMAT_R64G64_UINT; case GPU_FORMAT_R64G64_SINT: return VK_FORMAT_R64G64_SINT; case GPU_FORMAT_R64G64_SFLOAT: return VK_FORMAT_R64G64_SFLOAT; case GPU_FORMAT_R64G64B64_UINT: return VK_FORMAT_R64G64B64_UINT; case GPU_FORMAT_R64G64B64_SINT: return VK_FORMAT_R64G64B64_SINT; case GPU_FORMAT_R64G64B64_SFLOAT: return VK_FORMAT_R64G64B64_SFLOAT; case GPU_FORMAT_R64G64B64A64_UINT: return VK_FORMAT_R64G64B64A64_UINT; case GPU_FORMAT_R64G64B64A64_SINT: return VK_FORMAT_R64G64B64A64_SINT; case GPU_FORMAT_R64G64B64A64_SFLOAT: return VK_FORMAT_R64G64B64A64_SFLOAT; case GPU_FORMAT_D24_UNORM_S8_UINT: return VK_FORMAT_D24_UNORM_S8_UINT; case GPU_FORMAT_D32_SFLOAT_S8_UINT: return VK_FORMAT_D32_SFLOAT_S8_UINT; default: return VK_FORMAT_UNDEFINED; } } wp_intern GpuFormat gpuFormatFromVkFormat(VkFormat format) { switch (format) { case VK_FORMAT_R8_UINT: return GPU_FORMAT_R8_UINT; case VK_FORMAT_R8_SINT: return GPU_FORMAT_R8_SINT; case VK_FORMAT_R8_SRGB: return GPU_FORMAT_R8_SRGB; case VK_FORMAT_R8G8_UINT: return GPU_FORMAT_R8G8_UINT; case VK_FORMAT_R8G8_SINT: return GPU_FORMAT_R8G8_SINT; case VK_FORMAT_R8G8_SRGB: return GPU_FORMAT_R8G8_SRGB; case VK_FORMAT_R8G8B8_UINT: return GPU_FORMAT_R8G8B8_UINT; case VK_FORMAT_R8G8B8_SINT: return GPU_FORMAT_R8G8B8_SINT; case VK_FORMAT_R8G8B8_SRGB: return GPU_FORMAT_R8G8B8_SRGB; case VK_FORMAT_B8G8R8_UINT: return GPU_FORMAT_B8G8R8_UINT; case VK_FORMAT_B8G8R8_SINT: return GPU_FORMAT_B8G8R8_SINT; case VK_FORMAT_B8G8R8_SRGB: return GPU_FORMAT_B8G8R8_SRGB; case VK_FORMAT_R8G8B8A8_UINT: return GPU_FORMAT_R8G8B8A8_UINT; case VK_FORMAT_R8G8B8A8_SINT: return GPU_FORMAT_R8G8B8A8_SINT; case VK_FORMAT_R8G8B8A8_SRGB: return GPU_FORMAT_R8G8B8A8_SRGB; case VK_FORMAT_B8G8R8A8_UINT: return GPU_FORMAT_B8G8R8A8_UINT; case VK_FORMAT_B8G8R8A8_SINT: return GPU_FORMAT_B8G8R8A8_SINT; case VK_FORMAT_B8G8R8A8_SRGB: return GPU_FORMAT_B8G8R8A8_SRGB; case VK_FORMAT_R16_UINT: return GPU_FORMAT_R16_UINT; case VK_FORMAT_R16_SINT: return GPU_FORMAT_R16_SINT; case VK_FORMAT_R16_SFLOAT: return GPU_FORMAT_R16_SFLOAT; case VK_FORMAT_R16G16_UINT: return GPU_FORMAT_R16G16_UINT; case VK_FORMAT_R16G16_SINT: return GPU_FORMAT_R16G16_SINT; case VK_FORMAT_R16G16_SFLOAT: return GPU_FORMAT_R16G16_SFLOAT; case VK_FORMAT_R16G16B16_UINT: return GPU_FORMAT_R16G16B16_UINT; case VK_FORMAT_R16G16B16_SINT: return GPU_FORMAT_R16G16B16_SINT; case VK_FORMAT_R16G16B16_SFLOAT: return GPU_FORMAT_R16G16B16_SFLOAT; case VK_FORMAT_R16G16B16A16_UINT: return GPU_FORMAT_R16G16B16A16_UINT; case VK_FORMAT_R16G16B16A16_SINT: return GPU_FORMAT_R16G16B16A16_SINT; case VK_FORMAT_R16G16B16A16_SFLOAT: return GPU_FORMAT_R16G16B16A16_SFLOAT; case VK_FORMAT_R32_UINT: return GPU_FORMAT_R32_UINT; case VK_FORMAT_R32_SINT: return GPU_FORMAT_R32_SINT; case VK_FORMAT_R32_SFLOAT: return GPU_FORMAT_R32_SFLOAT; case VK_FORMAT_R32G32_UINT: return GPU_FORMAT_R32G32_UINT; case VK_FORMAT_R32G32_SINT: return GPU_FORMAT_R32G32_SINT; case VK_FORMAT_R32G32_SFLOAT: return GPU_FORMAT_R32G32_SFLOAT; case VK_FORMAT_R32G32B32_UINT: return GPU_FORMAT_R32G32B32_UINT; case VK_FORMAT_R32G32B32_SINT: return GPU_FORMAT_R32G32B32_SINT; case VK_FORMAT_R32G32B32_SFLOAT: return GPU_FORMAT_R32G32B32_SFLOAT; case VK_FORMAT_R32G32B32A32_UINT: return GPU_FORMAT_R32G32B32A32_UINT; case VK_FORMAT_R32G32B32A32_SINT: return GPU_FORMAT_R32G32B32A32_SINT; case VK_FORMAT_R32G32B32A32_SFLOAT: return GPU_FORMAT_R32G32B32A32_SFLOAT; case VK_FORMAT_R64_UINT: return GPU_FORMAT_R64_UINT; case VK_FORMAT_R64_SINT: return GPU_FORMAT_R64_SINT; case VK_FORMAT_R64_SFLOAT: return GPU_FORMAT_R64_SFLOAT; case VK_FORMAT_R64G64_UINT: return GPU_FORMAT_R64G64_UINT; case VK_FORMAT_R64G64_SINT: return GPU_FORMAT_R64G64_SINT; case VK_FORMAT_R64G64_SFLOAT: return GPU_FORMAT_R64G64_SFLOAT; case VK_FORMAT_R64G64B64_UINT: return GPU_FORMAT_R64G64B64_UINT; case VK_FORMAT_R64G64B64_SINT: return GPU_FORMAT_R64G64B64_SINT; case VK_FORMAT_R64G64B64_SFLOAT: return GPU_FORMAT_R64G64B64_SFLOAT; case VK_FORMAT_R64G64B64A64_UINT: return GPU_FORMAT_R64G64B64A64_UINT; case VK_FORMAT_R64G64B64A64_SINT: return GPU_FORMAT_R64G64B64A64_SINT; case VK_FORMAT_R64G64B64A64_SFLOAT: return GPU_FORMAT_R64G64B64A64_SFLOAT; case VK_FORMAT_D24_UNORM_S8_UINT: return GPU_FORMAT_D24_UNORM_S8_UINT; case VK_FORMAT_D32_SFLOAT_S8_UINT: return GPU_FORMAT_D32_SFLOAT_S8_UINT; default: return GPU_FORMAT_UNDEFINED; } } 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; } } 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_COLORSPACE_SRGB_NONLINEAR_KHR: return GPU_COLORSPACE_SRGB_NONLINEAR; default: return GPU_COLOR_SPACE_SRGB_NONLINEAR; } } wp_intern VkPresentModeKHR vkPresentModeFromGpuPresentMode(GpuPresentMode mode) { switch (mode) { case GPU_PRESENT_MODE_IMMEDIATE: return VK_PRESENT_MODE_IMMEDIATE_KHR; case GPU_PRESENT_MODE_FIFO: return VK_PRESENT_MODE_FIFO_KHR; case GPU_PRESENT_MODE_FIFO_RELAXED: return VK_PRESENT_MODE_FIFO_RELAXED_KHR; case GPU_PRESENT_MODE_FIFO_LATEST_READY: return VK_PRESENT_MODE_FIFO_LATEST_READY_KHR; } } wp_intern GpuPresentMode gpuPresentModeFromVkPresentMode(VkPresentModeKHR mode) { switch (mode) { case VK_PRESENT_MODE_FIFO_KHR: return GPU_PRESENT_MODE_FIFO; case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return GPU_PRESENT_MODE_FIFO_RELAXED; case VK_PRESENT_MODE_FIFO_LATEST_READY_KHR: return GPU_PRESENT_MODE_FIFO_LATEST_READY; default: return GPU_PRESENT_MODE_IMMEDIATE; } } wp_intern VkImageType vkImageTypeFromGpuImageType(GpuImageType type) { switch (type) { case GPU_IMAGE_TYPE_1D: return VK_IMAGE_TYPE_1D; case GPU_IMAGE_TYPE_2D: return VK_IMAGE_TYPE_2D; case GPU_IMAGE_TYPE_3D: return VK_IMAGE_TYPE_3D; } } wp_intern GpuImageType gpuImageTypeFromVkImageType(VkImageType type) { switch (type) { case VK_IMAGE_TYPE_1D: return GPU_IMAGE_TYPE_1D; case VK_IMAGE_TYPE_2D: return GPU_IMAGE_TYPE_2D; case VK_IMAGE_TYPE_3D: return GPU_IMAGE_TYPE_3D; default: return GPU_IMAGE_TYPE_2D; } } wp_intern VkImageViewType vkImageViewTypeFromGpuImageType(GpuImageType type) { switch (type) { case GPU_IMAGE_TYPE_1D: return VK_IMAGE_VIEW_TYPE_1D; case GPU_IMAGE_TYPE_2D: return VK_IMAGE_VIEW_TYPE_2D; case GPU_IMAGE_TYPE_3D: return VK_IMAGE_VIEW_TYPE_3D; } } wp_intern GpuImageType gpuImageTypeFromVkImageViewType(VkImageViewType type) { switch (type) { case VK_IMAGE_VIEW_TYPE_1D: return GPU_IMAGE_TYPE_1D; case VK_IMAGE_VIEW_TYPE_2D: return GPU_IMAGE_TYPE_2D; case VK_IMAGE_VIEW_TYPE_3D: return GPU_IMAGE_TYPE_3D; default: return GPU_IMAGE_TYPE_2D; } } wp_intern VkSampleCountFlagBits vkSampleCountFromGpuSampleCount(GpuSampleCount samples) { switch (samples) { case GPU_SAMPLE_COUNT_1_BIT: return VK_SAMPLE_COUNT_1_BIT; case GPU_SAMPLE_COUNT_2_BIT: return VK_SAMPLE_COUNT_2_BIT; case GPU_SAMPLE_COUNT_4_BIT: return VK_SAMPLE_COUNT_4_BIT; case GPU_SAMPLE_COUNT_8_BIT: return VK_SAMPLE_COUNT_8_BIT; case GPU_SAMPLE_COUNT_16_BIT: return VK_SAMPLE_COUNT_16_BIT; case GPU_SAMPLE_COUNT_32_BIT: return VK_SAMPLE_COUNT_32_BIT; case GPU_SAMPLE_COUNT_64_BIT: return VK_SAMPLE_COUNT_64_BIT; } } wp_intern GpuSampleCount gpuSampleCountFromVkSampleCount(VkSampleCountFlagBits samples) { switch (samples) { case VK_SAMPLE_COUNT_1_BIT: return GPU_SAMPLE_COUNT_1_BIT; case VK_SAMPLE_COUNT_2_BIT: return GPU_SAMPLE_COUNT_2_BIT; case VK_SAMPLE_COUNT_4_BIT: return GPU_SAMPLE_COUNT_4_BIT; case VK_SAMPLE_COUNT_8_BIT: return GPU_SAMPLE_COUNT_8_BIT; case VK_SAMPLE_COUNT_16_BIT: return GPU_SAMPLE_COUNT_16_BIT; case VK_SAMPLE_COUNT_32_BIT: return GPU_SAMPLE_COUNT_32_BIT; case VK_SAMPLE_COUNT_64_BIT: return GPU_SAMPLE_COUNT_64_BIT; default: return GPU_SAMPLE_COUNT_1_BIT; } } wp_intern VkImageTiling vkImageTilingFromGpuImageTiling(GpuImageTiling tiling) { switch (tiling) { case GPU_IMAGE_TILING_LINEAR: return VK_IMAGE_TILING_LINEAR; default: return VK_IMAGE_TILING_OPTIMAL; } } wp_intern GpuImageTiling gpuImageTilingFromVkImageTiling(VkImageTiling tiling) { switch (tiling) { case VK_IMAGE_TILING_LINEAR: return GPU_IMAGE_TILING_LINEAR; default: return GPU_IMAGE_TILING_OPTIMAL; } } wp_intern VkImageUsageFlags vkImageUsageFromGpuImageUsage(GpuImageUsage usage) { VkImageUsageFlags output = 0; output |= (usage & GPU_IMAGE_USAGE_TRANSFER_SRC) != 0 ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_TRANSFER_DST) != 0 ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_SAMPLED) != 0 ? VK_IMAGE_USAGE_SAMPLED_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_STORAGE) != 0 ? VK_IMAGE_USAGE_STORAGE_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_COLOR_ATTACHMENT) != 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT) != 0 ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_TRANSIENT_ATTACHMENT) != 0 ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_INPUT_ATTACHMENT) != 0 ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_HOST_TRANSFER) != 0 ? VK_IMAGE_USAGE_HOST_TRANSFER_BIT : 0; output |= (usage & GPU_IMAGE_USAGE_VIDEO_DECODE_DST) != 0 ? VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR : 0; output |= (usage & GPU_IMAGE_USAGE_VIDEO_DECODE_SRC) != 0 ? VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR : 0; output |= (usage & GPU_IMAGE_USAGE_FRAGMENT_DENSITY_MAP) != 0 ? VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT : 0; output |= (usage & GPU_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT) != 0 ? VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR : 0; output |= (usage & GPU_IMAGE_USAGE_VIDEO_ENCODE_DST) != 0 ? VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR : 0; output |= (usage & GPU_IMAGE_USAGE_VIDEO_ENCODE_SRC) != 0 ? VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR : 0; return output; } wp_intern GpuImageUsage gpuImageUsageFromVkImageUsage(VkImageUsageFlags usage) { GpuImageUsage output = 0; output |= (usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) != 0 ? GPU_IMAGE_USAGE_TRANSFER_SRC : 0; output |= (usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0 ? GPU_IMAGE_USAGE_TRANSFER_DST : 0; output |= (usage & VK_IMAGE_USAGE_SAMPLED_BIT) != 0 ? GPU_IMAGE_USAGE_SAMPLED : 0; output |= (usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0 ? GPU_IMAGE_USAGE_STORAGE : 0; output |= (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0 ? GPU_IMAGE_USAGE_COLOR_ATTACHMENT : 0; output |= (usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0 ? GPU_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT : 0; output |= (usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0 ? GPU_IMAGE_USAGE_TRANSIENT_ATTACHMENT : 0; output |= (usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) != 0 ? GPU_IMAGE_USAGE_INPUT_ATTACHMENT : 0; output |= (usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT) != 0 ? GPU_IMAGE_USAGE_HOST_TRANSFER : 0; output |= (usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) != 0 ? GPU_IMAGE_USAGE_VIDEO_DECODE_DST : 0; output |= (usage & VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR) != 0 ? GPU_IMAGE_USAGE_VIDEO_DECODE_SRC : 0; output |= (usage & VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT) != 0 ? GPU_IMAGE_USAGE_FRAGMENT_DENSITY_MAP : 0; output |= (usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR) != 0 ? GPU_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT : 0; output |= (usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR) != 0 ? GPU_IMAGE_USAGE_VIDEO_ENCODE_DST : 0; output |= (usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) != 0 ? GPU_IMAGE_USAGE_VIDEO_ENCODE_SRC : 0; return output; } wp_intern VkImageLayout vkImageLayoutFromGpuImageLayout(GpuImageLayout layout) { switch (layout) { case GPU_IMAGE_LAYOUT_GENERAL: return VK_IMAGE_LAYOUT_GENERAL; case GPU_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; case GPU_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; case GPU_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; case GPU_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; case GPU_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; case GPU_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; case GPU_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; case GPU_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; case GPU_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; case GPU_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL; case GPU_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL; case GPU_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL: return VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL; case GPU_IMAGE_LAYOUT_READ_ONLY_OPTIMAL: return VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; case GPU_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; case GPU_IMAGE_LAYOUT_PRESENT_SRC: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; case GPU_IMAGE_LAYOUT_VIDEO_DECODE_DST: return VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR; case GPU_IMAGE_LAYOUT_VIDEO_DECODE_SRC: return VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR; case GPU_IMAGE_LAYOUT_SHARED_PRESENT: return VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR; case GPU_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL: return VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT; case GPU_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL: return VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; case GPU_IMAGE_LAYOUT_VIDEO_ENCODE_DST: return VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR; case GPU_IMAGE_LAYOUT_VIDEO_ENCODE_SRC: return VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR; case GPU_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP: return VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR; default: return VK_IMAGE_LAYOUT_UNDEFINED; } } wp_intern GpuImageLayout gpuImageLayoutFromVkImageLayout(VkImageLayout layout) { switch (layout) { case VK_IMAGE_LAYOUT_GENERAL: return GPU_IMAGE_LAYOUT_GENERAL; case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return GPU_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: return GPU_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return GPU_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return GPU_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return GPU_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return GPU_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: return GPU_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: return GPU_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL; case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL: return GPU_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL: return GPU_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL; case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL: return GPU_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL; case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL: return GPU_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL; case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL: return GPU_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL: return GPU_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL; case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: return GPU_IMAGE_LAYOUT_PRESENT_SRC; case VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR: return GPU_IMAGE_LAYOUT_VIDEO_DECODE_DST; case VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR: return GPU_IMAGE_LAYOUT_VIDEO_DECODE_SRC; case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR: return GPU_IMAGE_LAYOUT_SHARED_PRESENT; case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT: return GPU_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL; case VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR: return GPU_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL; case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR: return GPU_IMAGE_LAYOUT_VIDEO_ENCODE_DST; case VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR: return GPU_IMAGE_LAYOUT_VIDEO_ENCODE_SRC; case VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR: return GPU_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP; default: return GPU_IMAGE_LAYOUT_UNDEFINED; } } wp_intern VkImageAspectFlags vkImageAspectFromGpuImageAspect(GpuImageAspect aspect) { VkImageAspectFlags output = VK_IMAGE_ASPECT_NONE; output |= (aspect & GPU_IMAGE_ASPECT_COLOR_BIT) != 0 ? VK_IMAGE_ASPECT_COLOR_BIT : 0; output |= (aspect & GPU_IMAGE_ASPECT_DEPTH_BIT) != 0 ? VK_IMAGE_ASPECT_DEPTH_BIT : 0; output |= (aspect & GPU_IMAGE_ASPECT_STENCIL_BIT) != 0 ? VK_IMAGE_ASPECT_STENCIL_BIT : 0; return output; } wp_intern GpuImageAspect gpuImageAspectFromVkImageAspect(VkImageAspectFlags aspect) { GpuImageAspect output = GPU_IMAGE_ASPECT_NONE; output |= (aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0 ? GPU_IMAGE_ASPECT_COLOR_BIT : 0; output |= (aspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0 ? GPU_IMAGE_ASPECT_DEPTH_BIT : 0; output |= (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 ? GPU_IMAGE_ASPECT_STENCIL_BIT : 0; return output; } wp_intern VkBufferUsageFlags2 vkBufferUsageFromGpuBufferUsage(GpuBufferUsage usage) { VkBufferUsageFlags2 output = 0; output |= (usage & GPU_BUFFER_USAGE_TRANSFER_SRC) != 0 ? VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_TRANSFER_DST) != 0 ? VK_BUFFER_USAGE_2_TRANSFER_DST_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER) != 0 ? VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_STORAGE_TEXEL_BUFFER) != 0 ? VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_UNIFORM_BUFFER) != 0 ? VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_STORAGE_BUFFER) != 0 ? VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_INDEX_BUFFER) != 0 ? VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_VERTEX_BUFFER) != 0 ? VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_INDIRECT_BUFFER) != 0 ? VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_SHADER_DEVICE_ADDRESS) != 0 ? VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT : 0; output |= (usage & GPU_BUFFER_USAGE_DESCRIPTOR_HEAP) != 0 ? VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT : 0; output |= (usage & GPU_BUFFER_USAGE_CONDITIONAL_RENDERING) != 0 ? VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT : 0; output |= (usage & GPU_BUFFER_USAGE_SHADER_BINDING_TABLE) != 0 ? VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR : 0; output |= (usage & GPU_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER) != 0 ? VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT : 0; output |= (usage & GPU_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER) != 0 ? VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT : 0; output |= (usage & GPU_BUFFER_USAGE_VIDEO_DECODE_SRC) != 0 ? VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR : 0; output |= (usage & GPU_BUFFER_USAGE_VIDEO_DECODE_DST) != 0 ? VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR : 0; output |= (usage & GPU_BUFFER_USAGE_VIDEO_ENCODE_DST) != 0 ? VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR : 0; output |= (usage & GPU_BUFFER_USAGE_VIDEO_ENCODE_SRC) != 0 ? VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR : 0; output |= (usage & GPU_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER) != 0 ? VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT : 0; output |= (usage & GPU_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER) != 0 ? VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT : 0; output |= (usage & GPU_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER) != 0 ? VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT : 0; return output; } wp_intern GpuBufferUsage gpuBufferUsageFromVkBufferUsage(VkBufferUsageFlags2 usage) { GpuBufferUsage output = 0; output |= (usage & VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT) != 0 ? GPU_BUFFER_USAGE_TRANSFER_SRC : 0; output |= (usage & VK_BUFFER_USAGE_2_TRANSFER_DST_BIT) != 0 ? GPU_BUFFER_USAGE_TRANSFER_DST : 0; output |= (usage & VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT) != 0 ? GPU_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT) != 0 ? GPU_BUFFER_USAGE_STORAGE_TEXEL_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_UNIFORM_BUFFER_BIT) != 0 ? GPU_BUFFER_USAGE_UNIFORM_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT) != 0 ? GPU_BUFFER_USAGE_STORAGE_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT) != 0 ? GPU_BUFFER_USAGE_INDEX_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_VERTEX_BUFFER_BIT) != 0 ? GPU_BUFFER_USAGE_VERTEX_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT) != 0 ? GPU_BUFFER_USAGE_INDIRECT_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT) != 0 ? GPU_BUFFER_USAGE_SHADER_DEVICE_ADDRESS : 0; output |= (usage & VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT) != 0 ? GPU_BUFFER_USAGE_DESCRIPTOR_HEAP : 0; output |= (usage & VK_BUFFER_USAGE_2_CONDITIONAL_RENDERING_BIT_EXT) != 0 ? GPU_BUFFER_USAGE_CONDITIONAL_RENDERING : 0; output |= (usage & VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR) != 0 ? GPU_BUFFER_USAGE_SHADER_BINDING_TABLE : 0; output |= (usage & VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT) != 0 ? GPU_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT) != 0 ? GPU_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_VIDEO_DECODE_SRC_BIT_KHR) != 0 ? GPU_BUFFER_USAGE_VIDEO_DECODE_SRC : 0; output |= (usage & VK_BUFFER_USAGE_2_VIDEO_DECODE_DST_BIT_KHR) != 0 ? GPU_BUFFER_USAGE_VIDEO_DECODE_DST : 0; output |= (usage & VK_BUFFER_USAGE_2_VIDEO_ENCODE_DST_BIT_KHR) != 0 ? GPU_BUFFER_USAGE_VIDEO_ENCODE_DST : 0; output |= (usage & VK_BUFFER_USAGE_2_VIDEO_ENCODE_SRC_BIT_KHR) != 0 ? GPU_BUFFER_USAGE_VIDEO_ENCODE_SRC : 0; output |= (usage & VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT) != 0 ? GPU_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT) != 0 ? GPU_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER : 0; output |= (usage & VK_BUFFER_USAGE_2_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT) != 0 ? GPU_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER : 0; return output; } wp_intern VkPipelineStageFlags2 vkPipelineStagesFromGpuPipelineStages(GpuPipelineStageFlags stage) { VkPipelineStageFlags2 output = 0; output |= (stage & GPU_PIPELINE_STAGE_TOP_OF_PIPE) != 0 ? VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_DRAW_INDIRECT) != 0 ? VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_VERTEX_INPUT) != 0 ? VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_VERTEX_SHADER) != 0 ? VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER) != 0 ? VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER) != 0 ? VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_GEOMETRY_SHADER) != 0 ? VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_FRAGMENT_SHADER) != 0 ? VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS) != 0 ? VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_LATE_FRAGMENT_TESTS) != 0 ? VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT) != 0 ? VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_COMPUTE_SHADER) != 0 ? VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_ALL_TRANSFER) != 0 ? VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR : 0; output |= (stage & GPU_PIPELINE_STAGE_TRANSFER) != 0 ? VK_PIPELINE_STAGE_2_TRANSFER_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_BOTTOM_OF_PIPE) != 0 ? VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_HOST) != 0 ? VK_PIPELINE_STAGE_2_HOST_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_ALL_GRAPHICS) != 0 ? VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_ALL_COMMANDS) != 0 ? VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_COPY) != 0 ? VK_PIPELINE_STAGE_2_COPY_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_RESOLVE) != 0 ? VK_PIPELINE_STAGE_2_RESOLVE_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_BLIT) != 0 ? VK_PIPELINE_STAGE_2_BLIT_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_CLEAR) != 0 ? VK_PIPELINE_STAGE_2_CLEAR_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_INDEX_INPUT) != 0 ? VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_VERTEX_ATTRIBUTE_INPUT) != 0 ? VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_PRE_RASTERIZATION_SHADERS) != 0 ? VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT : 0; output |= (stage & GPU_PIPELINE_STAGE_VIDEO_DECODE) != 0 ? VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR : 0; output |= (stage & GPU_PIPELINE_STAGE_VIDEO_ENCODE) != 0 ? VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR : 0; output |= (stage & GPU_PIPELINE_STAGE_CONDITIONAL_RENDERING) != 0 ? VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT : 0; output |= (stage & GPU_PIPELINE_STAGE_COMMAND_PREPROCESS) != 0 ? VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT : 0; output |= (stage & GPU_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT) != 0 ? VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR : 0; output |= (stage & GPU_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD) != 0 ? VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR : 0; output |= (stage & GPU_PIPELINE_STAGE_RAY_TRACING_SHADER) != 0 ? VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR : 0; output |= (stage & GPU_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS) != 0 ? VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT : 0; output |= (stage & GPU_PIPELINE_STAGE_TASK_SHADER) != 0 ? VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT : 0; output |= (stage & GPU_PIPELINE_STAGE_MESH_SHADER) != 0 ? VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT : 0; output |= (stage & GPU_PIPELINE_STAGE_ACCELERATION_STRUCTURE_COPY) != 0 ? VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR : 0; output |= (stage & GPU_PIPELINE_STAGE_MICROMAP_BUILD) != 0 ? VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT : 0; output |= (stage & GPU_PIPELINE_STAGE_COPY_INDIRECT) != 0 ? VK_PIPELINE_STAGE_2_COPY_INDIRECT_BIT_KHR : 0; output |= (stage & GPU_PIPELINE_STAGE_MEMORY_DECOMPRESSION) != 0 ? VK_PIPELINE_STAGE_2_MEMORY_DECOMPRESSION_BIT_EXT : 0; return output; } wp_intern GpuPipelineStageFlags gpuPipelineStagesFromVkPipelineStages(VkPipelineStageFlags2 stage) { GpuPipelineStageFlags output = 0; output |= (stage & VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT) != 0 ? GPU_PIPELINE_STAGE_TOP_OF_PIPE : 0; output |= (stage & VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT) != 0 ? GPU_PIPELINE_STAGE_DRAW_INDIRECT : 0; output |= (stage & VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT) != 0 ? GPU_PIPELINE_STAGE_VERTEX_INPUT : 0; output |= (stage & VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT) != 0 ? GPU_PIPELINE_STAGE_VERTEX_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT) != 0 ? GPU_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT) != 0 ? GPU_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT) != 0 ? GPU_PIPELINE_STAGE_GEOMETRY_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT) != 0 ? GPU_PIPELINE_STAGE_FRAGMENT_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT) != 0 ? GPU_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS : 0; output |= (stage & VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT) != 0 ? GPU_PIPELINE_STAGE_LATE_FRAGMENT_TESTS : 0; output |= (stage & VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT) != 0 ? GPU_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT : 0; output |= (stage & VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT) != 0 ? GPU_PIPELINE_STAGE_COMPUTE_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR) != 0 ? GPU_PIPELINE_STAGE_ALL_TRANSFER : 0; output |= (stage & VK_PIPELINE_STAGE_2_TRANSFER_BIT) != 0 ? GPU_PIPELINE_STAGE_TRANSFER : 0; output |= (stage & VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT) != 0 ? GPU_PIPELINE_STAGE_BOTTOM_OF_PIPE : 0; output |= (stage & VK_PIPELINE_STAGE_2_HOST_BIT) != 0 ? GPU_PIPELINE_STAGE_HOST : 0; output |= (stage & VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT) != 0 ? GPU_PIPELINE_STAGE_ALL_GRAPHICS : 0; output |= (stage & VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT) != 0 ? GPU_PIPELINE_STAGE_ALL_COMMANDS : 0; output |= (stage & VK_PIPELINE_STAGE_2_COPY_BIT) != 0 ? GPU_PIPELINE_STAGE_COPY : 0; output |= (stage & VK_PIPELINE_STAGE_2_RESOLVE_BIT) != 0 ? GPU_PIPELINE_STAGE_RESOLVE : 0; output |= (stage & VK_PIPELINE_STAGE_2_BLIT_BIT) != 0 ? GPU_PIPELINE_STAGE_BLIT : 0; output |= (stage & VK_PIPELINE_STAGE_2_CLEAR_BIT) != 0 ? GPU_PIPELINE_STAGE_CLEAR : 0; output |= (stage & VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT) != 0 ? GPU_PIPELINE_STAGE_INDEX_INPUT : 0; output |= (stage & VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT) != 0 ? GPU_PIPELINE_STAGE_VERTEX_ATTRIBUTE_INPUT : 0; output |= (stage & VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT) != 0 ? GPU_PIPELINE_STAGE_PRE_RASTERIZATION_SHADERS : 0; output |= (stage & VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR) != 0 ? GPU_PIPELINE_STAGE_VIDEO_DECODE : 0; output |= (stage & VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR) != 0 ? GPU_PIPELINE_STAGE_VIDEO_ENCODE : 0; output |= (stage & VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT) != 0 ? GPU_PIPELINE_STAGE_CONDITIONAL_RENDERING : 0; output |= (stage & VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT) != 0 ? GPU_PIPELINE_STAGE_COMMAND_PREPROCESS : 0; output |= (stage & VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR) != 0 ? GPU_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT : 0; output |= (stage & VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR) != 0 ? GPU_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD : 0; output |= (stage & VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR) != 0 ? GPU_PIPELINE_STAGE_RAY_TRACING_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT) != 0 ? GPU_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS : 0; output |= (stage & VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT) != 0 ? GPU_PIPELINE_STAGE_TASK_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT) != 0 ? GPU_PIPELINE_STAGE_MESH_SHADER : 0; output |= (stage & VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR) != 0 ? GPU_PIPELINE_STAGE_ACCELERATION_STRUCTURE_COPY : 0; output |= (stage & VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT) != 0 ? GPU_PIPELINE_STAGE_MICROMAP_BUILD : 0; output |= (stage & VK_PIPELINE_STAGE_2_COPY_INDIRECT_BIT_KHR) != 0 ? GPU_PIPELINE_STAGE_COPY_INDIRECT : 0; output |= (stage & VK_PIPELINE_STAGE_2_MEMORY_DECOMPRESSION_BIT_EXT) != 0 ? GPU_PIPELINE_STAGE_MEMORY_DECOMPRESSION : 0; return output; } wp_intern VkAccessFlags2 vkAccessFlagsFromGpuAccessFlags(GpuAccessFlags access) { VkAccessFlags2 output = 0; output |= (access & GPU_ACCESS_NONE) != 0 ? VK_ACCESS_2_NONE : 0; output |= (access & GPU_ACCESS_INDIRECT_COMMAND_READ) != 0 ? VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT : 0; output |= (access & GPU_ACCESS_INDEX_READ) != 0 ? VK_ACCESS_2_INDEX_READ_BIT : 0; output |= (access & GPU_ACCESS_VERTEX_ATTRIBUTE_READ) != 0 ? VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT : 0; output |= (access & GPU_ACCESS_UNIFORM_READ) != 0 ? VK_ACCESS_2_UNIFORM_READ_BIT : 0; output |= (access & GPU_ACCESS_INPUT_ATTACHMENT_READ) != 0 ? VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT : 0; output |= (access & GPU_ACCESS_SHADER_READ) != 0 ? VK_ACCESS_2_SHADER_READ_BIT : 0; output |= (access & GPU_ACCESS_SHADER_WRITE) != 0 ? VK_ACCESS_2_SHADER_WRITE_BIT : 0; output |= (access & GPU_ACCESS_COLOR_ATTACHMENT_READ) != 0 ? VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT : 0; output |= (access & GPU_ACCESS_COLOR_ATTACHMENT_WRITE) != 0 ? VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT : 0; output |= (access & GPU_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ) != 0 ? VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT : 0; output |= (access & GPU_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE) != 0 ? VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0; output |= (access & GPU_ACCESS_TRANSFER_READ) != 0 ? VK_ACCESS_2_TRANSFER_READ_BIT : 0; output |= (access & GPU_ACCESS_TRANSFER_WRITE) != 0 ? VK_ACCESS_2_TRANSFER_WRITE_BIT : 0; output |= (access & GPU_ACCESS_HOST_READ) != 0 ? VK_ACCESS_2_HOST_READ_BIT : 0; output |= (access & GPU_ACCESS_HOST_WRITE) != 0 ? VK_ACCESS_2_HOST_WRITE_BIT : 0; output |= (access & GPU_ACCESS_MEMORY_READ) != 0 ? VK_ACCESS_2_MEMORY_READ_BIT : 0; output |= (access & GPU_ACCESS_MEMORY_WRITE) != 0 ? VK_ACCESS_2_MEMORY_WRITE_BIT : 0; output |= (access & GPU_ACCESS_SHADER_SAMPLED_READ) != 0 ? VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR : 0; output |= (access & GPU_ACCESS_SHADER_STORAGE_READ) != 0 ? VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR : 0; output |= (access & GPU_ACCESS_SHADER_STORAGE_WRITE) != 0 ? VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR : 0; output |= (access & GPU_ACCESS_VIDEO_DECODE_READ) != 0 ? VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR : 0; output |= (access & GPU_ACCESS_VIDEO_DECODE_WRITE) != 0 ? VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR : 0; output |= (access & GPU_ACCESS_SAMPLER_HEAP_READ) != 0 ? VK_ACCESS_2_SAMPLER_HEAP_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_RESOURCE_HEAP_READ) != 0 ? VK_ACCESS_2_RESOURCE_HEAP_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_VIDEO_ENCODE_READ) != 0 ? VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR : 0; output |= (access & GPU_ACCESS_VIDEO_ENCODE_WRITE) != 0 ? VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR : 0; output |= (access & GPU_ACCESS_TRANSFORM_FEEDBACK_WRITE) != 0 ? VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT : 0; output |= (access & GPU_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ) != 0 ? VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE) != 0 ? VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT : 0; output |= (access & GPU_ACCESS_CONDITIONAL_RENDERING_READ) != 0 ? VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_COMMAND_PREPROCESS_READ) != 0 ? VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_COMMAND_PREPROCESS_WRITE) != 0 ? VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_EXT : 0; output |= (access & GPU_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ) != 0 ? VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR : 0; output |= (access & GPU_ACCESS_ACCELERATION_STRUCTURE_READ) != 0 ? VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR : 0; output |= (access & GPU_ACCESS_ACCELERATION_STRUCTURE_WRITE) != 0 ? VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR : 0; output |= (access & GPU_ACCESS_FRAGMENT_DENSITY_MAP_READ) != 0 ? VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT) != 0 ? VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT : 0; output |= (access & GPU_ACCESS_DESCRIPTOR_BUFFER_READ) != 0 ? VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_SHADER_BINDING_TABLE_READ) != 0 ? VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR : 0; output |= (access & GPU_ACCESS_MICROMAP_READ) != 0 ? VK_ACCESS_2_MICROMAP_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_MICROMAP_WRITE) != 0 ? VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT : 0; output |= (access & GPU_ACCESS_MEMORY_DECOMPRESSION_READ) != 0 ? VK_ACCESS_2_MEMORY_DECOMPRESSION_READ_BIT_EXT : 0; output |= (access & GPU_ACCESS_MEMORY_DECOMPRESSION_WRITE) != 0 ? VK_ACCESS_2_MEMORY_DECOMPRESSION_WRITE_BIT_EXT : 0; return output; } wp_intern GpuAccessFlags gpuAccessFlagsFromVkAccessFlags(VkAccessFlags2 access) { GpuAccessFlags output = 0; output |= (access & VK_ACCESS_2_NONE) != 0 ? GPU_ACCESS_NONE : 0; output |= (access & VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT) != 0 ? GPU_ACCESS_INDIRECT_COMMAND_READ : 0; output |= (access & VK_ACCESS_2_INDEX_READ_BIT) != 0 ? GPU_ACCESS_INDEX_READ : 0; output |= (access & VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT) != 0 ? GPU_ACCESS_VERTEX_ATTRIBUTE_READ : 0; output |= (access & VK_ACCESS_2_UNIFORM_READ_BIT) != 0 ? GPU_ACCESS_UNIFORM_READ : 0; output |= (access & VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT) != 0 ? GPU_ACCESS_INPUT_ATTACHMENT_READ : 0; output |= (access & VK_ACCESS_2_SHADER_READ_BIT) != 0 ? GPU_ACCESS_SHADER_READ : 0; output |= (access & VK_ACCESS_2_SHADER_WRITE_BIT) != 0 ? GPU_ACCESS_SHADER_WRITE : 0; output |= (access & VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT) != 0 ? GPU_ACCESS_COLOR_ATTACHMENT_READ : 0; output |= (access & VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT) != 0 ? GPU_ACCESS_COLOR_ATTACHMENT_WRITE : 0; output |= (access & VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT) != 0 ? GPU_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ : 0; output |= (access & VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) != 0 ? GPU_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE : 0; output |= (access & VK_ACCESS_2_TRANSFER_READ_BIT) != 0 ? GPU_ACCESS_TRANSFER_READ : 0; output |= (access & VK_ACCESS_2_TRANSFER_WRITE_BIT) != 0 ? GPU_ACCESS_TRANSFER_WRITE : 0; output |= (access & VK_ACCESS_2_HOST_READ_BIT) != 0 ? GPU_ACCESS_HOST_READ : 0; output |= (access & VK_ACCESS_2_HOST_WRITE_BIT) != 0 ? GPU_ACCESS_HOST_WRITE : 0; output |= (access & VK_ACCESS_2_MEMORY_READ_BIT) != 0 ? GPU_ACCESS_MEMORY_READ : 0; output |= (access & VK_ACCESS_2_MEMORY_WRITE_BIT) != 0 ? GPU_ACCESS_MEMORY_WRITE : 0; output |= (access & VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR) != 0 ? GPU_ACCESS_SHADER_SAMPLED_READ : 0; output |= (access & VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR) != 0 ? GPU_ACCESS_SHADER_STORAGE_READ : 0; output |= (access & VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR) != 0 ? GPU_ACCESS_SHADER_STORAGE_WRITE : 0; output |= (access & VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR) != 0 ? GPU_ACCESS_VIDEO_DECODE_READ : 0; output |= (access & VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR) != 0 ? GPU_ACCESS_VIDEO_DECODE_WRITE : 0; output |= (access & VK_ACCESS_2_SAMPLER_HEAP_READ_BIT_EXT) != 0 ? GPU_ACCESS_SAMPLER_HEAP_READ : 0; output |= (access & VK_ACCESS_2_RESOURCE_HEAP_READ_BIT_EXT) != 0 ? GPU_ACCESS_RESOURCE_HEAP_READ : 0; output |= (access & VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR) != 0 ? GPU_ACCESS_VIDEO_ENCODE_READ : 0; output |= (access & VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR) != 0 ? GPU_ACCESS_VIDEO_ENCODE_WRITE : 0; output |= (access & VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT) != 0 ? GPU_ACCESS_TRANSFORM_FEEDBACK_WRITE : 0; output |= (access & VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT) != 0 ? GPU_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ : 0; output |= (access & VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT) != 0 ? GPU_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE : 0; output |= (access & VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT) != 0 ? GPU_ACCESS_CONDITIONAL_RENDERING_READ : 0; output |= (access & VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_EXT) != 0 ? GPU_ACCESS_COMMAND_PREPROCESS_READ : 0; output |= (access & VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_EXT) != 0 ? GPU_ACCESS_COMMAND_PREPROCESS_WRITE : 0; output |= (access & VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR) != 0 ? GPU_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ : 0; output |= (access & VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR) != 0 ? GPU_ACCESS_ACCELERATION_STRUCTURE_READ : 0; output |= (access & VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) != 0 ? GPU_ACCESS_ACCELERATION_STRUCTURE_WRITE : 0; output |= (access & VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT) != 0 ? GPU_ACCESS_FRAGMENT_DENSITY_MAP_READ : 0; output |= (access & VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT) != 0 ? GPU_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT : 0; output |= (access & VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT) != 0 ? GPU_ACCESS_DESCRIPTOR_BUFFER_READ : 0; output |= (access & VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR) != 0 ? GPU_ACCESS_SHADER_BINDING_TABLE_READ : 0; output |= (access & VK_ACCESS_2_MICROMAP_READ_BIT_EXT) != 0 ? GPU_ACCESS_MICROMAP_READ : 0; output |= (access & VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT) != 0 ? GPU_ACCESS_MICROMAP_WRITE : 0; output |= (access & VK_ACCESS_2_MEMORY_DECOMPRESSION_READ_BIT_EXT) != 0 ? GPU_ACCESS_MEMORY_DECOMPRESSION_READ : 0; output |= (access & VK_ACCESS_2_MEMORY_DECOMPRESSION_WRITE_BIT_EXT) != 0 ? GPU_ACCESS_MEMORY_DECOMPRESSION_WRITE : 0; return output; } wp_intern VkFilter vkFilterFromGpuFilter(GpuFilter filter) { switch (filter) { case GPU_FILTER_NEAREST: return VK_FILTER_NEAREST; case GPU_FILTER_LINEAR: return VK_FILTER_LINEAR; case GPU_FILTER_CUBIC: return VK_FILTER_CUBIC_EXT; } } wp_intern GpuFilter gpuFilterFromVkFilter(VkFilter filter) { switch (filter) { case VK_FILTER_NEAREST: return GPU_FILTER_NEAREST; case VK_FILTER_LINEAR: return GPU_FILTER_LINEAR; case VK_FILTER_CUBIC_EXT: return GPU_FILTER_CUBIC; default: return GPU_FILTER_LINEAR; } } wp_intern VkSamplerMipmapMode vkSamplerMipmapModeFromGpuSamplerMipmapMode(GpuSamplerMipmapMode mode) { switch (mode) { case GPU_SAMPLER_MIPMAP_MODE_NEAREST: return VK_SAMPLER_MIPMAP_MODE_NEAREST; case GPU_SAMPLER_MIPMAP_MODE_LINEAR: return VK_SAMPLER_MIPMAP_MODE_LINEAR; } } wp_intern GpuSamplerMipmapMode gpuSamplerMipmapModeFromVkSamplerMipmapMode(VkSamplerMipmapMode mode) { switch (mode) { case VK_SAMPLER_MIPMAP_MODE_NEAREST: return GPU_SAMPLER_MIPMAP_MODE_NEAREST; case VK_SAMPLER_MIPMAP_MODE_LINEAR: return GPU_SAMPLER_MIPMAP_MODE_LINEAR; default: return GPU_SAMPLER_MIPMAP_MODE_LINEAR; } } wp_intern VkSamplerAddressMode vkSamplerAddressModeFromGpuSamplerAddressMode(GpuSamplerAddressMode mode) { switch (mode) { case GPU_SAMPLER_ADDRESS_MODE_REPEAT: return VK_SAMPLER_ADDRESS_MODE_REPEAT; case GPU_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; case GPU_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; case GPU_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; case GPU_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; } } wp_intern GpuSamplerAddressMode gpuSamplerAddressModeFromVkSamplerAddressMode(VkSamplerAddressMode mode) { switch (mode) { case VK_SAMPLER_ADDRESS_MODE_REPEAT: return GPU_SAMPLER_ADDRESS_MODE_REPEAT; case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return GPU_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return GPU_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return GPU_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return GPU_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; default: return GPU_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; } } wp_intern VkCompareOp vkCompareOpFromGpuCompareOp(GpuCompareOp op) { switch (op) { case GPU_COMPARE_OP_NEVER: return VK_COMPARE_OP_NEVER; case GPU_COMPARE_OP_LESS: return VK_COMPARE_OP_LESS; case GPU_COMPARE_OP_EQUAL: return VK_COMPARE_OP_EQUAL; case GPU_COMPARE_OP_LESS_OR_EQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL; case GPU_COMPARE_OP_GREATER: return VK_COMPARE_OP_GREATER; case GPU_COMPARE_OP_NOT_EQUAL: return VK_COMPARE_OP_NOT_EQUAL; case GPU_COMPARE_OP_GREATER_OR_EQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL; case GPU_COMPARE_OP_ALWAYS: return VK_COMPARE_OP_ALWAYS; } } wp_intern GpuCompareOp gpuCompareOpFromVkCompareOp(VkCompareOp op) { switch (op) { case VK_COMPARE_OP_NEVER: return GPU_COMPARE_OP_NEVER; case VK_COMPARE_OP_LESS: return GPU_COMPARE_OP_LESS; case VK_COMPARE_OP_EQUAL: return GPU_COMPARE_OP_EQUAL; case VK_COMPARE_OP_LESS_OR_EQUAL: return GPU_COMPARE_OP_LESS_OR_EQUAL; case VK_COMPARE_OP_GREATER: return GPU_COMPARE_OP_GREATER; case VK_COMPARE_OP_NOT_EQUAL: return GPU_COMPARE_OP_NOT_EQUAL; case VK_COMPARE_OP_GREATER_OR_EQUAL: return GPU_COMPARE_OP_GREATER_OR_EQUAL; case VK_COMPARE_OP_ALWAYS: return GPU_COMPARE_OP_ALWAYS; default: return GPU_COMPARE_OP_NEVER; } } wp_intern VkDescriptorType vkDescriptorTypeFromGpuDescriptorType(GpuDescriptorType type) { switch (type) { case GPU_DESCRIPTOR_TYPE_SAMPLER: return VK_DESCRIPTOR_TYPE_SAMPLER; case GPU_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; case GPU_DESCRIPTOR_TYPE_SAMPLED_IMAGE: return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; case GPU_DESCRIPTOR_TYPE_STORAGE_IMAGE: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; case GPU_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; case GPU_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; case GPU_DESCRIPTOR_TYPE_UNIFORM_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; case GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; case GPU_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; case GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; case GPU_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; case GPU_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: return VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK; default: break; } assertWithLogger(false, &logger, "Invalid GPU descriptor type"); } wp_intern GpuDescriptorType gpuDescriptorTypeFromVkDescriptorType(VkDescriptorType type) { switch (type) { case VK_DESCRIPTOR_TYPE_SAMPLER: return GPU_DESCRIPTOR_TYPE_SAMPLER; case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return GPU_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: return GPU_DESCRIPTOR_TYPE_SAMPLED_IMAGE; case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: return GPU_DESCRIPTOR_TYPE_STORAGE_IMAGE; case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: return GPU_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: return GPU_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: return GPU_DESCRIPTOR_TYPE_UNIFORM_BUFFER; case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: return GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER; case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: return GPU_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: return GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: return GPU_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: return GPU_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK; default: break; } assertWithLogger(false, &logger, "Invalid Vulkan descriptor type"); } wp_intern VkShaderStageFlags vkShaderStageFromGpuShaderStage(GpuShaderStage stages) { VkShaderStageFlags output = 0; output |= (stages & GPU_SHADER_STAGE_VERTEX) != 0 ? VK_SHADER_STAGE_VERTEX_BIT : 0; output |= (stages & GPU_SHADER_STAGE_TESSELLATION_CONTROL) != 0 ? VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT : 0; output |= (stages & GPU_SHADER_STAGE_TESSELLATION_EVALUATION) != 0 ? VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT : 0; output |= (stages & GPU_SHADER_STAGE_GEOMETRY) != 0 ? VK_SHADER_STAGE_GEOMETRY_BIT : 0; output |= (stages & GPU_SHADER_STAGE_FRAGMENT) != 0 ? VK_SHADER_STAGE_FRAGMENT_BIT : 0; output |= (stages & GPU_SHADER_STAGE_COMPUTE) != 0 ? VK_SHADER_STAGE_COMPUTE_BIT : 0; output |= (stages & GPU_SHADER_STAGE_ALL_GRAPHICS) != 0 ? VK_SHADER_STAGE_ALL_GRAPHICS : 0; output |= (stages & GPU_SHADER_STAGE_ALL) != 0 ? VK_SHADER_STAGE_ALL : 0; output |= (stages & GPU_SHADER_STAGE_RAYGEN) != 0 ? VK_SHADER_STAGE_RAYGEN_BIT_KHR : 0; output |= (stages & GPU_SHADER_STAGE_ANY_HIT) != 0 ? VK_SHADER_STAGE_ANY_HIT_BIT_KHR : 0; output |= (stages & GPU_SHADER_STAGE_CLOSEST_HIT) != 0 ? VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR : 0; output |= (stages & GPU_SHADER_STAGE_MISS) != 0 ? VK_SHADER_STAGE_MISS_BIT_KHR : 0; output |= (stages & GPU_SHADER_STAGE_INTERSECTION) != 0 ? VK_SHADER_STAGE_INTERSECTION_BIT_KHR : 0; output |= (stages & GPU_SHADER_STAGE_CALLABLE) != 0 ? VK_SHADER_STAGE_CALLABLE_BIT_KHR : 0; output |= (stages & GPU_SHADER_STAGE_TASK) != 0 ? VK_SHADER_STAGE_TASK_BIT_EXT : 0; output |= (stages & GPU_SHADER_STAGE_MESH) != 0 ? VK_SHADER_STAGE_MESH_BIT_EXT : 0; return output; } wp_intern GpuShaderStage gpuShaderStageFromVkShaderStage(VkShaderStageFlags stages) { GpuShaderStage output = 0; output |= (stages & VK_SHADER_STAGE_VERTEX_BIT) != 0 ? GPU_SHADER_STAGE_VERTEX : 0; output |= (stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0 ? GPU_SHADER_STAGE_TESSELLATION_CONTROL : 0; output |= (stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0 ? GPU_SHADER_STAGE_TESSELLATION_EVALUATION : 0; output |= (stages & VK_SHADER_STAGE_GEOMETRY_BIT) != 0 ? GPU_SHADER_STAGE_GEOMETRY : 0; output |= (stages & VK_SHADER_STAGE_FRAGMENT_BIT) != 0 ? GPU_SHADER_STAGE_FRAGMENT : 0; output |= (stages & VK_SHADER_STAGE_COMPUTE_BIT) != 0 ? GPU_SHADER_STAGE_COMPUTE : 0; output |= (stages & VK_SHADER_STAGE_ALL_GRAPHICS) != 0 ? GPU_SHADER_STAGE_ALL_GRAPHICS : 0; output |= (stages & VK_SHADER_STAGE_ALL) != 0 ? GPU_SHADER_STAGE_ALL : 0; output |= (stages & VK_SHADER_STAGE_RAYGEN_BIT_KHR) != 0 ? GPU_SHADER_STAGE_RAYGEN : 0; output |= (stages & VK_SHADER_STAGE_ANY_HIT_BIT_KHR) != 0 ? GPU_SHADER_STAGE_ANY_HIT : 0; output |= (stages & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) != 0 ? GPU_SHADER_STAGE_CLOSEST_HIT : 0; output |= (stages & VK_SHADER_STAGE_MISS_BIT_KHR) != 0 ? GPU_SHADER_STAGE_MISS : 0; output |= (stages & VK_SHADER_STAGE_INTERSECTION_BIT_KHR) != 0 ? GPU_SHADER_STAGE_INTERSECTION : 0; output |= (stages & VK_SHADER_STAGE_CALLABLE_BIT_KHR) != 0 ? GPU_SHADER_STAGE_CALLABLE : 0; output |= (stages & VK_SHADER_STAGE_TASK_BIT_EXT) != 0 ? GPU_SHADER_STAGE_TASK : 0; output |= (stages & VK_SHADER_STAGE_MESH_BIT_EXT) != 0 ? GPU_SHADER_STAGE_MESH : 0; return output; } wp_intern GpuDescriptorCategory descriptorCategoryFromDescriptorType(GpuDescriptorType type) { switch (type) { case GPU_DESCRIPTOR_TYPE_SAMPLER: case GPU_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case GPU_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case GPU_DESCRIPTOR_TYPE_STORAGE_IMAGE: case GPU_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: return GPU_DESCRIPTOR_CATEGORY_IMAGE; case GPU_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER: case GPU_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: case GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: return GPU_DESCRIPTOR_CATEGORY_BUFFER; case GPU_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case GPU_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: return GPU_DESCRIPTOR_CATEGORY_TEXEL_BUFFER; case GPU_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: return GPU_DESCRIPTOR_CATEGORY_UNIFORM_BLOCK; default: break; } assertWithLogger(0, &logger, "Unrecognised descriptor type"); } wp_intern u64 retrieveDescriptorImageInfos(const GpuDescriptorSetWriteInfo *src_write_info, VkWriteDescriptorSet *dst_write_info, VkDescriptorImageInfoArray dst_img_infos, u64 dst_img_infos_offset) { u64 img_desc_count = wpArrayCount(src_write_info->image_infos); for (u64 j = 0; j < img_desc_count; ++j) { GpuDescriptorImageInfo *img_info = &(src_write_info->image_infos[j]); VkDescriptorImageInfo vk_img_info = { .sampler = img_info->sampler != NULL ? img_info->sampler->vk_sampler : NULL, .imageView = img_info->image != NULL ? img_info->image->vk_view : NULL, .imageLayout = vkImageLayoutFromGpuImageLayout(img_info->image_layout), }; wpArrayAppendCapped(VkDescriptorImageInfo, dst_img_infos, &vk_img_info); } dst_write_info->descriptorCount = img_desc_count; dst_write_info->pImageInfo = &dst_img_infos[dst_img_infos_offset]; return img_desc_count; } wp_intern u64 retrieveDescriptorBufferInfos(const GpuDescriptorSetWriteInfo *src_write_info, VkWriteDescriptorSet *dst_write_info, VkDescriptorBufferInfoArray dst_buf_infos, u64 dst_buf_infos_offset) { u64 buf_desc_count = wpArrayCount(src_write_info->buffer_infos); for (u64 j = 0; j < buf_desc_count; ++j) { GpuDescriptorBufferInfo *buf_info = &(src_write_info->buffer_infos[j]); VkDescriptorBufferInfo vk_buf_info = { .buffer = buf_info->buffer->internal->vk_buffer, .offset = buf_info->offset, .range = buf_info->range > 0 ? buf_info->range : VK_WHOLE_SIZE, }; wpArrayAppendCapped(VkDescriptorBufferInfo, dst_buf_infos, &vk_buf_info); } dst_write_info->descriptorCount = buf_desc_count; dst_write_info->pBufferInfo = &dst_buf_infos[dst_buf_infos_offset]; return buf_desc_count; } wp_intern GraphicsPipelinesTotalCounts queryGraphicsPipelinesRequestTotalCounts(GpuGraphicsPipelinesCreateRequest request) { GraphicsPipelinesTotalCounts output = {0}; for (u64 i = 0; i < wpArrayCount(request.infos); ++i) { GpuGraphicsPipelineCreateInfo *info = &request.infos[i]; output.total_vertex_input_bindings_count += wpArrayCount(info->vertex_input_state.bindings); output.total_vertex_input_attributes_count += wpArrayCount(info->vertex_input_state.attributes); output.total_color_blend_attachments_count += wpArrayCount(info->color_blend_state.attachments); output.total_shader_stages_count += wpArrayCount(info->shader_stages); } return output; } wp_intern GraphicsPipelinesTempArrays allocateGraphicsPipelinesTempArrays(const WpAllocator *allocator, GpuGraphicsPipelinesCreateRequest request) { u64 pipeline_count = wpArrayCount(request.infos); GraphicsPipelinesTotalCounts counts = queryGraphicsPipelinesRequestTotalCounts(request); GraphicsPipelinesTempArrays output = { .vertex_input_states = wpArrayAllocCapacity(VkPipelineVertexInputStateCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .input_assembly_states = wpArrayAllocCapacity(VkPipelineInputAssemblyStateCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .tesselation_states = wpArrayAllocCapacity(VkPipelineTessellationStateCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .viewport_states = wpArrayAllocCapacity(VkPipelineViewportStateCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .rasterization_states = wpArrayAllocCapacity(VkPipelineRasterizationStateCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .multisample_states = wpArrayAllocCapacity(VkPipelineMultisampleStateCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .depth_stencil_states = wpArrayAllocCapacity(VkPipelineDepthStencilStateCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .color_blend_states = wpArrayAllocCapacity(VkPipelineColorBlendStateCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .dynamic_rendering_infos = wpArrayAllocCapacity(VkPipelineRenderingCreateInfo, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .color_attachment_formats = wpArrayAllocCapacity(VkFormat, allocator, pipeline_count, WP_ARRAY_INIT_FILLED), .vertex_bindings = wpArrayAllocCapacity(VkVertexInputBindingDescription, allocator, counts.total_vertex_input_bindings_count, WP_ARRAY_INIT_FILLED), .vertex_attributes = wpArrayAllocCapacity(VkVertexInputAttributeDescription, allocator, counts.total_vertex_input_attributes_count, WP_ARRAY_INIT_FILLED), .color_blend_attachments = wpArrayAllocCapacity(VkPipelineColorBlendAttachmentState, allocator, counts.total_color_blend_attachments_count, WP_ARRAY_INIT_FILLED), .shader_stages = wpArrayAllocCapacity(VkPipelineShaderStageCreateInfo, allocator, counts.total_shader_stages_count, WP_ARRAY_INIT_FILLED), }; b8 allocations_successful = output.vertex_input_states != NULL && output.input_assembly_states != NULL && output.tesselation_states != NULL && output.viewport_states != NULL && output.rasterization_states != NULL && output.multisample_states != NULL && output.depth_stencil_states != NULL && output.color_blend_states != NULL && output.dynamic_rendering_infos && output.color_attachment_formats != NULL && output.vertex_bindings != NULL && output.vertex_attributes != NULL && output.color_blend_attachments != NULL && output.shader_stages != NULL; assertWithLogger(allocations_successful, &logger, "Failed to allocate graphics pipelines temporary arrays"); return output; } wp_intern VkVertexInputRate vkVertexInputRateFromGpuVertexInputRate(GpuVertexInputRate rate) { switch (rate) { case GPU_VERTEX_INPUT_RATE_VERTEX: return VK_VERTEX_INPUT_RATE_VERTEX; case GPU_VERTEX_INPUT_RATE_INSTANCE: return VK_VERTEX_INPUT_RATE_INSTANCE; } } wp_intern GpuVertexInputRate gpuVertexInputRateFromVkVertexInputRate(VkVertexInputRate rate) { switch (rate) { case VK_VERTEX_INPUT_RATE_VERTEX: return GPU_VERTEX_INPUT_RATE_VERTEX; case VK_VERTEX_INPUT_RATE_INSTANCE: return GPU_VERTEX_INPUT_RATE_INSTANCE; default: return GPU_VERTEX_INPUT_RATE_VERTEX; } } wp_intern VkPrimitiveTopology vkPrimitiveTopologyFromGpuPrimitiveTopology(GpuPrimitiveTopology topology) { switch (topology) { case GPU_PRIMITIVE_TOPOLOGY_POINT_LIST: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; case GPU_PRIMITIVE_TOPOLOGY_LINE_LIST: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; case GPU_PRIMITIVE_TOPOLOGY_LINE_STRIP: return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; case GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; case GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; case GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; case GPU_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; case GPU_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY; case GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY; case GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; case GPU_PRIMITIVE_TOPOLOGY_PATCH_LIST: return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; } } wp_intern GpuPrimitiveTopology gpuPrimitiveTopologyFromVkPrimitiveTopology(VkPrimitiveTopology topology) { switch (topology) { case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: return GPU_PRIMITIVE_TOPOLOGY_POINT_LIST; case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: return GPU_PRIMITIVE_TOPOLOGY_LINE_LIST; case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: return GPU_PRIMITIVE_TOPOLOGY_LINE_STRIP; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: return GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: return GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: return GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: return GPU_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY; case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: return GPU_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: return GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY; case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: return GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: return GPU_PRIMITIVE_TOPOLOGY_PATCH_LIST; default: return GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; } } wp_intern VkPolygonMode vkPolygonModeFromGpuPolygonMode(GpuPolygonMode mode) { switch (mode) { case GPU_POLYGON_MODE_FILL: return VK_POLYGON_MODE_FILL; case GPU_POLYGON_MODE_LINE: return VK_POLYGON_MODE_LINE; case GPU_POLYGON_MODE_POINT: return VK_POLYGON_MODE_POINT; } } wp_intern GpuPolygonMode gpuPolygonModeFromVkPolygonMode(VkPolygonMode mode) { switch (mode) { case VK_POLYGON_MODE_FILL: return GPU_POLYGON_MODE_FILL; case VK_POLYGON_MODE_LINE: return GPU_POLYGON_MODE_LINE; case VK_POLYGON_MODE_POINT: return GPU_POLYGON_MODE_POINT; default: return GPU_POLYGON_MODE_FILL; } } wp_intern VkCullModeFlags vkCullModeFromGpuCullMode(GpuCullMode mode) { switch (mode) { case GPU_CULL_MODE_NONE: return VK_CULL_MODE_NONE; case GPU_CULL_MODE_FRONT: return VK_CULL_MODE_FRONT_BIT; case GPU_CULL_MODE_BACK: return VK_CULL_MODE_BACK_BIT; case GPU_CULL_MODE_FRONT_AND_BACK: return VK_CULL_MODE_FRONT_AND_BACK; } } wp_intern GpuCullMode gpuCullModeFromVkCullMode(VkCullModeFlags mode) { switch (mode) { case VK_CULL_MODE_NONE: return GPU_CULL_MODE_NONE; case VK_CULL_MODE_FRONT_BIT: return GPU_CULL_MODE_FRONT; case VK_CULL_MODE_BACK_BIT: return GPU_CULL_MODE_BACK; case VK_CULL_MODE_FRONT_AND_BACK: return GPU_CULL_MODE_FRONT_AND_BACK; default: return GPU_CULL_MODE_NONE; } } wp_intern VkFrontFace vkFrontFaceFromGpuFrontFace(GpuFrontFace front_face) { switch (front_face) { case GPU_FRONT_FACE_COUNTER_CLOCKWISE: return VK_FRONT_FACE_COUNTER_CLOCKWISE; case GPU_FRONT_FACE_CLOCKWISE: return VK_FRONT_FACE_CLOCKWISE; } } wp_intern GpuFrontFace gpuFrontFaceFromVkFrontFace(VkFrontFace front_face) { switch (front_face) { case VK_FRONT_FACE_COUNTER_CLOCKWISE: return GPU_FRONT_FACE_COUNTER_CLOCKWISE; case VK_FRONT_FACE_CLOCKWISE: return GPU_FRONT_FACE_CLOCKWISE; default: return GPU_FRONT_FACE_COUNTER_CLOCKWISE; } } wp_intern VkStencilOp vkStencilOpFromGpuStencil(GpuStencilOp op) { switch (op) { case GPU_STENCIL_OP_KEEP: return VK_STENCIL_OP_KEEP; case GPU_STENCIL_OP_ZERO: return VK_STENCIL_OP_ZERO; case GPU_STENCIL_OP_REPLACE: return VK_STENCIL_OP_REPLACE; case GPU_STENCIL_OP_INCREMENT_AND_CLAMP: return VK_STENCIL_OP_INCREMENT_AND_CLAMP; case GPU_STENCIL_OP_DECREMENT_AND_CLAMP: return VK_STENCIL_OP_DECREMENT_AND_CLAMP; case GPU_STENCIL_OP_INVERT: return VK_STENCIL_OP_INVERT; case GPU_STENCIL_OP_INCREMENT_AND_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP; case GPU_STENCIL_OP_DECREMENT_AND_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP; } } wp_intern GpuStencilOp gpuStencilOpFromVkStencil(VkStencilOp op) { switch (op) { case VK_STENCIL_OP_KEEP: return GPU_STENCIL_OP_KEEP; case VK_STENCIL_OP_ZERO: return GPU_STENCIL_OP_ZERO; case VK_STENCIL_OP_REPLACE: return GPU_STENCIL_OP_REPLACE; case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return GPU_STENCIL_OP_INCREMENT_AND_CLAMP; case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return GPU_STENCIL_OP_DECREMENT_AND_CLAMP; case VK_STENCIL_OP_INVERT: return GPU_STENCIL_OP_INVERT; case VK_STENCIL_OP_INCREMENT_AND_WRAP: return GPU_STENCIL_OP_INCREMENT_AND_WRAP; case VK_STENCIL_OP_DECREMENT_AND_WRAP: return GPU_STENCIL_OP_DECREMENT_AND_WRAP; default: return GPU_STENCIL_OP_KEEP; } } wp_intern VkBlendFactor vkBlendFactorFromGpuBlendFactor(GpuBlendFactor factor) { switch (factor) { case GPU_BLEND_FACTOR_ZERO: return VK_BLEND_FACTOR_ZERO; case GPU_BLEND_FACTOR_ONE: return VK_BLEND_FACTOR_ONE; case GPU_BLEND_FACTOR_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR; case GPU_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; case GPU_BLEND_FACTOR_DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR; case GPU_BLEND_FACTOR_ONE_MINUS_DST_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; case GPU_BLEND_FACTOR_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA; case GPU_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; case GPU_BLEND_FACTOR_DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA; case GPU_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; case GPU_BLEND_FACTOR_CONSTANT_COLOR: return VK_BLEND_FACTOR_CONSTANT_COLOR; case GPU_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR; case GPU_BLEND_FACTOR_CONSTANT_ALPHA: return VK_BLEND_FACTOR_CONSTANT_ALPHA; case GPU_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; case GPU_BLEND_FACTOR_SRC_ALPHA_SATURATE: return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; case GPU_BLEND_FACTOR_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR; case GPU_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; case GPU_BLEND_FACTOR_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA; case GPU_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; } } wp_intern GpuBlendFactor gpuBlendFactorFromVkBlendFactor(VkBlendFactor factor) { switch (factor) { case VK_BLEND_FACTOR_ZERO: return GPU_BLEND_FACTOR_ZERO; case VK_BLEND_FACTOR_ONE: return GPU_BLEND_FACTOR_ONE; case VK_BLEND_FACTOR_SRC_COLOR: return GPU_BLEND_FACTOR_SRC_COLOR; case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: return GPU_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; case VK_BLEND_FACTOR_DST_COLOR: return GPU_BLEND_FACTOR_DST_COLOR; case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: return GPU_BLEND_FACTOR_ONE_MINUS_DST_COLOR; case VK_BLEND_FACTOR_SRC_ALPHA: return GPU_BLEND_FACTOR_SRC_ALPHA; case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: return GPU_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; case VK_BLEND_FACTOR_DST_ALPHA: return GPU_BLEND_FACTOR_DST_ALPHA; case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: return GPU_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; case VK_BLEND_FACTOR_CONSTANT_COLOR: return GPU_BLEND_FACTOR_CONSTANT_COLOR; case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: return GPU_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR; case VK_BLEND_FACTOR_CONSTANT_ALPHA: return GPU_BLEND_FACTOR_CONSTANT_ALPHA; case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: return GPU_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: return GPU_BLEND_FACTOR_SRC_ALPHA_SATURATE; case VK_BLEND_FACTOR_SRC1_COLOR: return GPU_BLEND_FACTOR_SRC1_COLOR; case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: return GPU_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; case VK_BLEND_FACTOR_SRC1_ALPHA: return GPU_BLEND_FACTOR_SRC1_ALPHA; case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: return GPU_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; default: return GPU_BLEND_FACTOR_ZERO; } } wp_intern VkBlendOp vkBlendOpFromGpuBlendOp(GpuBlendOp op) { switch (op) { case GPU_BLEND_OP_ADD: return VK_BLEND_OP_ADD; case GPU_BLEND_OP_SUBTRACT: return VK_BLEND_OP_SUBTRACT; case GPU_BLEND_OP_REVERSE_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT; case GPU_BLEND_OP_MIN: return VK_BLEND_OP_MIN; case GPU_BLEND_OP_MAX: return VK_BLEND_OP_MAX; } } wp_intern GpuBlendOp gpuBlendOpFromVkBlendOp(VkBlendOp op) { switch (op) { case VK_BLEND_OP_ADD: return GPU_BLEND_OP_ADD; case VK_BLEND_OP_SUBTRACT: return GPU_BLEND_OP_SUBTRACT; case VK_BLEND_OP_REVERSE_SUBTRACT: return GPU_BLEND_OP_REVERSE_SUBTRACT; case VK_BLEND_OP_MIN: return GPU_BLEND_OP_MIN; case VK_BLEND_OP_MAX: return GPU_BLEND_OP_MAX; default: return GPU_BLEND_OP_ADD; } } wp_intern VkColorComponentFlags vkColorComponentFlagsFromGpuColorComponentFlags(GpuColorComponentFlags flags) { VkColorComponentFlags output = 0; output |= (flags & GPU_COLOR_COMPONENT_R) != 0 ? VK_COLOR_COMPONENT_R_BIT : 0; output |= (flags & GPU_COLOR_COMPONENT_G) != 0 ? VK_COLOR_COMPONENT_G_BIT : 0; output |= (flags & GPU_COLOR_COMPONENT_B) != 0 ? VK_COLOR_COMPONENT_B_BIT : 0; output |= (flags & GPU_COLOR_COMPONENT_A) != 0 ? VK_COLOR_COMPONENT_A_BIT : 0; return output; } wp_intern GpuColorComponentFlags gpuColorComponentFlagsFromVkColorComponentFlags(VkColorComponentFlags flags) { GpuColorComponentFlags output = 0; output |= (flags & VK_COLOR_COMPONENT_R_BIT) != 0 ? GPU_COLOR_COMPONENT_R : 0; output |= (flags & VK_COLOR_COMPONENT_G_BIT) != 0 ? GPU_COLOR_COMPONENT_G : 0; output |= (flags & VK_COLOR_COMPONENT_B_BIT) != 0 ? GPU_COLOR_COMPONENT_B : 0; output |= (flags & VK_COLOR_COMPONENT_A_BIT) != 0 ? GPU_COLOR_COMPONENT_A : 0; return output; } wp_intern VkLogicOp vkLogicOpFromGpuLogicOp(GpuLogicOp op) { switch (op) { case GPU_LOGIC_OP_CLEAR: return VK_LOGIC_OP_CLEAR; case GPU_LOGIC_OP_AND: return VK_LOGIC_OP_AND; case GPU_LOGIC_OP_AND_REVERSE: return VK_LOGIC_OP_AND_REVERSE; case GPU_LOGIC_OP_COPY: return VK_LOGIC_OP_COPY; case GPU_LOGIC_OP_AND_INVERTED: return VK_LOGIC_OP_AND_INVERTED; case GPU_LOGIC_OP_NO_OP: return VK_LOGIC_OP_NO_OP; case GPU_LOGIC_OP_XOR: return VK_LOGIC_OP_XOR; case GPU_LOGIC_OP_OR: return VK_LOGIC_OP_OR; case GPU_LOGIC_OP_NOR: return VK_LOGIC_OP_NOR; case GPU_LOGIC_OP_EQUIVALENT: return VK_LOGIC_OP_EQUIVALENT; case GPU_LOGIC_OP_INVERT: return VK_LOGIC_OP_INVERT; case GPU_LOGIC_OP_OR_REVERSE: return VK_LOGIC_OP_OR_REVERSE; case GPU_LOGIC_OP_COPY_INVERTED: return VK_LOGIC_OP_COPY_INVERTED; case GPU_LOGIC_OP_OR_INVERTED: return VK_LOGIC_OP_OR_INVERTED; case GPU_LOGIC_OP_NAND: return VK_LOGIC_OP_NAND; case GPU_LOGIC_OP_SET: return VK_LOGIC_OP_SET; } } wp_intern GpuLogicOp gpuLogicOpFromVkLogicOp(VkLogicOp op) { switch (op) { case VK_LOGIC_OP_CLEAR: return GPU_LOGIC_OP_CLEAR; case VK_LOGIC_OP_AND: return GPU_LOGIC_OP_AND; case VK_LOGIC_OP_AND_REVERSE: return GPU_LOGIC_OP_AND_REVERSE; case VK_LOGIC_OP_COPY: return GPU_LOGIC_OP_COPY; case VK_LOGIC_OP_AND_INVERTED: return GPU_LOGIC_OP_AND_INVERTED; case VK_LOGIC_OP_NO_OP: return GPU_LOGIC_OP_NO_OP; case VK_LOGIC_OP_XOR: return GPU_LOGIC_OP_XOR; case VK_LOGIC_OP_OR: return GPU_LOGIC_OP_OR; case VK_LOGIC_OP_NOR: return GPU_LOGIC_OP_NOR; case VK_LOGIC_OP_EQUIVALENT: return GPU_LOGIC_OP_EQUIVALENT; case VK_LOGIC_OP_INVERT: return GPU_LOGIC_OP_INVERT; case VK_LOGIC_OP_OR_REVERSE: return GPU_LOGIC_OP_OR_REVERSE; case VK_LOGIC_OP_COPY_INVERTED: return GPU_LOGIC_OP_COPY_INVERTED; case VK_LOGIC_OP_OR_INVERTED: return GPU_LOGIC_OP_OR_INVERTED; case VK_LOGIC_OP_NAND: return GPU_LOGIC_OP_NAND; case VK_LOGIC_OP_SET: return GPU_LOGIC_OP_SET; default: return GPU_LOGIC_OP_CLEAR; } }