mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 17:49:29 +01:00
Merge pull request #9287 from hrydgard/fbo-cleanup-3
FBO cleanup 3: The grand unification .. sort of
This commit is contained in:
commit
df86854c69
15 files changed
+469
-965
No files matched your search
@@ -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) {
|
||||
|
||||
@@ -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 ¶ms, 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,
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
return cache.size();
|
||||
}
|
||||
|
||||
void ForgetLastTexture() {
|
||||
void ForgetLastTexture() override {
|
||||
lastBoundTexture = -1;
|
||||
gstate_c.Dirty(DIRTY_TEXTURE_PARAMS);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
return cache.size();
|
||||
}
|
||||
|
||||
void ForgetLastTexture() {
|
||||
void ForgetLastTexture() override {
|
||||
lastBoundTexture = nullptr;
|
||||
gstate_c.Dirty(DIRTY_TEXTURE_PARAMS);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user