From 5e8175b224484fb84e7ee6083548ebd1c6eefd90 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Wed, 21 Oct 2026 01:15:28 +0100 Subject: [PATCH] Finalise implementation for graphic pipelines creation --- src/gpu/gpu.h | 65 +--- src/gpu/vulkan/vk_gpu.c | 724 ++++++++++++++++++++++++++++++++++++--- src/main.c | 83 ++++- src/shaders/shader.slang | 14 +- 4 files changed, 772 insertions(+), 114 deletions(-) diff --git a/src/gpu/gpu.h b/src/gpu/gpu.h index dbc5c65..d98213d 100644 --- a/src/gpu/gpu.h +++ b/src/gpu/gpu.h @@ -706,8 +706,8 @@ typedef struct GpuRect2d { typedef GpuRect2d *GpuRect2dArray; typedef struct GpuPipelineViewportStateInfo { - GpuViewportArray viewports; - GpuRect2dArray scissors; + u64 viewport_count; + u64 scissor_count; } GpuPipelineViewportStateInfo; typedef enum GpuPolygonMode { @@ -808,60 +808,13 @@ typedef enum GpuBlendOp { GPU_BLEND_OP_REVERSE_SUBTRACT, GPU_BLEND_OP_MIN, GPU_BLEND_OP_MAX, - GPU_BLEND_OP_ZERO_EXT, - GPU_BLEND_OP_SRC_EXT, - GPU_BLEND_OP_DST_EXT, - GPU_BLEND_OP_SRC_OVER_EXT, - GPU_BLEND_OP_DST_OVER_EXT, - GPU_BLEND_OP_SRC_IN_EXT, - GPU_BLEND_OP_DST_IN_EXT, - GPU_BLEND_OP_SRC_OUT_EXT, - GPU_BLEND_OP_DST_OUT_EXT, - GPU_BLEND_OP_SRC_ATOP_EXT, - GPU_BLEND_OP_DST_ATOP_EXT, - GPU_BLEND_OP_XOR_EXT, - GPU_BLEND_OP_MULTIPLY_EXT, - GPU_BLEND_OP_SCREEN_EXT, - GPU_BLEND_OP_OVERLAY_EXT, - GPU_BLEND_OP_DARKEN_EXT, - GPU_BLEND_OP_LIGHTEN_EXT, - GPU_BLEND_OP_COLORDODGE_EXT, - GPU_BLEND_OP_COLORBURN_EXT, - GPU_BLEND_OP_HARDLIGHT_EXT, - GPU_BLEND_OP_SOFTLIGHT_EXT, - GPU_BLEND_OP_DIFFERENCE_EXT, - GPU_BLEND_OP_EXCLUSION_EXT, - GPU_BLEND_OP_INVERT_EXT, - GPU_BLEND_OP_INVERT_RGB_EXT, - GPU_BLEND_OP_LINEARDODGE_EXT, - GPU_BLEND_OP_LINEARBURN_EXT, - GPU_BLEND_OP_VIVIDLIGHT_EXT, - GPU_BLEND_OP_LINEARLIGHT_EXT, - GPU_BLEND_OP_PINLIGHT_EXT, - GPU_BLEND_OP_HARDMIX_EXT, - GPU_BLEND_OP_HSL_HUE_EXT, - GPU_BLEND_OP_HSL_SATURATION_EXT, - GPU_BLEND_OP_HSL_COLOR_EXT, - GPU_BLEND_OP_HSL_LUMINOSITY_EXT, - GPU_BLEND_OP_PLUS_EXT, - GPU_BLEND_OP_PLUS_CLAMPED_EXT, - GPU_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT, - GPU_BLEND_OP_PLUS_DARKER_EXT, - GPU_BLEND_OP_MINUS_EXT, - GPU_BLEND_OP_MINUS_CLAMPED_EXT, - GPU_BLEND_OP_CONTRAST_EXT, - GPU_BLEND_OP_INVERT_OVG_EXT, - GPU_BLEND_OP_RED_EXT, - GPU_BLEND_OP_GREEN_EXT, - GPU_BLEND_OP_BLUE_EXT, - GPU_BLEND_OP_MAX_ENUM, } GpuBlendOp; typedef enum GpuColorComponentFlags { - GPU_COLOR_COMPONENT_R_BIT = wpU64Const(1) << 0, - GPU_COLOR_COMPONENT_G_BIT = wpU64Const(1) << 1, - GPU_COLOR_COMPONENT_B_BIT = wpU64Const(1) << 2, - GPU_COLOR_COMPONENT_A_BIT = wpU64Const(1) << 3, + GPU_COLOR_COMPONENT_R = wpU64Const(1) << 0, + GPU_COLOR_COMPONENT_G = wpU64Const(1) << 1, + GPU_COLOR_COMPONENT_B = wpU64Const(1) << 2, + GPU_COLOR_COMPONENT_A = wpU64Const(1) << 3, } GpuColorComponentFlags; typedef enum GpuLogicOp { @@ -916,6 +869,8 @@ typedef struct GpuGraphicsPipelineCreateInfo { GpuPipelineColorBlendStateInfo color_blend_state; GpuPipelineShaderStageInfoArray shader_stages; GpuPipelineLayout *layout; + GpuFormat color_attachment_format; + GpuFormat depth_attachment_format; } GpuGraphicsPipelineCreateInfo; typedef GpuGraphicsPipelineCreateInfo *GpuGraphicsPipelineCreateInfoArray; @@ -946,6 +901,8 @@ GpuSwapchain *gpuCreateSwapchain(const WpAllocator *allocator, const GpuSwapchainCreateRequest request); void gpuDestroySwapchain(GpuSwapchain *swapchain); u64 gpuGetSwapchainImageCount(GpuSwapchain *swapchain); +GpuFormat gpuGetSwapchainImageFormat(GpuSwapchain *swapchain); +GpuFormat gpuGetSwapchainDepthFormat(GpuSwapchain *swapchain); GpuSampler *gpuCreateSampler(const WpAllocator *allocator, GpuSamplerCreateRequest request); void gpuDestroySampler(GpuSampler *sampler); GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest request); @@ -956,7 +913,7 @@ void gpuDestroyBuffer(GpuBuffer *buffer); GpuFence *gpuCreateFence(const WpAllocator *allocator, GpuDevice *device); void gpuDestroyFence(GpuFence *fence); void gpuResetFence(GpuFence *fence); -GpuSemaphore *gpuCreateSemaphore(const WpAllocator *allocator, GpuDevice *device); +GpuSemaphore *gpuCreateSemaphore(const WpAllocator *allocator, GpuDevice *device); void gpuDestroySemaphore(GpuSemaphore *semaphore); GpuCommandPool *gpuCreateCommandPool(const WpAllocator *allocator, GpuDevice *device); void gpuDestroyCommandPool(GpuCommandPool *pool); diff --git a/src/gpu/vulkan/vk_gpu.c b/src/gpu/vulkan/vk_gpu.c index 3b04ebb..93cb5ad 100644 --- a/src/gpu/vulkan/vk_gpu.c +++ b/src/gpu/vulkan/vk_gpu.c @@ -43,8 +43,25 @@ typedef VkWriteDescriptorSet *VkWriteDescriptorSet 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; @@ -155,6 +172,37 @@ typedef struct VkExtensions { 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, @@ -162,63 +210,86 @@ typedef enum GpuDescriptorCategory { 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 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"); @@ -618,6 +689,14 @@ 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"); @@ -1235,6 +1314,210 @@ GpuPipelinePtrArray gpuCreateGraphicsPipelines(const WpAllocator *allocator, con 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; } @@ -2262,3 +2545,330 @@ wp_intern u64 retrieveDescriptorBufferInfos(const GpuDescriptorSetWriteInfo *src 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; + } +} diff --git a/src/main.c b/src/main.c index b45ac65..c45e292 100644 --- a/src/main.c +++ b/src/main.c @@ -1,12 +1,12 @@ // vim:fileencoding=utf-8:foldmethod=marker -#include "gpu/gpu.h" #include "utils/utils_inc.h" #include "config/config_inc.h" #include "window/window_inc.h" #include "gpu/gpu_inc.h" #include "wapp/wapp.h" #include "cglm/struct.h" +#include wp_intern WpLogger logger = wpLogMakeLogger(wpStr8LitRo("main")); @@ -139,6 +139,7 @@ i32 main(void) { .usage = GPU_BUFFER_USAGE_STORAGE_BUFFER, }; GpuBuffer storage = gpuCreateBuffer(&arena, storage_request); + memcpy(storage.cpu_mapping, (void *)floats, sizeof(f32) * wpArrayCount(floats)); GpuDescriptorPoolSizeArray pool_sizes = wpArray( GpuDescriptorPoolSize, @@ -224,6 +225,83 @@ i32 main(void) { }; GpuPipelineLayout *graphics_pipeline_layout = gpuCreatePipelineLayout(&arena, &temp_arena, graphics_pl_request); + GpuGraphicsPipelinesCreateRequest graphics_pipelines_request = { + .device = device, + .infos = wpArray( + GpuGraphicsPipelineCreateInfo, + (GpuGraphicsPipelineCreateInfo){ + .vertex_input_state = (GpuPipelineVertexInputStateInfo){ + .bindings = wpArray( + GpuVertexInputBinding, + (GpuVertexInputBinding){ .binding = 0, .stride = sizeof(Vertex), .input_rate = GPU_VERTEX_INPUT_RATE_VERTEX } + ), + .attributes = wpArray( + GpuVertexInputAttribute, + (GpuVertexInputAttribute){ + .location = 0, + .binding = 0, + .offset = offsetof(Vertex, position), + .format = GPU_FORMAT_R32G32B32_SFLOAT, + }, + (GpuVertexInputAttribute){ + .location = 1, + .binding = 0, + .offset = offsetof(Vertex, normal), + .format = GPU_FORMAT_R32G32B32_SFLOAT, + }, + (GpuVertexInputAttribute){ + .location = 2, + .binding = 0, + .offset = offsetof(Vertex, uv), + .format = GPU_FORMAT_R32G32_SFLOAT, + } + ) + }, + .input_assembly_state = (GpuPipelineInputAssemblyStateInfo){ + .topology = GPU_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + }, + .viewport_state = (GpuPipelineViewportStateInfo){ + .viewport_count = 1, + .scissor_count = 1, + }, + .rasterization_state = (GpuPipelineRasterizationStateInfo){ .line_width = 1.0f }, + .multisample_state = (GpuPipelineMultisampleStateInfo){ + .rasterization_samples = GPU_SAMPLE_COUNT_1_BIT + }, + .depth_stencil_state = (GpuPipelineDepthStencilStateInfo){ + .depth_test_enable = true, + .depth_write_enable = true, + .depth_compare_op = GPU_COMPARE_OP_LESS_OR_EQUAL, + }, + .color_blend_state = (GpuPipelineColorBlendStateInfo){ + .attachments = wpArray( + GpuPipelineColorBlendAttachmentState, + (GpuPipelineColorBlendAttachmentState){ + .color_write_mask = 0xf + } + ) + }, + .shader_stages = wpArray( + GpuPipelineShaderStageInfo, + (GpuPipelineShaderStageInfo){ + .shader = shader, + .name = "vertMain", + .stage = GPU_SHADER_STAGE_VERTEX, + }, + (GpuPipelineShaderStageInfo){ + .shader = shader, + .name = "fragMain", + .stage = GPU_SHADER_STAGE_FRAGMENT, + }, + ), + .layout = graphics_pipeline_layout, + .color_attachment_format = gpuGetSwapchainImageFormat(swapchain), + .depth_attachment_format = gpuGetSwapchainDepthFormat(swapchain), + }, + ), + }; + GpuPipelinePtrArray graphics_pipelines = gpuCreateGraphicsPipelines(&arena, &temp_arena, graphics_pipelines_request); + GpuPipelineLayoutCreateRequest compute_pl_request = { .device = device, .descriptor_set_layouts = wpArray(GpuDescriptorSetLayout *, set_layout), @@ -258,6 +336,9 @@ i32 main(void) { for (u64 i = 0; i < wpArrayCount(compute_pipelines); ++i) { gpuDestroyPipeline(compute_pipelines[i]); } + for (u64 i = 0; i < wpArrayCount(graphics_pipelines); ++i) { + gpuDestroyPipeline(graphics_pipelines[i]); + } gpuDestroyPipelineLayout(compute_pipeline_layout); gpuDestroyPipelineLayout(graphics_pipeline_layout); gpuDestroyShader(shader); diff --git a/src/shaders/shader.slang b/src/shaders/shader.slang index 6b7cbf8..bb523ad 100644 --- a/src/shaders/shader.slang +++ b/src/shaders/shader.slang @@ -1,3 +1,9 @@ +struct VSInput { + float3 Pos; + float3 Normal; + float2 UV; +}; + static float2 positions[3] = float2[]( float2( 0.0, -0.5), float2( 0.5, 0.5), @@ -25,13 +31,17 @@ uniform uint count; struct VertexOutput { float3 color; float4 sv_position : SV_Position; + float3 Normal; + float2 UV; }; [shader("vertex")] -VertexOutput vertMain(uint vid : SV_VertexID) { +VertexOutput vertMain(VSInput input, uint vid : SV_VertexID) { VertexOutput output; output.color = colors[vid]; - output.sv_position = float4(positions[vid], 0.0, 1.0); + output.sv_position = float4(input.Pos, 1.0); + output.Normal = input.Normal; + output.UV = input.UV; return output; }