mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 17:19:28 +01:00
Merge pull request #19736 from hrydgard/debugger-readback-inspect
ImGeDebugger: Add pixel color inspection
This commit is contained in:
19 files changed
+352
-222
No files matched your search
@@ -125,13 +125,13 @@ public:
|
||||
void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override;
|
||||
void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override;
|
||||
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override;
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override;
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, Aspect aspects, const char *tag) override;
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemory(Framebuffer *src, Aspect channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override;
|
||||
|
||||
// These functions should be self explanatory.
|
||||
void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) override;
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect channelBit, int layer) override;
|
||||
|
||||
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
||||
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount) override;
|
||||
void DrawIndexedClippedBatchUP(const void *vdata, int vertexCount, const void *idata, int indexCount, Slice<ClippedDraw> draws, const void *ub, size_t ubSize) override;
|
||||
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
void Clear(Aspect mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
|
||||
void BeginFrame(DebugFlags debugFlags) override;
|
||||
void EndFrame() override;
|
||||
@@ -1442,10 +1442,10 @@ void D3D11DrawContext::DrawIndexedClippedBatchUP(const void *vdata, int vertexCo
|
||||
} else {
|
||||
ID3D11ShaderResourceView *view = ((D3D11Framebuffer *)draws[i].bindFramebufferAsTex)->colorSRView;
|
||||
switch (draws[i].aspect) {
|
||||
case FB_DEPTH_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
view = ((D3D11Framebuffer *)draws[i].bindFramebufferAsTex)->depthSRView;
|
||||
break;
|
||||
case FB_STENCIL_BIT:
|
||||
case Aspect::STENCIL_BIT:
|
||||
view = ((D3D11Framebuffer *)draws[i].bindFramebufferAsTex)->stencilSRView;
|
||||
break;
|
||||
default:
|
||||
@@ -1607,17 +1607,17 @@ void D3D11DrawContext::BindSamplerStates(int start, int count, SamplerState **st
|
||||
context_->PSSetSamplers(start, count, samplers);
|
||||
}
|
||||
|
||||
void D3D11DrawContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
if ((mask & FBChannel::FB_COLOR_BIT) && curRenderTargetView_) {
|
||||
void D3D11DrawContext::Clear(Aspect mask, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
if ((mask & Aspect::COLOR_BIT) && curRenderTargetView_) {
|
||||
float colorRGBA[4];
|
||||
Uint8x4ToFloat4(colorRGBA, colorval);
|
||||
context_->ClearRenderTargetView(curRenderTargetView_, colorRGBA);
|
||||
}
|
||||
if ((mask & (FBChannel::FB_DEPTH_BIT | FBChannel::FB_STENCIL_BIT)) && curDepthStencilView_) {
|
||||
if ((mask & (Aspect::DEPTH_BIT | Aspect::STENCIL_BIT)) && curDepthStencilView_) {
|
||||
UINT clearFlag = 0;
|
||||
if (mask & FBChannel::FB_DEPTH_BIT)
|
||||
if (mask & Aspect::DEPTH_BIT)
|
||||
clearFlag |= D3D11_CLEAR_DEPTH;
|
||||
if (mask & FBChannel::FB_STENCIL_BIT)
|
||||
if (mask & Aspect::STENCIL_BIT)
|
||||
clearFlag |= D3D11_CLEAR_STENCIL;
|
||||
context_->ClearDepthStencilView(curDepthStencilView_, clearFlag, depthVal, stencilVal);
|
||||
}
|
||||
@@ -1656,18 +1656,18 @@ void D3D11DrawContext::BeginFrame(DebugFlags debugFlags) {
|
||||
}
|
||||
}
|
||||
|
||||
void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x, int y, int z, Framebuffer *dstfb, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBit, const char *tag) {
|
||||
void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x, int y, int z, Framebuffer *dstfb, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, Aspect aspect, const char *tag) {
|
||||
D3D11Framebuffer *src = (D3D11Framebuffer *)srcfb;
|
||||
D3D11Framebuffer *dst = (D3D11Framebuffer *)dstfb;
|
||||
|
||||
ID3D11Texture2D *srcTex = nullptr;
|
||||
ID3D11Texture2D *dstTex = nullptr;
|
||||
switch (channelBit) {
|
||||
case FBChannel::FB_COLOR_BIT:
|
||||
switch (aspect) {
|
||||
case Aspect::COLOR_BIT:
|
||||
srcTex = src->colorTex;
|
||||
dstTex = dst->colorTex;
|
||||
break;
|
||||
case FBChannel::FB_DEPTH_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
srcTex = src->depthStencilTex;
|
||||
dstTex = dst->depthStencilTex;
|
||||
break;
|
||||
@@ -1681,7 +1681,7 @@ void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x
|
||||
return;
|
||||
}
|
||||
|
||||
if (channelBit != FBChannel::FB_DEPTH_BIT) {
|
||||
if (aspect != Aspect::DEPTH_BIT) {
|
||||
// Non-full copies are not supported for the depth channel.
|
||||
// Note that we need to clip the source box.
|
||||
if (x < 0) {
|
||||
@@ -1705,13 +1705,13 @@ void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x
|
||||
}
|
||||
}
|
||||
|
||||
bool D3D11DrawContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) {
|
||||
bool D3D11DrawContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) {
|
||||
// Unfortunately D3D11 has no equivalent to this, gotta render a quad. Well, in some cases we can issue a copy instead.
|
||||
Crash();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int bx, int by, int bw, int bh, Draw::DataFormat destFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, Aspect channelBits, int bx, int by, int bw, int bh, Draw::DataFormat destFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
D3D11Framebuffer *fb = (D3D11Framebuffer *)src;
|
||||
|
||||
if (fb) {
|
||||
@@ -1729,7 +1729,7 @@ bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits
|
||||
if (bh <= 0 || bw <= 0)
|
||||
return true;
|
||||
|
||||
bool useGlobalPacktex = (bx + bw <= 512 && by + bh <= 512) && channelBits == FB_COLOR_BIT;
|
||||
bool useGlobalPacktex = (bx + bw <= 512 && by + bh <= 512) && channelBits == Aspect::COLOR_BIT;
|
||||
|
||||
ID3D11Texture2D *packTex = nullptr;
|
||||
if (!useGlobalPacktex) {
|
||||
@@ -1743,11 +1743,11 @@ bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits
|
||||
packDesc.Usage = D3D11_USAGE_STAGING;
|
||||
packDesc.SampleDesc.Count = 1;
|
||||
switch (channelBits) {
|
||||
case FB_COLOR_BIT:
|
||||
case Aspect::COLOR_BIT:
|
||||
packDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // TODO: fb->colorFormat;
|
||||
break;
|
||||
case FB_DEPTH_BIT:
|
||||
case FB_STENCIL_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
case Aspect::STENCIL_BIT:
|
||||
if (!fb) {
|
||||
// Not supported.
|
||||
return false;
|
||||
@@ -1760,8 +1760,8 @@ bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits
|
||||
device_->CreateTexture2D(&packDesc, nullptr, &packTex);
|
||||
} else {
|
||||
switch (channelBits) {
|
||||
case FB_DEPTH_BIT:
|
||||
case FB_STENCIL_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
case Aspect::STENCIL_BIT:
|
||||
if (!fb)
|
||||
return false;
|
||||
default:
|
||||
@@ -1776,12 +1776,12 @@ bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits
|
||||
D3D11_BOX srcBox{ (UINT)bx, (UINT)by, 0, (UINT)(bx + bw), (UINT)(by + bh), 1 };
|
||||
DataFormat srcFormat = DataFormat::UNDEFINED;
|
||||
switch (channelBits) {
|
||||
case FB_COLOR_BIT:
|
||||
case Aspect::COLOR_BIT:
|
||||
context_->CopySubresourceRegion(packTex, 0, bx, by, 0, fb ? fb->colorTex : bbRenderTargetTex_, 0, &srcBox);
|
||||
srcFormat = DataFormat::R8G8B8A8_UNORM;
|
||||
break;
|
||||
case FB_DEPTH_BIT:
|
||||
case FB_STENCIL_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
case Aspect::STENCIL_BIT:
|
||||
// For depth/stencil buffers, we can't reliably copy subrectangles, so just copy the whole resource.
|
||||
_assert_(fb); // Can't copy depth/stencil from backbuffer. Shouldn't happen thanks to checks above.
|
||||
context_->CopyResource(packTex, fb->depthStencilTex);
|
||||
@@ -1804,12 +1804,12 @@ bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits
|
||||
|
||||
const size_t srcByteOffset = by * map.RowPitch + bx * DataFormatSizeInBytes(srcFormat);
|
||||
const uint8_t *srcWithOffset = (const uint8_t *)map.pData + srcByteOffset;
|
||||
switch (channelBits) {
|
||||
case FB_COLOR_BIT:
|
||||
switch ((Aspect)channelBits) {
|
||||
case Aspect::COLOR_BIT:
|
||||
// Pixel size always 4 here because we always request BGRA8888.
|
||||
ConvertFromRGBA8888((uint8_t *)pixels, srcWithOffset, pixelStride, map.RowPitch / sizeof(uint32_t), bw, bh, destFormat);
|
||||
break;
|
||||
case FB_DEPTH_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
if (srcFormat == destFormat) {
|
||||
// Can just memcpy when it matches no matter the format!
|
||||
uint8_t *dst = (uint8_t *)pixels;
|
||||
@@ -1827,7 +1827,7 @@ bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits
|
||||
_assert_(false);
|
||||
}
|
||||
break;
|
||||
case FB_STENCIL_BIT:
|
||||
case Aspect::STENCIL_BIT:
|
||||
if (srcFormat == destFormat) {
|
||||
// Can just memcpy when it matches no matter the format!
|
||||
uint8_t *dst = (uint8_t *)pixels;
|
||||
@@ -1911,15 +1911,15 @@ void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Ren
|
||||
}
|
||||
}
|
||||
|
||||
void D3D11DrawContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) {
|
||||
void D3D11DrawContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect channelBit, int layer) {
|
||||
_dbg_assert_(binding < MAX_BOUND_TEXTURES);
|
||||
_dbg_assert_(layer == ALL_LAYERS || layer == 0); // No multiple layer support on D3D
|
||||
D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo;
|
||||
switch (channelBit) {
|
||||
case FBChannel::FB_COLOR_BIT:
|
||||
case Aspect::COLOR_BIT:
|
||||
context_->PSSetShaderResources(binding, 1, &fb->colorSRView);
|
||||
break;
|
||||
case FBChannel::FB_DEPTH_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
if (fb->depthSRView) {
|
||||
context_->PSSetShaderResources(binding, 1, &fb->depthSRView);
|
||||
}
|
||||
|
||||
@@ -517,17 +517,17 @@ public:
|
||||
void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override;
|
||||
void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override;
|
||||
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override {
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, Aspect aspect, const char *tag) override {
|
||||
// Not implemented
|
||||
}
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override;
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemory(Framebuffer *src, Aspect channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override;
|
||||
|
||||
// These functions should be self explanatory.
|
||||
void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) override;
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect channelBit, int layer) override;
|
||||
|
||||
uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) override;
|
||||
uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, Aspect aspect, int attachment) override;
|
||||
|
||||
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
||||
|
||||
@@ -576,7 +576,7 @@ public:
|
||||
void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount) override;
|
||||
void DrawIndexedClippedBatchUP(const void *vdata, int vertexCount, const void *idata, int indexCount, Slice<ClippedDraw> draws, const void *ub, size_t ubSize) override;
|
||||
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
void Clear(Aspect aspects, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
|
||||
uint64_t GetNativeObject(NativeObject obj, void *srcObject) override {
|
||||
switch (obj) {
|
||||
@@ -1246,11 +1246,11 @@ static uint32_t SwapRB(uint32_t c) {
|
||||
return (c & 0xFF00FF00) | ((c >> 16) & 0xFF) | ((c << 16) & 0xFF0000);
|
||||
}
|
||||
|
||||
void D3D9Context::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
void D3D9Context::Clear(Aspect aspects, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
UINT d3dMask = 0;
|
||||
if (mask & FBChannel::FB_COLOR_BIT) d3dMask |= D3DCLEAR_TARGET;
|
||||
if (mask & FBChannel::FB_DEPTH_BIT) d3dMask |= D3DCLEAR_ZBUFFER;
|
||||
if (mask & FBChannel::FB_STENCIL_BIT) d3dMask |= D3DCLEAR_STENCIL;
|
||||
if (aspects & Aspect::COLOR_BIT) d3dMask |= D3DCLEAR_TARGET;
|
||||
if (aspects & Aspect::DEPTH_BIT) d3dMask |= D3DCLEAR_ZBUFFER;
|
||||
if (aspects & Aspect::STENCIL_BIT) d3dMask |= D3DCLEAR_STENCIL;
|
||||
if (d3dMask) {
|
||||
device_->Clear(0, NULL, d3dMask, (D3DCOLOR)SwapRB(colorval), depthVal, stencilVal);
|
||||
}
|
||||
@@ -1398,42 +1398,42 @@ void D3D9Context::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPa
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t D3D9Context::GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) {
|
||||
uintptr_t D3D9Context::GetFramebufferAPITexture(Framebuffer *fbo, Aspect aspect, int attachment) {
|
||||
D3D9Framebuffer *fb = (D3D9Framebuffer *)fbo;
|
||||
if (channelBits & FB_SURFACE_BIT) {
|
||||
switch (channelBits & 7) {
|
||||
case FB_DEPTH_BIT:
|
||||
if (aspect & Aspect::SURFACE_BIT) {
|
||||
switch ((Aspect)(aspect & (Aspect)7)) {
|
||||
case Aspect::DEPTH_BIT:
|
||||
return (uintptr_t)fb->depthstencil.Get();
|
||||
case FB_STENCIL_BIT:
|
||||
case Aspect::STENCIL_BIT:
|
||||
return (uintptr_t)fb->depthstencil.Get();
|
||||
case FB_COLOR_BIT:
|
||||
case Aspect::COLOR_BIT:
|
||||
default:
|
||||
return (uintptr_t)fb->surf.Get();
|
||||
}
|
||||
} else {
|
||||
switch (channelBits & 7) {
|
||||
case FB_DEPTH_BIT:
|
||||
switch ((Aspect)(aspect & (Aspect)7)) {
|
||||
case Aspect::DEPTH_BIT:
|
||||
return (uintptr_t)fb->depthstenciltex.Get();
|
||||
case FB_STENCIL_BIT:
|
||||
case Aspect::STENCIL_BIT:
|
||||
return 0; // Can't texture from stencil
|
||||
case FB_COLOR_BIT:
|
||||
case Aspect::COLOR_BIT:
|
||||
default:
|
||||
return (uintptr_t)fb->tex.Get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void D3D9Context::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) {
|
||||
void D3D9Context::BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect channelBit, int layer) {
|
||||
_dbg_assert_(binding < MAX_BOUND_TEXTURES);
|
||||
_dbg_assert_(layer == ALL_LAYERS || layer == 0); // No stereo support
|
||||
D3D9Framebuffer *fb = (D3D9Framebuffer *)fbo;
|
||||
switch (channelBit) {
|
||||
case FB_DEPTH_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
if (fb->depthstenciltex) {
|
||||
device_->SetTexture(binding, fb->depthstenciltex.Get());
|
||||
}
|
||||
break;
|
||||
case FB_COLOR_BIT:
|
||||
case Aspect::COLOR_BIT:
|
||||
default:
|
||||
if (fb->tex) {
|
||||
device_->SetTexture(binding, fb->tex.Get());
|
||||
@@ -1453,7 +1453,7 @@ void D3D9Context::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
|
||||
}
|
||||
}
|
||||
|
||||
bool D3D9Context::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) {
|
||||
bool D3D9Context::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) {
|
||||
D3D9Framebuffer *src = (D3D9Framebuffer *)srcfb;
|
||||
D3D9Framebuffer *dst = (D3D9Framebuffer *)dstfb;
|
||||
|
||||
@@ -1461,10 +1461,10 @@ bool D3D9Context::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int
|
||||
ComPtr<IDirect3DSurface9> dstSurf;
|
||||
RECT srcRect{ (LONG)srcX1, (LONG)srcY1, (LONG)srcX2, (LONG)srcY2 };
|
||||
RECT dstRect{ (LONG)dstX1, (LONG)dstY1, (LONG)dstX2, (LONG)dstY2 };
|
||||
if (channelBits == FB_COLOR_BIT) {
|
||||
if (aspects == Aspect::COLOR_BIT) {
|
||||
srcSurf = src ? src->surf : deviceRTsurf;
|
||||
dstSurf = dst ? dst->surf : deviceRTsurf;
|
||||
} else if (channelBits & FB_DEPTH_BIT) {
|
||||
} else if (aspects & Aspect::DEPTH_BIT) {
|
||||
if (!src || !dst) {
|
||||
// Might have implications for non-buffered rendering.
|
||||
return false;
|
||||
@@ -1474,10 +1474,10 @@ bool D3D9Context::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return SUCCEEDED(device_->StretchRect(srcSurf.Get(), &srcRect, dstSurf.Get(), &dstRect, (filter == FB_BLIT_LINEAR && channelBits == FB_COLOR_BIT) ? D3DTEXF_LINEAR : D3DTEXF_POINT));
|
||||
return SUCCEEDED(device_->StretchRect(srcSurf.Get(), &srcRect, dstSurf.Get(), &dstRect, (filter == FB_BLIT_LINEAR && aspects == Aspect::COLOR_BIT) ? D3DTEXF_LINEAR : D3DTEXF_POINT));
|
||||
}
|
||||
|
||||
bool D3D9Context::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int bx, int by, int bw, int bh, Draw::DataFormat destFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
bool D3D9Context::CopyFramebufferToMemory(Framebuffer *src, Aspect aspects, int bx, int by, int bw, int bh, Draw::DataFormat destFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
D3D9Framebuffer *fb = (D3D9Framebuffer *)src;
|
||||
|
||||
if (fb) {
|
||||
@@ -1493,7 +1493,7 @@ bool D3D9Context::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int
|
||||
return true;
|
||||
|
||||
DataFormat srcFormat = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
if (channelBits != FB_COLOR_BIT) {
|
||||
if (aspects != Aspect::COLOR_BIT) {
|
||||
srcFormat = Draw::DataFormat::D24_S8;
|
||||
if (!supportsINTZ)
|
||||
return false;
|
||||
@@ -1505,7 +1505,7 @@ bool D3D9Context::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int
|
||||
|
||||
ComPtr<IDirect3DSurface9> offscreen;
|
||||
HRESULT hr = E_UNEXPECTED;
|
||||
if (channelBits == FB_COLOR_BIT) {
|
||||
if (aspects == Aspect::COLOR_BIT) {
|
||||
if (fb)
|
||||
fb->tex->GetLevelDesc(0, &desc);
|
||||
else
|
||||
@@ -1525,12 +1525,12 @@ bool D3D9Context::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
switch (channelBits) {
|
||||
case FB_COLOR_BIT:
|
||||
switch (aspects) {
|
||||
case Aspect::COLOR_BIT:
|
||||
// Pixel size always 4 here because we always request BGRA8888.
|
||||
ConvertFromBGRA8888((uint8_t *)pixels, (const uint8_t *)locked.pBits, pixelStride, locked.Pitch / sizeof(uint32_t), bw, bh, destFormat);
|
||||
break;
|
||||
case FB_DEPTH_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
if (srcFormat == destFormat) {
|
||||
// Can just memcpy when it matches no matter the format!
|
||||
uint8_t *dst = (uint8_t *)pixels;
|
||||
@@ -1548,7 +1548,7 @@ bool D3D9Context::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int
|
||||
_assert_(false);
|
||||
}
|
||||
break;
|
||||
case FB_STENCIL_BIT:
|
||||
case Aspect::STENCIL_BIT:
|
||||
if (srcFormat == destFormat) {
|
||||
uint8_t *dst = (uint8_t *)pixels;
|
||||
const uint8_t *src = (const uint8_t *)locked.pBits;
|
||||
@@ -1572,7 +1572,7 @@ bool D3D9Context::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int
|
||||
}
|
||||
}
|
||||
|
||||
if (channelBits != FB_COLOR_BIT) {
|
||||
if (aspects != Aspect::COLOR_BIT) {
|
||||
fb->depthstenciltex->UnlockRect(0);
|
||||
}
|
||||
if (offscreen) {
|
||||
|
||||
@@ -377,13 +377,13 @@ public:
|
||||
void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override;
|
||||
void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override;
|
||||
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override;
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override;
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, Aspect aspects, const char *tag) override;
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemory(Framebuffer *src, Aspect channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override;
|
||||
|
||||
// These functions should be self explanatory.
|
||||
void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) override;
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect channelBit, int layer) override;
|
||||
|
||||
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
||||
|
||||
@@ -446,7 +446,7 @@ public:
|
||||
void DrawIndexedUP(const void *vdata, int vertexCount, const void *idata, int indexCount) override;
|
||||
void DrawIndexedClippedBatchUP(const void *vdata, int vertexCount, const void *idata, int indexCount, Slice<ClippedDraw> draws, const void *ub, size_t ubSize) override;
|
||||
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
void Clear(Aspect mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
|
||||
std::string GetInfoString(InfoField info) const override {
|
||||
// TODO: Make these actually query the right information
|
||||
@@ -1042,18 +1042,18 @@ static void LogReadPixelsError(GLenum error) {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool OpenGLContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat dataFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
if (gl_extensions.IsGLES && (channelBits & FB_COLOR_BIT) == 0) {
|
||||
bool OpenGLContext::CopyFramebufferToMemory(Framebuffer *src, Aspect channelBits, int x, int y, int w, int h, Draw::DataFormat dataFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
if (gl_extensions.IsGLES && (channelBits & Aspect::COLOR_BIT) == 0) {
|
||||
// Can't readback depth or stencil on GLES.
|
||||
return false;
|
||||
}
|
||||
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)src;
|
||||
GLuint aspect = 0;
|
||||
if (channelBits & FB_COLOR_BIT)
|
||||
if (channelBits & Aspect::COLOR_BIT)
|
||||
aspect |= GL_COLOR_BUFFER_BIT;
|
||||
if (channelBits & FB_DEPTH_BIT)
|
||||
if (channelBits & Aspect::DEPTH_BIT)
|
||||
aspect |= GL_DEPTH_BUFFER_BIT;
|
||||
if (channelBits & FB_STENCIL_BIT)
|
||||
if (channelBits & Aspect::STENCIL_BIT)
|
||||
aspect |= GL_STENCIL_BUFFER_BIT;
|
||||
return renderManager_.CopyFramebufferToMemory(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, mode, tag);
|
||||
}
|
||||
@@ -1491,17 +1491,17 @@ void OpenGLContext::DrawIndexedClippedBatchUP(const void *vdata, int vertexCount
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
void OpenGLContext::Clear(Aspect aspects, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
float col[4];
|
||||
Uint8x4ToFloat4(col, colorval);
|
||||
GLuint glMask = 0;
|
||||
if (mask & FBChannel::FB_COLOR_BIT) {
|
||||
if (aspects & Aspect::COLOR_BIT) {
|
||||
glMask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if (mask & FBChannel::FB_DEPTH_BIT) {
|
||||
if (aspects & Aspect::DEPTH_BIT) {
|
||||
glMask |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
if (mask & FBChannel::FB_STENCIL_BIT) {
|
||||
if (aspects & Aspect::STENCIL_BIT) {
|
||||
glMask |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
renderManager_.Clear(colorval, depthVal, stencilVal, glMask, 0xF, 0, 0, targetWidth_, targetHeight_);
|
||||
@@ -1582,55 +1582,55 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Render
|
||||
curRenderTarget_ = fb;
|
||||
}
|
||||
|
||||
void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) {
|
||||
void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, Aspect aspects, const char *tag) {
|
||||
OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc;
|
||||
OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst;
|
||||
|
||||
int aspect = 0;
|
||||
if (channelBits & FB_COLOR_BIT) {
|
||||
aspect |= GL_COLOR_BUFFER_BIT;
|
||||
} else if (channelBits & (FB_STENCIL_BIT | FB_DEPTH_BIT)) {
|
||||
if (channelBits & FB_DEPTH_BIT)
|
||||
aspect |= GL_DEPTH_BUFFER_BIT;
|
||||
if (channelBits & FB_STENCIL_BIT)
|
||||
aspect |= GL_STENCIL_BUFFER_BIT;
|
||||
int glAspect = 0;
|
||||
if (aspects & Aspect::COLOR_BIT) {
|
||||
glAspect |= GL_COLOR_BUFFER_BIT;
|
||||
} else if (aspects & (Aspect::STENCIL_BIT | Aspect::DEPTH_BIT)) {
|
||||
if (aspects & Aspect::DEPTH_BIT)
|
||||
glAspect |= GL_DEPTH_BUFFER_BIT;
|
||||
if (aspects & Aspect::STENCIL_BIT)
|
||||
glAspect |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
renderManager_.CopyFramebuffer(src->framebuffer_, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer_, GLOffset2D{ dstX, dstY }, aspect, tag);
|
||||
renderManager_.CopyFramebuffer(src->framebuffer_, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer_, GLOffset2D{ dstX, dstY }, glAspect, tag);
|
||||
}
|
||||
|
||||
bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter, const char *tag) {
|
||||
bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter linearFilter, const char *tag) {
|
||||
OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc;
|
||||
OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst;
|
||||
GLuint aspect = 0;
|
||||
if (channels & FB_COLOR_BIT)
|
||||
if (aspects & Aspect::COLOR_BIT)
|
||||
aspect |= GL_COLOR_BUFFER_BIT;
|
||||
if (channels & FB_DEPTH_BIT)
|
||||
if (aspects & Aspect::DEPTH_BIT)
|
||||
aspect |= GL_DEPTH_BUFFER_BIT;
|
||||
if (channels & FB_STENCIL_BIT)
|
||||
if (aspects & Aspect::STENCIL_BIT)
|
||||
aspect |= GL_STENCIL_BUFFER_BIT;
|
||||
|
||||
renderManager_.BlitFramebuffer(src->framebuffer_, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer_, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR, tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) {
|
||||
void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect aspects, int layer) {
|
||||
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
|
||||
_assert_(binding < MAX_TEXTURE_SLOTS);
|
||||
|
||||
GLuint aspect = 0;
|
||||
if (channelBit & FB_COLOR_BIT) {
|
||||
aspect |= GL_COLOR_BUFFER_BIT;
|
||||
GLuint glAspect = 0;
|
||||
if (aspects & Aspect::COLOR_BIT) {
|
||||
glAspect |= GL_COLOR_BUFFER_BIT;
|
||||
boundTextures_[binding] = &fb->framebuffer_->color_texture;
|
||||
}
|
||||
if (channelBit & FB_DEPTH_BIT) {
|
||||
aspect |= GL_DEPTH_BUFFER_BIT;
|
||||
if (aspects & Aspect::DEPTH_BIT) {
|
||||
glAspect |= GL_DEPTH_BUFFER_BIT;
|
||||
boundTextures_[binding] = &fb->framebuffer_->z_stencil_texture;
|
||||
}
|
||||
if (channelBit & FB_STENCIL_BIT) {
|
||||
aspect |= GL_STENCIL_BUFFER_BIT;
|
||||
if (aspects & Aspect::STENCIL_BIT) {
|
||||
glAspect |= GL_STENCIL_BUFFER_BIT;
|
||||
boundTextures_[binding] = &fb->framebuffer_->z_stencil_texture;
|
||||
}
|
||||
renderManager_.BindFramebufferAsTexture(fb->framebuffer_, binding, aspect);
|
||||
renderManager_.BindFramebufferAsTexture(fb->framebuffer_, binding, glAspect);
|
||||
}
|
||||
|
||||
void OpenGLContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
|
||||
|
||||
@@ -452,14 +452,14 @@ public:
|
||||
void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override;
|
||||
void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) override;
|
||||
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override;
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override;
|
||||
void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, Aspect aspects, const char *tag) override;
|
||||
bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) override;
|
||||
bool CopyFramebufferToMemory(Framebuffer *src, Aspect aspects, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override;
|
||||
DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) override;
|
||||
|
||||
// These functions should be self explanatory.
|
||||
void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override;
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) override;
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect channelBit, int layer) override;
|
||||
|
||||
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
||||
|
||||
@@ -498,7 +498,7 @@ public:
|
||||
void BindCurrentPipeline();
|
||||
void ApplyDynamicState();
|
||||
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
void Clear(Aspect aspects, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
|
||||
void BeginFrame(DebugFlags debugFlags) override;
|
||||
void EndFrame() override;
|
||||
@@ -547,7 +547,7 @@ public:
|
||||
|
||||
void Invalidate(InvalidationFlags flags) override;
|
||||
|
||||
void InvalidateFramebuffer(FBInvalidationStage stage, uint32_t channels) override;
|
||||
void InvalidateFramebuffer(FBInvalidationStage stage, Aspect aspects) override;
|
||||
|
||||
void SetInvalidationCallback(InvalidationCallback callback) override {
|
||||
renderManager_.SetInvalidationCallback(callback);
|
||||
@@ -1618,13 +1618,13 @@ void VKContext::BindCurrentPipeline() {
|
||||
renderManager_.BindPipeline(curPipeline_->pipeline, curPipeline_->flags, pipelineLayout_);
|
||||
}
|
||||
|
||||
void VKContext::Clear(int clearMask, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
void VKContext::Clear(Aspect aspects, uint32_t colorval, float depthVal, int stencilVal) {
|
||||
int mask = 0;
|
||||
if (clearMask & FBChannel::FB_COLOR_BIT)
|
||||
if (aspects & Aspect::COLOR_BIT)
|
||||
mask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (clearMask & FBChannel::FB_DEPTH_BIT)
|
||||
if (aspects & Aspect::DEPTH_BIT)
|
||||
mask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (clearMask & FBChannel::FB_STENCIL_BIT)
|
||||
if (aspects & Aspect::STENCIL_BIT)
|
||||
mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
renderManager_.Clear(colorval, depthVal, stencilVal, mask);
|
||||
}
|
||||
@@ -1760,38 +1760,38 @@ Framebuffer *VKContext::CreateFramebuffer(const FramebufferDesc &desc) {
|
||||
return new VKFramebuffer(vkrfb, desc.multiSampleLevel);
|
||||
}
|
||||
|
||||
void VKContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x, int y, int z, Framebuffer *dstfb, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) {
|
||||
void VKContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x, int y, int z, Framebuffer *dstfb, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, Aspect aspects, const char *tag) {
|
||||
VKFramebuffer *src = (VKFramebuffer *)srcfb;
|
||||
VKFramebuffer *dst = (VKFramebuffer *)dstfb;
|
||||
|
||||
int aspectMask = 0;
|
||||
if (channelBits & FBChannel::FB_COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (channelBits & FBChannel::FB_DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (channelBits & FBChannel::FB_STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
if (aspects & Aspect::COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (aspects & Aspect::DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (aspects & Aspect::STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
renderManager_.CopyFramebuffer(src->GetFB(), VkRect2D{ {x, y}, {(uint32_t)width, (uint32_t)height } }, dst->GetFB(), VkOffset2D{ dstX, dstY }, aspectMask, tag);
|
||||
}
|
||||
|
||||
bool VKContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) {
|
||||
bool VKContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) {
|
||||
VKFramebuffer *src = (VKFramebuffer *)srcfb;
|
||||
VKFramebuffer *dst = (VKFramebuffer *)dstfb;
|
||||
|
||||
int aspectMask = 0;
|
||||
if (channelBits & FBChannel::FB_COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (channelBits & FBChannel::FB_DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (channelBits & FBChannel::FB_STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
if (aspects & Aspect::COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (aspects & Aspect::DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (aspects & Aspect::STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
renderManager_.BlitFramebuffer(src->GetFB(), VkRect2D{ {srcX1, srcY1}, {(uint32_t)(srcX2 - srcX1), (uint32_t)(srcY2 - srcY1) } }, dst->GetFB(), VkRect2D{ {dstX1, dstY1}, {(uint32_t)(dstX2 - dstX1), (uint32_t)(dstY2 - dstY1) } }, aspectMask, filter == FB_BLIT_LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST, tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VKContext::CopyFramebufferToMemory(Framebuffer *srcfb, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
bool VKContext::CopyFramebufferToMemory(Framebuffer *srcfb, Aspect aspects, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
VKFramebuffer *src = (VKFramebuffer *)srcfb;
|
||||
|
||||
int aspectMask = 0;
|
||||
if (channelBits & FBChannel::FB_COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (channelBits & FBChannel::FB_DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (channelBits & FBChannel::FB_STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
if (aspects & Aspect::COLOR_BIT) aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (aspects & Aspect::DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (aspects & Aspect::STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
|
||||
return renderManager_.CopyFramebufferToMemory(src ? src->GetFB() : nullptr, aspectMask, x, y, w, h, format, (uint8_t *)pixels, pixelStride, mode, tag);
|
||||
}
|
||||
@@ -1817,7 +1817,7 @@ void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPass
|
||||
curFramebuffer_ = fb;
|
||||
}
|
||||
|
||||
void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) {
|
||||
void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect channelBit, int layer) {
|
||||
VKFramebuffer *fb = (VKFramebuffer *)fbo;
|
||||
_assert_(binding >= 0 && binding < MAX_BOUND_TEXTURES);
|
||||
|
||||
@@ -1827,10 +1827,10 @@ void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChanne
|
||||
|
||||
int aspect = 0;
|
||||
switch (channelBit) {
|
||||
case FBChannel::FB_COLOR_BIT:
|
||||
case Aspect::COLOR_BIT:
|
||||
aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
break;
|
||||
case FBChannel::FB_DEPTH_BIT:
|
||||
case Aspect::DEPTH_BIT:
|
||||
aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
break;
|
||||
default:
|
||||
@@ -1868,13 +1868,13 @@ void VKContext::HandleEvent(Event ev, int width, int height, void *param1, void
|
||||
}
|
||||
}
|
||||
|
||||
void VKContext::InvalidateFramebuffer(FBInvalidationStage stage, uint32_t channels) {
|
||||
void VKContext::InvalidateFramebuffer(FBInvalidationStage stage, Aspect aspects) {
|
||||
VkImageAspectFlags flags = 0;
|
||||
if (channels & FBChannel::FB_COLOR_BIT)
|
||||
if (aspects & Aspect::COLOR_BIT)
|
||||
flags |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
if (channels & FBChannel::FB_DEPTH_BIT)
|
||||
if (aspects & Aspect::DEPTH_BIT)
|
||||
flags |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (channels & FBChannel::FB_STENCIL_BIT)
|
||||
if (aspects & Aspect::STENCIL_BIT)
|
||||
flags |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
if (stage == FB_INVALIDATION_LOAD) {
|
||||
renderManager_.SetLoadDontCare(flags);
|
||||
|
||||
+18
-16
@@ -258,16 +258,18 @@ enum class NativeObject {
|
||||
PUSH_POOL,
|
||||
};
|
||||
|
||||
enum FBChannel {
|
||||
FB_COLOR_BIT = 1,
|
||||
FB_DEPTH_BIT = 2,
|
||||
FB_STENCIL_BIT = 4,
|
||||
enum class Aspect {
|
||||
NO_BIT = 0,
|
||||
COLOR_BIT = 1,
|
||||
DEPTH_BIT = 2,
|
||||
STENCIL_BIT = 4,
|
||||
|
||||
// Implementation specific
|
||||
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
|
||||
FB_FORMAT_BIT = 128, // Actually retrieves the native format instead. D3D11 only.
|
||||
SURFACE_BIT = 32, // Used in conjunction with the others in D3D9 to get surfaces through get_api_texture
|
||||
VIEW_BIT = 64, // Used in conjunction with the others in D3D11 to get shader resource views through get_api_texture
|
||||
FORMAT_BIT = 128, // Actually retrieves the native format instead. D3D11 only.
|
||||
};
|
||||
ENUM_CLASS_BITOPS(Aspect);
|
||||
|
||||
enum FBInvalidationStage {
|
||||
FB_INVALIDATION_LOAD = 1,
|
||||
@@ -708,7 +710,7 @@ struct ClippedDraw {
|
||||
void *bindNativeTexture;
|
||||
Draw::SamplerState *samplerState;
|
||||
Draw::Pipeline *pipeline;
|
||||
Draw::FBChannel aspect;
|
||||
Draw::Aspect aspect;
|
||||
};
|
||||
|
||||
class DrawContext {
|
||||
@@ -773,11 +775,11 @@ public:
|
||||
// while in Vulkan this might cause various strangeness like image corruption.
|
||||
virtual void UpdateTextureLevels(Texture *texture, const uint8_t **data, TextureCallback initDataCallback, int numLevels) = 0;
|
||||
|
||||
virtual void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) = 0;
|
||||
virtual bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) = 0;
|
||||
virtual void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, Aspect aspects, const char *tag) = 0;
|
||||
virtual bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, Aspect aspects, FBBlitFilter filter, const char *tag) = 0;
|
||||
|
||||
// If the backend doesn't support old data, it's "OK" to block.
|
||||
virtual bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
virtual bool CopyFramebufferToMemory(Framebuffer *src, Aspect aspect, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) {
|
||||
return false;
|
||||
}
|
||||
virtual DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) {
|
||||
@@ -790,13 +792,13 @@ public:
|
||||
virtual void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) = 0;
|
||||
|
||||
// binding must be < MAX_TEXTURE_SLOTS (0, 1 are okay if it's 2).
|
||||
virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) = 0;
|
||||
virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, Aspect aspect, int layer) = 0;
|
||||
|
||||
// Framebuffer fetch / input attachment support, needs to be explicit in Vulkan.
|
||||
virtual void BindCurrentFramebufferForColorInput() {}
|
||||
|
||||
// deprecated, only used by D3D9
|
||||
virtual uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) {
|
||||
virtual uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, Aspect aspect, int attachment) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -805,8 +807,8 @@ public:
|
||||
// Could be useful in OpenGL ES to give hints about framebuffers on tiler GPUs
|
||||
// using glInvalidateFramebuffer, although drivers are known to botch that so we currently don't use it.
|
||||
// In Vulkan, this sets the LOAD_OP or the STORE_OP (depending on stage) of the current render pass instance to DONT_CARE.
|
||||
// channels is a bitwise combination of FBChannel::COLOR, DEPTH and STENCIL.
|
||||
virtual void InvalidateFramebuffer(FBInvalidationStage stage, uint32_t channels) {}
|
||||
// channels is a bitwise combination of Aspect::COLOR, DEPTH and STENCIL.
|
||||
virtual void InvalidateFramebuffer(FBInvalidationStage stage, Aspect aspects) {}
|
||||
|
||||
// Dynamic state
|
||||
virtual void SetScissorRect(int left, int top, int width, int height) = 0;
|
||||
@@ -861,7 +863,7 @@ public:
|
||||
|
||||
// This should be avoided as much as possible, in favor of clearing when binding a render target, which is native
|
||||
// on Vulkan.
|
||||
virtual void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) = 0;
|
||||
virtual void Clear(Aspect aspects, uint32_t colorval, float depthVal, int stencilVal) = 0;
|
||||
|
||||
// Necessary to correctly flip scissor rectangles etc for OpenGL.
|
||||
virtual void SetTargetSize(int w, int h) {
|
||||
|
||||
@@ -208,7 +208,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x
|
||||
draw_->SetViewport(viewport);
|
||||
draw_->SetScissorRect(0, 0, fbo->Width() * scaleX, fbo->Height() * scaleY);
|
||||
|
||||
draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_DEPTH_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, Aspect::DEPTH_BIT, 0);
|
||||
draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &depthReadbackSampler_);
|
||||
|
||||
// We must bind the program after starting the render pass.
|
||||
@@ -239,7 +239,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x
|
||||
};
|
||||
draw_->DrawUP(positions, 3);
|
||||
|
||||
draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT,
|
||||
draw_->CopyFramebufferToMemory(blitFBO, Aspect::COLOR_BIT,
|
||||
x * scaleX, y * scaleY, w * scaleX, h * scaleY,
|
||||
DataFormat::R8G8B8A8_UNORM, convBuf_, destW, mode, "ReadbackDepthbufferSync");
|
||||
|
||||
@@ -247,7 +247,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x
|
||||
// TODO: Use 4444 (or better, R16_UNORM) so we can copy lines directly (instead of 32 -> 16 on CPU)?
|
||||
format16Bit = true;
|
||||
} else {
|
||||
draw_->CopyFramebufferToMemory(fbo, FB_DEPTH_BIT, x, y, w, h, DataFormat::D32F, convBuf_, w, mode, "ReadbackDepthbufferSync");
|
||||
draw_->CopyFramebufferToMemory(fbo, Aspect::DEPTH_BIT, x, y, w, h, DataFormat::D32F, convBuf_, w, mode, "ReadbackDepthbufferSync");
|
||||
format16Bit = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1018,11 +1018,11 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir
|
||||
if (useRaster) {
|
||||
BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_DEPTH), "BlitDepthRaster");
|
||||
} else if (useCopy) {
|
||||
draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, w, h, 1, Draw::FB_DEPTH_BIT, "CopyFramebufferDepth");
|
||||
draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, w, h, 1, Draw::Aspect::DEPTH_BIT, "CopyFramebufferDepth");
|
||||
RebindFramebuffer("After BlitFramebufferDepth");
|
||||
} else if (useBlit) {
|
||||
// We'll accept whether we get a separate depth blit or not...
|
||||
draw_->BlitFramebuffer(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, "BlitFramebufferDepth");
|
||||
draw_->BlitFramebuffer(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, Draw::Aspect::DEPTH_BIT, Draw::FB_BLIT_NEAREST, "BlitFramebufferDepth");
|
||||
RebindFramebuffer("After BlitFramebufferDepth");
|
||||
}
|
||||
|
||||
@@ -1272,7 +1272,7 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF
|
||||
// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
|
||||
if (currentFramebufferCopy_ && (flags & BINDFBCOLOR_UNCACHED) == 0) {
|
||||
// We have a copy already that hasn't been invalidated, let's keep using it.
|
||||
draw_->BindFramebufferAsTexture(currentFramebufferCopy_, stage, Draw::FB_COLOR_BIT, layer);
|
||||
draw_->BindFramebufferAsTexture(currentFramebufferCopy_, stage, Draw::Aspect::COLOR_BIT, layer);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1284,7 +1284,7 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF
|
||||
bool partial = false;
|
||||
CopyFramebufferForColorTexture(©Info, framebuffer, flags, layer, &partial);
|
||||
RebindFramebuffer("After BindFramebufferAsColorTexture");
|
||||
draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, layer);
|
||||
draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::Aspect::COLOR_BIT, layer);
|
||||
|
||||
// Only cache the copy if it wasn't a partial copy.
|
||||
// TODO: Improve on this.
|
||||
@@ -1294,11 +1294,11 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF
|
||||
gpuStats.numCopiesForSelfTex++;
|
||||
} else {
|
||||
// Failed to get temp FBO? Weird.
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, layer);
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::Aspect::COLOR_BIT, layer);
|
||||
}
|
||||
return true;
|
||||
} else if (framebuffer != currentRenderVfb_ || (flags & BINDFBCOLOR_FORCE_SELF) != 0) {
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, layer);
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::Aspect::COLOR_BIT, layer);
|
||||
return true;
|
||||
} else {
|
||||
// Here it's an error because for some reason skipCopy is true. That shouldn't really happen.
|
||||
@@ -3018,7 +3018,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB
|
||||
// TODO: Maybe should handle flipY inside CopyFramebufferToMemorySync somehow?
|
||||
bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false;
|
||||
buffer.Allocate(w, h, GE_FORMAT_8888, flipY);
|
||||
bool retval = draw_->CopyFramebufferToMemory(bound, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetFramebuffer");
|
||||
bool retval = draw_->CopyFramebufferToMemory(bound, Draw::Aspect::COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetFramebuffer");
|
||||
|
||||
// Don't need to increment gpu stats for readback count here, this is a debugger-only function.
|
||||
|
||||
@@ -3060,7 +3060,7 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32
|
||||
buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, flipY);
|
||||
}
|
||||
// No need to free on failure, that's the caller's job (it likely will reuse a buffer.)
|
||||
bool retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetDepthBuffer");
|
||||
bool retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::Aspect::DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetDepthBuffer");
|
||||
if (!retval) {
|
||||
// Try ReadbackDepthbufferSync, in case GLES.
|
||||
buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY);
|
||||
@@ -3100,7 +3100,7 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G
|
||||
bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false;
|
||||
// No need to free on failure, the caller/destructor will do that. Usually this is a reused buffer, anyway.
|
||||
buffer.Allocate(w, h, GPU_DBG_FORMAT_8BIT, flipY);
|
||||
bool retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetStencilbuffer");
|
||||
bool retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::Aspect::STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetStencilbuffer");
|
||||
if (!retval) {
|
||||
retval = ReadbackStencilbuffer(vfb->fbo, 0, 0, w, h, buffer.GetData(), w, Draw::ReadbackMode::BLOCK);
|
||||
}
|
||||
@@ -3120,7 +3120,7 @@ bool GetOutputFramebuffer(Draw::DrawContext *draw, GPUDebugBuffer &buffer) {
|
||||
bool flipped = g_Config.iGPUBackend == (int)GPUBackend::OPENGL;
|
||||
|
||||
buffer.Allocate(w, h, fmt == Draw::DataFormat::R8G8B8A8_UNORM ? GPU_DBG_FORMAT_8888 : GPU_DBG_FORMAT_8888_BGRA, flipped);
|
||||
return draw->CopyFramebufferToMemory(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, fmt, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetOutputFramebuffer");
|
||||
return draw->CopyFramebufferToMemory(nullptr, Draw::Aspect::COLOR_BIT, 0, 0, w, h, fmt, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetOutputFramebuffer");
|
||||
}
|
||||
|
||||
bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||
@@ -3182,7 +3182,7 @@ void FramebufferManagerCommon::ReadbackFramebuffer(VirtualFramebuffer *vfb, int
|
||||
x * vfb->renderScaleFactor, y * vfb->renderScaleFactor,
|
||||
w * vfb->renderScaleFactor, h * vfb->renderScaleFactor, (uint16_t *)destPtr, stride, w, h, mode);
|
||||
} else {
|
||||
draw_->CopyFramebufferToMemory(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, stride, mode, "ReadbackFramebufferSync");
|
||||
draw_->CopyFramebufferToMemory(vfb->fbo, channel == RASTER_COLOR ? Draw::Aspect::COLOR_BIT : Draw::Aspect::DEPTH_BIT, x, y, w, h, destFormat, destPtr, stride, mode, "ReadbackFramebufferSync");
|
||||
}
|
||||
|
||||
char tag[128];
|
||||
@@ -3197,7 +3197,7 @@ void FramebufferManagerCommon::ReadbackFramebuffer(VirtualFramebuffer *vfb, int
|
||||
}
|
||||
|
||||
bool FramebufferManagerCommon::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode) {
|
||||
return draw_->CopyFramebufferToMemory(fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::S8, pixels, pixelsStride, mode, "ReadbackStencilbufferSync");
|
||||
return draw_->CopyFramebufferToMemory(fbo, Draw::Aspect::DEPTH_BIT, x, y, w, h, Draw::DataFormat::S8, pixels, pixelsStride, mode, "ReadbackStencilbufferSync");
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode) {
|
||||
@@ -3502,14 +3502,14 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
|
||||
const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2;
|
||||
if (sameSize && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) {
|
||||
draw_->CopyFramebufferImage(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1,
|
||||
channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, tag);
|
||||
channel == RASTER_COLOR ? Draw::Aspect::COLOR_BIT : Draw::Aspect::DEPTH_BIT, tag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (useBlit) {
|
||||
draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2,
|
||||
channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, tag);
|
||||
channel == RASTER_COLOR ? Draw::Aspect::COLOR_BIT : Draw::Aspect::DEPTH_BIT, Draw::FB_BLIT_NEAREST, tag);
|
||||
} else {
|
||||
Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_DEPTH);
|
||||
Draw::Framebuffer *srcFBO = src->fbo;
|
||||
@@ -3546,11 +3546,11 @@ void FramebufferManagerCommon::BlitUsingRaster(
|
||||
draw_->BindTexture(0, nullptr);
|
||||
// This will get optimized away in case it's already bound (in VK and GL at least..)
|
||||
draw_->BindFramebufferAsRenderTarget(dest, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, tag ? tag : "BlitUsingRaster");
|
||||
draw_->BindFramebufferAsTexture(src, 0, pipeline->info.readChannel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, Draw::ALL_LAYERS);
|
||||
draw_->BindFramebufferAsTexture(src, 0, pipeline->info.readChannel == RASTER_COLOR ? Draw::Aspect::COLOR_BIT : Draw::Aspect::DEPTH_BIT, Draw::ALL_LAYERS);
|
||||
|
||||
if (destX1 == 0.0f && destY1 == 0.0f && destX2 >= destW && destY2 >= destH) {
|
||||
// We overwrite the whole channel of the framebuffer, so we can invalidate the current contents.
|
||||
draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_LOAD, pipeline->info.writeChannel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT);
|
||||
draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_LOAD, pipeline->info.writeChannel == RASTER_COLOR ? Draw::Aspect::COLOR_BIT : Draw::Aspect::DEPTH_BIT);
|
||||
}
|
||||
|
||||
Draw::Viewport viewport{ 0.0f, 0.0f, (float)dest->Width(), (float)dest->Height(), 0.0f, 1.0f };
|
||||
@@ -3710,7 +3710,7 @@ void FramebufferManagerCommon::DrawImGuiDebug(int &selected) const {
|
||||
if (selected != -1) {
|
||||
// Now, draw the image of the selected framebuffer.
|
||||
Draw::Framebuffer *fb = vfbs_[selected]->fbo;
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(fb, Draw::FB_COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(fb, Draw::Aspect::COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
ImGui::Image(texId, ImVec2(fb->Width(), fb->Height()));
|
||||
}
|
||||
}
|
||||
@@ -611,15 +611,15 @@ bool PresentationCommon::BindSource(int binding, bool bindStereo) {
|
||||
} else if (srcFramebuffer_) {
|
||||
if (bindStereo) {
|
||||
if (srcFramebuffer_->Layers() > 1) {
|
||||
draw_->BindFramebufferAsTexture(srcFramebuffer_, binding, Draw::FB_COLOR_BIT, Draw::ALL_LAYERS);
|
||||
draw_->BindFramebufferAsTexture(srcFramebuffer_, binding, Draw::Aspect::COLOR_BIT, Draw::ALL_LAYERS);
|
||||
return true;
|
||||
} else {
|
||||
// Single layer. This might be from a post shader and those don't yet support stereo.
|
||||
draw_->BindFramebufferAsTexture(srcFramebuffer_, binding, Draw::FB_COLOR_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(srcFramebuffer_, binding, Draw::Aspect::COLOR_BIT, 0);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(srcFramebuffer_, binding, Draw::FB_COLOR_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(srcFramebuffer_, binding, Draw::Aspect::COLOR_BIT, 0);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -765,13 +765,13 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u
|
||||
PostShaderUniforms uniforms;
|
||||
const auto performShaderPass = [&](const ShaderInfo *shaderInfo, Draw::Framebuffer *postShaderFramebuffer, Draw::Pipeline *postShaderPipeline, int vertsOffset) {
|
||||
if (postShaderOutput) {
|
||||
draw_->BindFramebufferAsTexture(postShaderOutput, 0, Draw::FB_COLOR_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(postShaderOutput, 0, Draw::Aspect::COLOR_BIT, 0);
|
||||
} else {
|
||||
BindSource(0, false);
|
||||
}
|
||||
BindSource(1, false);
|
||||
if (shaderInfo->usePreviousFrame)
|
||||
draw_->BindFramebufferAsTexture(previousFramebuffer, 2, Draw::FB_COLOR_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(previousFramebuffer, 2, Draw::Aspect::COLOR_BIT, 0);
|
||||
|
||||
int nextWidth, nextHeight;
|
||||
draw_->GetFramebufferDimensions(postShaderFramebuffer, &nextWidth, &nextHeight);
|
||||
@@ -879,7 +879,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u
|
||||
|
||||
draw_->BindPipeline(pipeline);
|
||||
if (postShaderOutput) {
|
||||
draw_->BindFramebufferAsTexture(postShaderOutput, 0, Draw::FB_COLOR_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(postShaderOutput, 0, Draw::Aspect::COLOR_BIT, 0);
|
||||
} else {
|
||||
BindSource(0, false);
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ bool FramebufferManagerCommon::PerformWriteStencilFromMemory(u32 addr, int size,
|
||||
if (useBlit) {
|
||||
// Note that scissors don't affect blits on other APIs than OpenGL, so might want to try to get rid of this.
|
||||
draw_->SetScissorRect(0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight);
|
||||
draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST, "WriteStencilFromMemory_Blit");
|
||||
draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::Aspect::STENCIL_BIT, Draw::FB_BLIT_NEAREST, "WriteStencilFromMemory_Blit");
|
||||
RebindFramebuffer("RebindFramebuffer - Stencil");
|
||||
}
|
||||
|
||||
|
||||
@@ -1266,12 +1266,12 @@ bool TextureCacheCommon::GetCurrentFramebufferTextureDebug(GPUDebugBuffer &buffe
|
||||
buffer.Allocate(desiredW, desiredH, GPU_DBG_FORMAT_FLOAT, false);
|
||||
if (w < desiredW || h < desiredH)
|
||||
buffer.ZeroBytes();
|
||||
retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::D32F, buffer.GetData(), desiredW, Draw::ReadbackMode::BLOCK, "GetCurrentTextureDebug");
|
||||
retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::Aspect::DEPTH_BIT, x, y, w, h, Draw::DataFormat::D32F, buffer.GetData(), desiredW, Draw::ReadbackMode::BLOCK, "GetCurrentTextureDebug");
|
||||
} else {
|
||||
buffer.Allocate(desiredW, desiredH, GPU_DBG_FORMAT_8888, false);
|
||||
if (w < desiredW || h < desiredH)
|
||||
buffer.ZeroBytes();
|
||||
retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_COLOR_BIT, x, y, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), desiredW, Draw::ReadbackMode::BLOCK, "GetCurrentTextureDebug");
|
||||
retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::Aspect::COLOR_BIT, x, y, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), desiredW, Draw::ReadbackMode::BLOCK, "GetCurrentTextureDebug");
|
||||
}
|
||||
|
||||
// Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf.
|
||||
@@ -2368,16 +2368,16 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
|
||||
draw_->BindTexture(0, nullptr);
|
||||
draw_->BindTexture(1, nullptr);
|
||||
draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }, "Depal");
|
||||
draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_STORE, Draw::FB_DEPTH_BIT | Draw::FB_STENCIL_BIT);
|
||||
draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_STORE, Draw::Aspect::DEPTH_BIT | Draw::Aspect::STENCIL_BIT);
|
||||
draw_->SetScissorRect(u1, v1, u2 - u1, v2 - v1);
|
||||
Draw::Viewport viewport{ 0.0f, 0.0f, (float)depalWidth, (float)framebuffer->renderHeight, 0.0f, 1.0f };
|
||||
draw_->SetViewport(viewport);
|
||||
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, 0, depth ? Draw::FB_DEPTH_BIT : Draw::FB_COLOR_BIT, Draw::ALL_LAYERS);
|
||||
draw_->BindFramebufferAsTexture(framebuffer->fbo, 0, depth ? Draw::Aspect::DEPTH_BIT : Draw::Aspect::COLOR_BIT, Draw::ALL_LAYERS);
|
||||
if (clutRenderAddress_ == 0xFFFFFFFF) {
|
||||
draw_->BindTexture(1, clutTexture.texture);
|
||||
} else {
|
||||
draw_->BindFramebufferAsTexture(dynamicClutFbo_, 1, Draw::FB_COLOR_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(dynamicClutFbo_, 1, Draw::Aspect::COLOR_BIT, 0);
|
||||
}
|
||||
Draw::SamplerState *nearest = textureShaderCache_->GetSampler(false);
|
||||
Draw::SamplerState *clutSampler = textureShaderCache_->GetSampler(smoothedDepal);
|
||||
@@ -2394,7 +2394,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
|
||||
draw_->BindTexture(0, nullptr);
|
||||
framebufferManager_->RebindFramebuffer("ApplyTextureFramebuffer");
|
||||
|
||||
draw_->BindFramebufferAsTexture(depalFBO, 0, Draw::FB_COLOR_BIT, Draw::ALL_LAYERS);
|
||||
draw_->BindFramebufferAsTexture(depalFBO, 0, Draw::Aspect::COLOR_BIT, Draw::ALL_LAYERS);
|
||||
BoundFramebufferTexture();
|
||||
|
||||
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
|
||||
@@ -2474,13 +2474,13 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) {
|
||||
draw_->BindTexture(0, nullptr);
|
||||
draw_->BindTexture(1, nullptr);
|
||||
draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }, "Depal");
|
||||
draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_STORE, Draw::FB_DEPTH_BIT | Draw::FB_STENCIL_BIT);
|
||||
draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_STORE, Draw::Aspect::DEPTH_BIT | Draw::Aspect::STENCIL_BIT);
|
||||
draw_->SetScissorRect(u1, v1, u2 - u1, v2 - v1);
|
||||
Draw::Viewport viewport{ 0.0f, 0.0f, (float)texWidth, (float)texHeight, 0.0f, 1.0f };
|
||||
draw_->SetViewport(viewport);
|
||||
|
||||
draw_->BindNativeTexture(0, GetNativeTextureView(entry, false));
|
||||
draw_->BindFramebufferAsTexture(dynamicClutFbo_, 1, Draw::FB_COLOR_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(dynamicClutFbo_, 1, Draw::Aspect::COLOR_BIT, 0);
|
||||
Draw::SamplerState *nearest = textureShaderCache_->GetSampler(false);
|
||||
Draw::SamplerState *clutSampler = textureShaderCache_->GetSampler(false);
|
||||
draw_->BindSamplerStates(0, 1, &nearest);
|
||||
@@ -2496,7 +2496,7 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) {
|
||||
draw_->BindTexture(0, nullptr);
|
||||
framebufferManager_->RebindFramebuffer("ApplyTextureFramebuffer");
|
||||
|
||||
draw_->BindFramebufferAsTexture(depalFBO, 0, Draw::FB_COLOR_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(depalFBO, 0, Draw::Aspect::COLOR_BIT, 0);
|
||||
BoundFramebufferTexture();
|
||||
|
||||
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
|
||||
|
||||
@@ -461,11 +461,11 @@ void DrawEngineD3D11::Flush() {
|
||||
u32 clearColor = result.color;
|
||||
float clearDepth = result.depth;
|
||||
|
||||
uint32_t clearFlag = 0;
|
||||
Draw::Aspect clearFlag = Draw::Aspect::NO_BIT;
|
||||
|
||||
if (gstate.isClearModeColorMask()) clearFlag |= Draw::FBChannel::FB_COLOR_BIT;
|
||||
if (gstate.isClearModeAlphaMask()) clearFlag |= Draw::FBChannel::FB_STENCIL_BIT;
|
||||
if (gstate.isClearModeDepthMask()) clearFlag |= Draw::FBChannel::FB_DEPTH_BIT;
|
||||
if (gstate.isClearModeColorMask()) clearFlag |= Draw::Aspect::COLOR_BIT;
|
||||
if (gstate.isClearModeAlphaMask()) clearFlag |= Draw::Aspect::STENCIL_BIT;
|
||||
if (gstate.isClearModeDepthMask()) clearFlag |= Draw::Aspect::DEPTH_BIT;
|
||||
|
||||
uint8_t clearStencil = clearColor >> 24;
|
||||
draw_->Clear(clearFlag, clearColor, clearDepth, clearStencil);
|
||||
|
||||
@@ -39,7 +39,7 @@ bool FramebufferManagerDX9::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, i
|
||||
}
|
||||
|
||||
// We always read the depth buffer in 24_8 format.
|
||||
LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)draw_->GetFramebufferAPITexture(fbo, Draw::FB_DEPTH_BIT, 0);
|
||||
LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)draw_->GetFramebufferAPITexture(fbo, Draw::Aspect::DEPTH_BIT, 0);
|
||||
if (!tex)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -54,6 +54,6 @@ bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||
int w, h;
|
||||
draw_->GetFramebufferDimensions(nullptr, &w, &h);
|
||||
buffer.Allocate(w, h, GPU_DBG_FORMAT_888_RGB, true);
|
||||
draw_->CopyFramebufferToMemory(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetOutputFramebuffer");
|
||||
draw_->CopyFramebufferToMemory(nullptr, Draw::Aspect::COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetOutputFramebuffer");
|
||||
return true;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ bool FramebufferManagerGLES::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x
|
||||
|
||||
const bool useColorPath = gl_extensions.IsGLES;
|
||||
if (!useColorPath) {
|
||||
return draw_->CopyFramebufferToMemory(fbo, FB_STENCIL_BIT, x, y, w, h, DataFormat::S8, pixels, pixelsStride, ReadbackMode::BLOCK, "ReadbackStencilbufferSync");
|
||||
return draw_->CopyFramebufferToMemory(fbo, Aspect::STENCIL_BIT, x, y, w, h, DataFormat::S8, pixels, pixelsStride, ReadbackMode::BLOCK, "ReadbackStencilbufferSync");
|
||||
}
|
||||
|
||||
// Unsupported below GLES 3.1 or without ARB_stencil_texturing.
|
||||
@@ -135,7 +135,7 @@ bool FramebufferManagerGLES::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x
|
||||
Draw::Viewport viewport = { 0.0f, 0.0f, (float)fbo->Width(), (float)fbo->Height(), 0.0f, 1.0f };
|
||||
draw_->SetViewport(viewport);
|
||||
|
||||
draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_STENCIL_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, Aspect::STENCIL_BIT, 0);
|
||||
draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &stencilReadbackSampler_);
|
||||
|
||||
// We must bind the program after starting the render pass.
|
||||
@@ -150,7 +150,7 @@ bool FramebufferManagerGLES::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x
|
||||
};
|
||||
draw_->DrawUP(positions, 3);
|
||||
|
||||
draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, mode, "ReadbackStencilbufferSync");
|
||||
draw_->CopyFramebufferToMemory(blitFBO, Aspect::COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, mode, "ReadbackStencilbufferSync");
|
||||
|
||||
textureCache_->ForgetLastTexture();
|
||||
|
||||
|
||||
@@ -546,12 +546,12 @@ void DrawEngineVulkan::Flush() {
|
||||
bool clearColor = gstate.isClearModeColorMask();
|
||||
bool clearAlpha = gstate.isClearModeAlphaMask(); // and stencil
|
||||
bool clearDepth = gstate.isClearModeDepthMask();
|
||||
int mask = 0;
|
||||
Draw::Aspect mask = Draw::Aspect::NO_BIT;
|
||||
// The Clear detection takes care of doing a regular draw instead if separate masking
|
||||
// of color and alpha is needed, so we can just treat them as the same.
|
||||
if (clearColor || clearAlpha) mask |= Draw::FBChannel::FB_COLOR_BIT;
|
||||
if (clearDepth) mask |= Draw::FBChannel::FB_DEPTH_BIT;
|
||||
if (clearAlpha) mask |= Draw::FBChannel::FB_STENCIL_BIT;
|
||||
if (clearColor || clearAlpha) mask |= Draw::Aspect::COLOR_BIT;
|
||||
if (clearDepth) mask |= Draw::Aspect::DEPTH_BIT;
|
||||
if (clearAlpha) mask |= Draw::Aspect::STENCIL_BIT;
|
||||
// Note that since the alpha channel and the stencil channel are shared on the PSP,
|
||||
// when we clear alpha, we also clear stencil to the same value.
|
||||
draw_->Clear(mask, result.color, result.depth, result.color >> 24);
|
||||
|
||||
+108
-13
@@ -65,7 +65,7 @@ void DrawDisplayWindow(ImConfig &cfg, FramebufferManagerCommon *framebufferManag
|
||||
|
||||
VirtualFramebuffer *fb = framebufferManager->GetVFBAt(topaddr.ptr);
|
||||
if (fb && fb->fbo) {
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(fb->fbo, Draw::FB_COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(fb->fbo, Draw::Aspect::COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
ImGui::Image(texId, ImVec2(fb->width, fb->height));
|
||||
ImGui::Text("%s - %08x", fb->fbo->Tag(), topaddr.ptr);
|
||||
} else {
|
||||
@@ -161,10 +161,11 @@ void ImGePixelViewerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInte
|
||||
}
|
||||
|
||||
ImGePixelViewer::~ImGePixelViewer() {
|
||||
texture_->Release();
|
||||
if (texture_)
|
||||
texture_->Release();
|
||||
}
|
||||
|
||||
void ImGePixelViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw) {
|
||||
bool ImGePixelViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw) {
|
||||
if (dirty_) {
|
||||
UpdateTexture(draw);
|
||||
dirty_ = false;
|
||||
@@ -174,12 +175,86 @@ void ImGePixelViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw)
|
||||
if (texture_) {
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddTextureTemp(texture_, useAlpha ? ImGuiPipeline::TexturedAlphaBlend : ImGuiPipeline::TexturedOpaque);
|
||||
ImGui::Image(texId, ImVec2((float)width, (float)height));
|
||||
return true;
|
||||
} else {
|
||||
ImGui::Text("(invalid params: %dx%d, %08x)", width, height, addr);
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("(invalid address %08x)", addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ImGePixelViewer::GetColorAt(int x, int y) const {
|
||||
// Go look directly in RAM.
|
||||
int bpp = BufferFormatBytesPerPixel(format);
|
||||
u32 pixelAddr = addr + (y * stride + x) * bpp;
|
||||
switch (format) {
|
||||
case GE_FORMAT_8888:
|
||||
return Memory::Read_U32(pixelAddr);
|
||||
case GE_FORMAT_4444:
|
||||
return RGBA4444ToRGBA8888(Memory::Read_U16(pixelAddr));
|
||||
case GE_FORMAT_565:
|
||||
return RGB565ToRGBA8888(Memory::Read_U16(pixelAddr));
|
||||
case GE_FORMAT_5551:
|
||||
return RGBA5551ToRGBA8888(Memory::Read_U16(pixelAddr));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ImGeReadbackViewer::ImGeReadbackViewer() {
|
||||
// These are only forward declared in the header, so we initialize them here.
|
||||
channel = Draw::Aspect::COLOR_BIT;
|
||||
readbackFmt_ = Draw::DataFormat::UNDEFINED;
|
||||
}
|
||||
|
||||
ImGeReadbackViewer::~ImGeReadbackViewer() {
|
||||
if (texture_)
|
||||
texture_->Release();
|
||||
delete[] data_;
|
||||
}
|
||||
|
||||
bool ImGeReadbackViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw) {
|
||||
FramebufferManagerCommon *fbmanager = gpuDebug->GetFramebufferManagerCommon();
|
||||
if (!vfb || !vfb->fbo || !fbmanager) {
|
||||
ImGui::TextUnformatted("(N/A)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dirty_) {
|
||||
dirty_ = false;
|
||||
|
||||
delete[] data_;
|
||||
int w = vfb->fbo->Width();
|
||||
int h = vfb->fbo->Height();
|
||||
readbackFmt_ = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
data_ = new uint8_t[w * h * 4];
|
||||
draw->CopyFramebufferToMemory(vfb->fbo, channel, 0, 0, w, h, readbackFmt_, data_, w, Draw::ReadbackMode::BLOCK, "debugger");
|
||||
|
||||
// But for now, let's just draw the original FB, and we can always do that with color at least.
|
||||
}
|
||||
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(vfb->fbo, Draw::Aspect::COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
ImGui::Image(texId, ImVec2((float)vfb->fbo->Width(), (float)vfb->fbo->Height()));
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t ImGeReadbackViewer::GetColorAt(int x, int y) const {
|
||||
if (!vfb || !vfb->fbo || !data_) {
|
||||
return 0;
|
||||
}
|
||||
int bpp = (int)Draw::DataFormatSizeInBytes(readbackFmt_);
|
||||
int offset = (y * vfb->fbo->Width() + x) * bpp;
|
||||
switch (readbackFmt_) {
|
||||
case Draw::DataFormat::R8G8B8A8_UNORM:
|
||||
{
|
||||
uint32_t *read32 = (uint32_t *)(data_ + offset);
|
||||
return read32[0];
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ImGePixelViewer::UpdateTexture(Draw::DrawContext *draw) {
|
||||
@@ -557,6 +632,12 @@ void ImGeDebuggerWindow::NotifyStep() {
|
||||
swViewer_.showAlpha = false;
|
||||
swViewer_.useAlpha = false;
|
||||
swViewer_.Snapshot();
|
||||
|
||||
FramebufferManagerCommon *fbman = gpuDebug->GetFramebufferManagerCommon();
|
||||
if (fbman) {
|
||||
rbViewer_.vfb = fbman->GetExactVFB(gstate.getFrameBufAddress(), gstate.FrameBufStride(), gstate.FrameBufFormat());
|
||||
}
|
||||
rbViewer_.Snapshot();
|
||||
}
|
||||
|
||||
void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug, Draw::DrawContext *draw) {
|
||||
@@ -708,9 +789,7 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
||||
ImDrawList *drawList = ImGui::GetWindowDrawList();
|
||||
|
||||
if (coreState == CORE_STEPPING_GE) {
|
||||
FramebufferManagerCommon *fbman = gpuDebug->GetFramebufferManagerCommon();
|
||||
u32 fbptr = gstate.getFrameBufAddress();
|
||||
VirtualFramebuffer *vfb = fbman ? fbman->GetVFBAt(fbptr) : nullptr;
|
||||
VirtualFramebuffer *vfb = rbViewer_.vfb;
|
||||
if (vfb) {
|
||||
if (vfb->fbo) {
|
||||
ImGui::Text("Framebuffer: %s", vfb->fbo->Tag());
|
||||
@@ -723,8 +802,10 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
||||
if (ImGui::BeginTabItem("Color")) {
|
||||
const ImVec2 p0 = ImGui::GetCursorScreenPos();
|
||||
ImVec2 p1;
|
||||
if (vfb) {
|
||||
p1 = ImVec2(p0.x + vfb->width, p0.y + vfb->height);
|
||||
float scale = 1.0f;
|
||||
if (vfb && vfb->fbo) {
|
||||
scale = vfb->renderScaleFactor;
|
||||
p1 = ImVec2(p0.x + vfb->fbo->Width(), p0.y + vfb->fbo->Height());
|
||||
} else {
|
||||
// Guess
|
||||
p1 = ImVec2(p0.x + swViewer_.width, p0.y + swViewer_.height);
|
||||
@@ -733,18 +814,32 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
||||
// Draw border and background color
|
||||
drawList->PushClipRect(p0, p1, true);
|
||||
|
||||
PixelLookup *lookup = nullptr;
|
||||
if (vfb) {
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(vfb->fbo, Draw::FB_COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
ImGui::Image(texId, ImVec2(vfb->width, vfb->height));
|
||||
rbViewer_.Draw(gpuDebug, draw);
|
||||
lookup = &rbViewer_;
|
||||
// ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(vfb->fbo, Draw::Aspect::COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
// ImGui::Image(texId, ImVec2(vfb->width, vfb->height));
|
||||
} else {
|
||||
swViewer_.Draw(gpuDebug, draw);
|
||||
lookup = &swViewer_;
|
||||
}
|
||||
|
||||
// Draw vertex preview on top!
|
||||
DrawPreviewPrimitive(drawList, p0, previewPrim_, previewIndices_, previewVertices_, previewCount_, false);
|
||||
DrawPreviewPrimitive(drawList, p0, previewPrim_, previewIndices_, previewVertices_, previewCount_, false, scale, scale);
|
||||
|
||||
drawList->PopClipRect();
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
int x = (int)(ImGui::GetMousePos().x - p0.x);
|
||||
int y = (int)(ImGui::GetMousePos().y - p0.y);
|
||||
|
||||
uint32_t value = lookup->GetColorAt(x, y);
|
||||
ImGui::Text("%d, %d: %08x", x, y, value);
|
||||
} else {
|
||||
ImGui::TextUnformatted("(no pixel hovered)");
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Depth")) {
|
||||
@@ -756,8 +851,8 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
if (vfb) {
|
||||
ImGui::Text("%dx%d (emulated: %dx%d)", vfb->width, vfb->height, vfb->bufferWidth, vfb->bufferHeight);
|
||||
if (vfb && vfb->fbo) {
|
||||
ImGui::Text("VFB %dx%d (emulated: %dx%d)", vfb->width, vfb->height, vfb->fbo->Width(), vfb->fbo->Height());
|
||||
} else {
|
||||
// Use the swViewer_!
|
||||
ImGui::Text("Raw FB: %08x (%s)", gstate.getFrameBufRawAddress(), GeBufferFormatToString(gstate.FrameBufFormat()));
|
||||
|
||||
+35
-2
@@ -54,14 +54,24 @@ private:
|
||||
|
||||
namespace Draw {
|
||||
class Texture;
|
||||
enum class Aspect;
|
||||
enum class DataFormat : uint8_t;
|
||||
}
|
||||
|
||||
struct ImGePixelViewer {
|
||||
class PixelLookup {
|
||||
public:
|
||||
virtual ~PixelLookup() {}
|
||||
|
||||
virtual uint32_t GetColorAt(int x, int y) const = 0;
|
||||
};
|
||||
|
||||
struct ImGePixelViewer : public PixelLookup {
|
||||
~ImGePixelViewer();
|
||||
void Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw);
|
||||
bool Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw);
|
||||
void Snapshot() {
|
||||
dirty_ = true;
|
||||
}
|
||||
uint32_t GetColorAt(int x, int y) const override;
|
||||
|
||||
uint32_t addr = 0x04000000;
|
||||
uint16_t stride = 512;
|
||||
@@ -78,6 +88,28 @@ private:
|
||||
bool dirty_ = true;
|
||||
};
|
||||
|
||||
// Reads back framebuffers, not textures.
|
||||
struct ImGeReadbackViewer : public PixelLookup {
|
||||
ImGeReadbackViewer();
|
||||
~ImGeReadbackViewer();
|
||||
bool Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *);
|
||||
void Snapshot() {
|
||||
dirty_ = true;
|
||||
}
|
||||
uint32_t GetColorAt(int x, int y) const override;
|
||||
|
||||
VirtualFramebuffer *vfb = nullptr;
|
||||
|
||||
// This specifies what to show
|
||||
Draw::Aspect channel;
|
||||
|
||||
private:
|
||||
uint8_t *data_ = nullptr;
|
||||
Draw::DataFormat readbackFmt_;
|
||||
Draw::Texture *texture_ = nullptr;
|
||||
bool dirty_ = true;
|
||||
};
|
||||
|
||||
class ImGePixelViewerWindow {
|
||||
public:
|
||||
void Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug, Draw::DrawContext *draw);
|
||||
@@ -111,6 +143,7 @@ public:
|
||||
|
||||
private:
|
||||
ImGeDisasmView disasmView_;
|
||||
ImGeReadbackViewer rbViewer_;
|
||||
ImGePixelViewer swViewer_;
|
||||
int showBannerInFrames_ = 0;
|
||||
bool reloadPreview_ = false;
|
||||
|
||||
@@ -25,7 +25,7 @@ struct RegisteredTexture {
|
||||
Draw::Texture *texture;
|
||||
struct {
|
||||
Draw::Framebuffer *framebuffer;
|
||||
Draw::FBChannel aspect;
|
||||
Draw::Aspect aspect;
|
||||
};
|
||||
};
|
||||
ImGuiPipeline pipeline;
|
||||
@@ -93,7 +93,7 @@ void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_data, Draw::DrawContext *d
|
||||
void *boundNativeTexture;
|
||||
Draw::Pipeline *boundPipeline = bd->pipelines[0];
|
||||
Draw::SamplerState *boundSampler = bd->fontSampler;
|
||||
Draw::FBChannel boundAspect = Draw::FB_COLOR_BIT;
|
||||
Draw::Aspect boundAspect = Draw::Aspect::COLOR_BIT;
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++) {
|
||||
@@ -126,13 +126,13 @@ void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_data, Draw::DrawContext *d
|
||||
boundTexture = bd->tempTextures[index].texture;
|
||||
boundFBAsTexture = nullptr;
|
||||
boundNativeTexture = nullptr;
|
||||
boundAspect = Draw::FB_COLOR_BIT;
|
||||
boundAspect = Draw::Aspect::COLOR_BIT;
|
||||
break;
|
||||
case RegisteredTextureType::NativeTexture:
|
||||
boundTexture = nullptr;
|
||||
boundFBAsTexture = nullptr;
|
||||
boundNativeTexture = bd->tempTextures[index].nativeTexture;
|
||||
boundAspect = Draw::FB_COLOR_BIT;
|
||||
boundAspect = Draw::Aspect::COLOR_BIT;
|
||||
break;
|
||||
}
|
||||
boundPipeline = bd->pipelines[(int)bd->tempTextures[index].pipeline];
|
||||
@@ -364,7 +364,7 @@ ImTextureID ImGui_ImplThin3d_AddTextureTemp(Draw::Texture *texture, ImGuiPipelin
|
||||
return (ImTextureID)(uint64_t)(TEX_ID_OFFSET + bd->tempTextures.size() - 1);
|
||||
}
|
||||
|
||||
ImTextureID ImGui_ImplThin3d_AddFBAsTextureTemp(Draw::Framebuffer *framebuffer, Draw::FBChannel aspect, ImGuiPipeline pipeline) {
|
||||
ImTextureID ImGui_ImplThin3d_AddFBAsTextureTemp(Draw::Framebuffer *framebuffer, Draw::Aspect aspect, ImGuiPipeline pipeline) {
|
||||
BackendData* bd = ImGui_ImplThin3d_GetBackendData();
|
||||
|
||||
RegisteredTexture tex{ RegisteredTextureType::Framebuffer };
|
||||
|
||||
@@ -50,7 +50,7 @@ enum class ImGuiPipeline {
|
||||
// Textures are unregistered again in RenderDrawData. This is just simpler.
|
||||
IMGUI_IMPL_API ImTextureID ImGui_ImplThin3d_AddTextureTemp(Draw::Texture *texture, ImGuiPipeline pipeline = ImGuiPipeline::TexturedAlphaBlend);
|
||||
IMGUI_IMPL_API ImTextureID ImGui_ImplThin3d_AddNativeTextureTemp(void *texture, ImGuiPipeline pipeline = ImGuiPipeline::TexturedAlphaBlend);
|
||||
IMGUI_IMPL_API ImTextureID ImGui_ImplThin3d_AddFBAsTextureTemp(Draw::Framebuffer *framebuffer, Draw::FBChannel aspect = Draw::FB_COLOR_BIT, ImGuiPipeline pipeline = ImGuiPipeline::TexturedAlphaBlend);
|
||||
IMGUI_IMPL_API ImTextureID ImGui_ImplThin3d_AddFBAsTextureTemp(Draw::Framebuffer *framebuffer, Draw::Aspect aspect = Draw::Aspect::COLOR_BIT, ImGuiPipeline pipeline = ImGuiPipeline::TexturedAlphaBlend);
|
||||
|
||||
void ImGui_PushFixedFont();
|
||||
void ImGui_PopFont();
|
||||
|
||||
Reference in new issue
Block a user