blob: 0c7315b93be71f7651a91dbfc28721a3fc99cc65 [file] [log] [blame]
/*
* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
* Copyright (c) 2015-2025 Google, 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
*/
#include "../framework/layer_validation_tests.h"
#include <cstdlib>
class VkPositiveLayerTest : public VkLayerTest {};
TEST_F(VkPositiveLayerTest, StatelessValidationDisable) {
TEST_DESCRIPTION("Specify a non-zero value for a reserved parameter with stateless validation disabled");
VkValidationFeatureDisableEXT disables[] = {VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT};
VkValidationFeaturesEXT features = {};
features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
features.disabledValidationFeatureCount = 1;
features.pDisabledValidationFeatures = disables;
RETURN_IF_SKIP(Init(nullptr, nullptr, &features));
// Specify 0 for a reserved VkFlags parameter. Normally this is expected to trigger an stateless validation error, but this
// validation was disabled via the features extension, so no errors should be forthcoming.
VkEventCreateInfo event_info = vku::InitStructHelper();
event_info.flags = 1;
vkt::Event event(*m_device, event_info);
}
TEST_F(VkPositiveLayerTest, Maintenance1Tests) {
TEST_DESCRIPTION("Validate various special cases for the Maintenance1_KHR extension");
AddRequiredExtensions(VK_KHR_MAINTENANCE_1_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
vkt::CommandBuffer cmd_buf(*m_device, m_command_pool);
cmd_buf.Begin();
// Set Negative height, should give error if Maintenance 1 is not enabled
VkViewport viewport = {0, 0, 16, -16, 0, 1};
vk::CmdSetViewport(cmd_buf, 0, 1, &viewport);
cmd_buf.End();
}
TEST_F(VkPositiveLayerTest, ValidStructPNext) {
TEST_DESCRIPTION("Verify that a valid pNext value is handled correctly");
// Positive test to check parameter_validation and unique_objects support for NV_dedicated_allocation
AddRequiredExtensions(VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkDedicatedAllocationBufferCreateInfoNV dedicated_buffer_create_info = vku::InitStructHelper();
dedicated_buffer_create_info.dedicatedAllocation = VK_TRUE;
VkBufferCreateInfo buffer_create_info = vku::InitStructHelper(&dedicated_buffer_create_info);
buffer_create_info.size = 1024;
buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
vkt::Buffer buffer(*m_device, buffer_create_info, vkt::no_mem);
VkMemoryRequirements memory_reqs;
vk::GetBufferMemoryRequirements(device(), buffer, &memory_reqs);
VkDedicatedAllocationMemoryAllocateInfoNV dedicated_memory_info = vku::InitStructHelper();
dedicated_memory_info.buffer = buffer;
dedicated_memory_info.image = VK_NULL_HANDLE;
VkMemoryAllocateInfo memory_info = vku::InitStructHelper(&dedicated_memory_info);
memory_info.allocationSize = memory_reqs.size;
bool pass;
pass = m_device->Physical().SetMemoryType(memory_reqs.memoryTypeBits, &memory_info, 0);
ASSERT_TRUE(pass);
vkt::DeviceMemory buffer_memory(*m_device, memory_info);
vk::BindBufferMemory(device(), buffer, buffer_memory, 0);
}
TEST_F(VkPositiveLayerTest, DeviceIDPropertiesExtensions) {
TEST_DESCRIPTION("VkPhysicalDeviceIDProperties can be enabled from 1 of 3 extensions");
SetTargetApiVersion(VK_API_VERSION_1_0);
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
if (DeviceValidationVersion() != VK_API_VERSION_1_0) {
GTEST_SKIP() << "Test's for 1.0 only";
}
VkPhysicalDeviceIDProperties id_props = vku::InitStructHelper();
VkPhysicalDeviceProperties2 props2 = vku::InitStructHelper(&id_props);
vk::GetPhysicalDeviceProperties2KHR(Gpu(), &props2);
}
TEST_F(VkPositiveLayerTest, ParameterLayerFeatures2Capture) {
TEST_DESCRIPTION("Ensure parameter_validation_layer correctly captures physical device features");
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
VkResult err;
VkPhysicalDeviceFeatures2 features2 = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(features2);
if (!features2.features.samplerAnisotropy) {
GTEST_SKIP() << "samplerAnisotropy feature not supported";
}
if (!features2.features.pipelineStatisticsQuery) {
GTEST_SKIP() << "pipelineStatisticsQuery feature not supported";
}
// We're not creating a valid m_device, but the phy wrapper is useful
vkt::PhysicalDevice physical_device(Gpu());
vkt::QueueCreateInfoArray queue_info(physical_device.queue_properties_);
// Only request creation with queuefamilies that have at least one queue
std::vector<VkDeviceQueueCreateInfo> create_queue_infos;
auto qci = queue_info.Data();
for (uint32_t i = 0; i < queue_info.Size(); ++i) {
if (qci[i].queueCount) {
create_queue_infos.push_back(qci[i]);
}
}
VkDeviceCreateInfo dev_info = vku::InitStructHelper(&features2);
dev_info.flags = 0;
dev_info.queueCreateInfoCount = create_queue_infos.size();
dev_info.pQueueCreateInfos = create_queue_infos.data();
dev_info.enabledLayerCount = 0;
dev_info.ppEnabledLayerNames = nullptr;
dev_info.enabledExtensionCount = 0;
dev_info.ppEnabledExtensionNames = nullptr;
dev_info.pEnabledFeatures = nullptr;
VkDevice device;
err = vk::CreateDevice(Gpu(), &dev_info, nullptr, &device);
ASSERT_EQ(VK_SUCCESS, err);
{
// Test that the parameter layer is caching the features correctly using CreateSampler
VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
// If the features were not captured correctly, this should cause an error
sampler_ci.anisotropyEnable = VK_TRUE;
sampler_ci.maxAnisotropy = physical_device.limits_.maxSamplerAnisotropy;
VkSampler sampler = VK_NULL_HANDLE;
err = vk::CreateSampler(device, &sampler_ci, nullptr, &sampler);
ASSERT_EQ(VK_SUCCESS, err);
vk::DestroySampler(device, sampler, nullptr);
}
// Verify the core validation layer has captured the physical device features by creating a a query pool.
{
VkQueryPool query_pool;
VkQueryPoolCreateInfo qpci = vkt::QueryPool::CreateInfo(VK_QUERY_TYPE_PIPELINE_STATISTICS, 1);
qpci.pipelineStatistics = VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT;
err = vk::CreateQueryPool(device, &qpci, nullptr, &query_pool);
ASSERT_EQ(VK_SUCCESS, err);
vk::DestroyQueryPool(device, query_pool, nullptr);
}
vk::DestroyDevice(device, nullptr);
}
TEST_F(VkPositiveLayerTest, ApiVersionZero) {
TEST_DESCRIPTION("Check that apiVersion = 0 is valid.");
app_info_.apiVersion = 0U;
RETURN_IF_SKIP(InitFramework());
}
TEST_F(VkPositiveLayerTest, ModifyPnext) {
TEST_DESCRIPTION("Make sure invalid values in pNext structures are ignored at query time");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV shading = vku::InitStructHelper();
shading.maxFragmentShadingRateInvocationCount = static_cast<VkSampleCountFlagBits>(0);
VkPhysicalDeviceProperties2 props = vku::InitStructHelper(&shading);
vk::GetPhysicalDeviceProperties2(Gpu(), &props);
}
TEST_F(VkPositiveLayerTest, UseFirstQueueUnqueried) {
TEST_DESCRIPTION("Use first queue family and one queue without first querying with vkGetPhysicalDeviceQueueFamilyProperties");
RETURN_IF_SKIP(InitFramework());
const float q_priority[] = {1.0f};
VkDeviceQueueCreateInfo queue_ci = vku::InitStructHelper();
queue_ci.queueFamilyIndex = 0;
queue_ci.queueCount = 1;
queue_ci.pQueuePriorities = q_priority;
VkDeviceCreateInfo device_ci = vku::InitStructHelper();
device_ci.queueCreateInfoCount = 1;
device_ci.pQueueCreateInfos = &queue_ci;
VkDevice test_device;
vk::CreateDevice(Gpu(), &device_ci, nullptr, &test_device);
vk::DestroyDevice(test_device, nullptr);
}
// Android loader returns an error in this case
#if !defined(VK_USE_PLATFORM_ANDROID_KHR)
TEST_F(VkPositiveLayerTest, GetDevProcAddrNullPtr) {
TEST_DESCRIPTION("Call GetDeviceProcAddr on an enabled instance extension expecting nullptr");
AddRequiredExtensions(VK_KHR_SURFACE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
m_errorMonitor->SetAllowedFailureMsg("WARNING-vkGetDeviceProcAddr-device");
auto fpDestroySurface = (PFN_vkCreateValidationCacheEXT)vk::GetDeviceProcAddr(device(), "vkDestroySurfaceKHR");
if (fpDestroySurface) {
m_errorMonitor->SetError("Null was expected!");
}
}
TEST_F(VkPositiveLayerTest, GetDevProcAddrExtensions) {
TEST_DESCRIPTION("Call GetDeviceProcAddr with and without extension enabled");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
auto vkTrimCommandPool = vk::GetDeviceProcAddr(device(), "vkTrimCommandPool");
auto vkTrimCommandPoolKHR = vk::GetDeviceProcAddr(device(), "vkTrimCommandPoolKHR");
if (nullptr == vkTrimCommandPool) m_errorMonitor->SetError("Unexpected null pointer");
if (nullptr != vkTrimCommandPoolKHR) m_errorMonitor->SetError("Didn't receive expected null pointer");
const char *const extension = {VK_KHR_MAINTENANCE_1_EXTENSION_NAME};
const float q_priority[] = {1.0f};
VkDeviceQueueCreateInfo queue_ci = vku::InitStructHelper();
queue_ci.queueFamilyIndex = 0;
queue_ci.queueCount = 1;
queue_ci.pQueuePriorities = q_priority;
VkDeviceCreateInfo device_ci = vku::InitStructHelper();
device_ci.enabledExtensionCount = 1;
device_ci.ppEnabledExtensionNames = &extension;
device_ci.queueCreateInfoCount = 1;
device_ci.pQueueCreateInfos = &queue_ci;
VkDevice device;
vk::CreateDevice(Gpu(), &device_ci, NULL, &device);
vkTrimCommandPoolKHR = vk::GetDeviceProcAddr(device, "vkTrimCommandPoolKHR");
if (nullptr == vkTrimCommandPoolKHR) m_errorMonitor->SetError("Unexpected null pointer");
vk::DestroyDevice(device, nullptr);
}
#endif
TEST_F(VkPositiveLayerTest, Vulkan12FeaturesBufferDeviceAddress) {
TEST_DESCRIPTION("Enable bufferDeviceAddress feature via Vulkan12features struct");
SetTargetApiVersion(VK_API_VERSION_1_2);
RETURN_IF_SKIP(InitFramework());
VkPhysicalDeviceBufferDeviceAddressFeatures bda_features = vku::InitStructHelper();
VkPhysicalDeviceFeatures2 features2 = GetPhysicalDeviceFeatures2(bda_features);
if (!bda_features.bufferDeviceAddress) {
GTEST_SKIP() << "Buffer Device Address feature not supported, skipping test";
}
VkPhysicalDeviceVulkan12Features features12 = vku::InitStructHelper();
features12.bufferDeviceAddress = true;
features2.pNext = &features12;
RETURN_IF_SKIP(InitState(nullptr, &features2));
VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper();
alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
vkt::Buffer buffer(*m_device, 1024, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&alloc_flags);
(void)buffer.Address();
// Also verify that we don't get the KHR extension address without enabling the KHR extension
auto vkGetBufferDeviceAddressKHR =
(PFN_vkGetBufferDeviceAddressKHR)vk::GetDeviceProcAddr(device(), "vkGetBufferDeviceAddressKHR");
if (nullptr != vkGetBufferDeviceAddressKHR) m_errorMonitor->SetError("Didn't receive expected null pointer");
}
TEST_F(VkPositiveLayerTest, EnumeratePhysicalDeviceGroups) {
TEST_DESCRIPTION("Test using VkPhysicalDevice handles obtained with vkEnumeratePhysicalDeviceGroups");
#ifdef __linux__
if (std::getenv("NODEVICE_SELECT") == nullptr) {
// Currently due to a bug in MESA this test will fail.
// https://gitlab.freedesktop.org/mesa/mesa/-/commit/4588453815c58ec848b0ff6f18a08836e70f55df
//
// It's fixed as of v22.7.1:
// https://gitlab.freedesktop.org/mesa/mesa/-/tree/mesa-22.1.7/src/vulkan/device-select-layer
//
// To avoid impacting local users, skip this TEST unless NODEVICE_SELECT is specified.
// NODEVICE_SELECT enables/disables the implicit mesa layer which has illegal code:
// https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/vulkan/device-select-layer/VkLayer_MESA_device_select.json
GTEST_SKIP();
}
#endif
SetTargetApiVersion(VK_API_VERSION_1_1);
auto ici = GetInstanceCreateInfo();
VkInstance test_instance = VK_NULL_HANDLE;
ASSERT_EQ(VK_SUCCESS, vk::CreateInstance(&ici, nullptr, &test_instance));
for (const char *instance_ext_name : m_instance_extension_names) {
vk::InitInstanceExtension(test_instance, instance_ext_name);
}
ErrorMonitor monitor = ErrorMonitor(false);
monitor.CreateCallback(test_instance);
uint32_t physical_device_group_count = 0;
vk::EnumeratePhysicalDeviceGroups(test_instance, &physical_device_group_count, nullptr);
std::vector<VkPhysicalDeviceGroupProperties> device_groups(physical_device_group_count,
vku::InitStruct<VkPhysicalDeviceGroupProperties>());
vk::EnumeratePhysicalDeviceGroups(test_instance, &physical_device_group_count, device_groups.data());
if (physical_device_group_count > 0) {
VkPhysicalDevice physicalDevice = device_groups[0].physicalDevices[0];
uint32_t queueFamilyPropertyCount = 0;
vk::GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertyCount, nullptr);
}
monitor.DestroyCallback(test_instance);
vk::DestroyInstance(test_instance, nullptr);
}
TEST_F(VkPositiveLayerTest, ExtensionXmlDependsLogic) {
TEST_DESCRIPTION("Make sure the OR in 'depends' from XML is observed correctly");
// VK_KHR_buffer_device_address requires
// (VK_KHR_get_physical_device_properties2 AND VK_KHR_device_group) OR VK_VERSION_1_1
// If Vulkan 1.1 is not supported, should still be valid
SetTargetApiVersion(VK_API_VERSION_1_0);
if (!InstanceExtensionSupported(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME) ||
!InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
GTEST_SKIP() << "Did not find the required instance extensions";
}
m_instance_extension_names.push_back(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME);
m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
if (!DeviceExtensionSupported(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) ||
!DeviceExtensionSupported(VK_KHR_DEVICE_GROUP_EXTENSION_NAME)) {
GTEST_SKIP() << "Did not find the required device extensions";
}
m_device_extension_names.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
m_device_extension_names.push_back(VK_KHR_DEVICE_GROUP_EXTENSION_NAME);
RETURN_IF_SKIP(InitState());
}
TEST_F(VkPositiveLayerTest, FormatProperties3FromProfiles) {
// https://github.com/KhronosGroup/Vulkan-Profiles/pull/392
TEST_DESCRIPTION("Make sure VkFormatProperties3 is overwritten correctly in Profiles layer");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkFormatProperties3 fmt_props_3 = vku::InitStructHelper();
VkFormatProperties2 fmt_props = vku::InitStructHelper(&fmt_props_3);
vk::GetPhysicalDeviceFormatProperties2(Gpu(), VK_FORMAT_R8_UNORM, &fmt_props);
vk::GetPhysicalDeviceFormatProperties2(Gpu(), VK_FORMAT_R8G8B8A8_UNORM, &fmt_props);
}
TEST_F(VkPositiveLayerTest, GDPAWithMultiCmdExt) {
TEST_DESCRIPTION("Use GetDeviceProcAddr on a function which is provided by multiple extensions");
AddRequiredExtensions(VK_EXT_SHADER_OBJECT_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
auto vkCmdSetColorBlendAdvancedEXT = GetDeviceProcAddr<PFN_vkCmdSetColorBlendAdvancedEXT>("vkCmdSetColorBlendAdvancedEXT");
ASSERT_NE(vkCmdSetColorBlendAdvancedEXT, nullptr);
}
TEST_F(VkPositiveLayerTest, UseInteractionApi1) {
TEST_DESCRIPTION("Use an API that is provided by multiple extensions (part 1)");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
auto vkGetDeviceGroupPresentCapabilitiesKHR =
GetDeviceProcAddr<PFN_vkGetDeviceGroupPresentCapabilitiesKHR>("vkGetDeviceGroupPresentCapabilitiesKHR");
if (!vkGetDeviceGroupPresentCapabilitiesKHR) {
GTEST_SKIP() << "Driver doesn't expose vkGetDeviceGroupPresentCapabilitiesKHR";
}
VkDeviceGroupPresentCapabilitiesKHR device_group_present_caps = vku::InitStructHelper();
vk::GetDeviceGroupPresentCapabilitiesKHR(device(), &device_group_present_caps);
}
TEST_F(VkPositiveLayerTest, UseInteractionApi2) {
TEST_DESCRIPTION("Use an API that is provided by multiple extensions (part 2)");
SetTargetApiVersion(VK_API_VERSION_1_0);
AddRequiredExtensions(VK_KHR_SURFACE_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DEVICE_GROUP_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
auto vkGetDeviceGroupPresentCapabilitiesKHR =
GetDeviceProcAddr<PFN_vkGetDeviceGroupPresentCapabilitiesKHR>("vkGetDeviceGroupPresentCapabilitiesKHR");
if (!vkGetDeviceGroupPresentCapabilitiesKHR) {
GTEST_SKIP() << "Driver doesn't expose vkGetDeviceGroupPresentCapabilitiesKHR";
}
VkDeviceGroupPresentCapabilitiesKHR device_group_present_caps = vku::InitStructHelper();
vk::GetDeviceGroupPresentCapabilitiesKHR(device(), &device_group_present_caps);
}
TEST_F(VkPositiveLayerTest, ExtensionExpressions) {
TEST_DESCRIPTION(
"Enable an extension (e.g., VK_KHR_fragment_shading_rate) that depends on multiple core versions _or_ regular extensions");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::pipelineFragmentShadingRate);
RETURN_IF_SKIP(Init());
VkExtent2D fragment_size = {1, 1};
std::array combiner_ops = {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR};
m_command_buffer.Begin();
vk::CmdSetFragmentShadingRateKHR(m_command_buffer, &fragment_size, combiner_ops.data());
m_command_buffer.End();
}
TEST_F(VkPositiveLayerTest, AllowedDuplicateStype) {
TEST_DESCRIPTION("Pass duplicate structs to whose vk.xml definition contains allowduplicate=true");
VkInstance instance;
VkInstanceCreateInfo ici = vku::InitStructHelper();
ici.enabledLayerCount = instance_layers_.size();
ici.ppEnabledLayerNames = instance_layers_.data();
VkDebugUtilsMessengerCreateInfoEXT dbgUtils0 = vku::InitStructHelper();
VkDebugUtilsMessengerCreateInfoEXT dbgUtils1 = vku::InitStructHelper(&dbgUtils0);
ici.pNext = &dbgUtils1;
ASSERT_EQ(VK_SUCCESS, vk::CreateInstance(&ici, nullptr, &instance));
ASSERT_NO_FATAL_FAILURE(vk::DestroyInstance(instance, nullptr));
}
TEST_F(VkPositiveLayerTest, ExtensionsInCreateInstance) {
TEST_DESCRIPTION("Test to see if instance extensions are called during CreateInstance.");
// See https://github.com/KhronosGroup/Vulkan-Loader/issues/537 for more details.
// This is specifically meant to ensure a crash encountered in profiles does not occur, but also to
// attempt to ensure that no extension calls have been added to CreateInstance hooks.
// NOTE: it is certainly possible that a layer will call an extension during the Createinstance hook
// and the loader will _not_ crash (e.g., nvidia, android seem to not crash in this case, but AMD does).
// So, this test will only catch an erroneous extension _if_ run on HW/a driver that crashes in this use
// case.
AddOptionalExtensions(VK_KHR_SURFACE_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_DISPLAY_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
AddOptionalExtensions(VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
}
TEST_F(VkPositiveLayerTest, ExclusiveScissorVersionCount) {
TEST_DESCRIPTION("Test using vkCmdSetExclusiveScissorEnableNV.");
AddRequiredExtensions(VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
uint32_t propertyCount = 0u;
vk::EnumerateDeviceExtensionProperties(gpu_, nullptr, &propertyCount, nullptr);
std::vector<VkExtensionProperties> properties(propertyCount);
vk::EnumerateDeviceExtensionProperties(gpu_, nullptr, &propertyCount, properties.data());
bool exclusiveScissor2 = false;
for (const auto &prop : properties) {
if (strcmp(prop.extensionName, VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME) == 0) {
if (prop.specVersion >= 2) {
exclusiveScissor2 = true;
}
break;
}
}
if (!exclusiveScissor2) {
GTEST_SKIP() << VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME << " version 2 not supported";
}
RETURN_IF_SKIP(InitState());
m_command_buffer.Begin();
VkBool32 exclusiveScissorEnable = VK_TRUE;
vk::CmdSetExclusiveScissorEnableNV(m_command_buffer, 0u, 1u, &exclusiveScissorEnable);
m_command_buffer.End();
}
TEST_F(VkPositiveLayerTest, GetCalibratedTimestamps) {
TEST_DESCRIPTION("Basic usage of vkGetCalibratedTimestampsEXT.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
uint32_t count = 0;
vk::GetPhysicalDeviceCalibrateableTimeDomainsEXT(Gpu(), &count, nullptr);
if (count < 2) {
GTEST_SKIP() << "only 1 TimeDomain supported";
}
std::vector<VkTimeDomainEXT> time_domains(count);
vk::GetPhysicalDeviceCalibrateableTimeDomainsEXT(Gpu(), &count, time_domains.data());
VkCalibratedTimestampInfoEXT timestamp_infos[2];
timestamp_infos[0] = vku::InitStructHelper();
timestamp_infos[0].timeDomain = time_domains[0];
timestamp_infos[1] = vku::InitStructHelper();
timestamp_infos[1].timeDomain = time_domains[1];
uint64_t timestamps[2];
uint64_t max_deviation;
vk::GetCalibratedTimestampsEXT(device(), 2, timestamp_infos, timestamps, &max_deviation);
}
TEST_F(VkPositiveLayerTest, GetCalibratedTimestampsKHR) {
TEST_DESCRIPTION("Basic usage of vkGetCalibratedTimestampsKHR.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
uint32_t count = 0;
vk::GetPhysicalDeviceCalibrateableTimeDomainsKHR(Gpu(), &count, nullptr);
if (count < 2) {
GTEST_SKIP() << "only 1 TimeDomain supported";
}
std::vector<VkTimeDomainKHR> time_domains(count);
vk::GetPhysicalDeviceCalibrateableTimeDomainsKHR(Gpu(), &count, time_domains.data());
VkCalibratedTimestampInfoKHR timestamp_infos[2];
timestamp_infos[0] = vku::InitStructHelper();
timestamp_infos[0].timeDomain = time_domains[0];
timestamp_infos[1] = vku::InitStructHelper();
timestamp_infos[1].timeDomain = time_domains[1];
uint64_t timestamps[2];
uint64_t max_deviation;
vk::GetCalibratedTimestampsKHR(device(), 2, timestamp_infos, timestamps, &max_deviation);
}
TEST_F(VkPositiveLayerTest, ExtensionPhysicalDeviceFeatureEXT) {
TEST_DESCRIPTION("VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR has an EXT and KHR extension that can enable it");
AddRequiredExtensions(VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR query_feature = vku::InitStructHelper();
query_feature.globalPriorityQuery = VK_TRUE;
RETURN_IF_SKIP(InitState(nullptr, &query_feature));
}
TEST_F(VkPositiveLayerTest, ExtensionPhysicalDeviceFeatureKHR) {
TEST_DESCRIPTION("VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR has an EXT and KHR extension that can enable it");
AddRequiredExtensions(VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework());
VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR query_feature = vku::InitStructHelper();
query_feature.globalPriorityQuery = VK_TRUE;
RETURN_IF_SKIP(InitState(nullptr, &query_feature));
}
TEST_F(VkPositiveLayerTest, NoExtensionFromInstanceFunction) {
TEST_DESCRIPTION("Valid because we instance functions don't know which device it needs");
SetTargetApiVersion(VK_API_VERSION_1_1);
// Required to pass in various memory flags without querying for corresponding extensions.
AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkFormatProperties format_properties;
// need VK_KHR_sampler_ycbcr_conversion if it was a device function
vk::GetPhysicalDeviceFormatProperties(Gpu(), VK_FORMAT_B16G16R16G16_422_UNORM, &format_properties);
}
TEST_F(VkPositiveLayerTest, InstanceExtensionsCallingDeviceStruct0) {
TEST_DESCRIPTION(
"Use VkImageFormatListCreateInfo with VkPhysicalDeviceImageFormatInfo2 if VK_KHR_image_format_list is available");
SetTargetApiVersion(VK_API_VERSION_1_0);
AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(Gpu(), nullptr, VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME)) {
GTEST_SKIP() << "VK_KHR_image_format_list is not supported";
}
const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
// Requires device extension (VK_KHR_image_format_list)
VkImageFormatListCreateInfo format_list_info = vku::InitStructHelper();
format_list_info.viewFormatCount = 1;
format_list_info.pViewFormats = &format;
VkPhysicalDeviceImageFormatInfo2 image_format_info = vku::InitStructHelper(&format_list_info);
image_format_info.type = VK_IMAGE_TYPE_2D;
image_format_info.format = format;
image_format_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_format_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
VkImageFormatProperties2 image_format_properties = vku::InitStructHelper();
// Requires instance extension (VK_KHR_get_physical_device_properties2)
vk::GetPhysicalDeviceImageFormatProperties2KHR(Gpu(), &image_format_info, &image_format_properties);
}
TEST_F(VkPositiveLayerTest, InstanceExtensionsCallingDeviceStruct1) {
TEST_DESCRIPTION(
"Use VkBufferUsageFlags2CreateInfo with VkPhysicalDeviceExternalBufferInfo if VK_KHR_maintenance5 is available");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(Gpu(), nullptr, VK_KHR_MAINTENANCE_5_EXTENSION_NAME)) {
GTEST_SKIP() << "VK_KHR_maintenance5 is not supported";
}
#ifdef _WIN32
const auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
#else
const auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
#endif
// Requires device extension (VK_KHR_maintenance5)
VkBufferUsageFlags2CreateInfo bufferUsageFlags2 = vku::InitStructHelper();
bufferUsageFlags2.usage = VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT;
VkPhysicalDeviceExternalBufferInfo externalBufferInfo = vku::InitStructHelper(&bufferUsageFlags2);
externalBufferInfo.handleType = handle_type;
VkExternalBufferProperties externalBufferProperties = vku::InitStructHelper();
// Instance extension promoted to VK_VERSION_1_1
vk::GetPhysicalDeviceExternalBufferProperties(Gpu(), &externalBufferInfo, &externalBufferProperties);
}
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/10208
TEST_F(VkPositiveLayerTest, TimelineSemaphoreWithVulkan11) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8308");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_NV_LOW_LATENCY_2_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_PRESENT_ID_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
}
TEST_F(VkPositiveLayerTest, UnrecognizedEnumOutOfRange) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8367");
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(Gpu(), nullptr, VK_KHR_MAINTENANCE_5_EXTENSION_NAME)) {
GTEST_SKIP() << "VK_KHR_maintenance5 is not supported";
}
VkFormatProperties format_properties;
vk::GetPhysicalDeviceFormatProperties(Gpu(), static_cast<VkFormat>(8000), &format_properties);
m_errorMonitor->VerifyFound();
}
TEST_F(VkPositiveLayerTest, UnrecognizedEnumOutOfRange2) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8367");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(Gpu(), nullptr, VK_KHR_MAINTENANCE_5_EXTENSION_NAME)) {
GTEST_SKIP() << "VK_KHR_maintenance5 is not supported";
}
VkFormatProperties2 format_properties = vku::InitStructHelper();
vk::GetPhysicalDeviceFormatProperties2(Gpu(), static_cast<VkFormat>(8000), &format_properties);
}
TEST_F(VkPositiveLayerTest, UnrecognizedFlagOutOfRange) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8367");
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(Gpu(), nullptr, VK_KHR_MAINTENANCE_5_EXTENSION_NAME)) {
GTEST_SKIP() << "VK_KHR_maintenance5 is not supported";
}
VkImageFormatProperties format_properties;
vk::GetPhysicalDeviceImageFormatProperties(Gpu(), VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_1D, VK_IMAGE_TILING_OPTIMAL,
static_cast<VkImageUsageFlags>(0xffffffff), 0, &format_properties);
}
TEST_F(VkPositiveLayerTest, UnrecognizedFlagOutOfRange2) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8367");
SetTargetApiVersion(VK_API_VERSION_1_1);
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(Gpu(), nullptr, VK_KHR_MAINTENANCE_5_EXTENSION_NAME)) {
GTEST_SKIP() << "VK_KHR_maintenance5 is not supported";
}
VkImageFormatProperties2 format_properties = vku::InitStructHelper();
VkPhysicalDeviceImageFormatInfo2 format_info = vku::InitStructHelper();
format_info.format = VK_FORMAT_R8G8B8A8_UNORM;
format_info.flags = 0;
format_info.tiling = VK_IMAGE_TILING_OPTIMAL;
format_info.type = VK_IMAGE_TYPE_1D;
format_info.usage = static_cast<VkImageUsageFlags>(0xffffffff);
vk::GetPhysicalDeviceImageFormatProperties2(Gpu(), &format_info, &format_properties);
}
TEST_F(VkPositiveLayerTest, PhysicalDeviceLayeredApiVulkanProperties) {
SetTargetApiVersion(VK_API_VERSION_1_2);
RETURN_IF_SKIP(InitFramework());
// Don't enable maintenance7 because we are doing this at an instance level
// just make sure the extension is there
if (!DeviceExtensionSupported(VK_KHR_MAINTENANCE_7_EXTENSION_NAME)) {
GTEST_SKIP() << "Did not find the required device extensions";
}
RETURN_IF_SKIP(InitState());
VkPhysicalDeviceLayeredApiPropertiesKHR api_props = vku::InitStructHelper();
VkPhysicalDeviceLayeredApiPropertiesListKHR api_prop_lists = vku::InitStructHelper();
api_prop_lists.layeredApiCount = 1;
api_prop_lists.pLayeredApis = &api_props;
VkPhysicalDeviceProperties2 phys_dev_props_2 = vku::InitStructHelper(&api_prop_lists);
vk::GetPhysicalDeviceProperties2(Gpu(), &phys_dev_props_2);
}