diff --git a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp index 23227422c..056e91e1f 100644 --- a/core/hw/pvr/Renderer_if.cpp +++ b/core/hw/pvr/Renderer_if.cpp @@ -20,7 +20,7 @@ void retro_rend_present() sh4_cpu.Stop(); } #endif -void retro_resize_renderer(int w, int h); +void retro_resize_renderer(int w, int h, float aspectRatio); u32 FrameCount=1; @@ -175,7 +175,8 @@ private: bool renderToScreen = !_pvrrc->rend.isRTT && !config::EmulateFramebuffer; #ifdef LIBRETRO if (renderToScreen) - retro_resize_renderer(_pvrrc->rend.framebufferWidth, _pvrrc->rend.framebufferHeight); + retro_resize_renderer(_pvrrc->rend.framebufferWidth, _pvrrc->rend.framebufferHeight, + getOutputFramebufferAspectRatio(_pvrrc->rend)); #endif bool proc = renderer->Process(_pvrrc); if (!proc || renderToScreen) @@ -198,8 +199,8 @@ private: { #ifdef LIBRETRO int w, h; - getTAViewport(w, h); // FIXME ? - retro_resize_renderer(w, h); + getDCFramebufferReadSize(w, h); + retro_resize_renderer(w, h, getDCFramebufferAspectRatio()); #endif renderer->RenderFramebuffer(config); } @@ -344,6 +345,8 @@ void rend_start_render() ctx->rend.fb_W_SOF1 = FB_W_SOF1; ctx->rend.fb_W_CTRL.full = FB_W_CTRL.full; + ctx->rend.ta_GLOB_TILE_CLIP = TA_GLOB_TILE_CLIP; + ctx->rend.scaler_ctl = SCALER_CTL; ctx->rend.fb_X_CLIP = FB_X_CLIP; ctx->rend.fb_Y_CLIP = FB_Y_CLIP; ctx->rend.fb_W_LINESTRIDE = FB_W_LINESTRIDE.stride; @@ -354,7 +357,7 @@ void rend_start_render() if (!ctx->rend.isRTT) { int width, height; - getScaledFramebufferSize(width, height); + getScaledFramebufferSize(ctx->rend, width, height); ctx->rend.framebufferWidth = width; ctx->rend.framebufferHeight = height; } diff --git a/core/hw/pvr/ta_ctx.h b/core/hw/pvr/ta_ctx.h index f21b66721..36da3e60b 100644 --- a/core/hw/pvr/ta_ctx.h +++ b/core/hw/pvr/ta_ctx.h @@ -227,6 +227,8 @@ struct rend_context bool Overrun; bool isRTT; + TA_GLOB_TILE_CLIP_type ta_GLOB_TILE_CLIP; + SCALER_CTL_type scaler_ctl; FB_X_CLIP_type fb_X_CLIP; FB_Y_CLIP_type fb_Y_CLIP; u32 fb_W_LINESTRIDE; diff --git a/core/rend/dx11/dx11_renderer.cpp b/core/rend/dx11/dx11_renderer.cpp index 99b21cd10..cfbf006d3 100644 --- a/core/rend/dx11/dx11_renderer.cpp +++ b/core/rend/dx11/dx11_renderer.cpp @@ -443,9 +443,10 @@ bool DX11Renderer::Render() } else { + aspectRatio = getOutputFramebufferAspectRatio(pvrrc); #ifndef LIBRETRO deviceContext->OMSetRenderTargets(1, &theDX11Context.getRenderTarget().get(), nullptr); - renderFramebuffer(); + displayFramebuffer(); DrawOSD(false); theDX11Context.setFrameRendered(); #else @@ -461,7 +462,7 @@ bool DX11Renderer::Render() return !is_rtt; } -void DX11Renderer::renderFramebuffer() +void DX11Renderer::displayFramebuffer() { #ifndef LIBRETRO D3D11_VIEWPORT vp{}; @@ -479,10 +480,12 @@ void DX11Renderer::renderFramebuffer() deviceContext->ClearRenderTargetView(theDX11Context.getRenderTarget(), colors); int outwidth = settings.display.width; int outheight = settings.display.height; - float renderAR = getOutputFramebufferAspectRatio(); - float screenAR = (float)outwidth / outheight; - if (config::Rotate90) + float renderAR = aspectRatio; + if (config::Rotate90) { std::swap(outwidth, outheight); + renderAR = 1 / renderAR; + } + float screenAR = (float)outwidth / outheight; int dy = 0; int dx = 0; if (renderAR > screenAR) @@ -874,7 +877,7 @@ bool DX11Renderer::RenderLastFrame() { if (!frameRenderedOnce) return false; - renderFramebuffer(); + displayFramebuffer(); return true; } @@ -952,9 +955,10 @@ void DX11Renderer::RenderFramebuffer(const FramebufferInfo& info) float bar = (this->width - this->height * 640.f / 480.f) / 2.f; quad->draw(dcfbTextureView, samplers->getSampler(true), nullptr, bar / this->width * 2.f - 1.f, -1.f, (this->width - bar * 2.f) / this->width * 2.f, 2.f); + aspectRatio = getDCFramebufferAspectRatio(); #ifndef LIBRETRO deviceContext->OMSetRenderTargets(1, &theDX11Context.getRenderTarget().get(), nullptr); - renderFramebuffer(); + displayFramebuffer(); DrawOSD(false); theDX11Context.setFrameRendered(); #else diff --git a/core/rend/dx11/dx11_renderer.h b/core/rend/dx11/dx11_renderer.h index 63190d131..559c86173 100644 --- a/core/rend/dx11/dx11_renderer.h +++ b/core/rend/dx11/dx11_renderer.h @@ -93,7 +93,7 @@ protected: void updateFogTexture(); void updatePaletteTexture(); void readRttRenderTarget(u32 texAddress); - void renderFramebuffer(); + void displayFramebuffer(); void setCullMode(int mode); virtual void setRTTSize(int width, int height) {} void writeFramebufferToVRAM(); @@ -122,6 +122,7 @@ protected: bool frameRendered = false; bool frameRenderedOnce = false; Naomi2Helper n2Helper; + float aspectRatio = 4.f / 3.f; private: void readDCFramebuffer(); diff --git a/core/rend/dx11/oit/dx11_oitrenderer.cpp b/core/rend/dx11/oit/dx11_oitrenderer.cpp index 5944562ad..3780ce8d0 100644 --- a/core/rend/dx11/oit/dx11_oitrenderer.cpp +++ b/core/rend/dx11/oit/dx11_oitrenderer.cpp @@ -672,9 +672,10 @@ struct DX11OITRenderer : public DX11Renderer } else { + aspectRatio = getOutputFramebufferAspectRatio(pvrrc); #ifndef LIBRETRO deviceContext->OMSetRenderTargets(1, &theDX11Context.getRenderTarget().get(), nullptr); - renderFramebuffer(); + displayFramebuffer(); DrawOSD(false); theDX11Context.setFrameRendered(); #else diff --git a/core/rend/dx9/d3d_renderer.cpp b/core/rend/dx9/d3d_renderer.cpp index e4b58bace..6d1cdbab5 100644 --- a/core/rend/dx9/d3d_renderer.cpp +++ b/core/rend/dx9/d3d_renderer.cpp @@ -287,6 +287,7 @@ void D3DRenderer::RenderFramebuffer(const FramebufferInfo& info) RECT rd{ (LONG)bar, 0, (LONG)(this->width - bar), (LONG)this->height }; device->StretchRect(dcfbSurface, nullptr, framebufferSurface, &rd, D3DTEXF_LINEAR); + aspectRatio = getDCFramebufferAspectRatio(); displayFramebuffer(); DrawOSD(false); frameRendered = true; @@ -1088,6 +1089,7 @@ bool D3DRenderer::Render() } else { + aspectRatio = getOutputFramebufferAspectRatio(pvrrc); displayFramebuffer(); DrawOSD(false); frameRendered = true; @@ -1118,14 +1120,13 @@ void D3DRenderer::displayFramebuffer() { devCache.SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); device->ColorFill(backbuffer, 0, D3DCOLOR_ARGB(255, VO_BORDER_COL._red, VO_BORDER_COL._green, VO_BORDER_COL._blue)); - float renderAR = getOutputFramebufferAspectRatio(); float screenAR = (float)settings.display.width / settings.display.height; int dx = 0; int dy = 0; - if (renderAR > screenAR) - dy = (int)roundf(settings.display.height * (1 - screenAR / renderAR) / 2.f); + if (aspectRatio > screenAR) + dy = (int)roundf(settings.display.height * (1 - screenAR / aspectRatio) / 2.f); else - dx = (int)roundf(settings.display.width * (1 - renderAR / screenAR) / 2.f); + dx = (int)roundf(settings.display.width * (1 - aspectRatio / screenAR) / 2.f); if (!config::Rotate90) { diff --git a/core/rend/dx9/d3d_renderer.h b/core/rend/dx9/d3d_renderer.h index 936832d27..e36f21881 100644 --- a/core/rend/dx9/d3d_renderer.h +++ b/core/rend/dx9/d3d_renderer.h @@ -180,5 +180,6 @@ private: bool frameRendered = false; bool frameRenderedOnce = false; int maxAnisotropy = 1; + float aspectRatio = 4.f / 3.f; }; diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 27e10388c..041b676fc 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -941,7 +941,7 @@ static bool RenderFrame(int width, int height) writeFramebufferToVRAM(); #ifndef LIBRETRO else { - gl.ofbo.aspectRatio = getOutputFramebufferAspectRatio(); + gl.ofbo.aspectRatio = getOutputFramebufferAspectRatio(_pvrrc->rend); render_output_framebuffer(); } #endif diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index c1f23ed6f..74473efd2 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -708,7 +708,7 @@ void OpenGLRenderer::RenderFramebuffer(const FramebufferInfo& info) gl.ofbo2.framebuffer.reset(); if (gl.ofbo2.framebuffer == nullptr) - gl.ofbo2.framebuffer = std::unique_ptr(new GlFramebuffer(gl.dcfb.width, gl.dcfb.height)); + gl.ofbo2.framebuffer = std::unique_ptr(new GlFramebuffer(gl.dcfb.width, gl.dcfb.height, false, true)); else gl.ofbo2.framebuffer->bind(); glCheck(); diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 230dde528..5ce133d60 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -373,13 +373,16 @@ void do_swap_automation() static FILE* video_file = fopen(cfgLoadStr("record", "rawvid","").c_str(), "wb"); extern bool do_screenshot; + GlFramebuffer *framebuffer = gl.ofbo2.ready ? gl.ofbo2.framebuffer.get() : gl.ofbo.framebuffer.get(); + if (framebuffer == nullptr) + return; + int bytesz = framebuffer->getWidth() * framebuffer->getHeight() * 3; if (video_file) { - int bytesz = gl.ofbo.width * gl.ofbo.height * 3; u8* img = new u8[bytesz]; - glBindFramebuffer(GL_READ_FRAMEBUFFER, gl.ofbo.fbo); - glReadPixels(0, 0, gl.ofbo.width, gl.ofbo.height, GL_RGB, GL_UNSIGNED_BYTE, img); + framebuffer->bind(GL_READ_FRAMEBUFFER); + glReadPixels(0, 0, framebuffer->getWidth(), framebuffer->getHeight(), GL_RGB, GL_UNSIGNED_BYTE, img); fwrite(img, 1, bytesz, video_file); delete[] img; fflush(video_file); @@ -387,13 +390,12 @@ void do_swap_automation() if (do_screenshot) { - int bytesz = gl.ofbo.width * gl.ofbo.height * 3; u8* img = new u8[bytesz]; - glBindFramebuffer(GL_READ_FRAMEBUFFER, gl.ofbo.fbo); + framebuffer->bind(GL_READ_FRAMEBUFFER); glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(0, 0, gl.ofbo.width, gl.ofbo.height, GL_RGB, GL_UNSIGNED_BYTE, img); - dump_screenshot(img, gl.ofbo.width, gl.ofbo.height); + glReadPixels(0, 0, framebuffer->getWidth(), framebuffer->getHeight(), GL_RGB, GL_UNSIGNED_BYTE, img); + dump_screenshot(img, framebuffer->getWidth(), framebuffer->getHeight()); delete[] img; dc_exit(); flycast_term(); @@ -1380,7 +1382,7 @@ bool RenderFrame(int width, int height) writeFramebufferToVRAM(); #ifndef LIBRETRO else { - gl.ofbo.aspectRatio = getOutputFramebufferAspectRatio(); + gl.ofbo.aspectRatio = getOutputFramebufferAspectRatio(_pvrrc->rend); render_output_framebuffer(); } #endif diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index dc043f004..23c60d952 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -157,6 +157,7 @@ class GlFramebuffer { public: GlFramebuffer(int width, int height, bool withDepth = false, GLuint texture = 0); + GlFramebuffer(int width, int height, bool withDepth, bool withTexture); ~GlFramebuffer(); void bind(GLenum type = GL_FRAMEBUFFER) const { @@ -175,6 +176,8 @@ public: GLuint getFramebuffer() const { return framebuffer; } private: + void makeFramebuffer(bool withDepth); + int width; int height; GLuint texture; diff --git a/core/rend/gles/gltex.cpp b/core/rend/gles/gltex.cpp index c77b3a92c..a708e4227 100644 --- a/core/rend/gles/gltex.cpp +++ b/core/rend/gles/gltex.cpp @@ -440,7 +440,11 @@ GlFramebuffer::GlFramebuffer(int width, int height, bool withDepth, GLuint textu #endif } } + makeFramebuffer(withDepth); +} +void GlFramebuffer::makeFramebuffer(bool withDepth) +{ // Create the framebuffer glGenFramebuffers(1, &framebuffer); bind(); @@ -491,6 +495,33 @@ GlFramebuffer::GlFramebuffer(int width, int height, bool withDepth, GLuint textu glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer); } +GlFramebuffer::GlFramebuffer(int width, int height, bool withDepth, bool withTexture) +{ + if (gl.gl_major < 3 || withTexture) + { + // Create a texture for rendering to + texture = glcache.GenTexture(); + glcache.BindTexture(GL_TEXTURE_2D, texture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + else + { + // Use a renderbuffer and glBlitFramebuffer + glGenRenderbuffers(1, &colorBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer); +#ifdef GL_RGBA8 + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); +#endif + } + + makeFramebuffer(withDepth); +} + GlFramebuffer::~GlFramebuffer() { glDeleteFramebuffers(1, &framebuffer); diff --git a/core/rend/transform_matrix.h b/core/rend/transform_matrix.h index 35df79cd6..0663dff79 100644 --- a/core/rend/transform_matrix.h +++ b/core/rend/transform_matrix.h @@ -26,22 +26,22 @@ #include #include -inline static void getTAViewport(int& width, int& height) +inline static void getTAViewport(const rend_context& rendCtx, int& width, int& height) { - width = (TA_GLOB_TILE_CLIP.tile_x_num + 1) * 32; - height = (TA_GLOB_TILE_CLIP.tile_y_num + 1) * 32; + width = (rendCtx.ta_GLOB_TILE_CLIP.tile_x_num + 1) * 32; + height = (rendCtx.ta_GLOB_TILE_CLIP.tile_y_num + 1) * 32; } -inline static void getPvrFramebufferSize(int& width, int& height) +inline static void getPvrFramebufferSize(const rend_context& rendCtx, int& width, int& height) { - getTAViewport(width, height); + getTAViewport(rendCtx, width, height); if (!config::EmulateFramebuffer) { int maxHeight = FB_R_CTRL.vclk_div == 0 && SPG_CONTROL.interlace == 0 ? 240 : 480; - if (SCALER_CTL.vscalefactor != 0 - && (SCALER_CTL.vscalefactor > 1025 || SCALER_CTL.vscalefactor < 1024) + if (rendCtx.scaler_ctl.vscalefactor != 0 + && (rendCtx.scaler_ctl.vscalefactor > 1025 || rendCtx.scaler_ctl.vscalefactor < 1024) && SPG_CONTROL.interlace == 0) - maxHeight /= 1024.f / SCALER_CTL.vscalefactor; + maxHeight /= 1024.f / rendCtx.scaler_ctl.vscalefactor; if (FB_R_CTRL.fb_line_double) maxHeight /= 2; height = std::min(maxHeight, height); @@ -72,7 +72,7 @@ public: bool IsClipped() const { int width, height; - getTAViewport(width, height); + getTAViewport(*renderingContext, width, height); float sx, sy; GetScissorScaling(sx, sy); return renderingContext->fb_X_CLIP.min != 0 @@ -120,7 +120,7 @@ public: else { int w, h; - getPvrFramebufferSize(w, h); + getPvrFramebufferSize(*renderingContext, w, h); dcViewport.x = w; dcViewport.y = h; @@ -217,17 +217,17 @@ private: if (!renderingContext->isRTT && !config::EmulateFramebuffer) { - if (SCALER_CTL.vscalefactor > 0x400) - scale_y *= std::round(SCALER_CTL.vscalefactor / 1024.f); - if (SCALER_CTL.hscale) + if (renderingContext->scaler_ctl.vscalefactor > 0x400) + scale_y *= std::round(renderingContext->scaler_ctl.vscalefactor / 1024.f); + if (renderingContext->scaler_ctl.hscale) scale_x *= 2.f; } else if (config::EmulateFramebuffer) { - if (SCALER_CTL.hscale) + if (renderingContext->scaler_ctl.hscale) scale_x *= 2.f; - if (SCALER_CTL.vscalefactor > 0x401 || SCALER_CTL.vscalefactor < 0x400) - scale_y *= SCALER_CTL.vscalefactor / 1024.f; + if (renderingContext->scaler_ctl.vscalefactor > 0x401 || renderingContext->scaler_ctl.vscalefactor < 0x400) + scale_y *= renderingContext->scaler_ctl.vscalefactor / 1024.f; } } @@ -241,9 +241,9 @@ private: float sidebarWidth = 0; }; -inline static void getScaledFramebufferSize(int& width, int& height) +inline static void getScaledFramebufferSize(const rend_context& rendCtx, int& width, int& height) { - getPvrFramebufferSize(width, height); + getPvrFramebufferSize(rendCtx, width, height); if (!config::EmulateFramebuffer) { float upscaling = config::RenderResolution / 480.f; @@ -264,25 +264,25 @@ inline static void getScaledFramebufferSize(int& width, int& height) } } -inline static float getOutputFramebufferAspectRatio() +inline static float getOutputFramebufferAspectRatio(const rend_context& rendCtx) { int w,h; - getPvrFramebufferSize(w, h); + getPvrFramebufferSize(rendCtx, w, h); float width = w; float height = h; width *= 1 + VO_CONTROL.pixel_double; - width /= 1 + SCALER_CTL.hscale; + width /= 1 + rendCtx.scaler_ctl.hscale; height *= 1 + (FB_R_CTRL.vclk_div == 0 && SPG_CONTROL.interlace == 0); height *= 1 + (FB_R_CTRL.fb_line_double); - if (SCALER_CTL.vscalefactor != 0 - && (SCALER_CTL.vscalefactor > 1025 || SCALER_CTL.vscalefactor < 1024) + if (rendCtx.scaler_ctl.vscalefactor != 0 + && (rendCtx.scaler_ctl.vscalefactor > 1025 || rendCtx.scaler_ctl.vscalefactor < 1024) && SPG_CONTROL.interlace == 0) { if (config::EmulateFramebuffer) - height *= 1024.f / SCALER_CTL.vscalefactor; - else if (SCALER_CTL.vscalefactor > 1025) - height *= std::round(1024.f / SCALER_CTL.vscalefactor); + height *= 1024.f / rendCtx.scaler_ctl.vscalefactor; + else if (rendCtx.scaler_ctl.vscalefactor > 1025) + height *= std::round(1024.f / rendCtx.scaler_ctl.vscalefactor); } @@ -304,10 +304,10 @@ inline static float getOutputFramebufferAspectRatio() return renderAR * config::ScreenStretching / 100.f; } -inline static float getDCFramebufferAspectRatio() +inline static void getDCFramebufferReadSize(int& width, int& height) { - int width = FB_R_SIZE.fb_x_size + 1; // in 32-bit words - int height = FB_R_SIZE.fb_y_size + 1; + width = FB_R_SIZE.fb_x_size + 1; // in 32-bit words + height = FB_R_SIZE.fb_y_size + 1; switch (FB_R_CTRL.fb_depth) { @@ -322,6 +322,14 @@ inline static float getDCFramebufferAspectRatio() default: break; } +} + +inline static float getDCFramebufferAspectRatio() +{ + int width; + int height; + getDCFramebufferReadSize(width, height); + width *= 1 + VO_CONTROL.pixel_double; height *= 1 + (FB_R_CTRL.vclk_div == 0 && SPG_CONTROL.interlace == 0); height *= 1 + (FB_R_CTRL.fb_line_double); diff --git a/core/rend/vulkan/drawer.cpp b/core/rend/vulkan/drawer.cpp index 74873a7a4..4530608dd 100644 --- a/core/rend/vulkan/drawer.cpp +++ b/core/rend/vulkan/drawer.cpp @@ -744,6 +744,7 @@ void ScreenDrawer::EndRenderPass() { currentCommandBuffer.end(); commandPool->EndFrame(); + aspectRatio = getOutputFramebufferAspectRatio(_pvrrc->rend); } currentCommandBuffer = nullptr; Drawer::EndRenderPass(); diff --git a/core/rend/vulkan/drawer.h b/core/rend/vulkan/drawer.h index b6ad62da1..cba0f6ad1 100644 --- a/core/rend/vulkan/drawer.h +++ b/core/rend/vulkan/drawer.h @@ -287,7 +287,7 @@ public: return false; frameRendered = false; GetContext()->PresentFrame(colorAttachments[GetCurrentImage()]->GetImage(), - colorAttachments[GetCurrentImage()]->GetImageView(), viewport); + colorAttachments[GetCurrentImage()]->GetImageView(), viewport, aspectRatio); return true; } @@ -309,6 +309,7 @@ private: std::vector transitionNeeded; std::vector clearNeeded; bool frameRendered = false; + float aspectRatio = 0.f; }; class TextureDrawer : public Drawer diff --git a/core/rend/vulkan/oit/oit_drawer.h b/core/rend/vulkan/oit/oit_drawer.h index e9fbccea1..b07b24ffc 100644 --- a/core/rend/vulkan/oit/oit_drawer.h +++ b/core/rend/vulkan/oit/oit_drawer.h @@ -167,7 +167,7 @@ public: OITDrawer::Init(samplerManager, screenPipelineManager.get(), oitBuffers); MakeFramebuffers(viewport); - GetContext()->PresentFrame(vk::Image(), vk::ImageView(), viewport); + GetContext()->PresentFrame(vk::Image(), vk::ImageView(), viewport, 0); } void Term() { @@ -190,6 +190,7 @@ public: { currentCommandBuffer.end(); commandPool->EndFrame(); + aspectRatio = getOutputFramebufferAspectRatio(_pvrrc->rend); } currentCommandBuffer = nullptr; OITDrawer::EndFrame(); @@ -202,7 +203,7 @@ public: return false; frameRendered = false; GetContext()->PresentFrame(finalColorAttachments[GetCurrentImage()]->GetImage(), - finalColorAttachments[GetCurrentImage()]->GetImageView(), viewport.extent); + finalColorAttachments[GetCurrentImage()]->GetImageView(), viewport.extent, aspectRatio); return true; } @@ -220,6 +221,7 @@ private: std::unique_ptr screenPipelineManager; std::vector transitionNeeded; bool frameRendered = false; + float aspectRatio = 0.f; }; class OITTextureDrawer : public OITDrawer diff --git a/core/rend/vulkan/vk_context_lr.cpp b/core/rend/vulkan/vk_context_lr.cpp index 66262c0f0..71d9528c3 100644 --- a/core/rend/vulkan/vk_context_lr.cpp +++ b/core/rend/vulkan/vk_context_lr.cpp @@ -290,7 +290,7 @@ bool VulkanContext::init(retro_hw_render_interface_vulkan *retro_render_if) return true; } -void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent) +void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) { retro_image.image_view = (VkImageView)imageView; retro_image.create_info.image = (VkImage)image; diff --git a/core/rend/vulkan/vk_context_lr.h b/core/rend/vulkan/vk_context_lr.h index 80c1e92e7..f05f3a28a 100644 --- a/core/rend/vulkan/vk_context_lr.h +++ b/core/rend/vulkan/vk_context_lr.h @@ -38,7 +38,7 @@ public: void term() override; u32 GetGraphicsQueueFamilyIndex() const { return retro_render_if->queue_index; } - void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent); + void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio); vk::PhysicalDevice GetPhysicalDevice() const { return physicalDevice; } vk::Device GetDevice() const { return device; } diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index 68d37ac69..5a43f12f5 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -823,7 +823,7 @@ void VulkanContext::Present() noexcept if (lastFrameView && IsValid() && !gui_is_open()) for (int i = 1; i < swapInterval; i++) { - PresentFrame(vk::Image(), lastFrameView, lastFrameExtent); + PresentFrame(vk::Image(), lastFrameView, lastFrameExtent, lastFrameAR); presentQueue.presentKHR(vk::PresentInfoKHR(1, &(*renderCompleteSemaphores[currentSemaphore]), 1, &(*swapChain), ¤tImage)); currentSemaphore = (currentSemaphore + 1) % imageViews.size(); } @@ -847,7 +847,7 @@ void VulkanContext::Present() noexcept } } -void VulkanContext::DrawFrame(vk::ImageView imageView, const vk::Extent2D& extent) +void VulkanContext::DrawFrame(vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) { QuadVertex vtx[] = { { { -1, -1, 0 }, { 0, 0 } }, @@ -862,14 +862,13 @@ void VulkanContext::DrawFrame(vk::ImageView imageView, const vk::Extent2D& exten else quadPipeline->BindPipeline(commandBuffer); - float renderAR = getOutputFramebufferAspectRatio(); float screenAR = (float)width / height; float dx = 0; float dy = 0; - if (renderAR > screenAR) - dy = height * (1 - screenAR / renderAR) / 2; + if (aspectRatio > screenAR) + dy = height * (1 - screenAR / aspectRatio) / 2; else - dx = width * (1 - renderAR / screenAR) / 2; + dx = width * (1 - aspectRatio / screenAR) / 2; vk::Viewport viewport(dx, dy, width - dx * 2, height - dy * 2); commandBuffer.setViewport(0, 1, &viewport); @@ -928,10 +927,11 @@ vk::CommandBuffer VulkanContext::PrepareOverlay(bool vmu, bool crosshair) extern Renderer *renderer; -void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent) noexcept +void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) noexcept { lastFrameView = imageView; lastFrameExtent = extent; + lastFrameAR = aspectRatio; if (imageView && IsValid()) { @@ -942,7 +942,7 @@ void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const BeginRenderPass(); if (lastFrameView) // Might have been nullified if swap chain recreated - DrawFrame(imageView, extent); + DrawFrame(imageView, extent, aspectRatio); DrawOverlay(settings.display.uiScale, config::FloatVMUs, true); renderer->DrawOSD(false); @@ -955,7 +955,7 @@ void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const void VulkanContext::PresentLastFrame() { if (lastFrameView && IsValid()) - DrawFrame(lastFrameView, lastFrameExtent); + DrawFrame(lastFrameView, lastFrameExtent, lastFrameAR); } void VulkanContext::term() diff --git a/core/rend/vulkan/vulkan_context.h b/core/rend/vulkan/vulkan_context.h index e60436c9e..a4ce9ac2e 100644 --- a/core/rend/vulkan/vulkan_context.h +++ b/core/rend/vulkan/vulkan_context.h @@ -59,7 +59,7 @@ public: void BeginRenderPass(); void EndFrame(vk::CommandBuffer cmdBuffer = vk::CommandBuffer()); void Present() noexcept; - void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent) noexcept; + void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) noexcept; void PresentLastFrame(); vk::PhysicalDevice GetPhysicalDevice() const { return physicalDevice; } @@ -136,7 +136,7 @@ private: bool InitInstance(const char** extensions, uint32_t extensions_count); void InitImgui(); void DoSwapAutomation(); - void DrawFrame(vk::ImageView imageView, const vk::Extent2D& extent); + void DrawFrame(vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio); vk::SurfaceKHR GetSurface() const { return *surface; } bool HasSurfaceDimensionChanged() const; @@ -206,6 +206,7 @@ private: vk::ImageView lastFrameView; vk::Extent2D lastFrameExtent; + float lastFrameAR = 0.f; std::unique_ptr overlay; // only used to delay the destruction of overlay textures diff --git a/core/rend/vulkan/vulkan_renderer.h b/core/rend/vulkan/vulkan_renderer.h index ff1479fe6..4fefccbda 100644 --- a/core/rend/vulkan/vulkan_renderer.h +++ b/core/rend/vulkan/vulkan_renderer.h @@ -23,6 +23,7 @@ #include "pipeline.h" #include "rend/osd.h" #include "overlay.h" +#include "rend/transform_matrix.h" #ifndef LIBRETRO #include "rend/gui.h" #endif @@ -77,7 +78,7 @@ public: void Term() override { GetContext()->WaitIdle(); - GetContext()->PresentFrame(nullptr, nullptr, vk::Extent2D()); + GetContext()->PresentFrame(nullptr, nullptr, vk::Extent2D(), 0); #ifdef LIBRETRO overlay->Term(); overlay.reset(); @@ -304,7 +305,8 @@ protected: Texture *fbTexture = framebufferTextures[GetContext()->GetCurrentImageIndex()].get(); if (fbTexture == nullptr) return false; - GetContext()->PresentFrame(fbTexture->GetImage(), fbTexture->GetImageView(), fbTexture->getSize()); + GetContext()->PresentFrame(fbTexture->GetImage(), fbTexture->GetImageView(), fbTexture->getSize(), + getDCFramebufferAspectRatio()); return true; } diff --git a/shell/libretro/libretro.cpp b/shell/libretro/libretro.cpp index bd45ccd13..d693194cc 100644 --- a/shell/libretro/libretro.cpp +++ b/shell/libretro/libretro.cpp @@ -165,6 +165,7 @@ static int framebufferWidth; static int framebufferHeight; static int maxFramebufferWidth; static int maxFramebufferHeight; +static float framebufferAspectRatio = 4.f / 3.f; float libretro_expected_audio_samples_per_run; unsigned libretro_vsync_swap_interval = 1; @@ -600,7 +601,7 @@ static bool set_variable_visibility(void) static void setGameGeometry(retro_game_geometry& geometry) { - geometry.aspect_ratio = getOutputFramebufferAspectRatio(); + geometry.aspect_ratio = framebufferAspectRatio; if (rotate_screen) geometry.aspect_ratio = 1 / geometry.aspect_ratio; geometry.max_width = std::max(framebufferHeight * 16 / 9, framebufferWidth); @@ -622,12 +623,13 @@ void setAVInfo(retro_system_av_info& avinfo) libretro_expected_audio_samples_per_run = sample_rate / fps; } -void retro_resize_renderer(int w, int h) +void retro_resize_renderer(int w, int h, float aspectRatio) { if (w == framebufferWidth && h == framebufferHeight) return; framebufferWidth = w; framebufferHeight = h; + framebufferAspectRatio = aspectRatio; bool avinfoNeeded = framebufferHeight > maxFramebufferHeight || framebufferWidth > maxFramebufferWidth; maxFramebufferHeight = std::max(maxFramebufferHeight, framebufferHeight); maxFramebufferWidth = std::max(maxFramebufferWidth, framebufferWidth);