mirror of
https://github.com/love2d/love.git
synced 2026-08-18 11:44:15 +02:00
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.
This commit is contained in:
@@ -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<MTLRenderCommandEncoder> 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)
|
||||
|
||||
Reference in New Issue
Block a user