Jason McKesson avatar Jason McKesson committed 38affaf

Suite codegeneration seems to be working OK.

Comments (0)

Files changed (13)

 *.d
 *.a
 *.lo
+*_codegen.cpp

tests/codegen.lua

 function codegen.initialize(init_cmds)
 	assert(codegen._curr, "Attempt to set initialization data for a suite/test that doesn't exist.")
 	
-	InsertTableOfStrings(codegen._curr.initialize, init_cmds, "initialize")
+	if(type(init_cmds) == "string") then
+		table.insert(codegen._curr.initialize, init_cmds)
+	elseif(type(init_cmds) == "function") then
+		table.insert(codegen._curr.initialize, init_cmds)
+	elseif(type(input) == "table") then
+		for _,v in ipairs(input) do
+			codegen.initialize(v)
+		end
+	else
+		assert(nil, "initialize takes a string, function, or a table of strings.");
+	end
 end
 
 codegen.init = codegen.initialize
 	--Functions
 	"assert",
 	"collectgarbage",
+	"dofile",
 	"error",
 	"getfenv",
 	"getmetatable",
 	"ipairs",
 	"load",
 	"loadstring",
+	"loadfile",
 	"module",
 	"next",
 	"pairs",
 	os.chdir(oldcwd)
 end
 
+
+-------------------------------------------------------
+-- Code generation functions
+
+--Preprocessing steps
+local function minmax(tbl)
+	local min, max
+	for _,val in ipairs(tbl) do
+		if(not min or min > val) then
+			min = val
+		end
+		
+		if(not max or max < val) then
+			max = val
+		end
+	end
+	return min, max
+end
+
+local function MakeParamIface(suite)
+	local paramIface = {}
+	suite._paramIface = paramIface
+	
+	for name, range in pairs(suite.params) do
+		if(range._rng == "range") then
+			local iface = {}
+			paramIface[name] = iface;
+			
+			local endval = range.first + range.count - 1
+			iface.min = range.first
+			iface.max = endval
+			iface.count = range.count
+			iface.iter = function(self)
+				local state = {}
+				local function iterfunc(state, index)
+					if(not index) then
+						return 1, range.first
+					else
+						if(index >= range.count) then
+							return nil
+						else
+							return index + 1, range.first + index
+						end
+					end
+				end
+				return iterfunc, state
+			end
+		else
+			local iface = {}
+			paramIface[name] = iface;
+
+			local min, max = minmax(range)
+			iface.min = min
+			iface.max = max
+			iface.count = #range
+			iface.iter = function()
+				return ipairs(range)
+			end
+		end
+	end
+
+end
+
+--Headers and includes.
 local function WriteInclude(hFile, hdrsWritten, include)
 	if(type(include) == "table") then
 		for _,file in ipairs(include) do
 	end
 end
 
-local function WriteAndFormatInitStmts(hFile, suite, stmt)
-	--TODO: Load a file if stmt is a file.
-	--TODO: do the formatting.
+-- Parameters.
+local function WriteParamStructs(hFile, suite)
+	hFile:write([[
+struct ParamDefinition
+{
+	int min;
+	int max;
+	int count;
+	int *values;
 	
-	hFile:write("\t\t", stmt:gsub("%\n", "\n\t\t"), "\n\n")
+	boost::iterator_range<const int *> range() const {return boost::iterator_range<const int *>(values, values + count);}
+};]])
+	hFile:write("\n\n");
+	
+	for name, iface in pairs(suite._paramIface) do
+		hFile:write("const int ", gen.GetParamArrayVarname(name), "[] = {")
+		local temp = {}
+		for _, val in iface:iter() do
+			temp[#temp + 1] = val
+		end
+		hFile:write(table.concat(temp, ", "))
+		hFile:write("};\n")
+
+		hFile:write("const ParamDefinition ", gen.GetParamDefVarname(name), " = {")
+		hFile:write(iface.min, ", ", iface.max, ", ", iface.count, ", ")
+		hFile:write(gen.GetParamArrayVarname(name), "};\n\n")
+	end
 end
 
+local function GetStmtString(suite, stmt)
+	if(type(stmt) == "string") then return stmt end
+	if(type(stmt) == "function") then
+		return stmt(suite._paramIface)
+	end
+
+	--TODO: Stmt can be a file. Load it.
+end
+
+-- Initialization statements
+local function WriteAndFormatInitStmts(hFile, suite, stmt)
+	local currStmt = GetStmtString(suite, stmt)
+	
+	for name, range in pairs(suite.params) do
+		currStmt = currStmt:gsub("%$" .. name, gen.GetParamDefVarname(name))
+	end
+	
+	hFile:write("\t\t", currStmt:gsub("%\n", "\n\t\t"), "\n\n")
+end
+
+-- Suite and test classes.
 local specialVarTypes =
 {
 	["gl buffer object"] =
 
 function codegen.gencode()
 	for name, suite in pairs(codegen._suites) do
+		--Preprocessing of suite data.
+		MakeParamIface(suite)
+	
 		local mainFilename = suite._base_dir .. "/" .. gen.GetMainFilename(name)
 
 		local hFile = io.open(mainFilename, "w+")
 		WriteIncludes(hFile, suite)
 		hFile:write("\n\n")
 		
-		--TODO: Write basic parameter data.
+		WriteParamStructs(hFile, suite)
 		
 		WriteSuiteClass(hFile, suite)
 		hFile:write("\n\n")

tests/generate.lua

 	return testName .. "_test"
 end
 
+function gen.GetParamArrayVarname(paramName)
+	return "g_" .. paramName .. "_array"
+end
+
+function gen.GetParamDefVarname(paramName)
+	return "g_" .. paramName .. "_def"
+end
+
 function gen.WritePreamble(hFile, suite_name)
 	hFile:write([=[
 	/* Here's some preamble text. */
 		"<iostream>",
 		"<fstream>",
 		"<boost/range/irange.hpp>",
+		"<boost/range/iterator_range.hpp>",
 		"<boost/foreach.hpp>",
 	}
 end

tests/interleave_arrays/attrib3.vert

+
+#version 330
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec4 color;
+layout(location = 2) in vec2 texCoord;
+//layout(location = 3) in vec3 normal;
+//layout(location = 4) in vec3 tangent;
+//layout(location = 5) in vec3 bitangent;
+//layout(location = 6) in vec4 boneIndices;
+//layout(location = 7) in vec4 boneWeights;
+
+void main()
+{
+	vec4 accum = vec4(0.0);
+	accum += vec4(position, 1.0);
+	accum += vec4(color);
+	accum += vec4(texCoord, 0.0, 1.0);
+//	accum += vec4(normal, 1.0);
+//	accum += vec4(tangent, 1.0);
+//	accum += vec4(bitangent, 1.0);
+//	accum += vec4(boneIndices);
+//	accum += vec4(boneWeights);
+	gl_Position = accum;
+}
+

tests/interleave_arrays/attrib4.vert

+
+#version 330
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec4 color;
+layout(location = 2) in vec2 texCoord;
+layout(location = 3) in vec3 normal;
+//layout(location = 4) in vec3 tangent;
+//layout(location = 5) in vec3 bitangent;
+//layout(location = 6) in vec4 boneIndices;
+//layout(location = 7) in vec4 boneWeights;
+
+void main()
+{
+	vec4 accum = vec4(0.0);
+	accum += vec4(position, 1.0);
+	accum += vec4(color);
+	accum += vec4(texCoord, 0.0, 1.0);
+	accum += vec4(normal, 1.0);
+//	accum += vec4(tangent, 1.0);
+//	accum += vec4(bitangent, 1.0);
+//	accum += vec4(boneIndices);
+//	accum += vec4(boneWeights);
+	gl_Position = accum;
+}
+

tests/interleave_arrays/attrib5.vert

+
+#version 330
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec4 color;
+layout(location = 2) in vec2 texCoord;
+layout(location = 3) in vec3 normal;
+layout(location = 4) in vec3 tangent;
+//layout(location = 5) in vec3 bitangent;
+//layout(location = 6) in vec4 boneIndices;
+//layout(location = 7) in vec4 boneWeights;
+
+void main()
+{
+	vec4 accum = vec4(0.0);
+	accum += vec4(position, 1.0);
+	accum += vec4(color);
+	accum += vec4(texCoord, 0.0, 1.0);
+	accum += vec4(normal, 1.0);
+	accum += vec4(tangent, 1.0);
+//	accum += vec4(bitangent, 1.0);
+//	accum += vec4(boneIndices);
+//	accum += vec4(boneWeights);
+	gl_Position = accum;
+}
+

tests/interleave_arrays/attrib6.vert

+
+#version 330
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec4 color;
+layout(location = 2) in vec2 texCoord;
+layout(location = 3) in vec3 normal;
+layout(location = 4) in vec3 tangent;
+layout(location = 5) in vec3 bitangent;
+//layout(location = 6) in vec4 boneIndices;
+//layout(location = 7) in vec4 boneWeights;
+
+void main()
+{
+	vec4 accum = vec4(0.0);
+	accum += vec4(position, 1.0);
+	accum += vec4(color);
+	accum += vec4(texCoord, 0.0, 1.0);
+	accum += vec4(normal, 1.0);
+	accum += vec4(tangent, 1.0);
+	accum += vec4(bitangent, 1.0);
+//	accum += vec4(boneIndices);
+//	accum += vec4(boneWeights);
+	gl_Position = accum;
+}
+

tests/interleave_arrays/attrib7.vert

+
+#version 330
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec4 color;
+layout(location = 2) in vec2 texCoord;
+layout(location = 3) in vec3 normal;
+layout(location = 4) in vec3 tangent;
+layout(location = 5) in vec3 bitangent;
+layout(location = 6) in vec4 boneIndices;
+//layout(location = 7) in vec4 boneWeights;
+
+void main()
+{
+	vec4 accum = vec4(position, 1.0)
+	+ vec4(color)
+	+ vec4(texCoord, 0.0, 1.0)
+	+ vec4(normal, 1.0)
+	+ vec4(tangent, 1.0)
+	+ vec4(bitangent, 1.0)
+	+ vec4(boneIndices)
+//	+ vec4(boneWeights)
+	;
+	gl_Position = accum;
+}
+

tests/interleave_arrays/attrib8.vert

+
+#version 330
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec4 color;
+layout(location = 2) in vec2 texCoord;
+layout(location = 3) in vec3 normal;
+layout(location = 4) in vec3 tangent;
+layout(location = 5) in vec3 bitangent;
+layout(location = 6) in vec4 boneIndices;
+layout(location = 7) in vec4 boneWeights;
+
+void main()
+{
+	vec4 accum = vec4(0.0);
+	accum += vec4(position, 1.0);
+	accum += vec4(color);
+	accum += vec4(texCoord, 0.0, 1.0);
+	accum += vec4(normal, 1.0);
+	accum += vec4(tangent, 1.0);
+	accum += vec4(bitangent, 1.0);
+	accum += vec4(boneIndices);
+	accum += vec4(boneWeights);
+	gl_Position = accum;
+}
+

tests/interleave_arrays/attrib_data.lua

+
+return {
+	{size = 3,	type = "GL_FLOAT",			norm = "GL_FALSE",	ctype = "GLfloat", initVal = "1.0f", name = "positions"},
+	{size = 4,	type = "GL_UNSIGNED_BYTE",	norm = "GL_TRUE",	ctype = "GLubyte", initVal = "255", name = "color"},
+	{size = 2,	type = "GL_SHORT",			norm = "GL_FALSE",	ctype = "GLshort", initVal = "0f", name = "texCoord"},
+	{size = 3,	type = "GL_FLOAT",			norm = "GL_FALSE",	ctype = "GLfloat", initVal = "1.0f", name = "normal"},
+	{size = 3,	type = "GL_FLOAT",			norm = "GL_FALSE",	ctype = "GLfloat", initVal = "1.0f", name = "tangent"},
+	{size = 3,	type = "GL_FLOAT",			norm = "GL_FALSE",	ctype = "GLfloat", initVal = "1.0f", name = "bitangent"},
+	{size = 4,	type = "GL_UNSIGNED_BYTE",	norm = "GL_FALSE",	ctype = "GLubyte", initVal = "0", name = "boneIndices"},
+	{size = 4,	type = "GL_UNSIGNED_BYTE",	norm = "GL_TRUE",	ctype = "GLubyte", initVal = "1", name = "boneWeights"},
+}

tests/interleave_arrays/frag.frag

+
+#version 330
+
+out vec4 outColor;
+
+void main()
+{
+	outColor = vec4(1.0);
+}

tests/interleave_arrays/suite.lua

 	desc "Determine how much better interleaved arrays perform compared to non-interleaved and multiple-buffered arrays."
 	
 	includes "<boost/range.hpp>"
-	includes "<sstream>"
-	includes "<boost/range/irange.hpp>"
+	includes { "<sstream>", "<boost/range/irange.hpp>" }
 	
 	params
 	{
 	executions(3)
 	
 	variables {
-		test1 = "std::vector<int>",
-		a_buffer = "gl buffer object",
-		buffers = "gl list buffer object",
+		separateArrayBuffers = "gl list buffer object",
+		individualArrayBuffer = "gl buffer object",
+		interleavedArrayBuffers = "gl list buffer object",
+
+		individualOffsets = "std::vector<int>",
+		interleavedStrides = "std::vector<int>",
+		interleavedOffsets = "std::vector<int>",
+
+		attribSize = "std::vector<GLint>",
+		attribType = "std::vector<GLenum>",
+		attribNormalized = "std::vector<GLboolean>",
+
+		programs = "gl list program",
+
+		indexBuffer = "gl buffer object"
 	}
 	
-	initialize [[This is some code]]
-	initialize [[
-Code on multiple lines.
-This should be indented properly.
+	init [[
 
-Here's one empty line. This should remain.]]
+separateArrayBuffers = util::CreateBufferObjects($attribute_count.max);
+glGenBuffers(1, &individualArrayBuffer);
+interleavedArrayBuffers = util::CreateBufferObjects($attribute_count.count);
+glGenBuffers(1, &indexBuffer);
+programs = util::CreatePrograms($attribute_count.count);
+]]
+	local attribute_list = dofile("attrib_data.lua")
+
+	init [[
+attribSize.resize($attribute_count.max);
+attribType.resize($attribute_count.max);
+attribNormalized.resize($attribute_count.max);]]
+	
+	--Generate buffer storage.
+	init(function(paramIface)
+		assert(paramIface.attribute_count.max == #attribute_list, "Need to make sure the attribute list is kept up-to-date with the attribute_count parameter.")
+		
+		local strlist = {}
+
+		strlist[#strlist + 1] = "{\n"
+		
+		for index, typedef in ipairs(attribute_list) do
+			local cindex = index - 1
+			strlist[#strlist + 1] = string.format(
+				"\tattribSize[%i] = %i; attribType[%i] = %s; attribNormalized[%i] = %s;\n",
+				cindex, typedef.size,
+				cindex, typedef.type,
+				cindex, typedef.norm)
+		end
+		
+		strlist[#strlist + 1] = "\n\t//Create separate array buffers\n"
+		
+		for index, typedef in ipairs(attribute_list) do
+			local cindex = index - 1
+			strlist[#strlist + 1] = string.format(
+				"\tstd::vector<%s> %s(attribSize[%i] * $vertex_count.max, %s);\n",
+				typedef.ctype,
+				typedef.name,
+				cindex,
+				typedef.initVal)
+		end
+		
+		strlist[#strlist + 1] = "\n"
+		
+		for index, typedef in ipairs(attribute_list) do
+			local cindex = index - 1
+			strlist[#strlist + 1] = string.format(
+				"\tutil::FillBufferData(separateArrayBuffers[%i], GL_ARRAY_BUFFER, %s, GL_STATIC_DRAW);\n",
+				cindex,
+				typedef.name)
+		end
+		
+		strlist[#strlist + 1] = "\n\t//Create the individual buffer\n"
+		strlist[#strlist + 1] = [[
+	individualOffsets.reserve($attribute_count.max);
+	int totalBufferSize = 0;
+]]
+	
+		for index, typedef in ipairs(attribute_list) do
+			local cindex = index - 1
+			strlist[#strlist + 1] = string.format([[
+	individualOffsets.push_back(totalBufferSize);
+	totalBufferSize += util::CalcOffset(%s);
+]]				,
+				typedef.name)
+		end
+		
+		strlist[#strlist + 1] = "\n"
+
+		
+		strlist[#strlist + 1] = [[
+	glBindBuffer(GL_ARRAY_BUFFER, individualArrayBuffer);
+	glBufferData(GL_ARRAY_BUFFER, totalBufferSize, NULL, GL_STATIC_DRAW);
+]]
+
+		for index, typedef in ipairs(attribute_list) do
+			local cindex = index - 1
+			strlist[#strlist + 1] = string.format(
+				"\tglBufferSubData(GL_ARRAY_BUFFER, individualOffsets[%i], %s.size() * sizeof(%s), &%s[0]);\n",
+				cindex,
+				typedef.name,
+				typedef.ctype,
+				typedef.name)
+		end
+
+		strlist[#strlist + 1] = "\tglBindBuffer(GL_ARRAY_BUFFER, 0);\n"
+		
+		strlist[#strlist + 1] = "\n"
+		
+		
+		strlist[#strlist + 1] = [[
+	//Create the interleaved buffer
+	interleavedStrides.reserve($attribute_count.count);
+	interleavedOffsets.reserve($attribute_count.max);
+	std::vector<char> byteBuffer; //stores a single vertex worth of data.
+]]
+
+		
+		for index = 1, paramIface.attribute_count.min - 1 do
+			local cindex = index - 1
+			strlist[#strlist + 1] = string.format(
+		[[
+	interleavedOffsets.push_back(byteBuffer.size());
+	util::AddToInterleaveBuffer(byteBuffer, %s[0], %s.size() / $vertex_count.max);
+]]			,
+			attribute_list[index].name, attribute_list[index].name)
+		end
+		
+		for index, attrib in paramIface.attribute_count.iter() do
+			local cindex = index - 1
+			strlist[#strlist + 1] = string.format(
+		[[
+	//%i attribs
+	interleavedOffsets.push_back(byteBuffer.size());
+	util::AddToInterleaveBuffer(byteBuffer, %s[0], %s.size() / $vertex_count.max);
+	interleavedStrides.push_back(byteBuffer.size());
+	util::FillBufferData(interleavedArrayBuffers[%i], GL_ARRAY_BUFFER, util::RepeatBuffer(byteBuffer, $vertex_count.max), GL_STATIC_DRAW);
+
+]]			,
+			attrib,
+			attribute_list[attrib].name, attribute_list[attrib].name,
+			cindex)
+		end
+		
+		strlist[#strlist + 1] = "}\n"
+
+		return table.concat(strlist)
+	end)
+	
+	init [[
+std::string fragmentShader;
+{
+	std::ifstream input("frag.frag", std::ios::binary);
+	if(input)
+		fragmentShader.assign(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>());
+}
+
+BOOST_FOREACH(int attrib, $attribute_count.range())
+{
+	std::ostringstream buildName;
+	buildName << "manual\\attrib" << attrib << ".vert";
+	std::string name = buildName.str();
+
+	std::ifstream input(name.c_str(), std::ios::binary);
+	std::string vertexShader((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
+
+	try
+	{
+		glutil::LinkProgram(programs[attrib - $attribute_count.min], vertexShader, fragmentShader);
+	}
+	catch(std::exception &e)
+	{
+		std::cout << e.what() << std::endl;
+		throw;
+	}
+}
+]]
 
 test "arrayIndivSep"
 	desc "Separate arrays, where each array is within its own buffer object."

tests/util/report.cpp

 		const char *suite_desc, const char *gl_version, const char *gl_vendor,
 		const char *gl_renderer ) const
 	{
+		stream.precision(16);
+
 		stream << "return\n{\n";
 
 		OutputNamedValueLua(stream, 1, "name", suite_name);
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.