Add live_verification tests for runnign with real drivers
authorCharles Giessen <charles@lunarg.com>
Tue, 15 Feb 2022 20:56:21 +0000 (13:56 -0700)
committerCharles Giessen <charles@lunarg.com>
Tue, 15 Feb 2022 20:56:21 +0000 (13:56 -0700)
Some things need to be verified against real drivers. The supporting code in test_util and
test_environment make it easy to write application code which works against real drivers and
layers. This allows quickly verifying loader behavior out in the wild.

tests/CMakeLists.txt
tests/framework/test_environment.cpp
tests/framework/test_environment.h
tests/live_verification/CMakeLists.txt [new file with mode: 0644]
tests/live_verification/dynamic_rendering_get_proc_addr.cpp [new file with mode: 0644]

index 403951e..e64b7d1 100644 (file)
@@ -1,6 +1,6 @@
 # ~~~
-# Copyright (c) 2014-2018 Valve Corporation
-# Copyright (c) 2014-2018 LunarG, Inc.
+# Copyright (c) 2014-2022 Valve Corporation
+# Copyright (c) 2014-2022 LunarG, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -58,3 +58,6 @@ endif()
 
 # must happen after the dll's get copied over
 gtest_discover_tests(test_regression)
+
+# executables that are meant for testing against real drivers rather than the mocks
+add_subdirectory(live_verification)
\ No newline at end of file
index 48ea276..5365599 100644 (file)
@@ -65,6 +65,16 @@ std::vector<VkPhysicalDevice> InstWrapper::GetPhysDevs(uint32_t phys_dev_count,
     return physical_devices;
 }
 
+std::vector<VkPhysicalDevice> InstWrapper::GetPhysDevs(VkResult result_to_check) {
+    uint32_t physical_count = 0;
+    VkResult res = functions->vkEnumeratePhysicalDevices(inst, &physical_count, nullptr);
+    std::vector<VkPhysicalDevice> physical_devices;
+    physical_devices.resize(physical_count);
+    res = functions->vkEnumeratePhysicalDevices(inst, &physical_count, physical_devices.data());
+    EXPECT_EQ(result_to_check, res);
+    return physical_devices;
+}
+
 VkPhysicalDevice InstWrapper::GetPhysDev(VkResult result_to_check) {
     uint32_t physical_count = 1;
     VkPhysicalDevice physical_device = VK_NULL_HANDLE;
@@ -73,6 +83,18 @@ VkPhysicalDevice InstWrapper::GetPhysDev(VkResult result_to_check) {
     return physical_device;
 }
 
+std::vector<VkExtensionProperties> EnumerateDeviceExtensions(InstWrapper const& inst, VkPhysicalDevice physical_device) {
+    uint32_t ext_count = 1;
+    VkResult res = inst.functions->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &ext_count, nullptr);
+    EXPECT_EQ(VK_SUCCESS, res);
+    std::vector<VkExtensionProperties> extensions;
+    extensions.resize(ext_count);
+    res = inst.functions->vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &ext_count, nullptr);
+    EXPECT_EQ(VK_SUCCESS, res);
+    extensions.resize(ext_count);
+    return extensions;
+}
+
 DeviceWrapper::DeviceWrapper(InstWrapper& inst_wrapper, VkAllocationCallbacks* callbacks) noexcept
     : functions(inst_wrapper.functions), callbacks(callbacks){};
 DeviceWrapper::DeviceWrapper(VulkanFunctions& functions, VkDevice device, VkAllocationCallbacks* callbacks) noexcept
index 5e70b53..8f6d594 100644 (file)
@@ -137,7 +137,9 @@ struct InstWrapper {
     VulkanFunctions* operator->() { return functions; }
 
     // Enumerate physical devices using googletest to assert if it succeeded
-    std::vector<VkPhysicalDevice> GetPhysDevs(uint32_t phys_dev_count, VkResult result_to_check = VK_SUCCESS);
+    std::vector<VkPhysicalDevice> GetPhysDevs(VkResult result_to_check = VK_SUCCESS);  // query all physical devices
+    std::vector<VkPhysicalDevice> GetPhysDevs(uint32_t phys_dev_count,
+                                              VkResult result_to_check = VK_SUCCESS);  // query only phys_dev_count devices
     // Enumerate a single physical device using googletest to assert if it succeeded
     VkPhysicalDevice GetPhysDev(VkResult result_to_check = VK_SUCCESS);
 
@@ -147,6 +149,8 @@ struct InstWrapper {
     InstanceCreateInfo create_info{};
 };
 
+std::vector<VkExtensionProperties> EnumerateDeviceExtensions(InstWrapper const& inst, VkPhysicalDevice physical_device);
+
 struct DeviceWrapper {
     DeviceWrapper(InstWrapper& inst_wrapper, VkAllocationCallbacks* callbacks = nullptr) noexcept;
     DeviceWrapper(VulkanFunctions& functions, VkDevice device, VkAllocationCallbacks* callbacks = nullptr) noexcept;
diff --git a/tests/live_verification/CMakeLists.txt b/tests/live_verification/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d58f748
--- /dev/null
@@ -0,0 +1,19 @@
+# ~~~
+# Copyright (c) 2022 Valve Corporation
+# Copyright (c) 2022 LunarG, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ~~~
+
+add_executable(dynamic_rendering_get_proc_addr dynamic_rendering_get_proc_addr.cpp)
+target_link_libraries(dynamic_rendering_get_proc_addr testing_dependencies)
\ No newline at end of file
diff --git a/tests/live_verification/dynamic_rendering_get_proc_addr.cpp b/tests/live_verification/dynamic_rendering_get_proc_addr.cpp
new file mode 100644 (file)
index 0000000..301f63d
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2022 The Khronos Group Inc.
+ * Copyright (c) 2022 Valve Corporation
+ * Copyright (c) 2022 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ *
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ * Author: Charles Giessen <charles@lunarg.com>
+ */
+
+#include "test_environment.h"
+
+/*
+ * Tests to see if drivers return vkCmdBeginRenderingKHR as an unknown device or physical device extension
+ * If it is returned as a physical device extension, this test should crash. Otherwise it should work just fine.
+ */
+
+int main() {
+    VulkanFunctions vk_funcs{};
+
+    InstWrapper inst(vk_funcs);
+    inst.CheckCreate();
+    auto phys_devs = inst.GetPhysDevs();
+
+    for (const auto& phys_dev : phys_devs) {
+        auto extensions = EnumerateDeviceExtensions(inst, phys_dev);
+        bool has_dynamic_rendering = false;
+        for (const auto& ext : extensions) {
+            if (string_eq("VK_KHR_dynamic_rendering", ext.extensionName)) {
+                has_dynamic_rendering = true;
+                break;
+            }
+        }
+        if (has_dynamic_rendering) {
+            DeviceWrapper dev(inst);
+            dev.create_info.add_extension("VK_KHR_dynamic_rendering");
+            dev.CheckCreate(phys_dev);
+
+            DeviceFunctions funcs{vk_funcs, dev};
+            VkCommandPool command_pool;
+            VkCommandPoolCreateInfo pool_create_info{};
+            pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+            funcs.vkCreateCommandPool(dev, &pool_create_info, nullptr, &command_pool);
+            VkCommandBuffer command_buffer;
+            VkCommandBufferAllocateInfo alloc_info{};
+            alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+            alloc_info.commandBufferCount = 1;
+            alloc_info.commandPool = command_pool;
+            funcs.vkAllocateCommandBuffers(dev, &alloc_info, &command_buffer);
+            PFN_vkBeginCommandBuffer vkBeginCommandBuffer =
+                reinterpret_cast<PFN_vkBeginCommandBuffer>(vk_funcs.vkGetInstanceProcAddr(inst, "vkBeginCommandBuffer"));
+            VkCommandBufferBeginInfo begin_info{};
+            begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+            VkResult res = vkBeginCommandBuffer(command_buffer, &begin_info);
+            assert(res == VK_SUCCESS);
+
+            // call the dynamic rendering function
+            PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR =
+                reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(vk_funcs.vkGetDeviceProcAddr(dev.dev, "vkCmdBeginRenderingKHR"));
+            VkRenderingInfoKHR rendering_info{};
+            rendering_info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR;
+            vkCmdBeginRenderingKHR(command_buffer, &rendering_info);
+        }
+    }
+}
\ No newline at end of file