summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_blit_screen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl/gl_blit_screen.cpp')
-rw-r--r--src/video_core/renderer_opengl/gl_blit_screen.cpp272
1 files changed, 65 insertions, 207 deletions
diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp
index 5f6221b9b..f9dbef0fc 100644
--- a/src/video_core/renderer_opengl/gl_blit_screen.cpp
+++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp
@@ -2,100 +2,26 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "video_core/framebuffer_config.h"
-#include "video_core/host_shaders/ffx_a_h.h"
-#include "video_core/host_shaders/ffx_fsr1_h.h"
-#include "video_core/host_shaders/full_screen_triangle_vert.h"
-#include "video_core/host_shaders/opengl_fidelityfx_fsr_easu_frag.h"
-#include "video_core/host_shaders/opengl_fidelityfx_fsr_frag.h"
-#include "video_core/host_shaders/opengl_fidelityfx_fsr_rcas_frag.h"
-#include "video_core/host_shaders/opengl_present_frag.h"
-#include "video_core/host_shaders/opengl_present_scaleforce_frag.h"
-#include "video_core/host_shaders/opengl_present_vert.h"
-#include "video_core/host_shaders/present_bicubic_frag.h"
-#include "video_core/host_shaders/present_gaussian_frag.h"
-
#include "video_core/renderer_opengl/gl_blit_screen.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/gl_shader_util.h"
#include "video_core/renderer_opengl/gl_state_tracker.h"
+#include "video_core/renderer_opengl/present/filters.h"
#include "video_core/renderer_opengl/present/fsr.h"
#include "video_core/renderer_opengl/present/fxaa.h"
#include "video_core/renderer_opengl/present/smaa.h"
+#include "video_core/renderer_opengl/present/window_adapt_pass.h"
#include "video_core/textures/decoders.h"
namespace OpenGL {
-namespace {
-constexpr GLint PositionLocation = 0;
-constexpr GLint TexCoordLocation = 1;
-constexpr GLint ModelViewMatrixLocation = 0;
-
-struct ScreenRectVertex {
- constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v)
- : position{{static_cast<GLfloat>(x), static_cast<GLfloat>(y)}}, tex_coord{{u, v}} {}
-
- std::array<GLfloat, 2> position;
- std::array<GLfloat, 2> tex_coord;
-};
-
-/**
- * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
- * corner and (width, height) on the lower-bottom.
- *
- * The projection part of the matrix is trivial, hence these operations are represented
- * by a 3x2 matrix.
- */
-std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(float width, float height) {
- std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
-
- // clang-format off
- matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f;
- matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f;
- // Last matrix row is implicitly assumed to be [0, 0, 1].
- // clang-format on
-
- return matrix;
-}
-} // namespace
-
BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_,
Tegra::MaxwellDeviceMemoryManager& device_memory_,
StateTracker& state_tracker_, ProgramManager& program_manager_,
Device& device_)
: rasterizer(rasterizer_), device_memory(device_memory_), state_tracker(state_tracker_),
program_manager(program_manager_), device(device_) {
- // Create shader programs
- 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);
- present_gaussian_fragment =
- CreateProgram(HostShaders::PRESENT_GAUSSIAN_FRAG, GL_FRAGMENT_SHADER);
- present_scaleforce_fragment =
- CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG),
- GL_FRAGMENT_SHADER);
-
- // Generate presentation sampler
- present_sampler.Create();
- glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- 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);
- glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- // Generate VBO handle for drawing
- vertex_buffer.Create();
-
- // Attach vertex data to VAO
- glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
-
// Allocate textures for the screen
framebuffer_texture.resource.Create(GL_TEXTURE_2D);
@@ -106,15 +32,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_,
const u8 framebuffer_data[4] = {0, 0, 0, 0};
glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE,
framebuffer_data);
-
- // Enable unified vertex attributes and query vertex buffer address when the driver supports it
- if (device.HasVertexBufferUnifiedMemory()) {
- glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
- glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
- glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY);
- glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV,
- &vertex_buffer_address);
- }
}
BlitScreen::~BlitScreen() = default;
@@ -219,18 +136,14 @@ void BlitScreen::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& fra
glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format,
framebuffer_texture.width, framebuffer_texture.height);
- fxaa = std::make_unique<FXAA>(
- Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
- Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
- smaa = std::make_unique<SMAA>(
- Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
- Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
+ fxaa.reset();
+ smaa.reset();
}
void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
const Layout::FramebufferLayout& layout) {
FramebufferTextureInfo info = PrepareRenderTarget(framebuffer);
- const auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height);
+ auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height);
// TODO: Signal state tracker about these changes
state_tracker.NotifyScreenDrawVertexArray();
@@ -267,15 +180,14 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthRangeIndexed(0, 0.0, 0.0);
+ GLint old_read_fb;
+ GLint old_draw_fb;
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
+
GLuint texture = info.display_texture;
auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
- if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
- LOG_ERROR(Render_OpenGL, "Invalid antialiasing option selected {}", anti_aliasing);
- anti_aliasing = Settings::AntiAliasing::None;
- Settings::values.anti_aliasing.SetValue(anti_aliasing);
- }
-
if (anti_aliasing != Settings::AntiAliasing::None) {
glEnablei(GL_SCISSOR_TEST, 0);
auto scissor_width = Settings::values.resolution_info.ScaleUp(framebuffer_texture.width);
@@ -286,137 +198,83 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
glScissorIndexed(0, 0, 0, scissor_width, scissor_height);
glViewportIndexedf(0, 0.0f, 0.0f, viewport_width, viewport_height);
- 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);
-
switch (anti_aliasing) {
- case Settings::AntiAliasing::Fxaa: {
+ case Settings::AntiAliasing::Fxaa:
+ CreateFXAA();
texture = fxaa->Draw(program_manager, info.display_texture);
- } break;
- case Settings::AntiAliasing::Smaa: {
- texture = smaa->Draw(program_manager, info.display_texture);
- } break;
+ break;
+ case Settings::AntiAliasing::Smaa:
default:
- UNREACHABLE();
+ CreateSMAA();
+ texture = smaa->Draw(program_manager, info.display_texture);
+ break;
}
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
}
+
glDisablei(GL_SCISSOR_TEST, 0);
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
- GLint old_read_fb;
- GLint old_draw_fb;
- glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
- glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
-
if (!fsr || fsr->NeedsRecreation(layout.screen)) {
fsr = std::make_unique<FSR>(layout.screen.GetWidth(), layout.screen.GetHeight());
}
texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop);
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
+ crop = {0, 0, 1, 1};
}
- glBindTextureUnit(0, texture);
-
- const std::array ortho_matrix =
- MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
-
- const auto fragment_handle = [this]() {
- switch (Settings::values.scaling_filter.GetValue()) {
- case Settings::ScalingFilter::Bicubic:
- return present_bicubic_fragment.handle;
- case Settings::ScalingFilter::Gaussian:
- return present_gaussian_fragment.handle;
- case Settings::ScalingFilter::ScaleForce:
- return present_scaleforce_fragment.handle;
- case Settings::ScalingFilter::NearestNeighbor:
- case Settings::ScalingFilter::Bilinear:
- case Settings::ScalingFilter::Fsr:
- default:
- return present_bilinear_fragment.handle;
- }
- }();
- program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle);
- glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
- ortho_matrix.data());
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
- f32 left, top, right, bottom;
- if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
- // FSR has already applied the crop, so we just want to render the image
- // it has produced.
- left = 0;
- top = 0;
- right = 1;
- bottom = 1;
- } else {
- // Apply the precomputed crop.
- left = crop.left;
- top = crop.top;
- right = crop.right;
- bottom = crop.bottom;
- }
+ CreateWindowAdapt();
+ window_adapt->DrawToFramebuffer(program_manager, texture, layout, crop);
- // Map the coordinates to the screen.
- const auto& screen = layout.screen;
- const auto x = screen.left;
- const auto y = screen.top;
- const auto w = screen.GetWidth();
- const auto h = screen.GetHeight();
-
- const std::array vertices = {
- ScreenRectVertex(x, y, left, top),
- ScreenRectVertex(x + w, y, right, top),
- ScreenRectVertex(x, y + h, left, bottom),
- ScreenRectVertex(x + w, y + h, right, bottom),
- };
- glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
-
- glDisable(GL_FRAMEBUFFER_SRGB);
- glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width),
- static_cast<GLfloat>(layout.height));
-
- glEnableVertexAttribArray(PositionLocation);
- glEnableVertexAttribArray(TexCoordLocation);
- glVertexAttribDivisor(PositionLocation, 0);
- glVertexAttribDivisor(TexCoordLocation, 0);
- glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE,
- offsetof(ScreenRectVertex, position));
- glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE,
- offsetof(ScreenRectVertex, tex_coord));
- glVertexAttribBinding(PositionLocation, 0);
- glVertexAttribBinding(TexCoordLocation, 0);
- if (device.HasVertexBufferUnifiedMemory()) {
- glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex));
- glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address,
- sizeof(vertices));
- } else {
- glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
- }
+ // TODO
+ // program_manager.RestoreGuestPipeline();
+}
- if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
- glBindSampler(0, present_sampler.handle);
- } else {
- glBindSampler(0, present_sampler_nn.handle);
+void BlitScreen::CreateFXAA() {
+ smaa.reset();
+ if (!fxaa) {
+ fxaa = std::make_unique<FXAA>(
+ Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
+ Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
}
+}
- // 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);
+void BlitScreen::CreateSMAA() {
+ fxaa.reset();
+ if (!smaa) {
+ smaa = std::make_unique<SMAA>(
+ Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
+ Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
+ }
+}
- glClear(GL_COLOR_BUFFER_BIT);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+void BlitScreen::CreateWindowAdapt() {
+ if (window_adapt && Settings::values.scaling_filter.GetValue() == current_window_adapt) {
+ return;
+ }
- // TODO
- // program_manager.RestoreGuestPipeline();
+ current_window_adapt = Settings::values.scaling_filter.GetValue();
+ switch (current_window_adapt) {
+ case Settings::ScalingFilter::NearestNeighbor:
+ window_adapt = MakeNearestNeighbor(device);
+ break;
+ case Settings::ScalingFilter::Bicubic:
+ window_adapt = MakeBicubic(device);
+ break;
+ case Settings::ScalingFilter::Gaussian:
+ window_adapt = MakeGaussian(device);
+ break;
+ case Settings::ScalingFilter::ScaleForce:
+ window_adapt = MakeScaleForce(device);
+ break;
+ case Settings::ScalingFilter::Fsr:
+ case Settings::ScalingFilter::Bilinear:
+ default:
+ window_adapt = MakeBilinear(device);
+ break;
+ }
}
} // namespace OpenGL