Unify (well, almost) GetOutputFramebuffer (D3D11/GL)

This commit is contained in:
Henrik Rydgård 2017-10-16 16:27:16 +02:00
parent 214270d192
commit f2ea0ce472
8 changed files with 36 additions and 94 deletions

View File

@ -1925,3 +1925,12 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G
return false;
#endif
}
bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
int w, h;
draw_->GetFramebufferDimensions(nullptr, &w, &h);
buffer.Allocate(w, h, GE_FORMAT_8888, false, true);
draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w);
return true;
}

View File

@ -281,7 +281,7 @@ public:
virtual bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes);
virtual bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer);
virtual bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer);
virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer) = 0;
virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
protected:
virtual void SetViewport2D(int x, int y, int w, int h);

View File

@ -873,44 +873,3 @@ void FramebufferManagerD3D11::Resized() {
// Might have a new post shader - let's compile it.
CompilePostShader();
}
bool FramebufferManagerD3D11::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
ID3D11Texture2D *backbuffer = (ID3D11Texture2D *)draw_->GetNativeObject(Draw::NativeObject::BACKBUFFER_COLOR_TEX);
if (!backbuffer) {
ERROR_LOG(G3D, "Failed to get backbuffer from draw context");
return false;
}
D3D11_TEXTURE2D_DESC desc;
backbuffer->GetDesc(&desc);
int w = desc.Width;
int h = desc.Height;
buffer.Allocate(w, h, GE_FORMAT_8888, !useBufferedRendering_, true);
ID3D11Texture2D *packTex;
D3D11_TEXTURE2D_DESC packDesc{};
packDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
packDesc.BindFlags = 0;
packDesc.Width = w;
packDesc.Height = h;
packDesc.ArraySize = 1;
packDesc.MipLevels = 1;
packDesc.Usage = D3D11_USAGE_STAGING;
packDesc.SampleDesc.Count = 1;
packDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
ASSERT_SUCCESS(device_->CreateTexture2D(&packDesc, nullptr, &packTex));
context_->CopyResource(packTex, backbuffer);
D3D11_MAPPED_SUBRESOURCE map;
context_->Map(packTex, 0, D3D11_MAP_READ, 0, &map);
for (int y = 0; y < h; y++) {
uint8_t *dest = (uint8_t *)buffer.GetData() + y * w * 4;
const uint8_t *src = ((const uint8_t *)map.pData) + map.RowPitch * y;
memcpy(dest, src, 4 * w);
}
context_->Unmap(packTex, 0);
packTex->Release();
return true;
}

View File

@ -67,8 +67,6 @@ public:
virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
virtual void RebindFramebuffer() override;
// TODO: Remove

View File

@ -1130,12 +1130,9 @@ void FramebufferManagerGLES::Resized() {
}
bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
int pw = PSP_CoreParameter().pixelWidth;
int ph = PSP_CoreParameter().pixelHeight;
// The backbuffer is flipped (last bool)
buffer.Allocate(pw, ph, GPU_DBG_FORMAT_888_RGB, true);
draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, pw, ph, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), pw);
CHECK_GL_ERROR_IF_DEBUG();
int w, h;
draw_->GetFramebufferDimensions(nullptr, &w, &h);
buffer.Allocate(w, h, GPU_DBG_FORMAT_888_RGB, true);
draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), w);
return true;
}

View File

@ -756,42 +756,6 @@ void ConvertFromRGBA8888_Vulkan(u8 *dst, const u8 *src, u32 dstStride, u32 srcSt
}
}
#ifdef DEBUG_READ_PIXELS
// TODO: Make more generic.
static void LogReadPixelsError(GLenum error) {
switch (error) {
case GL_NO_ERROR:
break;
case GL_INVALID_ENUM:
ERROR_LOG(FRAMEBUF, "glReadPixels: GL_INVALID_ENUM");
break;
case GL_INVALID_VALUE:
ERROR_LOG(FRAMEBUF, "glReadPixels: GL_INVALID_VALUE");
break;
case GL_INVALID_OPERATION:
ERROR_LOG(FRAMEBUF, "glReadPixels: GL_INVALID_OPERATION");
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
ERROR_LOG(FRAMEBUF, "glReadPixels: GL_INVALID_FRAMEBUFFER_OPERATION");
break;
case GL_OUT_OF_MEMORY:
ERROR_LOG(FRAMEBUF, "glReadPixels: GL_OUT_OF_MEMORY");
break;
#ifndef USING_GLES2
case GL_STACK_UNDERFLOW:
ERROR_LOG(FRAMEBUF, "glReadPixels: GL_STACK_UNDERFLOW");
break;
case GL_STACK_OVERFLOW:
ERROR_LOG(FRAMEBUF, "glReadPixels: GL_STACK_OVERFLOW");
break;
#endif
default:
ERROR_LOG(FRAMEBUF, "glReadPixels: %08x", error);
break;
}
}
#endif
// One frame behind, but no stalling.
void FramebufferManagerVulkan::PackFramebufferAsync_(VirtualFramebuffer *vfb) {
const int MAX_PBO = 2;

View File

@ -1361,7 +1361,9 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 wid
bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int bx, int by, int bw, int bh, Draw::DataFormat format, void *pixels, int pixelStride) {
D3D11Framebuffer *fb = (D3D11Framebuffer *)src;
assert(fb->colorFormat == DXGI_FORMAT_R8G8B8A8_UNORM);
if (fb) {
assert(fb->colorFormat == DXGI_FORMAT_R8G8B8A8_UNORM);
}
bool useGlobalPacktex = (bx + bw <= 512 && by + bh <= 512) && channelBits == FB_COLOR_BIT;
@ -1383,6 +1385,7 @@ bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channel
break;
case FB_DEPTH_BIT:
case FB_STENCIL_BIT:
assert(fb);
packDesc.Format = fb->depthStencilFormat;
break;
default:
@ -1396,15 +1399,17 @@ bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channel
D3D11_BOX srcBox{ (UINT)bx, (UINT)by, 0, (UINT)(bx + bw), (UINT)(by + bh), 1 };
switch (channelBits) {
case FB_COLOR_BIT:
context_->CopySubresourceRegion(packTex, 0, bx, by, 0, fb->colorTex, 0, &srcBox);
context_->CopySubresourceRegion(packTex, 0, bx, by, 0, fb ? fb->colorTex : bbRenderTargetTex_, 0, &srcBox);
break;
case FB_DEPTH_BIT:
case FB_STENCIL_BIT:
// For depth/stencil buffers, we can't reliably copy subrectangles, so just copy the whole resource.
context_->CopyResource(packTex, fb->colorTex);
assert(fb); // We haven't got a texture for the backbuffer depth. Could make one but I don't think we need one.
context_->CopyResource(packTex, fb->depthStencilTex);
break;
default:
assert(false);
break;
}
// Ideally, we'd round robin between two packTexture_, and simply use the other one. Though if the game
@ -1509,8 +1514,13 @@ uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int chann
void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo;
*w = fb->width;
*h = fb->height;
if (fb) {
*w = fb->width;
*h = fb->height;
} else {
*w = bbWidth_;
*h = bbHeight_;
}
}
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd) {

View File

@ -1866,8 +1866,13 @@ OpenGLFramebuffer::~OpenGLFramebuffer() {
void OpenGLContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
*w = fb->width;
*h = fb->height;
if (fb) {
*w = fb->width;
*h = fb->height;
} else {
*w = targetWidth_;
*h = targetHeight_;
}
}
uint32_t OpenGLContext::GetDataFormatSupport(DataFormat fmt) const {