Files
godot-angle-static/util/test_utils.cpp
Jamie Madill e495e7fdd0 Redo perf and trace test parameters.
- Moves common argument parsing code into test_util.
- Changes the perf test arg parsing to use the common functions.
- Adds new --use-angle and --use-gl parameters to the trace tests.
- Also adds new --offscreen and --vsync parameters to the traces.
- Removes the now unneeded --enable-all-trace-tests argument.
- Both --arg=value and --arg value work in test suites now.

Now, instead of using --enable-all-trace-tests you can specify the
backend with --use-angle=swiftshader, --offscreen, or combinations
of those parameters. The test names are the same as they were
before, but only the configured tests will run in a session. We
could opt to simplify the test names in later CLs if we want to
simplify the test running. Ideally we'd keep the perf reporting
the same because then we'd keep the time series the same on the
test infra.

This also allows us to split up the trace tests into separate
targets on the bots, which will better allow us to control the
workloads and sampling of the tests. For example:

- angle_perftests becomes
  - angle_perftests (microbenchmarks)
  - angle_trace_perf_vulkan_tests (traces with vulkan back-end)
  - angle_trace_perf_native_tests (traces with system GL)

Bug: angleproject:7755
Change-Id: I537168f3a6de96425dfda05ed98220eff9b19b76
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3956937
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Cody Northrop <cnorthrop@google.com>
2022-10-19 16:50:01 +00:00

261 lines
6.5 KiB
C++

//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// system_utils: Defines common utility functions
#include "util/test_utils.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <cstring>
#include <fstream>
#include <iostream>
namespace angle
{
namespace
{
void DeleteArg(int *argc, char **argv, int argIndex)
{
// Shift the remainder of the argv list left by one. Note that argv has (*argc + 1) elements,
// the last one always being NULL. The following loop moves the trailing NULL element as well.
for (int index = argIndex; index < *argc; ++index)
{
argv[index] = argv[index + 1];
}
(*argc)--;
}
const char *GetSingleArg(const char *flag,
int *argc,
char **argv,
int argIndex,
ArgHandling handling)
{
if (strstr(argv[argIndex], flag) == argv[argIndex])
{
const char *ptr = argv[argIndex] + strlen(flag);
if (*ptr == '=')
{
if (handling == ArgHandling::Delete)
{
DeleteArg(argc, argv, argIndex);
}
return ptr + 1;
}
if (argIndex < *argc - 1)
{
ptr = argv[argIndex + 1];
if (handling == ArgHandling::Delete)
{
DeleteArg(argc, argv, argIndex);
DeleteArg(argc, argv, argIndex);
}
return ptr;
}
}
return nullptr;
}
using DisplayTypeInfo = std::pair<const char *, EGLint>;
const DisplayTypeInfo kDisplayTypes[] = {
{"d3d9", EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE},
{"d3d11", EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE},
{"gl", EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE},
{"gles", EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE},
{"metal", EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE},
{"null", EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE},
{"swiftshader", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
{"vulkan", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
};
} // anonymous namespace
bool GetFileSize(const char *filePath, uint32_t *sizeOut)
{
std::ifstream stream(filePath);
if (!stream)
{
return false;
}
stream.seekg(0, std::ios::end);
*sizeOut = static_cast<uint32_t>(stream.tellg());
return true;
}
bool ReadEntireFileToString(const char *filePath, std::string *contentsOut)
{
std::ifstream stream(filePath);
if (!stream)
{
return false;
}
stream.seekg(0, std::ios::end);
contentsOut->reserve(static_cast<unsigned int>(stream.tellg()));
stream.seekg(0, std::ios::beg);
contentsOut->assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
return true;
}
// static
Process::~Process() = default;
ProcessHandle::ProcessHandle() : mProcess(nullptr) {}
ProcessHandle::ProcessHandle(Process *process) : mProcess(process) {}
ProcessHandle::ProcessHandle(const std::vector<const char *> &args,
ProcessOutputCapture captureOutput)
: mProcess(LaunchProcess(args, captureOutput))
{}
ProcessHandle::~ProcessHandle()
{
reset();
}
ProcessHandle::ProcessHandle(ProcessHandle &&other) : mProcess(other.mProcess)
{
other.mProcess = nullptr;
}
ProcessHandle &ProcessHandle::operator=(ProcessHandle &&rhs)
{
std::swap(mProcess, rhs.mProcess);
return *this;
}
void ProcessHandle::reset()
{
if (mProcess)
{
delete mProcess;
mProcess = nullptr;
}
}
bool ParseIntArgWithHandling(const char *flag,
int *argc,
char **argv,
int argIndex,
int *valueOut,
ArgHandling handling)
{
const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
if (!value)
{
return false;
}
char *end = nullptr;
const long longValue = strtol(value, &end, 10);
if (*end != '\0')
{
printf("Error parsing integer flag value.\n");
exit(EXIT_FAILURE);
}
if (longValue == LONG_MAX || longValue == LONG_MIN || static_cast<int>(longValue) != longValue)
{
printf("Overflow when parsing integer flag value.\n");
exit(EXIT_FAILURE);
}
*valueOut = static_cast<int>(longValue);
return handling == ArgHandling::Delete;
}
bool ParseIntArg(const char *flag, int *argc, char **argv, int argIndex, int *valueOut)
{
return ParseIntArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
}
bool ParseFlag(const char *flag, int *argc, char **argv, int argIndex, bool *flagOut)
{
if (strcmp(flag, argv[argIndex]) == 0)
{
*flagOut = true;
DeleteArg(argc, argv, argIndex);
return true;
}
return false;
}
bool ParseStringArg(const char *flag, int *argc, char **argv, int argIndex, std::string *valueOut)
{
const char *value = GetSingleArg(flag, argc, argv, argIndex, ArgHandling::Delete);
if (!value)
{
return false;
}
*valueOut = value;
return true;
}
bool ParseCStringArg(const char *flag, int *argc, char **argv, int argIndex, const char **valueOut)
{
const char *value = GetSingleArg(flag, argc, argv, argIndex, ArgHandling::Delete);
if (!value)
{
return false;
}
*valueOut = value;
return true;
}
void AddArg(int *argc, char **argv, const char *arg)
{
// This unsafe const_cast is necessary to work around gtest limitations.
argv[*argc] = const_cast<char *>(arg);
argv[*argc + 1] = nullptr;
(*argc)++;
}
uint32_t GetPlatformANGLETypeFromArg(const char *useANGLEArg, uint32_t defaultPlatformType)
{
if (!useANGLEArg)
{
return defaultPlatformType;
}
for (const DisplayTypeInfo &displayTypeInfo : kDisplayTypes)
{
if (strcmp(displayTypeInfo.first, useANGLEArg) == 0)
{
std::cout << "Using ANGLE back-end API: " << displayTypeInfo.first << std::endl;
return displayTypeInfo.second;
}
}
std::cout << "Unknown ANGLE back-end API: " << useANGLEArg << std::endl;
exit(EXIT_FAILURE);
}
uint32_t GetANGLEDeviceTypeFromArg(const char *useANGLEArg, uint32_t defaultDeviceType)
{
if (useANGLEArg && strcmp(useANGLEArg, "swiftshader") == 0)
{
return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
}
else
{
return defaultDeviceType;
}
}
} // namespace angle