From aaab9791d57351476bb2114042fa4cebe99a4ae9 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 6 Jan 2024 15:21:06 -0400 Subject: [PATCH] Improve backbuffer depth buffer. - Setting the depth buffer for the backbuffer is now done as a boolean instead of a bit depth integer, in love.conf or love.window.setMode. - Error if depth writes are enabled when the active canvas setup or backbuffer does not have a depth buffer (now it matches stencil behaviour). - Don't allocate a backbuffer depth-stencil buffer if they're not requested. Metal also determines the format for that buffer based on which combination of depth and stencil is requested. OpenGL still has to allocate the depth-stencil buffer for the backbuffer all the time, because changing it requires the context to be recreated. --- src/modules/graphics/Graphics.cpp | 35 ++++++++++ src/modules/graphics/Graphics.h | 15 +++-- src/modules/graphics/metal/Graphics.h | 5 +- src/modules/graphics/metal/Graphics.mm | 81 ++++++++++++++---------- src/modules/graphics/opengl/Graphics.cpp | 60 +++++++++--------- src/modules/graphics/opengl/Graphics.h | 4 +- src/modules/graphics/vulkan/Graphics.cpp | 62 ++++++++++-------- src/modules/graphics/vulkan/Graphics.h | 5 +- src/modules/window/Window.h | 2 +- src/modules/window/sdl/Window.cpp | 11 ++-- src/modules/window/wrap_Window.cpp | 13 +++- 11 files changed, 183 insertions(+), 110 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index eeaeeff88..0797e4feb 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -185,6 +185,8 @@ Graphics::Graphics() , height(0) , pixelWidth(0) , pixelHeight(0) + , backbufferHasStencil(false) + , backbufferHasDepth(false) , created(false) , active(true) , batchedDrawState() @@ -617,6 +619,34 @@ Texture *Graphics::getTextureOrDefaultForActiveShader(Texture *tex) return getDefaultTexture(TEXTURE_2D, DATA_BASETYPE_FLOAT); } +void Graphics::validateStencilState(const StencilState &s) const +{ + if (s.action != STENCIL_KEEP) + { + const auto &rts = states.back().renderTargets; + love::graphics::Texture *dstexture = rts.depthStencil.texture.get(); + + if (!isRenderTargetActive() && !backbufferHasStencil) + throw love::Exception("The window must have stenciling enabled to draw to the main screen's stencil buffer."); + else if (isRenderTargetActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dstexture == nullptr || !isPixelFormatStencil(dstexture->getPixelFormat()))) + throw love::Exception("Drawing to the stencil buffer with a Canvas active requires either stencil=true or a custom stencil-type Canvas to be used, in setCanvas."); + } +} + +void Graphics::validateDepthState(bool depthwrite) const +{ + if (depthwrite) + { + const auto &rts = states.back().renderTargets; + love::graphics::Texture *dstexture = rts.depthStencil.texture.get(); + + if (!isRenderTargetActive() && !backbufferHasDepth) + throw love::Exception("The window must have depth enabled to draw to the main screen's depth buffer."); + else if (isRenderTargetActive() && (rts.temporaryRTFlags & TEMPORARY_RT_DEPTH) == 0 && (dstexture == nullptr || !isPixelFormatDepth(dstexture->getPixelFormat()))) + throw love::Exception("Drawing to the depth buffer with a Canvas active requires either depth=true or a custom depth-type Canvas to be used, in setCanvas."); + } +} + int Graphics::getWidth() const { return width; @@ -671,6 +701,11 @@ void Graphics::reset() origin(); } +void Graphics::backbufferChanged(int width, int height, int pixelwidth, int pixelheight) +{ + backbufferChanged(width, height, pixelwidth, pixelheight, backbufferHasStencil, backbufferHasDepth, getRequestedBackbufferMSAA()); +} + /** * State functions. **/ diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 38dec2568..030d9d7f1 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -506,16 +506,15 @@ public: virtual void present(void *screenshotCallbackData) = 0; /** - * Sets the current graphics display viewport dimensions. + * Called when the backbuffer changes. **/ - virtual void setViewportSize(int width, int height, int pixelwidth, int pixelheight) = 0; + virtual void backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) = 0; + void backbufferChanged(int width, int height, int pixelwidth, int pixelheight); /** * Sets the current graphics display viewport and initializes the renderer. - * @param width The viewport width. - * @param height The viewport height. **/ - virtual bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) = 0; + virtual bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) = 0; /** * Un-sets the current graphics display mode (uninitializing objects if @@ -1048,6 +1047,9 @@ protected: void releaseDefaultResources(); + void validateStencilState(const StencilState &s) const; + void validateDepthState(bool depthwrite) const; + void restoreState(const DisplayState &s); void restoreStateChecked(const DisplayState &s); @@ -1063,6 +1065,9 @@ protected: int pixelWidth; int pixelHeight; + bool backbufferHasStencil; + bool backbufferHasDepth; + bool created; bool active; diff --git a/src/modules/graphics/metal/Graphics.h b/src/modules/graphics/metal/Graphics.h index 1d910eb5e..d0477881c 100644 --- a/src/modules/graphics/metal/Graphics.h +++ b/src/modules/graphics/metal/Graphics.h @@ -68,8 +68,8 @@ public: Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override; - void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; - bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override; + void backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; + bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; void unSetMode() override; void setActive(bool active) override; @@ -231,7 +231,6 @@ private: uint32 dirtyRenderState; CullMode lastCullMode; Shader::RenderPipelineKey lastRenderPipelineKey; - bool windowHasStencil; int shaderSwitches; StrongRef backbufferMSAA; diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index 605172584..98dfd1c24 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -274,7 +274,6 @@ Graphics::Graphics() , dirtyRenderState(STATEBIT_ALL) , lastCullMode(CULL_MAX_ENUM) , lastRenderPipelineKey() - , windowHasStencil(false) , shaderSwitches(0) , requestedBackbufferMSAA(0) , attachmentStoreActions() @@ -464,13 +463,23 @@ Matrix4 Graphics::computeDeviceProjection(const Matrix4 &projection, bool /*rend return calculateDeviceProjection(projection, flags); } -void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) +void Graphics::backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) { + bool sizechanged = width != this->width || height != this->height + || pixelwidth != this->pixelWidth || pixelheight != this->pixelHeight; + + bool dschanged = backbufferstencil != this->backbufferHasStencil || backbufferdepth != this->backbufferHasDepth; + bool msaachanged = msaa != this->requestedBackbufferMSAA; + this->width = width; this->height = height; this->pixelWidth = pixelwidth; this->pixelHeight = pixelheight; + this->backbufferHasStencil = backbufferstencil; + this->backbufferHasDepth = backbufferdepth; + this->requestedBackbufferMSAA = msaa; + if (!isRenderTargetActive()) { dirtyRenderState |= STATEBIT_VIEWPORT | STATEBIT_SCISSOR; @@ -485,26 +494,38 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh settings.renderTarget = true; settings.readable.set(false); - backbufferMSAA.set(nullptr); - if (settings.msaa > 1) + if (sizechanged || msaachanged) { - settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_sRGB : PIXELFORMAT_BGRA8_UNORM; - backbufferMSAA.set(newTexture(settings), Acquire::NORETAIN); + backbufferMSAA.set(nullptr); + if (settings.msaa > 1) + { + settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_sRGB : PIXELFORMAT_BGRA8_UNORM; + backbufferMSAA.set(newTexture(settings), Acquire::NORETAIN); + } } - settings.format = PIXELFORMAT_DEPTH24_UNORM_STENCIL8; - backbufferDepthStencil.set(newTexture(settings), Acquire::NORETAIN); + if (sizechanged || msaachanged || dschanged) + { + backbufferDepthStencil.set(nullptr); + if (backbufferstencil || backbufferdepth) + { + if (backbufferstencil && backbufferdepth) + settings.format = PIXELFORMAT_DEPTH24_UNORM_STENCIL8; + else if (backbufferstencil) + settings.format = PIXELFORMAT_STENCIL8; + else if (backbufferdepth) + settings.format = PIXELFORMAT_DEPTH24_UNORM; + backbufferDepthStencil.set(newTexture(settings), Acquire::NORETAIN); + } + } } -bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) +bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) { @autoreleasepool { this->width = width; this->height = height; this->metalLayer = (__bridge CAMetalLayer *) context; - this->windowHasStencil = windowhasstencil; - this->requestedBackbufferMSAA = msaa; - metalLayer.device = device; metalLayer.pixelFormat = isGammaCorrect() ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm; @@ -516,7 +537,7 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int metalLayer.magnificationFilter = kCAFilterNearest; #endif - setViewportSize(width, height, pixelwidth, pixelheight); + backbufferChanged(width, height, pixelwidth, pixelheight, backbufferstencil, backbufferdepth, msaa); created = true; @@ -660,8 +681,10 @@ id Graphics::useRenderEncoder() passDesc.colorAttachments[0].depthPlane = 0; RenderTarget rt(backbufferDepthStencil); - setAttachment(rt, passDesc.depthAttachment, attachmentStoreActions.depth, false); - setAttachment(rt, passDesc.stencilAttachment, attachmentStoreActions.stencil, false); + if (rt.texture != nullptr && isPixelFormatDepth(rt.texture->getPixelFormat())) + setAttachment(rt, passDesc.depthAttachment, attachmentStoreActions.depth, false); + if (rt.texture != nullptr && isPixelFormatStencil(rt.texture->getPixelFormat())) + setAttachment(rt, passDesc.stencilAttachment, attachmentStoreActions.stencil, false); attachmentStoreActions.depth = MTLStoreActionDontCare; attachmentStoreActions.stencil = MTLStoreActionDontCare; @@ -700,11 +723,15 @@ void Graphics::submitRenderEncoder(SubmitType type) for (size_t i = 0; i < rts.colors.size(); i++) [renderEncoder setColorStoreAction:(store ? MTLStoreActionStore : actions.color[i]) atIndex:i]; - if (rts.depthStencil.texture.get() || rts.temporaryRTFlags != 0 || isbackbuffer) - { + love::graphics::Texture *ds = rts.depthStencil.texture.get(); + if (isbackbuffer) + ds = backbufferDepthStencil; + + if ((rts.temporaryRTFlags & TEMPORARY_RT_DEPTH) != 0 || (ds != nullptr && isPixelFormatDepth(ds->getPixelFormat()))) [renderEncoder setDepthStoreAction:store ? MTLStoreActionStore : actions.depth]; + + if ((rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) != 0 || (ds != nullptr && isPixelFormatStencil(ds->getPixelFormat()))) [renderEncoder setStencilStoreAction:store ? MTLStoreActionStore : actions.stencil]; - } [renderEncoder endEncoding]; renderEncoder = nil; @@ -1762,28 +1789,18 @@ void Graphics::setScissor() void Graphics::setStencilState(const StencilState &s) { - DisplayState &state = states.back(); - - if (s.action != STENCIL_KEEP) - { - const auto &rts = state.renderTargets; - love::graphics::Texture *dstexture = rts.depthStencil.texture.get(); - - if (!isRenderTargetActive() && !windowHasStencil) - throw love::Exception("The window must have stenciling enabled to draw to the main screen's stencil buffer."); - else if (isRenderTargetActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dstexture == nullptr || !isPixelFormatStencil(dstexture->getPixelFormat()))) - throw love::Exception("Drawing to the stencil buffer with a Canvas active requires either stencil=true or a custom stencil-type Canvas to be used, in setCanvas."); - } + validateStencilState(s); flushBatchedDraws(); - state.stencil = s; - + states.back().stencil = s; dirtyRenderState |= STATEBIT_STENCIL; } void Graphics::setDepthMode(CompareMode compare, bool write) { + validateDepthState(write); + DisplayState &state = states.back(); if (state.depthTest != compare || state.depthWrite != write) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index b56ed1cee..f6ff52205 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -200,13 +200,23 @@ Matrix4 Graphics::computeDeviceProjection(const Matrix4 &projection, bool render return calculateDeviceProjection(projection, flags); } -void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) +void Graphics::backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) { + bool changed = width != this->width || height != this->height + || pixelwidth != this->pixelWidth || pixelheight != this->pixelHeight; + + changed |= backbufferstencil != this->backbufferHasStencil || backbufferdepth != this->backbufferHasDepth; + changed |= msaa != this->requestedBackbufferMSAA; + this->width = width; this->height = height; this->pixelWidth = pixelwidth; this->pixelHeight = pixelheight; + this->backbufferHasStencil = backbufferstencil; + this->backbufferHasDepth = backbufferdepth; + this->requestedBackbufferMSAA = msaa; + if (!isRenderTargetActive()) { // Set the viewport to top-left corner. @@ -220,11 +230,9 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh resetProjection(); } - updateBackbuffer(width, height, pixelwidth, pixelheight, requestedBackbufferMSAA); -} + if (!changed) + return; -void Graphics::updateBackbuffer(int width, int height, int /*pixelwidth*/, int pixelheight, int msaa) -{ bool useinternalbackbuffer = false; if (msaa > 1) useinternalbackbuffer = true; @@ -253,8 +261,17 @@ void Graphics::updateBackbuffer(int width, int height, int /*pixelwidth*/, int p settings.format = isGammaCorrect() ? PIXELFORMAT_RGBA8_sRGB : PIXELFORMAT_RGBA8_UNORM; internalBackbuffer.set(newTexture(settings), Acquire::NORETAIN); - settings.format = PIXELFORMAT_DEPTH24_UNORM_STENCIL8; - internalBackbufferDepthStencil.set(newTexture(settings), Acquire::NORETAIN); + internalBackbufferDepthStencil.set(nullptr); + if (backbufferstencil || backbufferdepth) + { + if (backbufferstencil && backbufferdepth) + settings.format = PIXELFORMAT_DEPTH24_UNORM_STENCIL8; + else if (backbufferstencil) + settings.format = PIXELFORMAT_STENCIL8; + else if (backbufferdepth) + settings.format = PIXELFORMAT_DEPTH24_UNORM; + internalBackbufferDepthStencil.set(newTexture(settings), Acquire::NORETAIN); + } RenderTargets rts; rts.colors.push_back(internalBackbuffer.get()); @@ -269,8 +286,6 @@ void Graphics::updateBackbuffer(int width, int height, int /*pixelwidth*/, int p internalBackbufferFBO = 0; } - requestedBackbufferMSAA = msaa; - if (restoreFBO) gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, prevFBO); } @@ -300,14 +315,8 @@ GLuint Graphics::getSystemBackbufferFBO() const #endif } -bool Graphics::setMode(void */*context*/, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) +bool Graphics::setMode(void */*context*/, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) { - this->width = width; - this->height = height; - - this->windowHasStencil = windowhasstencil; - this->requestedBackbufferMSAA = msaa; - // Okay, setup OpenGL. gl.initContext(); @@ -364,7 +373,7 @@ bool Graphics::setMode(void */*context*/, int width, int height, int pixelwidth, setDebug(isDebugEnabled()); - setViewportSize(width, height, pixelwidth, pixelheight); + backbufferChanged(width, height, pixelwidth, pixelheight, backbufferstencil, backbufferdepth, msaa); if (batchedDrawState.vb[0] == nullptr) { @@ -1436,18 +1445,7 @@ void Graphics::setScissor() void Graphics::setStencilState(const StencilState &s) { - DisplayState &state = states.back(); - - if (s.action != STENCIL_KEEP) - { - const auto &rts = state.renderTargets; - love::graphics::Texture *dstexture = rts.depthStencil.texture.get(); - - if (!isRenderTargetActive() && !windowHasStencil) - throw love::Exception("The window must have stenciling enabled to draw to the main screen's stencil buffer."); - else if (isRenderTargetActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dstexture == nullptr || !isPixelFormatStencil(dstexture->getPixelFormat()))) - throw love::Exception("Drawing to the stencil buffer with a render target active requires either stencil=true or a custom stencil-type texture to be used, in setRenderTarget."); - } + validateStencilState(s); flushBatchedDraws(); @@ -1507,11 +1505,13 @@ void Graphics::setStencilState(const StencilState &s) if (s.writeMask != gl.getStencilWriteMask()) gl.setStencilWriteMask(s.writeMask); - state.stencil = s; + states.back().stencil = s; } void Graphics::setDepthMode(CompareMode compare, bool write) { + validateDepthState(write); + DisplayState &state = states.back(); if (state.depthTest != compare || state.depthWrite != write) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 894b52e21..7e064420e 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -64,8 +64,8 @@ public: Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override; - void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; - bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override; + void backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; + bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; void unSetMode() override; void setActive(bool active) override; diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 399e9b4e8..98e64e520 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -587,9 +587,10 @@ void Graphics::present(void *screenshotCallbackdata) beginFrame(); } -void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelheight) +void Graphics::backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) { - if (swapChain != VK_NULL_HANDLE && (pixelwidth != this->pixelWidth || pixelheight != this->pixelHeight || width != this->width || height != this->height)) + if (swapChain != VK_NULL_HANDLE && (pixelwidth != this->pixelWidth || pixelheight != this->pixelHeight || width != this->width || height != this->height + || backbufferstencil != this->backbufferHasStencil || backbufferdepth != this->backbufferHasDepth || msaa != requestedMsaa)) requestSwapchainRecreation(); this->width = width; @@ -597,17 +598,21 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh this->pixelWidth = pixelwidth; this->pixelHeight = pixelheight; + this->backbufferHasStencil = backbufferstencil; + this->backbufferHasDepth = backbufferdepth; + this->requestedMsaa = msaa; + if (!isRenderTargetActive()) resetProjection(); + + if (swapChain != VK_NULL_HANDLE) + msaaSamples = getMsaaCount(requestedMsaa); } -bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) +bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) { - requestedMsaa = msaa; - windowHasStencil = windowhasstencil; - // Must be called before the swapchain is created. - setViewportSize(width, height, pixelwidth, pixelheight); + backbufferChanged(width, height, pixelwidth, pixelheight, backbufferstencil, backbufferdepth, msaa); cleanUpFunctions.clear(); cleanUpFunctions.resize(MAX_FRAMES_IN_FLIGHT); @@ -1003,16 +1008,7 @@ void Graphics::setScissor() void Graphics::setStencilState(const StencilState &s) { - if (s.action != STENCIL_KEEP) - { - const auto& rts = states.back().renderTargets; - auto dsTexture = rts.depthStencil.texture.get(); - - if (!isRenderTargetActive() && !windowHasStencil) - throw love::Exception("The window must have stenciling enabled to draw to the main screen's stencil buffer"); - else if (isRenderTargetActive() && (rts.temporaryRTFlags & TEMPORARY_RT_STENCIL) == 0 && (dsTexture == nullptr || !isPixelFormatStencil(dsTexture->getPixelFormat()))) - throw love::Exception("drawing to the stencil buffer with a render target active requires either stencil=true or a custom stencil-type to be used, in setRenderTarget"); - } + validateStencilState(s); flushBatchedDraws(); @@ -1033,6 +1029,8 @@ void Graphics::setStencilState(const StencilState &s) void Graphics::setDepthMode(CompareMode compare, bool write) { + validateDepthState(write); + flushBatchedDraws(); if (optionalDeviceExtensions.extendedDynamicState) @@ -1284,11 +1282,12 @@ void Graphics::beginFrame() if (transitionColorDepthLayouts) { - Vulkan::cmdTransitionImageLayout( - commandBuffers.at(currentFrame), - depthImage, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + if (depthImage) + Vulkan::cmdTransitionImageLayout( + commandBuffers.at(currentFrame), + depthImage, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); if (colorImage) Vulkan::cmdTransitionImageLayout( @@ -2935,6 +2934,13 @@ VkFormat Graphics::findDepthFormat() void Graphics::createDepthResources() { + if (!backbufferHasDepth && !backbufferHasStencil) + { + depthImage = VK_NULL_HANDLE; + depthImageView = VK_NULL_HANDLE; + return; + } + VkImageCreateInfo imageInfo{}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.imageType = VK_IMAGE_TYPE_2D; @@ -2966,8 +2972,9 @@ void Graphics::createDepthResources() imageViewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - imageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (windowHasStencil) + if (backbufferHasDepth) + imageViewInfo.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + if (backbufferHasStencil) imageViewInfo.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; imageViewInfo.subresourceRange.baseMipLevel = 0; imageViewInfo.subresourceRange.levelCount = 1; @@ -3076,8 +3083,11 @@ void Graphics::cleanupSwapChain() vkDestroyImageView(device, colorImageView, nullptr); vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation); } - vkDestroyImageView(device, depthImageView, nullptr); - vmaDestroyImage(vmaAllocator, depthImage, depthImageAllocation); + if (depthImage) + { + vkDestroyImageView(device, depthImageView, nullptr); + vmaDestroyImage(vmaAllocator, depthImage, depthImageAllocation); + } for (const auto &swapChainImageView : swapChainImageViews) vkDestroyImageView(device, swapChainImageView, nullptr); swapChainImageViews.clear(); diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index a7c9f9ffd..fc51d69ce 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -284,8 +284,8 @@ public: Matrix4 computeDeviceProjection(const Matrix4 &projection, bool rendertotexture) const override; void discard(const std::vector& colorbuffers, bool depthstencil) override; void present(void *screenshotCallbackdata) override; - void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override; - bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override; + void backbufferChanged(int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; + bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, bool backbufferdepth, int msaa) override; void unSetMode() override; void setActive(bool active) override; int getRequestedBackbufferMSAA() const override; @@ -394,7 +394,6 @@ private: VkInstance instance = VK_NULL_HANDLE; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; uint32_t deviceApiVersion = VK_API_VERSION_1_0; - bool windowHasStencil = false; int requestedMsaa = 0; VkDevice device = VK_NULL_HANDLE; OptionalInstanceExtensions optionalInstanceExtensions; diff --git a/src/modules/window/Window.h b/src/modules/window/Window.h index d15091e43..9676dd455 100644 --- a/src/modules/window/Window.h +++ b/src/modules/window/Window.h @@ -262,7 +262,7 @@ struct WindowSettings int vsync = 1; int msaa = 0; bool stencil = true; - int depth = 0; + bool depth = false; bool resizable = false; int minwidth = 1; int minheight = 1; diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index b124bd54e..5205bcd7e 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -127,8 +127,7 @@ void Window::setGLFramebufferAttributes(bool sRGB) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0); - // Always use 24/8 depth/stencil (make sure any Graphics implementations - // that have their own backbuffer match this, too). + // Always use 24/8 depth/stencil. // Changing this after initial window creation would need the context to be // destroyed and recreated, which we really don't want. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); @@ -639,12 +638,12 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) context = (void *) SDL_Metal_GetLayer(metalView); #endif - graphics->setMode(context, (int) scaledw, (int) scaledh, pixelWidth, pixelHeight, f.stencil, f.msaa); + graphics->setMode(context, (int) scaledw, (int) scaledh, pixelWidth, pixelHeight, f.stencil, f.depth, f.msaa); this->settings.msaa = graphics->getBackbufferMSAA(); } else { - graphics->setViewportSize((int) scaledw, (int) scaledh, pixelWidth, pixelHeight); + graphics->backbufferChanged((int) scaledw, (int) scaledh, pixelWidth, pixelHeight, f.stencil, f.depth, f.msaa); } } @@ -687,7 +686,7 @@ bool Window::onSizeChanged(int width, int height) { double scaledw, scaledh; fromPixels((double) pixelWidth, (double) pixelHeight, scaledw, scaledh); - graphics->setViewportSize((int) scaledw, (int) scaledh, pixelWidth, pixelHeight); + graphics->backbufferChanged((int) scaledw, (int) scaledh, pixelWidth, pixelHeight); } return true; @@ -771,7 +770,7 @@ void Window::updateSettings(const WindowSettings &newsettings, bool updateGraphi { double scaledw, scaledh; fromPixels((double) pixelWidth, (double) pixelHeight, scaledw, scaledh); - graphics->setViewportSize((int) scaledw, (int) scaledh, pixelWidth, pixelHeight); + graphics->backbufferChanged((int) scaledw, (int) scaledh, pixelWidth, pixelHeight); } } diff --git a/src/modules/window/wrap_Window.cpp b/src/modules/window/wrap_Window.cpp index 3d3d86708..60aea2993 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -68,7 +68,6 @@ static int readWindowSettings(lua_State *L, int idx, WindowSettings &settings) settings.fullscreen = luax_boolflag(L, idx, settingName(Window::SETTING_FULLSCREEN), settings.fullscreen); settings.msaa = luax_intflag(L, idx, settingName(Window::SETTING_MSAA), settings.msaa); settings.stencil = luax_boolflag(L, idx, settingName(Window::SETTING_STENCIL), settings.stencil); - settings.depth = luax_intflag(L, idx, settingName(Window::SETTING_DEPTH), settings.depth); settings.resizable = luax_boolflag(L, idx, settingName(Window::SETTING_RESIZABLE), settings.resizable); settings.minwidth = luax_intflag(L, idx, settingName(Window::SETTING_MIN_WIDTH), settings.minwidth); settings.minheight = luax_intflag(L, idx, settingName(Window::SETTING_MIN_HEIGHT), settings.minheight); @@ -76,6 +75,16 @@ static int readWindowSettings(lua_State *L, int idx, WindowSettings &settings) settings.centered = luax_boolflag(L, idx, settingName(Window::SETTING_CENTERED), settings.centered); settings.usedpiscale = luax_boolflag(L, idx, settingName(Window::SETTING_USE_DPISCALE), settings.usedpiscale); + lua_getfield(L, idx, settingName(Window::SETTING_DEPTH)); + if (lua_type(L, -1) == LUA_TNUMBER) + { + luax_markdeprecated(L, 1, "window.depth number", API_FIELD, DEPRECATED_REPLACED, "window.depth boolean field"); + settings.depth = (int) luaL_checknumber(L, -1); + } + else if (!lua_isnoneornil(L, -1)) + settings.depth = lua_toboolean(L, -1); + lua_pop(L, 1); + settings.displayindex = luax_intflag(L, idx, settingName(Window::SETTING_DISPLAYINDEX), settings.displayindex + 1) - 1; lua_getfield(L, idx, settingName(Window::SETTING_DISPLAY)); if (!lua_isnoneornil(L, -1)) @@ -197,7 +206,7 @@ int w_getMode(lua_State *L) luax_pushboolean(L, settings.stencil); lua_setfield(L, -2, settingName(Window::SETTING_STENCIL)); - lua_pushinteger(L, settings.depth); + luax_pushboolean(L, settings.depth); lua_setfield(L, -2, settingName(Window::SETTING_DEPTH)); luax_pushboolean(L, settings.resizable);