diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp
index 9179d52cc..569d8df26 100644
--- a/src/graphics/Renderer.cpp
+++ b/src/graphics/Renderer.cpp
@@ -173,6 +173,7 @@ void Renderer::render_parts()
 {
 	auto &sd = SimulationData::CRef();
 	auto &elements = sd.elements;
+	auto &graphicscache = sd.graphicscache;
 	int deca, decr, decg, decb, cola, colr, colg, colb, firea, firer, fireg, fireb, pixel_mode, q, i, t, nx, ny, x, y;
 	int orbd[4] = {0, 0, 0, 0}, orbl[4] = {0, 0, 0, 0};
 	Particle * parts;
@@ -244,18 +245,21 @@ void Renderer::render_parts()
 				else if(!(colour_mode & COLOUR_BASC))
 				{
 					auto *graphics = useGraphicsFunction ? elements[t].Graphics : nullptr;
-					if (!graphics || graphics(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb)) //That's a lot of args, a struct might be better
+					auto makeReady = !graphics || graphics(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb); //That's a lot of args, a struct might be better
+					if (makeReady && useGraphicsFunction)
 					{
-						graphicscache[t].isready = 1;
-						graphicscache[t].pixel_mode = pixel_mode;
-						graphicscache[t].cola = cola;
-						graphicscache[t].colr = colr;
-						graphicscache[t].colg = colg;
-						graphicscache[t].colb = colb;
-						graphicscache[t].firea = firea;
-						graphicscache[t].firer = firer;
-						graphicscache[t].fireg = fireg;
-						graphicscache[t].fireb = fireb;
+						// I sure hope we locked sd.elementGraphicsMx exclusively
+						auto &wgraphicscache = SimulationData::Ref().graphicscache;
+						wgraphicscache[t].isready = 1;
+						wgraphicscache[t].pixel_mode = pixel_mode;
+						wgraphicscache[t].cola = cola;
+						wgraphicscache[t].colr = colr;
+						wgraphicscache[t].colg = colg;
+						wgraphicscache[t].colb = colb;
+						wgraphicscache[t].firea = firea;
+						wgraphicscache[t].firer = firer;
+						wgraphicscache[t].fireg = fireg;
+						wgraphicscache[t].fireb = fireb;
 					}
 				}
 				if((elements[t].Properties & PROP_HOT_GLOW) && sim->parts[i].temp>(elements[t].HighTemperature-800.0f))
diff --git a/src/graphics/Renderer.h b/src/graphics/Renderer.h
index d1f2b0909..98efee53a 100644
--- a/src/graphics/Renderer.h
+++ b/src/graphics/Renderer.h
@@ -1,5 +1,6 @@
 #pragma once
 #include "Graphics.h"
+#include "gui/game/RenderPreset.h"
 #include "gui/interface/Point.h"
 #include "common/tpt-rand.h"
 #include "SimulationConfig.h"
@@ -13,28 +14,6 @@
 class RenderPreset;
 class Simulation;
 
-struct gcache_item
-{
-	int isready;
-	int pixel_mode;
-	int cola, colr, colg, colb;
-	int firea, firer, fireg, fireb;
-	gcache_item() :
-	isready(0),
-	pixel_mode(0),
-	cola(0),
-	colr(0),
-	colg(0),
-	colb(0),
-	firea(0),
-	firer(0),
-	fireg(0),
-	fireb(0)
-	{
-	}
-};
-typedef struct gcache_item gcache_item;
-
 int HeatToColour(float temp);
 
 class Renderer: public RasterDrawMethods<Renderer>
@@ -65,7 +44,6 @@ public:
 	RNG rng;
 
 	Simulation * sim;
-	gcache_item *graphicscache;
 
 	std::vector<unsigned int> render_modes;
 	unsigned int render_mode;
@@ -148,7 +126,6 @@ public:
 	static std::unique_ptr<VideoBuffer> WallIcon(int wallID, Vec2<int> size);
 
 	Renderer(Simulation * sim);
-	~Renderer();
 
 #define RENDERER_TABLE(name) \
 	static std::vector<RGB<uint8_t>> name; \
diff --git a/src/graphics/RendererBasic.cpp b/src/graphics/RendererBasic.cpp
index 1d4efbf08..43f892732 100644
--- a/src/graphics/RendererBasic.cpp
+++ b/src/graphics/RendererBasic.cpp
@@ -323,10 +323,6 @@ Renderer::Renderer(Simulation * sim):
 		COLOUR_LIFE
 	});
 
-	//Prepare the graphics cache
-	graphicscache = new gcache_item[PT_NUM];
-	std::fill(&graphicscache[0], &graphicscache[0] + PT_NUM, gcache_item());
-
 	prepare_alpha(CELL, 1.0f);
 }
 
@@ -466,9 +462,4 @@ VideoBuffer Renderer::DumpFrame()
 	return newBuffer;
 }
 
-Renderer::~Renderer()
-{
-	delete[] graphicscache;
-}
-
 template struct RasterDrawMethods<Renderer>;
diff --git a/src/graphics/gcache_item.h b/src/graphics/gcache_item.h
new file mode 100644
index 000000000..b824ae359
--- /dev/null
+++ b/src/graphics/gcache_item.h
@@ -0,0 +1,15 @@
+#pragma once
+
+struct gcache_item
+{
+	int isready = 0;
+	int pixel_mode = 0;
+	int cola = 0;
+	int colr = 0;
+	int colg = 0;
+	int colb = 0;
+	int firea = 0;
+	int firer = 0;
+	int fireg = 0;
+	int fireb = 0;
+};
diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp
index 19d9c2781..9599efc92 100644
--- a/src/gui/game/GameView.cpp
+++ b/src/gui/game/GameView.cpp
@@ -2108,6 +2108,9 @@ void GameView::OnDraw()
 	Graphics * g = GetGraphics();
 	if (ren)
 	{
+		// we're the main thread, we may write graphicscache
+		auto &sd = SimulationData::Ref();
+		std::unique_lock lk(sd.elementGraphicsMx);
 		ren->clearScreen();
 		ren->RenderBegin();
 		ren->SetSample(c->PointTranslate(currentMouse));
diff --git a/src/gui/render/RenderView.cpp b/src/gui/render/RenderView.cpp
index d64286407..2fbb19e3f 100644
--- a/src/gui/render/RenderView.cpp
+++ b/src/gui/render/RenderView.cpp
@@ -1,6 +1,7 @@
 #include "RenderView.h"
 
 #include "simulation/ElementGraphics.h"
+#include "simulation/SimulationData.h"
 
 #include "graphics/Graphics.h"
 #include "graphics/Renderer.h"
@@ -158,6 +159,9 @@ void RenderView::OnDraw()
 	g->DrawFilledRect(WINDOW.OriginRect(), 0x000000_rgb);
 	if(ren)
 	{
+		// we're the main thread, we may write graphicscache
+		auto &sd = SimulationData::Ref();
+		std::unique_lock lk(sd.elementGraphicsMx);
 		ren->clearScreen();
 		ren->RenderBegin();
 		ren->RenderEnd();
diff --git a/src/lua/LegacyLuaAPI.cpp b/src/lua/LegacyLuaAPI.cpp
index 06ade0ef2..6eae5d11a 100644
--- a/src/lua/LegacyLuaAPI.cpp
+++ b/src/lua/LegacyLuaAPI.cpp
@@ -263,7 +263,7 @@ int luacon_elementwrite(lua_State* l)
 	luacon_model->BuildMenus();
 	auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
 	luacon_ci->custom_init_can_move();
-	std::fill(&luacon_ren->graphicscache[0], &luacon_ren->graphicscache[0] + PT_NUM, gcache_item());
+	sd.graphicscache = std::array<gcache_item, PT_NUM>();
 
 	return 0;
 }
diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp
index d5625b6b7..b3e24c9bf 100644
--- a/src/lua/LuaScriptInterface.cpp
+++ b/src/lua/LuaScriptInterface.cpp
@@ -3286,6 +3286,7 @@ void LuaScriptInterface::LuaSetParticleProperty(lua_State* l, int particleID, St
 
 int LuaScriptInterface::elements_loadDefault(lua_State * l)
 {
+	auto &sd = SimulationData::Ref();
 	auto &builtinElements = GetElements();
 	auto *luacon_ci = static_cast<LuaScriptInterface *>(commandInterface);
 	{
@@ -3304,7 +3305,6 @@ int LuaScriptInterface::elements_loadDefault(lua_State * l)
 			lua_settable(l, -3);
 
 			{
-				auto &sd = SimulationData::Ref();
 				std::unique_lock lk(sd.elementGraphicsMx);
 				auto &elements = sd.elements;
 				if (id < (int)builtinElements.size())
@@ -3321,7 +3321,6 @@ int LuaScriptInterface::elements_loadDefault(lua_State * l)
 		else
 		{
 			{
-				auto &sd = SimulationData::Ref();
 				std::unique_lock lk(sd.elementGraphicsMx);
 				auto &elements = sd.elements;
 				for (int i = 0; i < PT_NUM; i++)
@@ -3355,8 +3354,7 @@ int LuaScriptInterface::elements_loadDefault(lua_State * l)
 		}
 	}
 	luacon_ci->custom_init_can_move();
-	std::fill(luacon_ren->graphicscache, luacon_ren->graphicscache+PT_NUM, gcache_item());
-	SaveRenderer::Ref().Flush(0, PT_NUM);
+	sd.graphicscache = std::array<gcache_item, PT_NUM>();
 	return 0;
 }
 
@@ -3639,8 +3637,8 @@ int LuaScriptInterface::elements_element(lua_State * l)
 
 	if (lua_gettop(l) > 1)
 	{
+		auto &sd = SimulationData::Ref();
 		{
-			auto &sd = SimulationData::Ref();
 			std::unique_lock lk(sd.elementGraphicsMx);
 			auto &elements = sd.elements;
 			luaL_checktype(l, 2, LUA_TTABLE);
@@ -3744,8 +3742,7 @@ int LuaScriptInterface::elements_element(lua_State * l)
 
 		luacon_model->BuildMenus();
 		luacon_ci->custom_init_can_move();
-		luacon_ren->graphicscache[id].isready = 0;
-		SaveRenderer::Ref().Flush(id, id + 1);
+		sd.graphicscache[id].isready = 0;
 
 		return 0;
 	}
@@ -3846,6 +3843,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
 	{
 		if (prop != properties.end())
 		{
+			auto &sd = SimulationData::Ref();
 			if (lua_type(l, 3) != LUA_TNIL)
 			{
 				if (prop->Type == StructProperty::TransitionType)
@@ -3857,7 +3855,6 @@ int LuaScriptInterface::elements_property(lua_State * l)
 					}
 				}
 				{
-					auto &sd = SimulationData::Ref();
 					std::unique_lock lk(sd.elementGraphicsMx);
 					auto &elements = sd.elements;
 					intptr_t propertyAddress = (intptr_t)(((unsigned char*)&elements[id]) + prop->Offset);
@@ -3867,8 +3864,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
 
 			luacon_model->BuildMenus();
 			luacon_ci->custom_init_can_move();
-			luacon_ren->graphicscache[id].isready = 0;
-			SaveRenderer::Ref().Flush(id, id + 1);
+			sd.graphicscache[id].isready = 0;
 		}
 		else if (propertyName == "Update")
 		{
@@ -3914,8 +3910,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
 				lua_gr_func[id].Clear();
 				elements[id].Graphics = builtinElements[id].Graphics;
 			}
-			luacon_ren->graphicscache[id].isready = 0;
-			SaveRenderer::Ref().Flush(id, id + 1);
+			sd.graphicscache[id].isready = 0;
 		}
 		else if (propertyName == "Create")
 		{
diff --git a/src/simulation/SaveRenderer.cpp b/src/simulation/SaveRenderer.cpp
index 63dea381d..65c6f73ee 100644
--- a/src/simulation/SaveRenderer.cpp
+++ b/src/simulation/SaveRenderer.cpp
@@ -15,12 +15,6 @@ SaveRenderer::SaveRenderer(){
 	ren->blackDecorations = true;
 }
 
-void SaveRenderer::Flush(int begin, int end)
-{
-	std::lock_guard<std::mutex> gx(renderMutex);
-	std::fill(ren->graphicscache + begin, ren->graphicscache + end, gcache_item());
-}
-
 std::pair<std::unique_ptr<VideoBuffer>, MissingElements> SaveRenderer::Render(const GameSave *save, bool decorations, bool fire, Renderer *renderModeSource)
 {
 	// this function usually runs on a thread different from where element info in SimulationData may be written, so we acquire a read-only lock on it
diff --git a/src/simulation/SaveRenderer.h b/src/simulation/SaveRenderer.h
index d2a245339..65a8ac4ab 100644
--- a/src/simulation/SaveRenderer.h
+++ b/src/simulation/SaveRenderer.h
@@ -20,6 +20,5 @@ class SaveRenderer: public ExplicitSingleton<SaveRenderer> {
 public:
 	SaveRenderer();
 	std::pair<std::unique_ptr<VideoBuffer>, MissingElements> Render(const GameSave *save, bool decorations = true, bool fire = true, Renderer *renderModeSource = nullptr);
-	void Flush(int begin, int end);
 	virtual ~SaveRenderer();
 };
diff --git a/src/simulation/SimulationData.h b/src/simulation/SimulationData.h
index 6f7ae5421..0f8bebda3 100644
--- a/src/simulation/SimulationData.h
+++ b/src/simulation/SimulationData.h
@@ -9,6 +9,7 @@
 #include "Element.h"
 #include "Particle.h"
 #include "WallType.h"
+#include "graphics/gcache_item.h"
 #include <cstdint>
 #include <vector>
 #include <array>
@@ -173,6 +174,7 @@ class SimulationData : public ExplicitSingleton<SimulationData>
 {
 public:
 	std::array<Element, PT_NUM> elements;
+	std::array<gcache_item, PT_NUM> graphicscache;
 	std::vector<SimTool> tools;
 	std::vector<wall_type> wtypes;
 	std::vector<menu_section> msections;
diff --git a/src/simulation/elements/PIPE.cpp b/src/simulation/elements/PIPE.cpp
index 717d7b459..51df18f27 100644
--- a/src/simulation/elements/PIPE.cpp
+++ b/src/simulation/elements/PIPE.cpp
@@ -348,22 +348,23 @@ int Element_PIPE_graphics(GRAPHICS_FUNC_ARGS)
 {
 	auto &sd = SimulationData::CRef();
 	auto &elements = sd.elements;
+	auto &graphicscache = sd.graphicscache;
 	int t = TYP(cpart->ctype);
 	if (t>0 && t<PT_NUM && elements[t].Enabled)
 	{
 		if (t == PT_STKM || t == PT_STKM2 || t == PT_FIGH)
 			return 0;
-		if (ren->graphicscache[t].isready)
+		if (graphicscache[t].isready)
 		{
-			*pixel_mode = ren->graphicscache[t].pixel_mode;
-			*cola = ren->graphicscache[t].cola;
-			*colr = ren->graphicscache[t].colr;
-			*colg = ren->graphicscache[t].colg;
-			*colb = ren->graphicscache[t].colb;
-			*firea = ren->graphicscache[t].firea;
-			*firer = ren->graphicscache[t].firer;
-			*fireg = ren->graphicscache[t].fireg;
-			*fireb = ren->graphicscache[t].fireb;
+			*pixel_mode = graphicscache[t].pixel_mode;
+			*cola = graphicscache[t].cola;
+			*colr = graphicscache[t].colr;
+			*colg = graphicscache[t].colg;
+			*colb = graphicscache[t].colb;
+			*firea = graphicscache[t].firea;
+			*firer = graphicscache[t].firer;
+			*fireg = graphicscache[t].fireg;
+			*fireb = graphicscache[t].fireb;
 		}
 		else
 		{