Vulkan: Implement FXAA
This commit is contained in:
		 FernandoS27
					FernandoS27
				
			
				
					committed by
					
						 Fernando Sahmkow
						Fernando Sahmkow
					
				
			
			
				
	
			
			
			 Fernando Sahmkow
						Fernando Sahmkow
					
				
			
						parent
						
							056894f07a
						
					
				
				
					commit
					e6f1ed08fb
				
			| @@ -15,7 +15,7 @@ layout (location = 0) out vec4 posPos; | ||||
|  | ||||
| #ifdef VULKAN | ||||
|  | ||||
| #define BINDING_COLOR_TEXTURE 1 | ||||
| #define BINDING_COLOR_TEXTURE 0 | ||||
|  | ||||
| #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||||
|  | ||||
|   | ||||
| @@ -17,6 +17,8 @@ | ||||
| #include "core/frontend/emu_window.h" | ||||
| #include "core/memory.h" | ||||
| #include "video_core/gpu.h" | ||||
| #include "video_core/host_shaders/fxaa_frag_spv.h" | ||||
| #include "video_core/host_shaders/fxaa_vert_spv.h" | ||||
| #include "video_core/host_shaders/present_bicubic_frag_spv.h" | ||||
| #include "video_core/host_shaders/present_gaussian_frag_spv.h" | ||||
| #include "video_core/host_shaders/present_scaleforce_frag_spv.h" | ||||
| @@ -149,15 +151,9 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | ||||
|     scheduler.Wait(resource_ticks[image_index]); | ||||
|     resource_ticks[image_index] = scheduler.CurrentTick(); | ||||
|  | ||||
|     const VkImageView source_image_view = | ||||
|     VkImageView source_image_view = | ||||
|         use_accelerated ? screen_info.image_view : *raw_image_views[image_index]; | ||||
|  | ||||
|     if (!fsr) { | ||||
|         const bool is_nn = | ||||
|             Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::NearestNeighbor; | ||||
|         UpdateDescriptorSet(image_index, source_image_view, is_nn); | ||||
|     } | ||||
|  | ||||
|     BufferData data; | ||||
|     SetUniformData(data, layout); | ||||
|     SetVertexData(data, framebuffer, layout); | ||||
| @@ -239,6 +235,68 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     const auto anti_alias_pass = Settings::values.anti_aliasing.GetValue(); | ||||
|     if (use_accelerated && anti_alias_pass != Settings::AntiAliasing::None) { | ||||
|         UpdateAADescriptorSet(image_index, source_image_view, false); | ||||
|         const u32 up_scale = Settings::values.resolution_info.up_scale; | ||||
|         const u32 down_shift = Settings::values.resolution_info.down_shift; | ||||
|         VkExtent2D size{ | ||||
|             .width = (up_scale * framebuffer.width) >> down_shift, | ||||
|             .height = (up_scale * framebuffer.height) >> down_shift, | ||||
|         }; | ||||
|         source_image_view = *aa_image_view; | ||||
|         scheduler.Record([this, image_index, size, anti_alias_pass](vk::CommandBuffer cmdbuf) { | ||||
|             const f32 bg_red = Settings::values.bg_red.GetValue() / 255.0f; | ||||
|             const f32 bg_green = Settings::values.bg_green.GetValue() / 255.0f; | ||||
|             const f32 bg_blue = Settings::values.bg_blue.GetValue() / 255.0f; | ||||
|             const VkClearValue clear_color{ | ||||
|                 .color = {.float32 = {bg_red, bg_green, bg_blue, 1.0f}}, | ||||
|             }; | ||||
|             const VkRenderPassBeginInfo renderpass_bi{ | ||||
|                 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, | ||||
|                 .pNext = nullptr, | ||||
|                 .renderPass = *aa_renderpass, | ||||
|                 .framebuffer = *aa_framebuffer, | ||||
|                 .renderArea = | ||||
|                     { | ||||
|                         .offset = {0, 0}, | ||||
|                         .extent = size, | ||||
|                     }, | ||||
|                 .clearValueCount = 1, | ||||
|                 .pClearValues = &clear_color, | ||||
|             }; | ||||
|             const VkViewport viewport{ | ||||
|                 .x = 0.0f, | ||||
|                 .y = 0.0f, | ||||
|                 .width = static_cast<float>(size.width), | ||||
|                 .height = static_cast<float>(size.height), | ||||
|                 .minDepth = 0.0f, | ||||
|                 .maxDepth = 1.0f, | ||||
|             }; | ||||
|             const VkRect2D scissor{ | ||||
|                 .offset = {0, 0}, | ||||
|                 .extent = size, | ||||
|             }; | ||||
|             cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); | ||||
|             switch (anti_alias_pass) { | ||||
|             case Settings::AntiAliasing::Fxaa: | ||||
|                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline); | ||||
|                 break; | ||||
|             default: | ||||
|                 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline); | ||||
|                 break; | ||||
|             } | ||||
|             cmdbuf.SetViewport(0, viewport); | ||||
|             cmdbuf.SetScissor(0, scissor); | ||||
|  | ||||
|             cmdbuf.BindVertexBuffer(0, *buffer, offsetof(BufferData, vertices)); | ||||
|             cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *aa_pipeline_layout, 0, | ||||
|                                       aa_descriptor_sets[image_index], {}); | ||||
|             cmdbuf.Draw(4, 1, 0, 0); | ||||
|             cmdbuf.EndRenderPass(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     if (fsr) { | ||||
|         auto crop_rect = framebuffer.crop_rect; | ||||
|         if (crop_rect.GetWidth() == 0) { | ||||
| @@ -251,6 +309,10 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | ||||
|         VkImageView fsr_image_view = | ||||
|             fsr->Draw(scheduler, image_index, source_image_view, crop_rect); | ||||
|         UpdateDescriptorSet(image_index, fsr_image_view, true); | ||||
|     } else { | ||||
|         const bool is_nn = | ||||
|             Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::NearestNeighbor; | ||||
|         UpdateDescriptorSet(image_index, source_image_view, is_nn); | ||||
|     } | ||||
|  | ||||
|     scheduler.Record( | ||||
| @@ -329,11 +391,16 @@ VkSemaphore VKBlitScreen::DrawToSwapchain(const Tegra::FramebufferConfig& frameb | ||||
| } | ||||
|  | ||||
| vk::Framebuffer VKBlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent) { | ||||
|     return CreateFramebuffer(image_view, extent, renderpass); | ||||
| } | ||||
|  | ||||
| vk::Framebuffer VKBlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent, | ||||
|                                                 vk::RenderPass& rd) { | ||||
|     return device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{ | ||||
|         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .renderPass = *renderpass, | ||||
|         .renderPass = *rd, | ||||
|         .attachmentCount = 1, | ||||
|         .pAttachments = &image_view, | ||||
|         .width = extent.width, | ||||
| @@ -390,6 +457,8 @@ void VKBlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) | ||||
|  | ||||
| void VKBlitScreen::CreateShaders() { | ||||
|     vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV); | ||||
|     fxaa_vertex_shader = BuildShader(device, FXAA_VERT_SPV); | ||||
|     fxaa_fragment_shader = BuildShader(device, FXAA_FRAG_SPV); | ||||
|     bilinear_fragment_shader = BuildShader(device, VULKAN_PRESENT_FRAG_SPV); | ||||
|     bicubic_fragment_shader = BuildShader(device, PRESENT_BICUBIC_FRAG_SPV); | ||||
|     gaussian_fragment_shader = BuildShader(device, PRESENT_GAUSSIAN_FRAG_SPV); | ||||
| @@ -413,6 +482,13 @@ void VKBlitScreen::CreateDescriptorPool() { | ||||
|         }, | ||||
|     }}; | ||||
|  | ||||
|     const std::array<VkDescriptorPoolSize, 1> pool_sizes_aa{{ | ||||
|         { | ||||
|             .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||||
|             .descriptorCount = static_cast<u32>(2 * image_count), | ||||
|         }, | ||||
|     }}; | ||||
|  | ||||
|     const VkDescriptorPoolCreateInfo ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
| @@ -422,19 +498,33 @@ void VKBlitScreen::CreateDescriptorPool() { | ||||
|         .pPoolSizes = pool_sizes.data(), | ||||
|     }; | ||||
|     descriptor_pool = device.GetLogical().CreateDescriptorPool(ci); | ||||
|  | ||||
|     const VkDescriptorPoolCreateInfo ci_aa{ | ||||
|         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, | ||||
|         .maxSets = static_cast<u32>(image_count), | ||||
|         .poolSizeCount = static_cast<u32>(pool_sizes_aa.size()), | ||||
|         .pPoolSizes = pool_sizes_aa.data(), | ||||
|     }; | ||||
|     aa_descriptor_pool = device.GetLogical().CreateDescriptorPool(ci_aa); | ||||
| } | ||||
|  | ||||
| void VKBlitScreen::CreateRenderPass() { | ||||
|     renderpass = CreateRenderPassImpl(swapchain.GetImageViewFormat()); | ||||
| } | ||||
|  | ||||
| vk::RenderPass VKBlitScreen::CreateRenderPassImpl(VkFormat format, bool is_present) { | ||||
|     const VkAttachmentDescription color_attachment{ | ||||
|         .flags = 0, | ||||
|         .format = swapchain.GetImageViewFormat(), | ||||
|         .format = format, | ||||
|         .samples = VK_SAMPLE_COUNT_1_BIT, | ||||
|         .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, | ||||
|         .storeOp = VK_ATTACHMENT_STORE_OP_STORE, | ||||
|         .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, | ||||
|         .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, | ||||
|         .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | ||||
|         .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, | ||||
|         .finalLayout = is_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_GENERAL, | ||||
|     }; | ||||
|  | ||||
|     const VkAttachmentReference color_attachment_ref{ | ||||
| @@ -477,7 +567,7 @@ void VKBlitScreen::CreateRenderPass() { | ||||
|         .pDependencies = &dependency, | ||||
|     }; | ||||
|  | ||||
|     renderpass = device.GetLogical().CreateRenderPass(renderpass_ci); | ||||
|     return device.GetLogical().CreateRenderPass(renderpass_ci); | ||||
| } | ||||
|  | ||||
| void VKBlitScreen::CreateDescriptorSetLayout() { | ||||
| @@ -498,6 +588,23 @@ void VKBlitScreen::CreateDescriptorSetLayout() { | ||||
|         }, | ||||
|     }}; | ||||
|  | ||||
|     const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings_aa{{ | ||||
|         { | ||||
|             .binding = 0, | ||||
|             .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||||
|             .descriptorCount = 1, | ||||
|             .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | ||||
|             .pImmutableSamplers = nullptr, | ||||
|         }, | ||||
|         { | ||||
|             .binding = 1, | ||||
|             .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||||
|             .descriptorCount = 1, | ||||
|             .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, | ||||
|             .pImmutableSamplers = nullptr, | ||||
|         }, | ||||
|     }}; | ||||
|  | ||||
|     const VkDescriptorSetLayoutCreateInfo ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
| @@ -506,11 +613,21 @@ void VKBlitScreen::CreateDescriptorSetLayout() { | ||||
|         .pBindings = layout_bindings.data(), | ||||
|     }; | ||||
|  | ||||
|     const VkDescriptorSetLayoutCreateInfo ci_aa{ | ||||
|         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .bindingCount = static_cast<u32>(layout_bindings_aa.size()), | ||||
|         .pBindings = layout_bindings_aa.data(), | ||||
|     }; | ||||
|  | ||||
|     descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci); | ||||
|     aa_descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci_aa); | ||||
| } | ||||
|  | ||||
| void VKBlitScreen::CreateDescriptorSets() { | ||||
|     const std::vector layouts(image_count, *descriptor_set_layout); | ||||
|     const std::vector layouts_aa(image_count, *aa_descriptor_set_layout); | ||||
|  | ||||
|     const VkDescriptorSetAllocateInfo ai{ | ||||
|         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | ||||
| @@ -520,7 +637,16 @@ void VKBlitScreen::CreateDescriptorSets() { | ||||
|         .pSetLayouts = layouts.data(), | ||||
|     }; | ||||
|  | ||||
|     const VkDescriptorSetAllocateInfo ai_aa{ | ||||
|         .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .descriptorPool = *aa_descriptor_pool, | ||||
|         .descriptorSetCount = static_cast<u32>(image_count), | ||||
|         .pSetLayouts = layouts_aa.data(), | ||||
|     }; | ||||
|  | ||||
|     descriptor_sets = descriptor_pool.Allocate(ai); | ||||
|     aa_descriptor_sets = aa_descriptor_pool.Allocate(ai_aa); | ||||
| } | ||||
|  | ||||
| void VKBlitScreen::CreatePipelineLayout() { | ||||
| @@ -533,7 +659,17 @@ void VKBlitScreen::CreatePipelineLayout() { | ||||
|         .pushConstantRangeCount = 0, | ||||
|         .pPushConstantRanges = nullptr, | ||||
|     }; | ||||
|     const VkPipelineLayoutCreateInfo ci_aa{ | ||||
|         .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .setLayoutCount = 1, | ||||
|         .pSetLayouts = aa_descriptor_set_layout.address(), | ||||
|         .pushConstantRangeCount = 0, | ||||
|         .pPushConstantRanges = nullptr, | ||||
|     }; | ||||
|     pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); | ||||
|     aa_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci_aa); | ||||
| } | ||||
|  | ||||
| void VKBlitScreen::CreateGraphicsPipeline() { | ||||
| @@ -862,7 +998,7 @@ void VKBlitScreen::CreateFramebuffers() { | ||||
|  | ||||
|     for (std::size_t i = 0; i < image_count; ++i) { | ||||
|         const VkImageView image_view{swapchain.GetImageViewIndex(i)}; | ||||
|         framebuffers[i] = CreateFramebuffer(image_view, size); | ||||
|         framebuffers[i] = CreateFramebuffer(image_view, size, renderpass); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -872,6 +1008,11 @@ void VKBlitScreen::ReleaseRawImages() { | ||||
|     } | ||||
|     raw_images.clear(); | ||||
|     raw_buffer_commits.clear(); | ||||
|  | ||||
|     aa_image_view.reset(); | ||||
|     aa_image.reset(); | ||||
|     aa_commit = MemoryCommit{}; | ||||
|  | ||||
|     buffer.reset(); | ||||
|     buffer_commit = MemoryCommit{}; | ||||
| } | ||||
| @@ -898,8 +1039,11 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) | ||||
|     raw_image_views.resize(image_count); | ||||
|     raw_buffer_commits.resize(image_count); | ||||
|  | ||||
|     for (size_t i = 0; i < image_count; ++i) { | ||||
|         raw_images[i] = device.GetLogical().CreateImage(VkImageCreateInfo{ | ||||
|     const auto create_image = [&](bool used_on_framebuffer = false, u32 up_scale = 1, | ||||
|                                   u32 down_shift = 0) { | ||||
|         u32 extra_usages = used_on_framebuffer ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | ||||
|                                                : VK_IMAGE_USAGE_TRANSFER_DST_BIT; | ||||
|         return device.GetLogical().CreateImage(VkImageCreateInfo{ | ||||
|             .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, | ||||
|             .pNext = nullptr, | ||||
|             .flags = 0, | ||||
| @@ -907,26 +1051,30 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) | ||||
|             .format = GetFormat(framebuffer), | ||||
|             .extent = | ||||
|                 { | ||||
|                     .width = framebuffer.width, | ||||
|                     .height = framebuffer.height, | ||||
|                     .width = (up_scale * framebuffer.width) >> down_shift, | ||||
|                     .height = (up_scale * framebuffer.height) >> down_shift, | ||||
|                     .depth = 1, | ||||
|                 }, | ||||
|             .mipLevels = 1, | ||||
|             .arrayLayers = 1, | ||||
|             .samples = VK_SAMPLE_COUNT_1_BIT, | ||||
|             .tiling = VK_IMAGE_TILING_LINEAR, | ||||
|             .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, | ||||
|             .tiling = used_on_framebuffer ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR, | ||||
|             .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | extra_usages, | ||||
|             .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||||
|             .queueFamilyIndexCount = 0, | ||||
|             .pQueueFamilyIndices = nullptr, | ||||
|             .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | ||||
|         }); | ||||
|         raw_buffer_commits[i] = memory_allocator.Commit(raw_images[i], MemoryUsage::DeviceLocal); | ||||
|         raw_image_views[i] = device.GetLogical().CreateImageView(VkImageViewCreateInfo{ | ||||
|     }; | ||||
|     const auto create_commit = [&](vk::Image& image) { | ||||
|         return memory_allocator.Commit(image, MemoryUsage::DeviceLocal); | ||||
|     }; | ||||
|     const auto create_image_view = [&](vk::Image& image) { | ||||
|         return device.GetLogical().CreateImageView(VkImageViewCreateInfo{ | ||||
|             .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | ||||
|             .pNext = nullptr, | ||||
|             .flags = 0, | ||||
|             .image = *raw_images[i], | ||||
|             .image = *image, | ||||
|             .viewType = VK_IMAGE_VIEW_TYPE_2D, | ||||
|             .format = GetFormat(framebuffer), | ||||
|             .components = | ||||
| @@ -945,7 +1093,207 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) | ||||
|                     .layerCount = 1, | ||||
|                 }, | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     for (size_t i = 0; i < image_count; ++i) { | ||||
|         raw_images[i] = create_image(); | ||||
|         raw_buffer_commits[i] = create_commit(raw_images[i]); | ||||
|         raw_image_views[i] = create_image_view(raw_images[i]); | ||||
|     } | ||||
|  | ||||
|     // AA Resources | ||||
|     const u32 up_scale = Settings::values.resolution_info.up_scale; | ||||
|     const u32 down_shift = Settings::values.resolution_info.down_shift; | ||||
|     aa_image = create_image(true, up_scale, down_shift); | ||||
|     aa_commit = create_commit(aa_image); | ||||
|     aa_image_view = create_image_view(aa_image); | ||||
|     VkExtent2D size{ | ||||
|         .width = (up_scale * framebuffer.width) >> down_shift, | ||||
|         .height = (up_scale * framebuffer.height) >> down_shift, | ||||
|     }; | ||||
|     if (aa_renderpass) { | ||||
|         aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass); | ||||
|         return; | ||||
|     } | ||||
|     aa_renderpass = CreateRenderPassImpl(GetFormat(framebuffer), false); | ||||
|     aa_framebuffer = CreateFramebuffer(*aa_image_view, size, aa_renderpass); | ||||
|  | ||||
|     const std::array<VkPipelineShaderStageCreateInfo, 2> fxaa_shader_stages{{ | ||||
|         { | ||||
|             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||||
|             .pNext = nullptr, | ||||
|             .flags = 0, | ||||
|             .stage = VK_SHADER_STAGE_VERTEX_BIT, | ||||
|             .module = *fxaa_vertex_shader, | ||||
|             .pName = "main", | ||||
|             .pSpecializationInfo = nullptr, | ||||
|         }, | ||||
|         { | ||||
|             .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||||
|             .pNext = nullptr, | ||||
|             .flags = 0, | ||||
|             .stage = VK_SHADER_STAGE_FRAGMENT_BIT, | ||||
|             .module = *fxaa_fragment_shader, | ||||
|             .pName = "main", | ||||
|             .pSpecializationInfo = nullptr, | ||||
|         }, | ||||
|     }}; | ||||
|  | ||||
|     const auto vertex_binding_description = ScreenRectVertex::GetDescription(); | ||||
|     const auto vertex_attrs_description = ScreenRectVertex::GetAttributes(); | ||||
|  | ||||
|     const VkPipelineVertexInputStateCreateInfo vertex_input_ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .vertexBindingDescriptionCount = 1, | ||||
|         .pVertexBindingDescriptions = &vertex_binding_description, | ||||
|         .vertexAttributeDescriptionCount = u32{vertex_attrs_description.size()}, | ||||
|         .pVertexAttributeDescriptions = vertex_attrs_description.data(), | ||||
|     }; | ||||
|  | ||||
|     const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, | ||||
|         .primitiveRestartEnable = VK_FALSE, | ||||
|     }; | ||||
|  | ||||
|     const VkPipelineViewportStateCreateInfo viewport_state_ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .viewportCount = 1, | ||||
|         .pViewports = nullptr, | ||||
|         .scissorCount = 1, | ||||
|         .pScissors = nullptr, | ||||
|     }; | ||||
|  | ||||
|     const VkPipelineRasterizationStateCreateInfo rasterization_ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .depthClampEnable = VK_FALSE, | ||||
|         .rasterizerDiscardEnable = VK_FALSE, | ||||
|         .polygonMode = VK_POLYGON_MODE_FILL, | ||||
|         .cullMode = VK_CULL_MODE_NONE, | ||||
|         .frontFace = VK_FRONT_FACE_CLOCKWISE, | ||||
|         .depthBiasEnable = VK_FALSE, | ||||
|         .depthBiasConstantFactor = 0.0f, | ||||
|         .depthBiasClamp = 0.0f, | ||||
|         .depthBiasSlopeFactor = 0.0f, | ||||
|         .lineWidth = 1.0f, | ||||
|     }; | ||||
|  | ||||
|     const VkPipelineMultisampleStateCreateInfo multisampling_ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, | ||||
|         .sampleShadingEnable = VK_FALSE, | ||||
|         .minSampleShading = 0.0f, | ||||
|         .pSampleMask = nullptr, | ||||
|         .alphaToCoverageEnable = VK_FALSE, | ||||
|         .alphaToOneEnable = VK_FALSE, | ||||
|     }; | ||||
|  | ||||
|     const VkPipelineColorBlendAttachmentState color_blend_attachment{ | ||||
|         .blendEnable = VK_FALSE, | ||||
|         .srcColorBlendFactor = VK_BLEND_FACTOR_ZERO, | ||||
|         .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO, | ||||
|         .colorBlendOp = VK_BLEND_OP_ADD, | ||||
|         .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||||
|         .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, | ||||
|         .alphaBlendOp = VK_BLEND_OP_ADD, | ||||
|         .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | | ||||
|                           VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, | ||||
|     }; | ||||
|  | ||||
|     const VkPipelineColorBlendStateCreateInfo color_blend_ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .logicOpEnable = VK_FALSE, | ||||
|         .logicOp = VK_LOGIC_OP_COPY, | ||||
|         .attachmentCount = 1, | ||||
|         .pAttachments = &color_blend_attachment, | ||||
|         .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, | ||||
|     }; | ||||
|  | ||||
|     static constexpr std::array dynamic_states{ | ||||
|         VK_DYNAMIC_STATE_VIEWPORT, | ||||
|         VK_DYNAMIC_STATE_SCISSOR, | ||||
|     }; | ||||
|     const VkPipelineDynamicStateCreateInfo dynamic_state_ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .dynamicStateCount = static_cast<u32>(dynamic_states.size()), | ||||
|         .pDynamicStates = dynamic_states.data(), | ||||
|     }; | ||||
|  | ||||
|     const VkGraphicsPipelineCreateInfo fxaa_pipeline_ci{ | ||||
|         .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||||
|         .pNext = nullptr, | ||||
|         .flags = 0, | ||||
|         .stageCount = static_cast<u32>(fxaa_shader_stages.size()), | ||||
|         .pStages = fxaa_shader_stages.data(), | ||||
|         .pVertexInputState = &vertex_input_ci, | ||||
|         .pInputAssemblyState = &input_assembly_ci, | ||||
|         .pTessellationState = nullptr, | ||||
|         .pViewportState = &viewport_state_ci, | ||||
|         .pRasterizationState = &rasterization_ci, | ||||
|         .pMultisampleState = &multisampling_ci, | ||||
|         .pDepthStencilState = nullptr, | ||||
|         .pColorBlendState = &color_blend_ci, | ||||
|         .pDynamicState = &dynamic_state_ci, | ||||
|         .layout = *aa_pipeline_layout, | ||||
|         .renderPass = *aa_renderpass, | ||||
|         .subpass = 0, | ||||
|         .basePipelineHandle = 0, | ||||
|         .basePipelineIndex = 0, | ||||
|     }; | ||||
|  | ||||
|     // AA | ||||
|     aa_pipeline = device.GetLogical().CreateGraphicsPipeline(fxaa_pipeline_ci); | ||||
| } | ||||
|  | ||||
| void VKBlitScreen::UpdateAADescriptorSet(std::size_t image_index, VkImageView image_view, | ||||
|                                          bool nn) const { | ||||
|     const VkDescriptorImageInfo image_info{ | ||||
|         .sampler = nn ? *nn_sampler : *sampler, | ||||
|         .imageView = image_view, | ||||
|         .imageLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||
|     }; | ||||
|  | ||||
|     const VkWriteDescriptorSet sampler_write{ | ||||
|         .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | ||||
|         .pNext = nullptr, | ||||
|         .dstSet = aa_descriptor_sets[image_index], | ||||
|         .dstBinding = 0, | ||||
|         .dstArrayElement = 0, | ||||
|         .descriptorCount = 1, | ||||
|         .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||||
|         .pImageInfo = &image_info, | ||||
|         .pBufferInfo = nullptr, | ||||
|         .pTexelBufferView = nullptr, | ||||
|     }; | ||||
|  | ||||
|     const VkWriteDescriptorSet sampler_write_2{ | ||||
|         .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, | ||||
|         .pNext = nullptr, | ||||
|         .dstSet = aa_descriptor_sets[image_index], | ||||
|         .dstBinding = 1, | ||||
|         .dstArrayElement = 0, | ||||
|         .descriptorCount = 1, | ||||
|         .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, | ||||
|         .pImageInfo = &image_info, | ||||
|         .pBufferInfo = nullptr, | ||||
|         .pTexelBufferView = nullptr, | ||||
|     }; | ||||
|  | ||||
|     device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, sampler_write_2}, {}); | ||||
| } | ||||
|  | ||||
| void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view, | ||||
|   | ||||
| @@ -68,6 +68,9 @@ public: | ||||
|     [[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view, | ||||
|                                                     VkExtent2D extent); | ||||
|  | ||||
|     [[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view, | ||||
|                                                     VkExtent2D extent, vk::RenderPass& rd); | ||||
|  | ||||
| private: | ||||
|     struct BufferData; | ||||
|  | ||||
| @@ -76,6 +79,7 @@ private: | ||||
|     void CreateSemaphores(); | ||||
|     void CreateDescriptorPool(); | ||||
|     void CreateRenderPass(); | ||||
|     vk::RenderPass CreateRenderPassImpl(VkFormat, bool is_present = true); | ||||
|     void CreateDescriptorSetLayout(); | ||||
|     void CreateDescriptorSets(); | ||||
|     void CreatePipelineLayout(); | ||||
| @@ -91,6 +95,7 @@ private: | ||||
|     void CreateRawImages(const Tegra::FramebufferConfig& framebuffer); | ||||
|  | ||||
|     void UpdateDescriptorSet(std::size_t image_index, VkImageView image_view, bool nn) const; | ||||
|     void UpdateAADescriptorSet(std::size_t image_index, VkImageView image_view, bool nn) const; | ||||
|     void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const; | ||||
|     void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, | ||||
|                        const Layout::FramebufferLayout layout) const; | ||||
| @@ -109,6 +114,8 @@ private: | ||||
|     const VKScreenInfo& screen_info; | ||||
|  | ||||
|     vk::ShaderModule vertex_shader; | ||||
|     vk::ShaderModule fxaa_vertex_shader; | ||||
|     vk::ShaderModule fxaa_fragment_shader; | ||||
|     vk::ShaderModule bilinear_fragment_shader; | ||||
|     vk::ShaderModule bicubic_fragment_shader; | ||||
|     vk::ShaderModule gaussian_fragment_shader; | ||||
| @@ -116,6 +123,7 @@ private: | ||||
|     vk::DescriptorPool descriptor_pool; | ||||
|     vk::DescriptorSetLayout descriptor_set_layout; | ||||
|     vk::PipelineLayout pipeline_layout; | ||||
|     vk::Pipeline aa_pipeline; | ||||
|     vk::Pipeline nearest_neightbor_pipeline; | ||||
|     vk::Pipeline bilinear_pipeline; | ||||
|     vk::Pipeline bicubic_pipeline; | ||||
| @@ -136,6 +144,15 @@ private: | ||||
|     std::vector<vk::Image> raw_images; | ||||
|     std::vector<vk::ImageView> raw_image_views; | ||||
|     std::vector<MemoryCommit> raw_buffer_commits; | ||||
|     vk::Image aa_image; | ||||
|     vk::ImageView aa_image_view; | ||||
|     MemoryCommit aa_commit; | ||||
|     vk::Framebuffer aa_framebuffer; | ||||
|     vk::RenderPass aa_renderpass; | ||||
|     vk::DescriptorSets aa_descriptor_sets; | ||||
|     vk::DescriptorPool aa_descriptor_pool; | ||||
|     vk::DescriptorSetLayout aa_descriptor_set_layout; | ||||
|     vk::PipelineLayout aa_pipeline_layout; | ||||
|     u32 raw_width = 0; | ||||
|     u32 raw_height = 0; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user