summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Marshall Mohror2021-10-20 18:36:06 -0500
committerGravatar Fernando Sahmkow2021-11-16 22:11:32 +0100
commit48cf3764626e1ed30450d15e00befb75a4eae329 (patch)
treed05aa128a7b07349ceb09ebbf515682036fbea9c /src
parentFrontend: Add anti-aliasing method setting (diff)
downloadyuzu-48cf3764626e1ed30450d15e00befb75a4eae329.tar.gz
yuzu-48cf3764626e1ed30450d15e00befb75a4eae329.tar.xz
yuzu-48cf3764626e1ed30450d15e00befb75a4eae329.zip
OpenGL: Implement FXAA
Diffstat (limited to 'src')
-rw-r--r--src/video_core/host_shaders/CMakeLists.txt2
-rw-r--r--src/video_core/host_shaders/fxaa.frag72
-rw-r--r--src/video_core/host_shaders/fxaa.vert40
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.cpp2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp109
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h4
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
13 convert_depth_to_float.frag 13 convert_depth_to_float.frag
14 convert_float_to_depth.frag 14 convert_float_to_depth.frag
15 full_screen_triangle.vert 15 full_screen_triangle.vert
16 fxaa.frag
17 fxaa.vert
16 opengl_copy_bc4.comp 18 opengl_copy_bc4.comp
17 opengl_present.frag 19 opengl_present.frag
18 opengl_present.vert 20 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 @@
1// Adapted from
2// https://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/
3
4#version 460
5
6#ifdef VULKAN
7
8#define BINDING_COLOR_TEXTURE 1
9
10#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
11
12#define BINDING_COLOR_TEXTURE 0
13
14#endif
15
16layout (location = 0) in vec4 posPos;
17
18layout (location = 0) out vec4 frag_color;
19
20layout (binding = BINDING_COLOR_TEXTURE) uniform sampler2D input_texture;
21
22const float FXAA_SPAN_MAX = 8.0;
23const float FXAA_REDUCE_MUL = 1.0 / 8.0;
24const float FXAA_REDUCE_MIN = 1.0 / 128.0;
25
26#define FxaaTexLod0(t, p) textureLod(t, p, 0.0)
27#define FxaaTexOff(t, p, o) textureLodOffset(t, p, 0.0, o)
28
29vec3 FxaaPixelShader(vec4 posPos, sampler2D tex) {
30
31 vec3 rgbNW = FxaaTexLod0(tex, posPos.zw).xyz;
32 vec3 rgbNE = FxaaTexOff(tex, posPos.zw, ivec2(1,0)).xyz;
33 vec3 rgbSW = FxaaTexOff(tex, posPos.zw, ivec2(0,1)).xyz;
34 vec3 rgbSE = FxaaTexOff(tex, posPos.zw, ivec2(1,1)).xyz;
35 vec3 rgbM = FxaaTexLod0(tex, posPos.xy).xyz;
36/*---------------------------------------------------------*/
37 vec3 luma = vec3(0.299, 0.587, 0.114);
38 float lumaNW = dot(rgbNW, luma);
39 float lumaNE = dot(rgbNE, luma);
40 float lumaSW = dot(rgbSW, luma);
41 float lumaSE = dot(rgbSE, luma);
42 float lumaM = dot(rgbM, luma);
43/*---------------------------------------------------------*/
44 float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
45 float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
46/*---------------------------------------------------------*/
47 vec2 dir;
48 dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
49 dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
50/*---------------------------------------------------------*/
51 float dirReduce = max(
52 (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
53 FXAA_REDUCE_MIN);
54 float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
55 dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
56 max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
57 dir * rcpDirMin)) / textureSize(tex, 0);
58/*--------------------------------------------------------*/
59 vec3 rgbA = (1.0 / 2.0) * (
60 FxaaTexLod0(tex, posPos.xy + dir * (1.0 / 3.0 - 0.5)).xyz +
61 FxaaTexLod0(tex, posPos.xy + dir * (2.0 / 3.0 - 0.5)).xyz);
62 vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (
63 FxaaTexLod0(tex, posPos.xy + dir * (0.0 / 3.0 - 0.5)).xyz +
64 FxaaTexLod0(tex, posPos.xy + dir * (3.0 / 3.0 - 0.5)).xyz);
65 float lumaB = dot(rgbB, luma);
66 if((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA;
67 return rgbB;
68}
69
70void main() {
71 frag_color = vec4(FxaaPixelShader(posPos, input_texture), 1.0);
72}
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 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#version 460
6
7out gl_PerVertex {
8 vec4 gl_Position;
9};
10
11const vec2 vertices[4] =
12 vec2[4](vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, -1.0));
13
14layout (location = 0) out vec4 posPos;
15
16#ifdef VULKAN
17
18#define BINDING_COLOR_TEXTURE 1
19
20#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
21
22#define BINDING_COLOR_TEXTURE 0
23
24#endif
25
26layout (binding = BINDING_COLOR_TEXTURE) uniform sampler2D input_texture;
27
28const float FXAA_SUBPIX_SHIFT = 0;
29
30void main() {
31#ifdef VULKAN
32 vec2 vertex = vertices[gl_VertexIndex];
33#else
34 vec2 vertex = vertices[gl_VertexID];
35#endif
36 gl_Position = vec4(vertex, 0.0, 1.0);
37 vec2 vert_tex_coord = (vertex + 1.0) / 2.0;
38 posPos.xy = vert_tex_coord;
39 posPos.zw = vert_tex_coord - (0.5 + FXAA_SUBPIX_SHIFT) / textureSize(input_texture, 0);
40}
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() {
166 return; 166 return;
167 167
168 MICROPROFILE_SCOPE(OpenGL_ResourceCreation); 168 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
169 glGenFramebuffers(1, &handle); 169 glCreateFramebuffers(1, &handle);
170} 170}
171 171
172void OGLFramebuffer::Release() { 172void 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 @@
21#include "core/memory.h" 21#include "core/memory.h"
22#include "core/perf_stats.h" 22#include "core/perf_stats.h"
23#include "core/telemetry_session.h" 23#include "core/telemetry_session.h"
24#include "video_core/host_shaders/fxaa_frag.h"
25#include "video_core/host_shaders/fxaa_vert.h"
24#include "video_core/host_shaders/opengl_present_frag.h" 26#include "video_core/host_shaders/opengl_present_frag.h"
25#include "video_core/host_shaders/opengl_present_vert.h" 27#include "video_core/host_shaders/opengl_present_vert.h"
26#include "video_core/host_shaders/present_bicubic_frag.h" 28#include "video_core/host_shaders/present_bicubic_frag.h"
@@ -254,6 +256,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
254 256
255void RendererOpenGL::InitOpenGLObjects() { 257void RendererOpenGL::InitOpenGLObjects() {
256 // Create shader programs 258 // Create shader programs
259 fxaa_vertex = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER);
260 fxaa_fragment = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER);
257 present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); 261 present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER);
258 present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); 262 present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER);
259 present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER); 263 present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER);
@@ -287,6 +291,8 @@ void RendererOpenGL::InitOpenGLObjects() {
287 291
288 // Clear screen to black 292 // Clear screen to black
289 LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); 293 LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture);
294
295 fxaa_framebuffer.Create();
290} 296}
291 297
292void RendererOpenGL::AddTelemetryFields() { 298void RendererOpenGL::AddTelemetryFields() {
@@ -338,14 +344,83 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
338 texture.resource.Release(); 344 texture.resource.Release();
339 texture.resource.Create(GL_TEXTURE_2D); 345 texture.resource.Create(GL_TEXTURE_2D);
340 glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); 346 glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height);
347 fxaa_texture.Release();
348 fxaa_texture.Create(GL_TEXTURE_2D);
349 glTextureStorage2D(fxaa_texture.handle, 1, GL_RGBA16F, texture.width, texture.height);
350 glNamedFramebufferTexture(fxaa_framebuffer.handle, GL_COLOR_ATTACHMENT0, fxaa_texture.handle,
351 0);
341} 352}
342 353
343void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { 354void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
355 // TODO: Signal state tracker about these changes
356 state_tracker.NotifyScreenDrawVertexArray();
357 state_tracker.NotifyPolygonModes();
358 state_tracker.NotifyViewport0();
359 state_tracker.NotifyScissor0();
360 state_tracker.NotifyColorMask(0);
361 state_tracker.NotifyBlend0();
362 state_tracker.NotifyFramebuffer();
363 state_tracker.NotifyFrontFace();
364 state_tracker.NotifyCullTest();
365 state_tracker.NotifyDepthTest();
366 state_tracker.NotifyStencilTest();
367 state_tracker.NotifyPolygonOffset();
368 state_tracker.NotifyRasterizeEnable();
369 state_tracker.NotifyFramebufferSRGB();
370 state_tracker.NotifyLogicOp();
371 state_tracker.NotifyClipControl();
372 state_tracker.NotifyAlphaTest();
373
374 state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
375
344 // Update background color before drawing 376 // Update background color before drawing
345 glClearColor(Settings::values.bg_red.GetValue() / 255.0f, 377 glClearColor(Settings::values.bg_red.GetValue() / 255.0f,
346 Settings::values.bg_green.GetValue() / 255.0f, 378 Settings::values.bg_green.GetValue() / 255.0f,
347 Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); 379 Settings::values.bg_blue.GetValue() / 255.0f, 1.0f);
348 380
381 glEnable(GL_CULL_FACE);
382 glDisable(GL_COLOR_LOGIC_OP);
383 glDisable(GL_DEPTH_TEST);
384 glDisable(GL_STENCIL_TEST);
385 glDisable(GL_POLYGON_OFFSET_FILL);
386 glDisable(GL_RASTERIZER_DISCARD);
387 glDisable(GL_ALPHA_TEST);
388 glDisablei(GL_BLEND, 0);
389 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
390 glCullFace(GL_BACK);
391 glFrontFace(GL_CW);
392 glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
393
394 glBindTextureUnit(0, screen_info.display_texture);
395
396 if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa) {
397 program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle);
398
399 glEnablei(GL_SCISSOR_TEST, 0);
400 glScissorIndexed(0, 0, 0,
401 framebuffer_crop_rect.GetWidth() != 0 ? framebuffer_crop_rect.GetWidth()
402 : screen_info.texture.width,
403 framebuffer_crop_rect.GetHeight() != 0 ? framebuffer_crop_rect.GetHeight()
404 : screen_info.texture.height);
405 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(screen_info.texture.width),
406 static_cast<GLfloat>(screen_info.texture.height));
407 glDepthRangeIndexed(0, 0.0, 0.0);
408
409 glBindSampler(0, present_sampler.handle);
410 GLint old_read_fb;
411 GLint old_draw_fb;
412 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
413 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
414 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fxaa_framebuffer.handle);
415
416 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
417
418 glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
419 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
420
421 glBindTextureUnit(0, fxaa_texture.handle);
422 }
423
349 // Set projection matrix 424 // Set projection matrix
350 const std::array ortho_matrix = 425 const std::array ortho_matrix =
351 MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); 426 MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
@@ -422,47 +497,14 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
422 }; 497 };
423 glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); 498 glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
424 499
425 // TODO: Signal state tracker about these changes
426 state_tracker.NotifyScreenDrawVertexArray();
427 state_tracker.NotifyPolygonModes();
428 state_tracker.NotifyViewport0();
429 state_tracker.NotifyScissor0();
430 state_tracker.NotifyColorMask(0);
431 state_tracker.NotifyBlend0();
432 state_tracker.NotifyFramebuffer();
433 state_tracker.NotifyFrontFace();
434 state_tracker.NotifyCullTest();
435 state_tracker.NotifyDepthTest();
436 state_tracker.NotifyStencilTest();
437 state_tracker.NotifyPolygonOffset();
438 state_tracker.NotifyRasterizeEnable();
439 state_tracker.NotifyFramebufferSRGB();
440 state_tracker.NotifyLogicOp();
441 state_tracker.NotifyClipControl();
442 state_tracker.NotifyAlphaTest();
443
444 state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);
445 glEnable(GL_CULL_FACE);
446 if (screen_info.display_srgb) { 500 if (screen_info.display_srgb) {
447 glEnable(GL_FRAMEBUFFER_SRGB); 501 glEnable(GL_FRAMEBUFFER_SRGB);
448 } else { 502 } else {
449 glDisable(GL_FRAMEBUFFER_SRGB); 503 glDisable(GL_FRAMEBUFFER_SRGB);
450 } 504 }
451 glDisable(GL_COLOR_LOGIC_OP);
452 glDisable(GL_DEPTH_TEST);
453 glDisable(GL_STENCIL_TEST);
454 glDisable(GL_POLYGON_OFFSET_FILL);
455 glDisable(GL_RASTERIZER_DISCARD);
456 glDisable(GL_ALPHA_TEST);
457 glDisablei(GL_BLEND, 0);
458 glDisablei(GL_SCISSOR_TEST, 0); 505 glDisablei(GL_SCISSOR_TEST, 0);
459 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
460 glCullFace(GL_BACK);
461 glFrontFace(GL_CW);
462 glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
463 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width), 506 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width),
464 static_cast<GLfloat>(layout.height)); 507 static_cast<GLfloat>(layout.height));
465 glDepthRangeIndexed(0, 0.0, 0.0);
466 508
467 glEnableVertexAttribArray(PositionLocation); 509 glEnableVertexAttribArray(PositionLocation);
468 glEnableVertexAttribArray(TexCoordLocation); 510 glEnableVertexAttribArray(TexCoordLocation);
@@ -482,7 +524,6 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
482 glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); 524 glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
483 } 525 }
484 526
485 glBindTextureUnit(0, screen_info.display_texture);
486 if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) { 527 if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
487 glBindSampler(0, present_sampler.handle); 528 glBindSampler(0, present_sampler.handle);
488 } else { 529 } 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:
111 OGLSampler present_sampler; 111 OGLSampler present_sampler;
112 OGLSampler present_sampler_nn; 112 OGLSampler present_sampler_nn;
113 OGLBuffer vertex_buffer; 113 OGLBuffer vertex_buffer;
114 OGLProgram fxaa_vertex;
115 OGLProgram fxaa_fragment;
114 OGLProgram present_vertex; 116 OGLProgram present_vertex;
115 OGLProgram present_bilinear_fragment; 117 OGLProgram present_bilinear_fragment;
116 OGLProgram present_bicubic_fragment; 118 OGLProgram present_bicubic_fragment;
@@ -123,6 +125,8 @@ private:
123 125
124 /// Display information for Switch screen 126 /// Display information for Switch screen
125 ScreenInfo screen_info; 127 ScreenInfo screen_info;
128 OGLTexture fxaa_texture;
129 OGLFramebuffer fxaa_framebuffer;
126 130
127 /// OpenGL framebuffer data 131 /// OpenGL framebuffer data
128 std::vector<u8> gl_framebuffer_data; 132 std::vector<u8> gl_framebuffer_data;