mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-20 01:39:07 +02:00
thin3d: Add Framebuffer::HasDepthStencil, check it before depth/stencil copies
ResizeFramebufFBO now asks the framebuffer whether it has a depth/stencil buffer instead of guessing from the z address and stride. Vulkan CopyFramebuffer gets the debug asserts and bail-out BlitFramebuffer already had, and GL copies and blits get the same, so a copy out of a framebuffer without depth/stencil asserts where it's queued instead of in the queue runner. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
8fb0f74255
commit
074b66b49b
6 files changed
+35
-5
No files matched your search
@@ -64,9 +64,10 @@ public:
|
||||
// A D3D11Framebuffer is a D3D11Framebuffer plus all the textures it owns.
|
||||
class D3D11Framebuffer : public Framebuffer {
|
||||
public:
|
||||
D3D11Framebuffer(int width, int height) {
|
||||
D3D11Framebuffer(int width, int height, bool zStencil) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
hasDepthStencil_ = zStencil;
|
||||
}
|
||||
~D3D11Framebuffer() {
|
||||
}
|
||||
@@ -1495,7 +1496,7 @@ uint32_t D3D11DrawContext::GetDataFormatSupport(DataFormat fmt) const {
|
||||
|
||||
Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) {
|
||||
HRESULT hr;
|
||||
D3D11Framebuffer *fb = new D3D11Framebuffer(desc.width, desc.height);
|
||||
D3D11Framebuffer *fb = new D3D11Framebuffer(desc.width, desc.height, desc.z_stencil);
|
||||
|
||||
// We don't (yet?) support multiview for D3D11. Not sure if there's a way to do it.
|
||||
// Texture arrays are supported but we don't have any other use cases yet.
|
||||
|
||||
@@ -959,6 +959,7 @@ public:
|
||||
OpenGLFramebuffer(GLRenderManager *render, GLRFramebuffer *framebuffer) : render_(render), framebuffer_(framebuffer) {
|
||||
width_ = framebuffer->width;
|
||||
height_ = framebuffer->height;
|
||||
hasDepthStencil_ = framebuffer->z_stencil_;
|
||||
}
|
||||
~OpenGLFramebuffer() {
|
||||
render_->DeleteFramebuffer(framebuffer_);
|
||||
@@ -1596,6 +1597,14 @@ void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int s
|
||||
OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc;
|
||||
OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst;
|
||||
|
||||
if (aspects & (Aspect::DEPTH_BIT | Aspect::STENCIL_BIT)) {
|
||||
_dbg_assert_msg_(src->HasDepthStencil(), "%s", src->framebuffer_->Tag());
|
||||
_dbg_assert_msg_(dst->HasDepthStencil(), "%s", dst->framebuffer_->Tag());
|
||||
if (!src->HasDepthStencil() || !dst->HasDepthStencil()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int glAspect = 0;
|
||||
if (aspects & Aspect::COLOR_BIT) {
|
||||
glAspect |= GL_COLOR_BUFFER_BIT;
|
||||
@@ -1611,6 +1620,14 @@ void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int s
|
||||
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;
|
||||
if (aspects & (Aspect::DEPTH_BIT | Aspect::STENCIL_BIT)) {
|
||||
_dbg_assert_msg_(src->HasDepthStencil(), "%s", src->framebuffer_->Tag());
|
||||
_dbg_assert_msg_(dst->HasDepthStencil(), "%s", dst->framebuffer_->Tag());
|
||||
if (!src->HasDepthStencil() || !dst->HasDepthStencil()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint aspect = 0;
|
||||
if (aspects & Aspect::COLOR_BIT)
|
||||
aspect |= GL_COLOR_BUFFER_BIT;
|
||||
|
||||
@@ -1440,6 +1440,16 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,
|
||||
_dbg_assert_msg_(dstPos.x + srcRect.extent.width <= (uint32_t)dst->width, "dstPos + extent x > width");
|
||||
_dbg_assert_msg_(dstPos.y + srcRect.extent.height <= (uint32_t)dst->height, "dstPos + extent y > height");
|
||||
|
||||
if (aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
_dbg_assert_msg_(src->depth.image != VK_NULL_HANDLE, "%s", src->Tag());
|
||||
_dbg_assert_msg_(dst->depth.image != VK_NULL_HANDLE, "%s", dst->Tag());
|
||||
|
||||
if (!src->depth.image || !dst->depth.image) {
|
||||
// Something has gone wrong, but let's try to stumble along.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VkImageLayout finalSrcLayoutBeforeCopy = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
if (src == dst) {
|
||||
// We only use the first loop before, and transition to VK_IMAGE_LAYOUT_GENERAL.
|
||||
|
||||
@@ -1839,6 +1839,7 @@ public:
|
||||
height_ = fb->height;
|
||||
layers_ = fb->numLayers;
|
||||
multiSampleLevel_ = multiSampleLevel;
|
||||
hasDepthStencil_ = fb->HasDepth();
|
||||
}
|
||||
~VKFramebuffer() {
|
||||
_assert_msg_(buf_, "Null buf_ in VKFramebuffer - double delete?");
|
||||
|
||||
@@ -450,12 +450,14 @@ public:
|
||||
int Height() const { return height_; }
|
||||
int Layers() const { return layers_; }
|
||||
int MultiSampleLevel() const { return multiSampleLevel_; }
|
||||
bool HasDepthStencil() const { return hasDepthStencil_; }
|
||||
|
||||
virtual void UpdateTag(const char *tag) {}
|
||||
virtual const char *Tag() const { return "(no name)"; }
|
||||
|
||||
protected:
|
||||
int width_ = -1, height_ = -1, layers_ = 1, multiSampleLevel_ = 0;
|
||||
bool hasDepthStencil_ = false;
|
||||
};
|
||||
|
||||
class Buffer : public RefCountedObject {
|
||||
|
||||
@@ -2035,9 +2035,8 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
|
||||
if (vfb->usageFlags & FB_USAGE_RENDER_DEPTH) {
|
||||
BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min((u16)oldWidth, std::min(vfb->bufferWidth, vfb->width)), std::min((u16)oldHeight, std::min(vfb->height, vfb->bufferHeight)), 0, RASTER_DEPTH, "BlitDepth_ResizeFramebufFBO");
|
||||
}
|
||||
// A color framebuffer from CreateRAMFramebuffer (no z address or stride) has no depth/stencil buffer to copy from.
|
||||
const bool oldHasStencil = old.z_address != 0 || old.z_stride != 0;
|
||||
if (!skipCopy && vfb->fb_format != GE_FORMAT_565 && oldHasStencil) {
|
||||
// A color framebuffer from CreateRAMFramebuffer has no depth/stencil buffer to copy from.
|
||||
if (!skipCopy && vfb->fb_format != GE_FORMAT_565 && old.fbo->HasDepthStencil()) {
|
||||
// Keep the stencil too (Need for Speed Shift stencil tests right after its framebuffer grows from 480 to
|
||||
// 512 wide). D3D11 has no separate stencil copy, but copies it along with the depth above.
|
||||
const int stencilW = std::min(old.renderWidth, vfb->renderWidth);
|
||||
|
||||
Reference in new issue
Block a user