Merge vk-gl-cts/dev/VK_EXT_mesh_shader into vk-gl-cts/main
authorMatthew Netsch <quic_mnetsch@quicinc.com>
Thu, 13 Oct 2022 08:10:40 +0000 (10:10 +0200)
committerRicardo Garcia <rgarcia@igalia.com>
Thu, 13 Oct 2022 08:10:40 +0000 (10:10 +0200)
Change-Id: Ie15c59d595c0780f658128c8531d72baccc6c9bf

19 files changed:
1  2 
AndroidGen.mk
android/cts/main/vk-master-2022-03-01/dynamic-state.txt
android/cts/main/vk-master-2022-03-01/pipeline.txt
android/cts/main/vk-master/dynamic-state.txt
android/cts/main/vk-master/pipeline/fast-linked-library.txt
android/cts/main/vk-master/pipeline/monolithic.txt
android/cts/main/vk-master/pipeline/pipeline-library.txt
external/fetch_sources.py
external/vulkancts/framework/vulkan/generated/vulkan/vkDeviceFeatures2.inl
external/vulkancts/framework/vulkan/generated/vulkan/vkMandatoryFeatures.inl
external/vulkancts/modules/vulkan/dynamic_state/vktDynamicStateBaseClass.cpp
external/vulkancts/modules/vulkan/dynamic_state/vktDynamicStateBaseClass.hpp
external/vulkancts/modules/vulkan/dynamic_state/vktDynamicStateDSTests.cpp
external/vulkancts/modules/vulkan/dynamic_state/vktDynamicStateDiscardTests.cpp
external/vulkancts/mustpass/main/vk-default/dynamic-state.txt
external/vulkancts/mustpass/main/vk-default/pipeline/fast-linked-library.txt
external/vulkancts/mustpass/main/vk-default/pipeline/monolithic.txt
external/vulkancts/mustpass/main/vk-default/pipeline/pipeline-library.txt
external/vulkancts/scripts/gen_framework.py

diff --cc AndroidGen.mk
Simple merge
@@@ -25,14 -41,24 +41,30 @@@ dEQP-VK.dynamic_state.pipeline_library.
  dEQP-VK.dynamic_state.pipeline_library.image.blit
  dEQP-VK.dynamic_state.pipeline_library.image.copy
  dEQP-VK.dynamic_state.pipeline_library.image.resolve
 +dEQP-VK.dynamic_state.pipeline_library.discard.stencil
 +dEQP-VK.dynamic_state.pipeline_library.discard.viewport
 +dEQP-VK.dynamic_state.pipeline_library.discard.scissor
 +dEQP-VK.dynamic_state.pipeline_library.discard.depth
 +dEQP-VK.dynamic_state.pipeline_library.discard.blend
 +dEQP-VK.dynamic_state.pipeline_library.discard.line
+ dEQP-VK.dynamic_state.monolithic.vp_state.viewport_mesh
+ dEQP-VK.dynamic_state.monolithic.vp_state.scissor_mesh
+ dEQP-VK.dynamic_state.monolithic.vp_state.viewport_array_mesh
  dEQP-VK.dynamic_state.monolithic.rs_state.nonzero_depth_bias_constant
  dEQP-VK.dynamic_state.monolithic.rs_state.nonzero_depth_bias_clamp
+ dEQP-VK.dynamic_state.monolithic.rs_state.depth_bias_mesh
+ dEQP-VK.dynamic_state.monolithic.rs_state.depth_bias_clamp_mesh
+ dEQP-VK.dynamic_state.monolithic.rs_state.line_width_mesh
+ dEQP-VK.dynamic_state.monolithic.rs_state.nonzero_depth_bias_constant_mesh
+ dEQP-VK.dynamic_state.monolithic.rs_state.nonzero_depth_bias_clamp_mesh
+ dEQP-VK.dynamic_state.monolithic.cb_state.blend_constants_mesh
+ dEQP-VK.dynamic_state.monolithic.ds_state.depth_bounds_1_mesh
+ dEQP-VK.dynamic_state.monolithic.ds_state.depth_bounds_2_mesh
+ dEQP-VK.dynamic_state.monolithic.ds_state.stencil_params_basic_1_mesh
+ dEQP-VK.dynamic_state.monolithic.ds_state.stencil_params_basic_2_mesh
+ dEQP-VK.dynamic_state.monolithic.ds_state.stencil_params_advanced_mesh
+ dEQP-VK.dynamic_state.monolithic.general_state.state_switch_mesh
+ dEQP-VK.dynamic_state.monolithic.general_state.bind_order_mesh
  dEQP-VK.dynamic_state.monolithic.image.clear
  dEQP-VK.dynamic_state.monolithic.image.blit
  dEQP-VK.dynamic_state.monolithic.image.copy
@@@ -304,7 -304,7 +304,7 @@@ PACKAGES = 
        GitRepo(
                "https://github.com/KhronosGroup/glslang.git",
                "git@github.com:KhronosGroup/glslang.git",
-               "22d39cd684d136a81778cc17a0226ffad40d1cee",
 -              "8243ca3c30527152c909b100292e4360e189663f",
++              "28b53119bdfbc43eae532641337a7adbb315b273",
                "glslang",
                removeTags = ["master-tot"]),
        GitRepo(
@@@ -48,15 -58,30 +58,38 @@@ DynamicStateBaseClass::DynamicStateBase
  
  void DynamicStateBaseClass::initialize (void)
  {
-       const vk::VkDevice device               = m_context.getDevice();
-       const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+       const vk::VkDevice                                              device                          = m_context.getDevice();
+       const deUint32                                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       const auto                                                              vertDescType            = (m_isMesh ? vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : vk::VK_DESCRIPTOR_TYPE_MAX_ENUM);
+       std::vector<vk::VkPushConstantRange>    pcRanges;
+       // The mesh shading pipeline will contain a set with vertex data.
+ #ifndef CTS_USES_VULKANSC
+       if (m_isMesh)
+       {
+               vk::DescriptorSetLayoutBuilder  setLayoutBuilder;
+               vk::DescriptorPoolBuilder               poolBuilder;
+               setLayoutBuilder.addSingleBinding(vertDescType, vk::VK_SHADER_STAGE_MESH_BIT_EXT);
 -              m_setLayout = setLayoutBuilder.build(m_vk, device);
++              m_meshSetLayout = setLayoutBuilder.build(m_vk, device);
+               poolBuilder.addType(vertDescType);
+               m_descriptorPool = poolBuilder.build(m_vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
  
-       PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
-       if (m_descriptorSetLayout) {
-               pipelineLayoutCreateInfo.setLayoutCount = 1;
-               pipelineLayoutCreateInfo.pSetLayouts = &*m_descriptorSetLayout;
 -              m_descriptorSet = vk::makeDescriptorSet(m_vk, device, m_descriptorPool.get(), m_setLayout.get());
++              m_descriptorSet = vk::makeDescriptorSet(m_vk, device, m_descriptorPool.get(), m_meshSetLayout.get());
+               pcRanges.push_back(vk::makePushConstantRange(vk::VK_SHADER_STAGE_MESH_BIT_EXT, 0u, static_cast<uint32_t>(sizeof(uint32_t))));
        }
-       m_pipelineLayout = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
+ #endif // CTS_USES_VULKANSC
 -      m_pipelineLayout = vk::makePipelineLayout(m_vk, device, m_setLayout.get(), de::dataOrNull(pcRanges));
++      std::vector<vk::VkDescriptorSetLayout> rawSetLayouts;
++
++      if (m_meshSetLayout)
++              rawSetLayouts.push_back(m_meshSetLayout.get());
++
++      if (m_otherSetLayout)
++              rawSetLayouts.push_back(m_otherSetLayout.get());
++
++      m_pipelineLayout = vk::makePipelineLayout(m_vk, device, de::sizeU32(rawSetLayouts), de::dataOrNull(rawSetLayouts), de::sizeU32(pcRanges), de::dataOrNull(pcRanges));
  
        const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
        const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
@@@ -1,28 -1,28 +1,28 @@@
  #ifndef _VKTDYNAMICSTATEBASECLASS_HPP
  #define _VKTDYNAMICSTATEBASECLASS_HPP
  /*------------------------------------------------------------------------
-- * Vulkan Conformance Tests
-- * ------------------------
-- *
-- * Copyright (c) 2015 The Khronos Group Inc.
-- * Copyright (c) 2015 Intel Corporation
-- *
-- * 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
-- *
-- * Unless required by applicable law or agreed to in writing, software
-- * distributed under the License is distributed on an "AS IS" BASIS,
-- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- * See the License for the specific language governing permissions and
-- * limitations under the License.
-- *
-- *//*!
-- * \file
-- * \brief Dynamic State Tests - Base Class
-- *//*--------------------------------------------------------------------*/
++* Vulkan Conformance Tests
++* ------------------------
++*
++* Copyright (c) 2015 The Khronos Group Inc.
++* Copyright (c) 2015 Intel Corporation
++*
++* 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
++*
++* Unless required by applicable law or agreed to in writing, software
++* distributed under the License is distributed on an "AS IS" BASIS,
++* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++* See the License for the specific language governing permissions and
++* limitations under the License.
++*
++*//*!
++* \file
++* \brief Dynamic State Tests - Base Class
++*//*--------------------------------------------------------------------*/
  
  #include "tcuDefs.hpp"
  #include "vktTestCase.hpp"
@@@ -93,9 -103,11 +103,12 @@@ protected
  
        const vk::DeviceInterface&                                                              m_vk;
  
-       vk::GraphicsPipelineWrapper                                                             m_pipeline;
+       vk::Move<vk::VkDescriptorPool>                                                  m_descriptorPool;
 -      vk::Move<vk::VkDescriptorSetLayout>                                             m_setLayout;
++      vk::Move<vk::VkDescriptorSetLayout>                                             m_meshSetLayout;
++      vk::Move<vk::VkDescriptorSetLayout>                                             m_otherSetLayout;
        vk::Move<vk::VkPipelineLayout>                                                  m_pipelineLayout;
-       vk::Move<vk::VkDescriptorSetLayout>                                             m_descriptorSetLayout;
+       vk::Move<vk::VkDescriptorSet>                                                   m_descriptorSet;
+       vk::GraphicsPipelineWrapper                                                             m_pipeline;
  
        de::SharedPtr<Draw::Image>                                                              m_colorTargetImage;
        vk::Move<vk::VkImageView>                                                               m_colorTargetView;
@@@ -885,6 -1048,6 +1048,14 @@@ public
        }
  };
  
++void checkNothing (Context&)
++{}
++
++void checkMeshShaderSupport (Context& context)
++{
++      context.requireDeviceFunctionality("VK_EXT_mesh_shader");
++}
++
  class StencilParamsBasicTestCase : public TestCase
  {
  protected:
  
        virtual void checkSupport(Context& context) const
        {
++              checkMeshShaderSupport(context);
                checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
        }
  
@@@ -1057,6 -1252,17 +1261,12 @@@ void checkDepthBoundsSupport (Context& 
        context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_BOUNDS);
  }
  
 -void checkMeshShaderSupport (Context& context)
 -{
 -      context.requireDeviceFunctionality("VK_EXT_mesh_shader");
 -}
 -
+ void checkDepthBoundsAndMeshShaderSupport (Context& context)
+ {
+       checkDepthBoundsSupport(context);
+       checkMeshShaderSupport(context);
+ }
  } //anonymous
  
  DynamicStateDSTests::DynamicStateDSTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
@@@ -1072,17 -1278,44 +1282,45 @@@ DynamicStateDSTests::~DynamicStateDSTes
  
  void DynamicStateDSTests::init (void)
  {
-       ShaderMap shaderPaths;
-       shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
-       shaderPaths[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
+       ShaderMap basePaths;
+       basePaths[glu::SHADERTYPE_FRAGMENT]     = "vulkan/dynamic_state/VertexFetch.frag";
+       basePaths[glu::SHADERTYPE_MESH]         = nullptr;
+       basePaths[glu::SHADERTYPE_VERTEX]       = nullptr;
  
-       addChild(new InstanceFactory<DepthBoundsParamTestInstance, FunctionSupport0>(m_testCtx, "depth_bounds_1", "Perform depth bounds test 1", m_pipelineConstructionType, shaderPaths, checkDepthBoundsSupport));
-       addChild(new InstanceFactory<DepthBoundsTestInstance, FunctionSupport0>(m_testCtx, "depth_bounds_2", "Perform depth bounds test 1", m_pipelineConstructionType, shaderPaths, checkDepthBoundsSupport));
+       for (int useMeshIdx = 0; useMeshIdx < 2; ++useMeshIdx)
+       {
+               const bool                                      useMesh                         = (useMeshIdx > 0);
+               ShaderMap                                       shaderPaths                     (basePaths);
+               FunctionSupport0::Function      depthBoundsCheck        = nullptr;
++              FunctionSupport0::Function      meshSupportCheck        = (useMesh ? checkMeshShaderSupport : checkNothing);
+               std::string                                     nameSuffix;
+               std::string                                     descSuffix;
+               if (useMesh)
+               {
  #ifndef CTS_USES_VULKANSC
-       addChild(new StencilParamsBasicTestCase(m_testCtx, "stencil_params_basic_1", "Perform basic stencil test 1", m_pipelineConstructionType, 0x0D, 0x06, 0x05, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)));
-       addChild(new StencilParamsBasicTestCase(m_testCtx, "stencil_params_basic_2", "Perform basic stencil test 2", m_pipelineConstructionType, 0x06, 0x02, 0x05, tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)));
+                       shaderPaths[glu::SHADERTYPE_MESH] = "vulkan/dynamic_state/VertexFetch.mesh";
 -                      depthBoundsCheck = checkDepthBoundsSupport;
++                      depthBoundsCheck = checkDepthBoundsAndMeshShaderSupport;
+                       nameSuffix = "_mesh";
+                       descSuffix = " using mesh shaders";
+ #else
+                       continue;
  #endif // CTS_USES_VULKANSC
-       addChild(new InstanceFactory<StencilParamsAdvancedTestInstance>(m_testCtx, "stencil_params_advanced", "Perform advanced stencil test", m_pipelineConstructionType, shaderPaths));
+               }
+               else
+               {
+                       shaderPaths[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
 -                      depthBoundsCheck = checkDepthBoundsAndMeshShaderSupport;
++                      depthBoundsCheck = checkDepthBoundsSupport;
+               }
+               addChild(new InstanceFactory<DepthBoundsParamTestInstance, FunctionSupport0>(m_testCtx, "depth_bounds_1" + nameSuffix, "Perform depth bounds test 1" + descSuffix, m_pipelineConstructionType, shaderPaths, depthBoundsCheck));
+               addChild(new InstanceFactory<DepthBoundsTestInstance, FunctionSupport0>(m_testCtx, "depth_bounds_2" + nameSuffix, "Perform depth bounds test 1" + descSuffix, m_pipelineConstructionType, shaderPaths, depthBoundsCheck));
+ #ifndef CTS_USES_VULKANSC
+               addChild(new StencilParamsBasicTestCase(m_testCtx, "stencil_params_basic_1" + nameSuffix, "Perform basic stencil test 1" + descSuffix, m_pipelineConstructionType, 0x0D, 0x06, 0x05, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), useMesh));
+               addChild(new StencilParamsBasicTestCase(m_testCtx, "stencil_params_basic_2" + nameSuffix, "Perform basic stencil test 2" + descSuffix, m_pipelineConstructionType, 0x06, 0x02, 0x05, tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), useMesh));
+ #endif // CTS_USES_VULKANSC
 -              addChild(new InstanceFactory<StencilParamsAdvancedTestInstance>(m_testCtx, "stencil_params_advanced" + nameSuffix, "Perform advanced stencil test" + descSuffix, m_pipelineConstructionType, shaderPaths));
++              addChild(new InstanceFactory<StencilParamsAdvancedTestInstance, FunctionSupport0>(m_testCtx, "stencil_params_advanced" + nameSuffix, "Perform advanced stencil test" + descSuffix, m_pipelineConstructionType, shaderPaths, meshSupportCheck));
+       }
  }
  
  } // DynamicState
index 82d1351,0000000..e3fa8e3
mode 100644,000000..100644
--- /dev/null
@@@ -1,673 -1,0 +1,673 @@@
-       m_descriptorSetLayout = vk::createDescriptorSetLayout(m_vk, device, &descriptorSetLayoutCreateInfo);
 +/*------------------------------------------------------------------------
 + * Vulkan Conformance Tests
 + * ------------------------
 + *
 + * Copyright (c) 2022 LunarG, Inc.
 + * Copyright (c) 2022 The Khronos Group Inc.
 + * Copyright (c) 2022 Google LLC
 + *
 + * 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
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + *
 + *//*!
 + * \file
 + * \brief Dynamic State Discard Tests
 + *//*--------------------------------------------------------------------*/
 +
 +#include "vktDynamicStateDiscardTests.hpp"
 +
 +#include "vktDynamicStateBaseClass.hpp"
 +#include "vktDynamicStateTestCaseUtil.hpp"
 +
 +#include "vkImageUtil.hpp"
 +#include "vkCmdUtil.hpp"
 +
 +#include "tcuImageCompare.hpp"
 +#include "tcuTextureUtil.hpp"
 +#include "tcuRGBA.hpp"
 +#include "vkQueryUtil.hpp"
 +#include "vkObjUtil.hpp"
 +#include "vkTypeUtil.hpp"
 +#include "vkBufferWithMemory.hpp"
 +
 +namespace vkt
 +{
 +namespace DynamicState
 +{
 +using namespace Draw;
 +using namespace vk;
 +
 +enum TestDynamicStateDiscard
 +{
 +      TEST_STENCIL,
 +      TEST_VIEWPORT,
 +      TEST_SCISSOR,
 +      TEST_DEPTH,
 +      TEST_BLEND_CONSTANTS,
 +      TEST_LINE_WIDTH,
 +};
 +
 +class DiscardTestInstance : public DynamicStateBaseClass
 +{
 +public:
 +      DiscardTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName, vk::VkFormat depthStencilFormat);
 +
 +      virtual void                                                            initRenderPass  (const vk::VkDevice             device);
 +      virtual void                                                            initFramebuffer (const vk::VkDevice             device);
 +      virtual void                                                            initPipeline    (const vk::VkDevice             device);
 +
 +      void                                                                            beginRenderPass (const vk::VkClearColorValue& clearColor);
 +
 +      virtual tcu::TestStatus                                         iterate                 (void);
 +
 +protected:
 +
 +      virtual void                                                            setDynamicState (void) {
 +              DE_ASSERT(false);
 +      }
 +      virtual tcu::TestStatus                                         verifyResults   (void) {
 +              DE_ASSERT(false);
 +              return tcu::TestStatus(QP_TEST_RESULT_PASS, "");
 +      }
 +      const vk::VkFormat                                      m_depthStencilAttachmentFormat;
 +
 +      de::SharedPtr<Draw::Image>                      m_depthStencilImage;
 +      vk::Move<vk::VkImageView>                       m_depthStencilView;
 +      std::vector<vk::VkDynamicState>         m_dynamicStates;
 +      VkBool32                                                        m_depthBounds;
 +};
 +
 +DiscardTestInstance::DiscardTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName, vk::VkFormat depthStencilFormat)
 +      : DynamicStateBaseClass(context, pipelineConstructionType, vertexShaderName, fragmentShaderName)
 +      , m_depthStencilAttachmentFormat(depthStencilFormat)
 +      , m_depthBounds(VK_FALSE)
 +{
 +      const vk::VkDevice                              device                                  = m_context.getDevice();
 +
 +      const vk::VkExtent3D                    stencilImageExtent              = { WIDTH, HEIGHT, 1 };
 +      const ImageCreateInfo                   stencilImageCreateInfo  (vk::VK_IMAGE_TYPE_2D, m_depthStencilAttachmentFormat, stencilImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
 +
 +      m_depthStencilImage     = Image::createAndAlloc(m_vk, device, stencilImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
 +
 +      const ImageViewCreateInfo               stencilViewInfo(m_depthStencilImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_depthStencilAttachmentFormat);
 +      m_depthStencilView      = vk::createImageView(m_vk, device, &stencilViewInfo);
 +
 +      m_topology              = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
 +
 +      m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
 +      m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
 +      m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
 +      m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
 +
 +      const vk::VkDescriptorSetLayoutBinding binding =
 +      {
 +              0u,
 +              vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
 +              1,
 +              vk::VK_SHADER_STAGE_FRAGMENT_BIT,
 +              DE_NULL
 +      };
 +
 +      DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo(1, &binding);
-       vk::Move<vk::VkDescriptorSet>           descriptorSet           = makeDescriptorSet(m_vk, device, *descriptorPool, *m_descriptorSetLayout);
++      m_otherSetLayout = vk::createDescriptorSetLayout(m_vk, device, &descriptorSetLayoutCreateInfo);
 +}
 +
 +void DiscardTestInstance::initRenderPass (const vk::VkDevice device)
 +{
 +      RenderPassCreateInfo renderPassCreateInfo;
 +      renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
 +              vk::VK_SAMPLE_COUNT_1_BIT,
 +              vk::VK_ATTACHMENT_LOAD_OP_LOAD,
 +              vk::VK_ATTACHMENT_STORE_OP_STORE,
 +              vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
 +              vk::VK_ATTACHMENT_STORE_OP_STORE,
 +              vk::VK_IMAGE_LAYOUT_GENERAL,
 +              vk::VK_IMAGE_LAYOUT_GENERAL));
 +      renderPassCreateInfo.addAttachment(AttachmentDescription(m_depthStencilAttachmentFormat,
 +              vk::VK_SAMPLE_COUNT_1_BIT,
 +              vk::VK_ATTACHMENT_LOAD_OP_LOAD,
 +              vk::VK_ATTACHMENT_STORE_OP_STORE,
 +              vk::VK_ATTACHMENT_LOAD_OP_LOAD,
 +              vk::VK_ATTACHMENT_STORE_OP_STORE,
 +              vk::VK_IMAGE_LAYOUT_GENERAL,
 +              vk::VK_IMAGE_LAYOUT_GENERAL));
 +
 +      const vk::VkAttachmentReference colorAttachmentReference =
 +      {
 +              0,
 +              vk::VK_IMAGE_LAYOUT_GENERAL
 +      };
 +
 +      const vk::VkAttachmentReference stencilAttachmentReference =
 +      {
 +              1,
 +              vk::VK_IMAGE_LAYOUT_GENERAL
 +      };
 +
 +      renderPassCreateInfo.addSubpass(SubpassDescription(
 +              vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
 +              0,
 +              0,
 +              DE_NULL,
 +              1,
 +              &colorAttachmentReference,
 +              DE_NULL,
 +              stencilAttachmentReference,
 +              0,
 +              DE_NULL
 +      )
 +      );
 +
 +      m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
 +}
 +
 +void DiscardTestInstance::initFramebuffer (const vk::VkDevice device)
 +{
 +      std::vector<vk::VkImageView> attachments(2);
 +      attachments[0] = *m_colorTargetView;
 +      attachments[1] = *m_depthStencilView;
 +
 +      const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
 +
 +      m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
 +}
 +
 +void DiscardTestInstance::initPipeline(const vk::VkDevice device)
 +{
 +      const vk::Unique<vk::VkShaderModule>                                    vs(createShaderModule   (m_vk, device, m_context.getBinaryCollection().get(m_vertexShaderName), 0));
 +      const vk::Unique<vk::VkShaderModule>                                    fs(createShaderModule   (m_vk, device, m_context.getBinaryCollection().get(m_fragmentShaderName), 0));
 +      std::vector<vk::VkViewport>                                                             viewports                               { { 0.0f, 0.0f, (float)WIDTH, (float)HEIGHT, 0.0f, 1.0f } };
 +      std::vector<vk::VkRect2D>                                                               scissors                                { { { 0u, 0u }, { WIDTH, HEIGHT } } };
 +
 +      const PipelineCreateInfo::ColorBlendState::Attachment   attachmentState;
 +      const PipelineCreateInfo::ColorBlendState                               colorBlendState(1u, static_cast<const vk::VkPipelineColorBlendAttachmentState*>(&attachmentState));
 +      const PipelineCreateInfo::RasterizerState                               rasterizerState;
 +      PipelineCreateInfo::DepthStencilState                                   depthStencilState;
 +      const PipelineCreateInfo::DynamicState                                  dynamicState(m_dynamicStates);
 +
 +      depthStencilState.depthTestEnable               = VK_TRUE;
 +      depthStencilState.depthWriteEnable              = VK_TRUE;
 +      depthStencilState.depthCompareOp                = VK_COMPARE_OP_ALWAYS;
 +      depthStencilState.depthBoundsTestEnable = m_depthBounds;
 +      depthStencilState.minDepthBounds                = 0.0f;
 +      depthStencilState.maxDepthBounds                = 1.0f;
 +      depthStencilState.stencilTestEnable             = VK_TRUE;
 +      depthStencilState.front.failOp                  = VK_STENCIL_OP_KEEP;
 +      depthStencilState.front.passOp                  = VK_STENCIL_OP_REPLACE;
 +      depthStencilState.front.depthFailOp             = VK_STENCIL_OP_KEEP;
 +      depthStencilState.front.compareOp               = VK_COMPARE_OP_ALWAYS;
 +      depthStencilState.front.compareMask             = 0u;
 +      depthStencilState.front.writeMask               = 0u;
 +      depthStencilState.front.reference               = 0u;
 +      depthStencilState.back.failOp                   = VK_STENCIL_OP_KEEP;
 +      depthStencilState.back.passOp                   = VK_STENCIL_OP_REPLACE;
 +      depthStencilState.back.depthFailOp              = VK_STENCIL_OP_KEEP;
 +      depthStencilState.back.compareOp                = VK_COMPARE_OP_ALWAYS;
 +      depthStencilState.back.compareMask              = 0u;
 +      depthStencilState.back.writeMask                = 0u;
 +      depthStencilState.back.reference                = 0u;
 +
 +      m_pipeline.setDefaultTopology(m_topology)
 +              .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo*>(&dynamicState))
 +              .setDefaultMultisampleState()
 +              .setupVertexInputStete(&m_vertexInputState)
 +              .setupPreRasterizationShaderState(viewports,
 +                      scissors,
 +                      *m_pipelineLayout,
 +                      *m_renderPass,
 +                      0u,
 +                      *vs,
 +                      static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState))
 +              .setupFragmentShaderState(*m_pipelineLayout, *m_renderPass, 0u, *fs, static_cast<const vk::VkPipelineDepthStencilStateCreateInfo*>(&depthStencilState))
 +              .setupFragmentOutputState(*m_renderPass, 0u, static_cast<const vk::VkPipelineColorBlendStateCreateInfo*>(&colorBlendState))
 +              .setMonolithicPipelineLayout(*m_pipelineLayout)
 +              .buildPipeline();
 +}
 +
 +void DiscardTestInstance::beginRenderPass (const vk::VkClearColorValue& clearColor)
 +{
 +      beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
 +
 +      initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
 +              vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
 +
 +      const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
 +      m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
 +              vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
 +
 +      const vk::VkMemoryBarrier memBarrier =
 +      {
 +              vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
 +              DE_NULL,
 +              vk::VK_ACCESS_TRANSFER_WRITE_BIT,
 +              vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
 +      };
 +
 +      m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
 +              vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
 +              0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
 +
 +      if (m_depthStencilAttachmentFormat == vk::VK_FORMAT_S8_UINT) {
 +              initialTransitionStencil2DImage(m_vk, *m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
 +      }
 +      else
 +      {
 +              initialTransitionDepth2DImage(m_vk, *m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
 +      }
 +
 +
 +      const vk::VkClearDepthStencilValue      depthStencilClearValue  = { 0.0f, 0 };
 +      const ImageSubresourceRange                     subresourceRangeStencil = m_depthStencilAttachmentFormat == vk::VK_FORMAT_S8_UINT ? vk::VK_IMAGE_ASPECT_STENCIL_BIT : vk::VK_IMAGE_ASPECT_DEPTH_BIT;
 +      m_vk.cmdClearDepthStencilImage(*m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, &depthStencilClearValue, 1, &subresourceRangeStencil);
 +
 +      vk::VkMemoryBarrier dsMemBarrier;
 +      dsMemBarrier.sType = vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER;
 +      dsMemBarrier.pNext = NULL;
 +      dsMemBarrier.srcAccessMask = vk::VK_ACCESS_TRANSFER_WRITE_BIT;
 +      dsMemBarrier.dstAccessMask = vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
 +
 +      m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0, 1, &dsMemBarrier, 0, NULL, 0, NULL);
 +
 +      vk::beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, vk::makeRect2D(0, 0, WIDTH, HEIGHT));
 +}
 +tcu::TestStatus DiscardTestInstance::iterate(void) {
 +      const vk::VkQueue                                       queue                           = m_context.getUniversalQueue();
 +      const vk::VkDevice                                      device                          = m_context.getDevice();
 +      Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
 +
 +      const VkDescriptorPoolSize                      poolSizes[] =
 +      {
 +              { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,    1u      },
 +      };
 +      const VkDescriptorPoolCreateInfo        poolInfo =
 +      {
 +              VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
 +              DE_NULL,
 +              vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
 +              1u,             // maxSets
 +              DE_LENGTH_OF_ARRAY(poolSizes),
 +              poolSizes,
 +      };
 +
 +      vk::Move<vk::VkDescriptorPool>          descriptorPool          = createDescriptorPool(m_vk, device, &poolInfo);
++      vk::Move<vk::VkDescriptorSet>           descriptorSet           = makeDescriptorSet(m_vk, device, *descriptorPool, *m_otherSetLayout);
 +
 +      const vk::VkDeviceSize                          size                            = sizeof(int);
 +
 +      const BufferWithMemory                          buffer                          (m_vk, device, allocator, makeBufferCreateInfo(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), MemoryRequirement::HostVisible);
 +
 +      deUint32*                                                       ptr                                     = (deUint32*)buffer.getAllocation().getHostPtr();
 +      deMemset(ptr, 0u, static_cast<std::size_t>(size));
 +
 +      {
 +              const vk::VkDescriptorBufferInfo        bufferInfo              = makeDescriptorBufferInfo(*buffer, 0, size);
 +              const vk::VkWriteDescriptorSet          descriptorWrite =
 +              {
 +                      VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
 +                      DE_NULL,
 +                      *descriptorSet,
 +                      0u,             // dstBinding
 +                      0u,             // dstArrayElement
 +                      1u,             // descriptorCount
 +                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
 +                      DE_NULL,
 +                      &bufferInfo,
 +                      DE_NULL,
 +              };
 +
 +              m_vk.updateDescriptorSets(device, 1, &descriptorWrite, 0u, DE_NULL);
 +      }
 +
 +      const vk::VkClearColorValue                     clearColor                      = { { 0.0f, 0.0f, 0.0f, 1.0f } };
 +      beginRenderPass(clearColor);
 +      m_vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &*descriptorSet, 0, nullptr);
 +      m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.getPipeline());
 +      const vk::VkDeviceSize vertexBufferOffset = 0;
 +      const vk::VkBuffer              vertexBuffer = m_vertexBuffer->object();
 +      m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
 +
 +      setDynamicState();
 +
 +      m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
 +      endRenderPass(m_vk, *m_cmdBuffer);
 +      endCommandBuffer(m_vk, *m_cmdBuffer);
 +
 +      submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
 +
 +      return verifyResults();
 +}
 +
 +class StencilTestInstance : public DiscardTestInstance
 +{
 +public:
 +      StencilTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
 +              : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, vk::VK_FORMAT_S8_UINT)
 +      {
 +              m_dynamicStates = { vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE };
 +              const auto features = context.getDeviceFeatures();
 +              m_depthBounds = features.depthBounds;
 +
 +              DynamicStateBaseClass::initialize();
 +      }
 +
 +      virtual void setDynamicState(void) {
 +              uint32_t value = 0x80;
 +              m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
 +              m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
 +              m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
 +              m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
 +              m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
 +              m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
 +      }
 +
 +      virtual tcu::TestStatus verifyResults(void) {
 +              const vk::VkQueue                                       queue                   = m_context.getUniversalQueue();
 +              const vk::VkOffset3D                            zeroOffset              = { 0, 0, 0 };
 +              const tcu::ConstPixelBufferAccess       renderedFrame   = m_depthStencilImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_STENCIL_BIT);
 +
 +              for (int i = 0; i < WIDTH; ++i) {
 +                      for (int j = 0; j < HEIGHT; ++j) {
 +                              const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
 +                              if (pixel[0] != 0.0f) {
 +                                      return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
 +                              }
 +                      }
 +              }
 +              return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
 +      }
 +};
 +
 +class ViewportTestInstance : public DiscardTestInstance
 +{
 +public:
 +      ViewportTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
 +              : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, vk::VK_FORMAT_S8_UINT)
 +      {
 +              m_dynamicStates = { vk::VK_DYNAMIC_STATE_VIEWPORT };
 +              DynamicStateBaseClass::initialize();
 +      }
 +
 +      virtual void setDynamicState(void) {
 +              vk::VkViewport viewport = vk::makeViewport(tcu::UVec2(WIDTH, HEIGHT));
 +              m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport);
 +      }
 +
 +      virtual tcu::TestStatus verifyResults(void) {
 +              const vk::VkQueue       queue = m_context.getUniversalQueue();
 +              tcu::Texture2D          referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
 +              referenceFrame.allocLevel(0);
 +
 +              const vk::VkOffset3D                            zeroOffset = { 0, 0, 0 };
 +              const tcu::ConstPixelBufferAccess       renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
 +                      vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
 +
 +              for (int i = 0; i < WIDTH; ++i) {
 +                      for (int j = 0; j < HEIGHT; ++j) {
 +                              const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
 +                              if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) {
 +                                      return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
 +                              }
 +                      }
 +              }
 +              return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
 +      }
 +};
 +
 +class ScissorTestInstance : public DiscardTestInstance
 +{
 +public:
 +      ScissorTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
 +              : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, vk::VK_FORMAT_S8_UINT)
 +      {
 +              m_dynamicStates = { vk::VK_DYNAMIC_STATE_SCISSOR };
 +              DynamicStateBaseClass::initialize();
 +      }
 +
 +      virtual void setDynamicState(void) {
 +              vk::VkRect2D scissor = vk::makeRect2D(tcu::UVec2(WIDTH, HEIGHT));
 +              m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor);
 +      }
 +
 +      virtual tcu::TestStatus verifyResults(void) {
 +              const vk::VkQueue       queue = m_context.getUniversalQueue();
 +              tcu::Texture2D          referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
 +              referenceFrame.allocLevel(0);
 +
 +              const vk::VkOffset3D                            zeroOffset = { 0, 0, 0 };
 +              const tcu::ConstPixelBufferAccess       renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
 +                      vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
 +
 +              for (int i = 0; i < WIDTH; ++i) {
 +                      for (int j = 0; j < HEIGHT; ++j) {
 +                              const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
 +                              if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) {
 +                                      return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
 +                              }
 +                      }
 +              }
 +              return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
 +      }
 +};
 +
 +class DepthTestInstance : public DiscardTestInstance
 +{
 +public:
 +      DepthTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
 +              : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, vk::VK_FORMAT_D32_SFLOAT)
 +      {
 +              m_dynamicStates = { vk::VK_DYNAMIC_STATE_DEPTH_BIAS, vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS };
 +              DynamicStateBaseClass::initialize();
 +      }
 +
 +      virtual void setDynamicState(void) {
 +              m_vk.cmdSetDepthBounds(*m_cmdBuffer, 0.0f, 1.0f);
 +              m_vk.cmdSetDepthBias(*m_cmdBuffer, 1.0f, 1.0f, 1.0f);
 +      }
 +
 +      virtual tcu::TestStatus verifyResults(void) {
 +              const vk::VkQueue                                       queue                   = m_context.getUniversalQueue();
 +              const vk::VkOffset3D                            zeroOffset              = { 0, 0, 0 };
 +              const tcu::ConstPixelBufferAccess       renderedFrame   = m_depthStencilImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_DEPTH_BIT);
 +
 +              for (int i = 0; i < WIDTH; ++i) {
 +                      for (int j = 0; j < HEIGHT; ++j) {
 +                              const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
 +                              if (pixel[0] != 0.0f) {
 +                                      return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
 +                              }
 +                      }
 +              }
 +              return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
 +      }
 +};
 +
 +class BlendTestInstance : public DiscardTestInstance
 +{
 +public:
 +      BlendTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
 +              : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, vk::VK_FORMAT_S8_UINT)
 +      {
 +              m_dynamicStates = { vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS };
 +              DynamicStateBaseClass::initialize();
 +      }
 +
 +      virtual void setDynamicState(void) {
 +              float blendConstantsants[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
 +              m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants);
 +      }
 +
 +      virtual tcu::TestStatus verifyResults(void) {
 +              const vk::VkQueue       queue = m_context.getUniversalQueue();
 +              tcu::Texture2D          referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
 +              referenceFrame.allocLevel(0);
 +
 +              const vk::VkOffset3D                            zeroOffset = { 0, 0, 0 };
 +              const tcu::ConstPixelBufferAccess       renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
 +                      vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
 +
 +              for (int i = 0; i < WIDTH; ++i) {
 +                      for (int j = 0; j < HEIGHT; ++j) {
 +                              const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
 +                              if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) {
 +                                      return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
 +                              }
 +                      }
 +              }
 +              return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
 +      }
 +};
 +
 +class LineTestInstance : public DiscardTestInstance
 +{
 +public:
 +      LineTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
 +              : DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, vk::VK_FORMAT_S8_UINT)
 +      {
 +              m_dynamicStates = { vk::VK_DYNAMIC_STATE_LINE_WIDTH };
 +              DynamicStateBaseClass::initialize();
 +      }
 +
 +      virtual void setDynamicState(void) {
 +              m_vk.cmdSetLineWidth(*m_cmdBuffer, 1.0f);
 +      }
 +
 +      virtual tcu::TestStatus verifyResults(void) {
 +              const vk::VkQueue       queue = m_context.getUniversalQueue();
 +              tcu::Texture2D          referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
 +              referenceFrame.allocLevel(0);
 +
 +              const vk::VkOffset3D                            zeroOffset = { 0, 0, 0 };
 +              const tcu::ConstPixelBufferAccess       renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
 +                      vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
 +
 +              for (int i = 0; i < WIDTH; ++i) {
 +                      for (int j = 0; j < HEIGHT; ++j) {
 +                              const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
 +                              if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) {
 +                                      return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
 +                              }
 +                      }
 +              }
 +              return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
 +      }
 +};
 +
 +class DiscardTestCase : public vkt::TestCase
 +{
 +public:
 +      DiscardTestCase (tcu::TestContext& context, const char* name, const char* description, vk::PipelineConstructionType pipelineConstructionType, TestDynamicStateDiscard testCase)
 +              : TestCase      (context, name, description)
 +              , m_pipelineConstructionType(pipelineConstructionType)
 +              , m_testCase(testCase)
 +              , m_depthBounds(false)
 +      {
 +      }
 +
 +      virtual void    checkSupport(Context& context) const
 +      {
 +              checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
 +      }
 +
 +      TestInstance* createInstance(Context& context) const
 +      {
 +              switch (m_testCase) {
 +              case TEST_STENCIL:
 +                      return new StencilTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
 +              case TEST_VIEWPORT:
 +                      return new ViewportTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
 +              case TEST_SCISSOR:
 +                      return new ScissorTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
 +              case TEST_DEPTH:
 +                      return new DepthTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
 +              case TEST_BLEND_CONSTANTS:
 +                      return new BlendTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
 +              case TEST_LINE_WIDTH:
 +                      return new LineTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
 +              default:
 +                      break;
 +              }
 +              DE_ASSERT(false);
 +              return nullptr;
 +      }
 +
 +      virtual void initPrograms(vk::SourceCollections& programCollection) const
 +      {
 +              std::ostringstream vert;
 +              vert
 +                      << "#version 450\n"
 +                      << "\n"
 +                      << "layout(location = 0) in vec4 in_position;"
 +                      << "layout(location = 1) in vec4 in_color;"
 +                      << "\n"
 +                      << "layout(location = 0) out vec4 out_color;"
 +                      << "out gl_PerVertex { vec4 gl_Position; };"
 +                      << "\n"
 +                      << "void main ()\n"
 +                      << "{\n"
 +                      << "    gl_Position = in_position;\n"
 +                      << "    out_color = in_color;\n"
 +                      << "}\n";
 +
 +              programCollection.glslSources.add("discard.vert") << glu::VertexSource(vert.str());
 +
 +              std::ostringstream frag;
 +              frag
 +                      << "#version 450\n"
 +                      << "\n"
 +                      << "layout (set=0, binding=0, std140) uniform InputBlock {\n"
 +                      << "    int discard_all;\n"
 +                      << "} unif;\n"
 +                      << "\n"
 +                      << "layout (location = 0) in vec4 in_color;"
 +                      << "\n"
 +                      << "layout (location = 0) out vec4 color;"
 +                      << "\n"
 +                      << "void main ()\n"
 +                      << "{\n"
 +                      << "    if (unif.discard_all == 0) {\n"
 +                      << "            discard;\n"
 +                      << "    }\n"
 +                      << "    color = in_color;\n"
 +                      << "}\n";
 +
 +              programCollection.glslSources.add("discard.frag") << glu::FragmentSource(frag.str());
 +      }
 +
 +protected:
 +      vk::PipelineConstructionType    m_pipelineConstructionType;
 +      TestDynamicStateDiscard                 m_testCase;
 +      VkBool32                                                m_depthBounds;
 +};
 +
 +DynamicStateDiscardTests::DynamicStateDiscardTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
 +      : TestCaseGroup                                 (testCtx, "discard", "Tests for dynamic state")
 +      , m_pipelineConstructionType    (pipelineConstructionType)
 +{
 +      /* Left blank on purpose */
 +}
 +
 +DynamicStateDiscardTests::~DynamicStateDiscardTests ()
 +{
 +}
 +
 +void DynamicStateDiscardTests::init (void)
 +{
 +      addChild(new DiscardTestCase(m_testCtx, "stencil", "Use dynamic stencil with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_STENCIL));
 +      addChild(new DiscardTestCase(m_testCtx, "viewport", "Use dynamic viewport with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_VIEWPORT));
 +      addChild(new DiscardTestCase(m_testCtx, "scissor", "Use dynamic scissor with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_SCISSOR));
 +      addChild(new DiscardTestCase(m_testCtx, "depth", "Use dynamic depth with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_DEPTH));
 +      addChild(new DiscardTestCase(m_testCtx, "blend", "Use dynamic blend constants with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_BLEND_CONSTANTS));
 +      addChild(new DiscardTestCase(m_testCtx, "line", "Use dynamic line width with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_LINE_WIDTH));
 +}
 +
 +} // DynamicState
 +} // vkt