Merge pull request #9287 from hrydgard/fbo-cleanup-3

FBO cleanup 3: The grand unification .. sort of
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2017-02-07 09:10:05 +01:00
commit df86854c69
15 files changed
+469 -965

No files matched your search

+313
View File
@@ -18,6 +18,9 @@
#include <algorithm>
#include <sstream>
#include "ext/native/thin3d/thin3d.h"
#include "gfx_es2/gpu_features.h"
#include "i18n/i18n.h"
#include "Common/Common.h"
#include "Core/Config.h"
@@ -27,6 +30,7 @@
#include "Core/ELF/ParamSFO.h"
#include "Core/System.h"
#include "GPU/Common/FramebufferCommon.h"
#include "GPU/Common/TextureCacheCommon.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
@@ -179,6 +183,25 @@ bool FramebufferManagerCommon::ShouldDownloadFramebuffer(const VirtualFramebuffe
return updateVRAM_ || (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000);
}
void FramebufferManagerCommon::SetNumExtraFBOs(int num) {
for (size_t i = 0; i < extraFBOs_.size(); i++) {
delete extraFBOs_[i];
}
extraFBOs_.clear();
for (int i = 0; i < num; i++) {
// No depth/stencil for post processing
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ (int)renderWidth_, (int)renderHeight_, 1, 1, false, Draw::FBO_8888 });
extraFBOs_.push_back(fbo);
// The new FBO is still bound after creation, but let's bind it anyway.
draw_->BindFramebufferAsRenderTarget(fbo);
ClearBuffer();
}
currentRenderVfb_ = 0;
draw_->BindBackbufferAsRenderTarget();
}
// Heuristics to figure out the size of FBO to create.
void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int fb_stride, int &drawing_width, int &drawing_height) {
static const int MAX_FRAMEBUF_HEIGHT = 512;
@@ -476,6 +499,132 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
return vfb;
}
void FramebufferManagerCommon::DestroyFramebuf(VirtualFramebuffer *v) {
textureCache_->NotifyFramebuffer(v->fb_address, v, NOTIFY_FB_DESTROYED);
if (v->fbo) {
delete v->fbo;
v->fbo = nullptr;
}
// Wipe some pointers
if (currentRenderVfb_ == v)
currentRenderVfb_ = 0;
if (displayFramebuf_ == v)
displayFramebuf_ = 0;
if (prevDisplayFramebuf_ == v)
prevDisplayFramebuf_ = 0;
if (prevPrevDisplayFramebuf_ == v)
prevPrevDisplayFramebuf_ = 0;
delete v;
}
void FramebufferManagerCommon::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) {
if (!useBufferedRendering_) {
draw_->BindBackbufferAsRenderTarget();
// Let's ignore rendering to targets that have not (yet) been displayed.
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
}
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED);
ClearBuffer();
// ugly...
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
if (gstate_c.curRTRenderWidth != vfb->renderWidth || gstate_c.curRTRenderHeight != vfb->renderHeight) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerCommon::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) {
if (vfbFormatChanged) {
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
if (vfb->drawnFormat != vfb->format) {
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
}
}
// ugly...
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
if (gstate_c.curRTRenderWidth != vfb->renderWidth || gstate_c.curRTRenderHeight != vfb->renderHeight) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
} else {
DownloadFramebufferOnSwitch(prevVfb);
}
textureCache_->ForgetLastTexture();
if (useBufferedRendering_) {
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
} else {
// wtf? This should only happen very briefly when toggling bBufferedRendering
draw_->BindBackbufferAsRenderTarget();
}
} else {
if (vfb->fbo) {
// wtf? This should only happen very briefly when toggling bBufferedRendering
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_DESTROYED);
delete vfb->fbo;
vfb->fbo = nullptr;
}
draw_->BindBackbufferAsRenderTarget();
// Let's ignore rendering to targets that have not (yet) been displayed.
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
} else {
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
}
}
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
if (gl_extensions.IsGLES) {
// Some tiled mobile GPUs benefit IMMENSELY from clearing an FBO before rendering
// to it. This broke stuff before, so now it only clears on the first use of an
// FBO in a frame. This means that some games won't be able to avoid the on-some-GPUs
// performance-crushing framebuffer reloads from RAM, but we'll have to live with that.
if (vfb->last_frame_render != gpuStats.numFlips) {
ClearBuffer();
}
}
// Copy depth pixel value from the read framebuffer to the draw framebuffer
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !prevVfb->depthUpdated || isClearingDepth) {
// If depth wasn't updated, then we're at least "two degrees" away from the data.
// This is an optimization: it probably doesn't need to be copied in this case.
} else {
BlitFramebufferDepth(prevVfb, vfb);
}
}
if (vfb->drawnFormat != vfb->format) {
// TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer().
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
}
// ugly...
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
if (gstate_c.curRTRenderWidth != vfb->renderWidth || gstate_c.curRTRenderHeight != vfb->renderHeight) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerCommon::NotifyVideoUpload(u32 addr, int size, int width, GEBufferFormat fmt) {
// Note: UpdateFromMemory() is still called later.
// This is a special case where we have extra information prior to the invalidation.
@@ -553,6 +702,130 @@ void FramebufferManagerCommon::DownloadFramebufferOnSwitch(VirtualFramebuffer *v
}
}
void FramebufferManagerCommon::DecimateFBOs() {
if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) {
draw_->BindBackbufferAsRenderTarget();
}
currentRenderVfb_ = 0;
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i];
int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used);
if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) {
bool sync = gl_extensions.IsGLES;
ReadFramebufferToMemory(vfb, sync, 0, 0, vfb->width, vfb->height);
}
// Let's also "decimate" the usageFlags.
UpdateFramebufUsage(vfb);
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--);
}
}
}
for (auto it = tempFBOs_.begin(); it != tempFBOs_.end(); ) {
int age = frameLastFramebufUsed_ - it->second.last_frame_used;
if (age > FBO_OLD_AGE) {
delete it->second.fbo;
tempFBOs_.erase(it++);
} else {
++it;
}
}
// Do the same for ReadFramebuffersToMemory's VFBs
for (size_t i = 0; i < bvfbs_.size(); ++i) {
VirtualFramebuffer *vfb = bvfbs_[i];
int age = frameLastFramebufUsed_ - vfb->last_frame_render;
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
bvfbs_.erase(bvfbs_.begin() + i--);
}
}
}
void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) {
VirtualFramebuffer old = *vfb;
if (force) {
vfb->bufferWidth = w;
vfb->bufferHeight = h;
} else {
if (vfb->bufferWidth >= w && vfb->bufferHeight >= h) {
return;
}
// In case it gets thin and wide, don't resize down either side.
vfb->bufferWidth = std::max(vfb->bufferWidth, w);
vfb->bufferHeight = std::max(vfb->bufferHeight, h);
}
SetRenderSize(vfb);
bool trueColor = g_Config.bTrueColor;
if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) {
trueColor = true;
}
if (trueColor) {
vfb->colorDepth = Draw::FBO_8888;
} else {
switch (vfb->format) {
case GE_FORMAT_4444:
vfb->colorDepth = Draw::FBO_4444;
break;
case GE_FORMAT_5551:
vfb->colorDepth = Draw::FBO_5551;
break;
case GE_FORMAT_565:
vfb->colorDepth = Draw::FBO_565;
break;
case GE_FORMAT_8888:
default:
vfb->colorDepth = Draw::FBO_8888;
break;
}
}
textureCache_->ForgetLastTexture();
draw_->BindBackbufferAsRenderTarget();
if (!useBufferedRendering_) {
if (vfb->fbo) {
delete vfb->fbo;
vfb->fbo = nullptr;
}
return;
}
vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth });
if (old.fbo) {
INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format);
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
ClearBuffer();
if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) {
BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0);
}
}
delete old.fbo;
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
}
}
if (!vfb->fbo) {
ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight);
}
}
bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset, u32 skipDrawReason) {
if (updateVRAM_ || size == 0) {
return false;
@@ -998,6 +1271,46 @@ void FramebufferManagerCommon::SetSafeSize(u16 w, u16 h) {
}
}
void FramebufferManagerCommon::GetCardboardSettings(CardboardSettings *cardboardSettings) {
// Calculate Cardboard Settings
float cardboardScreenScale = g_Config.iCardboardScreenSize / 100.0f;
float cardboardScreenWidth = pixelWidth_ / 2.0f * cardboardScreenScale;
float cardboardScreenHeight = pixelHeight_ / 2.0f * cardboardScreenScale;
float cardboardMaxXShift = (pixelWidth_ / 2.0f - cardboardScreenWidth) / 2.0f;
float cardboardUserXShift = g_Config.iCardboardXShift / 100.0f * cardboardMaxXShift;
float cardboardLeftEyeX = cardboardMaxXShift + cardboardUserXShift;
float cardboardRightEyeX = pixelWidth_ / 2.0f + cardboardMaxXShift - cardboardUserXShift;
float cardboardMaxYShift = pixelHeight_ / 2.0f - cardboardScreenHeight / 2.0f;
float cardboardUserYShift = g_Config.iCardboardYShift / 100.0f * cardboardMaxYShift;
float cardboardScreenY = cardboardMaxYShift + cardboardUserYShift;
cardboardSettings->enabled = g_Config.bEnableCardboard;
cardboardSettings->leftEyeXPosition = cardboardLeftEyeX;
cardboardSettings->rightEyeXPosition = cardboardRightEyeX;
cardboardSettings->screenYPosition = cardboardScreenY;
cardboardSettings->screenWidth = cardboardScreenWidth;
cardboardSettings->screenHeight = cardboardScreenHeight;
}
Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth) {
u64 key = ((u64)depth << 32) | ((u32)w << 16) | h;
auto it = tempFBOs_.find(key);
if (it != tempFBOs_.end()) {
it->second.last_frame_used = gpuStats.numFlips;
return it->second.fbo;
}
textureCache_->ForgetLastTexture();
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, depth });
if (!fbo)
return fbo;
draw_->BindFramebufferAsRenderTarget(fbo);
ClearBuffer(true);
const TempFBO info = { fbo, gpuStats.numFlips };
tempFBOs_[key] = info;
return fbo;
}
void FramebufferManagerCommon::UpdateFramebufUsage(VirtualFramebuffer *vfb) {
auto checkFlag = [&](u16 flag, int last_frame) {
if (vfb->usageFlags & flag) {
+39 -6
View File
@@ -24,6 +24,7 @@
#include "Core/MemMap.h"
#include "GPU/GPU.h"
#include "GPU/ge_constants.h"
#include "thin3d/thin3d.h"
enum {
FB_USAGE_DISPLAYED_FRAMEBUFFER = 1,
@@ -50,6 +51,15 @@ namespace Draw {
class Framebuffer;
}
struct CardboardSettings {
bool enabled;
float leftEyeXPosition;
float rightEyeXPosition;
float screenYPosition;
float screenWidth;
float screenHeight;
};
class VulkanFBO;
struct VirtualFramebuffer {
@@ -137,6 +147,8 @@ namespace Draw {
class DrawContext;
}
class TextureCacheCommon;
class FramebufferManagerCommon {
public:
FramebufferManagerCommon(Draw::DrawContext *draw);
@@ -145,6 +157,7 @@ public:
virtual void Init();
void BeginFrame();
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format);
void DestroyFramebuf(VirtualFramebuffer *v);
VirtualFramebuffer *DoSetRenderFrameBuffer(const FramebufferHeuristicParams &params, u32 skipDrawReason);
VirtualFramebuffer *SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason) {
@@ -237,13 +250,19 @@ public:
virtual void Resized() = 0;
Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888);
protected:
// Cardboard Settings Calculator
void GetCardboardSettings(CardboardSettings *cardboardSettings);
void UpdateSize();
void SetNumExtraFBOs(int num);
virtual void DisableState() = 0;
virtual void ClearBuffer(bool keepState = false) = 0;
virtual void FlushBeforeCopy() = 0;
virtual void DecimateFBOs() = 0;
virtual void DecimateFBOs(); // keeping it virtual to let D3D do a little extra
// Used by ReadFramebufferToMemory and later framebuffer block copies
virtual void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) = 0;
@@ -252,12 +271,14 @@ protected:
u32 FramebufferByteSize(const VirtualFramebuffer *vfb) const;
static bool MaskedEqual(u32 addr1, u32 addr2);
virtual void DestroyFramebuf(VirtualFramebuffer *vfb) = 0;
virtual void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) = 0;
virtual void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) = 0;
virtual void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) = 0;
virtual void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) = 0;
void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb);
void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged);
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth);
virtual void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) = 0;
virtual void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) = 0;
void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false);
void ShowScreenResolution();
bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const;
@@ -282,6 +303,7 @@ protected:
}
Draw::DrawContext *draw_;
TextureCacheCommon *textureCache_;
u32 displayFramebufPtr_;
u32 displayStride_;
@@ -315,6 +337,17 @@ protected:
int pixelWidth_;
int pixelHeight_;
// Used by post-processing shaders
std::vector<Draw::Framebuffer *> extraFBOs_;
struct TempFBO {
Draw::Framebuffer *fbo;
int last_frame_used;
};
std::map<u64, TempFBO> tempFBOs_;
// Aggressively delete unused FBOs to save gpu memory.
enum {
FBO_OLD_AGE = 5,
+1
View File
@@ -57,6 +57,7 @@ public:
virtual bool SetOffsetTexture(u32 offset) = 0;
virtual void Invalidate(u32 addr, int size, GPUInvalidationType type) = 0;
virtual void InvalidateAll(GPUInvalidationType type) = 0;
virtual void ForgetLastTexture() = 0;
// FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to.
void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg);
+16 -271
View File
@@ -178,6 +178,11 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
}
}
void FramebufferManagerDX9::SetTextureCache(TextureCacheDX9 *tc) {
textureCacheDX9_ = tc;
textureCache_ = tc;
}
void FramebufferManagerDX9::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) {
u8 *convBuf = NULL;
D3DLOCKED_RECT rect;
@@ -273,8 +278,9 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
}
MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height);
DisableState();
DrawActiveTexture(drawPixelsTex_, dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, ROTATION_LOCKED_HORIZONTAL);
textureCache_->ForgetLastTexture();
device_->SetTexture(0, drawPixelsTex_);
DrawActiveTexture(dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, ROTATION_LOCKED_HORIZONTAL);
textureCacheDX9_->ForgetLastTexture();
dxstate.viewport.restore();
}
@@ -289,10 +295,11 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
float x, y, w, h;
int uvRotation = (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL;
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, uvRotation);
DrawActiveTexture(drawPixelsTex_, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, 0.0f, 0.0f, 480.0f / 512.0f, 1.0f, uvRotation);
device_->SetTexture(0, drawPixelsTex_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, 0.0f, 0.0f, 480.0f / 512.0f, 1.0f, uvRotation);
}
void FramebufferManagerDX9::DrawActiveTexture(LPDIRECT3DTEXTURE9 tex, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation) {
void FramebufferManagerDX9::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation) {
// TODO: StretchRect instead?
float coord[20] = {
x,y,0, u0,v0,
@@ -337,35 +344,12 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
pD3Ddevice->SetPixelShader(pFramebufferPixelShader);
pD3Ddevice->SetVertexShader(pFramebufferVertexShader);
shaderManager_->DirtyLastShader();
if (tex != NULL) {
pD3Ddevice->SetTexture(0, tex);
}
HRESULT hr = pD3Ddevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coord, 5 * sizeof(float));
if (FAILED(hr)) {
ERROR_LOG_REPORT(G3D, "DrawActiveTexture() failed: %08x", hr);
}
}
void FramebufferManagerDX9::DestroyFramebuf(VirtualFramebuffer *v) {
textureCache_->NotifyFramebuffer(v->fb_address, v, NOTIFY_FB_DESTROYED);
if (v->fbo) {
delete v->fbo;
v->fbo = nullptr;
}
// Wipe some pointers
if (currentRenderVfb_ == v)
currentRenderVfb_ = 0;
if (displayFramebuf_ == v)
displayFramebuf_ = 0;
if (prevDisplayFramebuf_ == v)
prevDisplayFramebuf_ = 0;
if (prevPrevDisplayFramebuf_ == v)
prevPrevDisplayFramebuf_ = 0;
delete v;
}
void FramebufferManagerDX9::RebindFramebuffer() {
if (currentRenderVfb_ && currentRenderVfb_->fbo) {
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo);
@@ -374,177 +358,6 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
}
}
void FramebufferManagerDX9::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) {
VirtualFramebuffer old = *vfb;
if (force) {
vfb->bufferWidth = w;
vfb->bufferHeight = h;
} else {
if (vfb->bufferWidth >= w && vfb->bufferHeight >= h) {
return;
}
// In case it gets thin and wide, don't resize down either side.
vfb->bufferWidth = std::max(vfb->bufferWidth, w);
vfb->bufferHeight = std::max(vfb->bufferHeight, h);
}
SetRenderSize(vfb);
bool trueColor = g_Config.bTrueColor;
if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) {
trueColor = true;
}
if (trueColor) {
vfb->colorDepth = Draw::FBO_8888;
} else {
switch (vfb->format) {
case GE_FORMAT_4444:
vfb->colorDepth = Draw::FBO_4444;
break;
case GE_FORMAT_5551:
vfb->colorDepth = Draw::FBO_5551;
break;
case GE_FORMAT_565:
vfb->colorDepth = Draw::FBO_565;
break;
case GE_FORMAT_8888:
default:
vfb->colorDepth = Draw::FBO_8888;
break;
}
}
textureCache_->ForgetLastTexture();
draw_->BindBackbufferAsRenderTarget();
if (!useBufferedRendering_) {
if (vfb->fbo) {
delete vfb->fbo;
vfb->fbo = nullptr;
}
return;
}
vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth });
if (old.fbo) {
INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format);
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
ClearBuffer();
if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) {
BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0);
}
}
delete old.fbo;
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
}
}
if (!vfb->fbo) {
ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight);
}
}
void FramebufferManagerDX9::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) {
if (!useBufferedRendering_) {
draw_->BindBackbufferAsRenderTarget();
// Let's ignore rendering to targets that have not (yet) been displayed.
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
}
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED);
ClearBuffer();
// ugly...
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
if (gstate_c.curRTRenderWidth != vfb->renderWidth || gstate_c.curRTRenderHeight != vfb->renderHeight) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerDX9::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
} else {
DownloadFramebufferOnSwitch(prevVfb);
}
textureCache_->ForgetLastTexture();
if (useBufferedRendering_) {
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
} else {
// wtf? This should only happen very briefly when toggling bBufferedRendering
draw_->BindBackbufferAsRenderTarget();
}
} else {
if (vfb->fbo) {
// wtf? This should only happen very briefly when toggling bBufferedRendering
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_DESTROYED);
delete vfb->fbo;
vfb->fbo = nullptr;
}
draw_->BindBackbufferAsRenderTarget();
// Let's ignore rendering to targets that have not (yet) been displayed.
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
} else {
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
}
}
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
// Copy depth pixel value from the read framebuffer to the draw framebuffer
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !prevVfb->depthUpdated || isClearingDepth) {
// If depth wasn't updated, then we're at least "two degrees" away from the data.
// This is an optimization: it probably doesn't need to be copied in this case.
} else {
BlitFramebufferDepth(prevVfb, vfb);
}
}
if (vfb->drawnFormat != vfb->format) {
// TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer().
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
}
// ugly...
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
if (gstate_c.curRTRenderWidth != vfb->renderWidth || gstate_c.curRTRenderHeight != vfb->renderHeight) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerDX9::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) {
if (vfbFormatChanged) {
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
if (vfb->drawnFormat != vfb->format) {
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
}
}
// ugly...
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
if (gstate_c.curRTRenderWidth != vfb->renderWidth || gstate_c.curRTRenderHeight != vfb->renderHeight) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerDX9::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) {
if (!useBufferedRendering_ || !vfb->fbo) {
return;
@@ -673,27 +486,6 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
}
}
Draw::Framebuffer *FramebufferManagerDX9::GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth) {
u64 key = ((u64)depth << 32) | ((u32)w << 16) | h;
auto it = tempFBOs_.find(key);
if (it != tempFBOs_.end()) {
it->second.last_frame_used = gpuStats.numFlips;
return it->second.fbo;
}
textureCache_->ForgetLastTexture();
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, depth });
if (!fbo)
return fbo;
draw_->BindFramebufferAsRenderTarget(fbo);
dxstate.viewport.force(0, 0, w, h);
ClearBuffer(true);
dxstate.viewport.restore();
const TempFBO info = {fbo, gpuStats.numFlips};
tempFBOs_[key] = info;
return fbo;
}
LPDIRECT3DSURFACE9 FramebufferManagerDX9::GetOffscreenSurface(LPDIRECT3DSURFACE9 similarSurface, VirtualFramebuffer *vfb) {
D3DSURFACE_DESC desc = {};
HRESULT hr = similarSurface->GetDesc(&desc);
@@ -713,7 +505,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
return it->second.surface;
}
textureCache_->ForgetLastTexture();
textureCacheDX9_->ForgetLastTexture();
LPDIRECT3DSURFACE9 offscreen = nullptr;
HRESULT hr = pD3Ddevice->CreateOffscreenPlainSurface(w, h, fmt, D3DPOOL_SYSTEMMEM, &offscreen, NULL);
if (FAILED(hr) || !offscreen) {
@@ -918,7 +710,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
}
dxstate.texMipFilter.set(D3DTEXF_NONE);
dxstate.texMipLodBias.set(0);
DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, u0, v0, u1, v1, uvRotation);
DrawActiveTexture(x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, u0, v0, u1, v1, uvRotation);
}
}
/*
@@ -963,7 +755,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
PackFramebufferDirectx9_(nvfb, x, y, w, h);
textureCache_->ForgetLastTexture();
textureCacheDX9_->ForgetLastTexture();
RebindFramebuffer();
}
}
@@ -997,7 +789,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
PackFramebufferDirectx9_(nvfb, x, y, w, h);
textureCache_->ForgetLastTexture();
textureCacheDX9_->ForgetLastTexture();
RebindFramebuffer();
}
}
@@ -1271,43 +1063,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
}
void FramebufferManagerDX9::DecimateFBOs() {
if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) {
draw_->BindBackbufferAsRenderTarget();
}
currentRenderVfb_ = 0;
bool updateVram = !(g_Config.iRenderingMode == FB_NON_BUFFERED_MODE || g_Config.iRenderingMode == FB_BUFFERED_MODE);
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i];
int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used);
if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) {
ReadFramebufferToMemory(vfb, false, 0, 0, vfb->width, vfb->height);
}
// Let's also "decimate" the usageFlags.
UpdateFramebufUsage(vfb);
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--);
}
}
}
for (auto it = tempFBOs_.begin(); it != tempFBOs_.end(); ) {
int age = frameLastFramebufUsed_ - it->second.last_frame_used;
if (age > FBO_OLD_AGE) {
delete it->second.fbo;
tempFBOs_.erase(it++);
} else {
++it;
}
}
FramebufferManagerCommon::DecimateFBOs();
for (auto it = offscreenSurfaces_.begin(); it != offscreenSurfaces_.end(); ) {
int age = frameLastFramebufUsed_ - it->second.last_frame_used;
if (age > FBO_OLD_AGE) {
@@ -1317,17 +1073,6 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
++it;
}
}
// Do the same for ReadFramebuffersToMemory's VFBs
for (size_t i = 0; i < bvfbs_.size(); ++i) {
VirtualFramebuffer *vfb = bvfbs_[i];
int age = frameLastFramebufUsed_ - vfb->last_frame_render;
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
bvfbs_.erase(bvfbs_.begin() + i--);
}
}
}
void FramebufferManagerDX9::DestroyAllFBOs(bool forceDelete) {
+5 -16
View File
@@ -45,9 +45,7 @@ public:
FramebufferManagerDX9(Draw::DrawContext *draw);
~FramebufferManagerDX9();
void SetTextureCache(TextureCacheDX9 *tc) {
textureCache_ = tc;
}
void SetTextureCache(TextureCacheDX9 *tc);
void SetShaderManager(ShaderManagerDX9 *sm) {
shaderManager_ = sm;
}
@@ -58,7 +56,7 @@ public:
virtual void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override;
virtual void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) override;
void DrawActiveTexture(LPDIRECT3DTEXTURE9 texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation);
void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation);
void DestroyAllFBOs(bool forceDelete);
@@ -66,9 +64,9 @@ public:
void Resized() override;
void DeviceLost();
void CopyDisplayToOutput();
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old);
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) override;
void BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, int flags);
@@ -79,9 +77,6 @@ public:
virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
void DestroyFramebuf(VirtualFramebuffer *vfb) override;
void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override;
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes);
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer);
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer);
@@ -89,7 +84,6 @@ public:
virtual void RebindFramebuffer() override;
Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888);
LPDIRECT3DSURFACE9 GetOffscreenSurface(LPDIRECT3DSURFACE9 similarSurface, VirtualFramebuffer *vfb);
LPDIRECT3DSURFACE9 GetOffscreenSurface(D3DFORMAT fmt, u32 w, u32 h);
@@ -102,9 +96,6 @@ protected:
// Used by ReadFramebufferToMemory and later framebuffer block copies
void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override;
void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) override;
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override;
void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) override;
bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
@@ -113,8 +104,6 @@ private:
void CompileDraw2DProgram();
void DestroyDraw2DProgram();
void SetNumExtraFBOs(int num);
void PackFramebufferDirectx9_(VirtualFramebuffer *vfb, int x, int y, int w, int h);
void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h);
static bool GetRenderTargetFramebuffer(LPDIRECT3DSURFACE9 renderTarget, LPDIRECT3DSURFACE9 offscreen, int w, int h, GPUDebugBuffer &buffer);
@@ -137,7 +126,7 @@ private:
LPDIRECT3DVERTEXSHADER9 stencilUploadVS_;
bool stencilUploadFailed_;
TextureCacheDX9 *textureCache_;
TextureCacheDX9 *textureCacheDX9_;
ShaderManagerDX9 *shaderManager_;
DrawEngineDX9 *drawEngine_;
+1 -1
View File
@@ -256,7 +256,7 @@ bool FramebufferManagerDX9::NotifyStencilUpload(u32 addr, int size, bool skipZer
pD3Ddevice->SetTexture(0, drawPixelsTex_);
shaderManager_->DirtyLastShader();
textureCache_->ForgetLastTexture();
textureCacheDX9_->ForgetLastTexture();
for (int i = 1; i < values; i += i) {
if (!(usedBits & i)) {
+1 -1
View File
@@ -65,7 +65,7 @@ public:
// Only used by Qt UI?
bool DecodeTexture(u8 *output, const GPUgstate &state);
void ForgetLastTexture();
void ForgetLastTexture() override;
void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight);
+55 -370
View File
@@ -114,25 +114,6 @@ void FramebufferManagerGLES::DisableState() {
glstate.stencilMask.set(0xFF);
}
void FramebufferManagerGLES::SetNumExtraFBOs(int num) {
for (size_t i = 0; i < extraFBOs_.size(); i++) {
delete extraFBOs_[i];
}
extraFBOs_.clear();
for (int i = 0; i < num; i++) {
// No depth/stencil for post processing
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ (int)renderWidth_, (int)renderHeight_, 1, 1, false, Draw::FBO_8888 });
extraFBOs_.push_back(fbo);
// The new FBO is still bound after creation, but let's bind it anyway.
draw_->BindFramebufferAsRenderTarget(fbo);
ClearBuffer();
}
currentRenderVfb_ = 0;
draw_->BindBackbufferAsRenderTarget();
}
void FramebufferManagerGLES::CompileDraw2DProgram() {
if (!draw2dprogram_) {
std::string errorString;
@@ -247,7 +228,7 @@ FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) :
timeLoc_(-1),
pixelDeltaLoc_(-1),
deltaLoc_(-1),
textureCache_(nullptr),
textureCacheGL_(nullptr),
shaderManager_(nullptr),
resized_(false),
pixelBufObj_(nullptr),
@@ -263,6 +244,11 @@ void FramebufferManagerGLES::Init() {
SetLineWidth();
}
void FramebufferManagerGLES::SetTextureCache(TextureCacheGLES *tc) {
textureCacheGL_ = tc;
textureCache_ = tc;
}
FramebufferManagerGLES::~FramebufferManagerGLES() {
if (drawPixelsTex_)
glDeleteTextures(1, &drawPixelsTex_);
@@ -287,7 +273,7 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma
}
if (!drawPixelsTex_) {
drawPixelsTex_ = textureCache_->AllocTextureName();
drawPixelsTex_ = textureCacheGL_->AllocTextureName();
drawPixelsTexW_ = width;
drawPixelsTexH_ = height;
@@ -376,12 +362,12 @@ void FramebufferManagerGLES::DrawPixels(VirtualFramebuffer *vfb, int dstX, int d
MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height);
DisableState();
DrawActiveTexture(0, dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, v0, 1.0f, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
textureCache_->ForgetLastTexture();
bool linearFilter = vfb || g_Config.iBufFilter == SCALE_LINEAR;
DrawActiveTexture(dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, v0, 1.0f, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter);
textureCacheGL_->ForgetLastTexture();
}
void FramebufferManagerGLES::DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) {
MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iTexFiltering == TEX_FILTER_NEAREST ? GL_NEAREST : GL_LINEAR);
@@ -413,36 +399,39 @@ void FramebufferManagerGLES::DrawFramebufferToOutput(const u8 *srcPixels, GEBuff
// We are drawing directly to the back buffer.
std::swap(v0, v1);
bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR;
GLSLProgram *program = nullptr;
if (applyPostShader && usePostShader_ && useBufferedRendering_)
program = postShaderProgram_;
if (cardboardSettings.enabled) {
// Left Eye Image
glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
if (applyPostShader && usePostShader_ && useBufferedRendering_) {
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL);
} else {
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
}
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, ROTATION_LOCKED_HORIZONTAL, linearFilter);
// Right Eye Image
glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
if (applyPostShader && usePostShader_ && useBufferedRendering_) {
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL);
} else {
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
}
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, ROTATION_LOCKED_HORIZONTAL, linearFilter);
} else {
// Fullscreen Image
glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_);
if (applyPostShader && usePostShader_ && useBufferedRendering_) {
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation);
} else {
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation);
}
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, uvRotation, linearFilter);
}
}
// x, y, w, h are relative coordinates against destW/destH, which is not very intuitive.
// TODO: This could totally use fbo_blit.
void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation) {
void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation, bool linearFilter) {
if (!program) {
if (!draw2dprogram_) {
CompileDraw2DProgram();
}
program = draw2dprogram_;
}
if (program != postShaderProgram_) {
shaderManager_->DirtyLastShader(); // dirty lastShader_
glsl_bind(program);
}
float texCoords[8] = {
u0,v0,
u1,v0,
@@ -467,11 +456,6 @@ void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y,
memcpy(texCoords, temp, sizeof(temp));
}
if (texture) {
// Previously had NVDrawTexture fallback here but wasn't worth it.
glBindTexture(GL_TEXTURE_2D, texture);
}
float pos[12] = {
x,y,0,
x+w,y,0,
@@ -486,26 +470,13 @@ void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y,
pos[i * 3 + 1] = pos[i * 3 + 1] * invDestH - 1.0f;
}
if (!program) {
if (!draw2dprogram_) {
CompileDraw2DProgram();
}
program = draw2dprogram_;
}
// Upscaling postshaders doesn't look well with linear
if (postShaderIsUpscalingFilter_) {
if (linearFilter) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR);
}
if (program != postShaderProgram_) {
shaderManager_->DirtyLastShader(); // dirty lastShader_
glsl_bind(program);
}
glEnableVertexAttribArray(program->a_position);
@@ -525,28 +496,6 @@ void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y,
}
glDisableVertexAttribArray(program->a_position);
glDisableVertexAttribArray(program->a_texcoord0);
glsl_unbind();
}
void FramebufferManagerGLES::DestroyFramebuf(VirtualFramebuffer *v) {
textureCache_->NotifyFramebuffer(v->fb_address, v, NOTIFY_FB_DESTROYED);
if (v->fbo) {
delete v->fbo;
v->fbo = nullptr;
}
// Wipe some pointers
if (currentRenderVfb_ == v)
currentRenderVfb_ = 0;
if (displayFramebuf_ == v)
displayFramebuf_ = 0;
if (prevDisplayFramebuf_ == v)
prevDisplayFramebuf_ = 0;
if (prevPrevDisplayFramebuf_ == v)
prevPrevDisplayFramebuf_ = 0;
delete v;
}
void FramebufferManagerGLES::RebindFramebuffer() {
@@ -559,177 +508,6 @@ void FramebufferManagerGLES::RebindFramebuffer() {
glstate.viewport.restore();
}
void FramebufferManagerGLES::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) {
VirtualFramebuffer old = *vfb;
if (force) {
vfb->bufferWidth = w;
vfb->bufferHeight = h;
} else {
if (vfb->bufferWidth >= w && vfb->bufferHeight >= h) {
return;
}
// In case it gets thin and wide, don't resize down either side.
vfb->bufferWidth = std::max(vfb->bufferWidth, w);
vfb->bufferHeight = std::max(vfb->bufferHeight, h);
}
SetRenderSize(vfb);
bool trueColor = g_Config.bTrueColor;
if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) {
trueColor = true;
}
if (trueColor) {
vfb->colorDepth = Draw::FBO_8888;
} else {
switch (vfb->format) {
case GE_FORMAT_4444:
vfb->colorDepth = Draw::FBO_4444;
break;
case GE_FORMAT_5551:
vfb->colorDepth = Draw::FBO_5551;
break;
case GE_FORMAT_565:
vfb->colorDepth = Draw::FBO_565;
break;
case GE_FORMAT_8888:
default:
vfb->colorDepth = Draw::FBO_8888;
break;
}
}
textureCache_->ForgetLastTexture();
draw_->BindBackbufferAsRenderTarget();
if (!useBufferedRendering_) {
if (vfb->fbo) {
delete vfb->fbo;
vfb->fbo = nullptr;
}
return;
}
vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth });
if (old.fbo) {
INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format);
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
ClearBuffer();
if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) {
BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0);
}
}
delete old.fbo;
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
}
}
if (!vfb->fbo) {
ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight);
}
}
void FramebufferManagerGLES::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) {
if (!useBufferedRendering_) {
draw_->BindBackbufferAsRenderTarget();
// Let's ignore rendering to targets that have not (yet) been displayed.
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
}
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED);
// Some AMD drivers crash if we don't clear the buffer first?
glDisable(GL_DITHER); // why?
ClearBuffer();
// ugly...
if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerGLES::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
} else {
DownloadFramebufferOnSwitch(prevVfb);
}
textureCache_->ForgetLastTexture();
if (useBufferedRendering_) {
if (vfb->fbo) {
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
} else {
// wtf? This should only happen very briefly when toggling bBufferedRendering
draw_->BindBackbufferAsRenderTarget();
}
} else {
if (vfb->fbo) {
// wtf? This should only happen very briefly when toggling bBufferedRendering
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_DESTROYED);
delete vfb->fbo;
vfb->fbo = nullptr;
}
draw_->BindBackbufferAsRenderTarget();
// Let's ignore rendering to targets that have not (yet) been displayed.
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
} else {
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
}
}
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
if (gl_extensions.IsGLES) {
// Some tiled mobile GPUs benefit IMMENSELY from clearing an FBO before rendering
// to it. This broke stuff before, so now it only clears on the first use of an
// FBO in a frame. This means that some games won't be able to avoid the on-some-GPUs
// performance-crushing framebuffer reloads from RAM, but we'll have to live with that.
if (vfb->last_frame_render != gpuStats.numFlips) {
ClearBuffer();
}
}
// Copy depth pixel value from the read framebuffer to the draw framebuffer
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !prevVfb->depthUpdated || isClearingDepth) {
// If depth wasn't updated, then we're at least "two degrees" away from the data.
// This is an optimization: it probably doesn't need to be copied in this case.
} else {
BlitFramebufferDepth(prevVfb, vfb);
}
}
if (vfb->drawnFormat != vfb->format) {
// TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer().
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
}
// ugly...
if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerGLES::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) {
if (vfbFormatChanged) {
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
if (vfb->drawnFormat != vfb->format) {
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
}
}
// ugly...
if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) {
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
}
}
void FramebufferManagerGLES::SetLineWidth() {
#ifndef USING_GLES2
if (g_Config.iInternalResolution == 0) {
@@ -793,25 +571,6 @@ void FramebufferManagerGLES::BlitFramebufferDepth(VirtualFramebuffer *src, Virtu
}
}
Draw::Framebuffer *FramebufferManagerGLES::GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth) {
u64 key = ((u64)depth << 32) | ((u32)w << 16) | h;
auto it = tempFBOs_.find(key);
if (it != tempFBOs_.end()) {
it->second.last_frame_used = gpuStats.numFlips;
return it->second.fbo;
}
textureCache_->ForgetLastTexture();
Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, depth });
if (!fbo)
return fbo;
draw_->BindFramebufferAsRenderTarget(fbo);
ClearBuffer(true);
const TempFBO info = {fbo, gpuStats.numFlips};
tempFBOs_[key] = info;
return fbo;
}
void FramebufferManagerGLES::BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags) {
if (framebuffer == NULL) {
framebuffer = currentRenderVfb_;
@@ -876,32 +635,6 @@ void FramebufferManagerGLES::BindFramebufferColor(int stage, u32 fbRawAddress, V
}
}
struct CardboardSettings * FramebufferManagerGLES::GetCardboardSettings(struct CardboardSettings * cardboardSettings) {
if (cardboardSettings) {
// Calculate Cardboard Settings
float cardboardScreenScale = g_Config.iCardboardScreenSize / 100.0f;
float cardboardScreenWidth = pixelWidth_ / 2.0f * cardboardScreenScale;
float cardboardScreenHeight = pixelHeight_ / 2.0f * cardboardScreenScale;
float cardboardMaxXShift = (pixelWidth_ / 2.0f - cardboardScreenWidth) / 2.0f;
float cardboardUserXShift = g_Config.iCardboardXShift / 100.0f * cardboardMaxXShift;
float cardboardLeftEyeX = cardboardMaxXShift + cardboardUserXShift;
float cardboardRightEyeX = pixelWidth_ / 2.0f + cardboardMaxXShift - cardboardUserXShift;
float cardboardMaxYShift = pixelHeight_ / 2.0f - cardboardScreenHeight / 2.0f;
float cardboardUserYShift = g_Config.iCardboardYShift / 100.0f * cardboardMaxYShift;
float cardboardScreenY = cardboardMaxYShift + cardboardUserYShift;
// Copy current Settings into Structure
cardboardSettings->enabled = g_Config.bEnableCardboard;
cardboardSettings->leftEyeXPosition = cardboardLeftEyeX;
cardboardSettings->rightEyeXPosition = cardboardRightEyeX;
cardboardSettings->screenYPosition = cardboardScreenY;
cardboardSettings->screenWidth = cardboardScreenWidth;
cardboardSettings->screenHeight = cardboardScreenHeight;
}
return cardboardSettings;
}
void FramebufferManagerGLES::CopyDisplayToOutput() {
DownloadFramebufferOnSwitch(currentRenderVfb_);
@@ -931,7 +664,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() {
u32 offsetX = 0;
u32 offsetY = 0;
struct CardboardSettings cardboardSettings;
CardboardSettings cardboardSettings;
GetCardboardSettings(&cardboardSettings);
VirtualFramebuffer *vfb = GetVFBAt(displayFramebufPtr_);
@@ -1031,21 +764,22 @@ void FramebufferManagerGLES::CopyDisplayToOutput() {
float v1 = (272.0f + offsetY) / (float)vfb->bufferHeight;
if (!usePostShader_) {
bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR;
// We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must
// flip V.
std::swap(v0, v1);
if (cardboardSettings.enabled) {
// Left Eye Image
glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter);
// Right Eye Image
glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter);
} else {
// Fullscreen Image
glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation, linearFilter);
}
} else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) {
// An additional pass, post-processing shader to the extra FBO.
@@ -1056,7 +790,8 @@ void FramebufferManagerGLES::CopyDisplayToOutput() {
shaderManager_->DirtyLastShader(); // dirty lastShader_
glsl_bind(postShaderProgram_);
UpdatePostShaderUniforms(vfb->bufferWidth, vfb->bufferHeight, renderWidth_, renderHeight_);
DrawActiveTexture(0, 0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL);
bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR;
DrawActiveTexture(0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL, linearFilter);
draw_->BindBackbufferAsRenderTarget();
@@ -1072,18 +807,19 @@ void FramebufferManagerGLES::CopyDisplayToOutput() {
// flip V.
std::swap(v0, v1);
linearFilter = !postShaderIsUpscalingFilter_ && g_Config.iBufFilter == SCALE_LINEAR;
if (g_Config.bEnableCardboard) {
// Left Eye Image
glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter);
// Right Eye Image
glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter);
} else {
// Fullscreen Image
glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation, linearFilter);
}
if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) {
@@ -1095,6 +831,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() {
// We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must
// flip V.
std::swap(v0, v1);
bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR;
shaderManager_->DirtyLastShader(); // dirty lastShader_
glsl_bind(postShaderProgram_);
@@ -1102,19 +839,17 @@ void FramebufferManagerGLES::CopyDisplayToOutput() {
if (g_Config.bEnableCardboard) {
// Left Eye Image
glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter);
// Right Eye Image
glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter);
} else {
// Fullscreen Image
glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation, linearFilter);
}
}
glBindTexture(GL_TEXTURE_2D, 0);
}
}
@@ -1148,7 +883,7 @@ void FramebufferManagerGLES::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bo
}
}
textureCache_->ForgetLastTexture();
textureCacheGL_->ForgetLastTexture();
RebindFramebuffer();
}
}
@@ -1186,7 +921,7 @@ void FramebufferManagerGLES::DownloadFramebufferForClut(u32 fb_address, u32 load
PackFramebufferSync_(nvfb, x, y, w, h);
textureCache_->ForgetLastTexture();
textureCacheGL_->ForgetLastTexture();
RebindFramebuffer();
}
}
@@ -1220,7 +955,7 @@ bool FramebufferManagerGLES::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb)
draw_->BindFramebufferAsRenderTarget(nvfb->fbo);
ClearBuffer();
glDisable(GL_DITHER);
glDisable(GL_DITHER); // Weird place to do this
return true;
}
@@ -1316,9 +1051,9 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
// Should maybe revamp that interface.
float srcW = src->bufferWidth;
float srcH = src->bufferHeight;
DrawActiveTexture(0, dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, draw2dprogram_, ROTATION_LOCKED_HORIZONTAL);
DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, draw2dprogram_, ROTATION_LOCKED_HORIZONTAL, false);
glBindTexture(GL_TEXTURE_2D, 0);
textureCache_->ForgetLastTexture();
textureCacheGL_->ForgetLastTexture();
glstate.viewport.restore();
glstate.blend.restore();
glstate.cullFace.restore();
@@ -1729,9 +1464,6 @@ void FramebufferManagerGLES::EndFrame() {
// TODO: Only do this if the new size actually changed the renderwidth/height.
DestroyAllFBOs(false);
// Probably not necessary
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
// Check if postprocessing shader is doing upscaling as it requires native resolution
const ShaderInfo *shaderInfo = 0;
if (g_Config.sPostShaderName != "Off") {
@@ -1821,53 +1553,6 @@ std::vector<FramebufferInfo> FramebufferManagerGLES::GetFramebufferList() {
return list;
}
void FramebufferManagerGLES::DecimateFBOs() {
draw_->BindBackbufferAsRenderTarget();
currentRenderVfb_ = 0;
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i];
int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used);
if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) {
bool sync = gl_extensions.IsGLES;
ReadFramebufferToMemory(vfb, sync, 0, 0, vfb->width, vfb->height);
}
// Let's also "decimate" the usageFlags.
UpdateFramebufUsage(vfb);
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--);
}
}
}
for (auto it = tempFBOs_.begin(); it != tempFBOs_.end(); ) {
int age = frameLastFramebufUsed_ - it->second.last_frame_used;
if (age > FBO_OLD_AGE) {
delete it->second.fbo;
tempFBOs_.erase(it++);
} else {
++it;
}
}
// Do the same for ReadFramebuffersToMemory's VFBs
for (size_t i = 0; i < bvfbs_.size(); ++i) {
VirtualFramebuffer *vfb = bvfbs_[i];
int age = frameLastFramebufUsed_ - vfb->last_frame_render;
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
bvfbs_.erase(bvfbs_.begin() + i--);
}
}
}
void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) {
draw_->BindBackbufferAsRenderTarget();
currentRenderVfb_ = 0;
@@ -1952,7 +1637,7 @@ bool FramebufferManagerGLES::GetFramebuffer(u32 fb_address, int fb_stride, GEBuf
glPixelStorei(GL_PACK_ALIGNMENT, 4);
SafeGLReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData());
// We may have clitted to a temp FBO.
// We may have blitted to a temp FBO.
RebindFramebuffer();
return true;
}
+6 -42
View File
@@ -51,23 +51,12 @@ struct AsyncPBO {
bool reading;
};
struct CardboardSettings {
bool enabled;
float leftEyeXPosition;
float rightEyeXPosition;
float screenYPosition;
float screenWidth;
float screenHeight;
};
class FramebufferManagerGLES : public FramebufferManagerCommon {
public:
FramebufferManagerGLES(Draw::DrawContext *draw);
~FramebufferManagerGLES();
void SetTextureCache(TextureCacheGLES *tc) {
textureCache_ = tc;
}
void SetTextureCache(TextureCacheGLES *tc);
void SetShaderManager(ShaderManagerGLES *sm) {
shaderManager_ = sm;
}
@@ -78,9 +67,8 @@ public:
void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override;
void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) override;
// If texture != 0, will bind it.
// x,y,w,h are relative to destW, destH which fill out the target completely.
void DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation);
void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation, bool linearFilter);
void DestroyAllFBOs(bool forceDelete);
@@ -90,9 +78,9 @@ public:
void DeviceLost();
void CopyDisplayToOutput();
void SetLineWidth();
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old);
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) override;
// For use when texturing from a framebuffer. May create a duplicate if target.
void BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags);
@@ -105,33 +93,21 @@ public:
bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
void DestroyFramebuf(VirtualFramebuffer *vfb) override;
void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override;
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes);
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer);
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer);
static bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
virtual void RebindFramebuffer() override;
Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888);
// Cardboard Settings Calculator
struct CardboardSettings * GetCardboardSettings(struct CardboardSettings * cardboardSettings);
protected:
void DisableState() override;
void ClearBuffer(bool keepState = false) override;
void FlushBeforeCopy() override;
void DecimateFBOs() override;
// Used by ReadFramebufferToMemory and later framebuffer block copies
void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override;
void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) override;
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override;
void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) override;
bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
@@ -141,8 +117,6 @@ private:
void CompileDraw2DProgram();
void DestroyDraw2DProgram();
void SetNumExtraFBOs(int num);
void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently
void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h);
void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h);
@@ -164,22 +138,12 @@ private:
int pixelDeltaLoc_;
int deltaLoc_;
TextureCacheGLES *textureCache_;
TextureCacheGLES *textureCacheGL_;
ShaderManagerGLES *shaderManager_;
DrawEngineGLES *drawEngine_;
// Used by post-processing shader
std::vector<Draw::Framebuffer *> extraFBOs_;
bool resized_;
struct TempFBO {
Draw::Framebuffer *fbo;
int last_frame_used;
};
std::map<u64, TempFBO> tempFBOs_;
// Not used under ES currently.
AsyncPBO *pixelBufObj_; //this isn't that large
u8 currentPBO_;
+1 -1
View File
@@ -1295,7 +1295,7 @@ bool GPU_GLES::GetCurrentClut(GPUDebugBuffer &buffer) {
}
bool GPU_GLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
return FramebufferManagerGLES::GetOutputFramebuffer(buffer);
return framebufferManagerGL_->GetOutputFramebuffer(buffer);
}
bool GPU_GLES::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) {
+2 -2
View File
@@ -190,7 +190,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
glViewport(0, 0, w, h);
MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight);
textureCache_->ForgetLastTexture();
textureCacheGL_->ForgetLastTexture();
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
@@ -215,7 +215,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
glstate.stencilMask.set(i);
glUniform1f(u_stencilValue, i * (1.0f / 255.0f));
}
DrawActiveTexture(0, 0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, stencilUploadProgram_, ROTATION_LOCKED_HORIZONTAL);
DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, stencilUploadProgram_, ROTATION_LOCKED_HORIZONTAL, false);
}
glstate.stencilMask.set(0xFF);
+1 -1
View File
@@ -72,7 +72,7 @@ public:
return cache.size();
}
void ForgetLastTexture() {
void ForgetLastTexture() override {
lastBoundTexture = -1;
gstate_c.Dirty(DIRTY_TEXTURE_PARAMS);
}
+23 -226
View File
@@ -86,7 +86,7 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(Draw::DrawContext *draw, Vulk
drawPixelsTexFormat_(GE_FORMAT_INVALID),
convBuf_(nullptr),
convBufSize_(0),
textureCache_(nullptr),
textureCacheVulkan_(nullptr),
shaderManager_(nullptr),
resized_(false),
pixelBufObj_(nullptr),
@@ -106,6 +106,11 @@ FramebufferManagerVulkan::~FramebufferManagerVulkan() {
DestroyDeviceObjects();
}
void FramebufferManagerVulkan::SetTextureCache(TextureCacheVulkan *tc) {
textureCacheVulkan_ = tc;
textureCache_ = tc;
}
void FramebufferManagerVulkan::InitDeviceObjects() {
// Create a bunch of render pass objects, for normal rendering with a depth buffer,
// with and without pre-clearing of both depth/stencil and color, so 4 combos.
@@ -416,7 +421,7 @@ void FramebufferManagerVulkan::DrawPixels(VirtualFramebuffer *vfb, int dstX, int
VulkanTexture *pixelTex = MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height);
DrawTexture(pixelTex, dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, pipelineBasicTex_, ROTATION_LOCKED_HORIZONTAL);
textureCache_->ForgetLastTexture();
textureCacheVulkan_->ForgetLastTexture();
}
void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) {
@@ -440,7 +445,12 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu
VkPipeline postShaderProgram_ = VK_NULL_HANDLE;
struct CardboardSettings cardboardSettings;
VkPipeline program = pipelineBasicTex_;
if (applyPostShader && usePostShader_ && useBufferedRendering_) {
program = postShaderProgram_;
}
CardboardSettings cardboardSettings;
GetCardboardSettings(&cardboardSettings);
// TODO: Don't use the viewport mechanism for this.
@@ -454,20 +464,13 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu
vp.width = cardboardSettings.screenWidth;
vp.height = cardboardSettings.screenHeight;
vkCmdSetViewport(curCmd_, 0, 1, &vp);
if (applyPostShader && usePostShader_ && useBufferedRendering_) {
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL);
} else {
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, pipelineBasicTex_, ROTATION_LOCKED_HORIZONTAL);
}
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, ROTATION_LOCKED_HORIZONTAL);
// Right Eye Image
vp.x = cardboardSettings.rightEyeXPosition;
vkCmdSetViewport(curCmd_, 0, 1, &vp);
if (applyPostShader && usePostShader_ && useBufferedRendering_) {
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL);
} else {
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, pipelineBasicTex_, ROTATION_LOCKED_HORIZONTAL);
}
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, ROTATION_LOCKED_HORIZONTAL);
} else {
// Fullscreen Image
vp.x = 0.0f;
@@ -475,11 +478,7 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu
vp.width = pixelWidth_;
vp.height = pixelHeight_;
vkCmdSetViewport(curCmd_, 0, 1, &vp);
if (applyPostShader && usePostShader_ && useBufferedRendering_) {
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation);
} else {
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, pipelineBasicTex_, uvRotation);
}
DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, uvRotation);
}
}
@@ -536,182 +535,11 @@ void FramebufferManagerVulkan::DrawTexture(VulkanTexture *texture, float x, floa
vkCmdDraw(cmd, 4, 1, 0, 0);
}
void FramebufferManagerVulkan::DestroyFramebuf(VirtualFramebuffer *v) {
textureCache_->NotifyFramebuffer(v->fb_address, v, NOTIFY_FB_DESTROYED);
if (v->fbo) {
delete v->fbo;
v->fbo = 0;
}
// Wipe some pointers
if (currentRenderVfb_ == v)
currentRenderVfb_ = 0;
if (displayFramebuf_ == v)
displayFramebuf_ = 0;
if (prevDisplayFramebuf_ == v)
prevDisplayFramebuf_ = 0;
if (prevPrevDisplayFramebuf_ == v)
prevPrevDisplayFramebuf_ = 0;
delete v;
}
void FramebufferManagerVulkan::RebindFramebuffer() {
// Switch command buffer?
}
void FramebufferManagerVulkan::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) {
return;
/*
VirtualFramebuffer old = *vfb;
if (force) {
vfb->bufferWidth = w;
vfb->bufferHeight = h;
if (currentRenderVfb_ && currentRenderVfb_->fbo) {
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo);
} else {
if (vfb->bufferWidth >= w && vfb->bufferHeight >= h) {
return;
}
// In case it gets thin and wide, don't resize down either side.
vfb->bufferWidth = std::max(vfb->bufferWidth, w);
vfb->bufferHeight = std::max(vfb->bufferHeight, h);
}
SetRenderSize(vfb);
bool trueColor = g_Config.bTrueColor;
if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) {
trueColor = true;
}
if (trueColor) {
vfb->colorDepth = VK_FBO_8888;
} else {
switch (vfb->format) {
case GE_FORMAT_4444:
vfb->colorDepth = VK_FBO_4444;
break;
case GE_FORMAT_5551:
vfb->colorDepth = VK_FBO_5551;
break;
case GE_FORMAT_565:
vfb->colorDepth = VK_FBO_565;
break;
case GE_FORMAT_8888:
default:
vfb->colorDepth = VK_FBO_8888;
break;
}
}
textureCache_->ForgetLastTexture();
if (!useBufferedRendering_) {
if (vfb->fbo) {
delete vfb->fbo;
vfb->fbo = 0;
}
return;
}
vfb->fbo = new VulkanFBO();
// bo_create(vfb->renderWidth, vfb->renderHeight, 1, true, (FBOColorDepth)vfb->colorDepth);
if (old.fbo) {
INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format);
if (vfb->fbo) {
/// BindFramebufferAsRenderTargetvfb->fbo);
ClearBuffer();
if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) {
BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0);
}
}
delete old.fbo;
if (vfb->fbo) {
// BindFramebufferAsRenderTargetvfb->fbo);
}
}
if (!vfb->fbo) {
ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight);
}
*/
}
void FramebufferManagerVulkan::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) {
if (!useBufferedRendering_) {
// Let's ignore rendering to targets that have not (yet) been displayed.
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
}
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED);
// ugly...
if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
}
void FramebufferManagerVulkan::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
} else {
DownloadFramebufferOnSwitch(prevVfb);
}
textureCache_->ForgetLastTexture();
if (useBufferedRendering_) {
if (vfb->fbo) {
// vfb->fbo->GetColorImageView();
}
} else {
if (vfb->fbo) {
// wtf? This should only happen very briefly when toggling bBufferedRendering
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_DESTROYED);
delete vfb->fbo;
vfb->fbo = nullptr;
}
// Let's ignore rendering to targets that have not (yet) been displayed.
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
} else {
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
}
}
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
// Copy depth pixel value from the read framebuffer to the draw framebuffer
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !prevVfb->depthUpdated || isClearingDepth) {
// If depth wasn't updated, then we're at least "two degrees" away from the data.
// This is an optimization: it probably doesn't need to be copied in this case.
} else {
BlitFramebufferDepth(prevVfb, vfb);
}
}
if (vfb->drawnFormat != vfb->format) {
// TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer().
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
}
// ugly...
if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
}
void FramebufferManagerVulkan::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) {
if (vfbFormatChanged) {
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
if (vfb->drawnFormat != vfb->format) {
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
}
}
// ugly...
if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
draw_->BindBackbufferAsRenderTarget();
}
}
@@ -721,7 +549,6 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skip
return false;
}
int FramebufferManagerVulkan::GetLineWidth() {
if (g_Config.iInternalResolution == 0) {
return std::max(1, (int)(renderWidth_ / 480));
@@ -833,11 +660,6 @@ VulkanTexture *FramebufferManagerVulkan::GetFramebufferColor(u32 fbRawAddress, V
}
}
struct CardboardSettings * FramebufferManagerVulkan::GetCardboardSettings(struct CardboardSettings * cardboardSettings) {
cardboardSettings->enabled = false;
return nullptr;
}
void FramebufferManagerVulkan::CopyDisplayToOutput() {
// This is where we should collect all the renderpasses from this frame,
// sort them in order according to texturing dependencies, and enqueue
@@ -947,7 +769,7 @@ void FramebufferManagerVulkan::CopyDisplayToOutput() {
displayFramebuf_ = vfb;
if (vfb->fbo) {
struct CardboardSettings cardboardSettings;
CardboardSettings cardboardSettings;
GetCardboardSettings(&cardboardSettings);
DEBUG_LOG(SCEGE, "Displaying FBO %08x", vfb->fb_address);
@@ -1075,7 +897,7 @@ void FramebufferManagerVulkan::ReadFramebufferToMemory(VirtualFramebuffer *vfb,
PackFramebufferSync_(nvfb, x, y, w, h);
}
textureCache_->ForgetLastTexture();
textureCacheVulkan_->ForgetLastTexture();
RebindFramebuffer();
}
}
@@ -1110,7 +932,7 @@ void FramebufferManagerVulkan::DownloadFramebufferForClut(u32 fb_address, u32 lo
PackFramebufferSync_(nvfb, x, y, w, h);
textureCache_->ForgetLastTexture();
textureCacheVulkan_->ForgetLastTexture();
RebindFramebuffer();
}
}
@@ -1578,31 +1400,6 @@ std::vector<FramebufferInfo> FramebufferManagerVulkan::GetFramebufferList() {
return list;
}
void FramebufferManagerVulkan::DecimateFBOs() {
currentRenderVfb_ = 0;
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i];
int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used);
if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) {
bool sync = true;
ReadFramebufferToMemory(vfb, sync, 0, 0, vfb->width, vfb->height);
}
// Let's also "decimate" the usageFlags.
UpdateFramebufUsage(vfb);
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--);
}
}
}
}
void FramebufferManagerVulkan::DestroyAllFBOs(bool forceDelete) {
currentRenderVfb_ = 0;
displayFramebuf_ = 0;
+4 -27
View File
@@ -64,23 +64,12 @@ struct AsyncPBOVulkan {
bool reading;
};
struct CardboardSettings {
bool enabled;
float leftEyeXPosition;
float rightEyeXPosition;
float screenYPosition;
float screenWidth;
float screenHeight;
};
class FramebufferManagerVulkan : public FramebufferManagerCommon {
public:
FramebufferManagerVulkan(Draw::DrawContext *draw, VulkanContext *vulkan);
~FramebufferManagerVulkan();
void SetTextureCache(TextureCacheVulkan *tc) {
textureCache_ = tc;
}
void SetTextureCache(TextureCacheVulkan *tc);
void SetShaderManager(ShaderManagerVulkan *sm) {
shaderManager_ = sm;
}
@@ -107,9 +96,9 @@ public:
void DeviceRestore(VulkanContext *vulkan);
void CopyDisplayToOutput();
int GetLineWidth();
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old);
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) override;
// For use when texturing from a framebuffer. May create a duplicate if target.
VulkanTexture *GetFramebufferColor(u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags);
@@ -122,9 +111,6 @@ public:
bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
void DestroyFramebuf(VirtualFramebuffer *vfb) override;
void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override;
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer);
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer);
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer);
@@ -134,9 +120,6 @@ public:
// VulkanFBO *GetTempFBO(u16 w, u16 h, VulkanFBOColorDepth depth = VK_FBO_8888);
// Cardboard Settings Calculator
struct CardboardSettings * GetCardboardSettings(struct CardboardSettings * cardboardSettings);
// Pass management
// void BeginPassClear()
@@ -151,18 +134,12 @@ protected:
void DisableState() override {}
void ClearBuffer(bool keepState = false) override;
void FlushBeforeCopy() override;
void DecimateFBOs() override;
// Used by ReadFramebufferToMemory and later framebuffer block copies
void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override;
void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) override;
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override;
void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) override;
bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
private:
// The returned texture does not need to be free'd, might be returned from a pool (currently single entry)
@@ -193,7 +170,7 @@ private:
u8 *convBuf_;
u32 convBufSize_;
TextureCacheVulkan *textureCache_;
TextureCacheVulkan *textureCacheVulkan_;
ShaderManagerVulkan *shaderManager_;
DrawEngineVulkan *drawEngine_;
+1 -1
View File
@@ -119,7 +119,7 @@ public:
return cache.size();
}
void ForgetLastTexture() {
void ForgetLastTexture() override {
lastBoundTexture = nullptr;
gstate_c.Dirty(DIRTY_TEXTURE_PARAMS);
}