mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Merge pull request #13634 from hrydgard/device-lost-improvements
Device lost improvements, unify BindFramebufferAsColorTexture
This commit is contained in:
18 files changed
+112
-196
No files matched your search
@@ -465,6 +465,8 @@ public:
|
||||
|
||||
uint64_t GetNativeObject(NativeObject obj) override {
|
||||
switch (obj) {
|
||||
case NativeObject::CONTEXT:
|
||||
return (uint64_t)vulkan_;
|
||||
case NativeObject::FRAMEBUFFER_RENDERPASS:
|
||||
// Return a representative renderpass.
|
||||
return (uint64_t)renderManager_.GetFramebufferRenderPass();
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "GPU/Common/PresentationCommon.h"
|
||||
#include "GPU/Common/TextureCacheCommon.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
@@ -702,6 +703,49 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int
|
||||
}
|
||||
}
|
||||
|
||||
bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (!framebuffer->fbo || !useBufferedRendering_) {
|
||||
draw_->BindTexture(0, nullptr);
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
|
||||
// Let's just not bother with the copy in that case.
|
||||
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
|
||||
if (GPUStepping::IsStepping()) {
|
||||
skipCopy = true;
|
||||
}
|
||||
// Currently rendering to this framebuffer. Need to make a copy.
|
||||
if (!skipCopy && framebuffer == currentRenderVfb_) {
|
||||
// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
|
||||
Draw::Framebuffer *renderCopy = GetTempFBO(TempFBO::COPY, framebuffer->renderWidth, framebuffer->renderHeight);
|
||||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
copyInfo.fbo = renderCopy;
|
||||
CopyFramebufferForColorTexture(©Info, framebuffer, flags);
|
||||
RebindFramebuffer("After BindFramebufferAsColorTexture");
|
||||
draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0);
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
}
|
||||
return true;
|
||||
} else if (framebuffer != currentRenderVfb_ || (flags & BINDFBCOLOR_FORCE_SELF) != 0) {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
return true;
|
||||
} else {
|
||||
ERROR_LOG_REPORT_ONCE(vulkanSelfTexture, G3D, "Attempting to texture from target (src=%08x / target=%08x / flags=%d)", framebuffer->fb_address, currentRenderVfb_->fb_address, flags);
|
||||
// To do this safely in Vulkan, we need to use input attachments.
|
||||
// Actually if the texture region and render regions don't overlap, this is safe, but we need
|
||||
// to transition to GENERAL image layout which will take some trickery.
|
||||
// Badness on D3D11 to bind the currently rendered-to framebuffer as a texture.
|
||||
draw_->BindTexture(0, nullptr);
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags) {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
@@ -2102,3 +2146,14 @@ std::vector<FramebufferInfo> FramebufferManagerCommon::GetFramebufferList() {
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::DeviceLost() {
|
||||
DestroyAllFBOs();
|
||||
presentation_->DeviceLost();
|
||||
draw_ = nullptr;
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::DeviceRestore(Draw::DrawContext *draw) {
|
||||
draw_ = draw;
|
||||
presentation_->DeviceRestore(draw);
|
||||
}
|
||||
@@ -233,6 +233,7 @@ public:
|
||||
bool NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason);
|
||||
void NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason);
|
||||
|
||||
bool BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags);
|
||||
void ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h);
|
||||
|
||||
void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes);
|
||||
@@ -305,6 +306,9 @@ public:
|
||||
virtual void Resized();
|
||||
virtual void DestroyAllFBOs();
|
||||
|
||||
virtual void DeviceLost();
|
||||
virtual void DeviceRestore(Draw::DrawContext *draw);
|
||||
|
||||
Draw::Framebuffer *GetTempFBO(TempFBO reason, u16 w, u16 h);
|
||||
|
||||
// Debug features
|
||||
@@ -424,9 +428,4 @@ protected:
|
||||
FBO_OLD_AGE = 5,
|
||||
FBO_OLD_USAGE_FLAG = 15,
|
||||
};
|
||||
|
||||
// Thin3D stuff for reinterpreting image data between the various 16-bit formats.
|
||||
// Safe, not optimal - there might be input attachment tricks, etc, but we can't use them
|
||||
// since we don't want N different implementations.
|
||||
Draw::Pipeline *reinterpretFromTo_[3][3];
|
||||
};
|
||||
@@ -314,45 +314,6 @@ static void CopyPixelDepthOnly(u32 *dstp, const u32 *srcp, size_t c) {
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerD3D11::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (!framebuffer->fbo || !useBufferedRendering_) {
|
||||
ID3D11ShaderResourceView *view = nullptr;
|
||||
context_->PSSetShaderResources(stage, 1, &view);
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return;
|
||||
}
|
||||
|
||||
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
|
||||
// Let's just not bother with the copy in that case.
|
||||
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
|
||||
if (GPUStepping::IsStepping()) {
|
||||
skipCopy = true;
|
||||
}
|
||||
// Currently rendering to this framebuffer. Need to make a copy.
|
||||
if (!skipCopy && framebuffer == currentRenderVfb_) {
|
||||
// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
|
||||
Draw::Framebuffer *renderCopy = GetTempFBO(TempFBO::COPY, framebuffer->renderWidth, framebuffer->renderHeight);
|
||||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
copyInfo.fbo = renderCopy;
|
||||
CopyFramebufferForColorTexture(©Info, framebuffer, flags);
|
||||
RebindFramebuffer("RebindFramebuffer - BindFramebufferAsColorTexture");
|
||||
draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0);
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
}
|
||||
} else if (framebuffer != currentRenderVfb_ || (flags & BINDFBCOLOR_FORCE_SELF) != 0) {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
} else {
|
||||
ERROR_LOG_REPORT_ONCE(d3d11SelfTexture, G3D, "Attempting to texture from target (src=%08x / target=%08x / flags=%d)", framebuffer->fb_address, currentRenderVfb_->fb_address, flags);
|
||||
// Badness on D3D11 to bind the currently rendered-to framebuffer as a texture.
|
||||
ID3D11ShaderResourceView *view = nullptr;
|
||||
context_->PSSetShaderResources(stage, 1, &view);
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerD3D11::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) {
|
||||
// Nothing to do here.
|
||||
}
|
||||
@@ -468,7 +429,3 @@ void FramebufferManagerD3D11::PackDepthbuffer(VirtualFramebuffer *vfb, int x, in
|
||||
|
||||
void FramebufferManagerD3D11::EndFrame() {
|
||||
}
|
||||
|
||||
void FramebufferManagerD3D11::DeviceLost() {
|
||||
DestroyAllFBOs();
|
||||
}
|
||||
@@ -42,11 +42,8 @@ public:
|
||||
void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) override;
|
||||
|
||||
void EndFrame();
|
||||
void DeviceLost();
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
|
||||
|
||||
void BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags);
|
||||
|
||||
virtual bool NotifyStencilUpload(u32 addr, int size, StencilUpload flags = StencilUpload::NEEDS_CLEAR) override;
|
||||
|
||||
// TODO: Remove
|
||||
|
||||
@@ -198,10 +198,12 @@ void GPU_D3D11::DeviceLost() {
|
||||
shaderManagerD3D11_->ClearShaders();
|
||||
drawEngine_.ClearInputLayoutMap();
|
||||
textureCacheD3D11_->Clear(false);
|
||||
framebufferManagerD3D11_->DeviceLost();
|
||||
|
||||
GPUCommon::DeviceLost();
|
||||
}
|
||||
|
||||
void GPU_D3D11::DeviceRestore() {
|
||||
GPUCommon::DeviceRestore();
|
||||
// Nothing needed.
|
||||
}
|
||||
|
||||
|
||||
@@ -336,41 +336,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
|
||||
return offscreen;
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (framebuffer == NULL) {
|
||||
framebuffer = currentRenderVfb_;
|
||||
}
|
||||
|
||||
if (!framebuffer->fbo || !useBufferedRendering_) {
|
||||
device_->SetTexture(stage, nullptr);
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return;
|
||||
}
|
||||
|
||||
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
|
||||
// Let's just not bother with the copy in that case.
|
||||
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
|
||||
if (GPUStepping::IsStepping()) {
|
||||
skipCopy = true;
|
||||
}
|
||||
if (!skipCopy && framebuffer == currentRenderVfb_) {
|
||||
// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
|
||||
Draw::Framebuffer *renderCopy = GetTempFBO(TempFBO::COPY, framebuffer->renderWidth, framebuffer->renderHeight);
|
||||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
copyInfo.fbo = renderCopy;
|
||||
|
||||
CopyFramebufferForColorTexture(©Info, framebuffer, flags);
|
||||
RebindFramebuffer("RebindFramebuffer - BindFramebufferAsColorTexture");
|
||||
draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0);
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
}
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) {
|
||||
// Nothing to do here.
|
||||
}
|
||||
@@ -559,10 +524,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
|
||||
void FramebufferManagerDX9::EndFrame() {
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::DeviceLost() {
|
||||
DestroyAllFBOs();
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::DecimateFBOs() {
|
||||
FramebufferManagerCommon::DecimateFBOs();
|
||||
for (auto it = offscreenSurfaces_.begin(); it != offscreenSurfaces_.end(); ) {
|
||||
|
||||
@@ -47,11 +47,8 @@ public:
|
||||
void DestroyAllFBOs();
|
||||
|
||||
void EndFrame();
|
||||
void DeviceLost();
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
|
||||
|
||||
void BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags);
|
||||
|
||||
virtual bool NotifyStencilUpload(u32 addr, int size, StencilUpload flags = StencilUpload::NEEDS_CLEAR) override;
|
||||
|
||||
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes);
|
||||
|
||||
@@ -242,13 +242,13 @@ void GPU_DX9::BuildReportingInfo() {
|
||||
|
||||
void GPU_DX9::DeviceLost() {
|
||||
// Simply drop all caches and textures.
|
||||
// FBOs appear to survive? Or no?
|
||||
shaderManagerDX9_->ClearCache(false);
|
||||
textureCacheDX9_->Clear(false);
|
||||
framebufferManagerDX9_->DeviceLost();
|
||||
GPUCommon::DeviceLost();
|
||||
}
|
||||
|
||||
void GPU_DX9::DeviceRestore() {
|
||||
GPUCommon::DeviceRestore();
|
||||
// Nothing needed.
|
||||
}
|
||||
|
||||
|
||||
@@ -263,36 +263,6 @@ void FramebufferManagerGLES::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GE
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (!framebuffer->fbo || !useBufferedRendering_) {
|
||||
render_->BindTexture(stage, nullptr);
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return;
|
||||
}
|
||||
|
||||
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
|
||||
// Let's just not bother with the copy in that case.
|
||||
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
|
||||
if (GPUStepping::IsStepping()) {
|
||||
skipCopy = true;
|
||||
}
|
||||
if (!skipCopy && framebuffer == currentRenderVfb_) {
|
||||
// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
|
||||
Draw::Framebuffer *renderCopy = GetTempFBO(TempFBO::COPY, framebuffer->renderWidth, framebuffer->renderHeight);
|
||||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
copyInfo.fbo = renderCopy;
|
||||
|
||||
CopyFramebufferForColorTexture(©Info, framebuffer, flags);
|
||||
draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0);
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
}
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) {
|
||||
_assert_msg_(nvfb->fbo, "Expecting a valid nvfb in UpdateDownloadTempBuffer");
|
||||
|
||||
@@ -389,16 +359,14 @@ void FramebufferManagerGLES::EndFrame() {
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::DeviceLost() {
|
||||
DestroyAllFBOs();
|
||||
FramebufferManagerCommon::DeviceLost();
|
||||
DestroyDeviceObjects();
|
||||
presentation_->DeviceLost();
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::DeviceRestore(Draw::DrawContext *draw) {
|
||||
draw_ = draw;
|
||||
presentation_->DeviceRestore(draw);
|
||||
render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
FramebufferManagerCommon::DeviceRestore(draw);
|
||||
CreateDeviceObjects();
|
||||
render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::Resized() {
|
||||
|
||||
@@ -46,18 +46,16 @@ public:
|
||||
virtual void Init() override;
|
||||
void EndFrame();
|
||||
void Resized() override;
|
||||
void DeviceLost();
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
|
||||
|
||||
// For use when texturing from a framebuffer. May create a duplicate if target.
|
||||
void BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags);
|
||||
void DeviceLost() override;
|
||||
void DeviceRestore(Draw::DrawContext *draw) override;
|
||||
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
|
||||
|
||||
bool NotifyStencilUpload(u32 addr, int size, StencilUpload flags = StencilUpload::NEEDS_CLEAR) override;
|
||||
|
||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
||||
|
||||
void DeviceRestore(Draw::DrawContext *draw);
|
||||
|
||||
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;
|
||||
|
||||
@@ -300,21 +300,18 @@ void GPU_GLES::DeviceLost() {
|
||||
fragmentTestCache_.DeviceLost();
|
||||
depalShaderCache_.DeviceLost();
|
||||
drawEngine_.DeviceLost();
|
||||
framebufferManagerGL_->DeviceLost();
|
||||
// Don't even try to access the lost device.
|
||||
draw_ = nullptr;
|
||||
|
||||
GPUCommon::DeviceLost();
|
||||
}
|
||||
|
||||
void GPU_GLES::DeviceRestore() {
|
||||
draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext();
|
||||
INFO_LOG(G3D, "GPU_GLES: DeviceRestore");
|
||||
GPUCommon::DeviceRestore();
|
||||
|
||||
UpdateCmdInfo();
|
||||
UpdateVsyncInterval(true);
|
||||
|
||||
shaderManagerGL_->DeviceRestore(draw_);
|
||||
textureCacheGL_->DeviceRestore(draw_);
|
||||
framebufferManagerGL_->DeviceRestore(draw_);
|
||||
drawEngine_.DeviceRestore(draw_);
|
||||
fragmentTestCache_.DeviceRestore(draw_);
|
||||
depalShaderCache_.DeviceRestore(draw_);
|
||||
|
||||
@@ -468,6 +468,18 @@ void GPUCommon::Reinitialize() {
|
||||
framebufferManager_->DestroyAllFBOs();
|
||||
}
|
||||
|
||||
// Call at the END of the GPU implementation's DeviceLost
|
||||
void GPUCommon::DeviceLost() {
|
||||
framebufferManager_->DeviceLost();
|
||||
draw_ = nullptr;
|
||||
}
|
||||
|
||||
// Call at the start of the GPU implementation's DeviceRestore
|
||||
void GPUCommon::DeviceRestore() {
|
||||
draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext();
|
||||
framebufferManager_->DeviceRestore(draw_);
|
||||
}
|
||||
|
||||
void GPUCommon::UpdateVsyncInterval(bool force) {
|
||||
#if !(PPSSPP_PLATFORM(ANDROID) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(IOS))
|
||||
int desiredVSyncInterval = g_Config.bVSync ? 1 : 0;
|
||||
|
||||
@@ -260,6 +260,9 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void DeviceLost() override;
|
||||
void DeviceRestore() override;
|
||||
|
||||
void SetDrawType(DrawType type, GEPrimitiveType prim) {
|
||||
if (type != lastDraw_) {
|
||||
// We always flush when drawing splines/beziers so no need to do so here
|
||||
|
||||
@@ -268,42 +268,6 @@ void FramebufferManagerVulkan::ReformatFramebufferFrom(VirtualFramebuffer *vfb,
|
||||
}
|
||||
}
|
||||
|
||||
VkImageView FramebufferManagerVulkan::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (!framebuffer->fbo || !useBufferedRendering_) {
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
|
||||
// Let's just not bother with the copy in that case.
|
||||
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
|
||||
if (GPUStepping::IsStepping()) {
|
||||
skipCopy = true;
|
||||
}
|
||||
// Currently rendering to this framebuffer. Need to make a copy.
|
||||
if (!skipCopy && framebuffer == currentRenderVfb_) {
|
||||
// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
|
||||
Draw::Framebuffer *renderCopy = GetTempFBO(TempFBO::COPY, framebuffer->renderWidth, framebuffer->renderHeight);
|
||||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
copyInfo.fbo = renderCopy;
|
||||
CopyFramebufferForColorTexture(©Info, framebuffer, flags);
|
||||
RebindFramebuffer("RebindFramebuffer - BindFramebufferAsColorTexture");
|
||||
draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0);
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
}
|
||||
return (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE0_IMAGEVIEW);
|
||||
} else if (framebuffer != currentRenderVfb_ || (flags & BINDFBCOLOR_FORCE_SELF) != 0) {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
|
||||
return (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE0_IMAGEVIEW);
|
||||
} else {
|
||||
ERROR_LOG_REPORT_ONCE(vulkanSelfTexture, G3D, "Attempting to texture from target (src=%08x / target=%08x / flags=%d)", framebuffer->fb_address, currentRenderVfb_->fb_address, flags);
|
||||
// To do this safely in Vulkan, we need to use input attachments.
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) {
|
||||
// Nothing to do here.
|
||||
}
|
||||
@@ -388,15 +352,12 @@ void FramebufferManagerVulkan::EndFrame() {
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::DeviceLost() {
|
||||
DestroyAllFBOs();
|
||||
FramebufferManagerCommon::DeviceLost();
|
||||
DestroyDeviceObjects();
|
||||
presentation_->DeviceLost();
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw) {
|
||||
vulkan_ = vulkan;
|
||||
draw_ = draw;
|
||||
presentation_->DeviceRestore(draw);
|
||||
|
||||
void FramebufferManagerVulkan::DeviceRestore(Draw::DrawContext *draw) {
|
||||
FramebufferManagerCommon::DeviceRestore(draw);
|
||||
vulkan_ = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||
InitDeviceObjects();
|
||||
}
|
||||
@@ -49,15 +49,14 @@ public:
|
||||
void BeginFrameVulkan(); // there's a BeginFrame in the base class, which this calls
|
||||
void EndFrame();
|
||||
|
||||
void DeviceLost();
|
||||
void DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw);
|
||||
void DeviceLost() override;
|
||||
void DeviceRestore(Draw::DrawContext *draw) override;
|
||||
|
||||
int GetLineWidth();
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
|
||||
|
||||
bool NotifyStencilUpload(u32 addr, int size, StencilUpload flags = StencilUpload::NEEDS_CLEAR) override;
|
||||
|
||||
VkImageView BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags);
|
||||
|
||||
// If within a render pass, this will just issue a regular clear. If beginning a new render pass,
|
||||
// do that.
|
||||
void NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth);
|
||||
|
||||
@@ -526,26 +526,25 @@ void GPU_Vulkan::DeviceLost() {
|
||||
SaveCache(shaderCachePath_);
|
||||
}
|
||||
DestroyDeviceObjects();
|
||||
framebufferManagerVulkan_->DeviceLost();
|
||||
vulkan2D_.DeviceLost();
|
||||
drawEngine_.DeviceLost();
|
||||
pipelineManager_->DeviceLost();
|
||||
textureCacheVulkan_->DeviceLost();
|
||||
depalShaderCache_.DeviceLost();
|
||||
shaderManagerVulkan_->ClearShaders();
|
||||
draw_ = nullptr;
|
||||
|
||||
GPUCommon::DeviceLost();
|
||||
}
|
||||
|
||||
void GPU_Vulkan::DeviceRestore() {
|
||||
GPUCommon::DeviceRestore();
|
||||
vulkan_ = (VulkanContext *)PSP_CoreParameter().graphicsContext->GetAPIContext();
|
||||
draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext();
|
||||
InitDeviceObjects();
|
||||
|
||||
CheckGPUFeatures();
|
||||
BuildReportingInfo();
|
||||
UpdateCmdInfo();
|
||||
|
||||
framebufferManagerVulkan_->DeviceRestore(vulkan_, draw_);
|
||||
vulkan2D_.DeviceRestore(vulkan_);
|
||||
drawEngine_.DeviceRestore(vulkan_, draw_);
|
||||
pipelineManager_->DeviceRestore(vulkan_);
|
||||
|
||||
@@ -558,7 +558,11 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
|
||||
TexCacheEntry::TexStatus alphaStatus = CheckAlpha(clutBuf_, getClutDestFormatVulkan(clutFormat), clutTotalColors, clutTotalColors, 1);
|
||||
gstate_c.SetTextureFullAlpha(alphaStatus == TexCacheEntry::STATUS_ALPHA_FULL);
|
||||
curSampler_ = samplerCache_.GetOrCreateSampler(samplerKey);
|
||||
imageView_ = framebufferManagerVulkan_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV | BINDFBCOLOR_APPLY_TEX_OFFSET);
|
||||
if (framebufferManagerVulkan_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV | BINDFBCOLOR_APPLY_TEX_OFFSET)) {
|
||||
imageView_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE0_IMAGEVIEW);
|
||||
} else {
|
||||
imageView_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::NULL_IMAGEVIEW);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
depalShader = depalShaderCache_->GetDepalettizeShader(clutMode, depth ? GE_FORMAT_DEPTH16 : framebuffer->drawnFormat);
|
||||
@@ -667,7 +671,12 @@ void TextureCacheVulkan::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
|
||||
// Since we may have switched render targets, we need to re-set depth/stencil etc states.
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE);
|
||||
} else {
|
||||
imageView_ = framebufferManagerVulkan_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV | BINDFBCOLOR_APPLY_TEX_OFFSET);
|
||||
if (framebufferManagerVulkan_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV | BINDFBCOLOR_APPLY_TEX_OFFSET)) {
|
||||
imageView_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE0_IMAGEVIEW);
|
||||
} else {
|
||||
imageView_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::NULL_IMAGEVIEW);
|
||||
}
|
||||
|
||||
drawEngine_->SetDepalTexture(VK_NULL_HANDLE);
|
||||
gstate_c.SetUseShaderDepal(false);
|
||||
|
||||
|
||||
Reference in new issue
Block a user