• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Depth Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineDepthTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestCaseUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "deUniquePtr.hpp"
45 #include "deStringUtil.hpp"
46 #include "deMemory.h"
47 
48 #include <sstream>
49 #include <vector>
50 
51 namespace vkt
52 {
53 namespace pipeline
54 {
55 
56 using namespace vk;
57 
58 namespace
59 {
60 
61 enum class DepthClipControlCase
62 {
63     DISABLED       = 0, // No depth clip control.
64     NORMAL         = 1, // Depth clip control with static viewport.
65     NORMAL_W       = 2, // Depth clip control with static viewport and .w different from 1.0f
66     BEFORE_STATIC  = 3, // Set dynamic viewport state, then bind a static pipeline.
67     BEFORE_DYNAMIC = 4, // Set dynamic viewport state, bind dynamic pipeline.
68     BEFORE_TWO_DYNAMICS =
69         5, // Set dynamic viewport state, bind dynamic pipeline with [0,1] view volume, then bind dynamic pipeline with [-1,1] view volume.
70     AFTER_DYNAMIC = 6, // Bind dynamic pipeline, then set dynamic viewport state.
71 };
72 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)73 bool isSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, VkPhysicalDevice device, VkFormat format)
74 {
75     VkFormatProperties formatProps;
76 
77     instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
78 
79     return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0u;
80 }
81 
testSupportsDepthStencilFormat(Context & context,VkFormat format)82 tcu::TestStatus testSupportsDepthStencilFormat(Context &context, VkFormat format)
83 {
84     DE_ASSERT(vk::isDepthStencilFormat(format));
85 
86     if (isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), format))
87         return tcu::TestStatus::pass("Format can be used in depth/stencil attachment");
88     else
89         return tcu::TestStatus::fail("Unsupported depth/stencil attachment format");
90 }
91 
testSupportsAtLeastOneDepthStencilFormat(Context & context,const std::vector<VkFormat> formats)92 tcu::TestStatus testSupportsAtLeastOneDepthStencilFormat(Context &context, const std::vector<VkFormat> formats)
93 {
94     std::ostringstream supportedFormatsMsg;
95     bool pass = false;
96 
97     DE_ASSERT(!formats.empty());
98 
99     for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
100     {
101         const VkFormat format = formats[formatNdx];
102 
103         DE_ASSERT(vk::isDepthStencilFormat(format));
104 
105         if (isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), format))
106         {
107             pass = true;
108             supportedFormatsMsg << vk::getFormatName(format);
109 
110             if (formatNdx < formats.size() - 1)
111                 supportedFormatsMsg << ", ";
112         }
113     }
114 
115     if (pass)
116         return tcu::TestStatus::pass(std::string("Supported depth/stencil formats: ") + supportedFormatsMsg.str());
117     else
118         return tcu::TestStatus::fail("All depth/stencil formats are unsupported");
119 }
120 
121 class DepthTest : public vkt::TestCase
122 {
123 public:
124     enum
125     {
126         QUAD_COUNT = 4
127     };
128 
129     static const float quadDepths[QUAD_COUNT];
130     static const float quadDepthsMinusOneToOne[QUAD_COUNT];
131     static const float quadWs[QUAD_COUNT];
132 
133     DepthTest(tcu::TestContext &testContext, const std::string &name,
134               const PipelineConstructionType pipelineConstructionType, const VkFormat depthFormat,
135               const VkCompareOp depthCompareOps[QUAD_COUNT], const bool separateDepthStencilLayouts,
136               const VkPrimitiveTopology primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
137               const bool depthBoundsTestEnable = false, const float depthBoundsMin = 0.0f,
138               const float depthBoundsMax = 1.0f, const bool depthTestEnable = true,
139               const bool stencilTestEnable = false, const bool depthAttachmentBound = true,
140               const bool colorAttachmentEnable = true, const bool hostVisible = false,
141               const tcu::UVec2 renderSize                 = tcu::UVec2(32, 32),
142               const DepthClipControlCase depthClipControl = DepthClipControlCase::DISABLED);
143     virtual ~DepthTest(void);
144     virtual void initPrograms(SourceCollections &programCollection) const;
145     virtual void checkSupport(Context &context) const;
146     virtual TestInstance *createInstance(Context &context) const;
147 
148 private:
149     const PipelineConstructionType m_pipelineConstructionType;
150     const VkFormat m_depthFormat;
151     const bool m_separateDepthStencilLayouts;
152     VkPrimitiveTopology m_primitiveTopology;
153     const bool m_depthBoundsTestEnable;
154     const float m_depthBoundsMin;
155     const float m_depthBoundsMax;
156     const bool m_depthTestEnable;
157     const bool m_stencilTestEnable;
158     const bool m_depthAttachmentBound;
159     const bool m_colorAttachmentEnable;
160     const bool m_hostVisible;
161     const tcu::UVec2 m_renderSize;
162     const DepthClipControlCase m_depthClipControl;
163     VkCompareOp m_depthCompareOps[QUAD_COUNT];
164 };
165 
166 class DepthTestInstance : public vkt::TestInstance
167 {
168 public:
169     DepthTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
170                       const VkFormat depthFormat, const VkCompareOp depthCompareOps[DepthTest::QUAD_COUNT],
171                       const bool separateDepthStencilLayouts, const VkPrimitiveTopology primitiveTopology,
172                       const bool depthBoundsTestEnable, const float depthBoundsMin, const float depthBoundsMax,
173                       const bool depthTestEnable, const bool stencilTestEnable, const bool depthAttachmentBound,
174                       const bool colorAttachmentEnable, const bool hostVisible, const tcu::UVec2 renderSize,
175                       const DepthClipControlCase depthClipControl);
176 
177     virtual ~DepthTestInstance(void);
178     virtual tcu::TestStatus iterate(void);
179 
180 private:
181     tcu::TestStatus verifyImage(void);
182 
183 private:
184     VkCompareOp m_depthCompareOps[DepthTest::QUAD_COUNT];
185     const tcu::UVec2 m_renderSize;
186     const VkFormat m_colorFormat;
187     const VkFormat m_depthFormat;
188     const bool m_separateDepthStencilLayouts;
189     VkPrimitiveTopology m_primitiveTopology;
190     const bool m_depthBoundsTestEnable;
191     const float m_depthBoundsMin;
192     const float m_depthBoundsMax;
193     const bool m_depthTestEnable;
194     const bool m_stencilTestEnable;
195     const bool m_depthAttachmentBound;
196     const bool m_colorAttachmentEnable;
197     const bool m_hostVisible;
198     const DepthClipControlCase m_depthClipControl;
199     VkImageSubresourceRange m_depthImageSubresourceRange;
200 
201     Move<VkImage> m_colorImage;
202     de::MovePtr<Allocation> m_colorImageAlloc;
203     Move<VkImage> m_depthImage;
204     de::MovePtr<Allocation> m_depthImageAlloc;
205     Move<VkImageView> m_colorAttachmentView;
206     Move<VkImageView> m_depthAttachmentView;
207     RenderPassWrapper m_renderPass;
208     Move<VkFramebuffer> m_framebuffer;
209 
210     ShaderWrapper m_vertexShaderModule;
211     ShaderWrapper m_fragmentShaderModule;
212 
213     Move<VkBuffer> m_vertexBuffer;
214     std::vector<Vertex4RGBA> m_vertices;
215     de::MovePtr<Allocation> m_vertexBufferAlloc;
216 
217     Move<VkBuffer> m_altVertexBuffer;
218     std::vector<Vertex4RGBA> m_altVertices;
219     de::MovePtr<Allocation> m_altVertexBufferAlloc;
220 
221     PipelineLayoutWrapper m_pipelineLayout;
222     GraphicsPipelineWrapper m_graphicsPipelines[DepthTest::QUAD_COUNT];
223     GraphicsPipelineWrapper m_altGraphicsPipelines[DepthTest::QUAD_COUNT];
224 
225     Move<VkCommandPool> m_cmdPool;
226     Move<VkCommandBuffer> m_cmdBuffer;
227 };
228 
229 const float DepthTest::quadDepths[QUAD_COUNT] = {0.1f, 0.0f, 0.3f, 0.2f};
230 
231 // Depth values suitable for the depth range of -1..1.
232 const float DepthTest::quadDepthsMinusOneToOne[QUAD_COUNT] = {-0.8f, -1.0f, 0.6f, 0.2f};
233 
234 const float DepthTest::quadWs[QUAD_COUNT] = {2.0f, 1.25f, 0.5f, 0.25f};
235 
DepthTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const VkFormat depthFormat,const VkCompareOp depthCompareOps[QUAD_COUNT],const bool separateDepthStencilLayouts,const VkPrimitiveTopology primitiveTopology,const bool depthBoundsTestEnable,const float depthBoundsMin,const float depthBoundsMax,const bool depthTestEnable,const bool stencilTestEnable,const bool depthAttachmentBound,const bool colorAttachmentEnable,const bool hostVisible,const tcu::UVec2 renderSize,const DepthClipControlCase depthClipControl)236 DepthTest::DepthTest(tcu::TestContext &testContext, const std::string &name,
237                      const PipelineConstructionType pipelineConstructionType, const VkFormat depthFormat,
238                      const VkCompareOp depthCompareOps[QUAD_COUNT], const bool separateDepthStencilLayouts,
239                      const VkPrimitiveTopology primitiveTopology, const bool depthBoundsTestEnable,
240                      const float depthBoundsMin, const float depthBoundsMax, const bool depthTestEnable,
241                      const bool stencilTestEnable, const bool depthAttachmentBound, const bool colorAttachmentEnable,
242                      const bool hostVisible, const tcu::UVec2 renderSize, const DepthClipControlCase depthClipControl)
243     : vkt::TestCase(testContext, name)
244     , m_pipelineConstructionType(pipelineConstructionType)
245     , m_depthFormat(depthFormat)
246     , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
247     , m_primitiveTopology(primitiveTopology)
248     , m_depthBoundsTestEnable(depthBoundsTestEnable)
249     , m_depthBoundsMin(depthBoundsMin)
250     , m_depthBoundsMax(depthBoundsMax)
251     , m_depthTestEnable(depthTestEnable)
252     , m_stencilTestEnable(stencilTestEnable)
253     , m_depthAttachmentBound(depthAttachmentBound)
254     , m_colorAttachmentEnable(colorAttachmentEnable)
255     , m_hostVisible(hostVisible)
256     , m_renderSize(renderSize)
257     , m_depthClipControl(depthClipControl)
258 {
259     deMemcpy(m_depthCompareOps, depthCompareOps, sizeof(VkCompareOp) * QUAD_COUNT);
260 }
261 
~DepthTest(void)262 DepthTest::~DepthTest(void)
263 {
264 }
265 
checkSupport(Context & context) const266 void DepthTest::checkSupport(Context &context) const
267 {
268     if (m_depthBoundsTestEnable)
269         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_BOUNDS);
270 
271     if (m_depthAttachmentBound &&
272         !isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_depthFormat))
273         throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") + getFormatName(m_depthFormat));
274 
275     if (m_separateDepthStencilLayouts &&
276         !context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts"))
277         TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported");
278 
279     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
280                                           m_pipelineConstructionType);
281 
282 #ifndef CTS_USES_VULKANSC
283     if (m_depthClipControl != DepthClipControlCase::DISABLED &&
284         !context.isDeviceFunctionalitySupported("VK_EXT_depth_clip_control"))
285         TCU_THROW(NotSupportedError, "VK_EXT_depth_clip_control is not supported");
286 #endif // CTS_USES_VULKANSC
287 }
288 
createInstance(Context & context) const289 TestInstance *DepthTest::createInstance(Context &context) const
290 {
291     return new DepthTestInstance(context, m_pipelineConstructionType, m_depthFormat, m_depthCompareOps,
292                                  m_separateDepthStencilLayouts, m_primitiveTopology, m_depthBoundsTestEnable,
293                                  m_depthBoundsMin, m_depthBoundsMax, m_depthTestEnable, m_stencilTestEnable,
294                                  m_depthAttachmentBound, m_colorAttachmentEnable, m_hostVisible, m_renderSize,
295                                  m_depthClipControl);
296 }
297 
initPrograms(SourceCollections & programCollection) const298 void DepthTest::initPrograms(SourceCollections &programCollection) const
299 {
300     if (m_colorAttachmentEnable)
301     {
302         programCollection.glslSources.add("color_vert")
303             << glu::VertexSource("#version 310 es\n"
304                                  "layout(location = 0) in vec4 position;\n"
305                                  "layout(location = 1) in vec4 color;\n"
306                                  "layout(location = 0) out highp vec4 vtxColor;\n"
307                                  "void main (void)\n"
308                                  "{\n"
309                                  "    gl_Position = position;\n"
310                                  "    gl_PointSize = 1.0f;\n"
311                                  "    vtxColor = color;\n"
312                                  "}\n");
313 
314         programCollection.glslSources.add("color_frag")
315             << glu::FragmentSource("#version 310 es\n"
316                                    "layout(location = 0) in highp vec4 vtxColor;\n"
317                                    "layout(location = 0) out highp vec4 fragColor;\n"
318                                    "void main (void)\n"
319                                    "{\n"
320                                    "    fragColor = vtxColor;\n"
321                                    "}\n");
322     }
323     else
324     {
325         programCollection.glslSources.add("color_vert") << glu::VertexSource("#version 310 es\n"
326                                                                              "layout(location = 0) in vec4 position;\n"
327                                                                              "layout(location = 1) in vec4 color;\n"
328                                                                              "void main (void)\n"
329                                                                              "{\n"
330                                                                              "    gl_Position = position;\n"
331                                                                              "    gl_PointSize = 1.0f;\n"
332                                                                              "}\n");
333     }
334 }
335 
DepthTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const VkFormat depthFormat,const VkCompareOp depthCompareOps[DepthTest::QUAD_COUNT],const bool separateDepthStencilLayouts,const VkPrimitiveTopology primitiveTopology,const bool depthBoundsTestEnable,const float depthBoundsMin,const float depthBoundsMax,const bool depthTestEnable,const bool stencilTestEnable,const bool depthAttachmentBound,const bool colorAttachmentEnable,const bool hostVisible,const tcu::UVec2 renderSize,const DepthClipControlCase depthClipControl)336 DepthTestInstance::DepthTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
337                                      const VkFormat depthFormat,
338                                      const VkCompareOp depthCompareOps[DepthTest::QUAD_COUNT],
339                                      const bool separateDepthStencilLayouts,
340                                      const VkPrimitiveTopology primitiveTopology, const bool depthBoundsTestEnable,
341                                      const float depthBoundsMin, const float depthBoundsMax, const bool depthTestEnable,
342                                      const bool stencilTestEnable, const bool depthAttachmentBound,
343                                      const bool colorAttachmentEnable, const bool hostVisible,
344                                      const tcu::UVec2 renderSize, const DepthClipControlCase depthClipControl)
345     : vkt::TestInstance(context)
346     , m_renderSize(renderSize)
347     , m_colorFormat(colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
348     , m_depthFormat(depthFormat)
349     , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
350     , m_primitiveTopology(primitiveTopology)
351     , m_depthBoundsTestEnable(depthBoundsTestEnable)
352     , m_depthBoundsMin(depthBoundsMin)
353     , m_depthBoundsMax(depthBoundsMax)
354     , m_depthTestEnable(depthTestEnable)
355     , m_stencilTestEnable(stencilTestEnable)
356     , m_depthAttachmentBound(depthAttachmentBound)
357     , m_colorAttachmentEnable(colorAttachmentEnable)
358     , m_hostVisible(hostVisible)
359     , m_depthClipControl(depthClipControl)
360     , m_graphicsPipelines{{context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
361                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
362                           {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
363                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
364                           {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
365                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
366                           {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
367                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType}}
368     , m_altGraphicsPipelines{{context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
369                               context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType},
370                              {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
371                               context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType},
372                              {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
373                               context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType},
374                              {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
375                               context.getDevice(), m_context.getDeviceExtensions(), pipelineConstructionType}}
376 {
377     const DeviceInterface &vk       = context.getDeviceInterface();
378     const VkDevice vkDevice         = context.getDevice();
379     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
380     SimpleAllocator memAlloc(
381         vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
382     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
383                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
384     const bool hasDepthClipControl                = (m_depthClipControl != DepthClipControlCase::DISABLED);
385     const bool useAltGraphicsPipelines            = (m_depthClipControl == DepthClipControlCase::BEFORE_TWO_DYNAMICS ||
386                                           m_depthClipControl == DepthClipControlCase::NORMAL_W);
387     const bool useAltVertices                     = m_depthClipControl == DepthClipControlCase::NORMAL_W;
388 
389     // Copy depth operators
390     deMemcpy(m_depthCompareOps, depthCompareOps, sizeof(VkCompareOp) * DepthTest::QUAD_COUNT);
391 
392     // Create color image
393     if (m_colorAttachmentEnable)
394     {
395         const VkImageCreateInfo colorImageParams = {
396             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
397             nullptr,                                                               // const void* pNext;
398             0u,                                                                    // VkImageCreateFlags flags;
399             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
400             m_colorFormat,                                                         // VkFormat format;
401             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
402             1u,                                                                    // uint32_t mipLevels;
403             1u,                                                                    // uint32_t arrayLayers;
404             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
405             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
406             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
407             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
408             1u,                                                                    // uint32_t queueFamilyIndexCount;
409             &queueFamilyIndex,         // const uint32_t* pQueueFamilyIndices;
410             VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
411         };
412 
413         m_colorImage = createImage(vk, vkDevice, &colorImageParams);
414 
415         // Allocate and bind color image memory
416         m_colorImageAlloc =
417             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
418         VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
419                                     m_colorImageAlloc->getOffset()));
420     }
421 
422     // bind depth attachment or depth format should be undefined.
423     DE_ASSERT(m_depthAttachmentBound || m_depthFormat == VK_FORMAT_UNDEFINED);
424 
425     // Create depth image
426     if (m_depthAttachmentBound)
427     {
428         const VkImageCreateInfo depthImageParams = {
429             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,      // VkStructureType sType;
430             nullptr,                                  // const void* pNext;
431             0u,                                       // VkImageCreateFlags flags;
432             VK_IMAGE_TYPE_2D,                         // VkImageType imageType;
433             m_depthFormat,                            // VkFormat format;
434             {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
435             1u,                                       // uint32_t mipLevels;
436             1u,                                       // uint32_t arrayLayers;
437             VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
438             VK_IMAGE_TILING_OPTIMAL,                  // VkImageTiling tiling;
439             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
440             VK_SHARING_MODE_EXCLUSIVE,                                                     // VkSharingMode sharingMode;
441             1u,                        // uint32_t queueFamilyIndexCount;
442             &queueFamilyIndex,         // const uint32_t* pQueueFamilyIndices;
443             VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
444         };
445 
446         m_depthImage = createImage(vk, vkDevice, &depthImageParams);
447 
448         // Allocate and bind depth image memory
449         auto memReqs = MemoryRequirement::Local | MemoryRequirement::HostVisible;
450 #ifdef CTS_USES_VULKANSC
451         try
452 #endif // CTS_USES_VULKANSC
453         {
454             m_depthImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthImage),
455                                                   m_hostVisible ? memReqs : MemoryRequirement::Any);
456 #ifdef CTS_USES_VULKANSC
457         }
458         catch (const tcu::NotSupportedError &)
459         {
460             // For VulkanSC, let this allocation fall back to any memory, to
461             // avoid object counting getting out of sync between main and subprocess.
462             m_depthImageAlloc =
463                 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthImage), MemoryRequirement::Any);
464 #endif // CTS_USES_VULKANSC
465         }
466         VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthImage, m_depthImageAlloc->getMemory(),
467                                     m_depthImageAlloc->getOffset()));
468 
469         const VkImageAspectFlags aspect = (mapVkFormat(m_depthFormat).order == tcu::TextureFormat::DS ?
470                                                VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT :
471                                                VK_IMAGE_ASPECT_DEPTH_BIT);
472         m_depthImageSubresourceRange =
473             makeImageSubresourceRange(aspect, 0u, depthImageParams.mipLevels, 0u, depthImageParams.arrayLayers);
474     }
475 
476     // Create color attachment view
477     if (m_colorAttachmentEnable)
478     {
479         const VkImageViewCreateInfo colorAttachmentViewParams = {
480             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
481             nullptr,                                    // const void* pNext;
482             0u,                                         // VkImageViewCreateFlags flags;
483             *m_colorImage,                              // VkImage image;
484             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
485             m_colorFormat,                              // VkFormat format;
486             componentMappingRGBA,                       // VkComponentMapping components;
487             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
488         };
489 
490         m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
491     }
492 
493     // Create depth attachment view
494     if (m_depthAttachmentBound)
495     {
496         const VkImageViewCreateInfo depthAttachmentViewParams = {
497             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
498             nullptr,                                  // const void* pNext;
499             0u,                                       // VkImageViewCreateFlags flags;
500             *m_depthImage,                            // VkImage image;
501             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
502             m_depthFormat,                            // VkFormat format;
503             componentMappingRGBA,                     // VkComponentMapping components;
504             m_depthImageSubresourceRange,             // VkImageSubresourceRange subresourceRange;
505         };
506 
507         m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
508     }
509 
510     // Create render pass
511     m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat, m_depthFormat);
512 
513     // Create framebuffer
514     {
515         std::vector<VkImage> images;
516         std::vector<VkImageView> attachmentBindInfos;
517 
518         if (m_colorAttachmentEnable)
519         {
520             images.push_back(*m_colorImage);
521             attachmentBindInfos.push_back(*m_colorAttachmentView);
522         }
523 
524         if (m_depthAttachmentBound)
525         {
526             images.push_back(*m_depthImage);
527             attachmentBindInfos.push_back(*m_depthAttachmentView);
528         }
529 
530         const VkFramebufferCreateInfo framebufferParams = {
531             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
532             nullptr,                                   // const void* pNext;
533             0u,                                        // VkFramebufferCreateFlags flags;
534             *m_renderPass,                             // VkRenderPass renderPass;
535             (uint32_t)attachmentBindInfos.size(),      // uint32_t attachmentCount;
536             attachmentBindInfos.data(),                // const VkImageView* pAttachments;
537             (uint32_t)m_renderSize.x(),                // uint32_t width;
538             (uint32_t)m_renderSize.y(),                // uint32_t height;
539             1u                                         // uint32_t layers;
540         };
541 
542         m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
543     }
544 
545     // Create pipeline layout
546     {
547         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
548             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
549             nullptr,                                       // const void* pNext;
550             0u,                                            // VkPipelineLayoutCreateFlags flags;
551             0u,                                            // uint32_t setLayoutCount;
552             nullptr,                                       // const VkDescriptorSetLayout* pSetLayouts;
553             0u,                                            // uint32_t pushConstantRangeCount;
554             nullptr                                        // const VkPushConstantRange* pPushConstantRanges;
555         };
556 
557         m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
558     }
559 
560     // Shader modules
561     m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
562     if (m_colorAttachmentEnable)
563         m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
564 
565     const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
566     const std::vector<VkViewport> badViewports{makeViewport(0.0f, 0.0f, static_cast<float>(m_renderSize.x()) / 2.0f,
567                                                             static_cast<float>(m_renderSize.y()) / 2.0f, 1.0f, 0.0f)};
568     const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
569     const bool dynamicViewport =
570         (static_cast<int>(m_depthClipControl) > static_cast<int>(DepthClipControlCase::BEFORE_STATIC));
571 
572     // Create pipeline
573     {
574         const VkVertexInputBindingDescription vertexInputBindingDescription{
575             0u,                         // uint32_t binding;
576             sizeof(Vertex4RGBA),        // uint32_t strideInBytes;
577             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
578         };
579 
580         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2]{
581             {
582                 0u,                            // uint32_t location;
583                 0u,                            // uint32_t binding;
584                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
585                 0u                             // uint32_t offset;
586             },
587             {
588                 1u,                            // uint32_t location;
589                 0u,                            // uint32_t binding;
590                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
591                 offsetof(Vertex4RGBA, color),  // uint32_t offset;
592             }};
593 
594         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
595             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
596             nullptr,                                                   // const void* pNext;
597             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
598             1u,                                                        // uint32_t vertexBindingDescriptionCount;
599             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
600             2u,                              // uint32_t vertexAttributeDescriptionCount;
601             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
602         };
603 
604         const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams{
605             VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                                sType
606             nullptr,             // const void*                                    pNext
607             0u,                  // VkPipelineInputAssemblyStateCreateFlags        flags
608             m_primitiveTopology, // VkPrimitiveTopology                            topology
609             VK_FALSE             // VkBool32                                        primitiveRestartEnable
610         };
611 
612         VkPipelineDepthStencilStateCreateInfo depthStencilStateParams{
613             VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
614             nullptr,                                                    // const void* pNext;
615             0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
616             m_depthTestEnable,                                          // VkBool32 depthTestEnable;
617             true,                                                       // VkBool32 depthWriteEnable;
618             VK_COMPARE_OP_LESS,                                         // VkCompareOp depthCompareOp;
619             m_depthBoundsTestEnable,                                    // VkBool32 depthBoundsTestEnable;
620             m_stencilTestEnable,                                        // VkBool32 stencilTestEnable;
621             // VkStencilOpState front;
622             {
623                 VK_STENCIL_OP_KEEP,  // VkStencilOp failOp;
624                 VK_STENCIL_OP_KEEP,  // VkStencilOp passOp;
625                 VK_STENCIL_OP_KEEP,  // VkStencilOp depthFailOp;
626                 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
627                 0u,                  // uint32_t compareMask;
628                 0u,                  // uint32_t writeMask;
629                 0u,                  // uint32_t reference;
630             },
631             // VkStencilOpState back;
632             {
633                 VK_STENCIL_OP_KEEP,  // VkStencilOp failOp;
634                 VK_STENCIL_OP_KEEP,  // VkStencilOp passOp;
635                 VK_STENCIL_OP_KEEP,  // VkStencilOp depthFailOp;
636                 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
637                 0u,                  // uint32_t compareMask;
638                 0u,                  // uint32_t writeMask;
639                 0u,                  // uint32_t reference;
640             },
641             m_depthBoundsMin, // float minDepthBounds;
642             m_depthBoundsMax, // float maxDepthBounds;
643         };
644 
645         // Make sure rasterization is not disabled when the fragment shader is missing.
646         const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams{
647             vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
648             nullptr,                                                        // const void* pNext;
649             0u,                                  // VkPipelineRasterizationStateCreateFlags flags;
650             VK_FALSE,                            // VkBool32 depthClampEnable;
651             VK_FALSE,                            // VkBool32 rasterizerDiscardEnable;
652             vk::VK_POLYGON_MODE_FILL,            // VkPolygonMode polygonMode;
653             vk::VK_CULL_MODE_NONE,               // VkCullModeFlags cullMode;
654             vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
655             VK_FALSE,                            // VkBool32 depthBiasEnable;
656             0.0f,                                // float depthBiasConstantFactor;
657             0.0f,                                // float depthBiasClamp;
658             0.0f,                                // float depthBiasSlopeFactor;
659             1.0f,                                // float lineWidth;
660         };
661 
662         PipelineViewportDepthClipControlCreateInfoWrapper depthClipControlWrapper;
663         PipelineViewportDepthClipControlCreateInfoWrapper depthClipControl01Wrapper;
664 
665 #ifndef CTS_USES_VULKANSC
666         VkPipelineViewportDepthClipControlCreateInfoEXT depthClipControlCreateInfo{
667             VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT, // VkStructureType sType;
668             nullptr,                                                                // const void* pNext;
669             VK_TRUE,                                                                // VkBool32 negativeOneToOne;
670         };
671         if (hasDepthClipControl)
672             depthClipControlWrapper.ptr = &depthClipControlCreateInfo;
673 
674         // Using the range 0,1 in the structure.
675         VkPipelineViewportDepthClipControlCreateInfoEXT depthClipControlCreateInfo01{
676             VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT, // VkStructureType sType;
677             nullptr,                                                                // const void* pNext;
678             VK_FALSE,                                                               // VkBool32 negativeOneToOne;
679         };
680         depthClipControl01Wrapper.ptr = &depthClipControlCreateInfo01;
681 #endif // CTS_USES_VULKANSC
682 
683         // Dynamic viewport if needed.
684         std::vector<VkDynamicState> dynamicStates;
685 
686         if (m_depthClipControl == DepthClipControlCase::BEFORE_DYNAMIC ||
687             m_depthClipControl == DepthClipControlCase::BEFORE_TWO_DYNAMICS ||
688             m_depthClipControl == DepthClipControlCase::AFTER_DYNAMIC)
689         {
690             dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
691         }
692 
693         const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
694             VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
695             nullptr,                                              // const void* pNext;
696             0u,                                                   // VkPipelineDynamicStateCreateFlags flags;
697             static_cast<uint32_t>(dynamicStates.size()),          // uint32_t dynamicStateCount;
698             de::dataOrNull(dynamicStates),                        // const VkDynamicState* pDynamicStates;
699         };
700 
701         const vk::VkPipelineColorBlendAttachmentState blendState{
702             VK_FALSE,
703             VK_BLEND_FACTOR_ONE,
704             VK_BLEND_FACTOR_ONE,
705             VK_BLEND_OP_ADD,
706             VK_BLEND_FACTOR_ONE,
707             VK_BLEND_FACTOR_ONE,
708             VK_BLEND_OP_ADD,
709             VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
710         };
711 
712         uint32_t colorAttachmentCount = (m_colorFormat != VK_FORMAT_UNDEFINED) ? 1u : 0u;
713 
714         const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo{
715             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
716             nullptr,                 // const void*                                    pNext
717             0u,                      // VkPipelineColorBlendStateCreateFlags            flags
718             VK_FALSE,                // VkBool32                                        logicOpEnable
719             VK_LOGIC_OP_CLEAR,       // VkLogicOp                                    logicOp
720             colorAttachmentCount,    // uint32_t                                        attachmentCount
721             &blendState,             // const VkPipelineColorBlendAttachmentState*    pAttachments
722             {0.0f, 0.0f, 0.0f, 0.0f} // float                                        blendConstants[4]
723         };
724 
725         for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
726         {
727             depthStencilStateParams.depthCompareOp = depthCompareOps[quadNdx];
728 
729             m_graphicsPipelines[quadNdx]
730                 .setDefaultMultisampleState()
731                 .setDefaultColorBlendState()
732                 .setViewportStatePnext(depthClipControlWrapper.ptr)
733                 .setDynamicState(&dynamicStateCreateInfo)
734                 .setupVertexInputState(&vertexInputStateParams, &inputAssemblyStateParams)
735                 .setupPreRasterizationShaderState((dynamicViewport ? badViewports : viewports), scissors,
736                                                   m_pipelineLayout, *m_renderPass, 0u, m_vertexShaderModule,
737                                                   &rasterizationStateParams)
738                 .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
739                                           &depthStencilStateParams)
740                 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfo)
741                 .setMonolithicPipelineLayout(m_pipelineLayout)
742                 .buildPipeline();
743 
744             if (useAltGraphicsPipelines)
745             {
746                 if (m_depthClipControl == DepthClipControlCase::NORMAL_W)
747                 {
748                     m_altGraphicsPipelines[quadNdx]
749                         .setDefaultMultisampleState()
750                         .setDefaultColorBlendState()
751                         .setViewportStatePnext(depthClipControl01Wrapper.ptr)
752                         .setDynamicState(&dynamicStateCreateInfo)
753                         .setupVertexInputState(&vertexInputStateParams, &inputAssemblyStateParams)
754                         .setupPreRasterizationShaderState((dynamicViewport ? badViewports : viewports), scissors,
755                                                           m_pipelineLayout, *m_renderPass, 0u, m_vertexShaderModule,
756                                                           &rasterizationStateParams)
757                         .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
758                                                   &depthStencilStateParams)
759                         .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfo)
760                         .setMonolithicPipelineLayout(m_pipelineLayout)
761                         .buildPipeline();
762                 }
763                 else
764                 {
765                     m_altGraphicsPipelines[quadNdx]
766                         .setDefaultMultisampleState()
767                         .setDefaultColorBlendState()
768                         .setViewportStatePnext(depthClipControl01Wrapper.ptr)
769                         .setDynamicState(&dynamicStateCreateInfo)
770                         .setupVertexInputState(&vertexInputStateParams)
771                         .setupPreRasterizationShaderState((dynamicViewport ? badViewports : viewports), scissors,
772                                                           m_pipelineLayout, *m_renderPass, 0u, m_vertexShaderModule,
773                                                           &rasterizationStateParams)
774                         .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
775                                                   &depthStencilStateParams)
776                         .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfo)
777                         .setMonolithicPipelineLayout(m_pipelineLayout)
778                         .buildPipeline();
779                 }
780             }
781         }
782     }
783 
784     // Create vertex buffer
785     {
786         const VkBufferCreateInfo vertexBufferParams = {
787             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
788             nullptr,                              // const void* pNext;
789             0u,                                   // VkBufferCreateFlags flags;
790             1024u,                                // VkDeviceSize size;
791             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,    // VkBufferUsageFlags usage;
792             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
793             1u,                                   // uint32_t queueFamilyIndexCount;
794             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
795         };
796 
797         m_vertices          = createOverlappingQuads();
798         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
799         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
800                                                 MemoryRequirement::HostVisible);
801 
802         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
803                                      m_vertexBufferAlloc->getOffset()));
804 
805         if (useAltVertices)
806         {
807             m_altVertices          = createOverlappingQuads();
808             m_altVertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
809             m_altVertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_altVertexBuffer),
810                                                        MemoryRequirement::HostVisible);
811 
812             VK_CHECK(vk.bindBufferMemory(vkDevice, *m_altVertexBuffer, m_altVertexBufferAlloc->getMemory(),
813                                          m_altVertexBufferAlloc->getOffset()));
814         }
815 
816         // Adjust depths
817         for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
818             for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
819             {
820                 m_vertices[quadNdx * 6 + vertexNdx].position.z() =
821                     (hasDepthClipControl ? DepthTest::quadDepthsMinusOneToOne[quadNdx] :
822                                            DepthTest::quadDepths[quadNdx]);
823                 if (m_depthClipControl == DepthClipControlCase::NORMAL_W)
824                 {
825                     const float w = DepthTest::quadWs[quadNdx];
826                     m_vertices[quadNdx * 6 + vertexNdx].position.x() *= w;
827                     m_vertices[quadNdx * 6 + vertexNdx].position.y() *= w;
828                     m_vertices[quadNdx * 6 + vertexNdx].position.z() *= w;
829                     m_vertices[quadNdx * 6 + vertexNdx].position.w() = w;
830                 }
831                 if (useAltVertices)
832                 {
833                     m_altVertices[quadNdx * 6 + vertexNdx].position = m_vertices[quadNdx * 6 + vertexNdx].position;
834                     float z = m_altVertices[quadNdx * 6 + vertexNdx].position.z();
835                     float w = m_altVertices[quadNdx * 6 + vertexNdx].position.w();
836                     if (depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_NOT_EQUAL ||
837                         depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_LESS ||
838                         depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_LESS_OR_EQUAL)
839                     {
840                         z += 0.01f;
841                     }
842                     else if (depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_GREATER ||
843                              depthCompareOps[quadNdx] == vk::VK_COMPARE_OP_GREATER_OR_EQUAL)
844                     {
845                         z -= 0.01f;
846                     }
847                     m_altVertices[quadNdx * 6 + vertexNdx].position.z() = (z + w) * 0.5f;
848                 }
849             }
850 
851         // Load vertices into vertex buffer
852         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
853         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
854 
855         if (useAltVertices)
856         {
857             deMemcpy(m_altVertexBufferAlloc->getHostPtr(), m_altVertices.data(),
858                      m_altVertices.size() * sizeof(Vertex4RGBA));
859             flushAlloc(vk, vkDevice, *m_altVertexBufferAlloc);
860         }
861     }
862 
863     // Create command pool
864     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
865 
866     // Create command buffer
867     {
868         std::vector<VkClearValue> attachmentClearValues;
869 
870         if (m_colorAttachmentEnable)
871             attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
872 
873         if (m_depthAttachmentBound)
874         {
875             attachmentClearValues.push_back(defaultClearValue(m_depthFormat));
876         }
877 
878         const VkImageMemoryBarrier colorBarrier = {
879             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType            sType;
880             nullptr,                                    // const void*                pNext;
881             (VkAccessFlags)0,                           // VkAccessFlags              srcAccessMask;
882             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags              dstAccessMask;
883             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout              oldLayout;
884             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout              newLayout;
885             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                   srcQueueFamilyIndex;
886             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                   dstQueueFamilyIndex;
887             *m_colorImage,                              // VkImage                    image;
888             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange    subresourceRange;
889         };
890 
891         VkImageSubresourceRange depthBarrierSubresourceRange = m_depthImageSubresourceRange;
892         VkImageLayout newLayout                              = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
893         if (m_separateDepthStencilLayouts)
894         {
895             depthBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
896             newLayout                               = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
897         }
898 
899         const VkImageMemoryBarrier depthBarrier = {
900             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,       // VkStructureType            sType;
901             nullptr,                                      // const void*                pNext;
902             (VkAccessFlags)0,                             // VkAccessFlags              srcAccessMask;
903             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags              dstAccessMask;
904             VK_IMAGE_LAYOUT_UNDEFINED,                    // VkImageLayout              oldLayout;
905             newLayout,                                    // VkImageLayout              newLayout;
906             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                   srcQueueFamilyIndex;
907             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                   dstQueueFamilyIndex;
908             *m_depthImage,                                // VkImage                    image;
909             depthBarrierSubresourceRange,                 // VkImageSubresourceRange    subresourceRange;
910         };
911 
912         std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
913 
914         if (m_colorAttachmentEnable)
915             imageLayoutBarriers.push_back(colorBarrier);
916 
917         if (m_depthAttachmentBound)
918         {
919             imageLayoutBarriers.push_back(depthBarrier);
920         }
921 
922         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
923 
924         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
925 
926         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
927                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
928                                   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
929                                   VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
930                               (VkDependencyFlags)0, 0u, nullptr, 0u, nullptr, (uint32_t)imageLayoutBarriers.size(),
931                               imageLayoutBarriers.data());
932 
933         m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
934                            (uint32_t)attachmentClearValues.size(), attachmentClearValues.data());
935 
936         const VkDeviceSize quadOffset = (m_vertices.size() / DepthTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
937 
938         for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
939         {
940             VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
941 
942             if (m_depthClipControl == DepthClipControlCase::NORMAL_W &&
943                 depthCompareOps[quadNdx] != vk::VK_COMPARE_OP_NEVER)
944             {
945                 m_altGraphicsPipelines[quadNdx].bind(*m_cmdBuffer);
946                 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_altVertexBuffer.get(), &vertexBufferOffset);
947                 vk.cmdDraw(*m_cmdBuffer, (uint32_t)(m_altVertices.size() / DepthTest::QUAD_COUNT), 1, 0, 0);
948             }
949 
950             if (m_depthClipControl == DepthClipControlCase::BEFORE_STATIC ||
951                 m_depthClipControl == DepthClipControlCase::BEFORE_DYNAMIC ||
952                 m_depthClipControl == DepthClipControlCase::BEFORE_TWO_DYNAMICS)
953             {
954                 if (vk::isConstructionTypeShaderObject(pipelineConstructionType))
955                 {
956 #ifndef CTS_USES_VULKANSC
957                     vk.cmdSetViewportWithCount(*m_cmdBuffer, 1u, viewports.data());
958 #else
959                     vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1u, viewports.data());
960 #endif
961                 }
962                 else
963                 {
964                     vk.cmdSetViewport(*m_cmdBuffer, 0u, 1u, viewports.data());
965                 }
966             }
967 
968             if (m_depthClipControl == DepthClipControlCase::BEFORE_TWO_DYNAMICS)
969                 m_altGraphicsPipelines[quadNdx].bind(*m_cmdBuffer);
970             m_graphicsPipelines[quadNdx].bind(*m_cmdBuffer);
971 
972             if (m_depthClipControl == DepthClipControlCase::AFTER_DYNAMIC)
973             {
974                 if (vk::isConstructionTypeShaderObject(pipelineConstructionType))
975                 {
976 #ifndef CTS_USES_VULKANSC
977                     vk.cmdSetViewportWithCount(*m_cmdBuffer, 1u, viewports.data());
978 #else
979                     vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1u, viewports.data());
980 #endif
981                 }
982                 else
983                 {
984                     vk.cmdSetViewport(*m_cmdBuffer, 0u, 1u, viewports.data());
985                 }
986             }
987 
988             vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
989             vk.cmdDraw(*m_cmdBuffer, (uint32_t)(m_vertices.size() / DepthTest::QUAD_COUNT), 1, 0, 0);
990         }
991 
992         m_renderPass.end(vk, *m_cmdBuffer);
993         endCommandBuffer(vk, *m_cmdBuffer);
994     }
995 }
996 
~DepthTestInstance(void)997 DepthTestInstance::~DepthTestInstance(void)
998 {
999 }
1000 
iterate(void)1001 tcu::TestStatus DepthTestInstance::iterate(void)
1002 {
1003     const DeviceInterface &vk = m_context.getDeviceInterface();
1004     const VkDevice vkDevice   = m_context.getDevice();
1005     const VkQueue queue       = m_context.getUniversalQueue();
1006 
1007     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1008 
1009     return verifyImage();
1010 }
1011 
verifyImage(void)1012 tcu::TestStatus DepthTestInstance::verifyImage(void)
1013 {
1014     const tcu::TextureFormat tcuColorFormat = mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
1015     const tcu::TextureFormat tcuDepthFormat =
1016         m_depthAttachmentBound ? mapVkFormat(m_depthFormat) : tcu::TextureFormat();
1017 
1018     const ColorVertexShader vertexShader;
1019     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuDepthFormat,
1020                                              (m_depthClipControl != DepthClipControlCase::DISABLED));
1021     const rr::Program program(&vertexShader, &fragmentShader);
1022     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1023     bool colorCompareOk = false;
1024     bool depthCompareOk = false;
1025 
1026     // Render reference image
1027     {
1028         for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
1029         {
1030             // Set depth state
1031             rr::RenderState renderState(refRenderer.getViewportState(),
1032                                         m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1033             renderState.fragOps.depthTestEnabled = m_depthTestEnable;
1034             renderState.fragOps.depthFunc        = mapVkCompareOp(m_depthCompareOps[quadNdx]);
1035             if (m_depthBoundsTestEnable)
1036             {
1037                 renderState.fragOps.depthBoundsTestEnabled = true;
1038                 renderState.fragOps.minDepthBound          = m_depthBoundsMin;
1039                 renderState.fragOps.maxDepthBound          = m_depthBoundsMax;
1040             }
1041 
1042             refRenderer.draw(
1043                 renderState, mapVkPrimitiveTopology(m_primitiveTopology),
1044                 std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6, m_vertices.begin() + (quadNdx + 1) * 6));
1045         }
1046     }
1047 
1048     // Compare color result with reference image
1049     if (m_colorAttachmentEnable)
1050     {
1051         const DeviceInterface &vk       = m_context.getDeviceInterface();
1052         const VkDevice vkDevice         = m_context.getDevice();
1053         const VkQueue queue             = m_context.getUniversalQueue();
1054         const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1055         SimpleAllocator allocator(
1056             vk, vkDevice,
1057             getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1058         de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
1059                                                                     *m_colorImage, m_colorFormat, m_renderSize);
1060 
1061         colorCompareOk = tcu::intThresholdPositionDeviationCompare(
1062             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
1063             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
1064     }
1065     else
1066     {
1067         colorCompareOk = true;
1068     }
1069 
1070     // Compare depth result with reference image
1071     if (m_depthAttachmentBound)
1072     {
1073         const DeviceInterface &vk       = m_context.getDeviceInterface();
1074         const VkDevice vkDevice         = m_context.getDevice();
1075         const VkQueue queue             = m_context.getUniversalQueue();
1076         const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1077         SimpleAllocator allocator(
1078             vk, vkDevice,
1079             getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1080         de::MovePtr<tcu::TextureLevel> result = readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
1081                                                                     *m_depthImage, m_depthFormat, m_renderSize);
1082 
1083         {
1084             de::MovePtr<tcu::TextureLevel> convertedReferenceLevel;
1085             tcu::Maybe<tcu::TextureFormat> convertedFormat;
1086 
1087             if (refRenderer.getDepthStencilAccess().getFormat().type == tcu::TextureFormat::UNSIGNED_INT_24_8_REV)
1088             {
1089                 convertedFormat = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT24);
1090             }
1091             else if (refRenderer.getDepthStencilAccess().getFormat().type == tcu::TextureFormat::UNSIGNED_INT_16_8_8)
1092             {
1093                 convertedFormat = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
1094             }
1095             else if (refRenderer.getDepthStencilAccess().getFormat().type ==
1096                      tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
1097             {
1098                 convertedFormat = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
1099             }
1100 
1101             if (convertedFormat)
1102             {
1103                 convertedReferenceLevel = de::MovePtr<tcu::TextureLevel>(
1104                     new tcu::TextureLevel(*convertedFormat, refRenderer.getDepthStencilAccess().getSize().x(),
1105                                           refRenderer.getDepthStencilAccess().getSize().y()));
1106                 tcu::copy(convertedReferenceLevel->getAccess(), refRenderer.getDepthStencilAccess());
1107             }
1108 
1109             float depthThreshold = 0.0f;
1110 
1111             if (tcu::getTextureChannelClass(result->getFormat().type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
1112             {
1113                 const tcu::IVec4 formatBits = tcu::getTextureFormatBitDepth(result->getFormat());
1114                 depthThreshold              = 1.0f / static_cast<float>((1 << formatBits[0]) - 1);
1115             }
1116             else if (tcu::getTextureChannelClass(result->getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1117             {
1118                 depthThreshold = 0.0000001f;
1119             }
1120             else
1121                 TCU_FAIL("unrecognized format type class");
1122 
1123             depthCompareOk = tcu::floatThresholdCompare(
1124                 m_context.getTestContext().getLog(), "DepthImageCompare", "Depth image comparison",
1125                 convertedReferenceLevel ? convertedReferenceLevel->getAccess() : refRenderer.getDepthStencilAccess(),
1126                 result->getAccess(), tcu::Vec4(depthThreshold, 0.0f, 0.0f, 0.0f), tcu::COMPARE_LOG_RESULT);
1127         }
1128     }
1129     else
1130     {
1131         depthCompareOk = true;
1132     }
1133 
1134     if (colorCompareOk && depthCompareOk)
1135         return tcu::TestStatus::pass("Result image matches reference");
1136     else
1137         return tcu::TestStatus::fail("Image mismatch");
1138 }
1139 
getFormatCaseName(const VkFormat format)1140 std::string getFormatCaseName(const VkFormat format)
1141 {
1142     const std::string fullName = getFormatName(format);
1143 
1144     DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
1145 
1146     return de::toLower(fullName.substr(10));
1147 }
1148 
getTopologyName(const VkPrimitiveTopology topology)1149 std::string getTopologyName(const VkPrimitiveTopology topology)
1150 {
1151     const std::string fullName = getPrimitiveTopologyName(topology);
1152 
1153     DE_ASSERT(de::beginsWith(fullName, "VK_PRIMITIVE_TOPOLOGY_"));
1154 
1155     return de::toLower(fullName.substr(22));
1156 }
1157 
getCompareOpsName(const VkCompareOp quadDepthOps[DepthTest::QUAD_COUNT])1158 std::string getCompareOpsName(const VkCompareOp quadDepthOps[DepthTest::QUAD_COUNT])
1159 {
1160     std::ostringstream name;
1161 
1162     for (int quadNdx = 0; quadNdx < DepthTest::QUAD_COUNT; quadNdx++)
1163     {
1164         const std::string fullOpName = getCompareOpName(quadDepthOps[quadNdx]);
1165 
1166         DE_ASSERT(de::beginsWith(fullOpName, "VK_COMPARE_OP_"));
1167 
1168         name << de::toLower(fullOpName.substr(14));
1169 
1170         if (quadNdx < DepthTest::QUAD_COUNT - 1)
1171             name << "_";
1172     }
1173 
1174     return name.str();
1175 }
1176 
1177 } // namespace
1178 
createDepthTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1179 tcu::TestCaseGroup *createDepthTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
1180 {
1181     const auto genFormatTests =
1182         (!vk::isConstructionTypeShaderObject(pipelineConstructionType) ||
1183          pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV);
1184 
1185     const VkFormat depthFormats[] = {VK_FORMAT_D16_UNORM,         VK_FORMAT_X8_D24_UNORM_PACK32,
1186                                      VK_FORMAT_D32_SFLOAT,        VK_FORMAT_D16_UNORM_S8_UINT,
1187                                      VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
1188 
1189     // Each entry configures the depth compare operators of QUAD_COUNT quads.
1190     // All entries cover pair-wise combinations of compare operators.
1191     const VkCompareOp depthOps[][DepthTest::QUAD_COUNT] = {
1192         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL},
1193         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER},
1194         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS_OR_EQUAL},
1195         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL,
1196          VK_COMPARE_OP_GREATER_OR_EQUAL},
1197         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS},
1198         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS},
1199         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER},
1200         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL},
1201         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS},
1202         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL},
1203         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER},
1204         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL},
1205         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_EQUAL},
1206         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_ALWAYS},
1207         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL},
1208         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS},
1209         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_ALWAYS},
1210         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER},
1211         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL},
1212         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER_OR_EQUAL},
1213         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NEVER},
1214         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL,
1215          VK_COMPARE_OP_GREATER},
1216         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS_OR_EQUAL},
1217         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NOT_EQUAL},
1218         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL},
1219         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL,
1220          VK_COMPARE_OP_LESS_OR_EQUAL},
1221         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS},
1222         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_EQUAL},
1223         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_NEVER},
1224         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL,
1225          VK_COMPARE_OP_LESS_OR_EQUAL},
1226         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_EQUAL},
1227         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS},
1228         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_ALWAYS},
1229         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL},
1230         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NEVER},
1231         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER_OR_EQUAL},
1232         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS_OR_EQUAL},
1233         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NEVER},
1234         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_EQUAL},
1235         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NOT_EQUAL},
1236         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_ALWAYS},
1237         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_ALWAYS},
1238         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS},
1239         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_EQUAL},
1240         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER},
1241         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_NOT_EQUAL},
1242         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL},
1243         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER_OR_EQUAL},
1244         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NEVER},
1245         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS},
1246         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_ALWAYS},
1247         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER},
1248         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_EQUAL},
1249         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NOT_EQUAL},
1250         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_LESS},
1251         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NEVER},
1252         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_NOT_EQUAL},
1253         {VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_EQUAL},
1254         {VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL},
1255         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER},
1256         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NEVER},
1257         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_GREATER},
1258         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NOT_EQUAL},
1259         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_ALWAYS},
1260         {VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER},
1261         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER},
1262         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL},
1263         {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL,
1264          VK_COMPARE_OP_LESS_OR_EQUAL},
1265         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS},
1266         {VK_COMPARE_OP_GREATER_OR_EQUAL, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_NEVER},
1267         {VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_EQUAL, VK_COMPARE_OP_EQUAL},
1268         {VK_COMPARE_OP_NEVER, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_GREATER_OR_EQUAL},
1269         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS},
1270         {VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_LESS_OR_EQUAL, VK_COMPARE_OP_NOT_EQUAL, VK_COMPARE_OP_GREATER}};
1271 
1272     const bool colorAttachmentEnabled[] = {true, false};
1273 
1274     const VkPrimitiveTopology primitiveTopologies[] = {
1275         VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST};
1276 
1277     de::MovePtr<tcu::TestCaseGroup> depthTests(new tcu::TestCaseGroup(testCtx, "depth"));
1278     de::MovePtr<tcu::TestCaseGroup> noColorAttachmentTests(new tcu::TestCaseGroup(testCtx, "nocolor"));
1279 
1280     // Tests for format features
1281     if (!isConstructionTypeLibrary(pipelineConstructionType) &&
1282         !isConstructionTypeShaderObject(pipelineConstructionType))
1283     {
1284         de::MovePtr<tcu::TestCaseGroup> formatFeaturesTests(new tcu::TestCaseGroup(testCtx, "format_features"));
1285 
1286         // Formats that must be supported in all implementations
1287         addFunctionCase(formatFeaturesTests.get(), "support_d16_unorm", testSupportsDepthStencilFormat,
1288                         VK_FORMAT_D16_UNORM);
1289 
1290         // Sets where at least one of the formats must be supported
1291         const VkFormat depthOnlyFormats[]    = {VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT};
1292         const VkFormat depthStencilFormats[] = {VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
1293 
1294         addFunctionCase(
1295             formatFeaturesTests.get(), "support_d24_unorm_or_d32_sfloat", testSupportsAtLeastOneDepthStencilFormat,
1296             std::vector<VkFormat>(depthOnlyFormats, depthOnlyFormats + DE_LENGTH_OF_ARRAY(depthOnlyFormats)));
1297 
1298         addFunctionCase(
1299             formatFeaturesTests.get(), "support_d24_unorm_s8_uint_or_d32_sfloat_s8_uint",
1300             testSupportsAtLeastOneDepthStencilFormat,
1301             std::vector<VkFormat>(depthStencilFormats, depthStencilFormats + DE_LENGTH_OF_ARRAY(depthStencilFormats)));
1302 
1303         depthTests->addChild(formatFeaturesTests.release());
1304     }
1305 
1306     for (uint32_t colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled);
1307          colorAttachmentEnabledIdx++)
1308     {
1309         const bool colorEnabled = colorAttachmentEnabled[colorAttachmentEnabledIdx];
1310 
1311         // Tests for format and compare operators
1312         if (genFormatTests)
1313         {
1314             // Uses different depth formats
1315             de::MovePtr<tcu::TestCaseGroup> formatTests(new tcu::TestCaseGroup(testCtx, "format"));
1316 
1317             for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthFormats); formatNdx++)
1318             {
1319                 const bool hasDepth   = tcu::hasDepthComponent(mapVkFormat(depthFormats[formatNdx]).order);
1320                 const bool hasStencil = tcu::hasStencilComponent(mapVkFormat(depthFormats[formatNdx]).order);
1321                 const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
1322 
1323                 for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount;
1324                      ++separateDepthStencilLayouts)
1325                 {
1326                     const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
1327 
1328                     de::MovePtr<tcu::TestCaseGroup> formatTest(
1329                         new tcu::TestCaseGroup(testCtx, (getFormatCaseName(depthFormats[formatNdx]) +
1330                                                          ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : ""))
1331                                                             .c_str()));
1332                     // Combines depth compare operators
1333                     de::MovePtr<tcu::TestCaseGroup> compareOpsTests(new tcu::TestCaseGroup(testCtx, "compare_ops"));
1334 
1335                     for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(primitiveTopologies); topologyNdx++)
1336                     {
1337                         const std::string topologyName = getTopologyName(primitiveTopologies[topologyNdx]) + "_";
1338                         for (size_t opsNdx = 0; opsNdx < DE_LENGTH_OF_ARRAY(depthOps); opsNdx++)
1339                         {
1340                             compareOpsTests->addChild(new DepthTest(
1341                                 testCtx, topologyName + getCompareOpsName(depthOps[opsNdx]), pipelineConstructionType,
1342                                 depthFormats[formatNdx], depthOps[opsNdx], useSeparateDepthStencilLayouts,
1343                                 primitiveTopologies[topologyNdx], false, 0.0f, 1.0f));
1344 
1345                             compareOpsTests->addChild(new DepthTest(
1346                                 testCtx, topologyName + getCompareOpsName(depthOps[opsNdx]) + "_depth_bounds_test",
1347                                 pipelineConstructionType, depthFormats[formatNdx], depthOps[opsNdx],
1348                                 useSeparateDepthStencilLayouts, primitiveTopologies[topologyNdx], true, 0.1f, 0.25f,
1349                                 true, false, true, colorEnabled));
1350                         }
1351                     }
1352                     // Special VkPipelineDepthStencilStateCreateInfo known to have issues
1353                     {
1354                         const VkCompareOp depthOpsSpecial[DepthTest::QUAD_COUNT] = {
1355                             VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER, VK_COMPARE_OP_NEVER};
1356 
1357                         compareOpsTests->addChild(new DepthTest(
1358                             testCtx, "never_zerodepthbounds_depthdisabled_stencilenabled", pipelineConstructionType,
1359                             depthFormats[formatNdx], depthOpsSpecial, useSeparateDepthStencilLayouts,
1360                             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, true, 0.0f, 0.0f, false, true, true, colorEnabled));
1361                     }
1362                     formatTest->addChild(compareOpsTests.release());
1363 
1364                     // Test case with depth test enabled, but depth write disabled
1365                     de::MovePtr<tcu::TestCaseGroup> depthTestDisabled(
1366                         new tcu::TestCaseGroup(testCtx, "depth_test_disabled"));
1367                     {
1368                         const VkCompareOp depthOpsDepthTestDisabled[DepthTest::QUAD_COUNT] = {
1369                             VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS};
1370                         depthTestDisabled->addChild(new DepthTest(
1371                             testCtx, "depth_write_enabled", pipelineConstructionType, depthFormats[formatNdx],
1372                             depthOpsDepthTestDisabled, useSeparateDepthStencilLayouts,
1373                             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false, /* depthBoundsTestEnable */
1374                             0.0f,                                       /* depthBoundMin*/
1375                             1.0f,                                       /* depthBoundMax*/
1376                             false,                                      /* depthTestEnable */
1377                             false,                                      /* stencilTestEnable */
1378                             true,                                       /* depthAttachmentBound */
1379                             colorEnabled /* colorAttachmentEnable */));
1380                     }
1381                     formatTest->addChild(depthTestDisabled.release());
1382 
1383                     // Test case with depth buffer placed in local memory
1384                     de::MovePtr<tcu::TestCaseGroup> hostVisibleTests(new tcu::TestCaseGroup(testCtx, "host_visible"));
1385                     {
1386                         const VkCompareOp hostVisibleOps[DepthTest::QUAD_COUNT] = {
1387                             VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS};
1388 
1389                         // Depth buffer placed in local memory
1390                         hostVisibleTests->addChild(
1391                             new DepthTest(testCtx, "local_memory_depth_buffer", pipelineConstructionType,
1392                                           depthFormats[formatNdx], hostVisibleOps, useSeparateDepthStencilLayouts,
1393                                           VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false, /* depthBoundsTestEnable */
1394                                           0.0f,                                       /* depthBoundMin*/
1395                                           1.0f,                                       /* depthBoundMax*/
1396                                           true,                                       /* depthTestEnable */
1397                                           false,                                      /* stencilTestEnable */
1398                                           true,                                       /* depthAttachmentBound */
1399                                           colorEnabled,                               /* colorAttachmentEnable */
1400                                           true,                                       /* hostVisible */
1401                                           tcu::UVec2(256, 256) /*renderSize*/));
1402                     }
1403 
1404                     formatTest->addChild(hostVisibleTests.release());
1405                     formatTests->addChild(formatTest.release());
1406                 }
1407             }
1408 
1409             if (colorEnabled)
1410                 depthTests->addChild(formatTests.release());
1411             else
1412                 noColorAttachmentTests->addChild(formatTests.release());
1413         }
1414     }
1415     if (genFormatTests)
1416         depthTests->addChild(noColorAttachmentTests.release());
1417 
1418     // no depth attachment bound test.
1419     if (!vk::isConstructionTypeShaderObject(pipelineConstructionType))
1420     {
1421         de::MovePtr<tcu::TestCaseGroup> depthBoundTestNoDepthAttachment(
1422             new tcu::TestCaseGroup(testCtx, "no_depth_attachment"));
1423         {
1424             const VkCompareOp depthOpsDepthTestDisabled[DepthTest::QUAD_COUNT] = {
1425                 VK_COMPARE_OP_NEVER, VK_COMPARE_OP_LESS, VK_COMPARE_OP_GREATER, VK_COMPARE_OP_ALWAYS};
1426             depthBoundTestNoDepthAttachment->addChild(new DepthTest(
1427                 testCtx, "depth_bound_test", pipelineConstructionType, VK_FORMAT_UNDEFINED, depthOpsDepthTestDisabled,
1428                 false, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, true, /* depthBoundsTestEnable */
1429                 0.1f,                                             /* depthBoundMin*/
1430                 0.2f,                                             /* depthBoundMax*/
1431                 false,                                            /* depthTestEnable */
1432                 false,                                            /* stencilTestEnable */
1433                 false,                                            /* depthAttachmentBound */
1434                 true /* colorAttachmentEnable */));
1435         }
1436         depthTests->addChild(depthBoundTestNoDepthAttachment.release());
1437     }
1438 
1439 #ifndef CTS_USES_VULKANSC
1440     de::MovePtr<tcu::TestCaseGroup> depthClipControlTests(new tcu::TestCaseGroup(testCtx, "depth_clip_control"));
1441     {
1442         const VkCompareOp compareOps[] = {VK_COMPARE_OP_ALWAYS, VK_COMPARE_OP_LESS};
1443 
1444         const struct
1445         {
1446             const DepthClipControlCase viewportCase;
1447             const std::string suffix;
1448         } kViewportCases[] = {
1449             {DepthClipControlCase::NORMAL, ""},
1450             {DepthClipControlCase::NORMAL_W, "_different_w"},
1451             {DepthClipControlCase::BEFORE_STATIC, "_viewport_before_static"},
1452             {DepthClipControlCase::BEFORE_DYNAMIC, "_viewport_before_dynamic"},
1453             {DepthClipControlCase::BEFORE_TWO_DYNAMICS, "_viewport_before_two_dynamic"},
1454             {DepthClipControlCase::AFTER_DYNAMIC, "_viewport_after_dynamic"},
1455         };
1456 
1457         for (const auto &viewportCase : kViewportCases)
1458             for (const auto &format : depthFormats)
1459                 for (const auto &compareOp : compareOps)
1460                 {
1461                     std::string testName = getFormatCaseName(format) + "_" +
1462                                            de::toLower(std::string(getCompareOpName(compareOp)).substr(14)) +
1463                                            viewportCase.suffix;
1464 
1465                     const VkCompareOp ops[DepthTest::QUAD_COUNT] = {compareOp, compareOp, compareOp, compareOp};
1466                     depthClipControlTests->addChild(new DepthTest(testCtx, testName, pipelineConstructionType, format,
1467                                                                   ops, false, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1468                                                                   false, 0.0f, 1.0f, true, false, true, true, false,
1469                                                                   tcu::UVec2(32, 32), viewportCase.viewportCase));
1470                 }
1471     }
1472     depthTests->addChild(depthClipControlTests.release());
1473 #endif // CTS_USES_VULKANSC
1474 
1475     return depthTests.release();
1476 }
1477 
1478 } // namespace pipeline
1479 } // namespace vkt
1480