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 +++++++++++++++++++++++++++++++++++++++------------------ src/shader.frag | 80 ++++++++++++++++++++++++------------------------ src/state.h | 10 +++++- 3 files changed, 115 insertions(+), 70 deletions(-) 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; diff --git a/src/shader.frag b/src/shader.frag index 1818cc8..3e80e21 100644 --- a/src/shader.frag +++ b/src/shader.frag @@ -16,50 +16,50 @@ layout(binding = 0) uniform UniformBufferObject { float dt; } ubo; -void main() { - // float pulse = sin(ubo.time * .2) * .5 + .5; - // outColor = vec4(fragColor * texture(texSampler, fragTexCoord).rgb * pulse, 1.0); - //outColor = texture(texSampler, fragTexCoord); - outColor = vec4(fragColor, 1); -// float repeat = 10; -// float f = mod(ubo.time, repeat); -// if (f < repeat / 2) { -// outColor = vec4(fragColor * radians(f) ,1); -// } else { -// outColor = vec4(fragColor * radians(1 - f) ,1); -// } -// //outColor = (vec4(1) * ubo.model + vec4(1)) * vec4(texture(texSampler, fragTexCoord).rgb * fragColor, 1.0); -} - -// float noise(vec2 p) { -// return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); +// void main() { +// // float pulse = sin(ubo.time * .2) * .5 + .5; +// // outColor = vec4(fragColor * texture(texSampler, fragTexCoord).rgb * pulse, 1.0); +// //outColor = texture(texSampler, fragTexCoord); +// outColor = vec4(fragColor, 1); +// // float repeat = 10; +// // float f = mod(ubo.time, repeat); +// // if (f < repeat / 2) { +// // outColor = vec4(fragColor * radians(f) ,1); +// // } else { +// // outColor = vec4(fragColor * radians(1 - f) ,1); +// // } +// // //outColor = (vec4(1) * ubo.model + vec4(1)) * vec4(texture(texSampler, fragTexCoord).rgb * fragColor, 1.0); // } -// float smoothNoise(vec2 p) { -// vec2 i = floor(p); -// vec2 f = fract(p); -// vec2 u = f * f * (3.0 - 2.0 * f); -// return mix(mix(noise(i + vec2(0.0, 0.0)), noise(i + vec2(1.0, 0.0)), u.x), -// mix(noise(i + vec2(0.0, 1.0)), noise(i + vec2(1.0, 1.0)), u.x), u.y); -// } +float noise(vec2 p) { + return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); +} -// float fbm(vec2 p) { -// float value = 0.0; -// float amplitude = 0.5; -// for (int i = 0; i < 6; i++) { -// value += amplitude * smoothNoise(p); -// p *= 2.0; -// amplitude *= 0.5; -// } -// return value; -// } +float smoothNoise(vec2 p) { + vec2 i = floor(p); + vec2 f = fract(p); + vec2 u = f * f * (3.0 - 2.0 * f); + return mix(mix(noise(i + vec2(0.0, 0.0)), noise(i + vec2(1.0, 0.0)), u.x), + mix(noise(i + vec2(0.0, 1.0)), noise(i + vec2(1.0, 1.0)), u.x), u.y); +} -// void main() { -// vec2 uv = gl_FragCoord.xy / ubo.resolution.xy; -// vec2 p = uv * 2.0 - vec2(1.0); -// float n = fbm(p * 5.0 - vec2(0.0, ubo.time * 2.0)); -// outColor = vec4(n, n * 0.5, 0.0, 1.0) * vec4(texture(texSampler, fragTexCoord).rgb, 1.0); -// } +float fbm(vec2 p) { + float value = 0.0; + float amplitude = 0.5; + for (int i = 0; i < 6; i++) { + value += amplitude * smoothNoise(p); + p *= 2.0; + amplitude *= 0.5; + } + return value; +} + +void main() { + vec2 uv = gl_FragCoord.xy / ubo.resolution.xy; + vec2 p = uv * 2.0 - vec2(1.0); + float n = fbm(p * 5.0 - vec2(0.0, ubo.time * 2.0)); + outColor = vec4(n, n * 0.5, 0.0, 1.0) * vec4(texture(texSampler, fragTexCoord).rgb, 1.0); +} // void main() { diff --git a/src/state.h b/src/state.h index 2f02a20..95f636b 100644 --- a/src/state.h +++ b/src/state.h @@ -142,13 +142,19 @@ typedef struct state { VkDeviceMemory vertexBufferMemory; char model_path[1000]; + + VkSampleCountFlagBits msaa_samples; + + VkImage vk_color_image; + VkDeviceMemory vk_color_image_memory; + VkImageView vk_color_image_view; } state_t; static void init_state(state_t *s) { - strcpy(s->model_path, "assets/viking_room.obj"); + strcpy(s->model_path, "assets/monkey.obj"); s->camera.pos[0] = 2.0f; s->camera.pos[1] = 2.0f; s->camera.pos[2] = 2.0f; @@ -198,4 +204,6 @@ init_state(state_t *s) s->prev_frag_result = NULL; s->polygon_mode = VK_POLYGON_MODE_FILL; + + s->msaa_samples = VK_SAMPLE_COUNT_1_BIT; } -- cgit v1.2.3