diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/host_shaders/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/host_shaders/fxaa.frag | 72 | ||||
| -rw-r--r-- | src/video_core/host_shaders/fxaa.vert | 40 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 109 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 4 | 
6 files changed, 194 insertions, 35 deletions
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index b0e15773c..6b5ea649a 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -13,6 +13,8 @@ set(SHADER_FILES      convert_depth_to_float.frag      convert_float_to_depth.frag      full_screen_triangle.vert +    fxaa.frag +    fxaa.vert      opengl_copy_bc4.comp      opengl_present.frag      opengl_present.vert diff --git a/src/video_core/host_shaders/fxaa.frag b/src/video_core/host_shaders/fxaa.frag new file mode 100644 index 000000000..23f910d4c --- /dev/null +++ b/src/video_core/host_shaders/fxaa.frag @@ -0,0 +1,72 @@ +// Adapted from +// https://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/ + +#version 460 + +#ifdef VULKAN + +#define BINDING_COLOR_TEXTURE 1 + +#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv + +#define BINDING_COLOR_TEXTURE 0 + +#endif + +layout (location = 0) in vec4 posPos; + +layout (location = 0) out vec4 frag_color; + +layout (binding = BINDING_COLOR_TEXTURE) uniform sampler2D input_texture; + +const float FXAA_SPAN_MAX = 8.0; +const float FXAA_REDUCE_MUL = 1.0 / 8.0; +const float FXAA_REDUCE_MIN = 1.0 / 128.0; + +#define FxaaTexLod0(t, p) textureLod(t, p, 0.0) +#define FxaaTexOff(t, p, o) textureLodOffset(t, p, 0.0, o) + +vec3 FxaaPixelShader(vec4 posPos, sampler2D tex) { + +    vec3 rgbNW = FxaaTexLod0(tex, posPos.zw).xyz; +    vec3 rgbNE = FxaaTexOff(tex, posPos.zw, ivec2(1,0)).xyz; +    vec3 rgbSW = FxaaTexOff(tex, posPos.zw, ivec2(0,1)).xyz; +    vec3 rgbSE = FxaaTexOff(tex, posPos.zw, ivec2(1,1)).xyz; +    vec3 rgbM  = FxaaTexLod0(tex, posPos.xy).xyz; +/*---------------------------------------------------------*/ +    vec3 luma = vec3(0.299, 0.587, 0.114); +    float lumaNW = dot(rgbNW, luma); +    float lumaNE = dot(rgbNE, luma); +    float lumaSW = dot(rgbSW, luma); +    float lumaSE = dot(rgbSE, luma); +    float lumaM  = dot(rgbM,  luma); +/*---------------------------------------------------------*/ +    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); +    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); +/*---------------------------------------------------------*/ +    vec2 dir; +    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); +    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE)); +/*---------------------------------------------------------*/ +    float dirReduce = max( +        (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), +        FXAA_REDUCE_MIN); +    float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); +    dir = min(vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX), +          max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), +          dir * rcpDirMin)) / textureSize(tex, 0); +/*--------------------------------------------------------*/ +    vec3 rgbA = (1.0 / 2.0) * ( +        FxaaTexLod0(tex, posPos.xy + dir * (1.0 / 3.0 - 0.5)).xyz + +        FxaaTexLod0(tex, posPos.xy + dir * (2.0 / 3.0 - 0.5)).xyz); +    vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * ( +        FxaaTexLod0(tex, posPos.xy + dir * (0.0 / 3.0 - 0.5)).xyz + +        FxaaTexLod0(tex, posPos.xy + dir * (3.0 / 3.0 - 0.5)).xyz); +    float lumaB = dot(rgbB, luma); +    if((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA; +    return rgbB; +} + +void main() { +  frag_color = vec4(FxaaPixelShader(posPos, input_texture), 1.0); +} diff --git a/src/video_core/host_shaders/fxaa.vert b/src/video_core/host_shaders/fxaa.vert new file mode 100644 index 000000000..715fce462 --- /dev/null +++ b/src/video_core/host_shaders/fxaa.vert @@ -0,0 +1,40 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#version 460 + +out gl_PerVertex { +    vec4 gl_Position; +}; + +const vec2 vertices[4] = +    vec2[4](vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, -1.0)); + +layout (location = 0) out vec4 posPos; + +#ifdef VULKAN + +#define BINDING_COLOR_TEXTURE 1 + +#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv + +#define BINDING_COLOR_TEXTURE 0 + +#endif + +layout (binding = BINDING_COLOR_TEXTURE) uniform sampler2D input_texture; + +const float FXAA_SUBPIX_SHIFT = 0; + +void main() { +#ifdef VULKAN +  vec2 vertex = vertices[gl_VertexIndex]; +#else +  vec2 vertex = vertices[gl_VertexID]; +#endif +  gl_Position = vec4(vertex, 0.0, 1.0); +  vec2 vert_tex_coord = (vertex + 1.0) / 2.0; +  posPos.xy = vert_tex_coord; +  posPos.zw = vert_tex_coord - (0.5 + FXAA_SUBPIX_SHIFT) / textureSize(input_texture, 0); +} diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index 8695c29e3..70947838c 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp @@ -166,7 +166,7 @@ void OGLFramebuffer::Create() {          return;      MICROPROFILE_SCOPE(OpenGL_ResourceCreation); -    glGenFramebuffers(1, &handle); +    glCreateFramebuffers(1, &handle);  }  void OGLFramebuffer::Release() { diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 227697c4f..dbe66a1b6 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -21,6 +21,8 @@  #include "core/memory.h"  #include "core/perf_stats.h"  #include "core/telemetry_session.h" +#include "video_core/host_shaders/fxaa_frag.h" +#include "video_core/host_shaders/fxaa_vert.h"  #include "video_core/host_shaders/opengl_present_frag.h"  #include "video_core/host_shaders/opengl_present_vert.h"  #include "video_core/host_shaders/present_bicubic_frag.h" @@ -254,6 +256,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color  void RendererOpenGL::InitOpenGLObjects() {      // Create shader programs +    fxaa_vertex = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER); +    fxaa_fragment = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER);      present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);      present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER);      present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER); @@ -287,6 +291,8 @@ void RendererOpenGL::InitOpenGLObjects() {      // Clear screen to black      LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); + +    fxaa_framebuffer.Create();  }  void RendererOpenGL::AddTelemetryFields() { @@ -338,14 +344,83 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,      texture.resource.Release();      texture.resource.Create(GL_TEXTURE_2D);      glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); +    fxaa_texture.Release(); +    fxaa_texture.Create(GL_TEXTURE_2D); +    glTextureStorage2D(fxaa_texture.handle, 1, GL_RGBA16F, texture.width, texture.height); +    glNamedFramebufferTexture(fxaa_framebuffer.handle, GL_COLOR_ATTACHMENT0, fxaa_texture.handle, +                              0);  }  void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { +    // TODO: Signal state tracker about these changes +    state_tracker.NotifyScreenDrawVertexArray(); +    state_tracker.NotifyPolygonModes(); +    state_tracker.NotifyViewport0(); +    state_tracker.NotifyScissor0(); +    state_tracker.NotifyColorMask(0); +    state_tracker.NotifyBlend0(); +    state_tracker.NotifyFramebuffer(); +    state_tracker.NotifyFrontFace(); +    state_tracker.NotifyCullTest(); +    state_tracker.NotifyDepthTest(); +    state_tracker.NotifyStencilTest(); +    state_tracker.NotifyPolygonOffset(); +    state_tracker.NotifyRasterizeEnable(); +    state_tracker.NotifyFramebufferSRGB(); +    state_tracker.NotifyLogicOp(); +    state_tracker.NotifyClipControl(); +    state_tracker.NotifyAlphaTest(); + +    state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); +      // Update background color before drawing      glClearColor(Settings::values.bg_red.GetValue() / 255.0f,                   Settings::values.bg_green.GetValue() / 255.0f,                   Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); +    glEnable(GL_CULL_FACE); +    glDisable(GL_COLOR_LOGIC_OP); +    glDisable(GL_DEPTH_TEST); +    glDisable(GL_STENCIL_TEST); +    glDisable(GL_POLYGON_OFFSET_FILL); +    glDisable(GL_RASTERIZER_DISCARD); +    glDisable(GL_ALPHA_TEST); +    glDisablei(GL_BLEND, 0); +    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +    glCullFace(GL_BACK); +    glFrontFace(GL_CW); +    glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + +    glBindTextureUnit(0, screen_info.display_texture); + +    if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa) { +        program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle); + +        glEnablei(GL_SCISSOR_TEST, 0); +        glScissorIndexed(0, 0, 0, +                         framebuffer_crop_rect.GetWidth() != 0 ? framebuffer_crop_rect.GetWidth() +                                                               : screen_info.texture.width, +                         framebuffer_crop_rect.GetHeight() != 0 ? framebuffer_crop_rect.GetHeight() +                                                                : screen_info.texture.height); +        glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(screen_info.texture.width), +                           static_cast<GLfloat>(screen_info.texture.height)); +        glDepthRangeIndexed(0, 0.0, 0.0); + +        glBindSampler(0, present_sampler.handle); +        GLint old_read_fb; +        GLint old_draw_fb; +        glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); +        glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); +        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fxaa_framebuffer.handle); + +        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + +        glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); +        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); + +        glBindTextureUnit(0, fxaa_texture.handle); +    } +      // Set projection matrix      const std::array ortho_matrix =          MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); @@ -422,47 +497,14 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {      };      glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); -    // TODO: Signal state tracker about these changes -    state_tracker.NotifyScreenDrawVertexArray(); -    state_tracker.NotifyPolygonModes(); -    state_tracker.NotifyViewport0(); -    state_tracker.NotifyScissor0(); -    state_tracker.NotifyColorMask(0); -    state_tracker.NotifyBlend0(); -    state_tracker.NotifyFramebuffer(); -    state_tracker.NotifyFrontFace(); -    state_tracker.NotifyCullTest(); -    state_tracker.NotifyDepthTest(); -    state_tracker.NotifyStencilTest(); -    state_tracker.NotifyPolygonOffset(); -    state_tracker.NotifyRasterizeEnable(); -    state_tracker.NotifyFramebufferSRGB(); -    state_tracker.NotifyLogicOp(); -    state_tracker.NotifyClipControl(); -    state_tracker.NotifyAlphaTest(); - -    state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); -    glEnable(GL_CULL_FACE);      if (screen_info.display_srgb) {          glEnable(GL_FRAMEBUFFER_SRGB);      } else {          glDisable(GL_FRAMEBUFFER_SRGB);      } -    glDisable(GL_COLOR_LOGIC_OP); -    glDisable(GL_DEPTH_TEST); -    glDisable(GL_STENCIL_TEST); -    glDisable(GL_POLYGON_OFFSET_FILL); -    glDisable(GL_RASTERIZER_DISCARD); -    glDisable(GL_ALPHA_TEST); -    glDisablei(GL_BLEND, 0);      glDisablei(GL_SCISSOR_TEST, 0); -    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -    glCullFace(GL_BACK); -    glFrontFace(GL_CW); -    glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);      glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width),                         static_cast<GLfloat>(layout.height)); -    glDepthRangeIndexed(0, 0.0, 0.0);      glEnableVertexAttribArray(PositionLocation);      glEnableVertexAttribArray(TexCoordLocation); @@ -482,7 +524,6 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {          glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));      } -    glBindTextureUnit(0, screen_info.display_texture);      if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {          glBindSampler(0, present_sampler.handle);      } else { diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 62a746e41..f6c66f804 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -111,6 +111,8 @@ private:      OGLSampler present_sampler;      OGLSampler present_sampler_nn;      OGLBuffer vertex_buffer; +    OGLProgram fxaa_vertex; +    OGLProgram fxaa_fragment;      OGLProgram present_vertex;      OGLProgram present_bilinear_fragment;      OGLProgram present_bicubic_fragment; @@ -123,6 +125,8 @@ private:      /// Display information for Switch screen      ScreenInfo screen_info; +    OGLTexture fxaa_texture; +    OGLFramebuffer fxaa_framebuffer;      /// OpenGL framebuffer data      std::vector<u8> gl_framebuffer_data;  | 
