metal: some fixes for MSAA

This commit is contained in:
Alex Szpakowski
2022-01-16 13:44:29 -04:00
parent d96e1636b1
commit 4e1c4a6afe
4 changed files with 45 additions and 27 deletions
+4
View File
@@ -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;
+28 -20
View File
@@ -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!");
+3 -1
View File
@@ -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
+10 -6
View File
@@ -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.