Home | History | Annotate | Download | only in tools
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program Test Executor
      3  * ------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Extract shader programs from log.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "xeTestLogParser.hpp"
     25 #include "xeTestResultParser.hpp"
     26 #include "deFilePath.hpp"
     27 #include "deStringUtil.hpp"
     28 #include "deString.h"
     29 
     30 #include <vector>
     31 #include <string>
     32 #include <cstdio>
     33 #include <cstdlib>
     34 #include <fstream>
     35 #include <iostream>
     36 #include <stdexcept>
     37 
     38 using std::vector;
     39 using std::string;
     40 using std::set;
     41 using std::map;
     42 
     43 struct CommandLine
     44 {
     45 	CommandLine (void)
     46 	{
     47 	}
     48 
     49 	string		filename;
     50 	string		dstPath;
     51 };
     52 
     53 static const char* getShaderTypeSuffix (const xe::ri::Shader::ShaderType shaderType)
     54 {
     55 	switch (shaderType)
     56 	{
     57 		case xe::ri::Shader::SHADERTYPE_VERTEX:				return "vert";
     58 		case xe::ri::Shader::SHADERTYPE_FRAGMENT:			return "frag";
     59 		case xe::ri::Shader::SHADERTYPE_GEOMETRY:			return "geom";
     60 		case xe::ri::Shader::SHADERTYPE_TESS_CONTROL:		return "tesc";
     61 		case xe::ri::Shader::SHADERTYPE_TESS_EVALUATION:	return "tese";
     62 		case xe::ri::Shader::SHADERTYPE_COMPUTE:			return "comp";
     63 		default:
     64 			throw xe::Error("Invalid shader type");
     65 	}
     66 }
     67 
     68 static void writeShaderProgram (const CommandLine& cmdLine, const std::string& casePath, const xe::ri::ShaderProgram& shaderProgram, int programNdx)
     69 {
     70 	const string basePath = string(de::FilePath::join(cmdLine.dstPath, casePath).getPath()) + "." + de::toString(programNdx);
     71 
     72 	for (int shaderNdx = 0; shaderNdx < shaderProgram.shaders.getNumItems(); shaderNdx++)
     73 	{
     74 		const xe::ri::Shader&	shader		= dynamic_cast<const xe::ri::Shader&>(shaderProgram.shaders.getItem(shaderNdx));
     75 		const string			shaderPath	= basePath + "." + getShaderTypeSuffix(shader.shaderType);
     76 
     77 		if (de::FilePath(shaderPath).exists())
     78 			throw xe::Error("File '" + shaderPath + "' exists already");
     79 
     80 		{
     81 			std::ofstream out(shaderPath.c_str(), std::ifstream::binary|std::ifstream::out);
     82 
     83 			if (!out.good())
     84 				throw xe::Error("Failed to open '" + shaderPath + "'");
     85 
     86 			out.write(shader.source.source.c_str(), shader.source.source.size());
     87 		}
     88 	}
     89 }
     90 
     91 struct StackEntry
     92 {
     93 	const xe::ri::List*		list;
     94 	int						curNdx;
     95 
     96 	explicit StackEntry (const xe::ri::List* list_) : list(list_), curNdx(0) {}
     97 };
     98 
     99 static void extractShaderPrograms (const CommandLine& cmdLine, const std::string& casePath, const xe::TestCaseResult& result)
    100 {
    101 	vector<StackEntry>	itemListStack;
    102 	int					programNdx		= 0;
    103 
    104 	itemListStack.push_back(StackEntry(&result.resultItems));
    105 
    106 	while (!itemListStack.empty())
    107 	{
    108 		StackEntry& curEntry = itemListStack.back();
    109 
    110 		if (curEntry.curNdx < curEntry.list->getNumItems())
    111 		{
    112 			const xe::ri::Item&	curItem	= curEntry.list->getItem(curEntry.curNdx);
    113 			curEntry.curNdx += 1;
    114 
    115 			if (curItem.getType() == xe::ri::TYPE_SHADERPROGRAM)
    116 			{
    117 				writeShaderProgram(cmdLine, casePath, static_cast<const xe::ri::ShaderProgram&>(curItem), programNdx);
    118 				programNdx += 1;
    119 			}
    120 			else if (curItem.getType() == xe::ri::TYPE_SECTION)
    121 				itemListStack.push_back(StackEntry(&static_cast<const xe::ri::Section&>(curItem).items));
    122 		}
    123 		else
    124 			itemListStack.pop_back();
    125 	}
    126 
    127 	if (programNdx == 0)
    128 		std::cout << "WARNING: no shader programs found in '" << casePath << "'\n";
    129 }
    130 
    131 class ShaderProgramExtractHandler : public xe::TestLogHandler
    132 {
    133 public:
    134 	ShaderProgramExtractHandler (const CommandLine& cmdLine)
    135 		: m_cmdLine(cmdLine)
    136 	{
    137 	}
    138 
    139 	void setSessionInfo (const xe::SessionInfo&)
    140 	{
    141 		// Ignored.
    142 	}
    143 
    144 	xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
    145 	{
    146 		return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
    147 	}
    148 
    149 	void testCaseResultUpdated (const xe::TestCaseResultPtr&)
    150 	{
    151 		// Ignored.
    152 	}
    153 
    154 	void testCaseResultComplete (const xe::TestCaseResultPtr& caseData)
    155 	{
    156 		if (caseData->getDataSize() > 0)
    157 		{
    158 			xe::TestCaseResult					fullResult;
    159 			xe::TestResultParser::ParseResult	parseResult;
    160 
    161 			m_testResultParser.init(&fullResult);
    162 			parseResult = m_testResultParser.parse(caseData->getData(), caseData->getDataSize());
    163 			DE_UNREF(parseResult);
    164 
    165 			extractShaderPrograms(m_cmdLine, caseData->getTestCasePath(), fullResult);
    166 		}
    167 	}
    168 
    169 private:
    170 	const CommandLine&		m_cmdLine;
    171 	xe::TestResultParser	m_testResultParser;
    172 };
    173 
    174 static void extractShaderProgramsFromLogFile (const CommandLine& cmdLine)
    175 {
    176 	std::ifstream					in				(cmdLine.filename.c_str(), std::ifstream::binary|std::ifstream::in);
    177 	ShaderProgramExtractHandler		resultHandler	(cmdLine);
    178 	xe::TestLogParser				parser			(&resultHandler);
    179 	deUint8							buf				[1024];
    180 	int								numRead			= 0;
    181 
    182 	if (!in.good())
    183 		throw std::runtime_error(string("Failed to open '") + cmdLine.filename + "'");
    184 
    185 	for (;;)
    186 	{
    187 		in.read((char*)&buf[0], DE_LENGTH_OF_ARRAY(buf));
    188 		numRead = (int)in.gcount();
    189 
    190 		if (numRead <= 0)
    191 			break;
    192 
    193 		parser.parse(&buf[0], numRead);
    194 	}
    195 
    196 	in.close();
    197 }
    198 
    199 static void printHelp (const char* binName)
    200 {
    201 	printf("%s: [filename] [dst path (optional)]\n", binName);
    202 }
    203 
    204 static bool parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
    205 {
    206 	for (int argNdx = 1; argNdx < argc; argNdx++)
    207 	{
    208 		const char* arg = argv[argNdx];
    209 
    210 		if (!deStringBeginsWith(arg, "--"))
    211 		{
    212 			if (cmdLine.filename.empty())
    213 				cmdLine.filename = arg;
    214 			else if (cmdLine.dstPath.empty())
    215 				cmdLine.dstPath = arg;
    216 			else
    217 				return false;
    218 		}
    219 		else
    220 			return false;
    221 	}
    222 
    223 	if (cmdLine.filename.empty())
    224 		return false;
    225 
    226 	return true;
    227 }
    228 
    229 int main (int argc, const char* const* argv)
    230 {
    231 	try
    232 	{
    233 		CommandLine cmdLine;
    234 
    235 		if (!parseCommandLine(cmdLine, argc, argv))
    236 		{
    237 			printHelp(argv[0]);
    238 			return -1;
    239 		}
    240 
    241 		extractShaderProgramsFromLogFile(cmdLine);
    242 	}
    243 	catch (const std::exception& e)
    244 	{
    245 		printf("FATAL ERROR: %s\n", e.what());
    246 		return -1;
    247 	}
    248 
    249 	return 0;
    250 }
    251