renderer_opengl: split out SMAA
This commit is contained in:
@@ -0,0 +1,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_shader_manager.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
#include "video_core/renderer_opengl/present/fsr.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
|
||||
@@ -0,0 +1,43 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/math_util.h"
|
||||
#include "video_core/fsr.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class ProgramManager;
|
||||
|
||||
class FSR {
|
||||
public:
|
||||
explicit FSR(std::string_view fsr_vertex_source, std::string_view fsr_easu_source,
|
||||
std::string_view fsr_rcas_source);
|
||||
~FSR();
|
||||
|
||||
void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
|
||||
u32 input_image_width, u32 input_image_height,
|
||||
const Common::Rectangle<f32>& crop_rect);
|
||||
|
||||
void InitBuffers();
|
||||
|
||||
void ReleaseBuffers();
|
||||
|
||||
[[nodiscard]] const OGLProgram& GetPresentFragmentProgram() const noexcept;
|
||||
|
||||
[[nodiscard]] bool AreBuffersInitialized() const noexcept;
|
||||
|
||||
private:
|
||||
OGLFramebuffer fsr_framebuffer;
|
||||
OGLProgram fsr_vertex;
|
||||
OGLProgram fsr_easu_frag;
|
||||
OGLProgram fsr_rcas_frag;
|
||||
OGLTexture fsr_intermediate_tex;
|
||||
};
|
||||
|
||||
} // namespace OpenGL
|
||||
@@ -0,0 +1,108 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "video_core/host_shaders/opengl_smaa_glsl.h"
|
||||
#include "video_core/host_shaders/smaa_blending_weight_calculation_frag.h"
|
||||
#include "video_core/host_shaders/smaa_blending_weight_calculation_vert.h"
|
||||
#include "video_core/host_shaders/smaa_edge_detection_frag.h"
|
||||
#include "video_core/host_shaders/smaa_edge_detection_vert.h"
|
||||
#include "video_core/host_shaders/smaa_neighborhood_blending_frag.h"
|
||||
#include "video_core/host_shaders/smaa_neighborhood_blending_vert.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_util.h"
|
||||
#include "video_core/renderer_opengl/present/smaa.h"
|
||||
#include "video_core/renderer_opengl/present/util.h"
|
||||
#include "video_core/smaa_area_tex.h"
|
||||
#include "video_core/smaa_search_tex.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
SMAA::SMAA(u32 width, u32 height) {
|
||||
const auto SmaaShader = [&](std::string_view specialized_source, GLenum stage) {
|
||||
std::string shader_source{specialized_source};
|
||||
ReplaceInclude(shader_source, "opengl_smaa.glsl", HostShaders::OPENGL_SMAA_GLSL);
|
||||
return CreateProgram(shader_source, stage);
|
||||
};
|
||||
|
||||
edge_detection_vert = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_VERT, GL_VERTEX_SHADER);
|
||||
edge_detection_frag = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_FRAG, GL_FRAGMENT_SHADER);
|
||||
blending_weight_calculation_vert =
|
||||
SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_VERT, GL_VERTEX_SHADER);
|
||||
blending_weight_calculation_frag =
|
||||
SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_FRAG, GL_FRAGMENT_SHADER);
|
||||
neighborhood_blending_vert =
|
||||
SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_VERT, GL_VERTEX_SHADER);
|
||||
neighborhood_blending_frag =
|
||||
SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_FRAG, GL_FRAGMENT_SHADER);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
area_tex.Create(GL_TEXTURE_2D);
|
||||
glTextureStorage2D(area_tex.handle, 1, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT);
|
||||
glTextureSubImage2D(area_tex.handle, 0, 0, 0, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG,
|
||||
GL_UNSIGNED_BYTE, areaTexBytes);
|
||||
search_tex.Create(GL_TEXTURE_2D);
|
||||
glTextureStorage2D(search_tex.handle, 1, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT);
|
||||
glTextureSubImage2D(search_tex.handle, 0, 0, 0, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_RED,
|
||||
GL_UNSIGNED_BYTE, searchTexBytes);
|
||||
|
||||
edges_tex.Create(GL_TEXTURE_2D);
|
||||
glTextureStorage2D(edges_tex.handle, 1, GL_RG16F, width, height);
|
||||
|
||||
blend_tex.Create(GL_TEXTURE_2D);
|
||||
glTextureStorage2D(blend_tex.handle, 1, GL_RGBA16F, width, height);
|
||||
|
||||
sampler = CreateBilinearSampler();
|
||||
|
||||
framebuffer.Create();
|
||||
|
||||
texture.Create(GL_TEXTURE_2D);
|
||||
glTextureStorage2D(texture.handle, 1, GL_RGBA16F, width, height);
|
||||
glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, texture.handle, 0);
|
||||
}
|
||||
|
||||
SMAA::~SMAA() = default;
|
||||
|
||||
GLuint SMAA::Draw(ProgramManager& program_manager, GLuint input_texture) {
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glFrontFace(GL_CCW);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer.handle);
|
||||
glBindSampler(0, sampler.handle);
|
||||
glBindSampler(1, sampler.handle);
|
||||
glBindSampler(2, sampler.handle);
|
||||
|
||||
glBindTextureUnit(0, input_texture);
|
||||
glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, edges_tex.handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
program_manager.BindPresentPrograms(edge_detection_vert.handle, edge_detection_frag.handle);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
glBindTextureUnit(0, edges_tex.handle);
|
||||
glBindTextureUnit(1, area_tex.handle);
|
||||
glBindTextureUnit(2, search_tex.handle);
|
||||
glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, blend_tex.handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
program_manager.BindPresentPrograms(blending_weight_calculation_vert.handle,
|
||||
blending_weight_calculation_frag.handle);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
glBindTextureUnit(0, input_texture);
|
||||
glBindTextureUnit(1, blend_tex.handle);
|
||||
glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, texture.handle, 0);
|
||||
program_manager.BindPresentPrograms(neighborhood_blending_vert.handle,
|
||||
neighborhood_blending_frag.handle);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glFrontFace(GL_CW);
|
||||
|
||||
return texture.handle;
|
||||
}
|
||||
|
||||
} // namespace OpenGL
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
class ProgramManager;
|
||||
|
||||
class SMAA {
|
||||
public:
|
||||
explicit SMAA(u32 width, u32 height);
|
||||
~SMAA();
|
||||
|
||||
GLuint Draw(ProgramManager& program_manager, GLuint input_texture);
|
||||
|
||||
private:
|
||||
OGLProgram edge_detection_vert;
|
||||
OGLProgram blending_weight_calculation_vert;
|
||||
OGLProgram neighborhood_blending_vert;
|
||||
OGLProgram edge_detection_frag;
|
||||
OGLProgram blending_weight_calculation_frag;
|
||||
OGLProgram neighborhood_blending_frag;
|
||||
OGLTexture area_tex;
|
||||
OGLTexture search_tex;
|
||||
OGLTexture edges_tex;
|
||||
OGLTexture blend_tex;
|
||||
OGLSampler sampler;
|
||||
OGLFramebuffer framebuffer;
|
||||
OGLTexture texture;
|
||||
};
|
||||
|
||||
} // namespace OpenGL
|
||||
@@ -0,0 +1,32 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
static inline void ReplaceInclude(std::string& shader_source, std::string_view include_name,
|
||||
std::string_view include_content) {
|
||||
const std::string include_string = fmt::format("#include \"{}\"", include_name);
|
||||
const std::size_t pos = shader_source.find(include_string);
|
||||
ASSERT(pos != std::string::npos);
|
||||
shader_source.replace(pos, include_string.size(), include_content);
|
||||
};
|
||||
|
||||
static inline OGLSampler CreateBilinearSampler() {
|
||||
OGLSampler sampler;
|
||||
sampler.Create();
|
||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
return sampler;
|
||||
}
|
||||
|
||||
} // namespace OpenGL
|
||||
Reference in New Issue
Block a user