forked from suyu/suyu
renderer_opengl: move out ownership of FSR resources
This commit is contained in:
parent
2ed9586130
commit
dd2918efd8
3 changed files with 77 additions and 103 deletions
|
@ -75,8 +75,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_,
|
||||||
CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG),
|
CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG),
|
||||||
GL_FRAGMENT_SHADER);
|
GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
fsr = std::make_unique<FSR>();
|
|
||||||
|
|
||||||
// Generate presentation sampler
|
// Generate presentation sampler
|
||||||
present_sampler.Create();
|
present_sampler.Create();
|
||||||
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
@ -269,7 +267,7 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
|
||||||
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
glDepthRangeIndexed(0, 0.0, 0.0);
|
glDepthRangeIndexed(0, 0.0, 0.0);
|
||||||
|
|
||||||
glBindTextureUnit(0, info.display_texture);
|
GLuint texture = info.display_texture;
|
||||||
|
|
||||||
auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
|
auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
|
||||||
if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
|
if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
|
||||||
|
@ -296,10 +294,10 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
|
||||||
|
|
||||||
switch (anti_aliasing) {
|
switch (anti_aliasing) {
|
||||||
case Settings::AntiAliasing::Fxaa: {
|
case Settings::AntiAliasing::Fxaa: {
|
||||||
glBindTextureUnit(0, fxaa->Draw(program_manager, info.display_texture));
|
texture = fxaa->Draw(program_manager, info.display_texture);
|
||||||
} break;
|
} break;
|
||||||
case Settings::AntiAliasing::Smaa: {
|
case Settings::AntiAliasing::Smaa: {
|
||||||
glBindTextureUnit(0, smaa->Draw(program_manager, info.display_texture));
|
texture = smaa->Draw(program_manager, info.display_texture);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -311,34 +309,37 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
|
||||||
glDisablei(GL_SCISSOR_TEST, 0);
|
glDisablei(GL_SCISSOR_TEST, 0);
|
||||||
|
|
||||||
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
|
if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
|
||||||
if (!fsr->AreBuffersInitialized()) {
|
GLint old_read_fb;
|
||||||
fsr->InitBuffers();
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindSampler(0, present_sampler.handle);
|
texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop);
|
||||||
fsr->Draw(program_manager, layout.screen, info.scaled_width, info.scaled_height, crop);
|
|
||||||
} else {
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
|
||||||
if (fsr->AreBuffersInitialized()) {
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
|
||||||
fsr->ReleaseBuffers();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glBindTextureUnit(0, texture);
|
||||||
|
|
||||||
const std::array ortho_matrix =
|
const std::array ortho_matrix =
|
||||||
MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
|
MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
|
||||||
|
|
||||||
const auto fragment_handle = [this]() {
|
const auto fragment_handle = [this]() {
|
||||||
switch (Settings::values.scaling_filter.GetValue()) {
|
switch (Settings::values.scaling_filter.GetValue()) {
|
||||||
case Settings::ScalingFilter::NearestNeighbor:
|
|
||||||
case Settings::ScalingFilter::Bilinear:
|
|
||||||
return present_bilinear_fragment.handle;
|
|
||||||
case Settings::ScalingFilter::Bicubic:
|
case Settings::ScalingFilter::Bicubic:
|
||||||
return present_bicubic_fragment.handle;
|
return present_bicubic_fragment.handle;
|
||||||
case Settings::ScalingFilter::Gaussian:
|
case Settings::ScalingFilter::Gaussian:
|
||||||
return present_gaussian_fragment.handle;
|
return present_gaussian_fragment.handle;
|
||||||
case Settings::ScalingFilter::ScaleForce:
|
case Settings::ScalingFilter::ScaleForce:
|
||||||
return present_scaleforce_fragment.handle;
|
return present_scaleforce_fragment.handle;
|
||||||
|
case Settings::ScalingFilter::NearestNeighbor:
|
||||||
|
case Settings::ScalingFilter::Bilinear:
|
||||||
case Settings::ScalingFilter::Fsr:
|
case Settings::ScalingFilter::Fsr:
|
||||||
return fsr->GetPresentFragmentProgram().handle;
|
|
||||||
default:
|
default:
|
||||||
return present_bilinear_fragment.handle;
|
return present_bilinear_fragment.handle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ using namespace FSR;
|
||||||
|
|
||||||
using FsrConstants = std::array<u32, 4 * 4>;
|
using FsrConstants = std::array<u32, 4 * 4>;
|
||||||
|
|
||||||
FSR::FSR() {
|
FSR::FSR(u32 output_width_, u32 output_height_) : width(output_width_), height(output_height_) {
|
||||||
std::string fsr_source{HostShaders::OPENGL_FIDELITYFX_FSR_FRAG};
|
std::string fsr_source{HostShaders::OPENGL_FIDELITYFX_FSR_FRAG};
|
||||||
ReplaceInclude(fsr_source, "ffx_a.h", HostShaders::FFX_A_H);
|
ReplaceInclude(fsr_source, "ffx_a.h", HostShaders::FFX_A_H);
|
||||||
ReplaceInclude(fsr_source, "ffx_fsr1.h", HostShaders::FFX_FSR1_H);
|
ReplaceInclude(fsr_source, "ffx_fsr1.h", HostShaders::FFX_FSR1_H);
|
||||||
|
@ -29,94 +29,70 @@ FSR::FSR() {
|
||||||
ReplaceInclude(fsr_easu_source, "opengl_fidelityfx_fsr.frag", fsr_source);
|
ReplaceInclude(fsr_easu_source, "opengl_fidelityfx_fsr.frag", fsr_source);
|
||||||
ReplaceInclude(fsr_rcas_source, "opengl_fidelityfx_fsr.frag", fsr_source);
|
ReplaceInclude(fsr_rcas_source, "opengl_fidelityfx_fsr.frag", fsr_source);
|
||||||
|
|
||||||
fsr_vertex = CreateProgram(HostShaders::FULL_SCREEN_TRIANGLE_VERT, GL_VERTEX_SHADER);
|
vert = CreateProgram(HostShaders::FULL_SCREEN_TRIANGLE_VERT, GL_VERTEX_SHADER);
|
||||||
fsr_easu_frag = CreateProgram(fsr_easu_source, GL_FRAGMENT_SHADER);
|
easu_frag = CreateProgram(fsr_easu_source, GL_FRAGMENT_SHADER);
|
||||||
fsr_rcas_frag = CreateProgram(fsr_rcas_source, GL_FRAGMENT_SHADER);
|
rcas_frag = CreateProgram(fsr_rcas_source, GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
glProgramUniform2f(fsr_vertex.handle, 0, 1.0f, 1.0f);
|
glProgramUniform2f(vert.handle, 0, 1.0f, -1.0f);
|
||||||
glProgramUniform2f(fsr_vertex.handle, 1, 0.0f, 0.0f);
|
glProgramUniform2f(vert.handle, 1, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
sampler = CreateBilinearSampler();
|
||||||
|
framebuffer.Create();
|
||||||
|
|
||||||
|
easu_tex.Create(GL_TEXTURE_2D);
|
||||||
|
glTextureStorage2D(easu_tex.handle, 1, GL_RGBA16F, width, height);
|
||||||
|
|
||||||
|
rcas_tex.Create(GL_TEXTURE_2D);
|
||||||
|
glTextureStorage2D(rcas_tex.handle, 1, GL_RGBA16F, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSR::~FSR() = default;
|
FSR::~FSR() = default;
|
||||||
|
|
||||||
void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
|
GLuint FSR::Draw(ProgramManager& program_manager, GLuint texture, u32 input_image_width,
|
||||||
u32 input_image_width, u32 input_image_height,
|
u32 input_image_height, const Common::Rectangle<f32>& crop_rect) {
|
||||||
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_width = static_cast<f32>(input_image_width);
|
||||||
const f32 input_height = static_cast<f32>(input_image_height);
|
const f32 input_height = static_cast<f32>(input_image_height);
|
||||||
const f32 output_width = static_cast<f32>(screen.GetWidth());
|
const f32 output_width = static_cast<f32>(width);
|
||||||
const f32 output_height = static_cast<f32>(screen.GetHeight());
|
const f32 output_height = static_cast<f32>(height);
|
||||||
const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width;
|
const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width;
|
||||||
const f32 viewport_x = 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_height = (crop_rect.bottom - crop_rect.top) * input_height;
|
||||||
const f32 viewport_y = crop_rect.top * input_height;
|
const f32 viewport_y = crop_rect.top * input_height;
|
||||||
|
|
||||||
FsrConstants constants;
|
FsrConstants easu_con{};
|
||||||
FsrEasuConOffset(constants.data() + 0, constants.data() + 4, constants.data() + 8,
|
FsrConstants rcas_con{};
|
||||||
constants.data() + 12, viewport_width, viewport_height, input_width,
|
|
||||||
|
FsrEasuConOffset(easu_con.data() + 0, easu_con.data() + 4, easu_con.data() + 8,
|
||||||
|
easu_con.data() + 12, viewport_width, viewport_height, input_width,
|
||||||
input_height, output_width, output_height, viewport_x, viewport_y);
|
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 =
|
const float sharpening =
|
||||||
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
|
static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f;
|
||||||
|
|
||||||
FsrRcasCon(constants.data(), sharpening);
|
FsrRcasCon(rcas_con.data(), sharpening);
|
||||||
glProgramUniform4uiv(fsr_rcas_frag.handle, 0, sizeof(constants), std::data(constants));
|
|
||||||
|
glProgramUniform4uiv(easu_frag.handle, 0, sizeof(easu_con), easu_con.data());
|
||||||
|
glProgramUniform4uiv(rcas_frag.handle, 0, sizeof(rcas_con), rcas_con.data());
|
||||||
|
|
||||||
|
glFrontFace(GL_CW);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer.handle);
|
||||||
|
glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, easu_tex.handle, 0);
|
||||||
|
glViewportIndexedf(0, 0.0f, 0.0f, output_width, output_height);
|
||||||
|
program_manager.BindPresentPrograms(vert.handle, easu_frag.handle);
|
||||||
|
glBindTextureUnit(0, texture);
|
||||||
|
glBindSampler(0, sampler.handle);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
|
||||||
|
glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, rcas_tex.handle, 0);
|
||||||
|
program_manager.BindPresentPrograms(vert.handle, rcas_frag.handle);
|
||||||
|
glBindTextureUnit(0, easu_tex.handle);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
|
||||||
|
return rcas_tex.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSR::InitBuffers() {
|
bool FSR::NeedsRecreation(const Common::Rectangle<u32>& screen) {
|
||||||
fsr_framebuffer.Create();
|
return screen.GetWidth() != width || screen.GetHeight() != height;
|
||||||
}
|
|
||||||
|
|
||||||
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
|
} // namespace OpenGL
|
||||||
|
|
|
@ -16,27 +16,24 @@ class ProgramManager;
|
||||||
|
|
||||||
class FSR {
|
class FSR {
|
||||||
public:
|
public:
|
||||||
explicit FSR();
|
explicit FSR(u32 output_width, u32 output_height);
|
||||||
~FSR();
|
~FSR();
|
||||||
|
|
||||||
void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
|
GLuint Draw(ProgramManager& program_manager, GLuint texture, u32 input_image_width,
|
||||||
u32 input_image_width, u32 input_image_height,
|
u32 input_image_height, const Common::Rectangle<f32>& crop_rect);
|
||||||
const Common::Rectangle<f32>& crop_rect);
|
|
||||||
|
|
||||||
void InitBuffers();
|
bool NeedsRecreation(const Common::Rectangle<u32>& screen);
|
||||||
|
|
||||||
void ReleaseBuffers();
|
|
||||||
|
|
||||||
[[nodiscard]] const OGLProgram& GetPresentFragmentProgram() const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] bool AreBuffersInitialized() const noexcept;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OGLFramebuffer fsr_framebuffer;
|
const u32 width;
|
||||||
OGLProgram fsr_vertex;
|
const u32 height;
|
||||||
OGLProgram fsr_easu_frag;
|
OGLFramebuffer framebuffer;
|
||||||
OGLProgram fsr_rcas_frag;
|
OGLSampler sampler;
|
||||||
OGLTexture fsr_intermediate_tex;
|
OGLProgram vert;
|
||||||
|
OGLProgram easu_frag;
|
||||||
|
OGLProgram rcas_frag;
|
||||||
|
OGLTexture easu_tex;
|
||||||
|
OGLTexture rcas_tex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
Loading…
Reference in a new issue