From 64617ea2c46d13cd2f72df72fcd426d2fc561bff Mon Sep 17 00:00:00 2001 From: gramanas Date: Sat, 1 Jun 2024 01:47:10 +0300 Subject: multisample --- src/render.c | 95 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 29 deletions(-) (limited to 'src/render.c') diff --git a/src/render.c b/src/render.c index 275752c..0f80d3a 100644 --- a/src/render.c +++ b/src/render.c @@ -364,6 +364,21 @@ vulkan_is_device_suitable(VkPhysicalDevice device) && swapChainAdequate && supportedFeatures.samplerAnisotropy; } +VkSampleCountFlagBits getMaxUsableSampleCount() { + VkPhysicalDeviceProperties physicalDeviceProperties; + vkGetPhysicalDeviceProperties(s.vk_physical_device, &physicalDeviceProperties); + + VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts; + if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; } + if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; } + if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; } + if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; } + if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; } + if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; } + + return VK_SAMPLE_COUNT_1_BIT; +} + void vulkan_pick_physical_device() { @@ -379,6 +394,7 @@ vulkan_pick_physical_device() for (uint32_t i = 0; i < deviceCount; i++) { if (vulkan_is_device_suitable(devices[i])) { s.vk_physical_device = devices[i]; + s.msaa_samples = getMaxUsableSampleCount(); break; } } @@ -423,6 +439,7 @@ vulkan_create_logical_device() VkPhysicalDeviceFeatures deviceFeatures = {0}; vkGetPhysicalDeviceFeatures(s.vk_physical_device, &deviceFeatures); deviceFeatures.samplerAnisotropy = VK_TRUE; + //deviceFeatures.sampleRateShading = VK_TRUE; #ifndef VKDEBUG /* Disable robust buffer access when building without debug */ deviceFeatures.robustBufferAccess = VK_FALSE; @@ -724,7 +741,7 @@ void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage *image, - VkDeviceMemory *imageMemory) + VkDeviceMemory *imageMemory, VkSampleCountFlagBits numSamples) { VkImageCreateInfo imageInfo = {0}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -738,7 +755,7 @@ createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkFormat format imageInfo.tiling = tiling; imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; imageInfo.usage = usage; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.samples = numSamples; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VK_CHECK(vkCreateImage(s.vk_device, &imageInfo, NULL, image)); @@ -880,7 +897,7 @@ vulkan_create_depth_resources() depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - &s.vk_depth_image, &s.vk_depth_image_memory); + &s.vk_depth_image, &s.vk_depth_image_memory, s.msaa_samples); s.vk_depth_image_view = create_image_view(s.vk_depth_image, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1); @@ -890,6 +907,18 @@ vulkan_create_depth_resources() VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1); } +void vulkan_create_color_resources() { + VkFormat colorFormat = s.vk_swap_chain_image_format; + + createImage(s.vk_swap_chain_extent.width, s.vk_swap_chain_extent.height, 1, + colorFormat, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + &s.vk_color_image, &s.vk_color_image_memory, s.msaa_samples); + s.vk_color_image_view = create_image_view(s.vk_color_image, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1); +} + void vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) { @@ -940,7 +969,9 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, - VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE + VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, + // TODO Make polygon mode dynamic + //VK_DYNAMIC_STATE_POLYGON_MODE_EXT }; VkPipelineDynamicStateCreateInfo dynamicState = {0}; @@ -993,13 +1024,12 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) scissor.offset = (VkOffset2D){0, 0}; scissor.extent = s.vk_swap_chain_extent; - VkPipelineViewportStateCreateInfo viewportState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .viewportCount = 1, - .pViewports = &viewport, - .scissorCount = 1, - .pScissors = &scissor, - }; + VkPipelineViewportStateCreateInfo viewportState = {0}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; VkPipelineRasterizationStateCreateInfo rasterizer = {0}; rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; @@ -1018,7 +1048,7 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) VkPipelineMultisampleStateCreateInfo multisampling = {0}; multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisampling.rasterizationSamples = s.msaa_samples; multisampling.minSampleShading = 1.0f; // Optional multisampling.pSampleMask = NULL; // Optional multisampling.alphaToCoverageEnable = VK_FALSE; // Optional @@ -1068,7 +1098,6 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) depthStencil.front = (VkStencilOpState){0}; // Optional depthStencil.back = (VkStencilOpState){0}; // Optional - // TODO depthAttachment VkPipelineRenderingCreateInfo pipeline_rendering_create_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, .colorAttachmentCount = 1, @@ -1150,7 +1179,9 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) VK_CHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo)); vkCmdSetDepthTestEnable(commandBuffer, 1); vkCmdSetDepthWriteEnable(commandBuffer, 1); - + // TODO Make polygon mode dynamic + //vkCmdSetPolygonModeEXT(commandBuffer, s.polygon_mode); + transitionImageLayout( s.vk_swap_chain_images[imageIndex], VK_FORMAT_R8G8B8A8_SRGB, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, @@ -1159,8 +1190,11 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) VkRenderingAttachmentInfo colorAttachment = {0}; colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; - colorAttachment.imageView = s.vk_swap_chain_image_views[imageIndex]; + colorAttachment.imageView = s.vk_color_image_view; colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + colorAttachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; + colorAttachment.resolveImageView = s.vk_swap_chain_image_views[imageIndex]; + colorAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; colorAttachment.clearValue.color = @@ -1459,6 +1493,10 @@ vulkan_create_descriptor_sets() void cleanupSwapChain() { + vkDestroyImageView(s.vk_device, s.vk_color_image_view, NULL); + vkDestroyImage(s.vk_device, s.vk_color_image, NULL); + vkFreeMemory(s.vk_device, s.vk_color_image_memory, NULL); + vkDestroyImageView(s.vk_device, s.vk_depth_image_view, NULL); vkDestroyImage(s.vk_device, s.vk_depth_image, NULL); vkFreeMemory(s.vk_device, s.vk_depth_image_memory, NULL); @@ -1478,6 +1516,7 @@ recreateSwapChain() vulkan_create_swap_chain(); vulkan_create_image_views(); + vulkan_create_color_resources(); vulkan_create_depth_resources(); } @@ -1558,7 +1597,7 @@ handle_input(bool * quit) /* strcpy(s.model_path, "assets/human.obj"); */ if (toggle) { - strcpy(s.model_path, "assets/monkey.obj"); + strcpy(s.model_path, "assets/viking_room.obj"); load_model_obj(); toggle = 0; } else { @@ -1760,7 +1799,7 @@ vulkan_create_texture_image() VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vk_texture_image, - &s.vk_texture_image_memory); + &s.vk_texture_image_memory, VK_SAMPLE_COUNT_1_BIT); transitionImageLayout( s.vk_texture_image, VK_FORMAT_R8G8B8A8_SRGB, 0, @@ -1961,7 +2000,7 @@ void load_model_gltf() { cgltf_free(data); } - + void init_vulkan() { @@ -1983,11 +2022,12 @@ init_vulkan() vulkan_create_graphics_pipeline(s.polygon_mode); vulkan_create_command_pool(); vulkan_create_depth_resources(); + vulkan_create_color_resources(); vulkan_create_texture_image(); vulkan_create_texture_image_view(); vulkan_create_texture_sampler(); - //load_model_obj(); - load_model_gltf(); + load_model_obj(); + //load_model_gltf(); vulkan_create_vertex_buffer(); vulkan_create_index_buffer(); vulkan_create_uniform_buffers(); @@ -2107,7 +2147,6 @@ updateUniformBuffer(uint32_t currentImage, float dt) } float prev_time = 0; - void draw_frame() { float time = current_time(); @@ -2134,22 +2173,20 @@ draw_frame() { // both could work //vkResetCommandPool(s.vk_device, s.vk_command_pool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT); vkResetCommandBuffer(s.frames[currentFrame].vk_command_buffer, 0); + recordCommandBuffer(s.frames[currentFrame].vk_command_buffer, imageIndex); + VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + VkSubmitInfo submitInfo = {0}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - - VkSemaphore waitSemaphores[] = {s.frames[currentFrame].image_available_semaphore}; - VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitSemaphores = &s.frames[currentFrame].image_available_semaphore; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &s.frames[currentFrame].vk_command_buffer; - - VkSemaphore signalSemaphores[] = {s.frames[currentFrame].render_finished_semaphore}; submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores; + submitInfo.pSignalSemaphores = &s.frames[currentFrame].render_finished_semaphore; if (vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, s.frames[currentFrame].in_flight_fence) != VK_SUCCESS) { vk_log(VK_ERROR, "failed to submit draw command buffer!\n"); @@ -2159,7 +2196,7 @@ draw_frame() { VkPresentInfoKHR presentInfo = {0}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = signalSemaphores; + presentInfo.pWaitSemaphores = &s.frames[currentFrame].render_finished_semaphore; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = swapChains; presentInfo.pImageIndices = &imageIndex; -- cgit v1.2.3