tests: Add tests for VK_EXT_line_rasterization
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 19572ff..f87ffa4 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -796,6 +796,22 @@
             pipelineobj.SetInputAssembly(&ia_state);
             break;
         }
+        case BsoFailLineStipple: {
+            pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
+            VkPipelineInputAssemblyStateCreateInfo ia_state = {};
+            ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+            ia_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
+            pipelineobj.SetInputAssembly(&ia_state);
+
+            VkPipelineRasterizationLineStateCreateInfoEXT line_state = {};
+            line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
+            line_state.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
+            line_state.stippledLineEnable = VK_TRUE;
+            line_state.lineStippleFactor = 0;
+            line_state.lineStipplePattern = 0;
+            pipelineobj.SetLineState(&line_state);
+            break;
+        }
         case BsoFailDepthBias: {
             pipelineobj.MakeDynamic(VK_DYNAMIC_STATE_DEPTH_BIAS);
             VkPipelineRasterizationStateCreateInfo rs_state = {};
@@ -1460,7 +1476,7 @@
 
 void CreatePipelineHelper::InitRasterizationInfo() {
     rs_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
-    rs_state_ci_.pNext = nullptr;
+    rs_state_ci_.pNext = &line_state_ci_;
     rs_state_ci_.flags = 0;
     rs_state_ci_.depthClampEnable = VK_FALSE;
     rs_state_ci_.rasterizerDiscardEnable = VK_FALSE;
@@ -1471,6 +1487,15 @@
     rs_state_ci_.lineWidth = 1.0F;
 }
 
+void CreatePipelineHelper::InitLineRasterizationInfo() {
+    line_state_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
+    line_state_ci_.pNext = nullptr;
+    line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
+    line_state_ci_.stippledLineEnable = VK_FALSE;
+    line_state_ci_.lineStippleFactor = 0;
+    line_state_ci_.lineStipplePattern = 0;
+}
+
 void CreatePipelineHelper::InitBlendStateInfo() {
     cb_ci_.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
     cb_ci_.logicOpEnable = VK_FALSE;
@@ -1531,6 +1556,7 @@
     InitDynamicStateInfo();
     InitShaderInfo();
     InitRasterizationInfo();
+    InitLineRasterizationInfo();
     InitBlendStateInfo();
     InitGraphicsPipelineInfo();
     InitPipelineCacheInfo();
diff --git a/tests/layer_validation_tests.h b/tests/layer_validation_tests.h
index 195bfff..5ef9803 100644
--- a/tests/layer_validation_tests.h
+++ b/tests/layer_validation_tests.h
@@ -80,7 +80,8 @@
     BsoFailIndexBufferBadSize,
     BsoFailIndexBufferBadOffset,
     BsoFailIndexBufferBadMapSize,
-    BsoFailIndexBufferBadMapOffset
+    BsoFailIndexBufferBadMapOffset,
+    BsoFailLineStipple,
 };
 
 static const char bindStateMinimalShaderText[] = "#version 450\nvoid main() {}\n";
@@ -437,6 +438,7 @@
     VkPipelineLayoutObj pipeline_layout_;
     VkPipelineDynamicStateCreateInfo dyn_state_ci_ = {};
     VkPipelineRasterizationStateCreateInfo rs_state_ci_ = {};
+    VkPipelineRasterizationLineStateCreateInfoEXT line_state_ci_ = {};
     VkPipelineColorBlendAttachmentState cb_attachments_ = {};
     VkPipelineColorBlendStateCreateInfo cb_ci_ = {};
     VkGraphicsPipelineCreateInfo gp_ci_ = {};
@@ -457,6 +459,7 @@
     void InitDynamicStateInfo();
     void InitShaderInfo();
     void InitRasterizationInfo();
+    void InitLineRasterizationInfo();
     void InitBlendStateInfo();
     void InitGraphicsPipelineInfo();
     void InitPipelineCacheInfo();
@@ -475,7 +478,7 @@
     // info_override can be any callable that takes a CreatePipelineHeper &
     // flags, error can be any args accepted by "SetDesiredFailure".
     template <typename Test, typename OverrideFunc, typename Error>
-    static void OneshotTest(Test &test, OverrideFunc &info_override, const VkFlags flags, const std::vector<Error> &errors,
+    static void OneshotTest(Test &test, const OverrideFunc &info_override, const VkFlags flags, const std::vector<Error> &errors,
                             bool positive_test = false) {
         CreatePipelineHelper helper(test);
         helper.InitInfo();
@@ -493,7 +496,8 @@
     }
 
     template <typename Test, typename OverrideFunc, typename Error>
-    static void OneshotTest(Test &test, OverrideFunc &info_override, const VkFlags flags, Error error, bool positive_test = false) {
+    static void OneshotTest(Test &test, const OverrideFunc &info_override, const VkFlags flags, Error error,
+                            bool positive_test = false) {
         OneshotTest(test, info_override, flags, std::vector<Error>(1, error), positive_test);
     }
 };
@@ -530,7 +534,7 @@
     // info_override can be any callable that takes a CreatePipelineHeper &
     // flags, error can be any args accepted by "SetDesiredFailure".
     template <typename Test, typename OverrideFunc, typename Error>
-    static void OneshotTest(Test &test, OverrideFunc &info_override, const VkFlags flags, const std::vector<Error> &errors,
+    static void OneshotTest(Test &test, const OverrideFunc &info_override, const VkFlags flags, const std::vector<Error> &errors,
                             bool positive_test = false) {
         CreateComputePipelineHelper helper(test);
         helper.InitInfo();
@@ -548,7 +552,8 @@
     }
 
     template <typename Test, typename OverrideFunc, typename Error>
-    static void OneshotTest(Test &test, OverrideFunc &info_override, const VkFlags flags, Error error, bool positive_test = false) {
+    static void OneshotTest(Test &test, const OverrideFunc &info_override, const VkFlags flags, Error error,
+                            bool positive_test = false) {
         OneshotTest(test, info_override, flags, std::vector<Error>(1, error), positive_test);
     }
 };
@@ -594,7 +599,7 @@
     // info_override can be any callable that takes a CreateNVRayTracingPipelineHelper &
     // flags, error can be any args accepted by "SetDesiredFailure".
     template <typename Test, typename OverrideFunc, typename Error>
-    static void OneshotTest(Test &test, OverrideFunc &info_override, const std::vector<Error> &errors,
+    static void OneshotTest(Test &test, const OverrideFunc &info_override, const std::vector<Error> &errors,
                             const VkFlags flags = VK_DEBUG_REPORT_ERROR_BIT_EXT) {
         CreateNVRayTracingPipelineHelper helper(test);
         helper.InitInfo();
@@ -607,13 +612,13 @@
     }
 
     template <typename Test, typename OverrideFunc, typename Error>
-    static void OneshotTest(Test &test, OverrideFunc &info_override, Error error,
+    static void OneshotTest(Test &test, const OverrideFunc &info_override, Error error,
                             const VkFlags flags = VK_DEBUG_REPORT_ERROR_BIT_EXT) {
         OneshotTest(test, info_override, std::vector<Error>(1, error), flags);
     }
 
     template <typename Test, typename OverrideFunc>
-    static void OneshotPositiveTest(Test &test, OverrideFunc &info_override,
+    static void OneshotPositiveTest(Test &test, const OverrideFunc &info_override,
                                     const VkDebugReportFlagsEXT message_flag_mask = VK_DEBUG_REPORT_ERROR_BIT_EXT) {
         CreateNVRayTracingPipelineHelper helper(test);
         helper.InitInfo();
diff --git a/tests/vklayertests_command.cpp b/tests/vklayertests_command.cpp
index ef852e7..3724cc8 100644
--- a/tests/vklayertests_command.cpp
+++ b/tests/vklayertests_command.cpp
@@ -179,6 +179,49 @@
     m_errorMonitor->VerifyFound();
 }
 
+TEST_F(VkLayerTest, DynamicLineStippleNotBound) {
+    TEST_DESCRIPTION(
+        "Run a simple draw calls to validate failure when Line Stipple dynamic state is required but not correctly bound.");
+
+    if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
+        m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+    } else {
+        printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix,
+               VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+        return;
+    }
+    ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
+    std::array<const char *, 1> required_device_extensions = {{VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME}};
+    for (auto device_extension : required_device_extensions) {
+        if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) {
+            m_device_extension_names.push_back(device_extension);
+        } else {
+            printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension);
+            return;
+        }
+    }
+
+    PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
+        (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
+    ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
+
+    auto line_rasterization_features = lvl_init_struct<VkPhysicalDeviceLineRasterizationFeaturesEXT>();
+    auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&line_rasterization_features);
+    vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
+
+    if (!line_rasterization_features.stippledBresenhamLines || !line_rasterization_features.bresenhamLines) {
+        printf("%sStipple Bresenham lines not supported; skipped.\n", kSkipPrefix);
+        return;
+    }
+
+    ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
+                                         "Dynamic line stipple state not set for this command buffer");
+    VKTriangleTest(BsoFailLineStipple);
+    m_errorMonitor->VerifyFound();
+}
+
 TEST_F(VkLayerTest, DynamicViewportNotBound) {
     TEST_DESCRIPTION(
         "Run a simple draw calls to validate failure when Viewport dynamic state is required but not correctly bound.");
diff --git a/tests/vklayertests_pipeline_shader.cpp b/tests/vklayertests_pipeline_shader.cpp
index 2ca5dab..e928ddd 100644
--- a/tests/vklayertests_pipeline_shader.cpp
+++ b/tests/vklayertests_pipeline_shader.cpp
@@ -5596,3 +5596,107 @@
     pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle());
     m_errorMonitor->VerifyFound();
 }
+
+TEST_F(VkLayerTest, CreatePipelineCheckLineRasterization) {
+    TEST_DESCRIPTION("Test VK_EXT_line_rasterization state against feature enables.");
+
+    if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
+        m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+    } else {
+        printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix,
+               VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+        return;
+    }
+    ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
+    std::array<const char *, 1> required_device_extensions = {{VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME}};
+    for (auto device_extension : required_device_extensions) {
+        if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) {
+            m_device_extension_names.push_back(device_extension);
+        } else {
+            printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension);
+            return;
+        }
+    }
+
+    PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
+        (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
+    ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
+
+    auto line_rasterization_features = lvl_init_struct<VkPhysicalDeviceLineRasterizationFeaturesEXT>();
+    auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&line_rasterization_features);
+    vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
+
+    line_rasterization_features.rectangularLines = VK_FALSE;
+    line_rasterization_features.bresenhamLines = VK_FALSE;
+    line_rasterization_features.smoothLines = VK_FALSE;
+    line_rasterization_features.stippledRectangularLines = VK_FALSE;
+    line_rasterization_features.stippledBresenhamLines = VK_FALSE;
+    line_rasterization_features.stippledSmoothLines = VK_FALSE;
+
+    ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
+
+    CreatePipelineHelper::OneshotTest(
+        *this,
+        [&](CreatePipelineHelper &helper) {
+            helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
+            helper.pipe_ms_state_ci_.alphaToCoverageEnable = VK_TRUE;
+        },
+        VK_DEBUG_REPORT_ERROR_BIT_EXT,
+        std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766",
+                                  "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769"});
+
+    CreatePipelineHelper::OneshotTest(
+        *this,
+        [&](CreatePipelineHelper &helper) {
+            helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
+            helper.line_state_ci_.stippledLineEnable = VK_TRUE;
+        },
+        VK_DEBUG_REPORT_ERROR_BIT_EXT,
+        std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
+                                  "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769",
+                                  "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772"});
+
+    CreatePipelineHelper::OneshotTest(
+        *this,
+        [&](CreatePipelineHelper &helper) {
+            helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
+            helper.line_state_ci_.stippledLineEnable = VK_TRUE;
+        },
+        VK_DEBUG_REPORT_ERROR_BIT_EXT,
+        std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
+                                  "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768",
+                                  "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771"});
+
+    CreatePipelineHelper::OneshotTest(
+        *this,
+        [&](CreatePipelineHelper &helper) {
+            helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
+            helper.line_state_ci_.stippledLineEnable = VK_TRUE;
+        },
+        VK_DEBUG_REPORT_ERROR_BIT_EXT,
+        std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
+                                  "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770",
+                                  "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773"});
+
+    CreatePipelineHelper::OneshotTest(
+        *this,
+        [&](CreatePipelineHelper &helper) {
+            helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
+            helper.line_state_ci_.stippledLineEnable = VK_TRUE;
+        },
+        VK_DEBUG_REPORT_ERROR_BIT_EXT,
+        std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
+                                  "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774"});
+
+    PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT =
+        (PFN_vkCmdSetLineStippleEXT)vkGetDeviceProcAddr(m_device->device(), "vkCmdSetLineStippleEXT");
+    ASSERT_TRUE(vkCmdSetLineStippleEXT != nullptr);
+
+    m_commandBuffer->begin();
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetLineStippleEXT-lineStippleFactor-02776");
+    vkCmdSetLineStippleEXT(m_commandBuffer->handle(), 0, 0);
+    m_errorMonitor->VerifyFound();
+    vkCmdSetLineStippleEXT(m_commandBuffer->handle(), 1, 1);
+    m_errorMonitor->VerifyFound();
+}
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index 08e6fa6..f000835 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -1610,7 +1610,7 @@
     m_vp_state.pScissors = nullptr;
 
     m_rs_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
-    m_rs_state.pNext = nullptr;
+    m_rs_state.pNext = &m_line_state;
     m_rs_state.flags = 0;
     m_rs_state.depthClampEnable = VK_FALSE;
     m_rs_state.rasterizerDiscardEnable = VK_FALSE;
@@ -1623,6 +1623,13 @@
     m_rs_state.depthBiasSlopeFactor = 0.0f;
     m_rs_state.lineWidth = 1.0f;
 
+    m_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
+    m_line_state.pNext = nullptr;
+    m_line_state.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
+    m_line_state.stippledLineEnable = VK_FALSE;
+    m_line_state.lineStippleFactor = 0;
+    m_line_state.lineStipplePattern = 0;
+
     m_ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
     m_ms_state.pNext = nullptr;
     m_ms_state.flags = 0;
@@ -1698,10 +1705,15 @@
 
 void VkPipelineObj::SetInputAssembly(const VkPipelineInputAssemblyStateCreateInfo *ia_state) { m_ia_state = *ia_state; }
 
-void VkPipelineObj::SetRasterization(const VkPipelineRasterizationStateCreateInfo *rs_state) { m_rs_state = *rs_state; }
+void VkPipelineObj::SetRasterization(const VkPipelineRasterizationStateCreateInfo *rs_state) {
+    m_rs_state = *rs_state;
+    m_rs_state.pNext = &m_line_state;
+}
 
 void VkPipelineObj::SetTessellation(const VkPipelineTessellationStateCreateInfo *te_state) { m_te_state = te_state; }
 
+void VkPipelineObj::SetLineState(const VkPipelineRasterizationLineStateCreateInfoEXT *line_state) { m_line_state = *line_state; }
+
 void VkPipelineObj::InitGraphicsPipelineCreateInfo(VkGraphicsPipelineCreateInfo *gp_ci) {
     gp_ci->stageCount = m_shaderStages.size();
     gp_ci->pStages = m_shaderStages.size() ? m_shaderStages.data() : nullptr;
diff --git a/tests/vkrenderframework.h b/tests/vkrenderframework.h
index 2b8561d..f6e8d33 100644
--- a/tests/vkrenderframework.h
+++ b/tests/vkrenderframework.h
@@ -452,6 +452,7 @@
     void SetTessellation(const VkPipelineTessellationStateCreateInfo *te_state);
     void SetViewport(const vector<VkViewport> viewports);
     void SetScissor(const vector<VkRect2D> scissors);
+    void SetLineState(const VkPipelineRasterizationLineStateCreateInfoEXT *line_state);
 
     void InitGraphicsPipelineCreateInfo(VkGraphicsPipelineCreateInfo *gp_ci);
 
@@ -467,6 +468,7 @@
     VkPipelineMultisampleStateCreateInfo m_ms_state;
     VkPipelineTessellationStateCreateInfo const *m_te_state;
     VkPipelineDynamicStateCreateInfo m_pd_state;
+    VkPipelineRasterizationLineStateCreateInfoEXT m_line_state;
     vector<VkDynamicState> m_dynamic_state_enables;
     vector<VkViewport> m_viewports;
     vector<VkRect2D> m_scissors;