diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp index 4e0d5762f0f38..b83276de7e7c5 100644 --- a/src/libANGLE/renderer/vulkan/RendererVk.cpp +++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp @@ -28,6 +28,14 @@ #include "libANGLE/renderer/vulkan/vk_format_utils.h" #include "platform/Platform.h" +// Consts +namespace +{ +const uint32_t kMockVendorID = 0xba5eba11; +const uint32_t kMockDeviceID = 0xf005ba11; +constexpr char kMockDeviceName[] = "Vulkan Mock Device"; +} // anonymous namespace + namespace rx { @@ -125,7 +133,7 @@ class ScopedVkLoaderEnvironment : angle::NonCopyable // Override environment variable to use the ANGLE layers. if (mEnableValidationLayers) { - if (!angle::PrependPathToEnvironmentVar(g_VkLoaderLayersPathEnv, ANGLE_VK_LAYERS_DIR)) + if (!angle::PrependPathToEnvironmentVar(g_VkLoaderLayersPathEnv, ANGLE_VK_DATA_DIR)) { ERR() << "Error setting environment for Vulkan layers init."; mEnableValidationLayers = false; @@ -251,11 +259,53 @@ RendererVk::~RendererVk() mPhysicalDevice = VK_NULL_HANDLE; } +void ChoosePhysicalDevice(const std::vector &physicalDevices, + bool preferMockICD, + VkPhysicalDevice *physicalDeviceOut, + VkPhysicalDeviceProperties *physicalDevicePropertiesOut) +{ + ASSERT(!physicalDevices.empty()); + if (preferMockICD) + { + for (const VkPhysicalDevice &physicalDevice : physicalDevices) + { + vkGetPhysicalDeviceProperties(physicalDevice, physicalDevicePropertiesOut); + if ((kMockVendorID == physicalDevicePropertiesOut->vendorID) && + (kMockDeviceID == physicalDevicePropertiesOut->deviceID) && + (strcmp(kMockDeviceName, physicalDevicePropertiesOut->deviceName) == 0)) + { + *physicalDeviceOut = physicalDevice; + return; + } + } + WARN() << "Vulkan Mock Driver was requested but Mock Device was not found. Using default " + "physicalDevice instead."; + } + + // Fall back to first device. + *physicalDeviceOut = physicalDevices[0]; + vkGetPhysicalDeviceProperties(*physicalDeviceOut, physicalDevicePropertiesOut); +} + vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *wsiName) { ScopedVkLoaderEnvironment scopedEnvironment(ShouldUseDebugLayers(attribs)); mEnableValidationLayers = scopedEnvironment.canEnableValidationLayers(); + bool enableNullDriver = false; +#if !defined(ANGLE_PLATFORM_ANDROID) + // Mock ICD does not currently run on Android + enableNullDriver = (attribs.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE) == + EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE); + if (enableNullDriver) + { + // Override environment variable to use built Mock ICD + // ANGLE_VK_ICD_JSON gets set to the built mock ICD in BUILD.gn + ANGLE_VK_CHECK(angle::SetEnvironmentVar(g_VkICDPathEnv, ANGLE_VK_ICD_JSON), + VK_ERROR_INITIALIZATION_FAILED); + } +#endif // !defined(ANGLE_PLATFORM_ANDROID) // Gather global layer properties. uint32_t instanceLayerCount = 0; ANGLE_VK_TRY(vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr)); @@ -348,10 +398,11 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w ANGLE_VK_CHECK(physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED); // TODO(jmadill): Handle multiple physical devices. For now, use the first device. - physicalDeviceCount = 1; - ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, &mPhysicalDevice)); - - vkGetPhysicalDeviceProperties(mPhysicalDevice, &mPhysicalDeviceProperties); + std::vector physicalDevices(physicalDeviceCount); + ANGLE_VK_TRY( + vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, physicalDevices.data())); + ChoosePhysicalDevice(physicalDevices, enableNullDriver, &mPhysicalDevice, + &mPhysicalDeviceProperties); // Ensure we can find a graphics queue family. uint32_t queueCount = 0; diff --git a/src/libANGLE/renderer/vulkan/vk_utils.cpp b/src/libANGLE/renderer/vulkan/vk_utils.cpp index 5fb76a45f2544..851b416c6791f 100644 --- a/src/libANGLE/renderer/vulkan/vk_utils.cpp +++ b/src/libANGLE/renderer/vulkan/vk_utils.cpp @@ -198,6 +198,7 @@ vk::Error AllocateBufferOrImageMemory(RendererVk *renderer, } // anonymous namespace const char *g_VkLoaderLayersPathEnv = "VK_LAYER_PATH"; +const char *g_VkICDPathEnv = "VK_ICD_FILENAMES"; const char *VulkanResultString(VkResult result) { diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h index a44cb2a1d9165..fe3afc74b2f14 100644 --- a/src/libANGLE/renderer/vulkan/vk_utils.h +++ b/src/libANGLE/renderer/vulkan/vk_utils.h @@ -74,6 +74,7 @@ bool GetAvailableValidationLayers(const std::vector &layerPro uint32_t *enabledLayerCount); extern const char *g_VkLoaderLayersPathEnv; +extern const char *g_VkICDPathEnv; enum class TextureDimension { diff --git a/src/tests/perf_tests/DrawCallPerf.cpp b/src/tests/perf_tests/DrawCallPerf.cpp index 2b7280b0ed74d..31db0cdeabcc1 100644 --- a/src/tests/perf_tests/DrawCallPerf.cpp +++ b/src/tests/perf_tests/DrawCallPerf.cpp @@ -190,7 +190,9 @@ ANGLE_INSTANTIATE_TEST(DrawCallPerfBenchmark, DrawArrays(DrawCallPerfOpenGLOrGLESParams(true, true), false), DrawArrays(DrawCallPerfOpenGLOrGLESParams(true, false), true), DrawArrays(DrawCallPerfValidationOnly(), false), - DrawArrays(DrawCallPerfVulkanParams(false), false), - DrawArrays(DrawCallPerfVulkanParams(false), true)); + DrawArrays(DrawCallPerfVulkanParams(true, false), true), + DrawArrays(DrawCallPerfVulkanParams(true, false), false), + DrawArrays(DrawCallPerfVulkanParams(false, false), false), + DrawArrays(DrawCallPerfVulkanParams(false, false), true)); } // namespace diff --git a/src/tests/perf_tests/DrawCallPerfParams.cpp b/src/tests/perf_tests/DrawCallPerfParams.cpp index f46aeb6188f6d..609a517f0496d 100644 --- a/src/tests/perf_tests/DrawCallPerfParams.cpp +++ b/src/tests/perf_tests/DrawCallPerfParams.cpp @@ -71,10 +71,10 @@ DrawCallPerfParams DrawCallPerfValidationOnly() return params; } -DrawCallPerfParams DrawCallPerfVulkanParams(bool renderToTexture) +DrawCallPerfParams DrawCallPerfVulkanParams(bool useNullDevice, bool renderToTexture) { DrawCallPerfParams params; - params.eglParameters = VULKAN(); + params.eglParameters = useNullDevice ? VULKAN_NULL() : VULKAN(); params.useFBO = renderToTexture; return params; } diff --git a/src/tests/perf_tests/DrawCallPerfParams.h b/src/tests/perf_tests/DrawCallPerfParams.h index a9c2da897e54b..d27ca92468d7a 100644 --- a/src/tests/perf_tests/DrawCallPerfParams.h +++ b/src/tests/perf_tests/DrawCallPerfParams.h @@ -38,6 +38,6 @@ DrawCallPerfParams DrawCallPerfD3D11Params(bool useNullDevice, bool renderToText DrawCallPerfParams DrawCallPerfD3D9Params(bool useNullDevice, bool renderToTexture); DrawCallPerfParams DrawCallPerfOpenGLOrGLESParams(bool useNullDevice, bool renderToTexture); DrawCallPerfParams DrawCallPerfValidationOnly(); -DrawCallPerfParams DrawCallPerfVulkanParams(bool renderToTexture); +DrawCallPerfParams DrawCallPerfVulkanParams(bool useNullDevice, bool renderToTexture); #endif // TESTS_PERF_TESTS_DRAW_CALL_PERF_PARAMS_H_ diff --git a/src/tests/test_utils/angle_test_configs.cpp b/src/tests/test_utils/angle_test_configs.cpp index 9aa6c72cc5a4a..e877752e1b2c5 100644 --- a/src/tests/test_utils/angle_test_configs.cpp +++ b/src/tests/test_utils/angle_test_configs.cpp @@ -398,6 +398,12 @@ EGLPlatformParameters VULKAN() return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE); } +EGLPlatformParameters VULKAN_NULL() +{ + return EGLPlatformParameters(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, EGL_DONT_CARE, EGL_DONT_CARE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE); +} + } // namespace egl_platform // ANGLE tests platforms @@ -671,9 +677,19 @@ PlatformParameters ES1_VULKAN() return PlatformParameters(1, 0, egl_platform::VULKAN()); } +PlatformParameters ES1_VULKAN_NULL() +{ + return PlatformParameters(1, 0, egl_platform::VULKAN_NULL()); +} + PlatformParameters ES2_VULKAN() { return PlatformParameters(2, 0, egl_platform::VULKAN()); } +PlatformParameters ES2_VULKAN_NULL() +{ + return PlatformParameters(2, 0, egl_platform::VULKAN_NULL()); +} + } // namespace angle diff --git a/src/tests/test_utils/angle_test_configs.h b/src/tests/test_utils/angle_test_configs.h index c1fda37dd7ac7..e1511966a59d8 100644 --- a/src/tests/test_utils/angle_test_configs.h +++ b/src/tests/test_utils/angle_test_configs.h @@ -99,6 +99,7 @@ EGLPlatformParameters OPENGLES_NULL(); EGLPlatformParameters OPENGL_OR_GLES(bool useNullDevice); EGLPlatformParameters VULKAN(); +EGLPlatformParameters VULKAN_NULL(); } // namespace egl_platform @@ -167,7 +168,9 @@ PlatformParameters ES3_NULL(); PlatformParameters ES31_NULL(); PlatformParameters ES1_VULKAN(); +PlatformParameters ES1_VULKAN_NULL(); PlatformParameters ES2_VULKAN(); +PlatformParameters ES2_VULKAN_NULL(); } // namespace angle diff --git a/third_party/vulkan-validation-layers/BUILD.gn b/third_party/vulkan-validation-layers/BUILD.gn index d84a266b63e3f..5a52d6e85d0c4 100644 --- a/third_party/vulkan-validation-layers/BUILD.gn +++ b/third_party/vulkan-validation-layers/BUILD.gn @@ -259,7 +259,8 @@ config("vulkan_loader_config") { "src/loader", ] defines = [ - "ANGLE_VK_LAYERS_DIR=\"$data_dir\"", + "ANGLE_VK_DATA_DIR=\"$data_dir\"", + "ANGLE_VK_ICD_JSON=\"$data_dir/VkICD_mock_icd.json\"", "API_NAME=\"Vulkan\"", ] @@ -524,12 +525,12 @@ if (!is_android) { # The layer JSON files are part of the necessary data deps. outputs = [ - "$root_out_dir/$data_dir/icd/VkICD_mock_icd.json", + "$root_out_dir/$data_dir/VkICD_mock_icd.json", ] data = [ - "$root_out_dir/$data_dir/icd/VkICD_mock_icd.json", + "$root_out_dir/$data_dir/VkICD_mock_icd.json", ] - args += [ rebase_path("$root_out_dir/$data_dir/icd", root_build_dir) ] + args += [ rebase_path("$root_out_dir/$data_dir", root_build_dir) ] } }