Browse Source

Clean up unused temporary Canvases after a few frames.

--HG--
branch : minor
Alex Szpakowski 7 years ago
parent
commit
b8c4b07edf

+ 4 - 2
src/modules/graphics/Graphics.cpp

@@ -728,12 +728,14 @@ Canvas *Graphics::getTemporaryCanvas(PixelFormat format, int w, int h, int sampl
 {
 {
 	love::graphics::Canvas *canvas = nullptr;
 	love::graphics::Canvas *canvas = nullptr;
 
 
-	for (Canvas *c : temporaryCanvases)
+	for (TemporaryCanvas &temp : temporaryCanvases)
 	{
 	{
+		Canvas *c = temp.canvas;
 		if (c->getPixelFormat() == format && c->getPixelWidth() == w
 		if (c->getPixelFormat() == format && c->getPixelWidth() == w
 			&& c->getPixelHeight() == h && c->getRequestedMSAA() == samples)
 			&& c->getPixelHeight() == h && c->getRequestedMSAA() == samples)
 		{
 		{
 			canvas = c;
 			canvas = c;
+			temp.framesSinceUse = 0;
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -748,7 +750,7 @@ Canvas *Graphics::getTemporaryCanvas(PixelFormat format, int w, int h, int sampl
 
 
 		canvas = newCanvas(settings);
 		canvas = newCanvas(settings);
 
 
-		temporaryCanvases.push_back(canvas);
+		temporaryCanvases.emplace_back(canvas);
 	}
 	}
 
 
 	return canvas;
 	return canvas;

+ 13 - 1
src/modules/graphics/Graphics.h

@@ -880,6 +880,17 @@ protected:
 		}
 		}
 	};
 	};
 
 
+	struct TemporaryCanvas
+	{
+		Canvas *canvas;
+		int framesSinceUse;
+
+		TemporaryCanvas(Canvas *c)
+			: canvas(c)
+			, framesSinceUse(0)
+		{}
+	};
+
 	virtual ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) = 0;
 	virtual ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) = 0;
 	virtual Shader *newShaderInternal(ShaderStage *vertex, ShaderStage *pixel) = 0;
 	virtual Shader *newShaderInternal(ShaderStage *vertex, ShaderStage *pixel) = 0;
 	virtual StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0;
 	virtual StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0;
@@ -922,7 +933,7 @@ protected:
 	std::vector<DisplayState> states;
 	std::vector<DisplayState> states;
 	std::vector<StackType> stackTypeStack;
 	std::vector<StackType> stackTypeStack;
 
 
-	std::vector<Canvas *> temporaryCanvases;
+	std::vector<TemporaryCanvas> temporaryCanvases;
 
 
 	int canvasSwitchCount;
 	int canvasSwitchCount;
 	int drawCallsBatched;
 	int drawCallsBatched;
@@ -932,6 +943,7 @@ protected:
 	Deprecations deprecations;
 	Deprecations deprecations;
 
 
 	static const size_t MAX_USER_STACK_DEPTH = 64;
 	static const size_t MAX_USER_STACK_DEPTH = 64;
+	static const int MAX_TEMPORARY_CANVAS_UNUSED_FRAMES = 16;
 
 
 private:
 private:
 
 

+ 15 - 2
src/modules/graphics/opengl/Graphics.cpp

@@ -287,8 +287,8 @@ void Graphics::unSetMode()
 	for (const auto &pair : framebufferObjects)
 	for (const auto &pair : framebufferObjects)
 		gl.deleteFramebuffer(pair.second);
 		gl.deleteFramebuffer(pair.second);
 
 
-	for (auto c : temporaryCanvases)
-		c->release();
+	for (auto temp : temporaryCanvases)
+		temp.canvas->release();
 
 
 	framebufferObjects.clear();
 	framebufferObjects.clear();
 	temporaryCanvases.clear();
 	temporaryCanvases.clear();
@@ -924,6 +924,19 @@ void Graphics::present(void *screenshotCallbackData)
 	gl.stats.shaderSwitches = 0;
 	gl.stats.shaderSwitches = 0;
 	canvasSwitchCount = 0;
 	canvasSwitchCount = 0;
 	drawCallsBatched = 0;
 	drawCallsBatched = 0;
+
+	// This assumes temporary canvases will only be used within a render pass.
+	for (int i = (int) temporaryCanvases.size() - 1; i >= 0; i--)
+	{
+		if (temporaryCanvases[i].framesSinceUse >= MAX_TEMPORARY_CANVAS_UNUSED_FRAMES)
+		{
+			temporaryCanvases[i].canvas->release();
+			temporaryCanvases[i] = temporaryCanvases.back();
+			temporaryCanvases.pop_back();
+		}
+		else
+			temporaryCanvases[i].framesSinceUse++;
+	}
 }
 }
 
 
 void Graphics::setScissor(const Rect &rect)
 void Graphics::setScissor(const Rect &rect)