tests: GH431 PR 510 Apply suggested changes

- Convert error to warning for overlapping ranges
- Consider overlapping ranges in range checks
- User a reference to avoid a copy
- Many more additional tests

Change-Id: I18ad43b98684f16a978461a1a089ebff5437a563
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 9c5b149..de87f46 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -3691,7 +3691,6 @@
 
     VkPipelineLayout pipeline_layout;
     VkPushConstantRange pc_range = {};
-    pc_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
     pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
     pipeline_layout_ci.pushConstantRangeCount = 1;
@@ -3701,39 +3700,47 @@
     // Check for invalid push constant ranges in pipeline layouts.
     //
     struct PipelineLayoutTestCase {
-        uint32_t const offset;
-        uint32_t const size;
+        VkPushConstantRange const range;
         char const *msg;
     };
 
-    const uint32_t tooBig = m_device->props.limits.maxPushConstantsSize + 0x4;
-    const std::array<PipelineLayoutTestCase, 10> rangeTests = {{
-        {0, 0, "vkCreatePipelineLayout() call has push constants index 0 with "
-               "size 0."},
-        {0, 1, "vkCreatePipelineLayout() call has push constants index 0 with "
-               "size 1."},
-        {1, 1, "vkCreatePipelineLayout() call has push constants index 0 with "
-               "size 1."},
-        {1, 0, "vkCreatePipelineLayout() call has push constants index 0 with "
-               "size 0."},
-        {1, 4, "vkCreatePipelineLayout() call has push constants index 0 with "
-               "offset 1. Offset must"},
-        {0, tooBig, "vkCreatePipelineLayout() call has push constants index 0 "
-                    "with offset "},
-        {tooBig, tooBig, "vkCreatePipelineLayout() call has push constants "
-                         "index 0 with offset "},
-        {tooBig, 0, "vkCreatePipelineLayout() call has push constants index 0 "
-                    "with offset "},
-        {0xFFFFFFF0, 0x00000020, "vkCreatePipelineLayout() call has push "
-                                 "constants index 0 with offset "},
-        {0x00000020, 0xFFFFFFF0, "vkCreatePipelineLayout() call has push "
-                                 "constants index 0 with offset "},
+    const uint32_t too_big = m_device->props.limits.maxPushConstantsSize + 0x4;
+    const std::array<PipelineLayoutTestCase, 10> range_tests = {{
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 0},
+         "vkCreatePipelineLayout() call has push constants index 0 with "
+         "size 0."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 1},
+         "vkCreatePipelineLayout() call has push constants index 0 with "
+         "size 1."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 1, 1},
+         "vkCreatePipelineLayout() call has push constants index 0 with "
+         "size 1."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 1, 0},
+         "vkCreatePipelineLayout() call has push constants index 0 with "
+         "size 0."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 1, 4},
+         "vkCreatePipelineLayout() call has push constants index 0 with "
+         "offset 1. Offset must"},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, too_big},
+         "vkCreatePipelineLayout() call has push constants index 0 "
+         "with offset "},
+        {{VK_SHADER_STAGE_VERTEX_BIT, too_big, too_big},
+         "vkCreatePipelineLayout() call has push constants "
+         "index 0 with offset "},
+        {{VK_SHADER_STAGE_VERTEX_BIT, too_big, 0},
+         "vkCreatePipelineLayout() call has push constants index 0 "
+         "with offset "},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0xFFFFFFF0, 0x00000020},
+         "vkCreatePipelineLayout() call has push "
+         "constants index 0 with offset "},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0x00000020, 0xFFFFFFF0},
+         "vkCreatePipelineLayout() call has push "
+         "constants index 0 with offset "},
     }};
 
     // Check for invalid offset and size
-    for (const auto &iter : rangeTests) {
-        pc_range.offset = iter.offset;
-        pc_range.size = iter.size;
+    for (const auto &iter : range_tests) {
+        pc_range = iter.range;
         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
                                              iter.msg);
         err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci,
@@ -3759,13 +3766,13 @@
     }
 
     // Check for overlapping ranges
-    const uint32_t rangesPerTest = 5;
+    const uint32_t ranges_per_test = 5;
     struct OverlappingRangeTestCase {
-        VkPushConstantRange ranges[rangesPerTest];
+        VkPushConstantRange const ranges[ranges_per_test];
         char const *msg;
     };
 
-    const std::array<OverlappingRangeTestCase, 5> orTests = {
+    const std::array<OverlappingRangeTestCase, 5> overlapping_range_tests = {
         {{{{VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
            {VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
            {VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
@@ -3813,11 +3820,11 @@
              "overlapping "
              "ranges: 0:[16, 20), 2:[4, 100)",
          }}};
-    pipeline_layout_ci.pushConstantRangeCount = rangesPerTest;
 
-    for (const auto &iter : orTests) {
+    for (const auto &iter : overlapping_range_tests) {
         pipeline_layout_ci.pPushConstantRanges = iter.ranges;
-        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+        pipeline_layout_ci.pushConstantRangeCount = ranges_per_test;
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT,
                                              iter.msg);
         err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci,
                                      NULL, &pipeline_layout);
@@ -3828,20 +3835,20 @@
     }
 
     // Run some positive tests to make sure overlap checking in the layer is OK
-    const std::array<OverlappingRangeTestCase, 2> orPosTests = {
-        {{{{VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
-           {VK_SHADER_STAGE_VERTEX_BIT, 4, 4},
-           {VK_SHADER_STAGE_VERTEX_BIT, 8, 4},
-           {VK_SHADER_STAGE_VERTEX_BIT, 12, 4},
-           {VK_SHADER_STAGE_VERTEX_BIT, 16, 4}},
-          ""},
-         {{{VK_SHADER_STAGE_VERTEX_BIT, 92, 24},
-           {VK_SHADER_STAGE_VERTEX_BIT, 80, 4},
-           {VK_SHADER_STAGE_VERTEX_BIT, 64, 8},
-           {VK_SHADER_STAGE_VERTEX_BIT, 4, 16},
-           {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}},
-          ""}}};
-    for (const auto &iter : orPosTests) {
+    const std::array<OverlappingRangeTestCase, 2> overlapping_range_tests_pos =
+        {{{{{VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
+            {VK_SHADER_STAGE_VERTEX_BIT, 4, 4},
+            {VK_SHADER_STAGE_VERTEX_BIT, 8, 4},
+            {VK_SHADER_STAGE_VERTEX_BIT, 12, 4},
+            {VK_SHADER_STAGE_VERTEX_BIT, 16, 4}},
+           ""},
+          {{{VK_SHADER_STAGE_VERTEX_BIT, 92, 24},
+            {VK_SHADER_STAGE_VERTEX_BIT, 80, 4},
+            {VK_SHADER_STAGE_VERTEX_BIT, 64, 8},
+            {VK_SHADER_STAGE_VERTEX_BIT, 4, 16},
+            {VK_SHADER_STAGE_VERTEX_BIT, 0, 4}},
+           ""}}};
+    for (const auto &iter : overlapping_range_tests_pos) {
         pipeline_layout_ci.pPushConstantRanges = iter.ranges;
         m_errorMonitor->ExpectSuccess();
         err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci,
@@ -3855,54 +3862,74 @@
     //
     // CmdPushConstants tests
     //
+    const uint8_t dummy_values[100] = {};
 
     // Check for invalid offset and size and if range is within layout range(s)
-    std::array<PipelineLayoutTestCase, 13> cmdRangeTests = {{
-        {0, 0, "vkCmdPushConstants() call has push constants with size 0. Size "
-               "must be greater than zero and a multiple of 4."},
-        {0, 1, "vkCmdPushConstants() call has push constants with size 1. Size "
-               "must be greater than zero and a multiple of 4."},
-        {1, 1, "vkCmdPushConstants() call has push constants with size 1. Size "
-               "must be greater than zero and a multiple of 4."},
-        {1, 0, "vkCmdPushConstants() call has push constants with offset 1. "
-               "Offset must be a multiple of 4."},
-        {1, 4, "vkCmdPushConstants() call has push constants with offset 1. "
-               "Offset must be a multiple of 4."},
-        {0, 20, "vkCmdPushConstants() Push constant range [0, 20) not within "
-                "any of the ranges in pipeline layout"},
-        {60, 8, "vkCmdPushConstants() Push constant range [60, 68) not within "
-                "any of the ranges in pipeline layout"},
-        {76, 8, "vkCmdPushConstants() Push constant range [76, 84) not within "
-                "any of the ranges in pipeline layout"},
-        {0, tooBig,
+    const std::array<PipelineLayoutTestCase, 16> cmd_range_tests = {{
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 0},
+         "vkCmdPushConstants() call has push constants with size 0. Size "
+         "must be greater than zero and a multiple of 4."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 1},
+         "vkCmdPushConstants() call has push constants with size 1. Size "
+         "must be greater than zero and a multiple of 4."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 1, 1},
+         "vkCmdPushConstants() call has push constants with size 1. Size "
+         "must be greater than zero and a multiple of 4."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 1, 0},
+         "vkCmdPushConstants() call has push constants with offset 1. "
+         "Offset must be a multiple of 4."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 1, 4},
+         "vkCmdPushConstants() call has push constants with offset 1. "
+         "Offset must be a multiple of 4."},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 20},
+         "vkCmdPushConstants() Push constant range [0, 20) with stageFlags = "
+         "0x1 not within flag-matching ranges in pipeline layout"},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 60, 8},
+         "vkCmdPushConstants() Push constant range [60, 68) with stageFlags = "
+         "0x1 not within flag-matching ranges in pipeline layout"},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 76, 8},
+         "vkCmdPushConstants() Push constant range [76, 84) with stageFlags = "
+         "0x1 not within flag-matching ranges in pipeline layout"},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 80},
+         "vkCmdPushConstants() Push constant range [0, 80) with stageFlags = "
+         "0x1 not within flag-matching ranges in pipeline layout"},
+        {{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0, 4},
+         "vkCmdPushConstants() stageFlags = 0x2 do not match the stageFlags in "
+         "any of the ranges in pipeline layout"},
+        {{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
+          0, 16},
+         "vkCmdPushConstants() stageFlags = 0x3 do not match the stageFlags in "
+         "any of the ranges in pipeline layout"},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, too_big},
          "vkCmdPushConstants() call has push constants with offset "},
-        {tooBig, tooBig,
+        {{VK_SHADER_STAGE_VERTEX_BIT, too_big, too_big},
          "vkCmdPushConstants() call has push constants with offset "},
-        {tooBig, 0,
+        {{VK_SHADER_STAGE_VERTEX_BIT, too_big, 0},
          "vkCmdPushConstants() call has push constants with offset "},
-        {0xFFFFFFF0, 0x00000020,
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0xFFFFFFF0, 0x00000020},
          "vkCmdPushConstants() call has push constants with offset "},
-        {0x00000020, 0xFFFFFFF0,
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0x00000020, 0xFFFFFFF0},
          "vkCmdPushConstants() call has push constants with offset "},
     }};
 
     // Two ranges for testing robustness
-    VkPushConstantRange pc_range2[] = {
-        {VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
+    const VkPushConstantRange pc_range2[] = {
         {VK_SHADER_STAGE_VERTEX_BIT, 64, 16},
+        {VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
     };
-    pipeline_layout_ci.pushConstantRangeCount = 2;
+    pipeline_layout_ci.pushConstantRangeCount =
+        sizeof(pc_range2) / sizeof(VkPushConstantRange);
     pipeline_layout_ci.pPushConstantRanges = pc_range2;
     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL,
                                  &pipeline_layout);
     ASSERT_VK_SUCCESS(err);
     BeginCommandBuffer();
-    for (const auto &iter : cmdRangeTests) {
+    for (const auto &iter : cmd_range_tests) {
         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
                                              iter.msg);
         vkCmdPushConstants(m_commandBuffer->GetBufferHandle(), pipeline_layout,
-                           VK_SHADER_STAGE_VERTEX_BIT, iter.offset, iter.size,
-                           NULL);
+                           iter.range.stageFlags, iter.range.offset,
+                           iter.range.size, dummy_values);
         m_errorMonitor->VerifyFound();
     }
 
@@ -3911,9 +3938,85 @@
         VK_DEBUG_REPORT_ERROR_BIT_EXT,
         "vkCmdPushConstants() call has no stageFlags set.");
     vkCmdPushConstants(m_commandBuffer->GetBufferHandle(), pipeline_layout, 0,
-                       0, 16, NULL);
+                       0, 16, dummy_values);
     m_errorMonitor->VerifyFound();
+    EndCommandBuffer();
+    vkResetCommandBuffer(m_commandBuffer->GetBufferHandle(), 0);
+    vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
 
+    // overlapping range tests with cmd
+    const std::array<PipelineLayoutTestCase, 3> cmd_overlap_tests = {{
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 20},
+         "vkCmdPushConstants() Push constant range [0, 20) with stageFlags = "
+         "0x1 not within flag-matching ranges in pipeline layout"},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 16, 4},
+         "vkCmdPushConstants() Push constant range [16, 20) with stageFlags = "
+         "0x1 not within flag-matching ranges in pipeline layout"},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 40, 16},
+         "vkCmdPushConstants() Push constant range [40, 56) with stageFlags = "
+         "0x1 not within flag-matching ranges in pipeline layout"},
+    }};
+    const VkPushConstantRange pc_range3[] = {
+        {VK_SHADER_STAGE_VERTEX_BIT, 20, 16},
+        {VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
+        {VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
+        {VK_SHADER_STAGE_VERTEX_BIT, 44, 8},
+        {VK_SHADER_STAGE_VERTEX_BIT, 80, 12},
+        {VK_SHADER_STAGE_VERTEX_BIT, 36, 8},
+        {VK_SHADER_STAGE_VERTEX_BIT, 56, 28},
+    };
+    pipeline_layout_ci.pushConstantRangeCount =
+        sizeof(pc_range3) / sizeof(VkPushConstantRange);
+    pipeline_layout_ci.pPushConstantRanges = pc_range3;
+    err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL,
+                                 &pipeline_layout);
+    ASSERT_VK_SUCCESS(err);
+    BeginCommandBuffer();
+    for (const auto &iter : cmd_overlap_tests) {
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+                                             iter.msg);
+        vkCmdPushConstants(m_commandBuffer->GetBufferHandle(), pipeline_layout,
+                           iter.range.stageFlags, iter.range.offset,
+                           iter.range.size, dummy_values);
+        m_errorMonitor->VerifyFound();
+    }
+    EndCommandBuffer();
+    vkResetCommandBuffer(m_commandBuffer->GetBufferHandle(), 0);
+    vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
+
+    // positive overlapping range tests with cmd
+    const std::array<PipelineLayoutTestCase, 4> cmd_overlap_tests_pos = {{
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, ""},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, ""},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 20, 12}, ""},
+        {{VK_SHADER_STAGE_VERTEX_BIT, 56, 36}, ""},
+    }};
+    const VkPushConstantRange pc_range4[] = {
+        {VK_SHADER_STAGE_VERTEX_BIT, 0, 64},
+        {VK_SHADER_STAGE_VERTEX_BIT, 20, 16},
+        {VK_SHADER_STAGE_VERTEX_BIT, 0, 16},
+        {VK_SHADER_STAGE_VERTEX_BIT, 0, 4},
+        {VK_SHADER_STAGE_VERTEX_BIT, 44, 8},
+        {VK_SHADER_STAGE_VERTEX_BIT, 80, 12},
+        {VK_SHADER_STAGE_VERTEX_BIT, 36, 8},
+        {VK_SHADER_STAGE_VERTEX_BIT, 56, 28},
+    };
+    pipeline_layout_ci.pushConstantRangeCount =
+        sizeof(pc_range4) / sizeof(VkPushConstantRange);
+    pipeline_layout_ci.pPushConstantRanges = pc_range4;
+    err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL,
+                                 &pipeline_layout);
+    ASSERT_VK_SUCCESS(err);
+    BeginCommandBuffer();
+    for (const auto &iter : cmd_overlap_tests_pos) {
+        m_errorMonitor->ExpectSuccess();
+        vkCmdPushConstants(m_commandBuffer->GetBufferHandle(), pipeline_layout,
+                           iter.range.stageFlags, iter.range.offset,
+                           iter.range.size, dummy_values);
+        m_errorMonitor->VerifyNotFound();
+    }
+    EndCommandBuffer();
+    vkResetCommandBuffer(m_commandBuffer->GetBufferHandle(), 0);
     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
 }