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:
parent
225734c0b3
commit
44ec286ba4
10 changed files with 78 additions and 75 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue