pvr: copy pvr regs at start_render time to avoid concurrent update

copy TA_GLOB_TILE_CLIP and SCALER_CTL to rend context when starting
render. Use rend context copy to calculate framebuffer size.
Fixes framebuffer size glitches in vf4 water stages.
lr: pass aspect ratio when resizing.

dx11: Wrong sizing of rotated games.

gl: test automation fixes.
This commit is contained in:
Flyinghead 2022-10-25 15:00:04 +02:00
parent 5722dc90f0
commit c1f0dd81d2
22 changed files with 143 additions and 77 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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)
{

View File

@ -180,5 +180,6 @@ private:
bool frameRendered = false;
bool frameRenderedOnce = false;
int maxAnisotropy = 1;
float aspectRatio = 4.f / 3.f;
};

View File

@ -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

View File

@ -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<GlFramebuffer>(new GlFramebuffer(gl.dcfb.width, gl.dcfb.height));
gl.ofbo2.framebuffer = std::unique_ptr<GlFramebuffer>(new GlFramebuffer(gl.dcfb.width, gl.dcfb.height, false, true));
else
gl.ofbo2.framebuffer->bind();
glCheck();

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -26,22 +26,22 @@
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
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);

View File

@ -744,6 +744,7 @@ void ScreenDrawer::EndRenderPass()
{
currentCommandBuffer.end();
commandPool->EndFrame();
aspectRatio = getOutputFramebufferAspectRatio(_pvrrc->rend);
}
currentCommandBuffer = nullptr;
Drawer::EndRenderPass();

View File

@ -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<bool> transitionNeeded;
std::vector<bool> clearNeeded;
bool frameRendered = false;
float aspectRatio = 0.f;
};
class TextureDrawer : public Drawer

View File

@ -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<OITPipelineManager> screenPipelineManager;
std::vector<bool> transitionNeeded;
bool frameRendered = false;
float aspectRatio = 0.f;
};
class OITTextureDrawer : public OITDrawer

View File

@ -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;

View File

@ -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; }

View File

@ -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), &currentImage));
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()

View File

@ -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<VulkanOverlay> overlay;
// only used to delay the destruction of overlay textures

View File

@ -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;
}

View File

@ -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);