• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
CommandLineCommandLine45 	CommandLine (void)
46 	{
47 	}
48 
49 	string		filename;
50 	string		dstPath;
51 };
52 
getShaderTypeSuffix(const xe::ri::Shader::ShaderType shaderType)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 		case xe::ri::Shader::SHADERTYPE_RAYGEN:				return "rgen";
64 		case xe::ri::Shader::SHADERTYPE_ANY_HIT:			return "ahit";
65 		case xe::ri::Shader::SHADERTYPE_CLOSEST_HIT:		return "chit";
66 		case xe::ri::Shader::SHADERTYPE_MISS:				return "miss";
67 		case xe::ri::Shader::SHADERTYPE_INTERSECTION:		return "sect";
68 		case xe::ri::Shader::SHADERTYPE_CALLABLE:			return "call";
69 		case xe::ri::Shader::SHADERTYPE_TASK:				return "task";
70 		case xe::ri::Shader::SHADERTYPE_MESH:				return "mesh";
71 
72 		default:
73 			throw xe::Error("Invalid shader type");
74 	}
75 }
76 
writeShaderProgram(const CommandLine & cmdLine,const std::string & casePath,const xe::ri::ShaderProgram & shaderProgram,int programNdx)77 static void writeShaderProgram (const CommandLine& cmdLine, const std::string& casePath, const xe::ri::ShaderProgram& shaderProgram, int programNdx)
78 {
79 	const string basePath = string(de::FilePath::join(cmdLine.dstPath, casePath).getPath()) + "." + de::toString(programNdx);
80 
81 	for (int shaderNdx = 0; shaderNdx < shaderProgram.shaders.getNumItems(); shaderNdx++)
82 	{
83 		const xe::ri::Shader&	shader		= dynamic_cast<const xe::ri::Shader&>(shaderProgram.shaders.getItem(shaderNdx));
84 		const string			shaderPath	= basePath + "." + getShaderTypeSuffix(shader.shaderType);
85 
86 		if (de::FilePath(shaderPath).exists())
87 			throw xe::Error("File '" + shaderPath + "' exists already");
88 
89 		{
90 			std::ofstream out(shaderPath.c_str(), std::ifstream::binary|std::ifstream::out);
91 
92 			if (!out.good())
93 				throw xe::Error("Failed to open '" + shaderPath + "'");
94 
95 			out.write(shader.source.source.c_str(), shader.source.source.size());
96 		}
97 	}
98 }
99 
100 struct StackEntry
101 {
102 	const xe::ri::List*		list;
103 	int						curNdx;
104 
StackEntryStackEntry105 	explicit StackEntry (const xe::ri::List* list_) : list(list_), curNdx(0) {}
106 };
107 
extractShaderPrograms(const CommandLine & cmdLine,const std::string & casePath,const xe::TestCaseResult & result)108 static void extractShaderPrograms (const CommandLine& cmdLine, const std::string& casePath, const xe::TestCaseResult& result)
109 {
110 	vector<StackEntry>	itemListStack;
111 	int					programNdx		= 0;
112 
113 	itemListStack.push_back(StackEntry(&result.resultItems));
114 
115 	while (!itemListStack.empty())
116 	{
117 		StackEntry& curEntry = itemListStack.back();
118 
119 		if (curEntry.curNdx < curEntry.list->getNumItems())
120 		{
121 			const xe::ri::Item&	curItem	= curEntry.list->getItem(curEntry.curNdx);
122 			curEntry.curNdx += 1;
123 
124 			if (curItem.getType() == xe::ri::TYPE_SHADERPROGRAM)
125 			{
126 				writeShaderProgram(cmdLine, casePath, static_cast<const xe::ri::ShaderProgram&>(curItem), programNdx);
127 				programNdx += 1;
128 			}
129 			else if (curItem.getType() == xe::ri::TYPE_SECTION)
130 				itemListStack.push_back(StackEntry(&static_cast<const xe::ri::Section&>(curItem).items));
131 		}
132 		else
133 			itemListStack.pop_back();
134 	}
135 
136 	if (programNdx == 0)
137 		std::cout << "WARNING: no shader programs found in '" << casePath << "'\n";
138 }
139 
140 class ShaderProgramExtractHandler : public xe::TestLogHandler
141 {
142 public:
ShaderProgramExtractHandler(const CommandLine & cmdLine)143 	ShaderProgramExtractHandler (const CommandLine& cmdLine)
144 		: m_cmdLine(cmdLine)
145 	{
146 	}
147 
setSessionInfo(const xe::SessionInfo &)148 	void setSessionInfo (const xe::SessionInfo&)
149 	{
150 		// Ignored.
151 	}
152 
startTestCaseResult(const char * casePath)153 	xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
154 	{
155 		return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
156 	}
157 
testCaseResultUpdated(const xe::TestCaseResultPtr &)158 	void testCaseResultUpdated (const xe::TestCaseResultPtr&)
159 	{
160 		// Ignored.
161 	}
162 
testCaseResultComplete(const xe::TestCaseResultPtr & caseData)163 	void testCaseResultComplete (const xe::TestCaseResultPtr& caseData)
164 	{
165 		if (caseData->getDataSize() > 0)
166 		{
167 			xe::TestCaseResult					fullResult;
168 			xe::TestResultParser::ParseResult	parseResult;
169 
170 			m_testResultParser.init(&fullResult);
171 			parseResult = m_testResultParser.parse(caseData->getData(), caseData->getDataSize());
172 			DE_UNREF(parseResult);
173 
174 			extractShaderPrograms(m_cmdLine, caseData->getTestCasePath(), fullResult);
175 		}
176 	}
177 
178 private:
179 	const CommandLine&		m_cmdLine;
180 	xe::TestResultParser	m_testResultParser;
181 };
182 
extractShaderProgramsFromLogFile(const CommandLine & cmdLine)183 static void extractShaderProgramsFromLogFile (const CommandLine& cmdLine)
184 {
185 	std::ifstream					in				(cmdLine.filename.c_str(), std::ifstream::binary|std::ifstream::in);
186 	ShaderProgramExtractHandler		resultHandler	(cmdLine);
187 	xe::TestLogParser				parser			(&resultHandler);
188 	deUint8							buf				[1024];
189 	int								numRead			= 0;
190 
191 	if (!in.good())
192 		throw std::runtime_error(string("Failed to open '") + cmdLine.filename + "'");
193 
194 	for (;;)
195 	{
196 		in.read((char*)&buf[0], DE_LENGTH_OF_ARRAY(buf));
197 		numRead = (int)in.gcount();
198 
199 		if (numRead <= 0)
200 			break;
201 
202 		parser.parse(&buf[0], numRead);
203 	}
204 
205 	in.close();
206 }
207 
printHelp(const char * binName)208 static void printHelp (const char* binName)
209 {
210 	printf("%s: [filename] [dst path (optional)]\n", binName);
211 }
212 
parseCommandLine(CommandLine & cmdLine,int argc,const char * const * argv)213 static bool parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
214 {
215 	for (int argNdx = 1; argNdx < argc; argNdx++)
216 	{
217 		const char* arg = argv[argNdx];
218 
219 		if (!deStringBeginsWith(arg, "--"))
220 		{
221 			if (cmdLine.filename.empty())
222 				cmdLine.filename = arg;
223 			else if (cmdLine.dstPath.empty())
224 				cmdLine.dstPath = arg;
225 			else
226 				return false;
227 		}
228 		else
229 			return false;
230 	}
231 
232 	if (cmdLine.filename.empty())
233 		return false;
234 
235 	return true;
236 }
237 
main(int argc,const char * const * argv)238 int main (int argc, const char* const* argv)
239 {
240 	try
241 	{
242 		CommandLine cmdLine;
243 
244 		if (!parseCommandLine(cmdLine, argc, argv))
245 		{
246 			printHelp(argv[0]);
247 			return -1;
248 		}
249 
250 		extractShaderProgramsFromLogFile(cmdLine);
251 	}
252 	catch (const std::exception& e)
253 	{
254 		printf("FATAL ERROR: %s\n", e.what());
255 		return -1;
256 	}
257 
258 	return 0;
259 }
260