Exemplo n.º 1
0
	void BFCLinkTracker::reset()
	{
		SCOPE_profile_cpu_function("BFC");
		{
			SCOPE_profile_cpu_i("BFC", "ResetLinks");
			for (auto &e : _links)
			{
				// beurk
				if (e != nullptr)
				{
					e->resetBFCTrackerIndex();
					for (auto &cullable : e->_cullables)
					{
						auto &item = e->_bfcBlockFactory->getItem(cullable.getItemId());
						item.setPosition(cullable.getPtr()->setBFCTransform(e->_globalTransformation));
					}
					e = nullptr;
				}
			}
			_links.clear();
		}
		{
			SCOPE_profile_cpu_i("BFC", "ResetFree");
			//beurk
			while (!_free.empty())
				_free.pop();
		}
	}
Exemplo n.º 2
0
	bool RenderThread::update()
	{
		/*
		- Tant qu'il n'y a pas de command
		-> je pop des task
		- Une fois que j'ai mes commandes
		-> pour chacunes d'elles
		-> je regarde si c'est a moi de les traiter (ex : changement de scene)
		-> si ca n'est pas a moi de les traiter
		-> je les passe au render context actif
		-> si il n'y a pas de render context actif, c'est que j'ai fait une erreur, et j'assert dans ta face :D
		*/

		_registerId();

		_run = true;
		_insideRun = true;
		DWORD threadId = GetThreadId(static_cast<HANDLE>(_threadHandle.native_handle()));
		SetThreadName(threadId, this->_name.c_str());

		TMQ::MessageBase *task = nullptr;

		while (_run && _insideRun)
		{
			SCOPE_profile_cpu_i("RenderTimer", "Update");

			if (TMQ::TaskManager::RenderThreadGetTask(task))
			{
				SCOPE_profile_cpu_i("RenderTimer", "Execute task");
				auto success = execute(task); // we receive a task that we cannot treat
				AGE_ASSERT(success);
			}
		}
		return true;
	}
Exemplo n.º 3
0
	bool MainThread::update()
	{
		SCOPE_profile_cpu_function("Main thread");
		std::chrono::system_clock::time_point waitStart;
		std::chrono::system_clock::time_point waitEnd;
		std::chrono::system_clock::time_point workStart;
		std::chrono::system_clock::time_point workEnd;
		std::size_t workCount = 0;
		std::size_t waitCount = 0;

		workStart = std::chrono::high_resolution_clock::now();

		if (_frameCounter - GetRenderThread()->getCurrentFrameCount() > 2)
		{
			_isRenderFrame = false;
		}
		else
		{
			_isRenderFrame = true;
		}

		if (!_engine->update())
		{
			return false;
		}

		{
			SCOPE_profile_cpu_i("MainThread", "Execute tasks");
			{
				TMQ::MessageBase *task = nullptr;
				while (TMQ::TaskManager::MainThreadGetTask(task))
				{
					SCOPE_profile_cpu_i("MainThread", "Execute task");
					auto result = execute(task);
					assert(result); // we receive a task that we cannot handle
				}
			}
		}

		workEnd = std::chrono::high_resolution_clock::now();
		workCount = std::chrono::duration_cast<std::chrono::microseconds>(workEnd - workStart).count();
		workCount -= waitCount;

		if (_isRenderFrame)
		{
			++_frameCounter;
		}

		return true;
	}
Exemplo n.º 4
0
	bool MainThread::tryToStealTasks()
	{
		SCOPE_profile_cpu_i("MainThread", "Steal tasks");
		{
			TMQ::MessageBase *task = nullptr;
			if (TMQ::TaskManager::MainThreadGetTask(task))
			{
				SCOPE_profile_cpu_i("MainThread", "Execute task");
				auto result = execute(task);
				assert(result); // we receive a task that we cannot handle
				return true;
			}
		}
		return false;
	}
Exemplo n.º 5
0
	void DepthOfField::renderPass(const DRBCameraDrawableList &infos)
	{
		if (infos.cameraInfos.data.dof)
		{
			SCOPE_profile_gpu_i("Depth of field");
			SCOPE_profile_cpu_i("RenderTimer", "Depth of field");

			_depth->bind();
			_depth->generateMipmaps();

			OpenGLState::glDepthMask(GL_FALSE);
			OpenGLState::glDisable(GL_DEPTH_TEST);
			OpenGLState::glDisable(GL_STENCIL_TEST);
			OpenGLState::glDisable(GL_CULL_FACE);

			_programs[PROGRAM_DEPTH_OF_FIELD]->use();
			_programs[PROGRAM_DEPTH_OF_FIELD]->get_resource<Sampler2D>(StringID("cleanMap", 0x90c5a5421e083038)).set(_clean);
			_programs[PROGRAM_DEPTH_OF_FIELD]->get_resource<Sampler2D>(StringID("depthMap", 0xeb35b90435165cd4)).set(_depth);
			_programs[PROGRAM_DEPTH_OF_FIELD]->get_resource<Sampler2D>(StringID("blurredMap1", 0x031e7d3c1b84e96a)).set(_blurred1);
			_programs[PROGRAM_DEPTH_OF_FIELD]->get_resource<Sampler2D>(StringID("blurredMap2", 0x031e7c3c1b84e7b7)).set(_blurred2);

			_quadPainter->uniqueDrawBegin(_programs[PROGRAM_DEPTH_OF_FIELD]);
			_quadPainter->uniqueDraw(GL_TRIANGLES, _programs[PROGRAM_DEPTH_OF_FIELD], _quadVertices);
			_quadPainter->uniqueDrawEnd();
		}
	}
Exemplo n.º 6
0
void SdlContext::swapContext()
{
    MicroProfileFlip();
    {
        SCOPE_profile_cpu_i("RenderTimer", "swapContext");
        SCOPE_profile_gpu_i("SwapContext");
        SDL_GL_SwapWindow(_window);
    }
}
	IRenderingPipeline & ARenderingPipeline::render(const DRBCameraDrawableList &infos)
	{
		SCOPE_profile_cpu_i("RenderTimer", "RenderPipeline");
		renderBegin(infos);
		// We iterate over the entry points5
		for (auto &renderPass : _rendering_list)
		{
			renderPass->render(infos);
		}
		renderEnd(infos);
		return (*this);
	}
Exemplo n.º 8
0
	bool RenderThread::init()
	{
		registerCallback<Tasks::Render::CreateRenderContext>([this](Tasks::Render::CreateRenderContext &msg)
		{
			_context = msg.engine->setInstance<SdlContext, IRenderContext>();

			auto configurationManager = msg.engine->getInstance<ConfigurationManager>();

			auto w = configurationManager->getConfiguration<int>("windowW")->getValue();
			auto h = configurationManager->getConfiguration<int>("windowH")->getValue();
			auto f = configurationManager->getConfiguration<bool>("fullScreen")->getValue();
			if (!_context->init(w, h, f, "~AGE~ V0.00001 Demo"))
			{
				msg.setValue(false);
				return;
			}

			if (_depthMapManager == nullptr)
			{
				_depthMapManager = new DepthMapManager;
			}

#ifdef DEBUG
			_depthMapManager->init(1280, 720, 4);
#else
			_depthMapManager->init(1280, 720, 2);
#endif

			msg.setValue(true);
		});

		registerCallback<Tasks::Render::InitRenderPipelines>([this](Tasks::Render::InitRenderPipelines &msg)
		{
			_context = msg.engine->setInstance<SdlContext, IRenderContext>();
			pipelines.resize(RenderType::TOTAL);
			pipelines[DEFERRED] = std::make_unique<DeferredShading>(_context->getScreenSize(), paintingManager);
			pipelines[DEBUG_DEFERRED] = std::make_unique<DebugDeferredShading>(_context->getScreenSize(), paintingManager);
			_recompileShaders();
			_initPipelines();
			_bonesTexture = createRenderPassOutput<TextureBuffer>(8184 * 2, GL_RGBA32F, sizeof(glm::mat4), GL_DYNAMIC_DRAW);
			msg.setValue(true);
		});

		registerCallback<Commands::ToRender::Flush>([&](Commands::ToRender::Flush& msg)
		{
			SCOPE_profile_cpu_i("RenderTimer", "Render frame");
			if (msg.isRenderFrame)
			{
#ifdef AGE_ENABLE_IMGUI
				std::shared_ptr<AGE::RenderImgui> imguiRenderList = nullptr;
				{
					std::lock_guard<AGE::SpinLock> lock(_mutex);

					imguiRenderList = _imguiRenderlist;
				}
				if (imguiRenderList != nullptr)
				{
					AGE::Imgui::getInstance()->renderThreadRenderFn(imguiRenderList->cmd_lists);
				}
				static bool first = true;
				if (first || imguiRenderList)
				{
					TMQ::TaskManager::emplaceMainTask<ImGuiEndOfFrame>();
					first = false;
				}
#endif
				_context->swapContext();
				{
					SCOPE_profile_gpu_i("Clear buffer");
					SCOPE_profile_cpu_i("RenderTimer", "Clear buffer");
					glClear(GL_COLOR_BUFFER_BIT);
				}
				++_frameCounter;

				if (_context)
				{
					_context->refreshInputs();
				}
			}
		});

		registerCallback<Tasks::Render::ReloadShaders>([&](Tasks::Render::ReloadShaders& msg)
		{
#ifdef AGE_DEBUG
			_recompileShaders();
#else
			std::cerr << "Error : You cannot recompile shader at runtime. This feature is enabled only in debug mode\n";
#endif
		});

 		registerSharedCallback<AGE::Tasks::Basic::BoolFunction>([&](AGE::Tasks::Basic::BoolFunction& msg)
		{
			SCOPE_profile_cpu_i("RenderTimer", "Bool function");
			msg.setValue(msg.function());
		});

		registerCallback<AGE::Tasks::Basic::VoidFunction>([&](AGE::Tasks::Basic::VoidFunction& msg)
		{
			SCOPE_profile_cpu_i("RenderTimer", "Void function");
			if (msg.function)
				msg.function();
		});

		registerCallback<AGE::Tasks::Basic::Exit>([&](AGE::Tasks::Basic::Exit& msg)
		{
			AGE::GetEngine()->deleteInstance<IRenderContext>();
			this->_insideRun = false;
			TMQ::TaskManager::emplaceSharedTask<Tasks::Basic::Exit>();
		});

		registerCallback<AGE::Tasks::Render::ContextGrabMouse>([&](AGE::Tasks::Render::ContextGrabMouse &msg)
		{
			_context->grabMouse(msg.grabMouse == 1 ? true : false);
		});

		registerCallback<AGE::DRBCameraDrawableListCommand>([&](AGE::DRBCameraDrawableListCommand &msg)
		{
			std::shared_ptr<Painter> line2DPainter = nullptr;
			std::shared_ptr<Painter> line3DPainter = nullptr;
			std::shared_ptr<Painter> line3DPainterDepth = nullptr;

			//if (pipelines[msg.list->cameraInfos.data.pipeline]->isDebug())
			//{
			DebugDrawManager* debugDrawManager = nullptr;
			if (GetEngine()->hasInstance<DebugDrawManager>())
			{
				debugDrawManager = GetEngine()->getInstance<DebugDrawManager>();
			}
			if (debugDrawManager)
			{
				debugDrawManager->renderBegin(paintingManager);
			}
			pipelines[msg.list->cameraInfos.data.pipeline]->render(*msg.list.get());
			if (debugDrawManager)
			{
				debugDrawManager->renderEnd();
			}
		});

		registerCallback<AGE::Tasks::UploadBonesToGPU>([&](AGE::Tasks::UploadBonesToGPU& msg)
		{
			SCOPE_profile_cpu_i("!!!HACK!!!", "Upload bones matrix to GPU");
			_bonesTexture->set(msg.bones->data(), msg.bones->size());
		});

		return true;
	}
Exemplo n.º 9
0
	void RenderCameraSystem::mainUpdate(float time)
	{
		SCOPE_profile_cpu_function("Camera system");
		_scene->getBfcLinkTracker()->reset();

		// check if the render thread does not already have stuff to draw
		if (GetMainThread()->isRenderFrame() == false)
		{
			return;
		}

		std::list<std::shared_ptr<DRBSpotLightDrawableList>> spotLightList;
		std::list<std::shared_ptr<DRBData>> pointLightList;


		for (auto &spotEntity : _spotLights.getCollection())
		{
			auto spot = spotEntity->getComponent<SpotLightComponent>();
			auto spotDrawableList = std::make_shared<DRBSpotLightDrawableList>();
			spotDrawableList->spotLight = spot->getCullableHandle().getPtr()->getDatas();

			auto spotData = std::static_pointer_cast<DRBSpotLightData>(spotDrawableList->spotLight);

			glm::mat4 spotViewProj = spot->updateShadowMatrix();

			Frustum spotlightFrustum;
			spotlightFrustum.setMatrix(spotViewProj);

			// Draw spotlight frustum debug:
			glm::vec4 worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, -1, -1, 1.0f);
			glm::vec3 aNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, 1, -1, 1.0f);
			glm::vec3 bNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, 1, -1, 1.0f);
			glm::vec3 cNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, -1, -1, 1.0f);
			glm::vec3 dNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, -1, 1, 1.0f);
			glm::vec3 aFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, 1, 1, 1.0f);
			glm::vec3 bFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, 1, 1, 1.0f);
			glm::vec3 cFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, -1, 1, 1.0f);
			glm::vec3 dFar = glm::vec3(worldPos / worldPos.w);

			glm::vec3 color = glm::vec3(1, 0, 0);
			bool activateDepth = true;

			if (_drawDebugLines)
			{
				AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DQuad>(aNear, bNear, cNear, dNear, color, activateDepth);
				AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DQuad>(aFar, bFar, cFar, dFar, color, activateDepth);
				AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(aNear, aFar, color, activateDepth);
				AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(bNear, bFar, color, activateDepth);
				AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(cNear, cFar, color, activateDepth);
				AGE::GetRenderThread()->getQueue()->emplaceTask<Commands::ToRender::Draw3DLine>(dNear, dFar, color, activateDepth);
			}

			std::atomic_size_t counter = 0;

			LFList<BFCItem> meshInLightList;
			std::size_t meshBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullableMesh);

			for (std::size_t i = 0; i < meshBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &spotlightFrustum, &counter, &meshInLightList](){
					bf->cullOnBlock(BFCCullableType::CullableMesh, meshInLightList, spotlightFrustum, i);
					counter.fetch_add(1);
				});
			}

			{
				SCOPE_profile_cpu_i("Camera system", "Cull for spots");
				while (counter < meshBlocksToCullNumber )
				{
				}
				//GetMainThread()->computeTasksWhile(std::function<bool()>([&counter, meshBlocksToCullNumber]() {
				//	return counter >= meshBlocksToCullNumber;
				//}));
			}

			while (meshInLightList.getSize() > 0)
			{
				spotDrawableList->meshs.push_back(meshInLightList.pop()->getDrawable()->getDatas());
			}

			spotLightList.push_back(spotDrawableList);
		}
		for (auto &pointLightEntity : _pointLights.getCollection())
		{
			auto point = pointLightEntity->getComponent<PointLightComponent>();
			
			pointLightList.push_back(point->getCullableHandle().getPtr()->getDatas());
		}

		for (auto &cameraEntity : _cameras.getCollection())
		{
			Frustum cameraFrustum;
			auto camera = cameraEntity->getComponent<CameraComponent>();

			std::atomic_size_t counter = 0;

			auto cameraList = std::make_shared<DRBCameraDrawableList>();
			cameraList->cameraInfos.data = camera->getData();
			cameraList->cameraInfos.view = glm::inverse(cameraEntity->getLink().getGlobalTransform());

			cameraFrustum.setMatrix(camera->getProjection() * cameraList->cameraInfos.view);

			LFList<BFCItem> meshList;
			LFList<BFCItem> pointLightListToCull;
			std::size_t meshBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullableMesh);
			std::size_t pointLightBlocksToCullNumber = _scene->getBfcBlockManagerFactory()->getBlockNumberToCull(BFCCullableType::CullablePointLight);
			std::size_t totalToCullNumber = meshBlocksToCullNumber + pointLightBlocksToCullNumber;
			
			for (std::size_t i = 0; i < meshBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &cameraFrustum, &counter, &meshList](){
					bf->cullOnBlock(BFCCullableType::CullableMesh, meshList, cameraFrustum, i);
					counter.fetch_add(1);
				});
			}

			for (std::size_t i = 0; i < pointLightBlocksToCullNumber; ++i)
			{
				BFCBlockManagerFactory *bf = _scene->getBfcBlockManagerFactory();
				EmplaceTask<Tasks::Basic::VoidFunction>([bf, i, &cameraFrustum, &counter, &pointLightListToCull](){
					bf->cullOnBlock(BFCCullableType::CullablePointLight, pointLightListToCull, cameraFrustum, i);
					counter.fetch_add(1);
				});
			}

			{
				SCOPE_profile_cpu_i("Camera system", "Cull for cam");
				while (counter < totalToCullNumber)
				{ }
				//GetMainThread()->computeTasksWhile(std::function<bool()>([&counter, totalToCullNumber]() {
				//	return counter >= totalToCullNumber;
				//}));
			}

			{
				SCOPE_profile_cpu_i("Camera system", "Copy LFList to std");
				while (meshList.getSize() > 0)
				{
					cameraList->meshs.push_back(meshList.pop()->getDrawable()->getDatas());
				}

				while (pointLightListToCull.getSize() > 0)
				{
					cameraList->pointLights.push_back(pointLightListToCull.pop()->getDrawable()->getDatas());
				}
			}
			if (OcclusionConfig::g_Occlusion_is_enabled)
			{
				occlusionCulling(cameraList->meshs, _drawDebugLines);
			}

			cameraList->spotLights = spotLightList;
			cameraList->pointLights = pointLightList;
			AGE::GetRenderThread()->getQueue()->emplaceTask<AGE::DRBCameraDrawableListCommand>(cameraList);
		}
	}
Exemplo n.º 10
0
	void DeferredShadowBuffering::renderPass(const DRBCameraDrawableList &infos)
	{
		//@PROUT
		SCOPE_profile_gpu_i("DeferredShadowBuffering render pass");
		SCOPE_profile_cpu_i("RenderTimer", "DeferredShadowBuffering render pass");

		OpenGLState::glEnable(GL_CULL_FACE);
		OpenGLState::glCullFace(GL_FRONT);
		OpenGLState::glDepthMask(GL_TRUE);
		OpenGLState::glDepthFunc(GL_LEQUAL);
		OpenGLState::glDisable(GL_BLEND);
		OpenGLState::glDisable(GL_STENCIL_TEST);
		OpenGLState::glEnable(GL_DEPTH_TEST);
		OpenGLState::glDepthMask(GL_TRUE);
		OpenGLState::glDepthFunc(GL_LESS);

		_programs[PROGRAM_BUFFERING]->use();

		// handle the number of sample
		if (_depthBuffers.size() < infos.spotLights.size())
		{
			std::size_t count = infos.spotLights.size() - _depthBuffers.size();
			for (int index = 0; index < count; ++index)
			{
				_depthBuffers.push_back(createRenderPassOutput<Texture2D>(_frame_buffer.width(), _frame_buffer.height(), GL_DEPTH24_STENCIL8, true));
				_depthBuffers.back()->bind();
				_depthBuffers.back()->parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
				_depthBuffers.back()->parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
				_depthBuffers.back()->parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
				_depthBuffers.back()->parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
				_depthBuffers.back()->parameter(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
			}
		}
		else if (_depthBuffers.size() > infos.spotLights.size())
		{
			std::size_t count = _depthBuffers.size() - infos.spotLights.size();
			for (int index = 0; index < count; ++index)
			{
				_depthBuffers.pop_back();
			}
		}
		// start to render to texture for each depth map
		auto it = _depthBuffers.begin();


		std::shared_ptr<Painter> painter = nullptr;
		std::shared_ptr<Painter> oldPainter = nullptr;

		for (auto &spotLightPtr : infos.spotLights)
		{
			SCOPE_profile_gpu_i("Spotlight pass");
			SCOPE_profile_cpu_i("RenderTimer", "Spotlight pass");

			DRBSpotLightData *spotlight = (DRBSpotLightData*)(spotLightPtr->spotLight.get());

			glViewport(0, 0, _frame_buffer.width(), _frame_buffer.height());
			_frame_buffer.attachment(*(*it), GL_DEPTH_STENCIL_ATTACHMENT);
			glClear(GL_DEPTH_BUFFER_BIT);
			_programs[PROGRAM_BUFFERING]->registerProperties(spotlight->globalProperties);
			_programs[PROGRAM_BUFFERING]->updateProperties(spotlight->globalProperties);

			// draw for the spot light selected
			for (auto &meshPaint : spotLightPtr->meshs)
			{
				auto mesh = (DRBMeshData*)(meshPaint.get());

				//temporary
				//todo, do not spawn entity while mesh is not loaded
				//currently it's not safe, because the paiter key can be invalid
				//during the first frames
				if (mesh->getPainterKey().isValid())
				{
					painter = _painterManager->get_painter(mesh->getPainterKey());
					if (painter != oldPainter)
					{
						if (oldPainter)
						{
							oldPainter->uniqueDrawEnd();
						}
						painter->uniqueDrawBegin(_programs[PROGRAM_BUFFERING]);
					}
					oldPainter = painter;
					painter->uniqueDraw(GL_TRIANGLES, _programs[PROGRAM_BUFFERING], mesh->globalProperties, mesh->getVerticesKey());
				}
			}
			spotlight->shadowMap = *it;
			++it;
		}
		if (oldPainter)
		{
			oldPainter->uniqueDrawEnd();
		}
	}
Exemplo n.º 11
0
	bool Imgui::init(Engine *en)
	{
#ifdef AGE_ENABLE_IMGUI

		GetMainThread()->registerCallback<ImGuiKeyEvent>([this](ImGuiKeyEvent &msg)
		{
			ImGuiIO& io = ImGui::GetIO();
			io.KeysDown[int(msg.key)] = msg.down;
			if (msg.key == AgeKeys::AGE_LCTRL || msg.key == AgeKeys::AGE_RCTRL)
				io.KeyCtrl = msg.down;
			else if (msg.key == AgeKeys::AGE_LSHIFT || msg.key == AgeKeys::AGE_RSHIFT)
				io.KeyShift = msg.down;
			else if (msg.down)
			{
				char character = keyToAscii.find(msg.key)->second;
				if (character != UNDEFINED_CHARACTER)
					io.AddInputCharacter(character);
			}
		});

		GetMainThread()->registerCallback<ImGuiEndOfFrame>([this](ImGuiEndOfFrame &msg)
		{
			SCOPE_profile_cpu_i("ImGui", "Render");
			ImGui::Render();
		});

		GetMainThread()->registerCallback<ImGuiMouseStateEvent>([this](ImGuiMouseStateEvent &msg)
		{
			_lastMouseState = msg;
		});

		_engine = en;
		//HARDCODED WINDOW TO FIX
		//auto window = di->getInstance<AGE::Threads::Render>()->getCommandQueue()->safePriorityFutureEmplace<RendCtxCommand::GetScreenSize, glm::uvec2>().get();

		ImGuiIO& io = ImGui::GetIO();
		//HARDCODED WINDOW TO FIX
		auto screenSize = en->getInstance<IRenderContext>()->getScreenSize();
		io.DisplaySize = ImVec2((float)screenSize.x, (float)screenSize.y);        // Display size, in pixels. For clamping windows positions.
		io.DeltaTime = 1.0f / 60.0f;                          // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable)
		io.KeyMap[ImGuiKey_Tab] = int(AgeKeys::AGE_TAB);             // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
		io.KeyMap[ImGuiKey_LeftArrow] =  int(AgeKeys::AGE_LEFT);
		io.KeyMap[ImGuiKey_RightArrow] = int(AgeKeys::AGE_RIGHT);
		io.KeyMap[ImGuiKey_UpArrow] =    int(AgeKeys::AGE_UP);
		io.KeyMap[ImGuiKey_DownArrow] =  int(AgeKeys::AGE_DOWN);
		io.KeyMap[ImGuiKey_Home] =       int(AgeKeys::AGE_HOME);
		io.KeyMap[ImGuiKey_End] =        int(AgeKeys::AGE_END);
		io.KeyMap[ImGuiKey_Delete] =     int(AgeKeys::AGE_DELETE);
		io.KeyMap[ImGuiKey_Backspace] =  int(AgeKeys::AGE_BACKSPACE);
		io.KeyMap[ImGuiKey_Enter] =      int(AgeKeys::AGE_RETURN);
		io.KeyMap[ImGuiKey_Escape] =     int(AgeKeys::AGE_ESCAPE);
		io.KeyMap[ImGuiKey_A] =          int(AgeKeys::AGE_a);
		io.KeyMap[ImGuiKey_C] =          int(AgeKeys::AGE_c);
		io.KeyMap[ImGuiKey_V] =          int(AgeKeys::AGE_v);
		io.KeyMap[ImGuiKey_X] =          int(AgeKeys::AGE_x);
		io.KeyMap[ImGuiKey_Y] =          int(AgeKeys::AGE_y);
		io.KeyMap[ImGuiKey_Z] =          int(AgeKeys::AGE_z);

		io.RenderDrawListsFn = renderDrawLists;

		//io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
		//io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;

		const GLchar *vertex_shader =
			"#version 330\n"
			"uniform mat4 ProjMtx;\n"
			"in vec2 Position;\n"
			"in vec2 UV;\n"
			"in vec4 Color;\n"
			"out vec2 Frag_UV;\n"
			"out vec4 Frag_Color;\n"
			"void main()\n"
			"{\n"
			"	Frag_UV = UV;\n"
			"	Frag_Color = Color;\n"
			"	gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
			"}\n";

		const GLchar* fragment_shader =
			"#version 330\n"
			"uniform sampler2D Texture;\n"
			"in vec2 Frag_UV;\n"
			"in vec4 Frag_Color;\n"
			"out vec4 Out_Color;\n"
			"void main()\n"
			"{\n"
			"	Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
			"}\n";

		shader_handle = glCreateProgram();
		vert_handle = glCreateShader(GL_VERTEX_SHADER);
		frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
		glShaderSource(vert_handle, 1, &vertex_shader, 0);
		glShaderSource(frag_handle, 1, &fragment_shader, 0);
		glCompileShader(vert_handle);
		glCompileShader(frag_handle);
		glAttachShader(shader_handle, vert_handle);
		glAttachShader(shader_handle, frag_handle);
		glLinkProgram(shader_handle);

		texture_location = glGetUniformLocation(shader_handle, "Texture");
		ortho_location = glGetUniformLocation(shader_handle, "ProjMtx");
		position_location = glGetAttribLocation(shader_handle, "Position");
		uv_location = glGetAttribLocation(shader_handle, "UV");
		colour_location = glGetAttribLocation(shader_handle, "Color");

		glGenBuffers(1, &vbo_handle);
		glBindBuffer(GL_ARRAY_BUFFER, vbo_handle);
		glBufferData(GL_ARRAY_BUFFER, vbo_max_size, NULL, GL_DYNAMIC_DRAW);

		glGenVertexArrays(1, &vao_handle);
		glBindVertexArray(vao_handle);
		glBindBuffer(GL_ARRAY_BUFFER, vbo_handle);
		glEnableVertexAttribArray(position_location);
		glEnableVertexAttribArray(uv_location);
		glEnableVertexAttribArray(colour_location);

		glVertexAttribPointer(position_location, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
		glVertexAttribPointer(uv_location, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
		glVertexAttribPointer(colour_location, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
		glBindVertexArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, 0);

		// Load font texture
		glGenTextures(1, &fontTex);
		glBindTexture(GL_TEXTURE_2D, fontTex);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		unsigned char* pixels;
		int width, height;
		io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
		io.Fonts->TexID = &fontTex;

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

		// Cleanup (don't clear the input data if you want to append new fonts later)
		io.Fonts->ClearInputData();
		io.Fonts->ClearTexData();
#else
		UNUSED(en);
#endif //AGE_ENABLE_IMGUI
		return true;
	}