Beispiel #1
0
int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int nCmdShow )
{
	ForceLoadComponentsDll();

#if HELIUM_TOOLS
	ForceLoadEditorSupportDll();
#endif

	HELIUM_TRACE_SET_LEVEL( TraceLevels::Debug );

	Timer::StaticInitialize();
	
#if !HELIUM_RELEASE && !HELIUM_PROFILE
	Helium::InitializeSymbols();
#endif

	AsyncLoader::GetStaticInstance().Initialize();

	FilePath baseDirectory;
	if ( !FileLocations::GetBaseDirectory( baseDirectory ) )
	{
		HELIUM_TRACE( TraceLevels::Error, TXT( "Could not get base directory." ) );
		return -1;
	}

	HELIUM_VERIFY( CacheManager::InitializeStaticInstance( baseDirectory ) );
	Helium::Bullet::Initialize();

	int resultCode = -1;

	{
	Reflect::Initialize();

	Helium::Components::Initialize();
	
	Helium::TaskScheduler::CalculateSchedule();

#if HELIUM_TOOLS
#endif

	InitEngineJobsDefaultHeap();
	InitGraphicsJobsDefaultHeap();
	InitTestJobsDefaultHeap();

#if HELIUM_TOOLS
	//HELIUM_VERIFY( LooseAssetLoader::InitializeStaticInstance() );
	HELIUM_VERIFY( LooseAssetLoader::InitializeStaticInstance() );

	AssetPreprocessor* pAssetPreprocessor = AssetPreprocessor::CreateStaticInstance();
	HELIUM_ASSERT( pAssetPreprocessor );
	PlatformPreprocessor* pPlatformPreprocessor = new PcPreprocessor;
	HELIUM_ASSERT( pPlatformPreprocessor );
	pAssetPreprocessor->SetPlatformPreprocessor( Cache::PLATFORM_PC, pPlatformPreprocessor );
#else
	HELIUM_VERIFY( CacheAssetLoader::InitializeStaticInstance() );
#endif

#if !GTEST
	AssetLoader* gAssetLoader = NULL;
#endif

	gAssetLoader = AssetLoader::GetStaticInstance();
	HELIUM_ASSERT( gAssetLoader );

	Config& rConfig = Config::GetStaticInstance();
	rConfig.BeginLoad();
	while( !rConfig.TryFinishLoad() )
	{
		gAssetLoader->Tick();
	}

#if HELIUM_TOOLS
	ConfigPc::SaveUserConfig();
#endif

	uint32_t displayWidth;
	uint32_t displayHeight;
	//bool bFullscreen;
	bool bVsync;
	
	{
		StrongPtr< GraphicsConfig > spGraphicsConfig(
			rConfig.GetConfigObject< GraphicsConfig >( Name( TXT( "GraphicsConfig" ) ) ) );
		HELIUM_ASSERT( spGraphicsConfig );
		displayWidth = spGraphicsConfig->GetWidth();
		displayHeight = spGraphicsConfig->GetHeight();
		//bFullscreen = spGraphicsConfig->GetFullscreen();
		bVsync = spGraphicsConfig->GetVsync();
	}

	WNDCLASSEXW windowClass;
	windowClass.cbSize = sizeof( windowClass );
	windowClass.style = 0;
	windowClass.lpfnWndProc = WindowProc;
	windowClass.cbClsExtra = 0;
	windowClass.cbWndExtra = 0;
	windowClass.hInstance = hInstance;
	windowClass.hIcon = NULL;
	windowClass.hCursor = NULL;
	windowClass.hbrBackground = NULL;
	windowClass.lpszMenuName = NULL;
	windowClass.lpszClassName = L"HeliumTestAppClass";
	windowClass.hIconSm = NULL;
	HELIUM_VERIFY( RegisterClassEx( &windowClass ) );

	WindowData windowData;
	windowData.hMainWnd = NULL;
	windowData.hSubWnd = NULL;
	windowData.bProcessMessages = true;
	windowData.bShutdownRendering = false;
	windowData.resultCode = 0;

	DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
	RECT windowRect;

	windowRect.left = 0;
	windowRect.top = 0;
	windowRect.right = static_cast< LONG >( displayWidth );
	windowRect.bottom = static_cast< LONG >( displayHeight );
	HELIUM_VERIFY( AdjustWindowRect( &windowRect, dwStyle, FALSE ) );

	HWND hMainWnd = ::CreateWindowW(
		L"HeliumTestAppClass",
		L"Helium TestApp",
		dwStyle,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		windowRect.right - windowRect.left,
		windowRect.bottom - windowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL );
	HELIUM_ASSERT( hMainWnd );

	windowRect.left = 0;
	windowRect.top = 0;
	windowRect.right = static_cast< LONG >( displayWidth );
	windowRect.bottom = static_cast< LONG >( displayHeight );
	HELIUM_VERIFY( AdjustWindowRect( &windowRect, dwStyle, FALSE ) );
#if MULTI_WINDOW
	HWND hSubWnd = ::CreateWindowW(
		L"HeliumTestAppClass",
		L"Helium TestApp (second view)",
		dwStyle,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		windowRect.right - windowRect.left,
		windowRect.bottom - windowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL );
	HELIUM_ASSERT( hSubWnd );
#endif

	windowData.hMainWnd = hMainWnd;
	SetWindowLongPtr( hMainWnd, GWLP_USERDATA, reinterpret_cast< LONG_PTR >( &windowData ) );
	ShowWindow( hMainWnd, nCmdShow );
	UpdateWindow( hMainWnd );
#if MULTI_WINDOW
	windowData.hSubWnd = hSubWnd;
	SetWindowLongPtr( hSubWnd, GWLP_USERDATA, reinterpret_cast< LONG_PTR >( &windowData ) );
	ShowWindow( hSubWnd, nCmdShow );
	UpdateWindow( hSubWnd );
#endif

	HELIUM_VERIFY( D3D9Renderer::CreateStaticInstance() );

	Renderer* pRenderer = Renderer::GetStaticInstance();
	HELIUM_ASSERT( pRenderer );
	pRenderer->Initialize();

	Renderer::ContextInitParameters contextInitParams;

	contextInitParams.pWindow = hMainWnd;
	contextInitParams.displayWidth = displayWidth;
	contextInitParams.displayHeight = displayHeight;
	contextInitParams.bVsync = bVsync;
	HELIUM_VERIFY( pRenderer->CreateMainContext( contextInitParams ) );
#if MULTI_WINDOW
	contextInitParams.pWindow = hSubWnd;
	RRenderContextPtr spSubRenderContext = pRenderer->CreateSubContext( contextInitParams );
	HELIUM_ASSERT( spSubRenderContext );
#endif

	Input::Initialize(&hMainWnd, false);

	{
		AssetPath prePassShaderPath;
		HELIUM_VERIFY( prePassShaderPath.Set(
			HELIUM_PACKAGE_PATH_CHAR_STRING TXT( "Shaders" ) HELIUM_OBJECT_PATH_CHAR_STRING TXT( "PrePass.hlsl" ) ) );

		AssetPtr spPrePassShader;
		HELIUM_VERIFY( AssetLoader::GetStaticInstance()->LoadObject( prePassShaderPath, spPrePassShader ) );

		HELIUM_ASSERT( spPrePassShader.Get() );
	}

	RenderResourceManager& rRenderResourceManager = RenderResourceManager::GetStaticInstance();
	rRenderResourceManager.Initialize();
	rRenderResourceManager.UpdateMaxViewportSize( displayWidth, displayHeight );

	//// Create a scene definition
	SceneDefinitionPtr spSceneDefinition;
	gAssetLoader->LoadObject( AssetPath( TXT( "/ExampleGames/Empty/Scenes/TestScene:SceneDefinition" ) ), spSceneDefinition );

	EntityDefinitionPtr spEntityDefinition;
	gAssetLoader->LoadObject( AssetPath( TXT( "/ExampleGames/Empty/Scenes/TestScene:TestBull_Entity" ) ), spEntityDefinition );

	DynamicDrawer& rDynamicDrawer = DynamicDrawer::GetStaticInstance();
	HELIUM_VERIFY( rDynamicDrawer.Initialize() );

	RRenderContextPtr spMainRenderContext = pRenderer->GetMainContext();
	HELIUM_ASSERT( spMainRenderContext );
	
	WorldManager& rWorldManager = WorldManager::GetStaticInstance();
	HELIUM_VERIFY( rWorldManager.Initialize() );

	// Create a world
	WorldPtr spWorld( rWorldManager.CreateWorld( spSceneDefinition ) );
	HELIUM_ASSERT( spWorld );
	HELIUM_TRACE( TraceLevels::Info, TXT( "Created world \"%s\".\n" ), *spSceneDefinition->GetPath().ToString() );

	//Slice *pRootSlice = spWorld->GetRootSlice();
	//Entity *pEntity = pRootSlice->CreateEntity(spEntityDefinition);
			
	GraphicsScene* pGraphicsScene = spWorld->GetComponents().GetFirst<GraphicsManagerComponent>()->GetGraphicsScene();
	HELIUM_ASSERT( pGraphicsScene );
	GraphicsSceneView* pMainSceneView = NULL;
	if( pGraphicsScene )
	{
		uint32_t mainSceneViewId = pGraphicsScene->AllocateSceneView();
		if( IsValid( mainSceneViewId ) )
		{
			float32_t aspectRatio =
				static_cast< float32_t >( displayWidth ) / static_cast< float32_t >( displayHeight );

			RSurface* pDepthStencilSurface = rRenderResourceManager.GetDepthStencilSurface();
			HELIUM_ASSERT( pDepthStencilSurface );

			pMainSceneView = pGraphicsScene->GetSceneView( mainSceneViewId );
			HELIUM_ASSERT( pMainSceneView );
			pMainSceneView->SetRenderContext( spMainRenderContext );
			pMainSceneView->SetDepthStencilSurface( pDepthStencilSurface );
			pMainSceneView->SetAspectRatio( aspectRatio );
			pMainSceneView->SetViewport( 0, 0, displayWidth, displayHeight );
			pMainSceneView->SetClearColor( Color( 0x00202020 ) );

			//spMainCamera->SetSceneViewId( mainSceneViewId );

#if MULTI_WINDOW
			uint32_t subSceneViewId = pGraphicsScene->AllocateSceneView();
			if( IsValid( subSceneViewId ) )
			{
				GraphicsSceneView* pSubSceneView = pGraphicsScene->GetSceneView( subSceneViewId );
				HELIUM_ASSERT( pSubSceneView );
				pSubSceneView->SetRenderContext( spSubRenderContext );
				pSubSceneView->SetDepthStencilSurface( pDepthStencilSurface );
				pSubSceneView->SetAspectRatio( aspectRatio );
				pSubSceneView->SetViewport( 0, 0, displayWidth, displayHeight );
				pSubSceneView->SetClearColor( Color( 0x00202020 ) );

				//spSubCamera->SetSceneViewId( subSceneViewId );
			}
#endif
		}
	
#if !HELIUM_RELEASE && !HELIUM_PROFILE
		BufferedDrawer& rSceneDrawer = pGraphicsScene->GetSceneBufferedDrawer();
		rSceneDrawer.DrawScreenText(
			20,
			20,
			String( TXT( "CACHING" ) ),
			Color( 0xff00ff00 ),
			RenderResourceManager::DEBUG_FONT_SIZE_LARGE );
		rSceneDrawer.DrawScreenText(
			21,
			20,
			String( TXT( "CACHING" ) ),
			Color( 0xff00ff00 ),
			RenderResourceManager::DEBUG_FONT_SIZE_LARGE );

		//rSceneDrawer.Draw

		//Helium::DynamicDrawer &drawer = DynamicDrawer::GetStaticInstance();
		//drawer.
#endif
	}

	rWorldManager.Update();
	
	float time = 0.0f;

#if MULTI_WINDOW
	spSubRenderContext.Release();
#endif
	spMainRenderContext.Release();

	
	Helium::StrongPtr<Helium::Texture2d> texture;
	gAssetLoader->LoadObject( AssetPath( TXT( "/Textures:Triangle.png" ) ), texture);

	Helium::RTexture2d *rTexture2d = texture->GetRenderResource2d();


	while( windowData.bProcessMessages )
	{
#if GRAPHICS_SCENE_BUFFERED_DRAWER
		BufferedDrawer& rSceneDrawer = pGraphicsScene->GetSceneBufferedDrawer();
		rSceneDrawer.DrawScreenText(
			20,
			20,
			String( TXT( "RUNNING" ) ),
			Color( 0xffffffff ),
			RenderResourceManager::DEBUG_FONT_SIZE_LARGE );
		rSceneDrawer.DrawScreenText(
			21,
			20,
			String( TXT( "RUNNING" ) ),
			Color( 0xffffffff ),
			RenderResourceManager::DEBUG_FONT_SIZE_LARGE );

		time += 0.01f;
		DynamicArray<SimpleVertex> verticesU;

		verticesU.New( -100.0f, -100.0f, 750.0f );
		verticesU.New( 100.0f, -100.0f, 750.0f );
		verticesU.New( 100.0f, 100.0f, 750.0f );
		verticesU.New( -100.0f, 100.0f, 750.0f );
		
		rSceneDrawer.DrawLineList( verticesU.GetData(), static_cast<uint32_t>( verticesU.GetSize() ) );
		
		DynamicArray<SimpleTexturedVertex> verticesT;
		verticesT.New( Simd::Vector3( -100.0f, 100.0f, 750.0f ), Simd::Vector2( 0.0f, 0.0f ) );
		verticesT.New( Simd::Vector3( 100.0f, 100.0f, 750.0f ), Simd::Vector2( 1.0f, 0.0f ) );
		verticesT.New( Simd::Vector3( -100.0f, -100.0f, 750.0f ), Simd::Vector2( 0.0f, 1.0f ) );
		verticesT.New( Simd::Vector3( 100.0f, -100.0f, 750.0f ), Simd::Vector2( 1.0f, 1.0f ) );
		

		//rSceneDrawer.DrawTextured(
		//	RENDERER_PRIMITIVE_TYPE_TRIANGLE_STRIP,
		//	verticesT.GetData(),
		//	verticesT.GetSize(),
		//	NULL,
		//	2,
		//	rTexture2d, Helium::Color(1.0f, 1.0f, 1.0f, 1.0f), Helium::RenderResourceManager::RASTERIZER_STATE_DEFAULT, Helium::RenderResourceManager::DEPTH_STENCIL_STATE_NONE);

		//rSceneDrawer.DrawTexturedQuad(rTexture2d);

		Helium::Simd::Matrix44 transform = Helium::Simd::Matrix44::IDENTITY;
		
		Simd::Vector3 location(0.0f, 400.0f, 0.0f);
		Simd::Quat rotation(Helium::Simd::Vector3::BasisZ, time);
		Simd::Vector3 scale(1000.0f, 1000.0f, 1000.0f);
		


		transform.SetRotationTranslationScaling(rotation, location, scale);
		rSceneDrawer.DrawTexturedQuad(rTexture2d, transform, Simd::Vector2(0.0f, 0.0f), Simd::Vector2(0.5f, 0.5f));
#endif
		
		//Helium::Simd::Vector3 up = Simd::Vector3::BasisY;
		////Helium::Simd::Vector3 eye(5000.0f * sin(time), 0.0f, 5000.0f * cos(time));
		//Helium::Simd::Vector3 eye(0.0f, 0.0f, -1000.0f);
		//Helium::Simd::Vector3 forward = Simd::Vector3::Zero - eye;
		//forward.Normalize();

		////pMainSceneView->SetClearColor( Color( 0xffffffff ) );
		//pMainSceneView->SetView(eye, forward, up);




		if (Input::IsKeyDown(Input::KeyCodes::KC_A))
		{
			HELIUM_TRACE( TraceLevels::Info, TXT( "A is down" ) );
		}

		if (Input::IsKeyDown(Input::KeyCodes::KC_ESCAPE))
		{
			HELIUM_TRACE( TraceLevels::Info, TXT( "Exiting" ) );
			break;
		}

		MSG message;
		if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) )
		{
			TranslateMessage( &message );
			DispatchMessage( &message );

			if( windowData.bShutdownRendering )
			{
				if( spWorld )
				{
					spWorld->Shutdown();
				}

				spWorld.Release();
				WorldManager::DestroyStaticInstance();

				spSceneDefinition.Release();
				spEntityDefinition.Release();

				DynamicDrawer::DestroyStaticInstance();
				RenderResourceManager::DestroyStaticInstance();

				Renderer::DestroyStaticInstance();

				break;
			}

			if( message.message == WM_QUIT )
			{
				windowData.bProcessMessages = false;
				windowData.resultCode = static_cast< int >( message.wParam );
				resultCode = static_cast< int >( message.wParam );

				break;
			}
		}

		rWorldManager.Update();

#if GRAPHICS_SCENE_BUFFERED_DRAWER
		if( pGraphicsScene )
		{
			BufferedDrawer& rSceneDrawer = pGraphicsScene->GetSceneBufferedDrawer();
			rSceneDrawer.DrawScreenText(
				20,
				20,
				String( TXT( "Debug text test!" ) ),
				Color( 0xffffffff ) );
		}
#endif
	}

	if( spWorld )
	{
		spWorld->Shutdown();
	}

	spWorld.Release();
	}
	WorldManager::DestroyStaticInstance();
	

	DynamicDrawer::DestroyStaticInstance();
	RenderResourceManager::DestroyStaticInstance();

	Helium::Input::Cleanup();

	Renderer::DestroyStaticInstance();
	

	JobManager::DestroyStaticInstance();

	Config::DestroyStaticInstance();

#if HELIUM_TOOLS
	AssetPreprocessor::DestroyStaticInstance();
#endif
	AssetLoader::DestroyStaticInstance();
	CacheManager::DestroyStaticInstance();
	
	Helium::Components::Cleanup();
	

	Reflect::Cleanup();
	AssetType::Shutdown();
	Asset::Shutdown();


	Reflect::ObjectRefCountSupport::Shutdown();
	Helium::Bullet::Cleanup();

	AssetPath::Shutdown();
	Name::Shutdown();

	FileLocations::Shutdown();

	ThreadLocalStackAllocator::ReleaseMemoryHeap();

#if HELIUM_ENABLE_MEMORY_TRACKING
	DynamicMemoryHeap::LogMemoryStats();
	ThreadLocalStackAllocator::ReleaseMemoryHeap();
#endif

	return resultCode;
}
Beispiel #2
0
int main( int argc, const char* argv[] )
#endif
{
	HELIUM_TRACE_SET_LEVEL( TraceLevels::Debug );

	Helium::GetComponentsDefaultHeap();
	Helium::GetBulletDefaultHeap();

#if HELIUM_TOOLS
	Helium::GetEditorSupportDefaultHeap();
#endif

	int32_t result = 0;

	{
		// Initialize a GameSystem instance.
		CommandLineInitializationImpl commandLineInitialization;
		MemoryHeapPreInitializationImpl memoryHeapPreInitialization;
		AssetLoaderInitializationImpl assetLoaderInitialization;
		ConfigInitializationImpl configInitialization;
#if HELIUM_DIRECT3D
		WindowManagerInitializationImpl windowManagerInitialization( hInstance, nCmdShow );
#else
		WindowManagerInitializationImpl windowManagerInitialization;
#endif
		RendererInitializationImpl rendererInitialization;
		//NullRendererInitialization rendererInitialization;
		AssetPath systemDefinitionPath( "/ExampleGames/PhysicsDemo:System" );

		GameSystem* pGameSystem = GameSystem::CreateStaticInstance();
		HELIUM_ASSERT( pGameSystem );
		bool bSystemInitSuccess = pGameSystem->Initialize(
			commandLineInitialization,
			memoryHeapPreInitialization,
			assetLoaderInitialization,
			configInitialization,
			windowManagerInitialization,
			rendererInitialization,
			systemDefinitionPath);
		
		if( bSystemInitSuccess )
		{
			World *pWorld = NULL; 

			{
				AssetLoader *pAssetLoader = AssetLoader::GetStaticInstance();
				SceneDefinitionPtr spSceneDefinition;

				AssetPath scenePath( TXT( "/ExampleGames/PhysicsDemo/Scenes/TestScene:SceneDefinition" ) );
				pAssetLoader->LoadObject(scenePath, spSceneDefinition );

				HELIUM_ASSERT( !spSceneDefinition->GetAllFlagsSet( Asset::FLAG_BROKEN ) );

				pWorld = pGameSystem->LoadScene(spSceneDefinition.Get());
			}

			HELIUM_ASSERT( pWorld );

			if ( pWorld )
			{
				AssetLoader *pAssetLoader = AssetLoader::GetStaticInstance();

				EntityDefinitionPtr spCubeDefinition;
				EntityDefinitionPtr spSphereDefinition;

				AssetPath spCubePath( TXT( "/ExampleGames/PhysicsDemo:Cube" ) );
				AssetPath spSpherePath( TXT( "/ExampleGames/PhysicsDemo:Sphere" ) );

				pAssetLoader->LoadObject(spCubePath, spCubeDefinition );
				pAssetLoader->LoadObject(spSpherePath, spSphereDefinition );

				Helium::StrongPtr< ParameterSet_InitLocated > locatedParamSet( new ParameterSet_InitLocated() );
				locatedParamSet->m_Position = Simd::Vector3::Zero;
				locatedParamSet->m_Rotation = Simd::Quat::IDENTITY;

				Simd::Vector3 &position = locatedParamSet->m_Position;
				Simd::Quat &rotation = locatedParamSet->m_Rotation;

				for (int i = 0; i < 25; ++i)
				{
					position = Simd::Vector3(
						50.0f * static_cast<float>(i / 5) - 100.0f + Helium::Ran(-10.0f, 10.0f), 
						Helium::Ran(150.0f, 200.0f), 
						50.0f * static_cast<float>(i % 5) - 100.0f + Helium::Ran(-10.0f, 10.0f));
					pWorld->GetRootSlice()->CreateEntity(spCubeDefinition, locatedParamSet.Get());
				}

				for (int i = 0; i < 25; ++i)
				{
					position = Simd::Vector3(
						50.0f * static_cast<float>(i / 5) - 100.0f + Helium::Ran(-10.0f, 10.0f), 
						Helium::Ran(250.0f, 300.0f), 
						50.0f * static_cast<float>(i % 5) - 100.0f + Helium::Ran(-10.0f, 10.0f));
					pWorld->GetRootSlice()->CreateEntity(spSphereDefinition, locatedParamSet.Get());
				}

				for (int i = 0; i < 25; ++i)
				{
					position = Simd::Vector3(
						50.0f * static_cast<float>(i / 5) - 100.0f + Helium::Ran(-10.0f, 10.0f), 
						Helium::Ran(350.0f, 400.0f), 
						50.0f * static_cast<float>(i % 5) - 100.0f + Helium::Ran(-10.0f, 10.0f));
					pWorld->GetRootSlice()->CreateEntity(spCubeDefinition, locatedParamSet.Get());
				}

				for (int i = 0; i < 25; ++i)
				{
					position = Simd::Vector3(
						50.0f * static_cast<float>(i / 5) - 100.0f + Helium::Ran(-10.0f, 10.0f), 
						Helium::Ran(450.0f, 500.0f), 
						50.0f * static_cast<float>(i % 5) - 100.0f + Helium::Ran(-10.0f, 10.0f));
					pWorld->GetRootSlice()->CreateEntity(spSphereDefinition, locatedParamSet.Get());
				}

				for (int i = 0; i < 25; ++i)
				{
					position = Simd::Vector3(
						50.0f * static_cast<float>(i / 5) - 100.0f + Helium::Ran(-10.0f, 10.0f), 
						Helium::Ran(550.0f, 600.0f), 
						50.0f * static_cast<float>(i % 5) - 100.0f + Helium::Ran(-10.0f, 10.0f));
					pWorld->GetRootSlice()->CreateEntity(spCubeDefinition, locatedParamSet.Get());
				}

				Window::NativeHandle windowHandle = rendererInitialization.GetMainWindow()->GetNativeHandle();
				Input::Initialize(windowHandle, false);
				Input::SetWindowSize( 
					rendererInitialization.GetMainWindow()->GetWidth(),
					rendererInitialization.GetMainWindow()->GetHeight());

				// Run the application.
				result = pGameSystem->Run();
			}
		}

		// Shut down and destroy the system.
		pGameSystem->Shutdown();
		System::DestroyStaticInstance();
	}

	// Perform final cleanup.
	ThreadLocalStackAllocator::ReleaseMemoryHeap();

#if HELIUM_ENABLE_MEMORY_TRACKING
	DynamicMemoryHeap::LogMemoryStats();
	ThreadLocalStackAllocator::ReleaseMemoryHeap();
#endif

	return result;
}
/// Initialize all resources provided by this manager.
///
/// @see Cleanup(), PostConfigUpdate()
bool RenderResourceManager::Initialize()
{
	// Release any existing resources.
	Cleanup();

	// Get the renderer and graphics configuration.
	Renderer* pRenderer = Renderer::GetInstance();
	if ( !pRenderer )
	{
		return false;
	}

	Config* pConfig = Config::GetInstance();
	if ( !HELIUM_VERIFY( pConfig ) )
	{
		return false;
	}

	StrongPtr< GraphicsConfig > spGraphicsConfig( pConfig->GetConfigObject< GraphicsConfig >( Name( "GraphicsConfig" ) ) );
	if ( !spGraphicsConfig )
	{
		HELIUM_TRACE( TraceLevels::Error, "RenderResourceManager::Initialize(): Initialization failed; missing GraphicsConfig.\n" );
		return false;
	}

	// Create the standard rasterizer states.
	RRasterizerState::Description rasterizerStateDesc;

	rasterizerStateDesc.fillMode = RENDERER_FILL_MODE_SOLID;
	rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_BACK;
	rasterizerStateDesc.winding = RENDERER_WINDING_CLOCKWISE;
	rasterizerStateDesc.depthBias = 0;
	rasterizerStateDesc.slopeScaledDepthBias = 0.0f;
	m_rasterizerStates[RASTERIZER_STATE_DEFAULT] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_DEFAULT] );

	rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_NONE;
	m_rasterizerStates[RASTERIZER_STATE_DOUBLE_SIDED] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_DOUBLE_SIDED] );

	rasterizerStateDesc.depthBias = 1;
	rasterizerStateDesc.slopeScaledDepthBias = 2.0f;
	m_rasterizerStates[RASTERIZER_STATE_SHADOW_DEPTH] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_SHADOW_DEPTH] );

	rasterizerStateDesc.depthBias = 0;
	rasterizerStateDesc.slopeScaledDepthBias = 0.0f;
	rasterizerStateDesc.fillMode = RENDERER_FILL_MODE_WIREFRAME;
	m_rasterizerStates[RASTERIZER_STATE_WIREFRAME_DOUBLE_SIDED] = pRenderer->CreateRasterizerState(
		rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_WIREFRAME_DOUBLE_SIDED] );

	rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_BACK;
	m_rasterizerStates[RASTERIZER_STATE_WIREFRAME] = pRenderer->CreateRasterizerState( rasterizerStateDesc );
	HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_WIREFRAME] );

	// Create the standard blend states.
	RBlendState::Description blendStateDesc;

	blendStateDesc.bBlendEnable = false;
	m_blendStates[BLEND_STATE_OPAQUE] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_OPAQUE] );

	blendStateDesc.colorWriteMask = 0;
	m_blendStates[BLEND_STATE_NO_COLOR] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_NO_COLOR] );

	blendStateDesc.colorWriteMask = RENDERER_COLOR_WRITE_MASK_FLAG_ALL;
	blendStateDesc.bBlendEnable = true;

	blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_SRC_ALPHA;
	blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_INV_SRC_ALPHA;
	blendStateDesc.function = RENDERER_BLEND_FUNCTION_ADD;
	m_blendStates[BLEND_STATE_TRANSPARENT] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_TRANSPARENT] );

	blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_ONE;
	blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_ONE;
	m_blendStates[BLEND_STATE_ADDITIVE] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_ADDITIVE] );

	blendStateDesc.function = RENDERER_BLEND_FUNCTION_REVERSE_SUBTRACT;
	m_blendStates[BLEND_STATE_SUBTRACTIVE] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_SUBTRACTIVE] );

	blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_DEST_COLOR;
	blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_ZERO;
	blendStateDesc.function = RENDERER_BLEND_FUNCTION_ADD;
	m_blendStates[BLEND_STATE_MODULATE] = pRenderer->CreateBlendState( blendStateDesc );
	HELIUM_ASSERT( m_blendStates[BLEND_STATE_MODULATE] );

	// Create the standard depth/stencil states.
	RDepthStencilState::Description depthStateDesc;

	depthStateDesc.stencilWriteMask = 0;
	depthStateDesc.bStencilTestEnable = false;

	depthStateDesc.depthFunction = RENDERER_COMPARE_FUNCTION_LESS_EQUAL;
	depthStateDesc.bDepthTestEnable = true;
	depthStateDesc.bDepthWriteEnable = true;
	m_depthStencilStates[DEPTH_STENCIL_STATE_DEFAULT] = pRenderer->CreateDepthStencilState( depthStateDesc );
	HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_DEFAULT] );

	depthStateDesc.bDepthWriteEnable = false;
	m_depthStencilStates[DEPTH_STENCIL_STATE_TEST_ONLY] = pRenderer->CreateDepthStencilState( depthStateDesc );
	HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_TEST_ONLY] );

	depthStateDesc.bDepthTestEnable = false;
	m_depthStencilStates[DEPTH_STENCIL_STATE_NONE] = pRenderer->CreateDepthStencilState( depthStateDesc );
	HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_NONE] );

	// Create the standard sampler states that are not dependent on configuration settings.
	RSamplerState::Description samplerStateDesc;
	samplerStateDesc.filter = RENDERER_TEXTURE_FILTER_MIN_POINT_MAG_POINT_MIP_POINT;
	samplerStateDesc.addressModeW = RENDERER_TEXTURE_ADDRESS_MODE_CLAMP;
	samplerStateDesc.mipLodBias = 0;
	samplerStateDesc.maxAnisotropy = spGraphicsConfig->GetMaxAnisotropy();

	for ( size_t addressModeIndex = 0; addressModeIndex < RENDERER_TEXTURE_ADDRESS_MODE_MAX; ++addressModeIndex )
	{
		ERendererTextureAddressMode addressMode = static_cast<ERendererTextureAddressMode>( addressModeIndex );
		samplerStateDesc.addressModeU = addressMode;
		samplerStateDesc.addressModeV = addressMode;
		samplerStateDesc.addressModeW = addressMode;

		m_samplerStates[TEXTURE_FILTER_POINT][addressModeIndex] = pRenderer->CreateSamplerState( samplerStateDesc );
		HELIUM_ASSERT( m_samplerStates[TEXTURE_FILTER_POINT][addressModeIndex] );
	}

	// Create the standard set of mesh vertex descriptions.
	RVertexDescription::Element vertexElements[6];

	vertexElements[0].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_3;
	vertexElements[0].semantic = RENDERER_VERTEX_SEMANTIC_POSITION;
	vertexElements[0].semanticIndex = 0;
	vertexElements[0].bufferIndex = 0;

	vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
	vertexElements[1].semanticIndex = 0;
	vertexElements[1].bufferIndex = 0;

	vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[2].semanticIndex = 0;
	vertexElements[2].bufferIndex = 0;

	vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_2;
	vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[3].semanticIndex = 1;
	vertexElements[3].bufferIndex = 0;

	m_spSimpleVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 2 );
	HELIUM_ASSERT( m_spSimpleVertexDescription );

	m_spSimpleTexturedVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 3 );
	HELIUM_ASSERT( m_spSimpleTexturedVertexDescription );

	m_spProjectedVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 4 );
	HELIUM_ASSERT( m_spProjectedVertexDescription );

	vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_NORMAL;
	vertexElements[1].semanticIndex = 0;
	vertexElements[1].bufferIndex = 0;

	vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TANGENT;
	vertexElements[2].semanticIndex = 0;
	vertexElements[2].bufferIndex = 0;

	vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
	vertexElements[3].semanticIndex = 0;
	vertexElements[3].bufferIndex = 0;

	vertexElements[4].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[4].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[4].semanticIndex = 0;
	vertexElements[4].bufferIndex = 0;

	vertexElements[5].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[5].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[5].semanticIndex = 1;
	vertexElements[5].bufferIndex = 0;

	m_staticMeshVertexDescriptions[0] = pRenderer->CreateVertexDescription( vertexElements, 5 );
	HELIUM_ASSERT( m_staticMeshVertexDescriptions[0] );

	m_staticMeshVertexDescriptions[1] = pRenderer->CreateVertexDescription( vertexElements, 6 );
	HELIUM_ASSERT( m_staticMeshVertexDescriptions[1] );

	vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_BLENDWEIGHT;
	vertexElements[1].semanticIndex = 0;
	vertexElements[1].bufferIndex = 0;

	vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4;
	vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_BLENDINDICES;
	vertexElements[2].semanticIndex = 0;
	vertexElements[2].bufferIndex = 0;

	vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_NORMAL;
	vertexElements[3].semanticIndex = 0;
	vertexElements[3].bufferIndex = 0;

	vertexElements[4].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[4].semantic = RENDERER_VERTEX_SEMANTIC_TANGENT;
	vertexElements[4].semanticIndex = 0;
	vertexElements[4].bufferIndex = 0;

	vertexElements[5].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[5].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[5].semanticIndex = 0;
	vertexElements[5].bufferIndex = 0;

	m_spSkinnedMeshVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 6 );
	HELIUM_ASSERT( m_spSkinnedMeshVertexDescription );

	vertexElements[0].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_2;
	vertexElements[0].semantic = RENDERER_VERTEX_SEMANTIC_POSITION;
	vertexElements[0].semanticIndex = 0;
	vertexElements[0].bufferIndex = 0;

	vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM;
	vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_COLOR;
	vertexElements[1].semanticIndex = 0;
	vertexElements[1].bufferIndex = 0;

	vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2;
	vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD;
	vertexElements[2].semanticIndex = 0;
	vertexElements[2].bufferIndex = 0;

	m_spScreenVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 3 );
	HELIUM_ASSERT( m_spScreenVertexDescription );

	// Create configuration-dependent render resources.
	PostConfigUpdate();

	// Attempt to load the depth-only pre-pass shader.
	// TODO: XXX TMC: Migrate to a more data-driven solution.
	AssetLoader* pAssetLoader = AssetLoader::GetInstance();
	HELIUM_ASSERT( pAssetLoader );

#ifdef HELIUM_DIRECT3D

	AssetPath prePassShaderPath;
	HELIUM_VERIFY( prePassShaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "PrePass.hlsl" ) );

	AssetPtr spPrePassShader;
	HELIUM_VERIFY( pAssetLoader->LoadObject( prePassShaderPath, spPrePassShader ) );

	Shader* pPrePassShader = Reflect::SafeCast< Shader >( spPrePassShader.Get() );
	if ( HELIUM_VERIFY( pPrePassShader ) )
	{
		size_t loadId = pPrePassShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pPrePassShader->TryFinishLoadVariant( loadId, m_spPrePassVertexShader ) )
			{
				pAssetLoader->Tick();
			}
		}
	}

	// Attempt to load the simple world-space, simple screen-space, and screen-space text shaders.
	// TODO: XXX TMC: Migrate to a more data-driven solution.
	AssetPath shaderPath;
	HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "Simple.hlsl" ) );

	AssetPtr spShader;
	HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) );

	Shader* pShader = Reflect::SafeCast< Shader >( spShader.Get() );
	if ( HELIUM_VERIFY( pShader ) )
	{
		size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpaceVertexShader ) )
			{
				pAssetLoader->Tick();
			}
		}

		loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpacePixelShader ) )
			{
				pAssetLoader->Tick();
			}
		}
	}

	HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "ScreenSpaceTexture.hlsl" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) );
	pShader = Reflect::SafeCast< Shader >( spShader.Get() );
	if ( HELIUM_VERIFY( pShader ) )
	{
		size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpaceVertexShader ) )
			{
				pAssetLoader->Tick();
			}
		}

		loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpacePixelShader ) )
			{
				pAssetLoader->Tick();
			}
		}
	}

	HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "ScreenText.hlsl" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) );
	pShader = Reflect::SafeCast< Shader >( spShader.Get() );
	if ( HELIUM_VERIFY( pShader ) )
	{
		size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextVertexShader ) )
			{
				pAssetLoader->Tick();
			}
		}

		loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 );
		HELIUM_ASSERT( IsValid( loadId ) );
		if ( IsValid( loadId ) )
		{
			while ( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextPixelShader ) )
			{
				pAssetLoader->Tick();
			}
		}
	}

	// Attempt to load the debug fonts.
	// TODO: XXX TMC: Migrate to a more data-driven solution.
	AssetPath fontPath;
	AssetPtr spFont;

	HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugSmall" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) );
	m_debugFonts[DEBUG_FONT_SIZE_SMALL] = Reflect::SafeCast< Font >( spFont.Get() );
	spFont.Release();

	HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugMedium" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) );
	m_debugFonts[DEBUG_FONT_SIZE_MEDIUM] = Reflect::SafeCast< Font >( spFont.Get() );
	spFont.Release();

	HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugLarge" ) );
	HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) );
	m_debugFonts[DEBUG_FONT_SIZE_LARGE] = Reflect::SafeCast< Font >( spFont.Get() );
	spFont.Release();

#endif

	return true;
}