Add methods to download depth to PSP RAM.

This commit is contained in:
Unknown W. Brackets 2016-01-18 12:57:37 -08:00
parent 2916298695
commit 0443fbebd0
5 changed files with 108 additions and 13 deletions

View file

@ -310,6 +310,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
vfb->fb_stride = params.fb_stride;
vfb->format = params.fmt;
}
// Keep track, but this isn't really used.
vfb->z_stride = params.z_stride;
// Heuristic: In throughmode, a higher height could be used. Let's avoid shrinking the buffer.
if (params.isModeThrough && (int)vfb->width < params.fb_stride) {
vfb->width = std::max((int)vfb->width, drawing_width);

View file

@ -1055,6 +1055,55 @@ namespace DX9 {
}
}
void FramebufferManagerDX9::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
if (!vfb->fbo) {
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
return;
}
// We always read the depth buffer in 24_8 format.
const u32 z_address = (0x04000000) | vfb->z_address;
DEBUG_LOG(SCEGE, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address);
LPDIRECT3DTEXTURE9 tex = fbo_get_depth_texture(vfb->fbo_dx9);
if (tex) {
D3DSURFACE_DESC desc;
D3DLOCKED_RECT locked;
tex->GetLevelDesc(0, &desc);
RECT rect = {0, 0, (LONG)desc.Width, (LONG)desc.Height};
HRESULT hr = tex->LockRect(0, &locked, &rect, D3DLOCK_READONLY);
if (SUCCEEDED(hr)) {
const int dstByteOffset = y * vfb->fb_stride * sizeof(s16);
const u32 *packed = (const u32 *)locked.pBits;
u16 *depth = (u16 *)Memory::GetPointer(z_address);
// TODO: Optimize.
for (int yp = 0; yp < h; ++yp) {
for (int xp = 0; xp < w; ++xp) {
const int offset = (yp + y) & vfb->z_stride + x + xp;
float scaled = FromScaledDepth((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f));
if (scaled <= 0.0f) {
depth[offset] = 0;
} else if (scaled >= 65535.0f) {
depth[offset] = 65535;
} else {
depth[offset] = (int)scaled;
}
}
}
tex->UnlockRect(0);
} else {
ERROR_LOG_REPORT(G3D, "Unable to lock rect from depth %08x: %d,%d %dx%d of %dx%d", vfb->fb_address, rect.left, rect.top, rect.right, rect.bottom, vfb->renderWidth, vfb->renderHeight);
}
} else {
ERROR_LOG_REPORT(G3D, "Unable to download render target depth from %08x", vfb->fb_address);
}
}
void FramebufferManagerDX9::EndFrame() {
if (resized_) {
DestroyAllFBOs();

View file

@ -115,6 +115,7 @@ private:
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);
// Used by DrawPixels

View file

@ -1676,30 +1676,30 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in
}
// Pixel size always 4 here because we always request RGBA8888
size_t bufSize = vfb->fb_stride * std::max(vfb->height, (u16)h) * 4;
u32 bufSize = vfb->fb_stride * (h - y) * 4;
u32 fb_address = (0x04000000) | vfb->fb_address;
GLubyte *packed = 0;
bool convert = vfb->format != GE_FORMAT_8888 || UseBGRA8888();
const int dstBpp = vfb->format == GE_FORMAT_8888 ? 4 : 2;
const int packWidth = x + w < vfb->width ? x + w : vfb->width;
const int packWidth = std::min(vfb->fb_stride, std::min(x + w, (int)vfb->width));
if (!convert) {
packed = (GLubyte *)Memory::GetPointer(fb_address);
} else { // End result may be 16-bit but we are reading 32-bit, so there may not be enough space at fb_address
u32 neededSize = (u32)bufSize * sizeof(GLubyte);
if (!convBuf_ || convBufSize_ < neededSize) {
int byteOffset = y * vfb->fb_stride * 4;
packed = (GLubyte *)Memory::GetPointer(fb_address + byteOffset);
} else {
// End result may be 16-bit but we are reading 32-bit, so there may not be enough space at fb_address
if (!convBuf_ || convBufSize_ < bufSize) {
delete [] convBuf_;
convBuf_ = new u8[neededSize];
convBufSize_ = neededSize;
convBuf_ = new u8[bufSize];
convBufSize_ = bufSize;
}
packed = convBuf_;
}
if (packed) {
DEBUG_LOG(SCEGE, "Reading framebuffer to mem, bufSize = %u, packed = %p, fb_address = %08x",
(u32)bufSize, packed, fb_address);
DEBUG_LOG(SCEGE, "Reading framebuffer to mem, bufSize = %u, fb_address = %08x", bufSize, fb_address);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
GLenum glfmt = GL_RGBA;
@ -1707,12 +1707,11 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in
glfmt = GL_BGRA_EXT;
}
int byteOffset = y * vfb->fb_stride * 4;
SafeGLReadPixels(0, y, h == 1 ? packWidth : vfb->fb_stride, h, glfmt, GL_UNSIGNED_BYTE, packed + byteOffset);
SafeGLReadPixels(0, y, h == 1 ? packWidth : vfb->fb_stride, h, glfmt, GL_UNSIGNED_BYTE, packed);
if (convert) {
int dstByteOffset = y * vfb->fb_stride * dstBpp;
ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), packed + byteOffset, vfb->fb_stride, vfb->fb_stride, packWidth, h, vfb->format);
ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), packed, vfb->fb_stride, vfb->fb_stride, packWidth, h, vfb->format);
}
}
@ -1731,6 +1730,49 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in
fbo_unbind_read();
}
void FramebufferManager::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
if (vfb->fbo) {
fbo_bind_for_read(vfb->fbo);
} else {
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
return;
}
// Pixel size always 4 here because we always request float
const u32 bufSize = vfb->z_stride * (h - y) * 4;
const u32 z_address = (0x04000000) | vfb->z_address;
const int packWidth = std::min(vfb->z_stride, std::min(x + w, (int)vfb->width));
if (!convBuf_ || convBufSize_ < bufSize) {
delete [] convBuf_;
convBuf_ = new u8[bufSize];
convBufSize_ = bufSize;
}
DEBUG_LOG(SCEGE, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
SafeGLReadPixels(0, y, h == 1 ? packWidth : vfb->z_stride, h, GL_DEPTH_COMPONENT, GL_FLOAT, convBuf_);
int dstByteOffset = y * vfb->fb_stride * sizeof(u16);
u16 *depth = (u16 *)Memory::GetPointer(z_address + dstByteOffset);
GLfloat *packed = (GLfloat *)convBuf_;
int totalPixels = h == 1 ? packWidth : vfb->z_stride * h;
for (int i = 0; i < totalPixels; ++i) {
float scaled = FromScaledDepth(packed[i]);
if (scaled <= 0.0f) {
depth[i] = 0;
} else if (scaled >= 65535.0f) {
depth[i] = 65535;
} else {
depth[i] = (int)scaled;
}
}
fbo_unbind_read();
}
#ifdef _WIN32
void ShowScreenResolution();
#endif

View file

@ -145,6 +145,7 @@ private:
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);
// Used by DrawPixels
unsigned int drawPixelsTex_;