Commit 0449a902 by Jonah Ryan-Davis Committed by Commit Bot

Move gpu_test_expectations from third_party into ANGLE.

1. Copy the code from src/tests/third_party/gpu_test_expectations to src/test/test_expectations, rename .cc files to .cpp. Put these in a new static library and update dEQP to link against it in src/tests/BUILD.gn. 2. Merge the code in angle_config.h into the rest of the expectations parser, this code was added so that the rest of the parser would compile in ANGLE's tree with minimal modification. Still need to follow up with the third step to close the issue. Bug: angleproject:2677 Change-Id: Icf09b4eeed83a6d09b1964ad2adcfa85cabb4b63 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1536312 Commit-Queue: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 4ae2c12f
...@@ -659,26 +659,34 @@ if (build_angle_deqp_tests && !is_fuchsia) { ...@@ -659,26 +659,34 @@ if (build_angle_deqp_tests && !is_fuchsia) {
} }
} }
config("angle_deqp_gtest_support_config") { config("angle_deqp_test_expectations_config") {
include_dirs = [ "third_party/gpu_test_expectations" ] include_dirs = [ "${angle_root}:angle_common" ]
}
angle_static_library("angle_deqp_test_expectations") {
public_configs += [ ":angle_deqp_test_expectations_config" ]
public_deps = [
"${angle_root}:angle_common",
"${angle_root}:angle_util",
]
sources = deqp_test_expectations_sources
if (is_mac) {
sources += deqp_test_expectations_sources_mac
libs = [ "Cocoa.framework" ]
}
} }
angle_source_set("angle_deqp_gtest_support") { angle_source_set("angle_deqp_gtest_support") {
testonly = true testonly = true
public_deps = [ public_deps = [
":angle_deqp_test_expectations",
":angle_deqp_tests_main", ":angle_deqp_tests_main",
"${angle_root}:angle_common", "${angle_root}:angle_common",
"${angle_root}:angle_util", "${angle_root}:angle_util",
] ]
public_configs += [ ":angle_deqp_gtest_support_config" ] libs = []
sources = deqp_gpu_test_expectations_sources
if (is_mac) {
sources += deqp_gpu_test_expectations_sources_mac
libs = [ "Cocoa.framework" ]
}
if (!is_android) { if (!is_android) {
public_deps += [ "${angle_root}:angle_gpu_info_util" ] public_deps += [ "${angle_root}:angle_gpu_info_util" ]
......
...@@ -1143,15 +1143,15 @@ deqp_libtester_sources_android = [ ...@@ -1143,15 +1143,15 @@ deqp_libtester_sources_android = [
"$_deqp_path/framework/platform/android/tcuAndroidInternals.cpp", "$_deqp_path/framework/platform/android/tcuAndroidInternals.cpp",
"$_deqp_path/framework/platform/android/tcuAndroidInternals.hpp", "$_deqp_path/framework/platform/android/tcuAndroidInternals.hpp",
] ]
deqp_gpu_test_expectations_sources = [ deqp_test_expectations_sources = [
"third_party/gpu_test_expectations/gpu_info.cc", "test_expectations/gpu_info.cpp",
"third_party/gpu_test_expectations/gpu_info.h", "test_expectations/gpu_info.h",
"third_party/gpu_test_expectations/gpu_test_config.cc", "test_expectations/gpu_test_config.cpp",
"third_party/gpu_test_expectations/gpu_test_config.h", "test_expectations/gpu_test_config.h",
"third_party/gpu_test_expectations/gpu_test_expectations_parser.cc", "test_expectations/gpu_test_expectations_parser.cpp",
"third_party/gpu_test_expectations/gpu_test_expectations_parser.h", "test_expectations/gpu_test_expectations_parser.h",
] ]
deqp_gpu_test_expectations_sources_mac = [ deqp_test_expectations_sources_mac = [
"third_party/gpu_test_expectations/gpu_test_config_mac.mm", "test_expectations/gpu_test_config_mac.mm",
"third_party/gpu_test_expectations/gpu_test_config_mac.h", "test_expectations/gpu_test_config_mac.h",
] ]
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
#include "common/debug.h" #include "common/debug.h"
#include "common/platform.h" #include "common/platform.h"
#include "common/string_utils.h" #include "common/string_utils.h"
#include "gpu_test_expectations_parser.h"
#include "platform/Platform.h" #include "platform/Platform.h"
#include "tests/test_expectations/gpu_test_expectations_parser.h"
#include "util/system_utils.h" #include "util/system_utils.h"
namespace namespace
......
...@@ -6,180 +6,179 @@ ...@@ -6,180 +6,179 @@
#include "gpu_info.h" #include "gpu_info.h"
namespace { namespace
{
void EnumerateGPUDevice(const gpu::GPUInfo::GPUDevice& device,
gpu::GPUInfo::Enumerator* enumerator) { void EnumerateGPUDevice(const gpu::GPUInfo::GPUDevice &device, gpu::GPUInfo::Enumerator *enumerator)
enumerator->BeginGPUDevice(); {
enumerator->AddInt("vendorId", device.vendor_id); enumerator->BeginGPUDevice();
enumerator->AddInt("deviceId", device.device_id); enumerator->AddInt("vendorId", device.vendor_id);
enumerator->AddBool("active", device.active); enumerator->AddInt("deviceId", device.device_id);
enumerator->AddString("vendorString", device.vendor_string); enumerator->AddBool("active", device.active);
enumerator->AddString("deviceString", device.device_string); enumerator->AddString("vendorString", device.vendor_string);
enumerator->AddString("driverVendor", device.driver_vendor); enumerator->AddString("deviceString", device.device_string);
enumerator->AddString("driverVersion", device.driver_version); enumerator->AddString("driverVendor", device.driver_vendor);
enumerator->AddString("driverDate", device.driver_date); enumerator->AddString("driverVersion", device.driver_version);
enumerator->AddInt("cudaComputeCapabilityMajor", enumerator->AddString("driverDate", device.driver_date);
device.cuda_compute_capability_major); enumerator->AddInt("cudaComputeCapabilityMajor", device.cuda_compute_capability_major);
enumerator->EndGPUDevice(); enumerator->EndGPUDevice();
} }
void EnumerateVideoDecodeAcceleratorSupportedProfile( void EnumerateVideoDecodeAcceleratorSupportedProfile(
const gpu::VideoDecodeAcceleratorSupportedProfile& profile, const gpu::VideoDecodeAcceleratorSupportedProfile &profile,
gpu::GPUInfo::Enumerator* enumerator) { gpu::GPUInfo::Enumerator *enumerator)
enumerator->BeginVideoDecodeAcceleratorSupportedProfile(); {
enumerator->AddInt("profile", profile.profile); enumerator->BeginVideoDecodeAcceleratorSupportedProfile();
enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width()); enumerator->AddInt("profile", profile.profile);
enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height()); enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width());
enumerator->AddInt("minResolutionWidth", profile.min_resolution.width()); enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height());
enumerator->AddInt("minResolutionHeight", profile.min_resolution.height()); enumerator->AddInt("minResolutionWidth", profile.min_resolution.width());
enumerator->AddBool("encrypted_only", profile.encrypted_only); enumerator->AddInt("minResolutionHeight", profile.min_resolution.height());
enumerator->EndVideoDecodeAcceleratorSupportedProfile(); enumerator->AddBool("encrypted_only", profile.encrypted_only);
enumerator->EndVideoDecodeAcceleratorSupportedProfile();
} }
void EnumerateVideoEncodeAcceleratorSupportedProfile( void EnumerateVideoEncodeAcceleratorSupportedProfile(
const gpu::VideoEncodeAcceleratorSupportedProfile& profile, const gpu::VideoEncodeAcceleratorSupportedProfile &profile,
gpu::GPUInfo::Enumerator* enumerator) { gpu::GPUInfo::Enumerator *enumerator)
enumerator->BeginVideoEncodeAcceleratorSupportedProfile(); {
enumerator->AddInt("profile", profile.profile); enumerator->BeginVideoEncodeAcceleratorSupportedProfile();
enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width()); enumerator->AddInt("profile", profile.profile);
enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height()); enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width());
enumerator->AddInt("maxFramerateNumerator", profile.max_framerate_numerator); enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height());
enumerator->AddInt("maxFramerateDenominator", enumerator->AddInt("maxFramerateNumerator", profile.max_framerate_numerator);
profile.max_framerate_denominator); enumerator->AddInt("maxFramerateDenominator", profile.max_framerate_denominator);
enumerator->EndVideoEncodeAcceleratorSupportedProfile(); enumerator->EndVideoEncodeAcceleratorSupportedProfile();
} }
const char* ImageDecodeAcceleratorTypeToString( const char *ImageDecodeAcceleratorTypeToString(gpu::ImageDecodeAcceleratorType type)
gpu::ImageDecodeAcceleratorType type) { {
switch (type) { switch (type)
case gpu::ImageDecodeAcceleratorType::kJpeg: {
return "JPEG"; case gpu::ImageDecodeAcceleratorType::kJpeg:
case gpu::ImageDecodeAcceleratorType::kUnknown: return "JPEG";
return "Unknown"; case gpu::ImageDecodeAcceleratorType::kUnknown:
} return "Unknown";
}
} }
const char* ImageDecodeAcceleratorSubsamplingToString( const char *ImageDecodeAcceleratorSubsamplingToString(
gpu::ImageDecodeAcceleratorSubsampling subsampling) { gpu::ImageDecodeAcceleratorSubsampling subsampling)
switch (subsampling) { {
case gpu::ImageDecodeAcceleratorSubsampling::k420: switch (subsampling)
return "4:2:0"; {
case gpu::ImageDecodeAcceleratorSubsampling::k422: case gpu::ImageDecodeAcceleratorSubsampling::k420:
return "4:2:2"; return "4:2:0";
} case gpu::ImageDecodeAcceleratorSubsampling::k422:
return "4:2:2";
}
} }
void EnumerateImageDecodeAcceleratorSupportedProfile( void EnumerateImageDecodeAcceleratorSupportedProfile(
const gpu::ImageDecodeAcceleratorSupportedProfile& profile, const gpu::ImageDecodeAcceleratorSupportedProfile &profile,
gpu::GPUInfo::Enumerator* enumerator) { gpu::GPUInfo::Enumerator *enumerator)
enumerator->BeginImageDecodeAcceleratorSupportedProfile(); {
enumerator->AddString("imageType", enumerator->BeginImageDecodeAcceleratorSupportedProfile();
ImageDecodeAcceleratorTypeToString(profile.image_type)); enumerator->AddString("imageType", ImageDecodeAcceleratorTypeToString(profile.image_type));
enumerator->AddString("minEncodedDimensions", enumerator->AddString("minEncodedDimensions", profile.min_encoded_dimensions.ToString());
profile.min_encoded_dimensions.ToString()); enumerator->AddString("maxEncodedDimensions", profile.max_encoded_dimensions.ToString());
enumerator->AddString("maxEncodedDimensions", std::string subsamplings;
profile.max_encoded_dimensions.ToString()); for (size_t i = 0; i < profile.subsamplings.size(); i++)
std::string subsamplings; {
for (size_t i = 0; i < profile.subsamplings.size(); i++) { if (i > 0)
if (i > 0) subsamplings += ", ";
subsamplings += ", "; subsamplings += ImageDecodeAcceleratorSubsamplingToString(profile.subsamplings[i]);
subsamplings += }
ImageDecodeAcceleratorSubsamplingToString(profile.subsamplings[i]); enumerator->AddString("subsamplings", subsamplings);
} enumerator->EndImageDecodeAcceleratorSupportedProfile();
enumerator->AddString("subsamplings", subsamplings);
enumerator->EndImageDecodeAcceleratorSupportedProfile();
} }
#if defined(OS_WIN) #if defined(OS_WIN)
void EnumerateOverlayCapability(const gpu::OverlayCapability& cap, void EnumerateOverlayCapability(const gpu::OverlayCapability &cap,
gpu::GPUInfo::Enumerator* enumerator) { gpu::GPUInfo::Enumerator *enumerator)
std::string key_string = "overlayCap"; {
key_string += OverlayFormatToString(cap.format); std::string key_string = "overlayCap";
enumerator->BeginOverlayCapability(); key_string += OverlayFormatToString(cap.format);
enumerator->AddString(key_string.c_str(), enumerator->BeginOverlayCapability();
cap.is_scaling_supported ? "SCALING" : "DIRECT"); enumerator->AddString(key_string.c_str(), cap.is_scaling_supported ? "SCALING" : "DIRECT");
enumerator->EndOverlayCapability(); enumerator->EndOverlayCapability();
} }
void EnumerateDx12VulkanVersionInfo(const gpu::Dx12VulkanVersionInfo& info, void EnumerateDx12VulkanVersionInfo(const gpu::Dx12VulkanVersionInfo &info,
gpu::GPUInfo::Enumerator* enumerator) { gpu::GPUInfo::Enumerator *enumerator)
enumerator->BeginDx12VulkanVersionInfo(); {
enumerator->AddBool("supportsDx12", info.supports_dx12); enumerator->BeginDx12VulkanVersionInfo();
enumerator->AddBool("supportsVulkan", info.supports_vulkan); enumerator->AddBool("supportsDx12", info.supports_dx12);
enumerator->AddInt("dx12FeatureLevel", enumerator->AddBool("supportsVulkan", info.supports_vulkan);
static_cast<int>(info.d3d12_feature_level)); enumerator->AddInt("dx12FeatureLevel", static_cast<int>(info.d3d12_feature_level));
enumerator->AddInt("vulkanVersion", static_cast<int>(info.vulkan_version)); enumerator->AddInt("vulkanVersion", static_cast<int>(info.vulkan_version));
enumerator->EndDx12VulkanVersionInfo(); enumerator->EndDx12VulkanVersionInfo();
} }
#endif #endif
} // namespace } // namespace
namespace gpu { namespace gpu
{
#if defined(OS_WIN) #if defined(OS_WIN)
const char* OverlayFormatToString(OverlayFormat format) { const char *OverlayFormatToString(OverlayFormat format)
switch (format) { {
case OverlayFormat::kBGRA: switch (format)
return "BGRA"; {
case OverlayFormat::kYUY2: case OverlayFormat::kBGRA:
return "YUY2"; return "BGRA";
case OverlayFormat::kNV12: case OverlayFormat::kYUY2:
return "NV12"; return "YUY2";
} case OverlayFormat::kNV12:
return "NV12";
}
} }
bool OverlayCapability::operator==(const OverlayCapability& other) const { bool OverlayCapability::operator==(const OverlayCapability &other) const
return format == other.format && {
is_scaling_supported == other.is_scaling_supported; return format == other.format && is_scaling_supported == other.is_scaling_supported;
} }
#endif #endif
VideoDecodeAcceleratorCapabilities::VideoDecodeAcceleratorCapabilities() VideoDecodeAcceleratorCapabilities::VideoDecodeAcceleratorCapabilities() : flags(0) {}
: flags(0) {}
VideoDecodeAcceleratorCapabilities::VideoDecodeAcceleratorCapabilities( VideoDecodeAcceleratorCapabilities::VideoDecodeAcceleratorCapabilities(
const VideoDecodeAcceleratorCapabilities& other) = default; const VideoDecodeAcceleratorCapabilities &other) = default;
VideoDecodeAcceleratorCapabilities::~VideoDecodeAcceleratorCapabilities() = VideoDecodeAcceleratorCapabilities::~VideoDecodeAcceleratorCapabilities() = default;
default;
ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile() ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile()
: image_type(ImageDecodeAcceleratorType::kUnknown) {} : image_type(ImageDecodeAcceleratorType::kUnknown)
{}
ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile( ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile(
const ImageDecodeAcceleratorSupportedProfile& other) = default; const ImageDecodeAcceleratorSupportedProfile &other) = default;
ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile( ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile(
ImageDecodeAcceleratorSupportedProfile&& other) = default; ImageDecodeAcceleratorSupportedProfile &&other) = default;
ImageDecodeAcceleratorSupportedProfile:: ImageDecodeAcceleratorSupportedProfile::~ImageDecodeAcceleratorSupportedProfile() = default;
~ImageDecodeAcceleratorSupportedProfile() = default;
ImageDecodeAcceleratorSupportedProfile& ImageDecodeAcceleratorSupportedProfile:: ImageDecodeAcceleratorSupportedProfile &ImageDecodeAcceleratorSupportedProfile::operator=(
operator=(const ImageDecodeAcceleratorSupportedProfile& other) = default; const ImageDecodeAcceleratorSupportedProfile &other) = default;
ImageDecodeAcceleratorSupportedProfile& ImageDecodeAcceleratorSupportedProfile:: ImageDecodeAcceleratorSupportedProfile &ImageDecodeAcceleratorSupportedProfile::operator=(
operator=(ImageDecodeAcceleratorSupportedProfile&& other) = default; ImageDecodeAcceleratorSupportedProfile &&other) = default;
GPUInfo::GPUDevice::GPUDevice() GPUInfo::GPUDevice::GPUDevice()
: vendor_id(0), : vendor_id(0), device_id(0), active(false), cuda_compute_capability_major(0)
device_id(0), {}
active(false),
cuda_compute_capability_major(0) {}
GPUInfo::GPUDevice::GPUDevice(const GPUInfo::GPUDevice& other) = default; GPUInfo::GPUDevice::GPUDevice(const GPUInfo::GPUDevice &other) = default;
GPUInfo::GPUDevice::GPUDevice(GPUInfo::GPUDevice&& other) noexcept = default; GPUInfo::GPUDevice::GPUDevice(GPUInfo::GPUDevice &&other) noexcept = default;
GPUInfo::GPUDevice::~GPUDevice() noexcept = default; GPUInfo::GPUDevice::~GPUDevice() noexcept = default;
GPUInfo::GPUDevice& GPUInfo::GPUDevice::operator=( GPUInfo::GPUDevice &GPUInfo::GPUDevice::operator=(const GPUInfo::GPUDevice &other) = default;
const GPUInfo::GPUDevice& other) = default;
GPUInfo::GPUDevice& GPUInfo::GPUDevice::operator=( GPUInfo::GPUDevice &GPUInfo::GPUDevice::operator=(GPUInfo::GPUDevice &&other) noexcept = default;
GPUInfo::GPUDevice&& other) noexcept = default;
GPUInfo::GPUInfo() GPUInfo::GPUInfo()
: optimus(false), : optimus(false),
...@@ -195,148 +194,144 @@ GPUInfo::GPUInfo() ...@@ -195,148 +194,144 @@ GPUInfo::GPUInfo()
system_visual(0), system_visual(0),
rgba_visual(0), rgba_visual(0),
#endif #endif
oop_rasterization_supported(false) { oop_rasterization_supported(false)
} {}
GPUInfo::GPUInfo(const GPUInfo& other) = default; GPUInfo::GPUInfo(const GPUInfo &other) = default;
GPUInfo::~GPUInfo() = default; GPUInfo::~GPUInfo() = default;
GPUInfo::GPUDevice& GPUInfo::active_gpu() { GPUInfo::GPUDevice &GPUInfo::active_gpu()
return const_cast<GPUInfo::GPUDevice&>( {
const_cast<const GPUInfo&>(*this).active_gpu()); return const_cast<GPUInfo::GPUDevice &>(const_cast<const GPUInfo &>(*this).active_gpu());
} }
const GPUInfo::GPUDevice& GPUInfo::active_gpu() const { const GPUInfo::GPUDevice &GPUInfo::active_gpu() const
if (gpu.active || secondary_gpus.empty()) {
if (gpu.active || secondary_gpus.empty())
return gpu;
for (const auto &secondary_gpu : secondary_gpus)
{
if (secondary_gpu.active)
return secondary_gpu;
}
DVLOG(2) << "No active GPU found, returning primary GPU.\n";
return gpu; return gpu;
for (const auto& secondary_gpu : secondary_gpus) {
if (secondary_gpu.active)
return secondary_gpu;
}
DVLOG(2) << "No active GPU found, returning primary GPU.\n";
return gpu;
} }
bool GPUInfo::IsInitialized() const { bool GPUInfo::IsInitialized() const
return gpu.vendor_id != 0 || !gl_vendor.empty(); {
return gpu.vendor_id != 0 || !gl_vendor.empty();
} }
void GPUInfo::EnumerateFields(Enumerator* enumerator) const { void GPUInfo::EnumerateFields(Enumerator *enumerator) const
struct GPUInfoKnownFields { {
base::TimeDelta initialization_time; struct GPUInfoKnownFields
bool optimus; {
bool amd_switchable; base::TimeDelta initialization_time;
GPUDevice gpu; bool optimus;
std::vector<GPUDevice> secondary_gpus; bool amd_switchable;
std::string pixel_shader_version; GPUDevice gpu;
std::string vertex_shader_version; std::vector<GPUDevice> secondary_gpus;
std::string max_msaa_samples; std::string pixel_shader_version;
std::string machine_model_name; std::string vertex_shader_version;
std::string machine_model_version; std::string max_msaa_samples;
std::string gl_version_string; std::string machine_model_name;
std::string gl_vendor; std::string machine_model_version;
std::string gl_renderer; std::string gl_version_string;
std::string gl_extensions; std::string gl_vendor;
std::string gl_ws_vendor; std::string gl_renderer;
std::string gl_ws_version; std::string gl_extensions;
std::string gl_ws_extensions; std::string gl_ws_vendor;
uint32_t gl_reset_notification_strategy; std::string gl_ws_version;
bool software_rendering; std::string gl_ws_extensions;
bool direct_rendering; uint32_t gl_reset_notification_strategy;
bool sandboxed; bool software_rendering;
bool in_process_gpu; bool direct_rendering;
bool passthrough_cmd_decoder; bool sandboxed;
bool can_support_threaded_texture_mailbox; bool in_process_gpu;
bool passthrough_cmd_decoder;
bool can_support_threaded_texture_mailbox;
#if defined(OS_WIN) #if defined(OS_WIN)
bool direct_composition; bool direct_composition;
bool supports_overlays; bool supports_overlays;
OverlayCapabilities overlay_capabilities; OverlayCapabilities overlay_capabilities;
DxDiagNode dx_diagnostics; DxDiagNode dx_diagnostics;
Dx12VulkanVersionInfo dx12_vulkan_version_info; Dx12VulkanVersionInfo dx12_vulkan_version_info;
#endif #endif
VideoDecodeAcceleratorCapabilities video_decode_accelerator_capabilities; VideoDecodeAcceleratorCapabilities video_decode_accelerator_capabilities;
VideoEncodeAcceleratorSupportedProfiles VideoEncodeAcceleratorSupportedProfiles video_encode_accelerator_supported_profiles;
video_encode_accelerator_supported_profiles; bool jpeg_decode_accelerator_supported;
bool jpeg_decode_accelerator_supported;
ImageDecodeAcceleratorSupportedProfiles ImageDecodeAcceleratorSupportedProfiles image_decode_accelerator_supported_profiles;
image_decode_accelerator_supported_profiles;
#if defined(USE_X11) #if defined(USE_X11)
VisualID system_visual; VisualID system_visual;
VisualID rgba_visual; VisualID rgba_visual;
#endif #endif
bool oop_rasterization_supported; bool oop_rasterization_supported;
}; };
// If this assert fails then most likely something below needs to be updated. // If this assert fails then most likely something below needs to be updated.
// Note that this assert is only approximate. If a new field is added to // Note that this assert is only approximate. If a new field is added to
// GPUInfo which fits within the current padding then it will not be caught. // GPUInfo which fits within the current padding then it will not be caught.
static_assert( static_assert(sizeof(GPUInfo) == sizeof(GPUInfoKnownFields),
sizeof(GPUInfo) == sizeof(GPUInfoKnownFields), "fields have changed in GPUInfo, GPUInfoKnownFields must be updated");
"fields have changed in GPUInfo, GPUInfoKnownFields must be updated");
// Required fields (according to DevTools protocol) first.
// Required fields (according to DevTools protocol) first. enumerator->AddString("machineModelName", machine_model_name);
enumerator->AddString("machineModelName", machine_model_name); enumerator->AddString("machineModelVersion", machine_model_version);
enumerator->AddString("machineModelVersion", machine_model_version); EnumerateGPUDevice(gpu, enumerator);
EnumerateGPUDevice(gpu, enumerator); for (const auto &secondary_gpu : secondary_gpus)
for (const auto& secondary_gpu : secondary_gpus) EnumerateGPUDevice(secondary_gpu, enumerator);
EnumerateGPUDevice(secondary_gpu, enumerator);
enumerator->BeginAuxAttributes();
enumerator->BeginAuxAttributes(); enumerator->AddTimeDeltaInSecondsF("initializationTime", initialization_time);
enumerator->AddTimeDeltaInSecondsF("initializationTime", enumerator->AddBool("optimus", optimus);
initialization_time); enumerator->AddBool("amdSwitchable", amd_switchable);
enumerator->AddBool("optimus", optimus); enumerator->AddString("pixelShaderVersion", pixel_shader_version);
enumerator->AddBool("amdSwitchable", amd_switchable); enumerator->AddString("vertexShaderVersion", vertex_shader_version);
enumerator->AddString("pixelShaderVersion", pixel_shader_version); enumerator->AddString("maxMsaaSamples", max_msaa_samples);
enumerator->AddString("vertexShaderVersion", vertex_shader_version); enumerator->AddString("glVersion", gl_version);
enumerator->AddString("maxMsaaSamples", max_msaa_samples); enumerator->AddString("glVendor", gl_vendor);
enumerator->AddString("glVersion", gl_version); enumerator->AddString("glRenderer", gl_renderer);
enumerator->AddString("glVendor", gl_vendor); enumerator->AddString("glExtensions", gl_extensions);
enumerator->AddString("glRenderer", gl_renderer); enumerator->AddString("glWsVendor", gl_ws_vendor);
enumerator->AddString("glExtensions", gl_extensions); enumerator->AddString("glWsVersion", gl_ws_version);
enumerator->AddString("glWsVendor", gl_ws_vendor); enumerator->AddString("glWsExtensions", gl_ws_extensions);
enumerator->AddString("glWsVersion", gl_ws_version); enumerator->AddInt("glResetNotificationStrategy",
enumerator->AddString("glWsExtensions", gl_ws_extensions); static_cast<int>(gl_reset_notification_strategy));
enumerator->AddInt( // TODO(kbr): add performance_stats.
"glResetNotificationStrategy", enumerator->AddBool("softwareRendering", software_rendering);
static_cast<int>(gl_reset_notification_strategy)); enumerator->AddBool("directRendering", direct_rendering);
// TODO(kbr): add performance_stats. enumerator->AddBool("sandboxed", sandboxed);
enumerator->AddBool("softwareRendering", software_rendering); enumerator->AddBool("inProcessGpu", in_process_gpu);
enumerator->AddBool("directRendering", direct_rendering); enumerator->AddBool("passthroughCmdDecoder", passthrough_cmd_decoder);
enumerator->AddBool("sandboxed", sandboxed); enumerator->AddBool("canSupportThreadedTextureMailbox", can_support_threaded_texture_mailbox);
enumerator->AddBool("inProcessGpu", in_process_gpu); // TODO(kbr): add dx_diagnostics on Windows.
enumerator->AddBool("passthroughCmdDecoder", passthrough_cmd_decoder);
enumerator->AddBool("canSupportThreadedTextureMailbox",
can_support_threaded_texture_mailbox);
// TODO(kbr): add dx_diagnostics on Windows.
#if defined(OS_WIN) #if defined(OS_WIN)
enumerator->AddBool("directComposition", direct_composition); enumerator->AddBool("directComposition", direct_composition);
enumerator->AddBool("supportsOverlays", supports_overlays); enumerator->AddBool("supportsOverlays", supports_overlays);
for (const auto& cap : overlay_capabilities) for (const auto &cap : overlay_capabilities)
EnumerateOverlayCapability(cap, enumerator); EnumerateOverlayCapability(cap, enumerator);
EnumerateDx12VulkanVersionInfo(dx12_vulkan_version_info, enumerator); EnumerateDx12VulkanVersionInfo(dx12_vulkan_version_info, enumerator);
#endif #endif
enumerator->AddInt("videoDecodeAcceleratorFlags", enumerator->AddInt("videoDecodeAcceleratorFlags", video_decode_accelerator_capabilities.flags);
video_decode_accelerator_capabilities.flags); for (const auto &profile : video_decode_accelerator_capabilities.supported_profiles)
for (const auto& profile : EnumerateVideoDecodeAcceleratorSupportedProfile(profile, enumerator);
video_decode_accelerator_capabilities.supported_profiles) for (const auto &profile : video_encode_accelerator_supported_profiles)
EnumerateVideoDecodeAcceleratorSupportedProfile(profile, enumerator); EnumerateVideoEncodeAcceleratorSupportedProfile(profile, enumerator);
for (const auto& profile : video_encode_accelerator_supported_profiles) enumerator->AddBool("jpegDecodeAcceleratorSupported", jpeg_decode_accelerator_supported);
EnumerateVideoEncodeAcceleratorSupportedProfile(profile, enumerator); for (const auto &profile : image_decode_accelerator_supported_profiles)
enumerator->AddBool("jpegDecodeAcceleratorSupported", EnumerateImageDecodeAcceleratorSupportedProfile(profile, enumerator);
jpeg_decode_accelerator_supported);
for (const auto& profile : image_decode_accelerator_supported_profiles)
EnumerateImageDecodeAcceleratorSupportedProfile(profile, enumerator);
#if defined(USE_X11) #if defined(USE_X11)
enumerator->AddInt64("systemVisual", system_visual); enumerator->AddInt64("systemVisual", system_visual);
enumerator->AddInt64("rgbaVisual", rgba_visual); enumerator->AddInt64("rgbaVisual", rgba_visual);
#endif #endif
enumerator->AddBool("oopRasterizationSupported", oop_rasterization_supported); enumerator->AddBool("oopRasterizationSupported", oop_rasterization_supported);
enumerator->EndAuxAttributes(); enumerator->EndAuxAttributes();
} }
} // namespace gpu } // namespace gpu
...@@ -13,387 +13,398 @@ ...@@ -13,387 +13,398 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "angle_config.h" #include "gpu_test_config.h"
#if defined(USE_X11) #if defined(USE_X11)
typedef unsigned long VisualID; typedef unsigned long VisualID;
#endif #endif
namespace gpu { namespace gpu
{
// These values are persisted to logs. Entries should not be renumbered and // These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. // numeric values should never be reused.
enum class GpuSeriesType { enum class GpuSeriesType
kUnknown = 0, {
// Intel 6th gen kUnknown = 0,
kIntelSandyBridge = 1, // Intel 6th gen
// Intel 7th gen kIntelSandyBridge = 1,
kIntelValleyView = 2, // BayTrail // Intel 7th gen
kIntelIvyBridge = 3, kIntelValleyView = 2, // BayTrail
kIntelHaswell = 4, kIntelIvyBridge = 3,
// Intel 8th gen kIntelHaswell = 4,
kIntelCherryView = 5, // Braswell // Intel 8th gen
kIntelBroadwell = 6, kIntelCherryView = 5, // Braswell
// Intel 9th gen kIntelBroadwell = 6,
kIntelApolloLake = 7, // Intel 9th gen
kIntelSkyLake = 8, kIntelApolloLake = 7,
kIntelGeminiLake = 9, kIntelSkyLake = 8,
kIntelKabyLake = 10, kIntelGeminiLake = 9,
kIntelCoffeeLake = 11, kIntelKabyLake = 10,
// Please also update |gpu_series_map| in process_json.py. kIntelCoffeeLake = 11,
kMaxValue = kIntelCoffeeLake, // Please also update |gpu_series_map| in process_json.py.
kMaxValue = kIntelCoffeeLake,
}; };
// Video profile. This *must* match media::VideoCodecProfile. // Video profile. This *must* match media::VideoCodecProfile.
enum VideoCodecProfile { enum VideoCodecProfile
VIDEO_CODEC_PROFILE_UNKNOWN = -1, {
VIDEO_CODEC_PROFILE_MIN = VIDEO_CODEC_PROFILE_UNKNOWN, VIDEO_CODEC_PROFILE_UNKNOWN = -1,
H264PROFILE_BASELINE = 0, VIDEO_CODEC_PROFILE_MIN = VIDEO_CODEC_PROFILE_UNKNOWN,
H264PROFILE_MAIN, H264PROFILE_BASELINE = 0,
H264PROFILE_EXTENDED, H264PROFILE_MAIN,
H264PROFILE_HIGH, H264PROFILE_EXTENDED,
H264PROFILE_HIGH10PROFILE, H264PROFILE_HIGH,
H264PROFILE_HIGH422PROFILE, H264PROFILE_HIGH10PROFILE,
H264PROFILE_HIGH444PREDICTIVEPROFILE, H264PROFILE_HIGH422PROFILE,
H264PROFILE_SCALABLEBASELINE, H264PROFILE_HIGH444PREDICTIVEPROFILE,
H264PROFILE_SCALABLEHIGH, H264PROFILE_SCALABLEBASELINE,
H264PROFILE_STEREOHIGH, H264PROFILE_SCALABLEHIGH,
H264PROFILE_MULTIVIEWHIGH, H264PROFILE_STEREOHIGH,
VP8PROFILE_ANY, H264PROFILE_MULTIVIEWHIGH,
VP9PROFILE_PROFILE0, VP8PROFILE_ANY,
VP9PROFILE_PROFILE1, VP9PROFILE_PROFILE0,
VP9PROFILE_PROFILE2, VP9PROFILE_PROFILE1,
VP9PROFILE_PROFILE3, VP9PROFILE_PROFILE2,
HEVCPROFILE_MAIN, VP9PROFILE_PROFILE3,
HEVCPROFILE_MAIN10, HEVCPROFILE_MAIN,
HEVCPROFILE_MAIN_STILL_PICTURE, HEVCPROFILE_MAIN10,
DOLBYVISION_PROFILE0, HEVCPROFILE_MAIN_STILL_PICTURE,
DOLBYVISION_PROFILE4, DOLBYVISION_PROFILE0,
DOLBYVISION_PROFILE5, DOLBYVISION_PROFILE4,
DOLBYVISION_PROFILE7, DOLBYVISION_PROFILE5,
THEORAPROFILE_ANY, DOLBYVISION_PROFILE7,
AV1PROFILE_PROFILE_MAIN, THEORAPROFILE_ANY,
AV1PROFILE_PROFILE_HIGH, AV1PROFILE_PROFILE_MAIN,
AV1PROFILE_PROFILE_PRO, AV1PROFILE_PROFILE_HIGH,
VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE_PRO, AV1PROFILE_PROFILE_PRO,
VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE_PRO,
}; };
// Specification of a decoding profile supported by a hardware decoder. // Specification of a decoding profile supported by a hardware decoder.
struct GPU_EXPORT VideoDecodeAcceleratorSupportedProfile { struct GPU_EXPORT VideoDecodeAcceleratorSupportedProfile
VideoCodecProfile profile; {
gfx::Size max_resolution; VideoCodecProfile profile;
gfx::Size min_resolution; gfx::Size max_resolution;
bool encrypted_only; gfx::Size min_resolution;
bool encrypted_only;
}; };
using VideoDecodeAcceleratorSupportedProfiles = using VideoDecodeAcceleratorSupportedProfiles = std::vector<VideoDecodeAcceleratorSupportedProfile>;
std::vector<VideoDecodeAcceleratorSupportedProfile>;
struct GPU_EXPORT VideoDecodeAcceleratorCapabilities { struct GPU_EXPORT VideoDecodeAcceleratorCapabilities
VideoDecodeAcceleratorCapabilities(); {
VideoDecodeAcceleratorCapabilities( VideoDecodeAcceleratorCapabilities();
const VideoDecodeAcceleratorCapabilities& other); VideoDecodeAcceleratorCapabilities(const VideoDecodeAcceleratorCapabilities &other);
~VideoDecodeAcceleratorCapabilities(); ~VideoDecodeAcceleratorCapabilities();
VideoDecodeAcceleratorSupportedProfiles supported_profiles; VideoDecodeAcceleratorSupportedProfiles supported_profiles;
uint32_t flags; uint32_t flags;
}; };
// Specification of an encoding profile supported by a hardware encoder. // Specification of an encoding profile supported by a hardware encoder.
struct GPU_EXPORT VideoEncodeAcceleratorSupportedProfile { struct GPU_EXPORT VideoEncodeAcceleratorSupportedProfile
VideoCodecProfile profile; {
gfx::Size max_resolution; VideoCodecProfile profile;
uint32_t max_framerate_numerator; gfx::Size max_resolution;
uint32_t max_framerate_denominator; uint32_t max_framerate_numerator;
uint32_t max_framerate_denominator;
}; };
using VideoEncodeAcceleratorSupportedProfiles = using VideoEncodeAcceleratorSupportedProfiles = std::vector<VideoEncodeAcceleratorSupportedProfile>;
std::vector<VideoEncodeAcceleratorSupportedProfile>;
enum class ImageDecodeAcceleratorType { enum class ImageDecodeAcceleratorType
kJpeg = 0, {
kUnknown = 1, kJpeg = 0,
kMaxValue = kUnknown, kUnknown = 1,
kMaxValue = kUnknown,
}; };
enum class ImageDecodeAcceleratorSubsampling { enum class ImageDecodeAcceleratorSubsampling
k420 = 0, {
k422 = 1, k420 = 0,
kMaxValue = k422, k422 = 1,
kMaxValue = k422,
}; };
// Specification of an image decoding profile supported by a hardware decoder. // Specification of an image decoding profile supported by a hardware decoder.
struct GPU_EXPORT ImageDecodeAcceleratorSupportedProfile { struct GPU_EXPORT ImageDecodeAcceleratorSupportedProfile
ImageDecodeAcceleratorSupportedProfile(); {
ImageDecodeAcceleratorSupportedProfile( ImageDecodeAcceleratorSupportedProfile();
const ImageDecodeAcceleratorSupportedProfile& other); ImageDecodeAcceleratorSupportedProfile(const ImageDecodeAcceleratorSupportedProfile &other);
ImageDecodeAcceleratorSupportedProfile( ImageDecodeAcceleratorSupportedProfile(ImageDecodeAcceleratorSupportedProfile &&other);
ImageDecodeAcceleratorSupportedProfile&& other); ~ImageDecodeAcceleratorSupportedProfile();
~ImageDecodeAcceleratorSupportedProfile(); ImageDecodeAcceleratorSupportedProfile &operator=(
ImageDecodeAcceleratorSupportedProfile& operator=( const ImageDecodeAcceleratorSupportedProfile &other);
const ImageDecodeAcceleratorSupportedProfile& other); ImageDecodeAcceleratorSupportedProfile &operator=(
ImageDecodeAcceleratorSupportedProfile& operator=( ImageDecodeAcceleratorSupportedProfile &&other);
ImageDecodeAcceleratorSupportedProfile&& other);
// Fields common to all image types.
// Fields common to all image types. // Type of image to which this profile applies, e.g., JPEG.
// Type of image to which this profile applies, e.g., JPEG. ImageDecodeAcceleratorType image_type;
ImageDecodeAcceleratorType image_type; // Minimum and maximum supported pixel dimensions of the encoded image.
// Minimum and maximum supported pixel dimensions of the encoded image. gfx::Size min_encoded_dimensions;
gfx::Size min_encoded_dimensions; gfx::Size max_encoded_dimensions;
gfx::Size max_encoded_dimensions;
// Fields specific to |image_type| == kJpeg.
// Fields specific to |image_type| == kJpeg. // The supported chroma subsampling formats, e.g. 4:2:0.
// The supported chroma subsampling formats, e.g. 4:2:0. std::vector<ImageDecodeAcceleratorSubsampling> subsamplings;
std::vector<ImageDecodeAcceleratorSubsampling> subsamplings;
}; };
using ImageDecodeAcceleratorSupportedProfiles = using ImageDecodeAcceleratorSupportedProfiles = std::vector<ImageDecodeAcceleratorSupportedProfile>;
std::vector<ImageDecodeAcceleratorSupportedProfile>;
#if defined(OS_WIN) #if defined(OS_WIN)
// Common overlay formats that we're interested in. Must match the OverlayFormat // Common overlay formats that we're interested in. Must match the OverlayFormat
// enum in //tools/metrics/histograms/enums.xml. Mapped to corresponding DXGI // enum in //tools/metrics/histograms/enums.xml. Mapped to corresponding DXGI
// formats in DirectCompositionSurfaceWin. // formats in DirectCompositionSurfaceWin.
enum class OverlayFormat { kBGRA = 0, kYUY2 = 1, kNV12 = 2, kMaxValue = kNV12 }; enum class OverlayFormat
{
kBGRA = 0,
kYUY2 = 1,
kNV12 = 2,
kMaxValue = kNV12
};
GPU_EXPORT const char* OverlayFormatToString(OverlayFormat format); GPU_EXPORT const char *OverlayFormatToString(OverlayFormat format);
struct GPU_EXPORT OverlayCapability { struct GPU_EXPORT OverlayCapability
OverlayFormat format; {
bool is_scaling_supported; OverlayFormat format;
bool operator==(const OverlayCapability& other) const; bool is_scaling_supported;
bool operator==(const OverlayCapability &other) const;
}; };
using OverlayCapabilities = std::vector<OverlayCapability>; using OverlayCapabilities = std::vector<OverlayCapability>;
struct GPU_EXPORT Dx12VulkanVersionInfo { struct GPU_EXPORT Dx12VulkanVersionInfo
bool IsEmpty() const { return !d3d12_feature_level && !vulkan_version; } {
bool IsEmpty() const { return !d3d12_feature_level && !vulkan_version; }
// True if the GPU driver supports DX12. // True if the GPU driver supports DX12.
bool supports_dx12 = false; bool supports_dx12 = false;
// True if the GPU driver supports Vulkan. // True if the GPU driver supports Vulkan.
bool supports_vulkan = false; bool supports_vulkan = false;
// The supported d3d feature level in the gpu driver; // The supported d3d feature level in the gpu driver;
uint32_t d3d12_feature_level = 0; uint32_t d3d12_feature_level = 0;
// The support Vulkan API version in the gpu driver; // The support Vulkan API version in the gpu driver;
uint32_t vulkan_version = 0; uint32_t vulkan_version = 0;
}; };
#endif #endif
struct GPU_EXPORT GPUInfo { struct GPU_EXPORT GPUInfo
struct GPU_EXPORT GPUDevice { {
GPUDevice(); struct GPU_EXPORT GPUDevice
GPUDevice(const GPUDevice& other); {
GPUDevice(GPUDevice&& other) noexcept; GPUDevice();
~GPUDevice() noexcept; GPUDevice(const GPUDevice &other);
GPUDevice& operator=(const GPUDevice& other); GPUDevice(GPUDevice &&other) noexcept;
GPUDevice& operator=(GPUDevice&& other) noexcept; ~GPUDevice() noexcept;
GPUDevice &operator=(const GPUDevice &other);
GPUDevice &operator=(GPUDevice &&other) noexcept;
// The DWORD (uint32_t) representing the graphics card vendor id. // The DWORD (uint32_t) representing the graphics card vendor id.
uint32_t vendor_id; uint32_t vendor_id;
// The DWORD (uint32_t) representing the graphics card device id. // The DWORD (uint32_t) representing the graphics card device id.
// Device ids are unique to vendor, not to one another. // Device ids are unique to vendor, not to one another.
uint32_t device_id; uint32_t device_id;
// Whether this GPU is the currently used one. // Whether this GPU is the currently used one.
// Currently this field is only supported and meaningful on OS X. // Currently this field is only supported and meaningful on OS X.
bool active; bool active;
// The strings that describe the GPU. // The strings that describe the GPU.
// In Linux these strings are obtained through libpci. // In Linux these strings are obtained through libpci.
// In Win/MacOSX, these two strings are not filled at the moment. // In Win/MacOSX, these two strings are not filled at the moment.
// In Android, these are respectively GL_VENDOR and GL_RENDERER. // In Android, these are respectively GL_VENDOR and GL_RENDERER.
std::string vendor_string; std::string vendor_string;
std::string device_string; std::string device_string;
std::string driver_vendor; std::string driver_vendor;
std::string driver_version; std::string driver_version;
std::string driver_date; std::string driver_date;
// NVIDIA CUDA compute capability, major version. 0 if undetermined. Can be // NVIDIA CUDA compute capability, major version. 0 if undetermined. Can be
// used to determine the hardware generation that the GPU belongs to. // used to determine the hardware generation that the GPU belongs to.
int cuda_compute_capability_major; int cuda_compute_capability_major;
}; };
GPUInfo(); GPUInfo();
GPUInfo(const GPUInfo& other); GPUInfo(const GPUInfo &other);
~GPUInfo(); ~GPUInfo();
// The currently active gpu. // The currently active gpu.
GPUDevice& active_gpu(); GPUDevice &active_gpu();
const GPUDevice& active_gpu() const; const GPUDevice &active_gpu() const;
bool IsInitialized() const; bool IsInitialized() const;
// The amount of time taken to get from the process starting to the message // The amount of time taken to get from the process starting to the message
// loop being pumped. // loop being pumped.
base::TimeDelta initialization_time; base::TimeDelta initialization_time;
// Computer has NVIDIA Optimus // Computer has NVIDIA Optimus
bool optimus; bool optimus;
// Computer has AMD Dynamic Switchable Graphics // Computer has AMD Dynamic Switchable Graphics
bool amd_switchable; bool amd_switchable;
// Primary GPU, for exmaple, the discrete GPU in a dual GPU machine. // Primary GPU, for exmaple, the discrete GPU in a dual GPU machine.
GPUDevice gpu; GPUDevice gpu;
// Secondary GPUs, for example, the integrated GPU in a dual GPU machine. // Secondary GPUs, for example, the integrated GPU in a dual GPU machine.
std::vector<GPUDevice> secondary_gpus; std::vector<GPUDevice> secondary_gpus;
// The version of the pixel/fragment shader used by the gpu. // The version of the pixel/fragment shader used by the gpu.
std::string pixel_shader_version; std::string pixel_shader_version;
// The version of the vertex shader used by the gpu. // The version of the vertex shader used by the gpu.
std::string vertex_shader_version; std::string vertex_shader_version;
// The maximum multisapling sample count, either through ES3 or // The maximum multisapling sample count, either through ES3 or
// EXT_multisampled_render_to_texture MSAA. // EXT_multisampled_render_to_texture MSAA.
std::string max_msaa_samples; std::string max_msaa_samples;
// The machine model identifier. They can contain any character, including // The machine model identifier. They can contain any character, including
// whitespaces. Currently it is supported on MacOSX and Android. // whitespaces. Currently it is supported on MacOSX and Android.
// Android examples: "Naxus 5", "XT1032". // Android examples: "Naxus 5", "XT1032".
// On MacOSX, the version is stripped out of the model identifier, for // On MacOSX, the version is stripped out of the model identifier, for
// example, the original identifier is "MacBookPro7,2", and we put // example, the original identifier is "MacBookPro7,2", and we put
// "MacBookPro" as machine_model_name, and "7.2" as machine_model_version. // "MacBookPro" as machine_model_name, and "7.2" as machine_model_version.
std::string machine_model_name; std::string machine_model_name;
// The version of the machine model. Currently it is supported on MacOSX. // The version of the machine model. Currently it is supported on MacOSX.
// See machine_model_name's comment. // See machine_model_name's comment.
std::string machine_model_version; std::string machine_model_version;
// The GL_VERSION string. // The GL_VERSION string.
std::string gl_version; std::string gl_version;
// The GL_VENDOR string. // The GL_VENDOR string.
std::string gl_vendor; std::string gl_vendor;
// The GL_RENDERER string. // The GL_RENDERER string.
std::string gl_renderer; std::string gl_renderer;
// The GL_EXTENSIONS string. // The GL_EXTENSIONS string.
std::string gl_extensions; std::string gl_extensions;
// GL window system binding vendor. "" if not available. // GL window system binding vendor. "" if not available.
std::string gl_ws_vendor; std::string gl_ws_vendor;
// GL window system binding version. "" if not available. // GL window system binding version. "" if not available.
std::string gl_ws_version; std::string gl_ws_version;
// GL window system binding extensions. "" if not available. // GL window system binding extensions. "" if not available.
std::string gl_ws_extensions; std::string gl_ws_extensions;
// GL reset notification strategy as defined by GL_ARB_robustness. 0 if GPU // GL reset notification strategy as defined by GL_ARB_robustness. 0 if GPU
// reset detection or notification not available. // reset detection or notification not available.
uint32_t gl_reset_notification_strategy; uint32_t gl_reset_notification_strategy;
bool software_rendering; bool software_rendering;
// Whether the driver uses direct rendering. True on most platforms, false on // Whether the driver uses direct rendering. True on most platforms, false on
// X11 when using remote X. // X11 when using remote X.
bool direct_rendering; bool direct_rendering;
// Whether the gpu process is running in a sandbox. // Whether the gpu process is running in a sandbox.
bool sandboxed; bool sandboxed;
// True if the GPU is running in the browser process instead of its own. // True if the GPU is running in the browser process instead of its own.
bool in_process_gpu; bool in_process_gpu;
// True if the GPU process is using the passthrough command decoder. // True if the GPU process is using the passthrough command decoder.
bool passthrough_cmd_decoder; bool passthrough_cmd_decoder;
// True only on android when extensions for threaded mailbox sharing are // True only on android when extensions for threaded mailbox sharing are
// present. Threaded mailbox sharing is used on Android only, so this check // present. Threaded mailbox sharing is used on Android only, so this check
// is only implemented on Android. // is only implemented on Android.
bool can_support_threaded_texture_mailbox = false; bool can_support_threaded_texture_mailbox = false;
#if defined(OS_WIN) #if defined(OS_WIN)
// True if we use direct composition surface on Windows. // True if we use direct composition surface on Windows.
bool direct_composition = false; bool direct_composition = false;
// True if we use direct composition surface overlays on Windows. // True if we use direct composition surface overlays on Windows.
bool supports_overlays = false; bool supports_overlays = false;
OverlayCapabilities overlay_capabilities; OverlayCapabilities overlay_capabilities;
// The information returned by the DirectX Diagnostics Tool. // The information returned by the DirectX Diagnostics Tool.
DxDiagNode dx_diagnostics; DxDiagNode dx_diagnostics;
Dx12VulkanVersionInfo dx12_vulkan_version_info; Dx12VulkanVersionInfo dx12_vulkan_version_info;
#endif #endif
VideoDecodeAcceleratorCapabilities video_decode_accelerator_capabilities; VideoDecodeAcceleratorCapabilities video_decode_accelerator_capabilities;
VideoEncodeAcceleratorSupportedProfiles VideoEncodeAcceleratorSupportedProfiles video_encode_accelerator_supported_profiles;
video_encode_accelerator_supported_profiles; bool jpeg_decode_accelerator_supported;
bool jpeg_decode_accelerator_supported;
ImageDecodeAcceleratorSupportedProfiles ImageDecodeAcceleratorSupportedProfiles image_decode_accelerator_supported_profiles;
image_decode_accelerator_supported_profiles;
#if defined(USE_X11) #if defined(USE_X11)
VisualID system_visual; VisualID system_visual;
VisualID rgba_visual; VisualID rgba_visual;
#endif #endif
bool oop_rasterization_supported; bool oop_rasterization_supported;
// Note: when adding new members, please remember to update EnumerateFields // Note: when adding new members, please remember to update EnumerateFields
// in gpu_info.cc. // in gpu_info.cc.
// In conjunction with EnumerateFields, this allows the embedder to // In conjunction with EnumerateFields, this allows the embedder to
// enumerate the values in this structure without having to embed // enumerate the values in this structure without having to embed
// references to its specific member variables. This simplifies the // references to its specific member variables. This simplifies the
// addition of new fields to this type. // addition of new fields to this type.
class Enumerator { class Enumerator
public: {
// The following methods apply to the "current" object. Initially this public:
// is the root object, but calls to BeginGPUDevice/EndGPUDevice and // The following methods apply to the "current" object. Initially this
// BeginAuxAttributes/EndAuxAttributes change the object to which these // is the root object, but calls to BeginGPUDevice/EndGPUDevice and
// calls should apply. // BeginAuxAttributes/EndAuxAttributes change the object to which these
virtual void AddInt64(const char* name, int64_t value) = 0; // calls should apply.
virtual void AddInt(const char* name, int value) = 0; virtual void AddInt64(const char *name, int64_t value) = 0;
virtual void AddString(const char* name, const std::string& value) = 0; virtual void AddInt(const char *name, int value) = 0;
virtual void AddBool(const char* name, bool value) = 0; virtual void AddString(const char *name, const std::string &value) = 0;
virtual void AddTimeDeltaInSecondsF(const char* name, virtual void AddBool(const char *name, bool value) = 0;
const base::TimeDelta& value) = 0; virtual void AddTimeDeltaInSecondsF(const char *name, const base::TimeDelta &value) = 0;
// Markers indicating that a GPUDevice is being described. // Markers indicating that a GPUDevice is being described.
virtual void BeginGPUDevice() = 0; virtual void BeginGPUDevice() = 0;
virtual void EndGPUDevice() = 0; virtual void EndGPUDevice() = 0;
// Markers indicating that a VideoDecodeAcceleratorSupportedProfile is // Markers indicating that a VideoDecodeAcceleratorSupportedProfile is
// being described. // being described.
virtual void BeginVideoDecodeAcceleratorSupportedProfile() = 0; virtual void BeginVideoDecodeAcceleratorSupportedProfile() = 0;
virtual void EndVideoDecodeAcceleratorSupportedProfile() = 0; virtual void EndVideoDecodeAcceleratorSupportedProfile() = 0;
// Markers indicating that a VideoEncodeAcceleratorSupportedProfile is // Markers indicating that a VideoEncodeAcceleratorSupportedProfile is
// being described. // being described.
virtual void BeginVideoEncodeAcceleratorSupportedProfile() = 0; virtual void BeginVideoEncodeAcceleratorSupportedProfile() = 0;
virtual void EndVideoEncodeAcceleratorSupportedProfile() = 0; virtual void EndVideoEncodeAcceleratorSupportedProfile() = 0;
// Markers indicating that an ImageDecodeAcceleratorSupportedProfile is // Markers indicating that an ImageDecodeAcceleratorSupportedProfile is
// being described. // being described.
virtual void BeginImageDecodeAcceleratorSupportedProfile() = 0; virtual void BeginImageDecodeAcceleratorSupportedProfile() = 0;
virtual void EndImageDecodeAcceleratorSupportedProfile() = 0; virtual void EndImageDecodeAcceleratorSupportedProfile() = 0;
// Markers indicating that "auxiliary" attributes of the GPUInfo // Markers indicating that "auxiliary" attributes of the GPUInfo
// (according to the DevTools protocol) are being described. // (according to the DevTools protocol) are being described.
virtual void BeginAuxAttributes() = 0; virtual void BeginAuxAttributes() = 0;
virtual void EndAuxAttributes() = 0; virtual void EndAuxAttributes() = 0;
virtual void BeginOverlayCapability() = 0; virtual void BeginOverlayCapability() = 0;
virtual void EndOverlayCapability() = 0; virtual void EndOverlayCapability() = 0;
virtual void BeginDx12VulkanVersionInfo() = 0; virtual void BeginDx12VulkanVersionInfo() = 0;
virtual void EndDx12VulkanVersionInfo() = 0; virtual void EndDx12VulkanVersionInfo() = 0;
protected: protected:
virtual ~Enumerator() = default; virtual ~Enumerator() = default;
}; };
// Outputs the fields in this structure to the provided enumerator. // Outputs the fields in this structure to the provided enumerator.
void EnumerateFields(Enumerator* enumerator) const; void EnumerateFields(Enumerator *enumerator) const;
}; };
} // namespace gpu } // namespace gpu
......
...@@ -11,358 +11,400 @@ ...@@ -11,358 +11,400 @@
#include "gpu_test_expectations_parser.h" #include "gpu_test_expectations_parser.h"
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
#include "gpu_test_config_mac.h" # include "gpu_test_config_mac.h"
#endif #endif
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
#include "gpu_info_util/SystemInfo.h" # include "gpu_info_util/SystemInfo.h"
#endif #endif
#if defined(OS_WIN) #if defined(OS_WIN)
namespace base { namespace base
namespace { {
namespace
{
// Disable the deprecated function warning for GetVersionEx // Disable the deprecated function warning for GetVersionEx
#pragma warning(disable: 4996) # pragma warning(disable : 4996)
class SysInfo class SysInfo
{ {
public: public:
static void OperatingSystemVersionNumbers( static void OperatingSystemVersionNumbers(int32_t *major_version,
int32_t *major_version, int32_t *minor_version, int32_t *bugfix_version); int32_t *minor_version,
int32_t *bugfix_version);
}; };
// static // static
void SysInfo::OperatingSystemVersionNumbers( void SysInfo::OperatingSystemVersionNumbers(int32_t *major_version,
int32_t *major_version, int32_t *minor_version, int32_t *bugfix_version) int32_t *minor_version,
int32_t *bugfix_version)
{ {
OSVERSIONINFOEX version_info = { sizeof version_info }; OSVERSIONINFOEX version_info = {sizeof version_info};
::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); ::GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&version_info));
*major_version = version_info.dwMajorVersion; *major_version = version_info.dwMajorVersion;
*minor_version = version_info.dwMinorVersion; *minor_version = version_info.dwMinorVersion;
*bugfix_version = version_info.dwBuildNumber; *bugfix_version = version_info.dwBuildNumber;
} }
} // anonymous namespace } // anonymous namespace
} // namespace base } // namespace base
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
namespace gpu { namespace gpu
{
namespace { namespace
{
GPUTestConfig::OS GetCurrentOS() { GPUTestConfig::OS GetCurrentOS()
{
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
return GPUTestConfig::kOsChromeOS; return GPUTestConfig::kOsChromeOS;
#elif defined(OS_LINUX) || defined(OS_OPENBSD) #elif defined(OS_LINUX) || defined(OS_OPENBSD)
return GPUTestConfig::kOsLinux; return GPUTestConfig::kOsLinux;
#elif defined(OS_WIN) #elif defined(OS_WIN)
int32_t major_version = 0; int32_t major_version = 0;
int32_t minor_version = 0; int32_t minor_version = 0;
int32_t bugfix_version = 0; int32_t bugfix_version = 0;
base::SysInfo::OperatingSystemVersionNumbers( base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, &bugfix_version);
&major_version, &minor_version, &bugfix_version); if (major_version == 5)
if (major_version == 5) return GPUTestConfig::kOsWinXP;
return GPUTestConfig::kOsWinXP; if (major_version == 6 && minor_version == 0)
if (major_version == 6 && minor_version == 0) return GPUTestConfig::kOsWinVista;
return GPUTestConfig::kOsWinVista; if (major_version == 6 && minor_version == 1)
if (major_version == 6 && minor_version == 1) return GPUTestConfig::kOsWin7;
return GPUTestConfig::kOsWin7; if (major_version == 6 && (minor_version == 2 || minor_version == 3))
if (major_version == 6 && (minor_version == 2 || minor_version == 3)) return GPUTestConfig::kOsWin8;
return GPUTestConfig::kOsWin8; if (major_version == 10)
if (major_version == 10) return GPUTestConfig::kOsWin10;
return GPUTestConfig::kOsWin10;
#elif defined(OS_MACOSX) #elif defined(OS_MACOSX)
int32_t major_version = 0; int32_t major_version = 0;
int32_t minor_version = 0; int32_t minor_version = 0;
int32_t bugfix_version = 0; int32_t bugfix_version = 0;
angle::GetOperatingSystemVersionNumbers(&major_version, &minor_version, &bugfix_version); angle::GetOperatingSystemVersionNumbers(&major_version, &minor_version, &bugfix_version);
if (major_version == 10) { if (major_version == 10)
switch (minor_version) { {
case 5: switch (minor_version)
return GPUTestConfig::kOsMacLeopard; {
case 6: case 5:
return GPUTestConfig::kOsMacSnowLeopard; return GPUTestConfig::kOsMacLeopard;
case 7: case 6:
return GPUTestConfig::kOsMacLion; return GPUTestConfig::kOsMacSnowLeopard;
case 8: case 7:
return GPUTestConfig::kOsMacMountainLion; return GPUTestConfig::kOsMacLion;
case 9: case 8:
return GPUTestConfig::kOsMacMavericks; return GPUTestConfig::kOsMacMountainLion;
case 10: case 9:
return GPUTestConfig::kOsMacYosemite; return GPUTestConfig::kOsMacMavericks;
case 11: case 10:
return GPUTestConfig::kOsMacElCapitan; return GPUTestConfig::kOsMacYosemite;
case 12: case 11:
return GPUTestConfig::kOsMacSierra; return GPUTestConfig::kOsMacElCapitan;
case 13: case 12:
return GPUTestConfig::kOsMacHighSierra; return GPUTestConfig::kOsMacSierra;
case 14: case 13:
return GPUTestConfig::kOsMacMojave; return GPUTestConfig::kOsMacHighSierra;
case 14:
return GPUTestConfig::kOsMacMojave;
}
} }
}
#elif defined(OS_ANDROID) #elif defined(OS_ANDROID)
return GPUTestConfig::kOsAndroid; return GPUTestConfig::kOsAndroid;
#elif defined(OS_FUCHSIA) #elif defined(OS_FUCHSIA)
return GPUTestConfig::kOsFuchsia; return GPUTestConfig::kOsFuchsia;
#endif #endif
return GPUTestConfig::kOsUnknown; return GPUTestConfig::kOsUnknown;
} }
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) { bool CollectBasicGraphicsInfo(GPUInfo *gpu_info)
angle::SystemInfo info; {
if (!angle::GetSystemInfo(&info)) { angle::SystemInfo info;
return false; if (!angle::GetSystemInfo(&info))
} {
const angle::GPUDeviceInfo& gpu = info.gpus[info.primaryGPUIndex]; return false;
gpu_info->gpu.vendor_id = gpu.vendorId; }
gpu_info->gpu.device_id = gpu.deviceId; const angle::GPUDeviceInfo &gpu = info.gpus[info.primaryGPUIndex];
gpu_info->gpu.active = true; gpu_info->gpu.vendor_id = gpu.vendorId;
return true; gpu_info->gpu.device_id = gpu.deviceId;
gpu_info->gpu.active = true;
return true;
} }
#else #else
bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) { bool CollectBasicGraphicsInfo(GPUInfo *gpu_info)
gpu_info->gpu.vendor_id = 0; {
gpu_info->gpu.device_id = 0; gpu_info->gpu.vendor_id = 0;
gpu_info->gpu.active = true; gpu_info->gpu.device_id = 0;
return false; gpu_info->gpu.active = true;
return false;
} }
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
} // namespace anonymous } // namespace
GPUTestConfig::GPUTestConfig() GPUTestConfig::GPUTestConfig()
: validate_gpu_info_(true), : validate_gpu_info_(true),
os_(kOsUnknown), os_(kOsUnknown),
gpu_device_id_(0), gpu_device_id_(0),
build_type_(kBuildTypeUnknown), build_type_(kBuildTypeUnknown),
api_(kAPIUnknown) {} api_(kAPIUnknown)
{}
GPUTestConfig::GPUTestConfig(const GPUTestConfig& other) = default; GPUTestConfig::GPUTestConfig(const GPUTestConfig &other) = default;
GPUTestConfig::~GPUTestConfig() = default; GPUTestConfig::~GPUTestConfig() = default;
void GPUTestConfig::set_os(int32_t os) { void GPUTestConfig::set_os(int32_t os)
DCHECK_EQ(0, os & ~(kOsAndroid | kOsWin | kOsMac | kOsLinux | kOsChromeOS | {
kOsFuchsia)); DCHECK_EQ(0, os & ~(kOsAndroid | kOsWin | kOsMac | kOsLinux | kOsChromeOS | kOsFuchsia));
os_ = os; os_ = os;
} }
void GPUTestConfig::AddGPUVendor(uint32_t gpu_vendor) { void GPUTestConfig::AddGPUVendor(uint32_t gpu_vendor)
DCHECK_NE(0u, gpu_vendor); {
for (size_t i = 0; i < gpu_vendor_.size(); ++i) DCHECK_NE(0u, gpu_vendor);
DCHECK_NE(gpu_vendor_[i], gpu_vendor); for (size_t i = 0; i < gpu_vendor_.size(); ++i)
gpu_vendor_.push_back(gpu_vendor); DCHECK_NE(gpu_vendor_[i], gpu_vendor);
gpu_vendor_.push_back(gpu_vendor);
} }
void GPUTestConfig::set_gpu_device_id(uint32_t id) { void GPUTestConfig::set_gpu_device_id(uint32_t id)
gpu_device_id_ = id; {
gpu_device_id_ = id;
} }
void GPUTestConfig::set_build_type(int32_t build_type) { void GPUTestConfig::set_build_type(int32_t build_type)
DCHECK_EQ(0, build_type & ~(kBuildTypeRelease | kBuildTypeDebug)); {
build_type_ = build_type; DCHECK_EQ(0, build_type & ~(kBuildTypeRelease | kBuildTypeDebug));
build_type_ = build_type;
} }
void GPUTestConfig::set_api(int32_t api) { void GPUTestConfig::set_api(int32_t api)
DCHECK_EQ(0, api & ~(kAPID3D9 | kAPID3D11 | kAPIGLDesktop | kAPIGLES | kAPIVulkan)); {
api_ = api; DCHECK_EQ(0, api & ~(kAPID3D9 | kAPID3D11 | kAPIGLDesktop | kAPIGLES | kAPIVulkan));
api_ = api;
} }
bool GPUTestConfig::IsValid() const { bool GPUTestConfig::IsValid() const
if (!validate_gpu_info_) {
if (!validate_gpu_info_)
return true;
if (gpu_device_id_ != 0 && (gpu_vendor_.size() != 1 || gpu_vendor_[0] == 0))
return false;
return true; return true;
if (gpu_device_id_ != 0 && (gpu_vendor_.size() != 1 || gpu_vendor_[0] == 0))
return false;
return true;
} }
bool GPUTestConfig::OverlapsWith(const GPUTestConfig& config) const { bool GPUTestConfig::OverlapsWith(const GPUTestConfig &config) const
DCHECK(IsValid()); {
DCHECK(config.IsValid()); DCHECK(IsValid());
if (config.os_ != kOsUnknown && os_ != kOsUnknown && DCHECK(config.IsValid());
(os_ & config.os_) == 0) if (config.os_ != kOsUnknown && os_ != kOsUnknown && (os_ & config.os_) == 0)
return false; return false;
if (config.gpu_vendor_.size() > 0 && gpu_vendor_.size() > 0) { if (config.gpu_vendor_.size() > 0 && gpu_vendor_.size() > 0)
bool shared = false; {
for (size_t i = 0; i < config.gpu_vendor_.size() && !shared; ++i) { bool shared = false;
for (size_t j = 0; j < gpu_vendor_.size(); ++j) { for (size_t i = 0; i < config.gpu_vendor_.size() && !shared; ++i)
if (config.gpu_vendor_[i] == gpu_vendor_[j]) { {
shared = true; for (size_t j = 0; j < gpu_vendor_.size(); ++j)
break; {
if (config.gpu_vendor_[i] == gpu_vendor_[j])
{
shared = true;
break;
}
}
} }
} if (!shared)
return false;
} }
if (!shared) if (config.gpu_device_id_ != 0 && gpu_device_id_ != 0 &&
return false; gpu_device_id_ != config.gpu_device_id_)
} return false;
if (config.gpu_device_id_ != 0 && gpu_device_id_ != 0 && if (config.build_type_ != kBuildTypeUnknown && build_type_ != kBuildTypeUnknown &&
gpu_device_id_ != config.gpu_device_id_) (build_type_ & config.build_type_) == 0)
return false; return false;
if (config.build_type_ != kBuildTypeUnknown && if (config.api() != kAPIUnknown && api_ != kAPIUnknown && api_ != config.api_)
build_type_ != kBuildTypeUnknown && return false;
(build_type_ & config.build_type_) == 0) return true;
return false;
if (config.api() != kAPIUnknown && api_ != kAPIUnknown && api_ != config.api_)
return false;
return true;
} }
void GPUTestConfig::DisableGPUInfoValidation() { void GPUTestConfig::DisableGPUInfoValidation()
validate_gpu_info_ = false; {
validate_gpu_info_ = false;
} }
void GPUTestConfig::ClearGPUVendor() { void GPUTestConfig::ClearGPUVendor()
gpu_vendor_.clear(); {
gpu_vendor_.clear();
} }
GPUTestBotConfig::~GPUTestBotConfig() = default; GPUTestBotConfig::~GPUTestBotConfig() = default;
void GPUTestBotConfig::AddGPUVendor(uint32_t gpu_vendor) { void GPUTestBotConfig::AddGPUVendor(uint32_t gpu_vendor)
DCHECK_EQ(0u, GPUTestConfig::gpu_vendor().size()); {
GPUTestConfig::AddGPUVendor(gpu_vendor); DCHECK_EQ(0u, GPUTestConfig::gpu_vendor().size());
GPUTestConfig::AddGPUVendor(gpu_vendor);
} }
bool GPUTestBotConfig::SetGPUInfo(const GPUInfo& gpu_info) { bool GPUTestBotConfig::SetGPUInfo(const GPUInfo &gpu_info)
DCHECK(validate_gpu_info_); {
if (gpu_info.gpu.device_id == 0 || gpu_info.gpu.vendor_id == 0) DCHECK(validate_gpu_info_);
return false; if (gpu_info.gpu.device_id == 0 || gpu_info.gpu.vendor_id == 0)
ClearGPUVendor(); return false;
AddGPUVendor(gpu_info.gpu.vendor_id); ClearGPUVendor();
set_gpu_device_id(gpu_info.gpu.device_id); AddGPUVendor(gpu_info.gpu.vendor_id);
return true; set_gpu_device_id(gpu_info.gpu.device_id);
return true;
} }
bool GPUTestBotConfig::IsValid() const { bool GPUTestBotConfig::IsValid() const
switch (os()) { {
case kOsWinXP: switch (os())
case kOsWinVista: {
case kOsWin7: case kOsWinXP:
case kOsWin8: case kOsWinVista:
case kOsWin10: case kOsWin7:
case kOsMacLeopard: case kOsWin8:
case kOsMacSnowLeopard: case kOsWin10:
case kOsMacLion: case kOsMacLeopard:
case kOsMacMountainLion: case kOsMacSnowLeopard:
case kOsMacMavericks: case kOsMacLion:
case kOsMacYosemite: case kOsMacMountainLion:
case kOsMacElCapitan: case kOsMacMavericks:
case kOsMacSierra: case kOsMacYosemite:
case kOsMacHighSierra: case kOsMacElCapitan:
case kOsMacMojave: case kOsMacSierra:
case kOsLinux: case kOsMacHighSierra:
case kOsChromeOS: case kOsMacMojave:
case kOsAndroid: case kOsLinux:
case kOsFuchsia: case kOsChromeOS:
break; case kOsAndroid:
default: case kOsFuchsia:
return false; break;
} default:
if (validate_gpu_info_) { return false;
if (gpu_vendor().size() != 1 || gpu_vendor()[0] == 0) }
return false; if (validate_gpu_info_)
if (gpu_device_id() == 0) {
return false; if (gpu_vendor().size() != 1 || gpu_vendor()[0] == 0)
} return false;
switch (build_type()) { if (gpu_device_id() == 0)
case kBuildTypeRelease: return false;
case kBuildTypeDebug: }
break; switch (build_type())
default: {
return false; case kBuildTypeRelease:
} case kBuildTypeDebug:
return true; break;
default:
return false;
}
return true;
} }
bool GPUTestBotConfig::Matches(const GPUTestConfig& config) const { bool GPUTestBotConfig::Matches(const GPUTestConfig &config) const
DCHECK(IsValid()); {
DCHECK(config.IsValid()); DCHECK(IsValid());
if (config.os() != kOsUnknown && (os() & config.os()) == 0) DCHECK(config.IsValid());
return false; if (config.os() != kOsUnknown && (os() & config.os()) == 0)
if (config.gpu_vendor().size() > 0) { return false;
bool contained = false; if (config.gpu_vendor().size() > 0)
for (size_t i = 0; i < config.gpu_vendor().size(); ++i) { {
if (!gpu_vendor().empty() && config.gpu_vendor()[i] == gpu_vendor()[0]) { bool contained = false;
contained = true; for (size_t i = 0; i < config.gpu_vendor().size(); ++i)
break; {
} if (!gpu_vendor().empty() && config.gpu_vendor()[i] == gpu_vendor()[0])
{
contained = true;
break;
}
}
if (!contained)
return false;
} }
if (!contained) if (config.gpu_device_id() != 0 && gpu_device_id() != config.gpu_device_id())
return false; return false;
} if (config.build_type() != kBuildTypeUnknown && (build_type() & config.build_type()) == 0)
if (config.gpu_device_id() != 0 && return false;
gpu_device_id() != config.gpu_device_id()) if (config.api() != 0 && (api() & config.api()) == 0)
return false; return false;
if (config.build_type() != kBuildTypeUnknown && return true;
(build_type() & config.build_type()) == 0)
return false;
if (config.api() != 0 && (api() & config.api()) == 0)
return false;
return true;
} }
bool GPUTestBotConfig::Matches(const std::string& config_data) const { bool GPUTestBotConfig::Matches(const std::string &config_data) const
GPUTestExpectationsParser parser; {
GPUTestConfig config; GPUTestExpectationsParser parser;
GPUTestConfig config;
if (!parser.ParseConfig(config_data, &config)) if (!parser.ParseConfig(config_data, &config))
return false; return false;
return Matches(config); return Matches(config);
} }
bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo* gpu_info) { bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo *gpu_info)
bool rt; {
if (!gpu_info) { bool rt;
GPUInfo my_gpu_info; if (!gpu_info)
if (!CollectBasicGraphicsInfo(&my_gpu_info)) { {
LOG(ERROR) << "Fail to identify GPU\n"; GPUInfo my_gpu_info;
DisableGPUInfoValidation(); if (!CollectBasicGraphicsInfo(&my_gpu_info))
rt = true; {
} else { LOG(ERROR) << "Fail to identify GPU\n";
rt = SetGPUInfo(my_gpu_info); DisableGPUInfoValidation();
rt = true;
}
else
{
rt = SetGPUInfo(my_gpu_info);
}
}
else
{
rt = SetGPUInfo(*gpu_info);
}
set_os(GetCurrentOS());
if (os() == kOsUnknown)
{
LOG(ERROR) << "Unknown OS\n";
rt = false;
} }
} else {
rt = SetGPUInfo(*gpu_info);
}
set_os(GetCurrentOS());
if (os() == kOsUnknown) {
LOG(ERROR) << "Unknown OS\n";
rt = false;
}
#if defined(NDEBUG) #if defined(NDEBUG)
set_build_type(kBuildTypeRelease); set_build_type(kBuildTypeRelease);
#else #else
set_build_type(kBuildTypeDebug); set_build_type(kBuildTypeDebug);
#endif #endif
return rt; return rt;
} }
// static // static
bool GPUTestBotConfig::CurrentConfigMatches(const std::string& config_data) { bool GPUTestBotConfig::CurrentConfigMatches(const std::string &config_data)
GPUTestBotConfig my_config; {
if (!my_config.LoadCurrentConfig(nullptr)) GPUTestBotConfig my_config;
return false; if (!my_config.LoadCurrentConfig(nullptr))
return my_config.Matches(config_data); return false;
return my_config.Matches(config_data);
} }
// static // static
bool GPUTestBotConfig::CurrentConfigMatches( bool GPUTestBotConfig::CurrentConfigMatches(const std::vector<std::string> &configs)
const std::vector<std::string>& configs) { {
GPUTestBotConfig my_config; GPUTestBotConfig my_config;
if (!my_config.LoadCurrentConfig(nullptr)) if (!my_config.LoadCurrentConfig(nullptr))
return false;
for (size_t i = 0; i < configs.size(); ++i)
{
if (my_config.Matches(configs[i]))
return true;
}
return false; return false;
for (size_t i = 0 ; i < configs.size(); ++i) {
if (my_config.Matches(configs[i]))
return true;
}
return false;
} }
// static // static
bool GPUTestBotConfig::GpuBlacklistedOnBot() { bool GPUTestBotConfig::GpuBlacklistedOnBot()
return false; {
return false;
} }
} // namespace gpu } // namespace gpu
// // Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
//
// angle_config.h:
// Helpers for importing the gpu test expectations package from Chrome.
//
#ifndef ANGLE_GPU_TEST_EXPECTATIONS_ANGLE_CONFIG_H_ #ifndef ANGLE_GPU_CONFIG_GPU_TEST_CONFIG_H_
#define ANGLE_GPU_TEST_EXPECTATIONS_ANGLE_CONFIG_H_ #define ANGLE_GPU_CONFIG_GPU_TEST_CONFIG_H_
#include <stdint.h> #include <stdint.h>
#include <iostream> #include <iostream>
#include <string>
#include <vector>
#include "common/debug.h" #include "common/debug.h"
#include "common/string_utils.h" #include "common/string_utils.h"
...@@ -73,4 +69,145 @@ struct DxDiagNode ...@@ -73,4 +69,145 @@ struct DxDiagNode
#endif #endif
// clang-format on // clang-format on
#endif namespace gpu
{
struct GPUInfo;
class GPU_EXPORT GPUTestConfig
{
public:
enum OS
{
kOsUnknown = 0,
kOsWinXP = 1 << 0,
kOsWinVista = 1 << 1,
kOsWin7 = 1 << 2,
kOsWin8 = 1 << 3,
kOsMacLeopard = 1 << 4,
kOsMacSnowLeopard = 1 << 5,
kOsMacLion = 1 << 6,
kOsMacMountainLion = 1 << 7,
kOsMacMavericks = 1 << 8,
kOsMacYosemite = 1 << 9,
kOsMacElCapitan = 1 << 10,
kOsMacSierra = 1 << 11,
kOsMacHighSierra = 1 << 12,
kOsMacMojave = 1 << 13,
kOsMac = kOsMacLeopard | kOsMacSnowLeopard | kOsMacLion | kOsMacMountainLion |
kOsMacMavericks | kOsMacYosemite | kOsMacElCapitan | kOsMacSierra |
kOsMacHighSierra | kOsMacMojave,
kOsLinux = 1 << 14,
kOsChromeOS = 1 << 15,
kOsAndroid = 1 << 16,
kOsWin10 = 1 << 17,
kOsWin = kOsWinXP | kOsWinVista | kOsWin7 | kOsWin8 | kOsWin10,
kOsFuchsia = 1 << 18,
};
enum BuildType
{
kBuildTypeUnknown = 0,
kBuildTypeRelease = 1 << 0,
kBuildTypeDebug = 1 << 1,
};
enum API
{
kAPIUnknown = 0,
kAPID3D9 = 1 << 0,
kAPID3D11 = 1 << 1,
kAPIGLDesktop = 1 << 2,
kAPIGLES = 1 << 3,
kAPIVulkan = 1 << 4,
};
GPUTestConfig();
GPUTestConfig(const GPUTestConfig &other);
virtual ~GPUTestConfig();
void set_os(int32_t os);
void set_gpu_device_id(uint32_t id);
void set_build_type(int32_t build_type);
void set_api(int32_t api);
virtual void AddGPUVendor(uint32_t gpu_vendor);
int32_t os() const { return os_; }
const std::vector<uint32_t> &gpu_vendor() const { return gpu_vendor_; }
uint32_t gpu_device_id() const { return gpu_device_id_; }
int32_t build_type() const { return build_type_; }
int32_t api() const { return api_; }
// Check if the config is valid. For example, if gpu_device_id_ is set, but
// gpu_vendor_ is unknown, then it's invalid.
virtual bool IsValid() const;
// Check if two configs overlap, i.e., if there exists a config that matches
// both configs.
bool OverlapsWith(const GPUTestConfig &config) const;
// Disable validation of GPU vendor and device ids.
void DisableGPUInfoValidation();
protected:
void ClearGPUVendor();
// Indicates that the OS has the notion of a numeric GPU vendor and device id
// and this data should be validated.
bool validate_gpu_info_;
private:
// operating system.
int32_t os_;
// GPU vendor.
std::vector<uint32_t> gpu_vendor_;
// GPU device id (unique to each vendor).
uint32_t gpu_device_id_;
// Release or Debug.
int32_t build_type_;
// Back-end rendering APIs.
int32_t api_;
};
class GPU_EXPORT GPUTestBotConfig : public GPUTestConfig
{
public:
GPUTestBotConfig() = default;
~GPUTestBotConfig() override;
// This should only be called when no gpu_vendor is added.
void AddGPUVendor(uint32_t gpu_vendor) override;
// Return false if gpu_info does not have valid vendor_id and device_id.
bool SetGPUInfo(const GPUInfo &gpu_info);
// Check if the bot config is valid, i.e., if it is one valid test-bot
// environment. For example, if a field is unknown, or if OS is not one
// fully defined OS, then it's valid.
bool IsValid() const override;
// Check if a bot config matches a test config, i.e., the test config is a
// superset of the bot config.
bool Matches(const GPUTestConfig &config) const;
bool Matches(const std::string &config_data) const;
// Setup the config with the current gpu testing environment.
// If gpu_info is nullptr, collect GPUInfo first.
bool LoadCurrentConfig(const GPUInfo *gpu_info);
// Check if this bot's config matches |config_data| or any of the |configs|.
static bool CurrentConfigMatches(const std::string &config_data);
static bool CurrentConfigMatches(const std::vector<std::string> &configs);
// Check if the bot has blacklisted all GPU features.
static bool GpuBlacklistedOnBot();
};
} // namespace gpu
#endif // ANGLE_GPU_CONFIG_GPU_TEST_CONFIG_H_
...@@ -46,4 +46,4 @@ void GetOperatingSystemVersionNumbers(int32_t *major_version, ...@@ -46,4 +46,4 @@ void GetOperatingSystemVersionNumbers(int32_t *major_version,
#endif #endif
} }
} // namespace angle } // namespace angle
...@@ -7,114 +7,122 @@ ...@@ -7,114 +7,122 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "angle_config.h"
#include "common/angleutils.h" #include "common/angleutils.h"
namespace base { namespace base
{
namespace { namespace
{
bool StartsWithASCII(const std::string& str, bool StartsWithASCII(const std::string &str, const std::string &search, bool case_sensitive)
const std::string& search, {
bool case_sensitive) { ASSERT(!case_sensitive);
ASSERT(!case_sensitive); return str.compare(0, search.length(), search) == 0;
return str.compare(0, search.length(), search) == 0;
} }
template <class Char> inline Char ToLowerASCII(Char c) { template <class Char>
return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c; inline Char ToLowerASCII(Char c)
{
return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c;
} }
template<typename Iter> template <typename Iter>
static inline bool DoLowerCaseEqualsASCII(Iter a_begin, static inline bool DoLowerCaseEqualsASCII(Iter a_begin, Iter a_end, const char *b)
Iter a_end, {
const char* b) { for (Iter it = a_begin; it != a_end; ++it, ++b)
for (Iter it = a_begin; it != a_end; ++it, ++b) { {
if (!*b || base::ToLowerASCII(*it) != *b) if (!*b || base::ToLowerASCII(*it) != *b)
return false; return false;
} }
return *b == 0; return *b == 0;
} }
bool LowerCaseEqualsASCII(const std::string& a, const char* b) { bool LowerCaseEqualsASCII(const std::string &a, const char *b)
return DoLowerCaseEqualsASCII(a.begin(), a.end(), b); {
return DoLowerCaseEqualsASCII(a.begin(), a.end(), b);
} }
} // anonymous namespace } // anonymous namespace
} // namespace base } // namespace base
namespace gpu { namespace gpu
{
namespace { namespace
{
enum LineParserStage { enum LineParserStage
kLineParserBegin = 0, {
kLineParserBugID, kLineParserBegin = 0,
kLineParserConfigs, kLineParserBugID,
kLineParserColon, kLineParserConfigs,
kLineParserTestName, kLineParserColon,
kLineParserEqual, kLineParserTestName,
kLineParserExpectations, kLineParserEqual,
kLineParserExpectations,
}; };
enum Token { enum Token
// os {
kConfigWinXP = 0, // os
kConfigWinVista, kConfigWinXP = 0,
kConfigWin7, kConfigWinVista,
kConfigWin8, kConfigWin7,
kConfigWin10, kConfigWin8,
kConfigWin, kConfigWin10,
kConfigMacLeopard, kConfigWin,
kConfigMacSnowLeopard, kConfigMacLeopard,
kConfigMacLion, kConfigMacSnowLeopard,
kConfigMacMountainLion, kConfigMacLion,
kConfigMacMavericks, kConfigMacMountainLion,
kConfigMacYosemite, kConfigMacMavericks,
kConfigMacElCapitan, kConfigMacYosemite,
kConfigMacSierra, kConfigMacElCapitan,
kConfigMacHighSierra, kConfigMacSierra,
kConfigMacMojave, kConfigMacHighSierra,
kConfigMac, kConfigMacMojave,
kConfigLinux, kConfigMac,
kConfigChromeOS, kConfigLinux,
kConfigAndroid, kConfigChromeOS,
// gpu vendor kConfigAndroid,
kConfigNVidia, // gpu vendor
kConfigAMD, kConfigNVidia,
kConfigIntel, kConfigAMD,
kConfigVMWare, kConfigIntel,
// build type kConfigVMWare,
kConfigRelease, // build type
kConfigDebug, kConfigRelease,
// ANGLE renderer kConfigDebug,
kConfigD3D9, // ANGLE renderer
kConfigD3D11, kConfigD3D9,
kConfigGLDesktop, kConfigD3D11,
kConfigGLES, kConfigGLDesktop,
kConfigVulkan, kConfigGLES,
// expectation kConfigVulkan,
kExpectationPass, // expectation
kExpectationFail, kExpectationPass,
kExpectationFlaky, kExpectationFail,
kExpectationTimeout, kExpectationFlaky,
kExpectationSkip, kExpectationTimeout,
// separator kExpectationSkip,
kSeparatorColon, // separator
kSeparatorEqual, kSeparatorColon,
kSeparatorEqual,
kNumberOfExactMatchTokens,
kNumberOfExactMatchTokens,
// others
kConfigGPUDeviceID, // others
kTokenComment, kConfigGPUDeviceID,
kTokenWord, kTokenComment,
kTokenWord,
}; };
struct TokenInfo { struct TokenInfo
const char* name; {
int32_t flag; const char *name;
int32_t flag;
}; };
const TokenInfo kTokenData[] = { const TokenInfo kTokenData[] = {
...@@ -158,22 +166,23 @@ const TokenInfo kTokenData[] = { ...@@ -158,22 +166,23 @@ const TokenInfo kTokenData[] = {
{"=", 0}, {"=", 0},
}; };
enum ErrorType { enum ErrorType
kErrorFileIO = 0, {
kErrorIllegalEntry, kErrorFileIO = 0,
kErrorInvalidEntry, kErrorIllegalEntry,
kErrorEntryWithOsConflicts, kErrorInvalidEntry,
kErrorEntryWithGpuVendorConflicts, kErrorEntryWithOsConflicts,
kErrorEntryWithBuildTypeConflicts, kErrorEntryWithGpuVendorConflicts,
kErrorEntryWithAPIConflicts, kErrorEntryWithBuildTypeConflicts,
kErrorEntryWithGpuDeviceIdConflicts, kErrorEntryWithAPIConflicts,
kErrorEntryWithExpectationConflicts, kErrorEntryWithGpuDeviceIdConflicts,
kErrorEntriesOverlap, kErrorEntryWithExpectationConflicts,
kErrorEntriesOverlap,
kNumberOfErrors,
kNumberOfErrors,
}; };
const char* kErrorMessage[] = { const char *kErrorMessage[] = {
"file IO failed", "file IO failed",
"entry with wrong format", "entry with wrong format",
"entry invalid, likely wrong modifiers combination", "entry invalid, likely wrong modifiers combination",
...@@ -186,418 +195,440 @@ const char* kErrorMessage[] = { ...@@ -186,418 +195,440 @@ const char* kErrorMessage[] = {
"two entries' configs overlap", "two entries' configs overlap",
}; };
Token ParseToken(const std::string& word) { Token ParseToken(const std::string &word)
if (base::StartsWithASCII(word, "//", false)) {
return kTokenComment; if (base::StartsWithASCII(word, "//", false))
if (base::StartsWithASCII(word, "0x", false)) return kTokenComment;
return kConfigGPUDeviceID; if (base::StartsWithASCII(word, "0x", false))
return kConfigGPUDeviceID;
for (int32_t i = 0; i < kNumberOfExactMatchTokens; ++i) {
if (base::LowerCaseEqualsASCII(word, kTokenData[i].name)) for (int32_t i = 0; i < kNumberOfExactMatchTokens; ++i)
return static_cast<Token>(i); {
} if (base::LowerCaseEqualsASCII(word, kTokenData[i].name))
return kTokenWord; return static_cast<Token>(i);
}
return kTokenWord;
} }
// reference name can have the last character as *. // reference name can have the last character as *.
bool NamesMatching(const std::string& ref, const std::string& test_name) { bool NamesMatching(const std::string &ref, const std::string &test_name)
size_t len = ref.length(); {
if (len == 0) size_t len = ref.length();
return false; if (len == 0)
if (ref[len - 1] == '*') { return false;
if (test_name.length() > len -1 && if (ref[len - 1] == '*')
ref.compare(0, len - 1, test_name, 0, len - 1) == 0) {
return true; if (test_name.length() > len - 1 && ref.compare(0, len - 1, test_name, 0, len - 1) == 0)
return false; return true;
} return false;
return (ref == test_name); }
return (ref == test_name);
} }
} // namespace anonymous } // namespace
GPUTestExpectationsParser::GPUTestExpectationsParser() { GPUTestExpectationsParser::GPUTestExpectationsParser()
// Some sanity check. {
DCHECK_EQ(static_cast<unsigned int>(kNumberOfExactMatchTokens), // Some sanity check.
sizeof(kTokenData) / sizeof(kTokenData[0])); DCHECK_EQ(static_cast<unsigned int>(kNumberOfExactMatchTokens),
DCHECK_EQ(static_cast<unsigned int>(kNumberOfErrors), sizeof(kTokenData) / sizeof(kTokenData[0]));
sizeof(kErrorMessage) / sizeof(kErrorMessage[0])); DCHECK_EQ(static_cast<unsigned int>(kNumberOfErrors),
sizeof(kErrorMessage) / sizeof(kErrorMessage[0]));
} }
GPUTestExpectationsParser::~GPUTestExpectationsParser() = default; GPUTestExpectationsParser::~GPUTestExpectationsParser() = default;
bool GPUTestExpectationsParser::LoadTestExpectations(const std::string& data) { bool GPUTestExpectationsParser::LoadTestExpectations(const std::string &data)
entries_.clear(); {
error_messages_.clear();
std::vector<std::string> lines = base::SplitString(
data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
bool rt = true;
for (size_t i = 0; i < lines.size(); ++i) {
if (!ParseLine(lines[i], i + 1))
rt = false;
}
if (DetectConflictsBetweenEntries()) {
entries_.clear(); entries_.clear();
rt = false; error_messages_.clear();
}
std::vector<std::string> lines =
base::SplitString(data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
bool rt = true;
for (size_t i = 0; i < lines.size(); ++i)
{
if (!ParseLine(lines[i], i + 1))
rt = false;
}
if (DetectConflictsBetweenEntries())
{
entries_.clear();
rt = false;
}
return rt; return rt;
} }
bool GPUTestExpectationsParser::LoadTestExpectationsFromFile( bool GPUTestExpectationsParser::LoadTestExpectationsFromFile(const std::string &path)
const std::string& path) { {
entries_.clear(); entries_.clear();
error_messages_.clear(); error_messages_.clear();
std::string data; std::string data;
if (!base::ReadFileToString(path, &data)) { if (!base::ReadFileToString(path, &data))
error_messages_.push_back(kErrorMessage[kErrorFileIO]); {
return false; error_messages_.push_back(kErrorMessage[kErrorFileIO]);
} return false;
return LoadTestExpectations(data); }
return LoadTestExpectations(data);
} }
int32_t GPUTestExpectationsParser::GetTestExpectation( int32_t GPUTestExpectationsParser::GetTestExpectation(const std::string &test_name,
const std::string& test_name, const GPUTestBotConfig &bot_config) const
const GPUTestBotConfig& bot_config) const { {
for (size_t i = 0; i < entries_.size(); ++i) { for (size_t i = 0; i < entries_.size(); ++i)
if (NamesMatching(entries_[i].test_name, test_name) && {
bot_config.Matches(entries_[i].test_config)) if (NamesMatching(entries_[i].test_name, test_name) &&
return entries_[i].test_expectation; bot_config.Matches(entries_[i].test_config))
} return entries_[i].test_expectation;
return kGpuTestPass; }
return kGpuTestPass;
} }
const std::vector<std::string>& const std::vector<std::string> &GPUTestExpectationsParser::GetErrorMessages() const
GPUTestExpectationsParser::GetErrorMessages() const { {
return error_messages_; return error_messages_;
} }
bool GPUTestExpectationsParser::ParseConfig( bool GPUTestExpectationsParser::ParseConfig(const std::string &config_data, GPUTestConfig *config)
const std::string& config_data, GPUTestConfig* config) { {
DCHECK(config); DCHECK(config);
std::vector<std::string> tokens = base::SplitString( std::vector<std::string> tokens = base::SplitString(
config_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE, config_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
base::SPLIT_WANT_NONEMPTY);
for (size_t i = 0; i < tokens.size(); ++i)
for (size_t i = 0; i < tokens.size(); ++i) { {
Token token = ParseToken(tokens[i]); Token token = ParseToken(tokens[i]);
switch (token) { switch (token)
case kConfigWinXP: {
case kConfigWinVista: case kConfigWinXP:
case kConfigWin7: case kConfigWinVista:
case kConfigWin8: case kConfigWin7:
case kConfigWin10: case kConfigWin8:
case kConfigWin: case kConfigWin10:
case kConfigMacLeopard: case kConfigWin:
case kConfigMacSnowLeopard: case kConfigMacLeopard:
case kConfigMacLion: case kConfigMacSnowLeopard:
case kConfigMacMountainLion: case kConfigMacLion:
case kConfigMacMavericks: case kConfigMacMountainLion:
case kConfigMacYosemite: case kConfigMacMavericks:
case kConfigMacElCapitan: case kConfigMacYosemite:
case kConfigMacSierra: case kConfigMacElCapitan:
case kConfigMacHighSierra: case kConfigMacSierra:
case kConfigMacMojave: case kConfigMacHighSierra:
case kConfigMac: case kConfigMacMojave:
case kConfigLinux: case kConfigMac:
case kConfigChromeOS: case kConfigLinux:
case kConfigAndroid: case kConfigChromeOS:
case kConfigNVidia: case kConfigAndroid:
case kConfigAMD: case kConfigNVidia:
case kConfigIntel: case kConfigAMD:
case kConfigVMWare: case kConfigIntel:
case kConfigRelease: case kConfigVMWare:
case kConfigDebug: case kConfigRelease:
case kConfigD3D9: case kConfigDebug:
case kConfigD3D11: case kConfigD3D9:
case kConfigGLDesktop: case kConfigD3D11:
case kConfigGLES: case kConfigGLDesktop:
case kConfigVulkan: case kConfigGLES:
case kConfigGPUDeviceID: case kConfigVulkan:
if (token == kConfigGPUDeviceID) { case kConfigGPUDeviceID:
if (!UpdateTestConfig(config, tokens[i], 0)) if (token == kConfigGPUDeviceID)
return false; {
} else { if (!UpdateTestConfig(config, tokens[i], 0))
if (!UpdateTestConfig(config, token, 0)) return false;
return false; }
else
{
if (!UpdateTestConfig(config, token, 0))
return false;
}
break;
default:
return false;
} }
break;
default:
return false;
} }
} return true;
return true;
} }
bool GPUTestExpectationsParser::ParseLine( bool GPUTestExpectationsParser::ParseLine(const std::string &line_data, size_t line_number)
const std::string& line_data, size_t line_number) { {
std::vector<std::string> tokens = base::SplitString( std::vector<std::string> tokens = base::SplitString(
line_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE, line_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
base::SPLIT_WANT_NONEMPTY); int32_t stage = kLineParserBegin;
int32_t stage = kLineParserBegin; GPUTestExpectationEntry entry;
GPUTestExpectationEntry entry; entry.line_number = line_number;
entry.line_number = line_number; GPUTestConfig &config = entry.test_config;
GPUTestConfig& config = entry.test_config; bool comments_encountered = false;
bool comments_encountered = false; for (size_t i = 0; i < tokens.size() && !comments_encountered; ++i)
for (size_t i = 0; i < tokens.size() && !comments_encountered; ++i) { {
Token token = ParseToken(tokens[i]); Token token = ParseToken(tokens[i]);
switch (token) { switch (token)
case kTokenComment: {
comments_encountered = true; case kTokenComment:
break; comments_encountered = true;
case kConfigWinXP: break;
case kConfigWinVista: case kConfigWinXP:
case kConfigWin7: case kConfigWinVista:
case kConfigWin8: case kConfigWin7:
case kConfigWin10: case kConfigWin8:
case kConfigWin: case kConfigWin10:
case kConfigMacLeopard: case kConfigWin:
case kConfigMacSnowLeopard: case kConfigMacLeopard:
case kConfigMacLion: case kConfigMacSnowLeopard:
case kConfigMacMountainLion: case kConfigMacLion:
case kConfigMacMavericks: case kConfigMacMountainLion:
case kConfigMacYosemite: case kConfigMacMavericks:
case kConfigMacElCapitan: case kConfigMacYosemite:
case kConfigMacSierra: case kConfigMacElCapitan:
case kConfigMacHighSierra: case kConfigMacSierra:
case kConfigMacMojave: case kConfigMacHighSierra:
case kConfigMac: case kConfigMacMojave:
case kConfigLinux: case kConfigMac:
case kConfigChromeOS: case kConfigLinux:
case kConfigAndroid: case kConfigChromeOS:
case kConfigNVidia: case kConfigAndroid:
case kConfigAMD: case kConfigNVidia:
case kConfigIntel: case kConfigAMD:
case kConfigVMWare: case kConfigIntel:
case kConfigRelease: case kConfigVMWare:
case kConfigDebug: case kConfigRelease:
case kConfigD3D9: case kConfigDebug:
case kConfigD3D11: case kConfigD3D9:
case kConfigGLDesktop: case kConfigD3D11:
case kConfigGLES: case kConfigGLDesktop:
case kConfigVulkan: case kConfigGLES:
case kConfigGPUDeviceID: case kConfigVulkan:
// MODIFIERS, could be in any order, need at least one. case kConfigGPUDeviceID:
if (stage != kLineParserConfigs && stage != kLineParserBugID) { // MODIFIERS, could be in any order, need at least one.
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], if (stage != kLineParserConfigs && stage != kLineParserBugID)
line_number); {
return false; PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
return false;
}
if (token == kConfigGPUDeviceID)
{
if (!UpdateTestConfig(&config, tokens[i], line_number))
return false;
}
else
{
if (!UpdateTestConfig(&config, token, line_number))
return false;
}
if (stage == kLineParserBugID)
stage++;
break;
case kSeparatorColon:
// :
if (stage != kLineParserConfigs)
{
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
return false;
}
stage++;
break;
case kSeparatorEqual:
// =
if (stage != kLineParserTestName)
{
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
return false;
}
stage++;
break;
case kTokenWord:
// BUG_ID or TEST_NAME
if (stage == kLineParserBegin)
{
// Bug ID is not used for anything; ignore it.
}
else if (stage == kLineParserColon)
{
entry.test_name = tokens[i];
}
else
{
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
return false;
}
stage++;
break;
case kExpectationPass:
case kExpectationFail:
case kExpectationFlaky:
case kExpectationTimeout:
case kExpectationSkip:
// TEST_EXPECTATIONS
if (stage != kLineParserEqual && stage != kLineParserExpectations)
{
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
return false;
}
if ((kTokenData[token].flag & entry.test_expectation) != 0)
{
PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts],
line_number);
return false;
}
entry.test_expectation = (kTokenData[token].flag | entry.test_expectation);
if (stage == kLineParserEqual)
stage++;
break;
default:
DCHECK(false);
break;
} }
if (token == kConfigGPUDeviceID) { }
if (!UpdateTestConfig(&config, tokens[i], line_number)) if (stage == kLineParserBegin)
return false; {
} else { // The whole line is empty or all comments
if (!UpdateTestConfig(&config, token, line_number)) return true;
}
if (stage == kLineParserExpectations)
{
if (!config.IsValid())
{
PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number);
return false; return false;
} }
if (stage == kLineParserBugID) entries_.push_back(entry);
stage++; return true;
break; }
case kSeparatorColon: PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
// : return false;
if (stage != kLineParserConfigs) { }
PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
line_number); bool GPUTestExpectationsParser::UpdateTestConfig(GPUTestConfig *config,
return false; int32_t token,
} size_t line_number)
stage++; {
break; DCHECK(config);
case kSeparatorEqual: switch (token)
// = {
if (stage != kLineParserTestName) { case kConfigWinXP:
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], case kConfigWinVista:
line_number); case kConfigWin7:
return false; case kConfigWin8:
} case kConfigWin10:
stage++; case kConfigWin:
break; case kConfigMacLeopard:
case kTokenWord: case kConfigMacSnowLeopard:
// BUG_ID or TEST_NAME case kConfigMacLion:
if (stage == kLineParserBegin) { case kConfigMacMountainLion:
// Bug ID is not used for anything; ignore it. case kConfigMacMavericks:
} else if (stage == kLineParserColon) { case kConfigMacYosemite:
entry.test_name = tokens[i]; case kConfigMacElCapitan:
} else { case kConfigMacSierra:
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], case kConfigMacHighSierra:
line_number); case kConfigMacMojave:
return false; case kConfigMac:
} case kConfigLinux:
stage++; case kConfigChromeOS:
break; case kConfigAndroid:
case kExpectationPass: if ((config->os() & kTokenData[token].flag) != 0)
case kExpectationFail: {
case kExpectationFlaky: PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts], line_number);
case kExpectationTimeout: return false;
case kExpectationSkip: }
// TEST_EXPECTATIONS config->set_os(config->os() | kTokenData[token].flag);
if (stage != kLineParserEqual && stage != kLineParserExpectations) { break;
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], case kConfigNVidia:
line_number); case kConfigAMD:
return false; case kConfigIntel:
} case kConfigVMWare:
if ((kTokenData[token].flag & entry.test_expectation) != 0) { {
PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts], uint32_t gpu_vendor = static_cast<uint32_t>(kTokenData[token].flag);
line_number); for (size_t i = 0; i < config->gpu_vendor().size(); ++i)
return false; {
if (config->gpu_vendor()[i] == gpu_vendor)
{
PushErrorMessage(kErrorMessage[kErrorEntryWithGpuVendorConflicts], line_number);
return false;
}
}
config->AddGPUVendor(gpu_vendor);
} }
entry.test_expectation =
(kTokenData[token].flag | entry.test_expectation);
if (stage == kLineParserEqual)
stage++;
break;
default:
DCHECK(false);
break; break;
case kConfigRelease:
case kConfigDebug:
if ((config->build_type() & kTokenData[token].flag) != 0)
{
PushErrorMessage(kErrorMessage[kErrorEntryWithBuildTypeConflicts], line_number);
return false;
}
config->set_build_type(config->build_type() | kTokenData[token].flag);
break;
case kConfigD3D9:
case kConfigD3D11:
case kConfigGLDesktop:
case kConfigGLES:
case kConfigVulkan:
if ((config->api() & kTokenData[token].flag) != 0)
{
PushErrorMessage(kErrorMessage[kErrorEntryWithAPIConflicts], line_number);
return false;
}
config->set_api(config->api() | kTokenData[token].flag);
break;
default:
DCHECK(false);
break;
} }
}
if (stage == kLineParserBegin) {
// The whole line is empty or all comments
return true; return true;
} }
if (stage == kLineParserExpectations) {
if (!config.IsValid()) { bool GPUTestExpectationsParser::UpdateTestConfig(GPUTestConfig *config,
PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number); const std::string &gpu_device_id,
size_t line_number)
{
DCHECK(config);
uint32_t device_id = 0;
if (config->gpu_device_id() != 0 || !base::HexStringToUInt(gpu_device_id, &device_id) ||
device_id == 0)
{
PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts], line_number);
return false; return false;
} }
entries_.push_back(entry); config->set_gpu_device_id(device_id);
return true; return true;
}
PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
return false;
} }
bool GPUTestExpectationsParser::UpdateTestConfig(GPUTestConfig* config, bool GPUTestExpectationsParser::DetectConflictsBetweenEntries()
int32_t token, {
size_t line_number) { bool rt = false;
DCHECK(config); for (size_t i = 0; i < entries_.size(); ++i)
switch (token) { {
case kConfigWinXP: for (size_t j = i + 1; j < entries_.size(); ++j)
case kConfigWinVista: {
case kConfigWin7: if (entries_[i].test_name == entries_[j].test_name &&
case kConfigWin8: entries_[i].test_config.OverlapsWith(entries_[j].test_config))
case kConfigWin10: {
case kConfigWin: PushErrorMessage(kErrorMessage[kErrorEntriesOverlap], entries_[i].line_number,
case kConfigMacLeopard: entries_[j].line_number);
case kConfigMacSnowLeopard: rt = true;
case kConfigMacLion: }
case kConfigMacMountainLion:
case kConfigMacMavericks:
case kConfigMacYosemite:
case kConfigMacElCapitan:
case kConfigMacSierra:
case kConfigMacHighSierra:
case kConfigMacMojave:
case kConfigMac:
case kConfigLinux:
case kConfigChromeOS:
case kConfigAndroid:
if ((config->os() & kTokenData[token].flag) != 0) {
PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts],
line_number);
return false;
}
config->set_os(config->os() | kTokenData[token].flag);
break;
case kConfigNVidia:
case kConfigAMD:
case kConfigIntel:
case kConfigVMWare:
{
uint32_t gpu_vendor = static_cast<uint32_t>(kTokenData[token].flag);
for (size_t i = 0; i < config->gpu_vendor().size(); ++i) {
if (config->gpu_vendor()[i] == gpu_vendor) {
PushErrorMessage(
kErrorMessage[kErrorEntryWithGpuVendorConflicts],
line_number);
return false;
}
} }
config->AddGPUVendor(gpu_vendor);
}
break;
case kConfigRelease:
case kConfigDebug:
if ((config->build_type() & kTokenData[token].flag) != 0) {
PushErrorMessage(
kErrorMessage[kErrorEntryWithBuildTypeConflicts],
line_number);
return false;
}
config->set_build_type(
config->build_type() | kTokenData[token].flag);
break;
case kConfigD3D9:
case kConfigD3D11:
case kConfigGLDesktop:
case kConfigGLES:
case kConfigVulkan:
if ((config->api() & kTokenData[token].flag) != 0) {
PushErrorMessage(kErrorMessage[kErrorEntryWithAPIConflicts],
line_number);
return false;
}
config->set_api(config->api() | kTokenData[token].flag);
break;
default:
DCHECK(false);
break;
}
return true;
}
bool GPUTestExpectationsParser::UpdateTestConfig(
GPUTestConfig* config,
const std::string& gpu_device_id,
size_t line_number) {
DCHECK(config);
uint32_t device_id = 0;
if (config->gpu_device_id() != 0 ||
!base::HexStringToUInt(gpu_device_id, &device_id) ||
device_id == 0) {
PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts],
line_number);
return false;
}
config->set_gpu_device_id(device_id);
return true;
}
bool GPUTestExpectationsParser::DetectConflictsBetweenEntries() {
bool rt = false;
for (size_t i = 0; i < entries_.size(); ++i) {
for (size_t j = i + 1; j < entries_.size(); ++j) {
if (entries_[i].test_name == entries_[j].test_name &&
entries_[i].test_config.OverlapsWith(entries_[j].test_config)) {
PushErrorMessage(kErrorMessage[kErrorEntriesOverlap],
entries_[i].line_number,
entries_[j].line_number);
rt = true;
}
} }
} return rt;
return rt;
} }
void GPUTestExpectationsParser::PushErrorMessage( void GPUTestExpectationsParser::PushErrorMessage(const std::string &message, size_t line_number)
const std::string& message, size_t line_number) { {
error_messages_.push_back("Line " + ToString(line_number) + error_messages_.push_back("Line " + ToString(line_number) + " : " + message.c_str());
" : " + message.c_str());
} }
void GPUTestExpectationsParser::PushErrorMessage( void GPUTestExpectationsParser::PushErrorMessage(const std::string &message,
const std::string& message, size_t entry1_line_number,
size_t entry1_line_number, size_t entry2_line_number)
size_t entry2_line_number) { {
error_messages_.push_back("Line " + ToString(entry1_line_number) + error_messages_.push_back("Line " + ToString(entry1_line_number) + " and " +
" and " + ToString(entry2_line_number) + ToString(entry2_line_number) + " : " + message.c_str());
" : " + message.c_str());
} }
GPUTestExpectationsParser:: GPUTestExpectationEntry::GPUTestExpectationEntry() GPUTestExpectationsParser::GPUTestExpectationEntry::GPUTestExpectationEntry()
: test_expectation(0), : test_expectation(0), line_number(0)
line_number(0) { {}
}
} // namespace gpu } // namespace gpu
...@@ -11,80 +11,80 @@ ...@@ -11,80 +11,80 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "angle_config.h"
#include "gpu_test_config.h" #include "gpu_test_config.h"
namespace gpu { namespace gpu
{
class GPU_EXPORT GPUTestExpectationsParser {
public: class GPU_EXPORT GPUTestExpectationsParser
enum GPUTestExpectation { {
kGpuTestPass = 1 << 0, public:
kGpuTestFail = 1 << 1, enum GPUTestExpectation
kGpuTestFlaky = 1 << 2, {
kGpuTestTimeout = 1 << 3, kGpuTestPass = 1 << 0,
kGpuTestSkip = 1 << 4, kGpuTestFail = 1 << 1,
}; kGpuTestFlaky = 1 << 2,
kGpuTestTimeout = 1 << 3,
GPUTestExpectationsParser(); kGpuTestSkip = 1 << 4,
~GPUTestExpectationsParser(); };
// Parse the text expectations, and if no error is encountered, GPUTestExpectationsParser();
// save all the entries. Otherwise, generate error messages. ~GPUTestExpectationsParser();
// Return true if parsing succeeds.
bool LoadTestExpectations(const std::string& data); // Parse the text expectations, and if no error is encountered,
bool LoadTestExpectationsFromFile(const std::string& path); // save all the entries. Otherwise, generate error messages.
// Return true if parsing succeeds.
// Query error messages from the last LoadTestExpectations() call. bool LoadTestExpectations(const std::string &data);
const std::vector<std::string>& GetErrorMessages() const; bool LoadTestExpectationsFromFile(const std::string &path);
// Get the test expectation of a given test on a given bot. // Query error messages from the last LoadTestExpectations() call.
int32_t GetTestExpectation(const std::string& test_name, const std::vector<std::string> &GetErrorMessages() const;
const GPUTestBotConfig& bot_config) const;
// Get the test expectation of a given test on a given bot.
// Parse a list of config modifiers. If we have a valid entry with no int32_t GetTestExpectation(const std::string &test_name,
// conflicts, | config | stores it, and the function returns true. const GPUTestBotConfig &bot_config) const;
bool ParseConfig(const std::string& config_data, GPUTestConfig* config);
// Parse a list of config modifiers. If we have a valid entry with no
private: // conflicts, | config | stores it, and the function returns true.
struct GPUTestExpectationEntry { bool ParseConfig(const std::string &config_data, GPUTestConfig *config);
GPUTestExpectationEntry();
private:
std::string test_name; struct GPUTestExpectationEntry
GPUTestConfig test_config; {
int32_t test_expectation; GPUTestExpectationEntry();
size_t line_number;
}; std::string test_name;
GPUTestConfig test_config;
// Parse a line of text. If we have a valid entry, save it; otherwise, int32_t test_expectation;
// generate error messages. size_t line_number;
bool ParseLine(const std::string& line_data, size_t line_number); };
// Update OS/GPUVendor/BuildType modifiers. May generate an error message. // Parse a line of text. If we have a valid entry, save it; otherwise,
bool UpdateTestConfig(GPUTestConfig* config, // generate error messages.
int32_t token, bool ParseLine(const std::string &line_data, size_t line_number);
size_t line_number);
// Update OS/GPUVendor/BuildType modifiers. May generate an error message.
// Update GPUDeviceID modifier. May generate an error message. bool UpdateTestConfig(GPUTestConfig *config, int32_t token, size_t line_number);
bool UpdateTestConfig(GPUTestConfig* config,
const std::string & gpu_device_id, // Update GPUDeviceID modifier. May generate an error message.
size_t line_number); bool UpdateTestConfig(GPUTestConfig *config,
const std::string &gpu_device_id,
// Check if two entries' config overlap with each other. May generate an size_t line_number);
// error message.
bool DetectConflictsBetweenEntries(); // Check if two entries' config overlap with each other. May generate an
// error message.
// Save an error message, which can be queried later. bool DetectConflictsBetweenEntries();
void PushErrorMessage(const std::string& message, size_t line_number);
void PushErrorMessage(const std::string& message, // Save an error message, which can be queried later.
size_t entry1_line_number, void PushErrorMessage(const std::string &message, size_t line_number);
size_t entry2_line_number); void PushErrorMessage(const std::string &message,
size_t entry1_line_number,
std::vector<GPUTestExpectationEntry> entries_; size_t entry2_line_number);
std::vector<std::string> error_messages_;
std::vector<GPUTestExpectationEntry> entries_;
std::vector<std::string> error_messages_;
}; };
} // namespace gpu } // namespace gpu
#endif // ANGLE_GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_ #endif // ANGLE_GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANGLE_GPU_CONFIG_GPU_TEST_CONFIG_H_
#define ANGLE_GPU_CONFIG_GPU_TEST_CONFIG_H_
#include <stdint.h>
#include <string>
#include <vector>
#include "angle_config.h"
namespace gpu {
struct GPUInfo;
class GPU_EXPORT GPUTestConfig {
public:
enum OS {
kOsUnknown = 0,
kOsWinXP = 1 << 0,
kOsWinVista = 1 << 1,
kOsWin7 = 1 << 2,
kOsWin8 = 1 << 3,
kOsMacLeopard = 1 << 4,
kOsMacSnowLeopard = 1 << 5,
kOsMacLion = 1 << 6,
kOsMacMountainLion = 1 << 7,
kOsMacMavericks = 1 << 8,
kOsMacYosemite = 1 << 9,
kOsMacElCapitan = 1 << 10,
kOsMacSierra = 1 << 11,
kOsMacHighSierra = 1 << 12,
kOsMacMojave = 1 << 13,
kOsMac = kOsMacLeopard | kOsMacSnowLeopard | kOsMacLion |
kOsMacMountainLion | kOsMacMavericks | kOsMacYosemite |
kOsMacElCapitan | kOsMacSierra | kOsMacHighSierra | kOsMacMojave,
kOsLinux = 1 << 14,
kOsChromeOS = 1 << 15,
kOsAndroid = 1 << 16,
kOsWin10 = 1 << 17,
kOsWin = kOsWinXP | kOsWinVista | kOsWin7 | kOsWin8 | kOsWin10,
kOsFuchsia = 1 << 18,
};
enum BuildType {
kBuildTypeUnknown = 0,
kBuildTypeRelease = 1 << 0,
kBuildTypeDebug = 1 << 1,
};
enum API {
kAPIUnknown = 0,
kAPID3D9 = 1 << 0,
kAPID3D11 = 1 << 1,
kAPIGLDesktop = 1 << 2,
kAPIGLES = 1 << 3,
kAPIVulkan = 1 << 4,
};
GPUTestConfig();
GPUTestConfig(const GPUTestConfig& other);
virtual ~GPUTestConfig();
void set_os(int32_t os);
void set_gpu_device_id(uint32_t id);
void set_build_type(int32_t build_type);
void set_api(int32_t api);
virtual void AddGPUVendor(uint32_t gpu_vendor);
int32_t os() const { return os_; }
const std::vector<uint32_t>& gpu_vendor() const { return gpu_vendor_; }
uint32_t gpu_device_id() const { return gpu_device_id_; }
int32_t build_type() const { return build_type_; }
int32_t api() const { return api_; }
// Check if the config is valid. For example, if gpu_device_id_ is set, but
// gpu_vendor_ is unknown, then it's invalid.
virtual bool IsValid() const;
// Check if two configs overlap, i.e., if there exists a config that matches
// both configs.
bool OverlapsWith(const GPUTestConfig& config) const;
// Disable validation of GPU vendor and device ids.
void DisableGPUInfoValidation();
protected:
void ClearGPUVendor();
// Indicates that the OS has the notion of a numeric GPU vendor and device id
// and this data should be validated.
bool validate_gpu_info_;
private:
// operating system.
int32_t os_;
// GPU vendor.
std::vector<uint32_t> gpu_vendor_;
// GPU device id (unique to each vendor).
uint32_t gpu_device_id_;
// Release or Debug.
int32_t build_type_;
// Back-end rendering APIs.
int32_t api_;
};
class GPU_EXPORT GPUTestBotConfig : public GPUTestConfig {
public:
GPUTestBotConfig() = default;
~GPUTestBotConfig() override;
// This should only be called when no gpu_vendor is added.
void AddGPUVendor(uint32_t gpu_vendor) override;
// Return false if gpu_info does not have valid vendor_id and device_id.
bool SetGPUInfo(const GPUInfo& gpu_info);
// Check if the bot config is valid, i.e., if it is one valid test-bot
// environment. For example, if a field is unknown, or if OS is not one
// fully defined OS, then it's valid.
bool IsValid() const override;
// Check if a bot config matches a test config, i.e., the test config is a
// superset of the bot config.
bool Matches(const GPUTestConfig& config) const;
bool Matches(const std::string& config_data) const;
// Setup the config with the current gpu testing environment.
// If gpu_info is nullptr, collect GPUInfo first.
bool LoadCurrentConfig(const GPUInfo* gpu_info);
// Check if this bot's config matches |config_data| or any of the |configs|.
static bool CurrentConfigMatches(const std::string& config_data);
static bool CurrentConfigMatches(const std::vector<std::string>& configs);
// Check if the bot has blacklisted all GPU features.
static bool GpuBlacklistedOnBot();
};
} // namespace gpu
#endif // ANGLE_GPU_CONFIG_GPU_TEST_CONFIG_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment