1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "video_core/fsr.h"
#include "video_core/renderer_opengl/gl_fsr.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
namespace OpenGL {
using namespace FSR;
using FsrConstants = std::array<u32, 4 * 4>;
FSR::FSR(std::string_view fsr_vertex_source, std::string_view fsr_easu_source,
std::string_view fsr_rcas_source)
: fsr_vertex{CreateProgram(fsr_vertex_source, GL_VERTEX_SHADER)},
fsr_easu_frag{CreateProgram(fsr_easu_source, GL_FRAGMENT_SHADER)},
fsr_rcas_frag{CreateProgram(fsr_rcas_source, GL_FRAGMENT_SHADER)} {
glProgramUniform2f(fsr_vertex.handle, 0, 1.0f, 1.0f);
glProgramUniform2f(fsr_vertex.handle, 1, 0.0f, 0.0f);
}
FSR::~FSR() = default;
void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
u32 input_image_width, u32 input_image_height,
const Common::Rectangle<f32>& crop_rect) {
const auto output_image_width = screen.GetWidth();
const auto output_image_height = screen.GetHeight();
if (fsr_intermediate_tex.handle) {
GLint fsr_tex_width, fsr_tex_height;
glGetTextureLevelParameteriv(fsr_intermediate_tex.handle, 0, GL_TEXTURE_WIDTH,
&fsr_tex_width);
glGetTextureLevelParameteriv(fsr_intermediate_tex.handle, 0, GL_TEXTURE_HEIGHT,
&fsr_tex_height);
if (static_cast<u32>(fsr_tex_width) != output_image_width ||
static_cast<u32>(fsr_tex_height) != output_image_height) {
fsr_intermediate_tex.Release();
}
}
if (!fsr_intermediate_tex.handle) {
fsr_intermediate_tex.Create(GL_TEXTURE_2D);
glTextureStorage2D(fsr_intermediate_tex.handle, 1, GL_RGB16F, output_image_width,
output_image_height);
glNamedFramebufferTexture(fsr_framebuffer.handle, GL_COLOR_ATTACHMENT0,
fsr_intermediate_tex.handle, 0);
}
GLint old_draw_fb;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
glFrontFace(GL_CW);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fsr_framebuffer.handle);
glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width),
static_cast<GLfloat>(output_image_height));
const f32 input_width = static_cast<f32>(input_image_width);
const f32 input_height = static_cast<f32>(input_image_height);
const f32 output_width = static_cast<f32>(screen.GetWidth());
const f32 output_height = static_cast<f32>(screen.GetHeight());
const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width;
const f32 viewport_x = crop_rect.left * input_width;
const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height;
const f32 viewport_y = crop_rect.top * input_height;
FsrConstants constants;
FsrEasuConOffset(constants.data() + 0, constants.data() + 4, constants.data() + 8,
constants.data() + 12, viewport_width, viewport_height, input_width,
input_height, output_width, output_height, viewport_x, viewport_y);
glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants));
program_manager.BindPresentPrograms(fsr_vertex.handle, fsr_easu_frag.handle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
glBindTextureUnit(0, fsr_intermediate_tex.handle);
const float sharpening =
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
FsrRcasCon(constants.data(), sharpening);
glProgramUniform4uiv(fsr_rcas_frag.handle, 0, sizeof(constants), std::data(constants));
}
void FSR::InitBuffers() {
fsr_framebuffer.Create();
}
void FSR::ReleaseBuffers() {
fsr_framebuffer.Release();
fsr_intermediate_tex.Release();
}
const OGLProgram& FSR::GetPresentFragmentProgram() const noexcept {
return fsr_rcas_frag;
}
bool FSR::AreBuffersInitialized() const noexcept {
return fsr_framebuffer.handle;
}
} // namespace OpenGL
|