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