From 251fe8046f9780cd5838564fa8a8aaa365704ea6 Mon Sep 17 00:00:00 2001 From: Jeremy Hayes Date: Mon, 15 Aug 2016 10:37:24 -0600 Subject: [PATCH] tests: add implicit layer tests Change-Id: I84e70b2eaafc59fa8d2c3642c87f3b908532445a --- tests/CMakeLists.txt | 1 + tests/layers/CMakeLists.txt | 8 ++ tests/layers/linux/VkLayer_test.json | 17 ++++ tests/layers/test.cpp | 140 +++++++++++++++++++++++++++++++++ tests/layers/windows/VkLayer_test.json | 17 ++++ tests/loader_validation_tests.cpp | 70 +++++++++++++++++ tests/run_extra_loader_tests.sh | 106 +++++++++++++++++++++++++ 7 files changed, 359 insertions(+) create mode 100644 tests/layers/linux/VkLayer_test.json create mode 100644 tests/layers/test.cpp create mode 100644 tests/layers/windows/VkLayer_test.json create mode 100755 tests/run_extra_loader_tests.sh diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c74c2de..7b9de1d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,6 +53,7 @@ if (NOT WIN32) COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/run_all_tests.sh COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/run_wrap_objects_tests.sh COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/run_loader_tests.sh + COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/run_extra_loader_tests.sh COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/vkvalidatelayerdoc.sh VERBATIM ) diff --git a/tests/layers/CMakeLists.txt b/tests/layers/CMakeLists.txt index 87d7793..3622f6a 100644 --- a/tests/layers/CMakeLists.txt +++ b/tests/layers/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required (VERSION 2.8.11) set(LAYER_JSON_FILES VkLayer_wrap_objects + VkLayer_test ) set(VK_LAYER_RPATH /usr/lib/x86_64-linux-gnu/vulkan/layer:/usr/lib/i386-linux-gnu/vulkan/layer) @@ -83,4 +84,11 @@ set (WRAP_SRCS ) add_vk_layer(wrap_objects ${WRAP_SRCS}) +set (TEST_SRCS + test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../layers/vk_layer_table.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../layers/vk_layer_extension_utils.cpp + ) +add_vk_layer(test ${TEST_SRCS}) + diff --git a/tests/layers/linux/VkLayer_test.json b/tests/layers/linux/VkLayer_test.json new file mode 100644 index 0000000..957d9a2 --- /dev/null +++ b/tests/layers/linux/VkLayer_test.json @@ -0,0 +1,17 @@ +{ + "file_format_version" : "1.0.0", + "layer" : { + "name": "VK_LAYER_LUNARG_test", + "type": "GLOBAL", + "library_path": "./libVkLayer_test.so", + "api_version": "1.0.11", + "implementation_version": "1", + "description": "LunarG Test Layer", + "enable_environment": { + "ENABLE_LAYER_TEST_1": "enable" + }, + "disable_environment": { + "DISABLE_LAYER_TEST_1": "" + } + } +} diff --git a/tests/layers/test.cpp b/tests/layers/test.cpp new file mode 100644 index 0000000..11f79cb --- /dev/null +++ b/tests/layers/test.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015-2016 Valve Corporation + * Copyright (c) 2015-2016 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. + * + * Author: Jeremy Hayes + */ + +#include +#include +#include + +#include "vk_dispatch_table_helper.h" +#include "vk_layer_data.h" +#include "vk_layer_extension_utils.h" + +namespace test +{ + +struct layer_data { + VkInstance instance; + VkLayerInstanceDispatchTable *instance_dispatch_table; + + layer_data() : instance(VK_NULL_HANDLE), instance_dispatch_table(nullptr) {}; +}; + +static std::unordered_map layer_data_map; + +VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance) +{ + VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); + assert(chain_info != nullptr); + + assert(chain_info->u.pLayerInfo != nullptr); + PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; + assert(fpGetInstanceProcAddr != nullptr); + + PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance"); + if (fpCreateInstance == nullptr) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; + VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); + if (result != VK_SUCCESS) + { + return result; + } + + layer_data *instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map); + instance_data->instance = *pInstance; + instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable; + layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr); + + // Marker for testing. + std::cout << "VK_LAYER_LUNARG_test: CreateInstance" << '\n'; + + return result; +} + +VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) +{ + dispatch_key key = get_dispatch_key(instance); + layer_data *instance_data = get_my_data_ptr(key, layer_data_map); + instance_data->instance_dispatch_table->DestroyInstance(instance, pAllocator); + + delete instance_data->instance_dispatch_table; + layer_data_map.erase(key); + + // Marker for testing. + std::cout << "VK_LAYER_LUNARG_test: DestroyInstance" << '\n'; +} + +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) +{ + // Return the functions that are intercepted by this layer. + static const struct + { + const char *name; + PFN_vkVoidFunction proc; + } core_instance_commands[] = + { + { "vkGetInstanceProcAddr", reinterpret_cast(GetInstanceProcAddr) }, + { "vkCreateInstance", reinterpret_cast(CreateInstance) }, + { "vkDestroyInstance", reinterpret_cast(DestroyInstance) } + }; + + for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) + { + if (!strcmp(core_instance_commands[i].name, funcName)) + { + return core_instance_commands[i].proc; + } + } + + // Only call down the chain for Vulkan commands that this layer does not intercept. + layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); + VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table; + if (pTable->GetInstanceProcAddr == nullptr) + { + return nullptr; + } + + return pTable->GetInstanceProcAddr(instance, funcName); +} + +} + +VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName) +{ + return test::GetInstanceProcAddr(instance, funcName); +} + +VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) +{ + return nullptr; +} + +VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) +{ + return VK_ERROR_LAYER_NOT_PRESENT; +} + +VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) +{ + return VK_ERROR_LAYER_NOT_PRESENT; +} diff --git a/tests/layers/windows/VkLayer_test.json b/tests/layers/windows/VkLayer_test.json new file mode 100644 index 0000000..a0da833 --- /dev/null +++ b/tests/layers/windows/VkLayer_test.json @@ -0,0 +1,17 @@ +{ + "file_format_version" : "1.0.0", + "layer" : { + "name": "VK_LAYER_LUNARG_test", + "type": "GLOBAL", + "library_path": ".\\libVkLayer_test.dll", + "api_version": "1.0.11", + "implementation_version": "1", + "description": "LunarG Test Layer", + "enable_environment": { + "ENABLE_LAYER_TEST_1": "enable" + }, + "disable_environment": { + "DISABLE_LAYER_TEST_1": "" + } + } +} diff --git a/tests/loader_validation_tests.cpp b/tests/loader_validation_tests.cpp index a6431ff..dbfdb09 100644 --- a/tests/loader_validation_tests.cpp +++ b/tests/loader_validation_tests.cpp @@ -317,6 +317,7 @@ std::vector CommandLine::arguments; struct EnumerateInstanceLayerProperties : public CommandLine {}; struct EnumerateInstanceExtensionProperties : public CommandLine {}; +struct ImplicitLayer : public CommandLine {}; // Test groups: // LX = lunar exchange @@ -579,6 +580,65 @@ TEST(EnumerateDeviceLayerProperties, PropertyCountLessThanAvailable) vkDestroyInstance(instance, nullptr); } +TEST(EnumerateDeviceLayerProperties, CreateInstanceWithoutLayers) +{ + VkInstance instance = VK_NULL_HANDLE; + VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); + ASSERT_EQ(result, VK_SUCCESS); + + uint32_t physicalCount = 0; + result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); + ASSERT_EQ(result, VK_SUCCESS); + ASSERT_GT(physicalCount, 0u); + + std::unique_ptr physical(new VkPhysicalDevice[physicalCount]); + result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); + ASSERT_EQ(result, VK_SUCCESS); + ASSERT_GT(physicalCount, 0u); + + for(uint32_t p = 0; p < physicalCount; ++p) + { + uint32_t count = 0u; + result = vkEnumerateDeviceLayerProperties(physical[p], &count, nullptr); + ASSERT_EQ(result, VK_SUCCESS); + ASSERT_EQ(count, 0u); + } + + vkDestroyInstance(instance, nullptr); +} + +TEST(EnumerateDeviceLayerProperties, CreateInstanceWithLayer) +{ + char const*const names[] = {"VK_LAYER_LUNARG_core_validation"}; // Temporary required due to MSVC bug. + auto const info = VK::InstanceCreateInfo(). + enabledLayerCount(1). + ppEnabledLayerNames(names); + + VkInstance instance = VK_NULL_HANDLE; + VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); + ASSERT_EQ(result, VK_SUCCESS); + + uint32_t physicalCount = 0; + result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); + ASSERT_EQ(result, VK_SUCCESS); + ASSERT_GT(physicalCount, 0u); + + std::unique_ptr physical(new VkPhysicalDevice[physicalCount]); + result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); + ASSERT_EQ(result, VK_SUCCESS); + ASSERT_GT(physicalCount, 0u); + + for(uint32_t p = 0; p < physicalCount; ++p) + { + uint32_t count = 0u; + result = vkEnumerateDeviceLayerProperties(physical[p], &count, nullptr); + ASSERT_EQ(result, VK_SUCCESS); + ASSERT_EQ(count, 1u); + } + + vkDestroyInstance(instance, nullptr); +} + TEST_F(EnumerateInstanceLayerProperties, Count) { uint32_t count = 0u; @@ -813,6 +873,16 @@ TEST(EnumerateDeviceExtensionProperties, DeviceExtensionEnumerated) vkDestroyInstance(instance, nullptr); } +TEST_F(ImplicitLayer, Present) +{ + auto const info = VK::InstanceCreateInfo(); + VkInstance instance = VK_NULL_HANDLE; + VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); + ASSERT_EQ(result, VK_SUCCESS); + + vkDestroyInstance(instance, nullptr); +} + TEST(WrapObjects, Insert) { VkInstance instance = VK_NULL_HANDLE; diff --git a/tests/run_extra_loader_tests.sh b/tests/run_extra_loader_tests.sh new file mode 100755 index 0000000..c29e573 --- /dev/null +++ b/tests/run_extra_loader_tests.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +pushd $(dirname "$0") > /dev/null + +RunImplicitLayerTest() +{ + # Check for local implicit directory. + : "${HOME:?}" + local implicitDirectory="$HOME/.local/share/vulkan/implicit_layer.d" + if [ ! -d "$implicitDirectory" ] + then + mkdir -p "$implicitDirectory" + fi + + # Check for the shared object. + local sharedObject="libVkLayer_test.so" + local layerDirectory="./layers" + if [ ! -f "$layerDirectory/$sharedObject" ] + then + echo "The file, $layerDirectory/$sharedObject, can not be found." >&2 + return 1 + fi + + # Check for the json which does not include the optional enable environment variable. + local json="VkLayer_test.json" + if [ ! -f "$layerDirectory/$json" ] + then + echo "The file, $layerDirectory/$json, can not be found." >&2 + return 1 + fi + + # Copy the test layer into the implicit directory. + if ! cp "$layerDirectory/$sharedObject" "$implicitDirectory/" || ! cp "$layerDirectory/$json" "$implicitDirectory/" + then + echo "unable to install test layer" >&2 + return 1 + fi + + # Test without setting enable environment variable. The loader should not load the layer. + output=$(GTEST_FILTER=ImplicitLayer.Present \ + ./vk_loader_validation_tests 2>&1) + if echo "$output" | grep -q "VK_LAYER_LUNARG_test: CreateInstance" + then + echo "test layer detected but enable environment variable was not set" >&2 + return 1 + fi + + # Test enable environment variable with good value. The loader should load the layer. + output=$(ENABLE_LAYER_TEST_1=enable \ + GTEST_FILTER=ImplicitLayer.Present \ + ./vk_loader_validation_tests 2>&1) + if ! echo "$output" | grep -q "VK_LAYER_LUNARG_test: CreateInstance" + then + echo "test layer not detected" >&2 + return 1 + fi + + # Test enable environment variable with bad value. The loader should not load the layer. + output=$(ENABLE_LAYER_TEST_1=wrong \ + GTEST_FILTER=ImplicitLayer.Present \ + ./vk_loader_validation_tests 2>&1) + if echo "$output" | grep -q "VK_LAYER_LUNARG_test: CreateInstance" + then + echo "test layer detected but enable environment variable was set to wrong value" >&2 + return 1 + fi + + # Test disable environment variable. The loader should not load the layer. + output=$(DISABLE_LAYER_TEST_1=value \ + GTEST_FILTER=ImplicitLayer.Present \ + ./vk_loader_validation_tests 2>&1) + if echo "$output" | grep -q "VK_LAYER_LUNARG_test: CreateInstance" + then + echo "test layer detected but disable environment variable was set" >&2 + return 1 + fi + + # Remove the enable environment variable. + if ! sed -i '/enable_environment\|ENABLE_LAYER_TEST_1\|},/d' "$implicitDirectory/$json" + then + echo "unable to remove enable environment variable" >&2 + return 1 + fi + + # Test without setting enable environment variable. The loader should load the layer. + output=$(GTEST_FILTER=ImplicitLayer.Present \ + ./vk_loader_validation_tests 2>&1) + if ! echo "$output" | grep -q "VK_LAYER_LUNARG_test: CreateInstance" + then + echo "test layer not detected" >&2 + return 1 + fi + + # Remove the test layer. + if ! rm "$implicitDirectory/$sharedObject" || ! rm "$implicitDirectory/$json" + then + echo "unable to uninstall test layer" >&2 + return 1 + fi + + echo "ImplicitLayer test PASSED" +} + +! RunImplicitLayerTest && echo "ImplicitLayer test FAILED" >&2 && exit 1 + +popd > /dev/null -- 2.7.4