fixed shaders for opengl es, fixed texture allocation when using secondary window (or android)

This commit is contained in:
KojoZero 2026-05-31 09:48:52 -07:00
parent 4deb00e856
commit 39a5880270
7 changed files with 83 additions and 33 deletions

View file

@ -265,7 +265,7 @@
<string name="antialiasing_filter_name">Antialiasing Filter</string>
<string name="antialiasing_filter_description">Reduces the amount of aliasing, resulting in smoother edges. FXAA is extremely lightweight but more aggressive and lower quality. SMAA is heavier but is higher quality and more selective with the edges it smooths.</string>
<string name="output_scaling_name">Output Scaling</string>
<string name="output_scaling_description">The method by which the game output is scaled to the screen. Nearest doesn\'t smooth visuals but causes uneven pixels at non-integer ratios. Bilinear smooths visuals but may cause aliasing when downscaling. Adaptive uses bilinear for upscaling, but uses area sampling to downscale without creating aliasing. FSR 1 is an upscaler which allows sharpening and allows better visuals without increasing the internal resolution. This should be used with antialiasing and a minimum internal resolution of 2x Native. Sharp Bilinear looks similar to nearest but is slightly smoothed to prevent uneven pixels at non-integer ratios.</string>
<string name="output_scaling_description">The method by which the game output is scaled to the screen. Nearest doesn\'t smooth visuals but causes uneven pixels at non-integer ratios. Bilinear smooths visuals but may cause aliasing when downscaling. Adaptive uses bilinear for upscaling, but uses area sampling to downscale without creating aliasing. FSR 1 is an upscaler which allows sharpening and allows better visuals without increasing the internal resolution, but needs to be used with antialiasing and a minimum internal resolution of 2x Native. Sharp Bilinear looks similar to nearest but is slightly smoothed to prevent uneven pixels at non-integer ratios.</string>
<string name="fsr_sharpness_name">FSR Sharpness</string>
<string name="fsr_sharpness_description">Specifies the strength of the sharpening pass when using FSR</string>
<string name="delay_render_thread">Delay Game Render Thread</string>

View file

@ -199,7 +199,7 @@ AF1 outputSizeInPixelsY){
con2[3]=AU1_AF1(AF1_( 2.0)*ARcpF1(inputSizeInPixelsY));
con3[0]=AU1_AF1(AF1_( 0.0)*ARcpF1(inputSizeInPixelsX));
con3[1]=AU1_AF1(AF1_( 4.0)*ARcpF1(inputSizeInPixelsY));
con3[2]=con3[3]=0;}
con3[2]=con3[3]=0u;}
//If the an offset into the input image resource
A_STATIC void FsrEasuConOffset(
@ -668,8 +668,8 @@ AF1 sharpness){
varAF2(hSharp)=initAF2(sharpness,sharpness);
con[0]=AU1_AF1(sharpness);
con[1]=AU1_AH2_AF2(hSharp);
con[2]=0;
con[3]=0;}
con[2]=0u;
con[3]=0u;}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//_____________________________________________________________/\_______________________________________________________________

View file

@ -52,8 +52,8 @@ vec4 AreaSampling(sampler2D textureSampler, vec2 texCoords) {
avg_color += area_se * texelFetch(textureSampler, ivec2(f_end.x, f_end.y), 0);
// Determine the size of the pixel box.
int x_range = int(f_end.x - f_beg.x - 0.5);
int y_range = int(f_end.y - f_beg.y - 0.5);
int x_range = int(float(f_end.x) - float(f_beg.x) - 0.5);
int y_range = int(float(f_end.y) - float(f_beg.y) - 0.5);
// Accumulate top and bottom edge pixels.
for (int x = f_beg.x + 1; x <= f_beg.x + x_range; ++x) {

View file

@ -124,6 +124,21 @@ RendererOpenGL::RendererOpenGL(Core::System& system, Pica::PicaCore& pica_,
RendererOpenGL::~RendererOpenGL() = default;
void RendererOpenGL::SwapBuffers() {
#ifdef ANDROID
// On Android, if secondary_window is defined at all,
// it means we have a second display
if (secondary_window) {
usingSecondaryLayout = true;
} else {
usingSecondaryLayout = false;
}
#else
if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) {
usingSecondaryLayout = true;
} else {
usingSecondaryLayout = false;
}
#endif
system.perf_stats->StartSwap();
// Maintain the rasterizer's state as a priority
OpenGLState prev_state = OpenGLState::GetCurState();
@ -138,6 +153,7 @@ void RendererOpenGL::SwapBuffers() {
render_window.SwapBuffers();
#else
const auto& main_layout = render_window.GetFramebufferLayout();
isSecondaryWindow = false;
RenderToMailbox(main_layout, render_window.mailbox, false);
#ifdef ANDROID
@ -145,6 +161,7 @@ void RendererOpenGL::SwapBuffers() {
// it means we have a second display
if (secondary_window) {
const auto& secondary_layout = secondary_window->GetFramebufferLayout();
isSecondaryWindow = true;
RenderToMailbox(secondary_layout, secondary_window->mailbox, false);
secondary_window->PollEvents();
}
@ -152,6 +169,7 @@ void RendererOpenGL::SwapBuffers() {
if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) {
ASSERT(secondary_window);
const auto& secondary_layout = secondary_window->GetFramebufferLayout();
isSecondaryWindow = true;
RenderToMailbox(secondary_layout, secondary_window->mailbox, false);
secondary_window->PollEvents();
}
@ -412,17 +430,25 @@ void RendererOpenGL::AllocatePPTextures(){
}
void RendererOpenGL::AllocateOutputSizeTextures(){
for (int i = 0; i < intermediateOutputSizeTextures.size(); i++){
if (currOutputScreenRects[i].GetHeight() != 0 && currOutputScreenRects[i].GetWidth() != 0){
for (int j = 0; j < intermediateOutputSizeTextures[0].size(); j++){
intermediateOutputSizeTextures[i][j].Release();
intermediateOutputSizeTextures[i][j].Create();
intermediateOutputSizeTextures[i][j].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currOutputScreenRects[i].GetWidth(), currOutputScreenRects[i].GetHeight());
for (int i = 0; i < intermediateOutputSizeTextures[isSecondaryWindow].size(); i++){
if (currOutputScreenRects[isSecondaryWindow][i].GetHeight() != 0 && currOutputScreenRects[isSecondaryWindow][i].GetWidth() != 0){
for (int j = 0; j < intermediateOutputSizeTextures[isSecondaryWindow][0].size(); j++){
intermediateOutputSizeTextures[isSecondaryWindow][i][j].Release();
intermediateOutputSizeTextures[isSecondaryWindow][i][j].Create();
intermediateOutputSizeTextures[isSecondaryWindow][i][j].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currOutputScreenRects[isSecondaryWindow][i].GetWidth(), currOutputScreenRects[isSecondaryWindow][i].GetHeight());
}
}
}
LOG_INFO(Render_OpenGL, "Reallocated OutputSize Textures");
LOG_INFO(Render_OpenGL, "Reallocated OutputSize Textures. PrevRects:\n{}x{}\n{}x{}\n{}x{}\nCurrRects:\n{}x{}\n{}x{}\n{}x{}",
prevOutputScreenRects[isSecondaryWindow][0].GetWidth(), prevOutputScreenRects[isSecondaryWindow][0].GetHeight(),
prevOutputScreenRects[isSecondaryWindow][1].GetWidth(), prevOutputScreenRects[isSecondaryWindow][1].GetHeight(),
prevOutputScreenRects[isSecondaryWindow][2].GetWidth(), prevOutputScreenRects[isSecondaryWindow][2].GetHeight(),
currOutputScreenRects[isSecondaryWindow][0].GetWidth(), currOutputScreenRects[isSecondaryWindow][0].GetHeight(),
currOutputScreenRects[isSecondaryWindow][1].GetWidth(), currOutputScreenRects[isSecondaryWindow][1].GetHeight(),
currOutputScreenRects[isSecondaryWindow][2].GetWidth(), currOutputScreenRects[isSecondaryWindow][2].GetHeight()
);
//
}
/**
@ -589,7 +615,9 @@ void RendererOpenGL::ReloadShader(Settings::StereoRenderOption render_3d) {
FSR_PASS_1_shader_frag_data += HostShaders::OPENGL_FSR_PASS1_PART3_FRAG;
FSR_PASS_1_shader.Create(HostShaders::OPENGL_FSR_PASS1_VERT, FSR_PASS_1_shader_frag_data);
SharpBilinear_shader.Create(HostShaders::OPENGL_SHARPBILINEAR_VERT, HostShaders::OPENGL_SHARPBILINEAR_FRAG);
std::string SharpBilinear_shader_frag_data = fragment_shader_precision_OES;
SharpBilinear_shader_frag_data += HostShaders::OPENGL_SHARPBILINEAR_FRAG;
SharpBilinear_shader.Create(HostShaders::OPENGL_SHARPBILINEAR_VERT, SharpBilinear_shader_frag_data);
state.Apply();
if (render_3d == Settings::StereoRenderOption::Anaglyph ||
@ -1085,7 +1113,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
state.viewport.width = screenWidth;
state.viewport.height = screenHeight;
state.Apply();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateOutputSizeTextures[currOutputScreen][0].handle, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateOutputSizeTextures[isSecondaryWindow][currOutputScreen][0].handle, 0);
glClear(GL_COLOR_BUFFER_BIT);
state.draw.shader_program = FSR_PASS_0_shader.handle;
state.Apply();
@ -1104,12 +1132,12 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
state.viewport.width = screenWidth;
state.viewport.height = screenHeight;
state.Apply();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateOutputSizeTextures[currOutputScreen][1].handle, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateOutputSizeTextures[isSecondaryWindow][currOutputScreen][1].handle, 0);
glClear(GL_COLOR_BUFFER_BIT);
state.draw.shader_program = FSR_PASS_1_shader.handle;
state.Apply();
AttachUniforms();
state.texture_units[0].texture_2d = intermediateOutputSizeTextures[currOutputScreen][0].handle;
state.texture_units[0].texture_2d = intermediateOutputSizeTextures[isSecondaryWindow][currOutputScreen][0].handle;
state.texture_units[0].sampler = samplers[1].handle;
glUniform1f(uniform_fsr_sharpening, fsr_sharpening);
glUniform4f(uniform_o_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight);
@ -1129,7 +1157,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
state.draw.shader_program = Present_shader.handle;
state.Apply();
AttachUniforms();
state.texture_units[0].texture_2d = intermediateOutputSizeTextures[currOutputScreen][1].handle;
state.texture_units[0].texture_2d = intermediateOutputSizeTextures[isSecondaryWindow][currOutputScreen][1].handle;
state.texture_units[0].sampler = samplers[1].handle;
glUniform1i(uniform_color_texture, 0);
glUniform1i(uniform_convert_colors, 0);
@ -1304,15 +1332,21 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
prevBottomTextureHeight = currBottomTextureHeight;
//Track Layout Changes
currOutputScreenRects[0] = layout.top_screen;
currOutputScreenRects[1] = layout.bottom_screen;
currOutputScreenRects[2] = layout.additional_screen;
if (currOutputScreenRects[0] != prevOutputScreenRects[0] || currOutputScreenRects[1] != prevOutputScreenRects[1] || currOutputScreenRects[2] != prevOutputScreenRects[2]){
currOutputScreenRects[isSecondaryWindow][0] = layout.top_screen;
currOutputScreenRects[isSecondaryWindow][1] = layout.bottom_screen;
currOutputScreenRects[isSecondaryWindow][2] = layout.additional_screen;
if (currOutputScreenRects[isSecondaryWindow][0] != prevOutputScreenRects[isSecondaryWindow][0] || currOutputScreenRects[isSecondaryWindow][1] != prevOutputScreenRects[isSecondaryWindow][1]){
if (layout.additional_screen_enabled){
if (currOutputScreenRects[isSecondaryWindow][2] != prevOutputScreenRects[isSecondaryWindow][2]){
AllocateOutputSizeTextures();
}
prevOutputScreenRects[0] = currOutputScreenRects[0];
prevOutputScreenRects[1] = currOutputScreenRects[1];
prevOutputScreenRects[2] = currOutputScreenRects[2];
} else {
AllocateOutputSizeTextures();
}
}
prevOutputScreenRects[isSecondaryWindow][0] = currOutputScreenRects[isSecondaryWindow][0];
prevOutputScreenRects[isSecondaryWindow][1] = currOutputScreenRects[isSecondaryWindow][1];
prevOutputScreenRects[isSecondaryWindow][2] = currOutputScreenRects[isSecondaryWindow][2];
//Set the Viewport
state.viewport.x = 0;

View file

@ -116,9 +116,9 @@ private:
std::array<OGLTexture, 2> antialiasFBOTexture;
//Intermediate Textures at output size. These are for Top Screen, Bottom Screen and Additional Screen Respectively
std::array<std::array<OGLTexture, 3>, 3> intermediateOutputSizeTextures;
std::array<Common::Rectangle<u32>, 3> prevOutputScreenRects;
std::array<Common::Rectangle<u32>, 3> currOutputScreenRects;
std::array<std::array<std::array<OGLTexture, 3>, 3>, 2> intermediateOutputSizeTextures;
std::array<std::array<Common::Rectangle<u32>, 3>, 2> prevOutputScreenRects;
std::array<std::array<Common::Rectangle<u32>, 3>, 2> currOutputScreenRects;
int currOutputScreen;
OGLTexture areatex;
OGLTexture searchtex;
@ -158,6 +158,11 @@ private:
float currBottomTextureWidth;
float currBottomTextureHeight;
std::array<int, 4> originalViewport;
// Secondary Layout Fix
bool usingSecondaryLayout;
bool isSecondaryWindow;
};
} // namespace OpenGL

View file

@ -2057,10 +2057,19 @@ void RendererVulkan::DrawScreens(Frame* frame, const Layout::FramebufferLayout&
currOutputScreenRects[0] = layout.top_screen;
currOutputScreenRects[1] = layout.bottom_screen;
currOutputScreenRects[2] = layout.additional_screen;
if (currOutputScreenRects[0] != prevOutputScreenRects[0] || currOutputScreenRects[1] != prevOutputScreenRects[1] || currOutputScreenRects[2] != prevOutputScreenRects[2]){
if (currOutputScreenRects[0] != prevOutputScreenRects[0] || currOutputScreenRects[1] != prevOutputScreenRects[1]){
if (layout.additional_screen_enabled){
if (currOutputScreenRects[2] != prevOutputScreenRects[2]){
AllocateOutputSizeTextures();
CreateOutputSizeTextureFramebuffers();
}
} else {
AllocateOutputSizeTextures();
CreateOutputSizeTextureFramebuffers();
}
}
prevOutputScreenRects[0] = currOutputScreenRects[0];
prevOutputScreenRects[1] = currOutputScreenRects[1];
prevOutputScreenRects[2] = currOutputScreenRects[2];

View file

@ -6,15 +6,17 @@
// High precision may or may not be supported in GLES3. If it isn't, use medium precision instead.
static constexpr char fragment_shader_precision_OES[] = R"(
#if GL_ES
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp int;
precision highp float;
precision highp sampler2D;
precision highp samplerBuffer;
precision highp uimage2D;
#else
precision mediump int;
precision mediump float;
precision highp sampler2D;
precision mediump samplerBuffer;
precision mediump uimage2D;
#endif // GL_FRAGMENT_PRECISION_HIGH