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