mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-11-04 12:34:39 +08:00 
			
		
		
		
	Presentation: add Nearest Neighbor filter.
This commit is contained in:
		
							parent
							
								
									77b0812d69
								
							
						
					
					
						commit
						b60966041c
					
				@ -61,10 +61,11 @@ enum class ResolutionSetup : u32 {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class ScalingFilter : u32 {
 | 
			
		||||
    Bilinear = 0,
 | 
			
		||||
    Bicubic = 1,
 | 
			
		||||
    ScaleForce = 2,
 | 
			
		||||
    Fsr = 3,
 | 
			
		||||
    NearestNeighbor = 0,
 | 
			
		||||
    Bilinear = 1,
 | 
			
		||||
    Bicubic = 2,
 | 
			
		||||
    ScaleForce = 3,
 | 
			
		||||
    Fsr = 4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ResolutionScalingInfo {
 | 
			
		||||
 | 
			
		||||
@ -264,6 +264,10 @@ void RendererOpenGL::InitOpenGLObjects() {
 | 
			
		||||
    glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
			
		||||
    glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
			
		||||
 | 
			
		||||
    present_sampler_nn.Create();
 | 
			
		||||
    glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 | 
			
		||||
    glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 | 
			
		||||
 | 
			
		||||
    // Generate VBO handle for drawing
 | 
			
		||||
    vertex_buffer.Create();
 | 
			
		||||
 | 
			
		||||
@ -346,6 +350,9 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
 | 
			
		||||
    GLuint fragment_handle;
 | 
			
		||||
    const auto filter = Settings::values.scaling_filter.GetValue();
 | 
			
		||||
    switch (filter) {
 | 
			
		||||
    case Settings::ScalingFilter::NearestNeighbor:
 | 
			
		||||
        fragment_handle = present_bilinear_fragment.handle;
 | 
			
		||||
        break;
 | 
			
		||||
    case Settings::ScalingFilter::Bilinear:
 | 
			
		||||
        fragment_handle = present_bilinear_fragment.handle;
 | 
			
		||||
        break;
 | 
			
		||||
@ -355,6 +362,12 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
 | 
			
		||||
    case Settings::ScalingFilter::ScaleForce:
 | 
			
		||||
        fragment_handle = present_scaleforce_fragment.handle;
 | 
			
		||||
        break;
 | 
			
		||||
    case Settings::ScalingFilter::Fsr:
 | 
			
		||||
        LOG_WARNING(
 | 
			
		||||
            Render_OpenGL,
 | 
			
		||||
            "FidelityFX FSR Super Sampling is not supported in OpenGL, changing to ScaleForce");
 | 
			
		||||
        fragment_handle = present_scaleforce_fragment.handle;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        fragment_handle = present_bilinear_fragment.handle;
 | 
			
		||||
        break;
 | 
			
		||||
@ -464,7 +477,11 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    glBindTextureUnit(0, screen_info.display_texture);
 | 
			
		||||
    glBindSampler(0, present_sampler.handle);
 | 
			
		||||
    if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
 | 
			
		||||
        glBindSampler(0, present_sampler.handle);
 | 
			
		||||
    } else {
 | 
			
		||||
        glBindSampler(0, present_sampler_nn.handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    glClear(GL_COLOR_BUFFER_BIT);
 | 
			
		||||
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 | 
			
		||||
 | 
			
		||||
@ -109,6 +109,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    // OpenGL object IDs
 | 
			
		||||
    OGLSampler present_sampler;
 | 
			
		||||
    OGLSampler present_sampler_nn;
 | 
			
		||||
    OGLBuffer vertex_buffer;
 | 
			
		||||
    OGLProgram present_vertex;
 | 
			
		||||
    OGLProgram present_bilinear_fragment;
 | 
			
		||||
 | 
			
		||||
@ -152,7 +152,9 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
 | 
			
		||||
        use_accelerated ? screen_info.image_view : *raw_image_views[image_index];
 | 
			
		||||
 | 
			
		||||
    if (!fsr) {
 | 
			
		||||
        UpdateDescriptorSet(image_index, source_image_view);
 | 
			
		||||
        const bool is_nn =
 | 
			
		||||
            Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::NearestNeighbor;
 | 
			
		||||
        UpdateDescriptorSet(image_index, source_image_view, is_nn);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BufferData data;
 | 
			
		||||
@ -247,7 +249,7 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
 | 
			
		||||
        crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor);
 | 
			
		||||
        VkImageView fsr_image_view =
 | 
			
		||||
            fsr->Draw(scheduler, image_index, source_image_view, crop_rect);
 | 
			
		||||
        UpdateDescriptorSet(image_index, fsr_image_view);
 | 
			
		||||
        UpdateDescriptorSet(image_index, fsr_image_view, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scheduler.Record(
 | 
			
		||||
@ -286,6 +288,9 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
 | 
			
		||||
            const auto filter = Settings::values.scaling_filter.GetValue();
 | 
			
		||||
            cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
 | 
			
		||||
            switch (filter) {
 | 
			
		||||
            case Settings::ScalingFilter::NearestNeighbor:
 | 
			
		||||
                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline);
 | 
			
		||||
                break;
 | 
			
		||||
            case Settings::ScalingFilter::Bilinear:
 | 
			
		||||
                cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline);
 | 
			
		||||
                break;
 | 
			
		||||
@ -745,13 +750,33 @@ void VKBlitScreen::CreateGraphicsPipeline() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VKBlitScreen::CreateSampler() {
 | 
			
		||||
    bool linear = Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::Fsr;
 | 
			
		||||
    const VkSamplerCreateInfo ci{
 | 
			
		||||
        .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
 | 
			
		||||
        .pNext = nullptr,
 | 
			
		||||
        .flags = 0,
 | 
			
		||||
        .magFilter = linear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
 | 
			
		||||
        .minFilter = linear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST,
 | 
			
		||||
        .magFilter = VK_FILTER_LINEAR,
 | 
			
		||||
        .minFilter = VK_FILTER_LINEAR,
 | 
			
		||||
        .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
 | 
			
		||||
        .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
 | 
			
		||||
        .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
 | 
			
		||||
        .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
 | 
			
		||||
        .mipLodBias = 0.0f,
 | 
			
		||||
        .anisotropyEnable = VK_FALSE,
 | 
			
		||||
        .maxAnisotropy = 0.0f,
 | 
			
		||||
        .compareEnable = VK_FALSE,
 | 
			
		||||
        .compareOp = VK_COMPARE_OP_NEVER,
 | 
			
		||||
        .minLod = 0.0f,
 | 
			
		||||
        .maxLod = 0.0f,
 | 
			
		||||
        .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,
 | 
			
		||||
        .unnormalizedCoordinates = VK_FALSE,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const VkSamplerCreateInfo ci_nn{
 | 
			
		||||
        .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
 | 
			
		||||
        .pNext = nullptr,
 | 
			
		||||
        .flags = 0,
 | 
			
		||||
        .magFilter = VK_FILTER_NEAREST,
 | 
			
		||||
        .minFilter = VK_FILTER_NEAREST,
 | 
			
		||||
        .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
 | 
			
		||||
        .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
 | 
			
		||||
        .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
 | 
			
		||||
@ -768,6 +793,7 @@ void VKBlitScreen::CreateSampler() {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    sampler = device.GetLogical().CreateSampler(ci);
 | 
			
		||||
    nn_sampler = device.GetLogical().CreateSampler(ci_nn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VKBlitScreen::CreateFramebuffers() {
 | 
			
		||||
@ -862,7 +888,8 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const {
 | 
			
		||||
void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view,
 | 
			
		||||
                                       bool nn) const {
 | 
			
		||||
    const VkDescriptorBufferInfo buffer_info{
 | 
			
		||||
        .buffer = *buffer,
 | 
			
		||||
        .offset = offsetof(BufferData, uniform),
 | 
			
		||||
@ -883,7 +910,7 @@ void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView imag
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const VkDescriptorImageInfo image_info{
 | 
			
		||||
        .sampler = *sampler,
 | 
			
		||||
        .sampler = nn ? *nn_sampler : *sampler,
 | 
			
		||||
        .imageView = image_view,
 | 
			
		||||
        .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -90,7 +90,7 @@ private:
 | 
			
		||||
    void CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer);
 | 
			
		||||
    void CreateRawImages(const Tegra::FramebufferConfig& framebuffer);
 | 
			
		||||
 | 
			
		||||
    void UpdateDescriptorSet(std::size_t image_index, VkImageView image_view) const;
 | 
			
		||||
    void UpdateDescriptorSet(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;
 | 
			
		||||
@ -115,12 +115,14 @@ private:
 | 
			
		||||
    vk::DescriptorPool descriptor_pool;
 | 
			
		||||
    vk::DescriptorSetLayout descriptor_set_layout;
 | 
			
		||||
    vk::PipelineLayout pipeline_layout;
 | 
			
		||||
    vk::Pipeline nearest_neightbor_pipeline;
 | 
			
		||||
    vk::Pipeline bilinear_pipeline;
 | 
			
		||||
    vk::Pipeline bicubic_pipeline;
 | 
			
		||||
    vk::Pipeline scaleforce_pipeline;
 | 
			
		||||
    vk::RenderPass renderpass;
 | 
			
		||||
    std::vector<vk::Framebuffer> framebuffers;
 | 
			
		||||
    vk::DescriptorSets descriptor_sets;
 | 
			
		||||
    vk::Sampler nn_sampler;
 | 
			
		||||
    vk::Sampler sampler;
 | 
			
		||||
 | 
			
		||||
    vk::Buffer buffer;
 | 
			
		||||
 | 
			
		||||
@ -387,6 +387,11 @@
 | 
			
		||||
           </item>
 | 
			
		||||
           <item>
 | 
			
		||||
            <widget class="QComboBox" name="scaling_filter_combobox">
 | 
			
		||||
             <item>
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>Nearest Neighbor</string>
 | 
			
		||||
              </property>
 | 
			
		||||
             </item>
 | 
			
		||||
             <item>
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>Bilinear</string>
 | 
			
		||||
@ -404,7 +409,7 @@
 | 
			
		||||
             </item>
 | 
			
		||||
             <item>
 | 
			
		||||
              <property name="text">
 | 
			
		||||
               <string>FidelityFX Super Resolution</string>
 | 
			
		||||
               <string>FidelityFX Super Resolution [Vulkan Only]</string>
 | 
			
		||||
              </property>
 | 
			
		||||
             </item>
 | 
			
		||||
            </widget>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user