layers: Add sampler unnormalized coords checks
Adds checks for VUIDs:
VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072
VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073
VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074
VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075
VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077
and tests them with:
VkLayerTest.UnnormalizedCoordinatesEnabled
diff --git a/layers/parameter_validation_utils.cpp b/layers/parameter_validation_utils.cpp
index 295f1db..17f95bb 100644
--- a/layers/parameter_validation_utils.cpp
+++ b/layers/parameter_validation_utils.cpp
@@ -2021,6 +2021,7 @@
if (pCreateInfo != nullptr) {
const auto &features = device_data->physical_device_features;
const auto &limits = device_data->device_limits;
+
if (pCreateInfo->anisotropyEnable == VK_TRUE) {
if (!in_inclusive_range(pCreateInfo->maxAnisotropy, 1.0F, limits.maxSamplerAnisotropy)) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
@@ -2037,14 +2038,54 @@
"vkCreateSampler(): Anisotropic sampling feature is not enabled, %s must be VK_FALSE.",
"pCreateInfo->anisotropyEnable");
}
+ }
- // Anistropy and unnormalized coordinates cannot be enabled simultaneously
- if (pCreateInfo->unnormalizedCoordinates == VK_TRUE) {
+ if (pCreateInfo->unnormalizedCoordinates == VK_TRUE) {
+ if (pCreateInfo->minFilter != pCreateInfo->magFilter) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072",
+ "vkCreateSampler(): when pCreateInfo->unnormalizedCoordinates is VK_TRUE, "
+ "pCreateInfo->minFilter (%s) and pCreateInfo->magFilter (%s) must be equal.",
+ string_VkFilter(pCreateInfo->minFilter), string_VkFilter(pCreateInfo->magFilter));
+ }
+ if (pCreateInfo->mipmapMode != VK_SAMPLER_MIPMAP_MODE_NEAREST) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073",
+ "vkCreateSampler(): when pCreateInfo->unnormalizedCoordinates is VK_TRUE, "
+ "pCreateInfo->mipmapMode (%s) must be VK_SAMPLER_MIPMAP_MODE_NEAREST.",
+ string_VkSamplerMipmapMode(pCreateInfo->mipmapMode));
+ }
+ if (pCreateInfo->minLod != 0.0f || pCreateInfo->maxLod != 0.0f) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074",
+ "vkCreateSampler(): when pCreateInfo->unnormalizedCoordinates is VK_TRUE, "
+ "pCreateInfo->minLod (%f) and pCreateInfo->maxLod (%f) must both be zero.",
+ pCreateInfo->minLod, pCreateInfo->maxLod);
+ }
+ if ((pCreateInfo->addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE &&
+ pCreateInfo->addressModeU != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
+ (pCreateInfo->addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE &&
+ pCreateInfo->addressModeV != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075",
+ "vkCreateSampler(): when pCreateInfo->unnormalizedCoordinates is VK_TRUE, "
+ "pCreateInfo->addressModeU (%s) and pCreateInfo->addressModeV (%s) must both be "
+ "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE or VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER.",
+ string_VkSamplerAddressMode(pCreateInfo->addressModeU),
+ string_VkSamplerAddressMode(pCreateInfo->addressModeV));
+ }
+ if (pCreateInfo->anisotropyEnable == VK_TRUE) {
skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
"VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076",
"vkCreateSampler(): pCreateInfo->anisotropyEnable and pCreateInfo->unnormalizedCoordinates must "
"not both be VK_TRUE.");
}
+ if (pCreateInfo->compareEnable == VK_TRUE) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ "VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077",
+ "vkCreateSampler(): pCreateInfo->compareEnable and pCreateInfo->unnormalizedCoordinates must "
+ "not both be VK_TRUE.");
+ }
}
// If compareEnable is VK_TRUE, compareOp must be a valid VkCompareOp value
diff --git a/layers/vk_validation_error_database.txt b/layers/vk_validation_error_database.txt
index 63e5da8..2c30bf7 100644
--- a/layers/vk_validation_error_database.txt
+++ b/layers/vk_validation_error_database.txt
@@ -1304,12 +1304,12 @@
VALIDATION_ERROR_1260085a~^~N~^~Unknown~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-mipLodBias-01069~^~core~^~The spec valid usage text states 'The absolute value of mipLodBias must be less than or equal to VkPhysicalDeviceLimits::maxSamplerLodBias' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-mipLodBias-01069)~^~
VALIDATION_ERROR_1260085c~^~Y~^~AnisotropyFeatureDisabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-anisotropyEnable-01070~^~core~^~The spec valid usage text states 'If the anisotropic sampling feature is not enabled, anisotropyEnable must be VK_FALSE' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-anisotropyEnable-01070)~^~
VALIDATION_ERROR_1260085e~^~Y~^~AnisotropyFeatureEnabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-anisotropyEnable-01071~^~core~^~The spec valid usage text states 'If anisotropyEnable is VK_TRUE, maxAnisotropy must be between 1.0 and VkPhysicalDeviceLimits::maxSamplerAnisotropy, inclusive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-anisotropyEnable-01071)~^~
-VALIDATION_ERROR_12600860~^~N~^~Unknown~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, minFilter and magFilter must be equal' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072)~^~
-VALIDATION_ERROR_12600862~^~N~^~Unknown~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, mipmapMode must be VK_SAMPLER_MIPMAP_MODE_NEAREST' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073)~^~
-VALIDATION_ERROR_12600864~^~N~^~Unknown~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, minLod and maxLod must be zero' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074)~^~
-VALIDATION_ERROR_12600866~^~N~^~Unknown~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, addressModeU and addressModeV must each be either VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE or VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075)~^~
+VALIDATION_ERROR_12600860~^~Y~^~UnnormalizedCoordinatesEnabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, minFilter and magFilter must be equal' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072)~^~
+VALIDATION_ERROR_12600862~^~Y~^~UnnormalizedCoordinatesEnabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, mipmapMode must be VK_SAMPLER_MIPMAP_MODE_NEAREST' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073)~^~
+VALIDATION_ERROR_12600864~^~Y~^~UnnormalizedCoordinatesEnabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, minLod and maxLod must be zero' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074)~^~
+VALIDATION_ERROR_12600866~^~Y~^~UnnormalizedCoordinatesEnabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, addressModeU and addressModeV must each be either VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE or VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075)~^~
VALIDATION_ERROR_12600868~^~Y~^~AnisotropyFeatureEnabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, anisotropyEnable must be VK_FALSE' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076)~^~
-VALIDATION_ERROR_1260086a~^~N~^~Unknown~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, compareEnable must be VK_FALSE' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077)~^~
+VALIDATION_ERROR_1260086a~^~Y~^~UnnormalizedCoordinatesEnabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077~^~core~^~The spec valid usage text states 'If unnormalizedCoordinates is VK_TRUE, compareEnable must be VK_FALSE' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077)~^~
VALIDATION_ERROR_1260086c~^~Y~^~Unknown~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-addressModeU-01078~^~core~^~The spec valid usage text states 'If any of addressModeU, addressModeV or addressModeW are VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, borderColor must be a valid VkBorderColor value' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-addressModeU-01078)~^~
VALIDATION_ERROR_1260086e~^~Y~^~MirrorClampToEdgeNotEnabled~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-addressModeU-01079~^~core~^~The spec valid usage text states 'If the VK_KHR_sampler_mirror_clamp_to_edge extension is not enabled, addressModeU, addressModeV and addressModeW must not be VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-addressModeU-01079)~^~
VALIDATION_ERROR_12600870~^~Y~^~Unknown~^~VkSamplerCreateInfo~^~VUID-VkSamplerCreateInfo-compareEnable-01080~^~core~^~The spec valid usage text states 'If compareEnable is VK_TRUE, compareOp must be a valid VkCompareOp value' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkSamplerCreateInfo-compareEnable-01080)~^~
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 3f6638b..9e02540 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -197,13 +197,13 @@
sampler_create_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler_create_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
sampler_create_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
- sampler_create_info.mipLodBias = 1.0;
+ sampler_create_info.mipLodBias = 0.0;
sampler_create_info.anisotropyEnable = VK_FALSE;
sampler_create_info.maxAnisotropy = 1.0;
sampler_create_info.compareEnable = VK_FALSE;
sampler_create_info.compareOp = VK_COMPARE_OP_NEVER;
- sampler_create_info.minLod = 1.0;
- sampler_create_info.maxLod = 1.0;
+ sampler_create_info.minLod = 0.0;
+ sampler_create_info.maxLod = 16.0;
sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
sampler_create_info.unnormalizedCoordinates = VK_FALSE;
@@ -1585,7 +1585,7 @@
ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features));
- // These tests require that the device support sparse residency for 2D images
+ // These tests require that the device support anisotropic filtering
if (VK_TRUE != device_features.samplerAnisotropy) {
printf("%s Test requires unsupported samplerAnisotropy feature. Skipped.\n", kSkipPrefix);
return;
@@ -1642,6 +1642,78 @@
}
}
+TEST_F(VkLayerTest, UnnormalizedCoordinatesEnabled) {
+ TEST_DESCRIPTION("Validate restrictions on sampler parameters when unnormalizedCoordinates is true.");
+
+ ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
+ VkSamplerCreateInfo sampler_info_ref = SafeSaneSamplerCreateInfo();
+ sampler_info_ref.unnormalizedCoordinates = VK_TRUE;
+ sampler_info_ref.minLod = 0.0f;
+ sampler_info_ref.maxLod = 0.0f;
+ VkSamplerCreateInfo sampler_info = sampler_info_ref;
+ ASSERT_NO_FATAL_FAILURE(InitState());
+
+ auto do_test = [this](std::string code, const VkSamplerCreateInfo *pCreateInfo) -> void {
+ VkResult err;
+ VkSampler sampler = VK_NULL_HANDLE;
+ m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, code);
+ err = vkCreateSampler(m_device->device(), pCreateInfo, NULL, &sampler);
+ m_errorMonitor->VerifyFound();
+ if (VK_SUCCESS == err) {
+ vkDestroySampler(m_device->device(), sampler, NULL);
+ }
+ };
+
+ // min and mag filters must be the same
+ sampler_info.minFilter = VK_FILTER_NEAREST;
+ sampler_info.magFilter = VK_FILTER_LINEAR;
+ do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072", &sampler_info);
+ std::swap(sampler_info.minFilter, sampler_info.magFilter);
+ do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072", &sampler_info);
+ sampler_info = sampler_info_ref;
+
+ // mipmapMode must be NEAREST
+ sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073", &sampler_info);
+ sampler_info = sampler_info_ref;
+
+ // minlod and maxlod must be zero
+ sampler_info.maxLod = 3.14159f;
+ do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074", &sampler_info);
+ sampler_info.minLod = 2.71828f;
+ do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074", &sampler_info);
+ sampler_info = sampler_info_ref;
+
+ // addressModeU and addressModeV must both be CLAMP_TO_EDGE or CLAMP_TO_BORDER
+ // checks all 12 invalid combinations out of 16 total combinations
+ const std::array<VkSamplerAddressMode, 4> kAddressModes = {{
+ VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
+ }};
+ for (const auto umode : kAddressModes) {
+ for (const auto vmode : kAddressModes) {
+ if ((umode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && umode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
+ (vmode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && vmode != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)) {
+ sampler_info.addressModeU = umode;
+ sampler_info.addressModeV = vmode;
+ do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075", &sampler_info);
+ }
+ }
+ }
+ sampler_info = sampler_info_ref;
+
+ // VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076 is tested in AnisotropyFeatureEnabled above
+ // Since it requires checking/enabling the anisotropic filtering feature, it's easier to do it
+ // with the other anisotropic tests.
+
+ // compareEnable must be VK_FALSE
+ sampler_info.compareEnable = VK_TRUE;
+ do_test("VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01077", &sampler_info);
+ sampler_info = sampler_info_ref;
+}
+
TEST_F(VkLayerTest, UnrecognizedValueMaxEnum) {
ASSERT_NO_FATAL_FAILURE(Init());
@@ -30118,7 +30190,7 @@
m_commandBuffer->end();
m_errorMonitor->VerifyNotFound();
-#if 0
+#if 0
// Copy to/from buffer
VkBufferCreateInfo bci = {};
bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;