mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
metal: some fixes for MSAA
This commit is contained in:
@@ -123,6 +123,8 @@ public:
|
|||||||
id<MTLCommandBuffer> getCommandBuffer() const { return commandBuffer; }
|
id<MTLCommandBuffer> getCommandBuffer() const { return commandBuffer; }
|
||||||
void submitCommandBuffer(SubmitType type);
|
void submitCommandBuffer(SubmitType type);
|
||||||
|
|
||||||
|
void submitAllEncoders(SubmitType type);
|
||||||
|
|
||||||
id<MTLRenderCommandEncoder> useRenderEncoder();
|
id<MTLRenderCommandEncoder> useRenderEncoder();
|
||||||
id<MTLRenderCommandEncoder> getRenderEncoder() const { return renderEncoder; }
|
id<MTLRenderCommandEncoder> getRenderEncoder() const { return renderEncoder; }
|
||||||
void submitRenderEncoder(SubmitType type);
|
void submitRenderEncoder(SubmitType type);
|
||||||
@@ -141,6 +143,8 @@ public:
|
|||||||
Buffer *getDefaultAttributesBuffer() const { return defaultAttributesBuffer; }
|
Buffer *getDefaultAttributesBuffer() const { return defaultAttributesBuffer; }
|
||||||
Texture *getDefaultTexture(TextureType textype) const { return defaultTextures[textype]; }
|
Texture *getDefaultTexture(TextureType textype) const { return defaultTextures[textype]; }
|
||||||
|
|
||||||
|
int getClosestMSAASamples(int requestedsamples);
|
||||||
|
|
||||||
static Graphics *getInstance() { return graphicsInstance; }
|
static Graphics *getInstance() { return graphicsInstance; }
|
||||||
|
|
||||||
id<MTLDevice> device;
|
id<MTLDevice> device;
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ static MTLPrimitiveType getMTLPrimitiveType(PrimitiveType prim)
|
|||||||
{
|
{
|
||||||
case PRIMITIVE_TRIANGLES: return MTLPrimitiveTypeTriangle;
|
case PRIMITIVE_TRIANGLES: return MTLPrimitiveTypeTriangle;
|
||||||
case PRIMITIVE_TRIANGLE_STRIP: return MTLPrimitiveTypeTriangleStrip;
|
case PRIMITIVE_TRIANGLE_STRIP: return MTLPrimitiveTypeTriangleStrip;
|
||||||
case PRIMITIVE_TRIANGLE_FAN: return MTLPrimitiveTypeTriangle; // This needs to be emulated.
|
case PRIMITIVE_TRIANGLE_FAN: return MTLPrimitiveTypeTriangle; // TODO: This needs to be emulated.
|
||||||
case PRIMITIVE_POINTS: return MTLPrimitiveTypePoint;
|
case PRIMITIVE_POINTS: return MTLPrimitiveTypePoint;
|
||||||
case PRIMITIVE_MAX_ENUM: return MTLPrimitiveTypeTriangle;
|
case PRIMITIVE_MAX_ENUM: return MTLPrimitiveTypeTriangle;
|
||||||
}
|
}
|
||||||
@@ -448,7 +448,7 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh
|
|||||||
backbufferMSAA.set(nullptr);
|
backbufferMSAA.set(nullptr);
|
||||||
if (settings.msaa > 1)
|
if (settings.msaa > 1)
|
||||||
{
|
{
|
||||||
settings.format = isGammaCorrect() ? PIXELFORMAT_RGBA8_UNORM_sRGB : PIXELFORMAT_RGBA8_UNORM;
|
settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM;
|
||||||
backbufferMSAA.set(newTexture(settings), Acquire::NORETAIN);
|
backbufferMSAA.set(newTexture(settings), Acquire::NORETAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,9 +537,7 @@ id<MTLCommandBuffer> Graphics::useCommandBuffer()
|
|||||||
|
|
||||||
void Graphics::submitCommandBuffer(SubmitType type)
|
void Graphics::submitCommandBuffer(SubmitType type)
|
||||||
{
|
{
|
||||||
submitRenderEncoder(type);
|
submitAllEncoders(type);
|
||||||
submitBlitEncoder();
|
|
||||||
submitComputeEncoder();
|
|
||||||
|
|
||||||
if (commandBuffer != nil)
|
if (commandBuffer != nil)
|
||||||
{
|
{
|
||||||
@@ -548,6 +546,13 @@ void Graphics::submitCommandBuffer(SubmitType type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Graphics::submitAllEncoders(SubmitType type)
|
||||||
|
{
|
||||||
|
submitRenderEncoder(type);
|
||||||
|
submitBlitEncoder();
|
||||||
|
submitComputeEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
static inline void setAttachment(const Graphics::RenderTarget &rt, MTLRenderPassAttachmentDescriptor *desc, MTLStoreAction &storeaction, bool setload = true)
|
static inline void setAttachment(const Graphics::RenderTarget &rt, MTLRenderPassAttachmentDescriptor *desc, MTLStoreAction &storeaction, bool setload = true)
|
||||||
{
|
{
|
||||||
bool isvolume = rt.texture->getTextureType() == TEXTURE_VOLUME;
|
bool isvolume = rt.texture->getTextureType() == TEXTURE_VOLUME;
|
||||||
@@ -579,8 +584,7 @@ id<MTLRenderCommandEncoder> Graphics::useRenderEncoder()
|
|||||||
{
|
{
|
||||||
if (renderEncoder == nil)
|
if (renderEncoder == nil)
|
||||||
{
|
{
|
||||||
submitBlitEncoder();
|
submitAllEncoders(SUBMIT_STORE);
|
||||||
submitComputeEncoder();
|
|
||||||
|
|
||||||
// Pass desc info for non-backbuffer render targets are set up in
|
// Pass desc info for non-backbuffer render targets are set up in
|
||||||
// setRenderTargetsInternal.
|
// setRenderTargetsInternal.
|
||||||
@@ -682,8 +686,7 @@ id<MTLBlitCommandEncoder> Graphics::useBlitEncoder()
|
|||||||
{
|
{
|
||||||
if (blitEncoder == nil)
|
if (blitEncoder == nil)
|
||||||
{
|
{
|
||||||
submitRenderEncoder(SUBMIT_STORE);
|
submitAllEncoders(SUBMIT_STORE);
|
||||||
submitComputeEncoder();
|
|
||||||
blitEncoder = [useCommandBuffer() blitCommandEncoder];
|
blitEncoder = [useCommandBuffer() blitCommandEncoder];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,8 +706,7 @@ id<MTLComputeCommandEncoder> Graphics::useComputeEncoder()
|
|||||||
{
|
{
|
||||||
if (computeEncoder == nil)
|
if (computeEncoder == nil)
|
||||||
{
|
{
|
||||||
submitRenderEncoder(SUBMIT_STORE);
|
submitAllEncoders(SUBMIT_STORE);
|
||||||
submitBlitEncoder();
|
|
||||||
computeEncoder = [useCommandBuffer() computeCommandEncoder];
|
computeEncoder = [useCommandBuffer() computeCommandEncoder];
|
||||||
renderBindings = {};
|
renderBindings = {};
|
||||||
}
|
}
|
||||||
@@ -902,20 +904,26 @@ void Graphics::applyRenderState(id<MTLRenderCommandEncoder> encoder, const Verte
|
|||||||
key.blend = state.blend;
|
key.blend = state.blend;
|
||||||
key.colorChannelMask = state.colorMask;
|
key.colorChannelMask = state.colorMask;
|
||||||
|
|
||||||
if (state.renderTargets.getFirstTarget().texture.get() == nullptr)
|
const auto &firsttarget = state.renderTargets.getFirstTarget();
|
||||||
|
|
||||||
|
if (firsttarget.texture.get() == nullptr)
|
||||||
{
|
{
|
||||||
key.colorRenderTargetFormats = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM;
|
key.colorRenderTargetFormats = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM;
|
||||||
key.depthStencilFormat = backbufferDepthStencil->getPixelFormat();
|
key.depthStencilFormat = backbufferDepthStencil->getPixelFormat();
|
||||||
|
key.msaa = backbufferMSAA ? (uint8) backbufferMSAA->getMSAA() : 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto &rts = state.renderTargets.colors;
|
const auto &rts = state.renderTargets.colors;
|
||||||
|
|
||||||
for (size_t i = 0; i < rts.size(); i++)
|
for (size_t i = 0; i < rts.size(); i++)
|
||||||
key.colorRenderTargetFormats |= (rts[i].texture->getPixelFormat()) << (8 * i);
|
key.colorRenderTargetFormats |= (rts[i].texture->getPixelFormat()) << (8 * i);
|
||||||
|
|
||||||
// TODO: automatic depth/stencil (state doesn't store it).
|
// TODO: automatic depth/stencil (state doesn't store it).
|
||||||
if (state.renderTargets.depthStencil.texture.get())
|
if (state.renderTargets.depthStencil.texture.get())
|
||||||
key.depthStencilFormat = state.renderTargets.depthStencil.texture->getPixelFormat();
|
key.depthStencilFormat = state.renderTargets.depthStencil.texture->getPixelFormat();
|
||||||
|
|
||||||
|
key.msaa = (uint8) firsttarget.texture->getMSAA();
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = shader->getCachedRenderPipeline(key);
|
pipeline = shader->getCachedRenderPipeline(key);
|
||||||
@@ -2052,19 +2060,19 @@ Graphics::RendererInfo Graphics::getRendererInfo() const
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::initCapabilities()
|
int Graphics::getClosestMSAASamples(int requestedsamples)
|
||||||
{
|
{
|
||||||
int msaa = 1;
|
|
||||||
const int checkmsaa[] = {32, 16, 8, 4, 2};
|
const int checkmsaa[] = {32, 16, 8, 4, 2};
|
||||||
for (int samples : checkmsaa)
|
for (int samples : checkmsaa)
|
||||||
{
|
{
|
||||||
if ([device supportsTextureSampleCount:samples])
|
if (samples <= requestedsamples && [device supportsTextureSampleCount:samples])
|
||||||
{
|
return samples;
|
||||||
msaa = samples;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::initCapabilities()
|
||||||
|
{
|
||||||
if (@available(macOS 10.15, iOS 13.0, *))
|
if (@available(macOS 10.15, iOS 13.0, *))
|
||||||
{
|
{
|
||||||
for (NSInteger i = 0; i < 7; i++)
|
for (NSInteger i = 0; i < 7; i++)
|
||||||
@@ -2161,7 +2169,7 @@ void Graphics::initCapabilities()
|
|||||||
capabilities.limits[LIMIT_RENDER_TARGETS] = 8;
|
capabilities.limits[LIMIT_RENDER_TARGETS] = 8;
|
||||||
else
|
else
|
||||||
capabilities.limits[LIMIT_RENDER_TARGETS] = 4;
|
capabilities.limits[LIMIT_RENDER_TARGETS] = 4;
|
||||||
capabilities.limits[LIMIT_TEXTURE_MSAA] = msaa;
|
capabilities.limits[LIMIT_TEXTURE_MSAA] = getClosestMSAASamples(32);
|
||||||
capabilities.limits[LIMIT_ANISOTROPY] = 16.0f;
|
capabilities.limits[LIMIT_ANISOTROPY] = 16.0f;
|
||||||
static_assert(LIMIT_MAX_ENUM == 13, "Graphics::initCapabilities must be updated when adding a new system limit!");
|
static_assert(LIMIT_MAX_ENUM == 13, "Graphics::initCapabilities must be updated when adding a new system limit!");
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
ptrdiff_t getRenderTargetHandle() const override { return msaaTexture != nil ? (ptrdiff_t) msaaTexture : (ptrdiff_t) texture; }
|
ptrdiff_t getRenderTargetHandle() const override { return msaaTexture != nil ? (ptrdiff_t) msaaTexture : (ptrdiff_t) texture; }
|
||||||
ptrdiff_t getSamplerHandle() const override { return (ptrdiff_t) sampler; }
|
ptrdiff_t getSamplerHandle() const override { return (ptrdiff_t) sampler; }
|
||||||
|
|
||||||
int getMSAA() const override { return 1 /* TODO*/; }
|
int getMSAA() const override { return actualMSAASamples; }
|
||||||
|
|
||||||
id<MTLSamplerState> getMTLSampler() const { return sampler; }
|
id<MTLSamplerState> getMTLSampler() const { return sampler; }
|
||||||
|
|
||||||
@@ -63,6 +63,8 @@ private:
|
|||||||
id<MTLTexture> msaaTexture;
|
id<MTLTexture> msaaTexture;
|
||||||
id<MTLSamplerState> sampler;
|
id<MTLSamplerState> sampler;
|
||||||
|
|
||||||
|
int actualMSAASamples;
|
||||||
|
|
||||||
}; // Texture
|
}; // Texture
|
||||||
|
|
||||||
} // metal
|
} // metal
|
||||||
|
|||||||
@@ -41,12 +41,15 @@ static MTLTextureType getMTLTextureType(TextureType type, int msaa)
|
|||||||
return MTLTextureType2D;
|
return MTLTextureType2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(love::graphics::Graphics *gfx, id<MTLDevice> device, const Settings &settings, const Slices *data)
|
Texture::Texture(love::graphics::Graphics *gfxbase, id<MTLDevice> device, const Settings &settings, const Slices *data)
|
||||||
: love::graphics::Texture(gfx, settings, data)
|
: love::graphics::Texture(gfxbase, settings, data)
|
||||||
, texture(nil)
|
, texture(nil)
|
||||||
, msaaTexture(nil)
|
, msaaTexture(nil)
|
||||||
, sampler(nil)
|
, sampler(nil)
|
||||||
|
, actualMSAASamples(1)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
|
auto gfx = (Graphics *) gfxbase;
|
||||||
|
|
||||||
MTLTextureDescriptor *desc = [MTLTextureDescriptor new];
|
MTLTextureDescriptor *desc = [MTLTextureDescriptor new];
|
||||||
|
|
||||||
int w = pixelWidth;
|
int w = pixelWidth;
|
||||||
@@ -81,11 +84,12 @@ Texture::Texture(love::graphics::Graphics *gfx, id<MTLDevice> device, const Sett
|
|||||||
if (texture == nil)
|
if (texture == nil)
|
||||||
throw love::Exception("Out of graphics memory.");
|
throw love::Exception("Out of graphics memory.");
|
||||||
|
|
||||||
if (getRequestedMSAA() > 1)
|
actualMSAASamples = gfx->getClosestMSAASamples(getRequestedMSAA());
|
||||||
|
|
||||||
|
if (actualMSAASamples > 1)
|
||||||
{
|
{
|
||||||
// TODO: sampleCount validation
|
desc.sampleCount = actualMSAASamples;
|
||||||
desc.sampleCount = getRequestedMSAA();
|
desc.textureType = getMTLTextureType(texType, actualMSAASamples);
|
||||||
desc.textureType = getMTLTextureType(texType, (int)desc.sampleCount);
|
|
||||||
desc.usage &= ~MTLTextureUsageShaderRead;
|
desc.usage &= ~MTLTextureUsageShaderRead;
|
||||||
|
|
||||||
// TODO: This needs to be cleared, etc.
|
// TODO: This needs to be cleared, etc.
|
||||||
|
|||||||
Reference in New Issue
Block a user