1
0
Fork 0
mirror of https://github.com/hrydgard/ppsspp.git synced 2025-04-02 11:01:50 -04:00

Framebuffer: Keep the render scale factor around, no need to recompute it.

This commit is contained in:
Henrik Rydgård 2020-11-05 11:21:00 +01:00
parent 225734c0b3
commit 44ec286ba4
10 changed files with 78 additions and 75 deletions

View file

@ -66,11 +66,12 @@ struct CoreParameter {
std::string *collectEmuLog = nullptr;
bool headLess; // Try to avoid messageboxes etc
// Internal PSP resolution
// Internal PSP rendering resolution and scale factor.
int renderScaleFactor;
int renderWidth;
int renderHeight;
// Actual pixel output resolution (for use by glViewport and the like)
// Actual output resolution in pixels.
int pixelWidth;
int pixelHeight;

View file

@ -77,6 +77,7 @@ bool FramebufferManagerCommon::UpdateSize() {
renderWidth_ = (float)PSP_CoreParameter().renderWidth;
renderHeight_ = (float)PSP_CoreParameter().renderHeight;
renderScaleFactor_ = (float)PSP_CoreParameter().renderScaleFactor;
pixelWidth_ = PSP_CoreParameter().pixelWidth;
pixelHeight_ = PSP_CoreParameter().pixelHeight;
bloomHack_ = g_Config.iBloomHack;
@ -340,14 +341,6 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
}
}
float renderWidthFactor = renderWidth_ / 480.0f;
float renderHeightFactor = renderHeight_ / 272.0f;
if (PSP_CoreParameter().compat.flags().Force04154000Download && params.fb_address == 0x04154000) {
renderWidthFactor = 1.0;
renderHeightFactor = 1.0;
}
// None found? Create one.
if (!vfb) {
vfb = new VirtualFramebuffer{};
@ -356,28 +349,28 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
vfb->fb_stride = params.fb_stride;
vfb->z_address = params.z_address;
vfb->z_stride = params.z_stride;
// The other width/height parameters are set in ResizeFramebufFBO below.
vfb->width = drawing_width;
vfb->height = drawing_height;
vfb->newWidth = drawing_width;
vfb->newHeight = drawing_height;
vfb->lastFrameNewSize = gpuStats.numFlips;
vfb->renderWidth = (u16)(drawing_width * renderWidthFactor);
vfb->renderHeight = (u16)(drawing_height * renderHeightFactor);
vfb->bufferWidth = drawing_width;
vfb->bufferHeight = drawing_height;
vfb->format = params.fmt;
vfb->drawnFormat = params.fmt;
vfb->usageFlags = FB_USAGE_RENDERTARGET;
SetColorUpdated(vfb, skipDrawReason);
u32 byteSize = ColorBufferByteSize(vfb);
if (Memory::IsVRAMAddress(params.fb_address) && params.fb_address + byteSize > framebufRangeEnd_) {
framebufRangeEnd_ = params.fb_address + byteSize;
}
// This is where we actually create the framebuffer. The true is "force".
ResizeFramebufFBO(vfb, drawing_width, drawing_height, true);
NotifyRenderFramebufferCreated(vfb);
SetColorUpdated(vfb, skipDrawReason);
INFO_LOG(FRAMEBUF, "Creating FBO for %08x (z: %08x) : %i x %i x %i", vfb->fb_address, vfb->z_address, vfb->width, vfb->height, vfb->format);
vfb->last_frame_render = gpuStats.numFlips;
@ -1046,6 +1039,7 @@ void FramebufferManagerCommon::DecimateFBOs() {
}
}
// Requires width/height to be set already.
void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, int h, bool force, bool skipCopy) {
_dbg_assert_(w > 0);
_dbg_assert_(h > 0);
@ -1067,7 +1061,32 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
vfb->bufferHeight = std::max((int)vfb->bufferHeight, h);
}
SetRenderSize(vfb);
bool force1x = false;
switch (bloomHack_) {
case 1:
force1x = vfb->bufferWidth <= 128 || vfb->bufferHeight <= 64;
break;
case 2:
force1x = vfb->bufferWidth <= 256 || vfb->bufferHeight <= 128;
break;
case 3:
force1x = vfb->bufferWidth < 480 || vfb->bufferWidth > 800 || vfb->bufferHeight < 272; // GOW uses 864x272
break;
}
if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000) {
force1x = true;
}
if (force1x && g_Config.iInternalResolution != 1) {
vfb->renderScaleFactor = 1.0f;
vfb->renderWidth = vfb->bufferWidth;
vfb->renderHeight = vfb->bufferHeight;
} else {
vfb->renderScaleFactor = renderScaleFactor_;
vfb->renderWidth = (u16)(vfb->bufferWidth * renderScaleFactor_);
vfb->renderHeight = (u16)(vfb->bufferHeight * renderScaleFactor_);
}
// During hardware rendering, we always render at full color depth even if the game wouldn't on real hardware.
// It's not worth the trouble trying to support lower bit-depth rendering, just
@ -1655,35 +1674,6 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS
}
}
void FramebufferManagerCommon::SetRenderSize(VirtualFramebuffer *vfb) {
float renderWidthFactor = renderWidth_ / 480.0f;
float renderHeightFactor = renderHeight_ / 272.0f;
bool force1x = false;
switch (bloomHack_) {
case 1:
force1x = vfb->bufferWidth <= 128 || vfb->bufferHeight <= 64;
break;
case 2:
force1x = vfb->bufferWidth <= 256 || vfb->bufferHeight <= 128;
break;
case 3:
force1x = vfb->bufferWidth < 480 || vfb->bufferWidth > 800 || vfb->bufferHeight < 272; // GOW uses 864x272
break;
}
if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000) {
force1x = true;
}
if (force1x && g_Config.iInternalResolution != 1) {
vfb->renderWidth = vfb->bufferWidth;
vfb->renderHeight = vfb->bufferHeight;
} else {
vfb->renderWidth = (u16)(vfb->bufferWidth * renderWidthFactor);
vfb->renderHeight = (u16)(vfb->bufferHeight * renderHeightFactor);
}
}
void FramebufferManagerCommon::SetSafeSize(u16 w, u16 h) {
VirtualFramebuffer *vfb = currentRenderVfb_;
if (vfb) {
@ -1695,10 +1685,11 @@ void FramebufferManagerCommon::SetSafeSize(u16 w, u16 h) {
void FramebufferManagerCommon::Resized() {
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
int w, h;
presentation_->CalculateRenderResolution(&w, &h, &postShaderIsUpscalingFilter_, &postShaderIsSupersampling_);
int w, h, scaleFactor;
presentation_->CalculateRenderResolution(&w, &h, &scaleFactor, &postShaderIsUpscalingFilter_, &postShaderIsSupersampling_);
PSP_CoreParameter().renderWidth = w;
PSP_CoreParameter().renderHeight = h;
PSP_CoreParameter().renderScaleFactor = scaleFactor;
if (UpdateSize()) {
DestroyAllFBOs();
@ -1736,6 +1727,11 @@ void FramebufferManagerCommon::DestroyAllFBOs() {
tempFB.second.fbo->Release();
}
tempFBOs_.clear();
for (auto iter : fbosToDelete_) {
iter->Release();
}
fbosToDelete_.clear();
}
Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u16 h) {

View file

@ -61,21 +61,24 @@ struct VirtualFramebuffer {
u16 width;
u16 height;
// renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions.
// The physical buffer may be larger than renderWidth/renderHeight.
u16 renderWidth;
u16 renderHeight;
// bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than width/height.
// bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than or equal to width/height.
// Actual physical buffer is this size times the render resolution multiplier.
// The buffer may be used to render a width or height from 0 to these values without being recreated.
u16 bufferWidth;
u16 bufferHeight;
// renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions.
// The physical buffer may be larger than renderWidth/renderHeight.
u16 renderWidth;
u16 renderHeight;
float renderScaleFactor;
u16 usageFlags;
u16 newWidth;
u16 newHeight;
int lastFrameNewSize;
Draw::Framebuffer *fbo;
@ -396,9 +399,10 @@ protected:
bool gameUsesSequentialCopies_ = false;
// Sampled in BeginFrame for safety.
// Sampled in BeginFrame/UpdateSize for safety.
float renderWidth_ = 0.0f;
float renderHeight_ = 0.0f;
float renderScaleFactor_ = 1.0f;
int pixelWidth_;
int pixelHeight_;
int bloomHack_ = 0;

View file

@ -729,7 +729,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u
draw_->BindPipeline(nullptr);
}
void PresentationCommon::CalculateRenderResolution(int *width, int *height, bool *upscaling, bool *ssaa) {
void PresentationCommon::CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) {
// Check if postprocessing shader is doing upscaling as it requires native resolution
std::vector<const ShaderInfo *> shaderInfo;
if (!g_Config.vPostShaderNames.empty() && g_Config.vPostShaderNames[0] != "Off") {
@ -776,4 +776,6 @@ void PresentationCommon::CalculateRenderResolution(int *width, int *height, bool
*width = 480 * zoom;
*height = 272 * zoom;
}
*scaleFactor = zoom;
}

View file

@ -100,7 +100,7 @@ public:
void SourceFramebuffer(Draw::Framebuffer *fb, int bufferWidth, int bufferHeight);
void CopyToOutput(OutputFlags flags, int uvRotation, float u0, float v0, float u1, float v1);
void CalculateRenderResolution(int *width, int *height, bool *upscaling, bool *ssaa);
void CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa);
protected:
void CreateDeviceObjects();

View file

@ -420,8 +420,8 @@ void FramebufferManagerD3D11::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
return;
}
float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth;
float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight;
float srcXFactor = src->renderScaleFactor;
float srcYFactor = src->renderScaleFactor;
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
if (srcBpp != bpp && bpp != 0) {
srcXFactor = (srcXFactor * bpp) / srcBpp;
@ -431,8 +431,8 @@ void FramebufferManagerD3D11::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
int srcY1 = srcY * srcYFactor;
int srcY2 = (srcY + h) * srcYFactor;
float dstXFactor = (float)dst->renderWidth / (float)dst->bufferWidth;
float dstYFactor = (float)dst->renderHeight / (float)dst->bufferHeight;
float dstXFactor = dst->renderScaleFactor;
float dstYFactor = dst->renderScaleFactor;
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
if (dstBpp != bpp && bpp != 0) {
dstXFactor = (dstXFactor * bpp) / dstBpp;

View file

@ -383,8 +383,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
return;
}
float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth;
float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight;
float srcXFactor = (float)src->renderScaleFactor;
float srcYFactor = (float)src->renderScaleFactor;
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
if (srcBpp != bpp && bpp != 0) {
srcXFactor = (srcXFactor * bpp) / srcBpp;
@ -394,8 +394,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
int srcY1 = srcY * srcYFactor;
int srcY2 = (srcY + h) * srcYFactor;
float dstXFactor = (float)dst->renderWidth / (float)dst->bufferWidth;
float dstYFactor = (float)dst->renderHeight / (float)dst->bufferHeight;
float dstXFactor = (float)dst->renderScaleFactor;
float dstYFactor = (float)dst->renderScaleFactor;
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
if (dstBpp != bpp && bpp != 0) {
dstXFactor = (dstXFactor * bpp) / dstBpp;

View file

@ -315,8 +315,8 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
bool useBlit = gstate_c.Supports(GPU_SUPPORTS_FRAMEBUFFER_BLIT);
float srcXFactor = useBlit ? (float)src->renderWidth / (float)src->bufferWidth : 1.0f;
float srcYFactor = useBlit ? (float)src->renderHeight / (float)src->bufferHeight : 1.0f;
float srcXFactor = useBlit ? src->renderScaleFactor : 1.0f;
float srcYFactor = useBlit ? src->renderScaleFactor : 1.0f;
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
if (srcBpp != bpp && bpp != 0) {
srcXFactor = (srcXFactor * bpp) / srcBpp;
@ -326,8 +326,8 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
int srcY1 = srcY * srcYFactor;
int srcY2 = (srcY + h) * srcYFactor;
float dstXFactor = useBlit ? (float)dst->renderWidth / (float)dst->bufferWidth : 1.0f;
float dstYFactor = useBlit ? (float)dst->renderHeight / (float)dst->bufferHeight : 1.0f;
float dstXFactor = useBlit ? dst->renderScaleFactor : 1.0f;
float dstYFactor = useBlit ? dst->renderScaleFactor : 1.0f;
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
if (dstBpp != bpp && bpp != 0) {
dstXFactor = (dstXFactor * bpp) / dstBpp;

View file

@ -261,7 +261,6 @@ void FramebufferManagerVulkan::ReformatFramebufferFrom(VirtualFramebuffer *vfb,
// We have to bind here instead of clear, since it can be that no framebuffer is bound.
// The backend can sometimes directly optimize it to a clear.
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "ReformatFramebuffer");
// draw_->Clear(Draw::FBChannel::FB_COLOR_BIT | Draw::FBChannel::FB_STENCIL_BIT, 0, 0.0f, 0);
// Need to dirty anything that has command buffer dynamic state, in case we started a new pass above.
// Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager.
@ -339,8 +338,10 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
return;
}
float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth;
float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight;
float srcXFactor = (float)src->renderScaleFactor;
float srcYFactor = (float)src->renderScaleFactor;
// Some games use wrong-format block transfers. Simulate that.
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
if (srcBpp != bpp && bpp != 0) {
srcXFactor = (srcXFactor * bpp) / srcBpp;
@ -350,8 +351,8 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
int srcY1 = srcY * srcYFactor;
int srcY2 = (srcY + h) * srcYFactor;
float dstXFactor = (float)dst->renderWidth / (float)dst->bufferWidth;
float dstYFactor = (float)dst->renderHeight / (float)dst->bufferHeight;
float dstXFactor = (float)dst->renderScaleFactor;
float dstYFactor = (float)dst->renderScaleFactor;
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
if (dstBpp != bpp && bpp != 0) {
dstXFactor = (dstXFactor * bpp) / dstBpp;
@ -367,8 +368,6 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
return;
}
// BlitFramebuffer can clip, but CopyFramebufferImage is more restricted.
// In case the src goes outside, we just skip the optimization in that case.
const bool sameSize = dstX2 - dstX1 == srcX2 - srcX1 && dstY2 - dstY1 == srcY2 - srcY1;
const bool srcInsideBounds = srcX2 <= src->renderWidth && srcY2 <= src->renderHeight;
const bool dstInsideBounds = dstX2 <= dst->renderWidth && dstY2 <= dst->renderHeight;

View file

@ -358,6 +358,7 @@ int main(int argc, const char* argv[])
coreParameter.startBreak = false;
coreParameter.printfEmuLog = !autoCompare;
coreParameter.headLess = true;
coreParameter.renderScaleFactor = 1;
coreParameter.renderWidth = 480;
coreParameter.renderHeight = 272;
coreParameter.pixelWidth = 480;