From d567ce0bebf6fee7ddfdb00c7dc3485ef786e21c Mon Sep 17 00:00:00 2001 From: Greg Wells Date: Sat, 5 Jul 2025 17:02:38 -0400 Subject: [PATCH] render pass stuff for multisampling --- .../output_device/vulkan_physical_device.c | 29 ++++++++++++++----- .../output_device/vulkan_physical_device.h | 4 +++ .../vulkan_render_pass_descriptor.c | 16 ++++++++-- .../vulkan_render_pass_descriptor.h | 1 + .../apis/vulkan/src/textures/vulkan_texture.c | 2 +- .../gryphn_physical_output_device.h | 1 - .../gryphn_render_pass_descriptor.h | 7 +++++ projects/core/src/textures/gryphn_texture.h | 2 ++ 8 files changed, 51 insertions(+), 11 deletions(-) diff --git a/projects/apis/vulkan/src/output_device/vulkan_physical_device.c b/projects/apis/vulkan/src/output_device/vulkan_physical_device.c index 9358970..abadf9f 100644 --- a/projects/apis/vulkan/src/output_device/vulkan_physical_device.c +++ b/projects/apis/vulkan/src/output_device/vulkan_physical_device.c @@ -3,12 +3,8 @@ #include #include -gnMultisampleCountFlags getVulkanSampleCount(VkPhysicalDevice device) { - VkPhysicalDeviceProperties physicalDeviceProperties; - vkGetPhysicalDeviceProperties(device, &physicalDeviceProperties); - VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts; - - gnMultisampleCountFlags sampleCount = GN_SAMPLES_NONE; +gnMultisampleCountFlags vkSampleCountToGryphn(VkSampleCountFlags counts) { + gnMultisampleCountFlags sampleCount = 0; if (counts & VK_SAMPLE_COUNT_64_BIT) { sampleCount |= GN_SAMPLE_BIT_64; } if (counts & VK_SAMPLE_COUNT_32_BIT) { sampleCount |= GN_SAMPLE_BIT_32; } if (counts & VK_SAMPLE_COUNT_16_BIT) { sampleCount |= GN_SAMPLE_BIT_16; } @@ -16,6 +12,21 @@ gnMultisampleCountFlags getVulkanSampleCount(VkPhysicalDevice device) { if (counts & VK_SAMPLE_COUNT_4_BIT) { sampleCount |= GN_SAMPLE_BIT_4; } if (counts & VK_SAMPLE_COUNT_2_BIT) { sampleCount |= GN_SAMPLE_BIT_2; } if (counts & VK_SAMPLE_COUNT_1_BIT) { sampleCount |= GN_SAMPLE_BIT_1; } + return sampleCount; +} + +#include + +VkSampleCountFlags gnSampleCountToVulkan(gnMultisampleCountFlags counts) { + VkSampleCountFlags sampleCount = 0; + + if ((counts & GN_SAMPLE_BIT_64) == GN_SAMPLE_BIT_64) { sampleCount |= VK_SAMPLE_COUNT_64_BIT; } + if ((counts & GN_SAMPLE_BIT_32) == GN_SAMPLE_BIT_32) { sampleCount |= VK_SAMPLE_COUNT_32_BIT; } + if ((counts & GN_SAMPLE_BIT_16) == GN_SAMPLE_BIT_16) { sampleCount |= VK_SAMPLE_COUNT_16_BIT; } + if ((counts & GN_SAMPLE_BIT_8) == GN_SAMPLE_BIT_8) { sampleCount |= VK_SAMPLE_COUNT_8_BIT; } + if ((counts & GN_SAMPLE_BIT_4) == GN_SAMPLE_BIT_4) { sampleCount |= VK_SAMPLE_COUNT_4_BIT; } + if ((counts & GN_SAMPLE_BIT_2) == GN_SAMPLE_BIT_2) { sampleCount |= VK_SAMPLE_COUNT_2_BIT; } + if ((counts & GN_SAMPLE_BIT_1) == GN_SAMPLE_BIT_1) { sampleCount |= VK_SAMPLE_COUNT_1_BIT; } return sampleCount; } @@ -61,7 +72,11 @@ gnPhysicalDevice* getPhysicalDevices(gnInstanceHandle instance, uint32_t* device outputDevices[i].queueProperties.queueProperties[i].queueType = finalQueueType; } - outputDevices[i].features.avaliableSamples = getVulkanSampleCount(physicalDevices[i]); + VkPhysicalDeviceProperties physicalDeviceProperties; + vkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties); + VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts; + + outputDevices[i].features.avaliableSamples = vkSampleCountToGryphn(counts); } free(physicalDevices); diff --git a/projects/apis/vulkan/src/output_device/vulkan_physical_device.h b/projects/apis/vulkan/src/output_device/vulkan_physical_device.h index 3956221..e381bb1 100644 --- a/projects/apis/vulkan/src/output_device/vulkan_physical_device.h +++ b/projects/apis/vulkan/src/output_device/vulkan_physical_device.h @@ -8,3 +8,7 @@ typedef struct gnPlatformPhysicalDevice_t { gnPhysicalDevice* getPhysicalDevices(gnInstanceHandle instance, uint32_t* deviceCount); gnBool queueCanPresentToSurface(const gnPhysicalDevice device, uint32_t queueIndex, gnWindowSurfaceHandle windowSurface); + + +gnMultisampleCountFlags vkSampleCountToGryphn(VkSampleCountFlags counts); +VkSampleCountFlags gnSampleCountToVulkan(gnMultisampleCountFlags counts); diff --git a/projects/apis/vulkan/src/renderpass/vulkan_render_pass_descriptor.c b/projects/apis/vulkan/src/renderpass/vulkan_render_pass_descriptor.c index bc15294..9a2836d 100644 --- a/projects/apis/vulkan/src/renderpass/vulkan_render_pass_descriptor.c +++ b/projects/apis/vulkan/src/renderpass/vulkan_render_pass_descriptor.c @@ -1,6 +1,7 @@ #include "vulkan_render_pass_descriptor.h" #include "vulkan_surface/vulkan_surface.h" #include "output_device/vulkan_output_devices.h" +#include #include "stdio.h" VkAttachmentLoadOp vkGryphnLoadOperation(gnLoadOperation loadOperation) { @@ -50,7 +51,7 @@ gnReturnCode createRenderPass(gnRenderPassDescriptor renderPass, gnDevice device for (int i = 0; i < info.attachmentCount; i++) { renderPass->renderPassDescriptor->attachments[i].format = vkGryphnFormatToVulkanFormat(info.attachmentInfos[i].format); renderPass->renderPassDescriptor->attachments[i].flags = 0; - renderPass->renderPassDescriptor->attachments[i].samples = VK_SAMPLE_COUNT_1_BIT; + renderPass->renderPassDescriptor->attachments[i].samples = gnSampleCountToVulkan(info.attachmentInfos[i].samples); renderPass->renderPassDescriptor->attachments[i].loadOp = vkGryphnLoadOperation(info.attachmentInfos[i].loadOperation); renderPass->renderPassDescriptor->attachments[i].storeOp = vkGryphnStoreOperation(info.attachmentInfos[i].storeOperation); @@ -66,9 +67,12 @@ gnReturnCode createRenderPass(gnRenderPassDescriptor renderPass, gnDevice device renderPass->renderPassDescriptor->subpasses = malloc(sizeof(VkSubpassDescription) * info.subpassCount); renderPass->renderPassDescriptor->colorAttachments = malloc(sizeof(VkAttachmentReference*) * info.subpassCount); renderPass->renderPassDescriptor->depthAttachments = malloc(sizeof(VkAttachmentReference) * info.subpassCount); + renderPass->renderPassDescriptor->resolveAttachments = malloc(sizeof(VkAttachmentReference*) * info.subpassCount); + for (int i = 0; i < info.subpassCount; i++) { renderPass->renderPassDescriptor->colorAttachments[i] = malloc(sizeof(VkAttachmentReference) * info.subpassInfos[i].colorAttachmentCount); + renderPass->renderPassDescriptor->resolveAttachments[i] = malloc(sizeof(VkAttachmentReference) * info.subpassInfos[i].resolveAttachmentCount); for (int c = 0; c < info.subpassInfos[i].colorAttachmentCount; c++) { renderPass->renderPassDescriptor->colorAttachments[i][c] = (VkAttachmentReference){ @@ -77,11 +81,19 @@ gnReturnCode createRenderPass(gnRenderPassDescriptor renderPass, gnDevice device }; } + for (int c = 0; c < info.subpassInfos[i].resolveAttachmentCount; c++) { + renderPass->renderPassDescriptor->resolveAttachments[i][c] = (VkAttachmentReference){ + .attachment = info.subpassInfos[i].resolveAttachments[c].index, + .layout = vkGryphnImageLayout(info.subpassInfos[i].resolveAttachments[c].imageLayout) + }; + } + renderPass->renderPassDescriptor->subpasses[i] = (VkSubpassDescription){ .flags = 0, .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, .colorAttachmentCount = info.subpassInfos[i].colorAttachmentCount, - .pColorAttachments = renderPass->renderPassDescriptor->colorAttachments[i] + .pColorAttachments = renderPass->renderPassDescriptor->colorAttachments[i], + .pResolveAttachments = renderPass->renderPassDescriptor->resolveAttachments[i] }; if (info.subpassInfos[i].depthAttachment != NULL) { diff --git a/projects/apis/vulkan/src/renderpass/vulkan_render_pass_descriptor.h b/projects/apis/vulkan/src/renderpass/vulkan_render_pass_descriptor.h index 6ba1cfe..1a22ab2 100644 --- a/projects/apis/vulkan/src/renderpass/vulkan_render_pass_descriptor.h +++ b/projects/apis/vulkan/src/renderpass/vulkan_render_pass_descriptor.h @@ -14,6 +14,7 @@ typedef struct gnPlatformRenderPassDescriptor_t { VkAttachmentReference** colorAttachments; VkAttachmentReference* depthAttachments; + VkAttachmentReference** resolveAttachments; } gnPlatformRenderPassDescriptor; VkPipelineStageFlags vkGryphnRenderPassStage(gnRenderPassStage stage); diff --git a/projects/apis/vulkan/src/textures/vulkan_texture.c b/projects/apis/vulkan/src/textures/vulkan_texture.c index 4e8e608..12d7f6a 100644 --- a/projects/apis/vulkan/src/textures/vulkan_texture.c +++ b/projects/apis/vulkan/src/textures/vulkan_texture.c @@ -146,7 +146,7 @@ gnReturnCode createTexture(gnTexture texture, gnDevice device, const gnTextureIn .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .tiling = VK_IMAGE_TILING_OPTIMAL, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .samples = VK_SAMPLE_COUNT_1_BIT, + .samples = gnSampleCountToVulkan(info.samples), .extent = { .width = info.extent.width, .height = info.extent.height, diff --git a/projects/core/src/output_device/gryphn_physical_output_device.h b/projects/core/src/output_device/gryphn_physical_output_device.h index c2af5b5..fb3fba0 100644 --- a/projects/core/src/output_device/gryphn_physical_output_device.h +++ b/projects/core/src/output_device/gryphn_physical_output_device.h @@ -8,7 +8,6 @@ typedef enum gnDeviceType { } gnDeviceType; typedef enum gnMultisampleCountFlags { - GN_SAMPLES_NONE = 0, GN_SAMPLE_BIT_1 = 1 << 0, // 0x01 GN_SAMPLE_BIT_2 = 1 << 1, // 0x02 GN_SAMPLE_BIT_4 = 1 << 2, // 0x04 diff --git a/projects/core/src/renderpass/gryphn_render_pass_descriptor.h b/projects/core/src/renderpass/gryphn_render_pass_descriptor.h index 17604c7..7c4386e 100644 --- a/projects/core/src/renderpass/gryphn_render_pass_descriptor.h +++ b/projects/core/src/renderpass/gryphn_render_pass_descriptor.h @@ -2,6 +2,7 @@ #include "stdint.h" #include "utils/gryphn_image_format.h" #include "utils/gryphn_error_code.h" +#include "core/src/output_device/gryphn_physical_output_device.h" #include "gryphn_handles.h" typedef enum gnRenderPassStage { @@ -32,6 +33,8 @@ typedef struct gnRenderPassAttachmentInfo_t { gnImageLayout initialLayout; gnImageLayout finalLayout; + + gnMultisampleCountFlags samples; } gnRenderPassAttachmentInfo; typedef struct gnSubpassAttachmentInfo_t { @@ -42,7 +45,11 @@ typedef struct gnSubpassAttachmentInfo_t { typedef struct gnSubpassInfo_t { uint32_t colorAttachmentCount; gnSubpassAttachmentInfo* colorAttachments; + gnSubpassAttachmentInfo* depthAttachment; + + uint32_t resolveAttachmentCount; + gnSubpassAttachmentInfo* resolveAttachments; } gnSubpassInfo; #define GN_SUBPASS_EXTERNAL -1 diff --git a/projects/core/src/textures/gryphn_texture.h b/projects/core/src/textures/gryphn_texture.h index 056e8fb..ee1f4db 100644 --- a/projects/core/src/textures/gryphn_texture.h +++ b/projects/core/src/textures/gryphn_texture.h @@ -2,6 +2,7 @@ #include "utils/gryphn_image_format.h" #include "utils/gryphn_error_code.h" #include "utils/math/gryphn_vec3.h" +#include "core/src/output_device/gryphn_physical_output_device.h" #include typedef enum gnTextureType { @@ -18,6 +19,7 @@ typedef enum gnTextureWrap { typedef struct gnTextureInfo { gnExtent3D extent; + gnMultisampleCountFlags samples; uint32_t mipmapLevels; gnTextureType type; gnImageFormat format;