1 // Copyright 2021 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "common/GPUInfo.h" 16 #include "common/Platform.h" 17 #include "common/SystemUtils.h" 18 #include "dawn/webgpu_cpp.h" 19 #include "dawn_native/DawnNative.h" 20 21 #if defined(DAWN_ENABLE_BACKEND_VULKAN) 22 # include "dawn_native/VulkanBackend.h" 23 #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) 24 25 #if defined(DAWN_ENABLE_BACKEND_D3D12) 26 # include "dawn_native/D3D12Backend.h" 27 #endif // defined(DAWN_ENABLE_BACKEND_D3D12) 28 29 #if defined(DAWN_ENABLE_BACKEND_METAL) 30 # include "dawn_native/MetalBackend.h" 31 #endif // defined(DAWN_ENABLE_BACKEND_METAL) 32 33 #if defined(DAWN_ENABLE_BACKEND_METAL) 34 # include "dawn_native/MetalBackend.h" 35 #endif // defined(DAWN_ENABLE_BACKEND_METAL) 36 37 #if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) || defined(DAWN_ENABLE_BACKEND_OPENGLES) 38 # include "GLFW/glfw3.h" 39 # include "dawn_native/OpenGLBackend.h" 40 #endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) || defined(DAWN_ENABLE_BACKEND_OPENGLES) 41 42 #include <gtest/gtest.h> 43 44 namespace { 45 46 class AdapterDiscoveryTests : public ::testing::Test {}; 47 48 #if defined(DAWN_ENABLE_BACKEND_VULKAN) 49 // Test only discovering the SwiftShader adapter TEST(AdapterDiscoveryTests, OnlySwiftShader)50 TEST(AdapterDiscoveryTests, OnlySwiftShader) { 51 dawn_native::Instance instance; 52 53 dawn_native::vulkan::AdapterDiscoveryOptions options; 54 options.forceSwiftShader = true; 55 instance.DiscoverAdapters(&options); 56 57 const auto& adapters = instance.GetAdapters(); 58 EXPECT_LE(adapters.size(), 1u); // 0 or 1 SwiftShader adapters. 59 for (const auto& adapter : adapters) { 60 wgpu::AdapterProperties properties; 61 adapter.GetProperties(&properties); 62 63 EXPECT_EQ(properties.backendType, wgpu::BackendType::Vulkan); 64 EXPECT_EQ(properties.adapterType, wgpu::AdapterType::CPU); 65 EXPECT_TRUE(gpu_info::IsSwiftshader(properties.vendorID, properties.deviceID)); 66 } 67 } 68 69 // Test discovering only Vulkan adapters TEST(AdapterDiscoveryTests, OnlyVulkan)70 TEST(AdapterDiscoveryTests, OnlyVulkan) { 71 dawn_native::Instance instance; 72 73 dawn_native::vulkan::AdapterDiscoveryOptions options; 74 instance.DiscoverAdapters(&options); 75 76 const auto& adapters = instance.GetAdapters(); 77 for (const auto& adapter : adapters) { 78 wgpu::AdapterProperties properties; 79 adapter.GetProperties(&properties); 80 81 EXPECT_EQ(properties.backendType, wgpu::BackendType::Vulkan); 82 } 83 } 84 #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) 85 86 #if defined(DAWN_ENABLE_BACKEND_D3D12) 87 // Test discovering only D3D12 adapters TEST(AdapterDiscoveryTests, OnlyD3D12)88 TEST(AdapterDiscoveryTests, OnlyD3D12) { 89 dawn_native::Instance instance; 90 91 dawn_native::d3d12::AdapterDiscoveryOptions options; 92 instance.DiscoverAdapters(&options); 93 94 const auto& adapters = instance.GetAdapters(); 95 for (const auto& adapter : adapters) { 96 wgpu::AdapterProperties properties; 97 adapter.GetProperties(&properties); 98 99 EXPECT_EQ(properties.backendType, wgpu::BackendType::D3D12); 100 } 101 } 102 103 // Test discovering a D3D12 adapter from a prexisting DXGI adapter TEST(AdapterDiscoveryTests, MatchingDXGIAdapter)104 TEST(AdapterDiscoveryTests, MatchingDXGIAdapter) { 105 using Microsoft::WRL::ComPtr; 106 107 ComPtr<IDXGIFactory4> dxgiFactory; 108 HRESULT hr = ::CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgiFactory)); 109 ASSERT_EQ(hr, S_OK); 110 111 for (uint32_t adapterIndex = 0;; ++adapterIndex) { 112 ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr; 113 if (dxgiFactory->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) { 114 break; // No more adapters to enumerate. 115 } 116 117 dawn_native::Instance instance; 118 119 dawn_native::d3d12::AdapterDiscoveryOptions options; 120 options.dxgiAdapter = std::move(dxgiAdapter); 121 instance.DiscoverAdapters(&options); 122 123 const auto& adapters = instance.GetAdapters(); 124 for (const auto& adapter : adapters) { 125 wgpu::AdapterProperties properties; 126 adapter.GetProperties(&properties); 127 128 EXPECT_EQ(properties.backendType, wgpu::BackendType::D3D12); 129 } 130 } 131 } 132 #endif // defined(DAWN_ENABLE_BACKEND_D3D12) 133 134 #if defined(DAWN_ENABLE_BACKEND_METAL) 135 // Test discovering only Metal adapters TEST(AdapterDiscoveryTests, OnlyMetal)136 TEST(AdapterDiscoveryTests, OnlyMetal) { 137 dawn_native::Instance instance; 138 139 dawn_native::metal::AdapterDiscoveryOptions options; 140 instance.DiscoverAdapters(&options); 141 142 const auto& adapters = instance.GetAdapters(); 143 for (const auto& adapter : adapters) { 144 wgpu::AdapterProperties properties; 145 adapter.GetProperties(&properties); 146 147 EXPECT_EQ(properties.backendType, wgpu::BackendType::Metal); 148 } 149 } 150 #endif // defined(DAWN_ENABLE_BACKEND_METAL) 151 152 #if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) 153 // Test discovering only desktop OpenGL adapters TEST(AdapterDiscoveryTests, OnlyDesktopGL)154 TEST(AdapterDiscoveryTests, OnlyDesktopGL) { 155 if (!glfwInit()) { 156 GTEST_SKIP() << "glfwInit() failed"; 157 } 158 glfwDefaultWindowHints(); 159 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 160 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); 161 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); 162 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 163 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); 164 165 GLFWwindow* window = 166 glfwCreateWindow(400, 400, "Dawn OpenGL test window", nullptr, nullptr); 167 glfwMakeContextCurrent(window); 168 169 dawn_native::Instance instance; 170 171 dawn_native::opengl::AdapterDiscoveryOptions options; 172 options.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress); 173 instance.DiscoverAdapters(&options); 174 glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); 175 176 const auto& adapters = instance.GetAdapters(); 177 for (const auto& adapter : adapters) { 178 wgpu::AdapterProperties properties; 179 adapter.GetProperties(&properties); 180 181 EXPECT_EQ(properties.backendType, wgpu::BackendType::OpenGL); 182 } 183 184 glfwDestroyWindow(window); 185 } 186 #endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) 187 188 #if defined(DAWN_ENABLE_BACKEND_OPENGLES) 189 // Test discovering only OpenGLES adapters TEST(AdapterDiscoveryTests, OnlyOpenGLES)190 TEST(AdapterDiscoveryTests, OnlyOpenGLES) { 191 ScopedEnvironmentVar angleDefaultPlatform; 192 if (GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM").first.empty()) { 193 angleDefaultPlatform.Set("ANGLE_DEFAULT_PLATFORM", "swiftshader"); 194 } 195 196 if (!glfwInit()) { 197 GTEST_SKIP() << "glfwInit() failed"; 198 } 199 glfwDefaultWindowHints(); 200 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 201 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); 202 glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); 203 glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); 204 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); 205 206 GLFWwindow* window = 207 glfwCreateWindow(400, 400, "Dawn OpenGLES test window", nullptr, nullptr); 208 glfwMakeContextCurrent(window); 209 210 dawn_native::Instance instance; 211 212 dawn_native::opengl::AdapterDiscoveryOptionsES options; 213 options.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress); 214 instance.DiscoverAdapters(&options); 215 glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); 216 217 const auto& adapters = instance.GetAdapters(); 218 for (const auto& adapter : adapters) { 219 wgpu::AdapterProperties properties; 220 adapter.GetProperties(&properties); 221 222 EXPECT_EQ(properties.backendType, wgpu::BackendType::OpenGLES); 223 } 224 225 glfwDestroyWindow(window); 226 } 227 #endif // defined(DAWN_ENABLE_BACKEND_OPENGLES) 228 229 #if defined(DAWN_ENABLE_BACKEND_METAL) && defined(DAWN_ENABLE_BACKEND_VULKAN) 230 // Test discovering the Metal backend, then the Vulkan backend 231 // does not duplicate adapters. TEST(AdapterDiscoveryTests, OneBackendThenTheOther)232 TEST(AdapterDiscoveryTests, OneBackendThenTheOther) { 233 dawn_native::Instance instance; 234 uint32_t metalAdapterCount = 0; 235 { 236 dawn_native::metal::AdapterDiscoveryOptions options; 237 instance.DiscoverAdapters(&options); 238 239 const auto& adapters = instance.GetAdapters(); 240 metalAdapterCount = adapters.size(); 241 for (const auto& adapter : adapters) { 242 wgpu::AdapterProperties properties; 243 adapter.GetProperties(&properties); 244 245 ASSERT_EQ(properties.backendType, wgpu::BackendType::Metal); 246 } 247 } 248 { 249 dawn_native::vulkan::AdapterDiscoveryOptions options; 250 instance.DiscoverAdapters(&options); 251 252 uint32_t metalAdapterCount2 = 0; 253 const auto& adapters = instance.GetAdapters(); 254 for (const auto& adapter : adapters) { 255 wgpu::AdapterProperties properties; 256 adapter.GetProperties(&properties); 257 258 EXPECT_TRUE(properties.backendType == wgpu::BackendType::Metal || 259 properties.backendType == wgpu::BackendType::Vulkan); 260 if (properties.backendType == wgpu::BackendType::Metal) { 261 metalAdapterCount2++; 262 } 263 } 264 EXPECT_EQ(metalAdapterCount, metalAdapterCount2); 265 } 266 } 267 #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) && defined(DAWN_ENABLE_BACKEND_METAL) 268 269 } // anonymous namespace 270