int main (int argc, const char** argv)
{
	if (argc < 2)
	{
		printf ("USAGE: glsloptimizer testfolder\n");
		return 1;
	}

	bool hasOpenGL = InitializeOpenGL ();
	bool hasMetal = InitializeMetal ();
	glslopt_ctx* ctx[3] = {
		glslopt_initialize(kGlslTargetOpenGLES20),
		glslopt_initialize(kGlslTargetOpenGLES30),
		glslopt_initialize(kGlslTargetOpenGL),
	};
	glslopt_ctx* ctxMetal = glslopt_initialize(kGlslTargetMetal);

	std::string baseFolder = argv[1];

	clock_t time0 = clock();

	// 2.39s
	// ralloc fix 256 initial: 1.35s

	static const char* kTypeName[2] = { "vertex", "fragment" };
	size_t tests = 0;
	size_t errors = 0;
	for (int type = 0; type < 2; ++type)
	{
		std::string testFolder = baseFolder + "/" + kTypeName[type];

		static const char* kAPIName[3] = { "OpenGL ES 2.0", "OpenGL ES 3.0", "OpenGL" };
		static const char* kApiIn [3] = {"-inES.txt", "-inES3.txt", "-in.txt"};
		static const char* kApiOut[3] = {"-outES.txt", "-outES3.txt", "-out.txt"};
		static const char* kApiOutMetal[3] = {"-outESMetal.txt", "-outES3Metal.txt", "-outMetal.txt"};
		for (int api = 0; api < 3; ++api)
		{
			printf ("\n** running %s tests for %s...\n", kTypeName[type], kAPIName[api]);
			StringVector inputFiles = GetFiles (testFolder, kApiIn[api]);

			size_t n = inputFiles.size();
			for (size_t i = 0; i < n; ++i)
			{
				std::string inname = inputFiles[i];
				//if (inname != "ast-in.txt")
				//	continue;
				std::string outname = inname.substr (0,inname.size()-strlen(kApiIn[api])) + kApiOut[api];
				std::string outnameMetal = inname.substr (0,inname.size()-strlen(kApiIn[api])) + kApiOutMetal[api];
				const bool useMetal = (api == 1);
				bool ok = TestFile (ctx[api], type==0, inname, testFolder + "/" + inname, testFolder + "/" + outname, api<=1, hasOpenGL, false);
				if (!ok)
				{
					++errors;
				}
				if (useMetal)
				{
					ok = TestFile (ctxMetal, type==0, inname, testFolder + "/" + inname, testFolder + "/" + outnameMetal, api==0, false, hasMetal);
					if (!ok)
					{
						++errors;
					}
				}
				++tests;
			}
		}
	}
	clock_t time1 = clock();
	float timeDelta = float(time1-time0)/CLOCKS_PER_SEC;

	if (errors != 0)
		printf ("\n**** %i tests (%.2fsec), %i !!!FAILED!!!\n", (int)tests, timeDelta, (int)errors);
	else
		printf ("\n**** %i tests (%.2fsec) succeeded\n", (int)tests, timeDelta);
	
	// 3.25s
	// with builtin call linking, 3.84s

	for (int i = 0; i < 2; ++i)
		glslopt_cleanup (ctx[i]);
	glslopt_cleanup (ctxMetal);
	CleanupGL();

	return errors ? 1 : 0;
}
int main (int argc, const char** argv)
{
#ifndef __S3E__
	if (argc < 2)
	{
		printf ("USAGE: glsloptimizer testfolder\n");
		return 1;
	}
#endif

	bool hasOpenGL = InitializeOpenGL ();
	bool hasMetal = InitializeMetal ();
	glslopt_ctx* ctx[3] = {
		glslopt_initialize(kGlslTargetOpenGLES20),
		glslopt_initialize(kGlslTargetOpenGLES30),
		glslopt_initialize(kGlslTargetOpenGL),
	};
	glslopt_ctx* ctxMetal = glslopt_initialize(kGlslTargetMetal);

#ifndef __S3E__
	std::string baseFolder = argv[1];
#else
	std::string baseFolder = "." ;
#endif

	clock_t time0 = clock();

	// 2.39s
	// ralloc fix 256 initial: 1.35s

	static const char* kTypeName[2] = { "vertex", "fragment" };
	size_t tests = 0;
	size_t errors = 0;

	int type = 0 ; // vertex
	std::string testFolder = baseFolder + "/" + kTypeName[type];

	static const char* kAPIName[3] = { "OpenGL ES 2.0", "OpenGL ES 3.0", "OpenGL" };
	static const char* kApiIn [3] = {"-inES.txt", "-inES3.txt", "-in.txt"};
	static const char* kApiOut[3] = {"-outES.txt", "-outES3.txt", "-out.txt"};
	static const char* kApiOutMetal[3] = {"-outESMetal.txt", "-outES3Metal.txt", "-outMetal.txt"};

	int api= 0 ;		// OpenGL ES 2.0

	printf ("\n** running %s tests for %s...\n", kTypeName[type], kAPIName[api]);

	std::string inname = "ogre-inES.txt";
	std::string outname = inname.substr (0,inname.size()-strlen(kApiIn[api])) + kApiOut[api];
	std::string outnameMetal = inname.substr (0,inname.size()-strlen(kApiIn[api])) + kApiOutMetal[api];
	const bool useMetal = (api == 1);
#ifdef __S3E__
	// with s3e we wont perform GLES check
	hasOpenGL = false ;
#endif
	bool ok = TestFile (ctx[api], type==0, inname, testFolder + "/" + inname, testFolder + "/" + outname, api<=1, hasOpenGL, false);
	if (!ok)
	{
		++errors;
	}

	// for __S3E__ we normally wont test Metal
	if (useMetal)
	{
		ok = TestFile (ctxMetal, type==0, inname, testFolder + "/" + inname, testFolder + "/" + outnameMetal, api==0, false, hasMetal);
		if (!ok)
		{
			++errors;
		}
	}
	++tests;

	clock_t time1 = clock();
	float timeDelta = float(time1-time0)/CLOCKS_PER_SEC;

	if (errors != 0)
		printf ("\n**** %i tests (%.2fsec), %i !!!FAILED!!!\n", (int)tests, timeDelta, (int)errors);
	else
		printf ("\n**** %i tests (%.2fsec) succeeded\n", (int)tests, timeDelta);
	
	// 3.25s
	// with builtin call linking, 3.84s

	for (int i = 0; i < 2; ++i)
		glslopt_cleanup (ctx[i]);
	glslopt_cleanup (ctxMetal);
	CleanupGL();

	return errors ? 1 : 0;
}