tests: Implement VkViewport tests
authorPetr Kraus <petr_kraus@email.cz>
Tue, 9 Jan 2018 23:19:16 +0000 (00:19 +0100)
committerjzulauf-lunarg <32470354+jzulauf-lunarg@users.noreply.github.com>
Mon, 19 Feb 2018 16:11:34 +0000 (09:11 -0700)
layers/vk_validation_error_database.txt
tests/layer_validation_tests.cpp

index 5667869..dbfe7ce 100644 (file)
@@ -1539,23 +1539,23 @@ VALIDATION_ERROR_14e09005~^~Y~^~Unknown~^~vkCreateViSurfaceNN~^~VUID-VkViSurface
 VALIDATION_ERROR_14e1c40d~^~Y~^~Unknown~^~vkCreateViSurfaceNN~^~VUID-VkViSurfaceCreateInfoNN-pNext-pNext~^~core~^~The spec valid usage text states 'pNext must be NULL' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViSurfaceCreateInfoNN-pNext-pNext)~^~implicit
 VALIDATION_ERROR_14e2b00b~^~Y~^~Unknown~^~vkCreateViSurfaceNN~^~VUID-VkViSurfaceCreateInfoNN-sType-sType~^~core~^~The spec valid usage text states 'sType must be VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViSurfaceCreateInfoNN-sType-sType)~^~implicit
 VALIDATION_ERROR_14e30e01~^~N~^~Unknown~^~vkCreateViSurfaceNN~^~VUID-VkViSurfaceCreateInfoNN-window-parameter~^~core~^~The spec valid usage text states 'window must be a pointer' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViSurfaceCreateInfoNN-window-parameter)~^~implicit
-VALIDATION_ERROR_15000996~^~N~^~ViewportAndScissorBoundsChecking~^~vkCmdSetViewport~^~VUID-VkViewport-width-01227~^~core~^~The spec valid usage text states 'width must be greater than 0.0 and less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[0]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-width-01227)~^~removed from spec
-VALIDATION_ERROR_15000998~^~N~^~ViewportAndScissorBoundsChecking~^~vkCmdSetViewport~^~VUID-VkViewport-height-01228~^~core~^~The spec valid usage text states 'height must be greater than 0.0 and less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[1]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-height-01228)~^~removed from spec
-VALIDATION_ERROR_1500099a~^~N~^~ViewportBoundsCheckingWithNVHExtensionEnabled~^~vkCmdSetViewport~^~VUID-VkViewport-height-01229~^~core~^~The spec valid usage text states 'height must be greater than or equal to -VkPhysicalDeviceLimits::maxViewportDimensions[1] and less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[1]' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkViewport-height-01229)~^~removed from spec
+VALIDATION_ERROR_15000996~^~N~^~None~^~vkCmdSetViewport~^~VUID-VkViewport-width-01227~^~core~^~The spec valid usage text states 'width must be greater than 0.0 and less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[0]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-width-01227)~^~removed from spec
+VALIDATION_ERROR_15000998~^~N~^~None~^~vkCmdSetViewport~^~VUID-VkViewport-height-01228~^~core~^~The spec valid usage text states 'height must be greater than 0.0 and less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[1]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-height-01228)~^~removed from spec
+VALIDATION_ERROR_1500099a~^~N~^~None~^~vkCmdSetViewport~^~VUID-VkViewport-height-01229~^~core~^~The spec valid usage text states 'height must be greater than or equal to -VkPhysicalDeviceLimits::maxViewportDimensions[1] and less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[1]' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkViewport-height-01229)~^~removed from spec
 VALIDATION_ERROR_1500099c~^~N~^~None~^~vkCmdSetViewport~^~VUID-VkViewport-height-01230~^~core~^~The spec valid usage text states 'If the VK_AMD_negative_viewport_height extension is enabled, height can also be negative.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkViewport-height-01230)~^~removed from spec
-VALIDATION_ERROR_1500099e~^~N~^~ViewportAndScissorBoundsChecking~^~vkCmdSetViewport~^~VUID-VkViewport-x-01231~^~core~^~The spec valid usage text states 'x and y must each be between viewportBoundsRange[0] and viewportBoundsRange[1], inclusive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-x-01231)~^~removed from spec
-VALIDATION_ERROR_150009a0~^~Y~^~ViewportAndScissorBoundsChecking~^~vkCmdSetViewport~^~VUID-VkViewport-x-01232~^~core~^~The spec valid usage text states '(x + width) must be less than or equal to viewportBoundsRange[1]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-x-01232)~^~
-VALIDATION_ERROR_150009a2~^~Y~^~ViewportAndScissorBoundsChecking~^~vkCmdSetViewport~^~VUID-VkViewport-y-01233~^~core~^~The spec valid usage text states '(y + height) must be less than or equal to viewportBoundsRange[1]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-y-01233)~^~
-VALIDATION_ERROR_150009a4~^~Y~^~Unknown~^~vkCmdSetViewport~^~VUID-VkViewport-minDepth-01234~^~!(VK_EXT_depth_range_unrestricted)~^~The spec valid usage text states 'minDepth must be between 0.0 and 1.0, inclusive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-minDepth-01234)~^~
-VALIDATION_ERROR_150009a6~^~Y~^~Unknown~^~vkCmdSetViewport~^~VUID-VkViewport-maxDepth-01235~^~!(VK_EXT_depth_range_unrestricted)~^~The spec valid usage text states 'maxDepth must be between 0.0 and 1.0, inclusive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-maxDepth-01235)~^~
-VALIDATION_ERROR_15000dd4~^~Y~^~None~^~VkViewport~^~VUID-VkViewport-width-01770~^~core~^~The spec valid usage text states 'width must be greater than 0.0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-width-01770)~^~
-VALIDATION_ERROR_15000dd6~^~Y~^~None~^~VkViewport~^~VUID-VkViewport-width-01771~^~core~^~The spec valid usage text states 'width must be less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[0]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-width-01771)~^~
-VALIDATION_ERROR_15000dd8~^~Y~^~None~^~VkViewport~^~VUID-VkViewport-height-01772~^~!(VK_KHR_maintenance1,VK_AMD_negative_viewport_height)~^~The spec valid usage text states 'height must be greater than 0.0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-height-01772)~^~
-VALIDATION_ERROR_15000dda~^~Y~^~None~^~VkViewport~^~VUID-VkViewport-height-01773~^~core~^~The spec valid usage text states 'The absolute value of height must be less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[1]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-height-01773)~^~
-VALIDATION_ERROR_15000ddc~^~Y~^~None~^~VkViewport~^~VUID-VkViewport-x-01774~^~core~^~The spec valid usage text states 'x must be greater than or equal to viewportBoundsRange[0]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-x-01774)~^~
-VALIDATION_ERROR_15000dde~^~Y~^~None~^~VkViewport~^~VUID-VkViewport-y-01775~^~core~^~The spec valid usage text states 'y must be greater than or equal to viewportBoundsRange[0]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-y-01775)~^~
-VALIDATION_ERROR_15000de0~^~Y~^~None~^~VkViewport~^~VUID-VkViewport-y-01776~^~(VK_KHR_maintenance1,VK_AMD_negative_viewport_height)~^~The spec valid usage text states 'y must be less than or equal to viewportBoundsRange[1]' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkViewport-y-01776)~^~
-VALIDATION_ERROR_15000de2~^~Y~^~None~^~VkViewport~^~VUID-VkViewport-y-01777~^~(VK_KHR_maintenance1,VK_AMD_negative_viewport_height)~^~The spec valid usage text states '(y + height) must be greater than or equal to viewportBoundsRange[0]' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkViewport-y-01777)~^~
+VALIDATION_ERROR_1500099e~^~N~^~None~^~vkCmdSetViewport~^~VUID-VkViewport-x-01231~^~core~^~The spec valid usage text states 'x and y must each be between viewportBoundsRange[0] and viewportBoundsRange[1], inclusive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-x-01231)~^~removed from spec
+VALIDATION_ERROR_150009a0~^~Y~^~SetDynViewportParamTests~^~vkCmdSetViewport~^~VUID-VkViewport-x-01232~^~core~^~The spec valid usage text states '(x + width) must be less than or equal to viewportBoundsRange[1]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-x-01232)~^~
+VALIDATION_ERROR_150009a2~^~Y~^~SetDynViewportParamTests,SetDynViewportParamMaintenance1Tests~^~vkCmdSetViewport~^~VUID-VkViewport-y-01233~^~core~^~The spec valid usage text states '(y + height) must be less than or equal to viewportBoundsRange[1]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-y-01233)~^~
+VALIDATION_ERROR_150009a4~^~Y~^~SetDynViewportParamTests~^~vkCmdSetViewport~^~VUID-VkViewport-minDepth-01234~^~!(VK_EXT_depth_range_unrestricted)~^~The spec valid usage text states 'minDepth must be between 0.0 and 1.0, inclusive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-minDepth-01234)~^~
+VALIDATION_ERROR_150009a6~^~Y~^~SetDynViewportParamTests~^~vkCmdSetViewport~^~VUID-VkViewport-maxDepth-01235~^~!(VK_EXT_depth_range_unrestricted)~^~The spec valid usage text states 'maxDepth must be between 0.0 and 1.0, inclusive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-maxDepth-01235)~^~
+VALIDATION_ERROR_15000dd4~^~Y~^~SetDynViewportParamTests~^~VkViewport~^~VUID-VkViewport-width-01770~^~core~^~The spec valid usage text states 'width must be greater than 0.0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-width-01770)~^~
+VALIDATION_ERROR_15000dd6~^~Y~^~SetDynViewportParamTests~^~VkViewport~^~VUID-VkViewport-width-01771~^~core~^~The spec valid usage text states 'width must be less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[0]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-width-01771)~^~
+VALIDATION_ERROR_15000dd8~^~Y~^~SetDynViewportParamTests~^~VkViewport~^~VUID-VkViewport-height-01772~^~!(VK_KHR_maintenance1,VK_AMD_negative_viewport_height)~^~The spec valid usage text states 'height must be greater than 0.0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-height-01772)~^~
+VALIDATION_ERROR_15000dda~^~Y~^~SetDynViewportParamTests,SetDynViewportParamMaintenance1Tests~^~VkViewport~^~VUID-VkViewport-height-01773~^~core~^~The spec valid usage text states 'The absolute value of height must be less than or equal to VkPhysicalDeviceLimits::maxViewportDimensions[1]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-height-01773)~^~
+VALIDATION_ERROR_15000ddc~^~Y~^~SetDynViewportParamTests~^~VkViewport~^~VUID-VkViewport-x-01774~^~core~^~The spec valid usage text states 'x must be greater than or equal to viewportBoundsRange[0]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-x-01774)~^~
+VALIDATION_ERROR_15000dde~^~Y~^~SetDynViewportParamTests,SetDynViewportParamMaintenance1Tests~^~VkViewport~^~VUID-VkViewport-y-01775~^~core~^~The spec valid usage text states 'y must be greater than or equal to viewportBoundsRange[0]' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewport-y-01775)~^~
+VALIDATION_ERROR_15000de0~^~Y~^~SetDynViewportParamMaintenance1Tests~^~VkViewport~^~VUID-VkViewport-y-01776~^~(VK_KHR_maintenance1,VK_AMD_negative_viewport_height)~^~The spec valid usage text states 'y must be less than or equal to viewportBoundsRange[1]' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkViewport-y-01776)~^~
+VALIDATION_ERROR_15000de2~^~Y~^~SetDynViewportParamMaintenance1Tests~^~VkViewport~^~VUID-VkViewport-y-01777~^~(VK_KHR_maintenance1,VK_AMD_negative_viewport_height)~^~The spec valid usage text states '(y + height) must be greater than or equal to viewportBoundsRange[0]' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkViewport-y-01777)~^~
 VALIDATION_ERROR_15230c01~^~N~^~Unknown~^~vkCmdBindVertexBuffers~^~VUID-VkViewportSwizzleNV-w-parameter~^~core~^~The spec valid usage text states 'w must be a valid VkViewportCoordinateSwizzleNV value' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewportSwizzleNV-w-parameter)~^~implicit
 VALIDATION_ERROR_15231001~^~N~^~Unknown~^~vkCmdBindVertexBuffers~^~VUID-VkViewportSwizzleNV-x-parameter~^~core~^~The spec valid usage text states 'x must be a valid VkViewportCoordinateSwizzleNV value' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewportSwizzleNV-x-parameter)~^~implicit
 VALIDATION_ERROR_15231201~^~N~^~Unknown~^~vkCmdBindVertexBuffers~^~VUID-VkViewportSwizzleNV-y-parameter~^~core~^~The spec valid usage text states 'y must be a valid VkViewportCoordinateSwizzleNV value' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkViewportSwizzleNV-y-parameter)~^~implicit
@@ -2516,9 +2516,9 @@ VALIDATION_ERROR_1d80049e~^~N~^~Unknown~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor
 VALIDATION_ERROR_1d8004a0~^~N~^~Unknown~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-firstScissor-00592~^~core~^~The spec valid usage text states 'The sum of firstScissor and scissorCount must be between 1 and VkPhysicalDeviceLimits::maxViewports, inclusive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-firstScissor-00592)~^~
 VALIDATION_ERROR_1d8004a2~^~N~^~Unknown~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-firstScissor-00593~^~core~^~The spec valid usage text states 'If the multiple viewports feature is not enabled, firstScissor must be 0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-firstScissor-00593)~^~
 VALIDATION_ERROR_1d8004a4~^~N~^~Unknown~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-scissorCount-00594~^~core~^~The spec valid usage text states 'If the multiple viewports feature is not enabled, scissorCount must be 1' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-scissorCount-00594)~^~
-VALIDATION_ERROR_1d8004a6~^~Y~^~ViewportAndScissorBoundsChecking~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-x-00595~^~core~^~The spec valid usage text states 'The x and y members of offset must be greater than or equal to 0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-x-00595)~^~
-VALIDATION_ERROR_1d8004a8~^~Y~^~ViewportAndScissorBoundsChecking~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-offset-00596~^~core~^~The spec valid usage text states 'Evaluation of (offset.x + extent.width) must not cause a signed integer addition overflow' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-offset-00596)~^~
-VALIDATION_ERROR_1d8004aa~^~Y~^~ViewportAndScissorBoundsChecking~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-offset-00597~^~core~^~The spec valid usage text states 'Evaluation of (offset.y + extent.height) must not cause a signed integer addition overflow' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-offset-00597)~^~
+VALIDATION_ERROR_1d8004a6~^~Y~^~ScissorBoundsChecking~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-x-00595~^~core~^~The spec valid usage text states 'The x and y members of offset must be greater than or equal to 0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-x-00595)~^~
+VALIDATION_ERROR_1d8004a8~^~Y~^~ScissorBoundsChecking~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-offset-00596~^~core~^~The spec valid usage text states 'Evaluation of (offset.x + extent.width) must not cause a signed integer addition overflow' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-offset-00596)~^~
+VALIDATION_ERROR_1d8004aa~^~Y~^~ScissorBoundsChecking~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-offset-00597~^~core~^~The spec valid usage text states 'Evaluation of (offset.y + extent.height) must not cause a signed integer addition overflow' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-offset-00597)~^~
 VALIDATION_ERROR_1d802401~^~Y~^~None~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-commandBuffer-parameter~^~core~^~The spec valid usage text states 'commandBuffer must be a valid VkCommandBuffer handle' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-commandBuffer-parameter)~^~implicit
 VALIDATION_ERROR_1d802413~^~Y~^~None~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-commandBuffer-recording~^~core~^~The spec valid usage text states 'commandBuffer must be in the recording state' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-commandBuffer-recording)~^~implicit
 VALIDATION_ERROR_1d802415~^~Y~^~Unknown~^~vkCmdSetScissor~^~VUID-vkCmdSetScissor-commandBuffer-cmdpool~^~core~^~The spec valid usage text states 'The VkCommandPool that commandBuffer was allocated from must support graphics operations' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkCmdSetScissor-commandBuffer-cmdpool)~^~implicit
index 4f2178f..295bbae 100644 (file)
@@ -48,6 +48,7 @@
 
 #include <algorithm>
 #include <functional>
+#include <limits>
 #include <memory>
 #include <unordered_set>
 
@@ -94,6 +95,18 @@ size_t size(ElementT (&)[array_size]) {
     return array_size;
 }
 
+template <typename F>
+F PositiveDir() {
+    using Lim = std::numeric_limits<F>;
+    return Lim::has_infinity ? Lim::infinity() : Lim::max();
+}
+
+template <typename F>
+F NegativeDir() {
+    using Lim = std::numeric_limits<F>;
+    return Lim::has_infinity ? -Lim::infinity() : Lim::lowest();
+}
+
 // Format search helper
 VkFormat FindSupportedDepthStencilFormat(VkPhysicalDevice phy) {
     VkFormat ds_formats[] = {VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
@@ -20887,6 +20900,7 @@ TEST_F(VkLayerTest, SetDynViewportParamTests) {
 
     m_commandBuffer->begin();
 
+    // array tests
     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_1e000990);
     vkCmdSetViewport(m_commandBuffer->handle(), 1, 1, viewports);
     m_errorMonitor->VerifyFound();
@@ -20912,6 +20926,127 @@ TEST_F(VkLayerTest, SetDynViewportParamTests) {
     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_1e03fa01);
     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, nullptr);
     m_errorMonitor->VerifyFound();
+
+    // core viewport tests
+    using std::vector;
+    struct TestCase {
+        VkViewport vp;
+        vector<UNIQUE_VALIDATION_ERROR_CODE> vuids;
+    };
+
+    const auto one_past_max_w =
+        nextafterf(static_cast<float>(m_device->props.limits.maxViewportDimensions[0]), PositiveDir<float>());
+    const auto one_past_max_h =
+        nextafterf(static_cast<float>(m_device->props.limits.maxViewportDimensions[1]), PositiveDir<float>());
+
+    const auto min_bound = m_device->props.limits.viewportBoundsRange[0];
+    const auto max_bound = m_device->props.limits.viewportBoundsRange[1];
+    const auto one_before_min_bounds = nextafterf(min_bound, NegativeDir<float>());
+    const auto one_past_max_bounds = nextafterf(max_bound, PositiveDir<float>());
+
+    const auto below_zero = nextafterf(0.0, -1.0);
+    const auto past_one = nextafterf(1.0, 2.0);
+
+    const vector<TestCase> test_cases = {
+        {{0.0, 0.0, 0.0, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_15000dd4}},
+        {{0.0, 0.0, one_past_max_w, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_15000dd6}},
+        {{0.0, 0.0, NAN, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_15000dd4}},
+        {{0.0, 0.0, 64.0, 0.0, 0.0, 1.0}, {VALIDATION_ERROR_15000dd8}},
+        {{0.0, 0.0, 64.0, one_past_max_h, 0.0, 1.0}, {VALIDATION_ERROR_15000dda}},
+        {{0.0, 0.0, 64.0, NAN, 0.0, 1.0}, {VALIDATION_ERROR_15000dd8}},
+        {{one_before_min_bounds, 0.0, 64.0, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_15000ddc}},
+        {{one_past_max_bounds, 0.0, 64.0, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_150009a0}},
+        {{NAN, 0.0, 64.0, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_15000ddc}},
+        {{0.0, one_before_min_bounds, 64.0, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_15000dde}},
+        {{0.0, one_past_max_bounds, 64.0, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_150009a2}},
+        {{0.0, NAN, 64.0, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_15000dde}},
+        {{max_bound, 0.0, 1.0, 64.0, 0.0, 1.0}, {VALIDATION_ERROR_150009a0}},
+        {{0.0, max_bound, 64.0, 1.0, 0.0, 1.0}, {VALIDATION_ERROR_150009a2}},
+        {{0.0, 0.0, 64.0, 64.0, below_zero, 1.0}, {VALIDATION_ERROR_150009a4}},
+        {{0.0, 0.0, 64.0, 64.0, past_one, 1.0}, {VALIDATION_ERROR_150009a4}},
+        {{0.0, 0.0, 64.0, 64.0, NAN, 1.0}, {VALIDATION_ERROR_150009a4}},
+        {{0.0, 0.0, 64.0, 64.0, 0.0, below_zero}, {VALIDATION_ERROR_150009a6}},
+        {{0.0, 0.0, 64.0, 64.0, 0.0, past_one}, {VALIDATION_ERROR_150009a6}},
+        {{0.0, 0.0, 64.0, 64.0, 0.0, NAN}, {VALIDATION_ERROR_150009a6}},
+    };
+
+    for (const auto &test_case : test_cases) {
+        for (const auto vuid : test_case.vuids) m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid);
+        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &test_case.vp);
+        m_errorMonitor->VerifyFound();
+    }
+}
+
+void NegHeightViewportTests(VkDeviceObj *m_device, VkCommandBufferObj *m_commandBuffer, ErrorMonitor *m_errorMonitor) {
+    const auto &limits = m_device->props.limits;
+
+    m_commandBuffer->begin();
+
+    using std::vector;
+    struct TestCase {
+        VkViewport vp;
+        vector<UNIQUE_VALIDATION_ERROR_CODE> vuids;
+    };
+
+    const auto one_before_min_h = nextafterf(-static_cast<float>(limits.maxViewportDimensions[1]), NegativeDir<float>());
+    const auto one_past_max_h = nextafterf(static_cast<float>(limits.maxViewportDimensions[1]), PositiveDir<float>());
+
+    const auto min_bound = limits.viewportBoundsRange[0];
+    const auto max_bound = limits.viewportBoundsRange[1];
+    const auto one_before_min_bound = nextafterf(min_bound, NegativeDir<float>());
+    const auto one_past_max_bound = nextafterf(max_bound, PositiveDir<float>());
+
+    const vector<TestCase> test_cases = {{{0.0, 0.0, 64.0, one_before_min_h, 0.0, 1.0}, {VALIDATION_ERROR_15000dda}},
+                                         {{0.0, 0.0, 64.0, one_past_max_h, 0.0, 1.0}, {VALIDATION_ERROR_15000dda}},
+                                         {{0.0, 0.0, 64.0, NAN, 0.0, 1.0}, {VALIDATION_ERROR_15000dda}},
+                                         {{0.0, one_before_min_bound, 64.0, 1.0, 0.0, 1.0}, {VALIDATION_ERROR_15000dde}},
+                                         {{0.0, one_past_max_bound, 64.0, -1.0, 0.0, 1.0}, {VALIDATION_ERROR_15000de0}},
+                                         {{0.0, min_bound, 64.0, -1.0, 0.0, 1.0}, {VALIDATION_ERROR_15000de2}},
+                                         {{0.0, max_bound, 64.0, 1.0, 0.0, 1.0}, {VALIDATION_ERROR_150009a2}}};
+
+    for (const auto &test_case : test_cases) {
+        for (const auto vuid : test_case.vuids) {
+            if (vuid == VALIDATION_ERROR_UNDEFINED)
+                m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+                                                     "is less than VkPhysicalDeviceLimits::viewportBoundsRange[0]");
+            else
+                m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, vuid);
+        }
+        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &test_case.vp);
+        m_errorMonitor->VerifyFound();
+    }
+}
+
+TEST_F(VkLayerTest, SetDynViewportParamMaintenance1Tests) {
+    TEST_DESCRIPTION("Verify errors are detected on misuse of SetViewport with a negative viewport extension enabled.");
+
+    ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
+
+    if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) {
+        m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
+    } else {
+        printf("             VK_KHR_maintenance1 extension not supported -- skipping test\n");
+        return;
+    }
+    ASSERT_NO_FATAL_FAILURE(InitState());
+
+    NegHeightViewportTests(m_device, m_commandBuffer, m_errorMonitor);
+}
+
+TEST_F(VkLayerTest, SetDynViewportParamAmdNegHeightTests) {
+    TEST_DESCRIPTION("Verify errors are detected on misuse of SetViewport with AMD negative viewport extension enabled.");
+
+    ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
+
+    if (DeviceExtensionSupported(gpu(), nullptr, VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME)) {
+        m_device_extension_names.push_back(VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME);
+    } else {
+        printf("             VK_AMD_negative_viewport_height extension not supported -- skipping test\n");
+        return;
+    }
+    ASSERT_NO_FATAL_FAILURE(InitState());
+
+    NegHeightViewportTests(m_device, m_commandBuffer, m_errorMonitor);
 }
 
 TEST_F(VkLayerTest, SetDynViewportParamMultiviewportTests) {
@@ -21762,81 +21897,13 @@ TEST_F(VkLayerTest, PushDescriptorSetCmdPushBadArgs) {
     m_errorMonitor->VerifyFound();
 }
 
-TEST_F(VkLayerTest, ViewportBoundsCheckingWithNVHExtensionEnabled) {
-    TEST_DESCRIPTION("Verify errors are detected on misuse of SetViewport with a negative viewport extension enabled.");
-
-    ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
-
-    if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) {
-        m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
-    } else {
-        printf("             Maintenance1 Extension not supported, skipping tests\n");
-        return;
-    }
-    ASSERT_NO_FATAL_FAILURE(InitState());
-    const VkPhysicalDeviceLimits &limits = m_device->props.limits;
-
-    m_commandBuffer->begin();
-    {
-        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_1500099a);
-        VkViewport viewport = {0, 0, 16, -(static_cast<float>(limits.maxViewportDimensions[1] + 1)), 0, 1};
-        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
-        m_errorMonitor->VerifyFound();
-    }
-    m_commandBuffer->end();
-}
-
-TEST_F(VkLayerTest, ViewportAndScissorBoundsChecking) {
-    TEST_DESCRIPTION("Verify errors are detected on misuse of SetViewport and SetScissor.");
+TEST_F(VkLayerTest, ScissorBoundsChecking) {
+    TEST_DESCRIPTION("Verify errors are detected on misuse of SetScissor.");
 
     ASSERT_NO_FATAL_FAILURE(Init());
 
     m_commandBuffer->begin();
 
-    const VkPhysicalDeviceLimits &limits = m_device->props.limits;
-
-    {
-        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_15000996);
-        VkViewport viewport = {0, 0, static_cast<float>(limits.maxViewportDimensions[0] + 1), 16, 0, 1};
-        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
-        m_errorMonitor->VerifyFound();
-    }
-
-    {
-        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_15000998);
-        VkViewport viewport = {0, 0, 16, static_cast<float>(limits.maxViewportDimensions[1] + 1), 0, 1};
-        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
-        m_errorMonitor->VerifyFound();
-    }
-
-    {
-        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_1500099e);
-        VkViewport viewport = {limits.viewportBoundsRange[0] - 1, 0, 16, 16, 0, 1};
-        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
-        m_errorMonitor->VerifyFound();
-    }
-
-    {
-        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_1500099e);
-        VkViewport viewport = {0, limits.viewportBoundsRange[0] - 1, 16, 16, 0, 1};
-        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
-        m_errorMonitor->VerifyFound();
-    }
-
-    {
-        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_150009a0);
-        VkViewport viewport = {limits.viewportBoundsRange[1], 0, 16, 16, 0, 1};
-        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
-        m_errorMonitor->VerifyFound();
-    }
-
-    {
-        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_150009a2);
-        VkViewport viewport = {0, limits.viewportBoundsRange[1], 16, 16, 0, 1};
-        vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
-        m_errorMonitor->VerifyFound();
-    }
-
     {
         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_1d8004a6);
         VkRect2D scissor = {{-1, 0}, {16, 16}};