Path: blob/main_old/src/tests/deqp_support/angle_deqp_gtest.cpp
1693 views
//1// Copyright 2015 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// angle_deqp_gtest:6// dEQP and GoogleTest integration logic. Calls through to the random7// order executor.89#include <stdint.h>10#include <array>11#include <fstream>1213#include <gtest/gtest.h>1415#include "angle_deqp_libtester.h"16#include "common/Optional.h"17#include "common/angleutils.h"18#include "common/debug.h"19#include "common/platform.h"20#include "common/string_utils.h"21#include "common/system_utils.h"22#include "platform/PlatformMethods.h"23#include "tests/test_utils/runner/TestSuite.h"24#include "util/OSWindow.h"25#include "util/test_utils.h"2627namespace angle28{29namespace30{31#if !defined(NDEBUG)32constexpr bool kIsDebug = true;33#else34constexpr bool kIsDebug = false;35#endif // !defined(NDEBUG)3637bool gGlobalError = false;38bool gExpectError = false;39bool gVerbose = false;4041// Set this to true temporarily to enable image logging in release. Useful for diagnosing errors.42bool gLogImages = kIsDebug;4344constexpr char kInfoTag[] = "*RESULT";4546void HandlePlatformError(PlatformMethods *platform, const char *errorMessage)47{48if (!gExpectError)49{50FAIL() << errorMessage;51}52gGlobalError = true;53}5455std::string DrawElementsToGoogleTestName(const std::string &dEQPName)56{57std::string gTestName = dEQPName.substr(dEQPName.find('.') + 1);58std::replace(gTestName.begin(), gTestName.end(), '.', '_');5960// Occurs in some luminance tests61gTestName.erase(std::remove(gTestName.begin(), gTestName.end(), '-'), gTestName.end());62return gTestName;63}6465// Relative to the ANGLE root folder.66constexpr char kCTSRootPath[] = "third_party/VK-GL-CTS/src/";67constexpr char kSupportPath[] = "src/tests/deqp_support/";6869#define OPENGL_CTS_DIR(PATH) "external/openglcts/data/mustpass/gles/" PATH7071const char *gCaseListFiles[] = {72OPENGL_CTS_DIR("aosp_mustpass/master/gles2-master.txt"),73OPENGL_CTS_DIR("aosp_mustpass/master/gles3-master.txt"),74OPENGL_CTS_DIR("aosp_mustpass/master/gles31-master.txt"),75"/android/cts/master/egl-master.txt",76OPENGL_CTS_DIR("khronos_mustpass/master/gles2-khr-master.txt"),77OPENGL_CTS_DIR("khronos_mustpass/master/gles3-khr-master.txt"),78OPENGL_CTS_DIR("khronos_mustpass/master/gles31-khr-master.txt"),79OPENGL_CTS_DIR("khronos_mustpass/master/gles32-khr-master.txt"),80OPENGL_CTS_DIR("aosp_mustpass/master/gles3-rotate-landscape.txt"),81OPENGL_CTS_DIR("aosp_mustpass/master/gles3-rotate-reverse-portrait.txt"),82OPENGL_CTS_DIR("aosp_mustpass/master/gles3-rotate-reverse-landscape.txt"),83OPENGL_CTS_DIR("aosp_mustpass/master/gles31-rotate-landscape.txt"),84OPENGL_CTS_DIR("aosp_mustpass/master/gles31-rotate-reverse-portrait.txt"),85OPENGL_CTS_DIR("aosp_mustpass/master/gles31-rotate-reverse-landscape.txt"),86};8788#undef OPENGL_CTS_DIR8990const char *gTestExpectationsFiles[] = {91"deqp_gles2_test_expectations.txt", "deqp_gles3_test_expectations.txt",92"deqp_gles31_test_expectations.txt", "deqp_egl_test_expectations.txt",93"deqp_khr_gles2_test_expectations.txt", "deqp_khr_gles3_test_expectations.txt",94"deqp_khr_gles31_test_expectations.txt", "deqp_khr_gles32_test_expectations.txt",95"deqp_gles3_rotate_test_expectations.txt", "deqp_gles3_rotate_test_expectations.txt",96"deqp_gles3_rotate_test_expectations.txt", "deqp_gles31_rotate_test_expectations.txt",97"deqp_gles31_rotate_test_expectations.txt", "deqp_gles31_rotate_test_expectations.txt",98};99100using APIInfo = std::pair<const char *, GPUTestConfig::API>;101102constexpr APIInfo kEGLDisplayAPIs[] = {103{"angle-d3d9", GPUTestConfig::kAPID3D9},104{"angle-d3d11", GPUTestConfig::kAPID3D11},105{"angle-d3d11-ref", GPUTestConfig::kAPID3D11},106{"angle-gl", GPUTestConfig::kAPIGLDesktop},107{"angle-gles", GPUTestConfig::kAPIGLES},108{"angle-metal", GPUTestConfig::kAPIMetal},109{"angle-null", GPUTestConfig::kAPIUnknown},110{"angle-swiftshader", GPUTestConfig::kAPISwiftShader},111{"angle-vulkan", GPUTestConfig::kAPIVulkan},112};113114constexpr char kdEQPEGLString[] = "--deqp-egl-display-type=";115constexpr char kANGLEEGLString[] = "--use-angle=";116constexpr char kANGLEPreRotation[] = "--emulated-pre-rotation=";117constexpr char kANGLEDirectSPIRVGen[] = "--direct-spirv-gen";118constexpr char kdEQPCaseString[] = "--deqp-case=";119constexpr char kVerboseString[] = "--verbose";120constexpr char kRenderDocString[] = "--renderdoc";121122std::array<char, 500> gCaseStringBuffer;123124// For angle_deqp_gles3*_rotateN_tests, default gOptions.preRotation to N.125#if defined(ANGLE_DEQP_GLES3_ROTATE90_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE90_TESTS)126constexpr uint32_t kDefaultPreRotation = 90;127#elif defined(ANGLE_DEQP_GLES3_ROTATE180_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE180_TESTS)128constexpr uint32_t kDefaultPreRotation = 180;129#elif defined(ANGLE_DEQP_GLES3_ROTATE270_TESTS) || defined(ANGLE_DEQP_GLES31_ROTATE270_TESTS)130constexpr uint32_t kDefaultPreRotation = 270;131#else132constexpr uint32_t kDefaultPreRotation = 0;133#endif134135const APIInfo *gInitAPI = nullptr;136dEQPOptions gOptions = {137kDefaultPreRotation, // preRotation138false, // enableDirectSPIRVGen139false, // enableRenderDocCapture140};141142constexpr const char gdEQPEGLConfigNameString[] = "--deqp-gl-config-name=";143constexpr const char gdEQPLogImagesString[] = "--deqp-log-images=";144145// Default the config to RGBA8146const char *gEGLConfigName = "rgba8888d24s8";147148// Returns the default API for a platform.149const char *GetDefaultAPIName()150{151#if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX) || \152defined(ANGLE_PLATFORM_WINDOWS)153return "angle-vulkan";154#elif defined(ANGLE_PLATFORM_APPLE)155return "angle-gl";156#else157# error Unknown platform.158#endif159}160161const APIInfo *FindAPIInfo(const std::string &arg)162{163for (auto &displayAPI : kEGLDisplayAPIs)164{165if (arg == displayAPI.first)166{167return &displayAPI;168}169}170return nullptr;171}172173const APIInfo *GetDefaultAPIInfo()174{175const APIInfo *defaultInfo = FindAPIInfo(GetDefaultAPIName());176ASSERT(defaultInfo);177return defaultInfo;178}179180std::string GetTestStatLine(const std::string &key, const std::string &value)181{182return std::string(kInfoTag) + ": " + key + ": " + value + "\n";183}184185// During the CaseList initialization we cannot use the GTEST FAIL macro to quit the program because186// the initialization is called outside of tests the first time.187void Die()188{189exit(EXIT_FAILURE);190}191192Optional<std::string> FindFileFromPath(const char *dirPath, const char *filePath)193{194std::stringstream strstr;195strstr << dirPath << filePath;196std::string path = strstr.str();197198constexpr size_t kMaxFoundPathLen = 1000;199char foundPath[kMaxFoundPathLen];200if (angle::FindTestDataPath(path.c_str(), foundPath, kMaxFoundPathLen))201{202return std::string(foundPath);203}204205return Optional<std::string>::Invalid();206}207208Optional<std::string> FindCaseListPath(size_t testModuleIndex)209{210return FindFileFromPath(kCTSRootPath, gCaseListFiles[testModuleIndex]);211}212213Optional<std::string> FindTestExpectationsPath(size_t testModuleIndex)214{215return FindFileFromPath(kSupportPath, gTestExpectationsFiles[testModuleIndex]);216}217218class dEQPCaseList219{220public:221dEQPCaseList(size_t testModuleIndex);222223struct CaseInfo224{225CaseInfo(const std::string &dEQPName, const std::string &gTestName, int expectation)226: mDEQPName(dEQPName), mGTestName(gTestName), mExpectation(expectation)227{}228229std::string mDEQPName;230std::string mGTestName;231int mExpectation;232};233234void initialize();235236const CaseInfo &getCaseInfo(size_t caseIndex) const237{238ASSERT(mInitialized);239ASSERT(caseIndex < mCaseInfoList.size());240return mCaseInfoList[caseIndex];241}242243size_t numCases() const244{245ASSERT(mInitialized);246return mCaseInfoList.size();247}248249private:250std::vector<CaseInfo> mCaseInfoList;251size_t mTestModuleIndex;252bool mInitialized = false;253};254255dEQPCaseList::dEQPCaseList(size_t testModuleIndex) : mTestModuleIndex(testModuleIndex) {}256257void dEQPCaseList::initialize()258{259if (mInitialized)260{261return;262}263264mInitialized = true;265266Optional<std::string> caseListPath = FindCaseListPath(mTestModuleIndex);267if (!caseListPath.valid())268{269std::cerr << "Failed to find case list file." << std::endl;270Die();271}272273Optional<std::string> testExpectationsPath = FindTestExpectationsPath(mTestModuleIndex);274if (!testExpectationsPath.valid())275{276std::cerr << "Failed to find test expectations file." << std::endl;277Die();278}279280GPUTestConfig::API api = GetDefaultAPIInfo()->second;281// Set the API from the command line, or using the default platform API.282if (gInitAPI)283{284api = gInitAPI->second;285}286287GPUTestConfig testConfig =288GPUTestConfig(api, gOptions.preRotation, gOptions.enableDirectSPIRVGen);289290#if !defined(ANGLE_PLATFORM_ANDROID)291// Note: These prints mess up parsing of test list when running on Android.292std::cout << "Using test config with:" << std::endl;293for (uint32_t condition : testConfig.getConditions())294{295const char *name = GetConditionName(condition);296if (name != nullptr)297{298std::cout << " " << name << std::endl;299}300}301#endif302303TestSuite *testSuite = TestSuite::GetInstance();304305if (!testSuite->loadTestExpectationsFromFileWithConfig(testConfig,306testExpectationsPath.value()))307{308Die();309}310311std::ifstream caseListStream(caseListPath.value());312if (caseListStream.fail())313{314std::cerr << "Failed to load the case list." << std::endl;315Die();316}317318while (!caseListStream.eof())319{320std::string inString;321std::getline(caseListStream, inString);322323std::string dEQPName = TrimString(inString, kWhitespaceASCII);324if (dEQPName.empty())325continue;326std::string gTestName = DrawElementsToGoogleTestName(dEQPName);327if (gTestName.empty())328continue;329330int expectation = testSuite->getTestExpectation(dEQPName);331mCaseInfoList.push_back(CaseInfo(dEQPName, gTestName, expectation));332}333334if (testSuite->logAnyUnusedTestExpectations())335{336Die();337}338}339340template <size_t TestModuleIndex>341class dEQPTest : public testing::TestWithParam<size_t>342{343public:344static testing::internal::ParamGenerator<size_t> GetTestingRange()345{346return testing::Range<size_t>(0, GetCaseList().numCases());347}348349static std::string GetCaseGTestName(size_t caseIndex)350{351const auto &caseInfo = GetCaseList().getCaseInfo(caseIndex);352return caseInfo.mGTestName;353}354355static const dEQPCaseList &GetCaseList()356{357static dEQPCaseList sCaseList(TestModuleIndex);358sCaseList.initialize();359return sCaseList;360}361362static void SetUpTestCase();363static void TearDownTestCase();364365protected:366void runTest() const367{368if (sTestExceptionCount > 1)369{370std::cout << "Too many exceptions, skipping all remaining tests." << std::endl;371return;372}373374const auto &caseInfo = GetCaseList().getCaseInfo(GetParam());375std::cout << caseInfo.mDEQPName << std::endl;376377// Tests that crash exit the harness before collecting the result. To tally the number of378// crashed tests we track how many tests we "tried" to run.379sTestCount++;380381if (caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestSkip)382{383sSkippedTestCount++;384std::cout << "Test skipped.\n";385return;386}387388TestSuite *testSuite = TestSuite::GetInstance();389testSuite->maybeUpdateTestTimeout(caseInfo.mExpectation);390391gExpectError = (caseInfo.mExpectation != GPUTestExpectationsParser::kGpuTestPass);392dEQPTestResult result = deqp_libtester_run(caseInfo.mDEQPName.c_str());393394bool testSucceeded = countTestResultAndReturnSuccess(result);395396// Check the global error flag for unexpected platform errors.397if (gGlobalError)398{399testSucceeded = false;400gGlobalError = false;401}402403if (caseInfo.mExpectation == GPUTestExpectationsParser::kGpuTestPass)404{405EXPECT_TRUE(testSucceeded);406407if (!testSucceeded)408{409sUnexpectedFailed.push_back(caseInfo.mDEQPName);410}411}412else if (testSucceeded)413{414std::cout << "Test expected to fail but passed!" << std::endl;415sUnexpectedPasses.push_back(caseInfo.mDEQPName);416}417}418419bool countTestResultAndReturnSuccess(dEQPTestResult result) const420{421switch (result)422{423case dEQPTestResult::Pass:424sPassedTestCount++;425return true;426case dEQPTestResult::Fail:427sFailedTestCount++;428return false;429case dEQPTestResult::NotSupported:430sNotSupportedTestCount++;431return true;432case dEQPTestResult::Exception:433sTestExceptionCount++;434return false;435default:436std::cerr << "Unexpected test result code: " << static_cast<int>(result) << "\n";437return false;438}439}440441static void PrintTestStats()442{443uint32_t crashedCount =444sTestCount - (sPassedTestCount + sFailedTestCount + sNotSupportedTestCount +445sTestExceptionCount + sSkippedTestCount);446447std::cout << GetTestStatLine("Total", std::to_string(sTestCount));448std::cout << GetTestStatLine("Passed", std::to_string(sPassedTestCount));449std::cout << GetTestStatLine("Failed", std::to_string(sFailedTestCount));450std::cout << GetTestStatLine("Skipped", std::to_string(sSkippedTestCount));451std::cout << GetTestStatLine("Not Supported", std::to_string(sNotSupportedTestCount));452std::cout << GetTestStatLine("Exception", std::to_string(sTestExceptionCount));453std::cout << GetTestStatLine("Crashed", std::to_string(crashedCount));454455if (!sUnexpectedPasses.empty())456{457std::cout << GetTestStatLine("Unexpected Passed Count",458std::to_string(sUnexpectedPasses.size()));459for (const std::string &testName : sUnexpectedPasses)460{461std::cout << GetTestStatLine("Unexpected Passed Tests", testName);462}463}464465if (!sUnexpectedFailed.empty())466{467std::cout << GetTestStatLine("Unexpected Failed Count",468std::to_string(sUnexpectedFailed.size()));469for (const std::string &testName : sUnexpectedFailed)470{471std::cout << GetTestStatLine("Unexpected Failed Tests", testName);472}473}474}475476static uint32_t sTestCount;477static uint32_t sPassedTestCount;478static uint32_t sFailedTestCount;479static uint32_t sTestExceptionCount;480static uint32_t sNotSupportedTestCount;481static uint32_t sSkippedTestCount;482483static std::vector<std::string> sUnexpectedFailed;484static std::vector<std::string> sUnexpectedPasses;485};486487template <size_t TestModuleIndex>488uint32_t dEQPTest<TestModuleIndex>::sTestCount = 0;489template <size_t TestModuleIndex>490uint32_t dEQPTest<TestModuleIndex>::sPassedTestCount = 0;491template <size_t TestModuleIndex>492uint32_t dEQPTest<TestModuleIndex>::sFailedTestCount = 0;493template <size_t TestModuleIndex>494uint32_t dEQPTest<TestModuleIndex>::sTestExceptionCount = 0;495template <size_t TestModuleIndex>496uint32_t dEQPTest<TestModuleIndex>::sNotSupportedTestCount = 0;497template <size_t TestModuleIndex>498uint32_t dEQPTest<TestModuleIndex>::sSkippedTestCount = 0;499template <size_t TestModuleIndex>500std::vector<std::string> dEQPTest<TestModuleIndex>::sUnexpectedFailed;501template <size_t TestModuleIndex>502std::vector<std::string> dEQPTest<TestModuleIndex>::sUnexpectedPasses;503504// static505template <size_t TestModuleIndex>506void dEQPTest<TestModuleIndex>::SetUpTestCase()507{508sPassedTestCount = 0;509sFailedTestCount = 0;510sNotSupportedTestCount = 0;511sTestExceptionCount = 0;512sTestCount = 0;513sSkippedTestCount = 0;514sUnexpectedPasses.clear();515sUnexpectedFailed.clear();516517std::vector<const char *> argv;518519// Reserve one argument for the binary name.520argv.push_back("");521522// Add init api.523const char *targetApi = gInitAPI ? gInitAPI->first : GetDefaultAPIName();524std::string apiArgString = std::string(kdEQPEGLString) + targetApi;525argv.push_back(apiArgString.c_str());526527// Add config name528const char *targetConfigName = gEGLConfigName;529std::string configArgString = std::string(gdEQPEGLConfigNameString) + targetConfigName;530argv.push_back(configArgString.c_str());531532// Hide SwiftShader window to prevent a race with Xvfb causing hangs on test bots533if (gInitAPI && gInitAPI->second == GPUTestConfig::kAPISwiftShader)534{535argv.push_back("--deqp-visibility=hidden");536}537538TestSuite *testSuite = TestSuite::GetInstance();539540std::stringstream logNameStream;541logNameStream << "TestResults";542if (testSuite->getBatchId() != -1)543{544logNameStream << "-Batch" << std::setfill('0') << std::setw(3) << testSuite->getBatchId();545}546logNameStream << ".qpa";547548std::stringstream logArgStream;549logArgStream << "--deqp-log-filename=" << testSuite->addTestArtifact(logNameStream.str());550551std::string logNameString = logArgStream.str();552argv.push_back(logNameString.c_str());553554if (!gLogImages)555{556argv.push_back("--deqp-log-images=disable");557}558559// Flushing during multi-process execution punishes HDDs. http://anglebug.com/5157560if (testSuite->getBatchId() != -1)561{562argv.push_back("--deqp-log-flush=disable");563}564565// Init the platform.566if (!deqp_libtester_init_platform(static_cast<int>(argv.size()), argv.data(),567reinterpret_cast<void *>(&HandlePlatformError), gOptions))568{569std::cout << "Aborting test due to dEQP initialization error." << std::endl;570exit(1);571}572}573574// static575template <size_t TestModuleIndex>576void dEQPTest<TestModuleIndex>::TearDownTestCase()577{578PrintTestStats();579deqp_libtester_shutdown_platform();580}581582#define ANGLE_INSTANTIATE_DEQP_TEST_CASE(API, N) \583class dEQP : public dEQPTest<N> \584{}; \585TEST_P(dEQP, API) { runTest(); } \586\587INSTANTIATE_TEST_SUITE_P(, dEQP, dEQP::GetTestingRange(), \588[](const testing::TestParamInfo<size_t> &info) { \589return dEQP::GetCaseGTestName(info.param); \590})591592#ifdef ANGLE_DEQP_GLES2_TESTS593ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES2, 0);594#endif595596#ifdef ANGLE_DEQP_GLES3_TESTS597ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3, 1);598#endif599600#ifdef ANGLE_DEQP_GLES31_TESTS601ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31, 2);602#endif603604#ifdef ANGLE_DEQP_EGL_TESTS605ANGLE_INSTANTIATE_DEQP_TEST_CASE(EGL, 3);606#endif607608#ifdef ANGLE_DEQP_KHR_GLES2_TESTS609ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES2, 4);610#endif611612#ifdef ANGLE_DEQP_KHR_GLES3_TESTS613ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES3, 5);614#endif615616#ifdef ANGLE_DEQP_KHR_GLES31_TESTS617ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES31, 6);618#endif619620#ifdef ANGLE_DEQP_KHR_GLES32_TESTS621ANGLE_INSTANTIATE_DEQP_TEST_CASE(KHR_GLES32, 7);622#endif623624#ifdef ANGLE_DEQP_GLES3_ROTATE90_TESTS625ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE90, 8);626#endif627628#ifdef ANGLE_DEQP_GLES3_ROTATE180_TESTS629ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE180, 9);630#endif631632#ifdef ANGLE_DEQP_GLES3_ROTATE270_TESTS633ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES3_ROTATE270, 10);634#endif635636#ifdef ANGLE_DEQP_GLES31_ROTATE90_TESTS637ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE90, 11);638#endif639640#ifdef ANGLE_DEQP_GLES31_ROTATE180_TESTS641ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE180, 12);642#endif643644#ifdef ANGLE_DEQP_GLES31_ROTATE270_TESTS645ANGLE_INSTANTIATE_DEQP_TEST_CASE(GLES31_ROTATE270, 13);646#endif647648void HandleDisplayType(const char *displayTypeString)649{650std::stringstream argStream;651652if (gInitAPI)653{654std::cout << "Cannot specify two EGL displays!" << std::endl;655exit(1);656}657658if (strncmp(displayTypeString, "angle-", strlen("angle-")) != 0)659{660argStream << "angle-";661}662663argStream << displayTypeString;664std::string arg = argStream.str();665666gInitAPI = FindAPIInfo(arg);667668if (!gInitAPI)669{670std::cout << "Unknown ANGLE back-end API: " << displayTypeString << std::endl;671exit(1);672}673}674675void HandlePreRotation(const char *preRotationString)676{677std::istringstream argStream(preRotationString);678679uint32_t preRotation = 0;680argStream >> preRotation;681682if (!argStream ||683(preRotation != 0 && preRotation != 90 && preRotation != 180 && preRotation != 270))684{685std::cout << "Invalid PreRotation '" << preRotationString686<< "'; must be either 0, 90, 180 or 270" << std::endl;687exit(1);688}689690gOptions.preRotation = preRotation;691}692693void HandleEGLConfigName(const char *configNameString)694{695gEGLConfigName = configNameString;696}697698// The --deqp-case flag takes a case expression that is parsed into a --gtest_filter. It converts699// the "dEQP" style names (functional.thing.*) into "GoogleTest" style names (functional_thing_*).700// Currently it does not handle multiple tests and multiple filters in different arguments.701void HandleCaseName(const char *caseString, int *argc, int argIndex, char **argv)702{703std::string googleTestName = DrawElementsToGoogleTestName(caseString);704gCaseStringBuffer.fill(0);705int bytesWritten = snprintf(gCaseStringBuffer.data(), gCaseStringBuffer.size() - 1,706"--gtest_filter=*%s", googleTestName.c_str());707if (bytesWritten <= 0 || static_cast<size_t>(bytesWritten) >= gCaseStringBuffer.size() - 1)708{709std::cout << "Error parsing test case string: " << caseString;710exit(1);711}712713argv[argIndex] = gCaseStringBuffer.data();714}715716void HandleLogImages(const char *logImagesString)717{718if (strcmp(logImagesString, "enable") == 0)719{720gLogImages = true;721}722else if (strcmp(logImagesString, "disable") == 0)723{724gLogImages = false;725}726else727{728std::cout << "Error parsing log images setting. Use enable/disable.";729exit(1);730}731}732} // anonymous namespace733734// Called from main() to process command-line arguments.735void InitTestHarness(int *argc, char **argv)736{737int argIndex = 0;738while (argIndex < *argc)739{740if (strncmp(argv[argIndex], kdEQPEGLString, strlen(kdEQPEGLString)) == 0)741{742HandleDisplayType(argv[argIndex] + strlen(kdEQPEGLString));743}744else if (strncmp(argv[argIndex], kANGLEEGLString, strlen(kANGLEEGLString)) == 0)745{746HandleDisplayType(argv[argIndex] + strlen(kANGLEEGLString));747}748else if (strncmp(argv[argIndex], kANGLEPreRotation, strlen(kANGLEPreRotation)) == 0)749{750HandlePreRotation(argv[argIndex] + strlen(kANGLEPreRotation));751}752else if (strncmp(argv[argIndex], kANGLEDirectSPIRVGen, strlen(kANGLEDirectSPIRVGen)) == 0)753{754gOptions.enableDirectSPIRVGen = true;755}756else if (strncmp(argv[argIndex], gdEQPEGLConfigNameString,757strlen(gdEQPEGLConfigNameString)) == 0)758{759HandleEGLConfigName(argv[argIndex] + strlen(gdEQPEGLConfigNameString));760}761else if (strncmp(argv[argIndex], kdEQPCaseString, strlen(kdEQPCaseString)) == 0)762{763HandleCaseName(argv[argIndex] + strlen(kdEQPCaseString), argc, argIndex, argv);764}765else if (strncmp(argv[argIndex], kVerboseString, strlen(kVerboseString)) == 0 ||766strcmp(argv[argIndex], "-v") == 0)767{768gVerbose = true;769}770else if (strncmp(argv[argIndex], gdEQPLogImagesString, strlen(gdEQPLogImagesString)) == 0)771{772HandleLogImages(argv[argIndex] + strlen(gdEQPLogImagesString));773}774else if (strncmp(argv[argIndex], kRenderDocString, strlen(kRenderDocString)) == 0)775{776gOptions.enableRenderDocCapture = true;777}778argIndex++;779}780781GPUTestConfig::API api = GetDefaultAPIInfo()->second;782if (gInitAPI)783{784api = gInitAPI->second;785}786if (gOptions.preRotation != 0 && api != GPUTestConfig::kAPIVulkan &&787api != GPUTestConfig::kAPISwiftShader)788{789std::cout << "PreRotation is only supported on Vulkan" << std::endl;790exit(1);791}792if (gOptions.enableDirectSPIRVGen != 0 && api != GPUTestConfig::kAPIVulkan &&793api != GPUTestConfig::kAPISwiftShader)794{795std::cout << "SPIR-V generation is only relevant to Vulkan" << std::endl;796exit(1);797}798}799} // namespace angle800801802