Browse Source

metal: initial sampler cache implementation

Alex Szpakowski 5 years ago
parent
commit
ceb1e4459b

+ 4 - 0
src/modules/graphics/metal/Graphics.h

@@ -23,6 +23,8 @@
 #include "graphics/Graphics.h"
 #include "Metal.h"
 
+#include <map>
+
 @class CAMetalLayer;
 @protocol CAMetalDrawable;
 
@@ -187,6 +189,8 @@ private:
 	uint32 dirtyRenderState;
 	bool windowHasStencil;
 
+	std::map<uint64, void *> cachedSamplers;
+
 }; // Graphics
 
 } // metal

+ 33 - 20
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<MTLSamplerState> Graphics::getCachedSampler(const SamplerState &s)
 { @autoreleasepool {
-	id<MTLSamplerState> sampler = nil;
+	uint64 key = s.toKey();
 
-	{
-		MTLSamplerDescriptor *desc = [MTLSamplerDescriptor new];
+	auto it = cachedSamplers.find(key);
+	if (it != cachedSamplers.end())
+		return (__bridge id<MTLSamplerState>) it->second;
+
+	MTLSamplerDescriptor *desc = [MTLSamplerDescriptor new];
 
-		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.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);
+	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<MTLSamplerState> 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

+ 5 - 3
src/modules/graphics/metal/Texture.mm

@@ -127,6 +127,8 @@ Texture::Texture(id<MTLDevice> 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