From ceb1e4459b4f9f4e62f65a262c840526fb33289d Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 26 Apr 2020 09:09:26 -0300 Subject: [PATCH] metal: initial sampler cache implementation --- src/modules/graphics/metal/Graphics.h | 4 ++ src/modules/graphics/metal/Graphics.mm | 53 ++++++++++++++++---------- src/modules/graphics/metal/Texture.mm | 8 ++-- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/modules/graphics/metal/Graphics.h b/src/modules/graphics/metal/Graphics.h index 22a2f589a..a6f77639a 100644 --- a/src/modules/graphics/metal/Graphics.h +++ b/src/modules/graphics/metal/Graphics.h @@ -23,6 +23,8 @@ #include "graphics/Graphics.h" #include "Metal.h" +#include + @class CAMetalLayer; @protocol CAMetalDrawable; @@ -187,6 +189,8 @@ private: uint32 dirtyRenderState; bool windowHasStencil; + std::map cachedSamplers; + }; // Graphics } // metal diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index a107a7fbb..dfd0e20fc 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -198,6 +198,9 @@ Graphics::~Graphics() passDesc = nil; commandQueue = nil; device = nil; + + for (auto &kvp : cachedSamplers) + CFBridgingRelease(kvp.second); }} love::graphics::StreamBuffer *Graphics::newStreamBuffer(BufferType type, size_t size) @@ -393,32 +396,37 @@ void Graphics::submitBlitEncoder() id Graphics::getCachedSampler(const SamplerState &s) { @autoreleasepool { - id sampler = nil; + uint64 key = s.toKey(); - { - MTLSamplerDescriptor *desc = [MTLSamplerDescriptor new]; + auto it = cachedSamplers.find(key); + if (it != cachedSamplers.end()) + return (__bridge id) it->second; - desc.minFilter = getMTLSamplerFilter(s.minFilter); - desc.magFilter = getMTLSamplerFilter(s.magFilter); - desc.mipFilter = getMTLSamplerMipFilter(s.mipmapFilter); - desc.maxAnisotropy = std::max(1.0f, std::min((float)s.maxAnisotropy, 16.0f)); + MTLSamplerDescriptor *desc = [MTLSamplerDescriptor new]; - desc.sAddressMode = getMTLSamplerAddressMode(s.wrapU); - desc.tAddressMode = getMTLSamplerAddressMode(s.wrapV); - desc.rAddressMode = getMTLSamplerAddressMode(s.wrapW); + desc.minFilter = getMTLSamplerFilter(s.minFilter); + desc.magFilter = getMTLSamplerFilter(s.magFilter); + desc.mipFilter = getMTLSamplerMipFilter(s.mipmapFilter); + desc.maxAnisotropy = std::max(1.0f, std::min((float)s.maxAnisotropy, 16.0f)); + + desc.sAddressMode = getMTLSamplerAddressMode(s.wrapU); + desc.tAddressMode = getMTLSamplerAddressMode(s.wrapV); + desc.rAddressMode = getMTLSamplerAddressMode(s.wrapW); #ifdef LOVE_MACOS - desc.borderColor = MTLSamplerBorderColorOpaqueWhite; + desc.borderColor = MTLSamplerBorderColorOpaqueWhite; #endif - desc.lodMinClamp = s.minLod; - desc.lodMaxClamp = s.maxLod; + desc.lodMinClamp = s.minLod; + desc.lodMaxClamp = s.maxLod; - if (s.depthSampleMode.hasValue) - desc.compareFunction = getMTLCompareFunction(s.depthSampleMode.value); + if (s.depthSampleMode.hasValue) + desc.compareFunction = getMTLCompareFunction(s.depthSampleMode.value); - sampler = [device newSamplerStateWithDescriptor:desc]; - } + id sampler = [device newSamplerStateWithDescriptor:desc]; + + if (sampler != nil) + cachedSamplers[key] = (void *) CFBridgingRetain(sampler); return sampler; }} @@ -776,8 +784,8 @@ void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth // TODO: handle clearing mid-pass if (c.hasValue) { - MTLClearColor color = MTLClearColorMake(c.value.r, c.value.g, c.value.b, c.value.a); - for (int i = 0; i < 8; i++) + auto color = MTLClearColorMake(c.value.r, c.value.g, c.value.b, c.value.a); + for (int i = 0; i < MAX_COLOR_RENDER_TARGETS; i++) { passDesc.colorAttachments[0].clearColor = color; passDesc.colorAttachments[0].loadAction = MTLLoadActionClear; @@ -1050,7 +1058,12 @@ void Graphics::setPointSize(float size) void Graphics::setWireframe(bool enable) { - // TODO + if (enable != states.back().wireframe) + { + flushBatchedDraws(); + states.back().wireframe = enable; + dirtyRenderState |= STATEBIT_WIREFRAME; + } } PixelFormat Graphics::getSizedFormat(PixelFormat format, bool /*rendertarget*/, bool /*readable*/, bool /*sRGB*/) const diff --git a/src/modules/graphics/metal/Texture.mm b/src/modules/graphics/metal/Texture.mm index b4c352a01..7fff37932 100644 --- a/src/modules/graphics/metal/Texture.mm +++ b/src/modules/graphics/metal/Texture.mm @@ -127,6 +127,8 @@ Texture::Texture(id device, const Settings &settings, const Slices *d // so generateMipmaps here is fine - when they aren't already initialized. if (getMipmapCount() > 1 && (data == nullptr || data->getMipmapCount() <= 1)) generateMipmaps(); + + setSamplerState(samplerState); }} Texture::~Texture() @@ -206,9 +208,9 @@ love::image::ImageData *Texture::newImageData(love::image::Image *module, int sl } void Texture::setSamplerState(const SamplerState &s) -{ - // TODO -} +{ @autoreleasepool { + sampler = Graphics::getInstance()->getCachedSampler(s); +}} } // metal } // graphics