D3D11: Implement basic framebuffer readback.
Also make debug interfaces more consistent.
This commit is contained in:
parent
522ac5c739
commit
0e8aeaea3a
21 changed files with 118 additions and 177 deletions
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#define WRITE p+=sprintf
|
#define WRITE p+=sprintf
|
||||||
|
|
||||||
|
// TODO: Add a compute shader path. Complete waste of time to set up a graphics state.
|
||||||
|
|
||||||
// Uses integer instructions available since OpenGL 3.0. Suitable for ES 3.0 as well.
|
// Uses integer instructions available since OpenGL 3.0. Suitable for ES 3.0 as well.
|
||||||
void GenerateDepalShader300(char *buffer, GEBufferFormat pixelFormat, ShaderLanguage language) {
|
void GenerateDepalShader300(char *buffer, GEBufferFormat pixelFormat, ShaderLanguage language) {
|
||||||
char *p = buffer;
|
char *p = buffer;
|
||||||
|
|
|
@ -1325,6 +1325,7 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1:1 pixel sides buffers, we resize buffers to these before we read them back.
|
||||||
VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFramebuffer *vfb) {
|
VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFramebuffer *vfb) {
|
||||||
// For now we'll keep these on the same struct as the ones that can get displayed
|
// For now we'll keep these on the same struct as the ones that can get displayed
|
||||||
// (and blatantly copy work already done above while at it).
|
// (and blatantly copy work already done above while at it).
|
||||||
|
|
|
@ -152,6 +152,7 @@ namespace Draw {
|
||||||
class DrawContext;
|
class DrawContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GPUDebugBuffer;
|
||||||
class TextureCacheCommon;
|
class TextureCacheCommon;
|
||||||
class ShaderManagerCommon;
|
class ShaderManagerCommon;
|
||||||
|
|
||||||
|
@ -264,6 +265,11 @@ public:
|
||||||
|
|
||||||
Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888);
|
Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888);
|
||||||
|
|
||||||
|
// Debug features
|
||||||
|
virtual bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) = 0;
|
||||||
|
virtual bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) = 0;
|
||||||
|
virtual bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void SetViewport2D(int x, int y, int w, int h) = 0;
|
virtual void SetViewport2D(int x, int y, int w, int h) = 0;
|
||||||
void CalculatePostShaderUniforms(int bufferWidth, int bufferHeight, int renderWidth, int renderHeight, PostShaderUniforms *uniforms);
|
void CalculatePostShaderUniforms(int bufferWidth, int bufferHeight, int renderWidth, int renderHeight, PostShaderUniforms *uniforms);
|
||||||
|
|
|
@ -105,6 +105,18 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw)
|
||||||
vb.Usage = D3D11_USAGE_DYNAMIC;
|
vb.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
vb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
vb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
device_->CreateBuffer(&vb, nullptr, &quadBuffer_);
|
device_->CreateBuffer(&vb, nullptr, &quadBuffer_);
|
||||||
|
|
||||||
|
D3D11_TEXTURE2D_DESC packDesc{};
|
||||||
|
packDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||||
|
packDesc.BindFlags = 0;
|
||||||
|
packDesc.Width = 512; // 512x512 is the maximum size of a framebuffer on the PSP.
|
||||||
|
packDesc.Height = 512;
|
||||||
|
packDesc.ArraySize = 1;
|
||||||
|
packDesc.MipLevels = 1;
|
||||||
|
packDesc.Usage = D3D11_USAGE_STAGING;
|
||||||
|
packDesc.SampleDesc.Count = 1;
|
||||||
|
packDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
device_->CreateTexture2D(&packDesc, nullptr, &packTexture_);
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferManagerD3D11::~FramebufferManagerD3D11() {
|
FramebufferManagerD3D11::~FramebufferManagerD3D11() {
|
||||||
|
@ -635,7 +647,7 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 wid
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
for (u32 y = 0; y < height; ++y) {
|
for (u32 y = 0; y < height; ++y) {
|
||||||
ConvertBGRA8888ToRGBA8888(dst32, src32, width);
|
memcpy(dst32, src32, width * 4);
|
||||||
src32 += srcStride;
|
src32 += srcStride;
|
||||||
dst32 += dstStride;
|
dst32 += dstStride;
|
||||||
}
|
}
|
||||||
|
@ -646,21 +658,21 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 wid
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case GE_FORMAT_565: // BGR 565
|
case GE_FORMAT_565: // BGR 565
|
||||||
for (u32 y = 0; y < height; ++y) {
|
for (u32 y = 0; y < height; ++y) {
|
||||||
ConvertBGRA8888ToRGB565(dst16, src32, width);
|
ConvertRGBA8888ToRGB565(dst16, src32, width);
|
||||||
src32 += srcStride;
|
src32 += srcStride;
|
||||||
dst16 += dstStride;
|
dst16 += dstStride;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GE_FORMAT_5551: // ABGR 1555
|
case GE_FORMAT_5551: // ABGR 1555
|
||||||
for (u32 y = 0; y < height; ++y) {
|
for (u32 y = 0; y < height; ++y) {
|
||||||
ConvertBGRA8888ToRGBA5551(dst16, src32, width);
|
ConvertRGBA8888ToRGBA5551(dst16, src32, width);
|
||||||
src32 += srcStride;
|
src32 += srcStride;
|
||||||
dst16 += dstStride;
|
dst16 += dstStride;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GE_FORMAT_4444: // ABGR 4444
|
case GE_FORMAT_4444: // ABGR 4444
|
||||||
for (u32 y = 0; y < height; ++y) {
|
for (u32 y = 0; y < height; ++y) {
|
||||||
ConvertBGRA8888ToRGBA4444(dst16, src32, width);
|
ConvertRGBA8888ToRGBA4444(dst16, src32, width);
|
||||||
src32 += srcStride;
|
src32 += srcStride;
|
||||||
dst16 += dstStride;
|
dst16 += dstStride;
|
||||||
}
|
}
|
||||||
|
@ -673,6 +685,9 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 wid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function takes an already correctly-sized framebuffer and packs it into RAM.
|
||||||
|
// Does not need to account for scaling.
|
||||||
|
// Color conversion is currently done on CPU but should be done on GPU.
|
||||||
void FramebufferManagerD3D11::PackFramebufferD3D11_(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
void FramebufferManagerD3D11::PackFramebufferD3D11_(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
||||||
if (!vfb->fbo) {
|
if (!vfb->fbo) {
|
||||||
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferD3D11_: vfb->fbo == 0");
|
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferD3D11_: vfb->fbo == 0");
|
||||||
|
@ -686,85 +701,38 @@ void FramebufferManagerD3D11::PackFramebufferD3D11_(VirtualFramebuffer *vfb, int
|
||||||
// We always need to convert from the framebuffer native format.
|
// We always need to convert from the framebuffer native format.
|
||||||
// Right now that's always 8888.
|
// Right now that's always 8888.
|
||||||
DEBUG_LOG(HLE, "Reading framebuffer to mem, fb_address = %08x", fb_address);
|
DEBUG_LOG(HLE, "Reading framebuffer to mem, fb_address = %08x", fb_address);
|
||||||
|
ID3D11Texture2D *colorTex = (ID3D11Texture2D *)draw_->GetFramebufferAPITexture(vfb->fbo, Draw::FB_COLOR_BIT, 0);
|
||||||
|
|
||||||
/*
|
D3D11_BOX srcBox{ 0, 0, 0, vfb->width, vfb->height, 1 };
|
||||||
LPDIRECT3DSURFACE9 renderTarget = (LPDIRECT3DSURFACE9)draw_->GetFramebufferAPITexture(vfb->fbo, Draw::FB_COLOR_BIT | Draw::FB_SURFACE_BIT, 0);
|
context_->CopySubresourceRegion(packTexture_, 0, 0, 0, 0, colorTex, 0, &srcBox);
|
||||||
D3DSURFACE_DESC desc;
|
|
||||||
renderTarget->GetDesc(&desc);
|
|
||||||
|
|
||||||
LPDIRECT3DSURFACE9 offscreen = GetOffscreenSurface(renderTarget, vfb);
|
// Ideally, we'd round robin between two packTexture_, and simply use the other one. Though if the game
|
||||||
if (offscreen) {
|
// does a once-off copy, that won't work at all.
|
||||||
HRESULT hr = pD3Ddevice->GetRenderTargetData(renderTarget, offscreen);
|
|
||||||
if (SUCCEEDED(hr)) {
|
// BIG GPU STALL
|
||||||
D3DLOCKED_RECT locked;
|
D3D11_MAPPED_SUBRESOURCE map;
|
||||||
u32 widthFactor = vfb->renderWidth / vfb->bufferWidth;
|
HRESULT result = context_->Map(packTexture_, 0, D3D11_MAP_READ, 0, &map);
|
||||||
u32 heightFactor = vfb->renderHeight / vfb->bufferHeight;
|
if (FAILED(result)) {
|
||||||
RECT rect = { (LONG)(x * widthFactor), (LONG)(y * heightFactor), (LONG)((x + w) * widthFactor), (LONG)((y + h) * heightFactor) };
|
return;
|
||||||
hr = offscreen->LockRect(&locked, &rect, D3DLOCK_READONLY);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
// TODO: Handle the other formats? We don't currently create them, I think.
|
|
||||||
const int dstByteOffset = (y * vfb->fb_stride + x) * dstBpp;
|
|
||||||
// Pixel size always 4 here because we always request BGRA8888.
|
|
||||||
ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), (u8 *)locked.pBits, vfb->fb_stride, locked.Pitch / 4, w, h, vfb->format);
|
|
||||||
offscreen->UnlockRect();
|
|
||||||
} else {
|
|
||||||
ERROR_LOG_REPORT(G3D, "Unable to lock rect from %08x: %d,%d %dx%d of %dx%d", fb_address, rect.left, rect.top, rect.right, rect.bottom, vfb->renderWidth, vfb->renderHeight);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ERROR_LOG_REPORT(G3D, "Unable to download render target data from %08x", fb_address);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
// TODO: Handle the other formats? We don't currently create them, I think.
|
||||||
|
const int srcByteOffset = y * map.RowPitch + x * 4;
|
||||||
|
const int dstByteOffset = (y * vfb->fb_stride + x) * dstBpp;
|
||||||
|
// Pixel size always 4 here because we always request BGRA8888.
|
||||||
|
ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), (u8 *)map.pData, vfb->fb_stride, map.RowPitch/4, w, h, vfb->format);
|
||||||
|
context_->Unmap(packTexture_, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nobody calls this yet.
|
||||||
void FramebufferManagerD3D11::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
void FramebufferManagerD3D11::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
||||||
if (!vfb->fbo) {
|
if (!vfb->fbo) {
|
||||||
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
|
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We always read the depth buffer in 24_8 format.
|
|
||||||
const u32 z_address = (0x04000000) | vfb->z_address;
|
const u32 z_address = (0x04000000) | vfb->z_address;
|
||||||
|
// TODO
|
||||||
/*
|
|
||||||
DEBUG_LOG(SCEGE, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address);
|
|
||||||
|
|
||||||
LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)draw_->GetFramebufferAPITexture(vfb->fbo, Draw::FB_DEPTH_BIT, 0);
|
|
||||||
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 FramebufferManagerD3D11::EndFrame() {
|
void FramebufferManagerD3D11::EndFrame() {
|
||||||
|
@ -868,18 +836,18 @@ void FramebufferManagerD3D11::Resized() {
|
||||||
resized_ = true;
|
resized_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManagerD3D11::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
bool FramebufferManagerD3D11::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramebufferManagerD3D11::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramebufferManagerD3D11::GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManagerD3D11::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
bool FramebufferManagerD3D11::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManagerD3D11::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FramebufferManagerD3D11::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
|
|
||||||
return false;
|
|
||||||
}
|
|
|
@ -69,9 +69,9 @@ public:
|
||||||
|
|
||||||
virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
||||||
|
|
||||||
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes);
|
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) override;
|
||||||
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer);
|
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) override;
|
||||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer);
|
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) override;
|
||||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
||||||
|
|
||||||
virtual void RebindFramebuffer() override;
|
virtual void RebindFramebuffer() override;
|
||||||
|
@ -136,6 +136,8 @@ private:
|
||||||
ShaderManagerD3D11 *shaderManagerD3D11_;
|
ShaderManagerD3D11 *shaderManagerD3D11_;
|
||||||
DrawEngineD3D11 *drawEngine_;
|
DrawEngineD3D11 *drawEngine_;
|
||||||
|
|
||||||
|
ID3D11Texture2D *packTexture_;
|
||||||
|
|
||||||
// Used by post-processing shader
|
// Used by post-processing shader
|
||||||
std::vector<Draw::Framebuffer *> extraFBOs_;
|
std::vector<Draw::Framebuffer *> extraFBOs_;
|
||||||
|
|
||||||
|
@ -145,4 +147,4 @@ private:
|
||||||
AsyncPBO *pixelBufObj_; //this isn't that large
|
AsyncPBO *pixelBufObj_; //this isn't that large
|
||||||
u8 currentPBO_;
|
u8 currentPBO_;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -981,18 +981,6 @@ void GPU_D3D11::DoState(PointerWrap &p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_D3D11::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
|
||||||
return framebufferManagerD3D11_->GetCurrentFramebuffer(buffer, type, maxRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_D3D11::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
|
||||||
return framebufferManagerD3D11_->GetCurrentDepthbuffer(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_D3D11::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
|
|
||||||
return framebufferManagerD3D11_->GetCurrentStencilbuffer(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_D3D11::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
bool GPU_D3D11::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||||
if (!gstate.isTextureMapEnabled()) {
|
if (!gstate.isTextureMapEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -64,9 +64,6 @@ public:
|
||||||
}
|
}
|
||||||
std::vector<FramebufferInfo> GetFramebufferList() override;
|
std::vector<FramebufferInfo> GetFramebufferList() override;
|
||||||
|
|
||||||
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes = -1) override;
|
|
||||||
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
|
|
||||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
|
|
||||||
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
|
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
|
||||||
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
|
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
|
||||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
||||||
|
|
|
@ -632,7 +632,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
|
||||||
|
|
||||||
void FramebufferManagerDX9::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) {
|
void FramebufferManagerDX9::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) {
|
||||||
if (!dst->fbo || !src->fbo || !useBufferedRendering_) {
|
if (!dst->fbo || !src->fbo || !useBufferedRendering_) {
|
||||||
// This can happen if they recently switched from non-buffered.
|
// This can happen if we recently switched from non-buffered.
|
||||||
draw_->BindBackbufferAsRenderTarget();
|
draw_->BindBackbufferAsRenderTarget();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -939,11 +939,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
|
||||||
resized_ = true;
|
resized_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManagerDX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
bool FramebufferManagerDX9::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat fb_format, GPUDebugBuffer &buffer, int maxRes) {
|
||||||
u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : displayFramebufPtr_;
|
|
||||||
int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : displayStride_;
|
|
||||||
GEBufferFormat fb_format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : displayFormat_;
|
|
||||||
|
|
||||||
VirtualFramebuffer *vfb = currentRenderVfb_;
|
VirtualFramebuffer *vfb = currentRenderVfb_;
|
||||||
if (!vfb) {
|
if (!vfb) {
|
||||||
vfb = GetVFBAt(fb_address);
|
vfb = GetVFBAt(fb_address);
|
||||||
|
@ -1026,13 +1022,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManagerDX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
bool FramebufferManagerDX9::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) {
|
||||||
u32 fb_address = gstate.getFrameBufRawAddress();
|
|
||||||
int fb_stride = gstate.FrameBufStride();
|
|
||||||
|
|
||||||
u32 z_address = gstate.getDepthBufRawAddress();
|
|
||||||
int z_stride = gstate.DepthBufStride();
|
|
||||||
|
|
||||||
VirtualFramebuffer *vfb = currentRenderVfb_;
|
VirtualFramebuffer *vfb = currentRenderVfb_;
|
||||||
if (!vfb) {
|
if (!vfb) {
|
||||||
vfb = GetVFBAt(fb_address);
|
vfb = GetVFBAt(fb_address);
|
||||||
|
@ -1070,13 +1060,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManagerDX9::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
|
bool FramebufferManagerDX9::GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) {
|
||||||
u32 fb_address = gstate.getFrameBufRawAddress();
|
|
||||||
int fb_stride = gstate.FrameBufStride();
|
|
||||||
|
|
||||||
u32 z_address = gstate.getDepthBufRawAddress();
|
|
||||||
int z_stride = gstate.DepthBufStride();
|
|
||||||
|
|
||||||
VirtualFramebuffer *vfb = currentRenderVfb_;
|
VirtualFramebuffer *vfb = currentRenderVfb_;
|
||||||
if (!vfb) {
|
if (!vfb) {
|
||||||
vfb = GetVFBAt(fb_address);
|
vfb = GetVFBAt(fb_address);
|
||||||
|
@ -1084,7 +1068,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
|
||||||
|
|
||||||
if (!vfb) {
|
if (!vfb) {
|
||||||
// If there's no vfb and we're drawing there, must be memory?
|
// If there's no vfb and we're drawing there, must be memory?
|
||||||
buffer = GPUDebugBuffer(Memory::GetPointer(z_address | 0x04000000), z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
buffer = GPUDebugBuffer(Memory::GetPointer(vfb->z_address | 0x04000000), vfb->z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,9 +71,9 @@ public:
|
||||||
|
|
||||||
virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
||||||
|
|
||||||
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes);
|
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes);
|
||||||
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer);
|
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) override;
|
||||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer);
|
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) override;
|
||||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
||||||
|
|
||||||
virtual void RebindFramebuffer() override;
|
virtual void RebindFramebuffer() override;
|
||||||
|
|
|
@ -976,18 +976,6 @@ void GPU_DX9::DoState(PointerWrap &p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
|
||||||
return framebufferManagerDX9_->GetCurrentFramebuffer(buffer, type, maxRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_DX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
|
||||||
return framebufferManagerDX9_->GetCurrentDepthbuffer(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_DX9::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
|
|
||||||
return framebufferManagerDX9_->GetCurrentStencilbuffer(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||||
if (!gstate.isTextureMapEnabled()) {
|
if (!gstate.isTextureMapEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -65,9 +65,6 @@ public:
|
||||||
}
|
}
|
||||||
std::vector<FramebufferInfo> GetFramebufferList() override;
|
std::vector<FramebufferInfo> GetFramebufferList() override;
|
||||||
|
|
||||||
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes = -1) override;
|
|
||||||
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
|
|
||||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
|
|
||||||
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
|
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
|
||||||
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
|
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
|
||||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
||||||
|
|
|
@ -87,9 +87,9 @@ public:
|
||||||
|
|
||||||
bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
||||||
|
|
||||||
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes);
|
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) override;
|
||||||
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer);
|
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) override;
|
||||||
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer);
|
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) override;
|
||||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
||||||
|
|
||||||
virtual void RebindFramebuffer() override;
|
virtual void RebindFramebuffer() override;
|
||||||
|
|
|
@ -1230,30 +1230,6 @@ void GPU_GLES::DoState(PointerWrap &p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_GLES::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
|
||||||
u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManagerGL_->DisplayFramebufAddr();
|
|
||||||
int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManagerGL_->DisplayFramebufStride();
|
|
||||||
GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManagerGL_->DisplayFramebufFormat();
|
|
||||||
return framebufferManagerGL_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
|
||||||
u32 fb_address = gstate.getFrameBufRawAddress();
|
|
||||||
int fb_stride = gstate.FrameBufStride();
|
|
||||||
|
|
||||||
u32 z_address = gstate.getDepthBufRawAddress();
|
|
||||||
int z_stride = gstate.DepthBufStride();
|
|
||||||
|
|
||||||
return framebufferManagerGL_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_GLES::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
|
|
||||||
u32 fb_address = gstate.getFrameBufRawAddress();
|
|
||||||
int fb_stride = gstate.FrameBufStride();
|
|
||||||
|
|
||||||
return framebufferManagerGL_->GetStencilbuffer(fb_address, fb_stride, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
|
||||||
if (!gstate.isTextureMapEnabled()) {
|
if (!gstate.isTextureMapEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -67,9 +67,6 @@ public:
|
||||||
}
|
}
|
||||||
std::vector<FramebufferInfo> GetFramebufferList() override;
|
std::vector<FramebufferInfo> GetFramebufferList() override;
|
||||||
|
|
||||||
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override;
|
|
||||||
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
|
|
||||||
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
|
|
||||||
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
|
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
|
||||||
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
|
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
|
||||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
||||||
|
|
|
@ -2116,3 +2116,27 @@ bool GPUCommon::PerformStencilUpload(u32 dest, int size) {
|
||||||
void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) {
|
void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) {
|
||||||
framebufferManager_->NotifyStencilUpload(dest, size);
|
framebufferManager_->NotifyStencilUpload(dest, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GPUCommon::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
||||||
|
u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManager_->DisplayFramebufAddr();
|
||||||
|
int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_->DisplayFramebufStride();
|
||||||
|
GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManager_->DisplayFramebufFormat();
|
||||||
|
return framebufferManager_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPUCommon::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
|
||||||
|
u32 fb_address = gstate.getFrameBufRawAddress();
|
||||||
|
int fb_stride = gstate.FrameBufStride();
|
||||||
|
|
||||||
|
u32 z_address = gstate.getDepthBufRawAddress();
|
||||||
|
int z_stride = gstate.DepthBufStride();
|
||||||
|
|
||||||
|
return framebufferManager_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPUCommon::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
|
||||||
|
u32 fb_address = gstate.getFrameBufRawAddress();
|
||||||
|
int fb_stride = gstate.FrameBufStride();
|
||||||
|
|
||||||
|
return framebufferManager_->GetStencilbuffer(fb_address, fb_stride, buffer);
|
||||||
|
}
|
||||||
|
|
|
@ -162,6 +162,10 @@ public:
|
||||||
|
|
||||||
// From GPUDebugInterface.
|
// From GPUDebugInterface.
|
||||||
bool GetCurrentDisplayList(DisplayList &list) override;
|
bool GetCurrentDisplayList(DisplayList &list) override;
|
||||||
|
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override;
|
||||||
|
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
|
||||||
|
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
|
||||||
|
|
||||||
std::vector<DisplayList> ActiveDisplayLists() override;
|
std::vector<DisplayList> ActiveDisplayLists() override;
|
||||||
void ResetListPC(int listID, u32 pc) override;
|
void ResetListPC(int listID, u32 pc) override;
|
||||||
void ResetListStall(int listID, u32 stall) override;
|
void ResetListStall(int listID, u32 stall) override;
|
||||||
|
|
|
@ -838,8 +838,7 @@ bool SoftGPU::FramebufferDirty() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes)
|
bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
|
||||||
{
|
|
||||||
int x1 = gstate.getRegionX1();
|
int x1 = gstate.getRegionX1();
|
||||||
int y1 = gstate.getRegionY1();
|
int y1 = gstate.getRegionY1();
|
||||||
int x2 = gstate.getRegionX2() + 1;
|
int x2 = gstate.getRegionX2() + 1;
|
||||||
|
|
|
@ -1166,7 +1166,7 @@ void FramebufferManagerVulkan::Resized() {
|
||||||
resized_ = true;
|
resized_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FramebufferManagerVulkan::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer) {
|
bool FramebufferManagerVulkan::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxStride) {
|
||||||
// TODO: Doing this synchronously will require stalling the pipeline. Maybe better
|
// TODO: Doing this synchronously will require stalling the pipeline. Maybe better
|
||||||
// to do it callback-style?
|
// to do it callback-style?
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -100,9 +100,9 @@ public:
|
||||||
|
|
||||||
bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
||||||
|
|
||||||
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer);
|
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) override;
|
||||||
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer);
|
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) override;
|
||||||
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer);
|
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) override;
|
||||||
static bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
static bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
||||||
|
|
||||||
virtual void RebindFramebuffer() override;
|
virtual void RebindFramebuffer() override;
|
||||||
|
|
|
@ -328,6 +328,7 @@ enum FBChannel {
|
||||||
|
|
||||||
// Implementation specific
|
// Implementation specific
|
||||||
FB_SURFACE_BIT = 32, // Used in conjunction with the others in D3D9 to get surfaces through get_api_texture
|
FB_SURFACE_BIT = 32, // Used in conjunction with the others in D3D9 to get surfaces through get_api_texture
|
||||||
|
FB_VIEW_BIT = 64, // Used in conjunction with the others in D3D11 to get shader resource views through get_api_texture
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FBBlitFilter {
|
enum FBBlitFilter {
|
||||||
|
|
|
@ -1060,7 +1060,7 @@ Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) {
|
||||||
descColor.Height = desc.height;
|
descColor.Height = desc.height;
|
||||||
descColor.MipLevels = 1;
|
descColor.MipLevels = 1;
|
||||||
descColor.ArraySize = 1;
|
descColor.ArraySize = 1;
|
||||||
descColor.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
descColor.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
descColor.SampleDesc.Count = 1;
|
descColor.SampleDesc.Count = 1;
|
||||||
descColor.SampleDesc.Quality = 0;
|
descColor.SampleDesc.Quality = 0;
|
||||||
descColor.Usage = D3D11_USAGE_DEFAULT;
|
descColor.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
@ -1213,8 +1213,15 @@ void D3D11DrawContext::BindBackbufferAsRenderTarget() {
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) {
|
uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) {
|
||||||
// D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo;
|
D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo;
|
||||||
return 0;
|
switch (channelBit) {
|
||||||
|
case FB_COLOR_BIT: return (uintptr_t)fb->colorTex;
|
||||||
|
case FB_DEPTH_BIT: return (uintptr_t)fb->depthStencilTex;
|
||||||
|
case FB_COLOR_BIT | FB_VIEW_BIT: return (uintptr_t)fb->colorRTView;
|
||||||
|
case FB_DEPTH_BIT | FB_VIEW_BIT: return (uintptr_t)fb->depthStencilRTView;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
|
void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue