1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2021 Valve Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests using depth/stencil images as descriptors.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktImageDepthStencilDescriptorTests.hpp"
26 
27 #include "vkBarrierUtil.hpp"
28 #include "vkTypeUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkImageWithMemory.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkBufferWithMemory.hpp"
36 
37 #include "tcuMaybe.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuImageCompare.hpp"
40 
41 #include "deUniquePtr.hpp"
42 #include "deStringUtil.hpp"
43 
44 #include <iterator>
45 #include <vector>
46 #include <sstream>
47 #include <string>
48 
49 namespace vkt
50 {
51 namespace image
52 {
53 
54 namespace
55 {
56 
57 using namespace vk;
58 
getExtent()59 VkExtent3D getExtent()
60 {
61     return makeExtent3D(8u, 8u, 1u);
62 }
63 
getColorBufferFormat()64 VkFormat getColorBufferFormat()
65 {
66     return VK_FORMAT_R8G8B8A8_UNORM;
67 }
68 
getFloatStorageFormat()69 VkFormat getFloatStorageFormat()
70 {
71     return VK_FORMAT_R32_SFLOAT;
72 }
73 
getUintStorageFormat()74 VkFormat getUintStorageFormat()
75 {
76     return VK_FORMAT_R32_UINT;
77 }
78 
layoutExtension(VkImageLayout layout)79 tcu::Maybe<std::string> layoutExtension(VkImageLayout layout)
80 {
81     std::string extension;
82 
83     switch (layout)
84     {
85     case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
86     case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
87         extension = "VK_KHR_maintenance2";
88         break;
89     case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
90     case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
91         // Note: we will not be using separate depth/stencil layouts. There's a separate group of tests for that.
92         extension = "VK_KHR_separate_depth_stencil_layouts";
93         break;
94     default:
95         DE_ASSERT(false);
96         break;
97     }
98 
99     if (!extension.empty())
100         return tcu::just(extension);
101     return tcu::Nothing;
102 }
103 
104 // Types of access for an image aspect.
105 enum class AspectAccess
106 {
107     NONE = 0,
108     RO   = 1, // Different subtypes, see below.
109     RW   = 2, // This always means a normal read/write depth/stencil attachment (NOT a storage image).
110 };
111 
operator <<(std::ostream & stream,AspectAccess access)112 std::ostream &operator<<(std::ostream &stream, AspectAccess access)
113 {
114     if (access == AspectAccess::NONE)
115         stream << "none";
116     else if (access == AspectAccess::RO)
117         stream << "ro";
118     else if (access == AspectAccess::RW)
119         stream << "rw";
120     else
121         DE_ASSERT(false);
122 
123     return stream;
124 }
125 
126 // Types of read-only accesses.
127 enum class ReadOnlyAccess
128 {
129     DS_ATTACHMENT    = 0, // Depth/stencil attachment but read-only (writes not enabled).
130     INPUT_ATTACHMENT = 1, // Input attachment in the set.
131     SAMPLED          = 2, // Sampled image.
132 };
133 
operator <<(std::ostream & stream,ReadOnlyAccess access)134 std::ostream &operator<<(std::ostream &stream, ReadOnlyAccess access)
135 {
136     if (access == ReadOnlyAccess::DS_ATTACHMENT)
137         stream << "att";
138     else if (access == ReadOnlyAccess::INPUT_ATTACHMENT)
139         stream << "ia";
140     else if (access == ReadOnlyAccess::SAMPLED)
141         stream << "sampled";
142     else
143         DE_ASSERT(false);
144 
145     return stream;
146 }
147 
148 // A given layout gives different accesses to each aspect.
getLegalAccess(VkImageLayout layout,VkImageAspectFlagBits aspect)149 AspectAccess getLegalAccess(VkImageLayout layout, VkImageAspectFlagBits aspect)
150 {
151     DE_ASSERT(aspect == VK_IMAGE_ASPECT_DEPTH_BIT || aspect == VK_IMAGE_ASPECT_STENCIL_BIT);
152 
153     if (layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
154         return ((aspect == VK_IMAGE_ASPECT_STENCIL_BIT) ? AspectAccess::RW : AspectAccess::RO);
155     else if (layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
156         return ((aspect == VK_IMAGE_ASPECT_DEPTH_BIT) ? AspectAccess::RW : AspectAccess::RO);
157     else if (layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL)
158         return ((aspect == VK_IMAGE_ASPECT_DEPTH_BIT) ? AspectAccess::RO : AspectAccess::NONE);
159     else if (layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)
160         return ((aspect == VK_IMAGE_ASPECT_STENCIL_BIT) ? AspectAccess::RO : AspectAccess::NONE);
161 
162     DE_ASSERT(false);
163     return AspectAccess::NONE; // Unreachable.
164 }
165 
166 using ROAccessVec = std::vector<ReadOnlyAccess>;
167 
operator <<(std::ostream & stream,const ROAccessVec & vec)168 std::ostream &operator<<(std::ostream &stream, const ROAccessVec &vec)
169 {
170     for (size_t i = 0u; i < vec.size(); ++i)
171         stream << ((i > 0u) ? "_" : "") << vec[i];
172     return stream;
173 }
174 
175 // We cannot access depth/stencil images both as a depth/stencil attachment and an input attachment at the same time if they have
176 // both aspects, because input attachments can only have one aspect.
incompatibleInputAttachmentAccess(AspectAccess depthAccess,const ROAccessVec * depthROAccesses,AspectAccess stencilAccess,const ROAccessVec * stencilROAccesses)177 bool incompatibleInputAttachmentAccess(AspectAccess depthAccess, const ROAccessVec *depthROAccesses,
178                                        AspectAccess stencilAccess, const ROAccessVec *stencilROAccesses)
179 {
180     const bool depthAsDSAttachment =
181         (depthAccess == AspectAccess::RW ||
182          (depthAccess == AspectAccess::RO &&
183           de::contains(begin(*depthROAccesses), end(*depthROAccesses), ReadOnlyAccess::DS_ATTACHMENT)));
184     const bool stencilAsDSAttachment =
185         (stencilAccess == AspectAccess::RW ||
186          (stencilAccess == AspectAccess::RO &&
187           de::contains(begin(*stencilROAccesses), end(*stencilROAccesses), ReadOnlyAccess::DS_ATTACHMENT)));
188     const bool depthAsInputAttachment =
189         (depthAccess == AspectAccess::RO &&
190          de::contains(begin(*depthROAccesses), end(*depthROAccesses), ReadOnlyAccess::INPUT_ATTACHMENT));
191     const bool stencilAsInputAttachment =
192         (stencilAccess == AspectAccess::RO &&
193          de::contains(begin(*stencilROAccesses), end(*stencilROAccesses), ReadOnlyAccess::INPUT_ATTACHMENT));
194 
195     return ((depthAsDSAttachment && stencilAsInputAttachment) || (stencilAsDSAttachment && depthAsInputAttachment));
196 }
197 
getReadOnlyUsageFlags(const ROAccessVec & readOnlyAccesses)198 VkImageUsageFlags getReadOnlyUsageFlags(const ROAccessVec &readOnlyAccesses)
199 {
200     VkImageUsageFlags usageFlags = 0u;
201 
202     for (const auto &access : readOnlyAccesses)
203     {
204         if (access == ReadOnlyAccess::DS_ATTACHMENT)
205             usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
206         else if (access == ReadOnlyAccess::INPUT_ATTACHMENT)
207             usageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
208         else if (access == ReadOnlyAccess::SAMPLED)
209             usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
210         else
211             DE_ASSERT(false);
212     }
213 
214     return usageFlags;
215 }
216 
217 // Resources needed for an aspect that will be used as a descriptor in shaders (sampled or input attachment).
218 struct InputOutputDescriptor
219 {
220     uint32_t binding;
221     tcu::Maybe<uint32_t> inputAttachmentIndex;
222     VkImageAspectFlagBits aspect;
223 };
224 
225 using IODescVec = std::vector<InputOutputDescriptor>;
226 
227 // Test parameters.
228 struct TestParams
229 {
230     VkFormat format;            // Image format.
231     VkImageLayout layout;       // Layout being tested.
232     AspectAccess depthAccess;   // Type of access that will be used for depth (must be legal).
233     AspectAccess stencilAccess; // Type of access that will be used for stencil (must be legal).
234 
235     tcu::Maybe<ROAccessVec> depthROAccesses; // Types of read-only accesses for depth (used when depthAccess is RO).
236     tcu::Maybe<ROAccessVec>
237         stencilROAccesses; // Types of read-only accesses for stencil (used when stencilAccess is RO).
238 
239     VkImageUsageFlags getUsageFlags() const;
240 
241     // Get a list of descriptors needed according to the given test parameters.
242     IODescVec getDescriptors() const;
243 
244     // Does this case need a depth/stencil attachment?
245     bool dsAttachmentNeeded() const;
246 
247     // Does this case use the depth aspect as an input attachment?
248     bool depthAsInputAttachment() const;
249 
250     // Does this case use the stencil aspect as an input attachment?
251     bool stencilAsInputAttachment() const;
252 
253     // Does this case need an input attachment?
254     bool inputAttachmentNeeded() const;
255 
256     // Does this case need a depth/stencil attachment as a depth buffer?
257     bool depthBufferNeeded() const;
258 
259     // Does this case need the pipeline depth test enabled?
260     bool needsDepthTest() const;
261 
262     // Does this case need the stencil test enabled?
263     bool needsStencilTest() const;
264 };
265 
getUsageFlags() const266 VkImageUsageFlags TestParams::getUsageFlags() const
267 {
268     VkImageUsageFlags usageFlags = (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
269 
270     if (depthAccess == AspectAccess::RW || stencilAccess == AspectAccess::RW)
271         usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
272 
273     if (depthAccess == AspectAccess::RO)
274     {
275         DE_ASSERT(static_cast<bool>(depthROAccesses));
276         usageFlags |= getReadOnlyUsageFlags(*depthROAccesses);
277     }
278 
279     if (stencilAccess == AspectAccess::RO)
280     {
281         DE_ASSERT(static_cast<bool>(stencilROAccesses));
282         usageFlags |= getReadOnlyUsageFlags(*stencilROAccesses);
283     }
284 
285     return usageFlags;
286 }
287 
addDescriptors(IODescVec & descriptors,uint32_t & inputAttachmentCount,const ROAccessVec & accesses,VkImageAspectFlagBits aspect)288 void addDescriptors(IODescVec &descriptors, uint32_t &inputAttachmentCount, const ROAccessVec &accesses,
289                     VkImageAspectFlagBits aspect)
290 {
291     for (const auto &access : accesses)
292     {
293         // Get a new binding number and a new input attachment index if needed, then append the new descriptor to the list if
294         // appropriate.
295 
296         InputOutputDescriptor descriptor = {
297             static_cast<uint32_t>(descriptors.size()), // uint32_t binding;
298             tcu::Nothing,                              // tcu::Maybe<uint32_t> inputAttachmentIndex;
299             aspect,                                    // VkImageAspectFlagBits aspect;
300         };
301 
302         if (access == ReadOnlyAccess::INPUT_ATTACHMENT)
303             descriptor.inputAttachmentIndex = tcu::just(inputAttachmentCount++);
304 
305         if (access == ReadOnlyAccess::INPUT_ATTACHMENT || access == ReadOnlyAccess::SAMPLED)
306             descriptors.push_back(descriptor);
307     }
308 }
309 
getDescriptors() const310 IODescVec TestParams::getDescriptors() const
311 {
312     IODescVec descriptors;
313     uint32_t inputAttachmentCount = 0u;
314 
315     if (static_cast<bool>(depthROAccesses))
316         addDescriptors(descriptors, inputAttachmentCount, *depthROAccesses, VK_IMAGE_ASPECT_DEPTH_BIT);
317 
318     if (static_cast<bool>(stencilROAccesses))
319         addDescriptors(descriptors, inputAttachmentCount, *stencilROAccesses, VK_IMAGE_ASPECT_STENCIL_BIT);
320 
321     return descriptors;
322 }
323 
dsAttachmentNeeded() const324 bool TestParams::dsAttachmentNeeded() const
325 {
326     // The depth/stencil attachment is needed if the image is going to be used as a depth/stencil attachment or an input attachment.
327     return (inputAttachmentNeeded() || depthBufferNeeded());
328 }
329 
depthAsInputAttachment() const330 bool TestParams::depthAsInputAttachment() const
331 {
332     return (depthAccess == AspectAccess::RO &&
333             de::contains(begin(*depthROAccesses), end(*depthROAccesses), ReadOnlyAccess::INPUT_ATTACHMENT));
334 }
335 
stencilAsInputAttachment() const336 bool TestParams::stencilAsInputAttachment() const
337 {
338     return (stencilAccess == AspectAccess::RO &&
339             de::contains(begin(*stencilROAccesses), end(*stencilROAccesses), ReadOnlyAccess::INPUT_ATTACHMENT));
340 }
341 
inputAttachmentNeeded() const342 bool TestParams::inputAttachmentNeeded() const
343 {
344     // An input attachment is needed if any of the depth or stencil aspects include a read-only access as an input attachment.
345     return (depthAsInputAttachment() || stencilAsInputAttachment());
346 }
347 
depthBufferNeeded() const348 bool TestParams::depthBufferNeeded() const
349 {
350     // The depth buffer is needed if any of the depth or stencil aspects include a read-write or read-only DS access.
351     return (needsDepthTest() || needsStencilTest());
352 }
353 
needsDepthTest() const354 bool TestParams::needsDepthTest() const
355 {
356     // The depth test is needed if the depth aspect includes a read-write or read-only DS access.
357     return (depthAccess == AspectAccess::RW ||
358             (depthAccess == AspectAccess::RO &&
359              de::contains(begin(*depthROAccesses), end(*depthROAccesses), ReadOnlyAccess::DS_ATTACHMENT)));
360 }
361 
needsStencilTest() const362 bool TestParams::needsStencilTest() const
363 {
364     // The stencil test is needed if the stencil aspect includes a read-write or read-only DS access.
365     return (stencilAccess == AspectAccess::RW ||
366             (stencilAccess == AspectAccess::RO &&
367              de::contains(begin(*stencilROAccesses), end(*stencilROAccesses), ReadOnlyAccess::DS_ATTACHMENT)));
368 }
369 
370 class DepthStencilDescriptorCase : public vkt::TestCase
371 {
372 public:
373     DepthStencilDescriptorCase(tcu::TestContext &testCtx, const std::string &name, const TestParams &params);
~DepthStencilDescriptorCase(void)374     virtual ~DepthStencilDescriptorCase(void)
375     {
376     }
377 
378     void checkSupport(Context &context) const override;
379     TestInstance *createInstance(Context &context) const override;
380     void initPrograms(vk::SourceCollections &programCollection) const override;
381 
382 protected:
383     TestParams m_params;
384 };
385 
386 class DepthStencilDescriptorInstance : public vkt::TestInstance
387 {
388 public:
389     DepthStencilDescriptorInstance(Context &context, const TestParams &params);
~DepthStencilDescriptorInstance(void)390     virtual ~DepthStencilDescriptorInstance(void)
391     {
392     }
393 
394     tcu::TestStatus iterate() override;
395 
396 protected:
397     // Must match the shaders.
398     struct PushConstantData
399     {
400         float colorR;
401         float colorG;
402         float colorB;
403         float colorA;
404         float depth;
405 
PushConstantDatavkt::image::__anoneef40f980111::DepthStencilDescriptorInstance::PushConstantData406         PushConstantData() : colorR(0.0f), colorG(0.0f), colorB(0.0f), colorA(0.0f), depth(0.0f)
407         {
408         }
409 
PushConstantDatavkt::image::__anoneef40f980111::DepthStencilDescriptorInstance::PushConstantData410         PushConstantData(const tcu::Vec4 &color, float depth_)
411             : colorR(color.x())
412             , colorG(color.y())
413             , colorB(color.z())
414             , colorA(color.w())
415             , depth(depth_)
416         {
417         }
418     };
419 
420     TestParams m_params;
421 };
422 
DepthStencilDescriptorCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)423 DepthStencilDescriptorCase::DepthStencilDescriptorCase(tcu::TestContext &testCtx, const std::string &name,
424                                                        const TestParams &params)
425     : vkt::TestCase(testCtx, name)
426     , m_params(params)
427 {
428 }
429 
checkSupport(Context & context) const430 void DepthStencilDescriptorCase::checkSupport(Context &context) const
431 {
432     context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
433 
434     const auto requiredExtension = layoutExtension(m_params.layout);
435     if (requiredExtension)
436         context.requireDeviceFunctionality(*requiredExtension);
437 
438     // Check format support.
439     const auto &vki    = context.getInstanceInterface();
440     const auto physDev = context.getPhysicalDevice();
441     const auto imgType = VK_IMAGE_TYPE_2D;
442     const auto tiling  = VK_IMAGE_TILING_OPTIMAL;
443     const auto usage   = m_params.getUsageFlags();
444 
445     VkImageFormatProperties formatProperties;
446     const auto res = vki.getPhysicalDeviceImageFormatProperties(physDev, m_params.format, imgType, tiling, usage, 0u,
447                                                                 &formatProperties);
448     if (res == VK_ERROR_FORMAT_NOT_SUPPORTED)
449         TCU_THROW(NotSupportedError, "Format does not support required properties");
450     else if (res != VK_SUCCESS)
451         TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned " + de::toString(res));
452 }
453 
createInstance(Context & context) const454 TestInstance *DepthStencilDescriptorCase::createInstance(Context &context) const
455 {
456     return new DepthStencilDescriptorInstance(context, m_params);
457 }
458 
initPrograms(vk::SourceCollections & programCollection) const459 void DepthStencilDescriptorCase::initPrograms(vk::SourceCollections &programCollection) const
460 {
461     std::ostringstream vert;
462     vert << "#version 450\n"
463          << "\n"
464          << "layout(push_constant, std430) uniform PushConstantBlock {\n"
465          << "    float colorR;\n"
466          << "    float colorG;\n"
467          << "    float colorB;\n"
468          << "    float colorA;\n"
469          << "    float depth;\n"
470          << "} pc;\n"
471          << "\n"
472          << "vec2 vertexPositions[3] = vec2[](\n"
473          << "    vec2(-1.0, -1.0),\n"
474          << "    vec2(-1.0,  3.0),\n"
475          << "    vec2( 3.0, -1.0));\n"
476          << "\n"
477          << "void main () {\n"
478          << "    gl_Position = vec4(vertexPositions[gl_VertexIndex], pc.depth, 1.0);\n"
479          << "}\n";
480     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
481 
482     // When any of the image aspects is going to be used as an input attachment or sampled image, we need an input descriptor and an
483     // output descriptor to verify reading from it.
484     std::ostringstream descriptorsDecl;
485     std::ostringstream descriptorsSideEffects;
486     const auto descriptors = m_params.getDescriptors();
487 
488     // Samplers set (set number 2).
489     descriptorsDecl
490         << "layout (set=2, binding=0) uniform sampler globalSampler;\n"  // Sampler with float border color (depth).
491         << "layout (set=2, binding=1) uniform sampler uglobalSampler;\n" // Sampler with int border color (stencil).
492         ;
493 
494     for (const auto &descriptor : descriptors)
495     {
496         const auto prefix = ((descriptor.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) ? "u" : "");
497         const auto suffix = ((descriptor.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) ? "ui" : "f");
498         std::ostringstream loadOp;
499 
500         // Input descriptor declaration.
501         if (static_cast<bool>(descriptor.inputAttachmentIndex))
502         {
503             const auto &iaIndex = *descriptor.inputAttachmentIndex;
504             descriptorsDecl << "layout (input_attachment_index=" << iaIndex << ", set=0, binding=" << descriptor.binding
505                             << ") uniform " << prefix << "subpassInput attachment" << descriptor.binding << ";\n";
506             loadOp << "subpassLoad(attachment" << descriptor.binding << ")";
507         }
508         else
509         {
510             descriptorsDecl << "layout (set=0, binding=" << descriptor.binding << ") uniform " << prefix
511                             << "texture2D sampledImage" << descriptor.binding << ";\n";
512             loadOp
513                 << "texture(" << prefix << "sampler2D(sampledImage" << descriptor.binding << ", " << prefix
514                 << "globalSampler), gl_FragCoord.xy)"; // This needs a sampler with unnormalizedCoordinates == VK_TRUE.
515         }
516 
517         // Output descriptor declaration (output descriptors in set 1).
518         descriptorsDecl << "layout (r32" << suffix << ", set=1, binding=" << descriptor.binding << ") uniform "
519                         << prefix << "image2D storage" << descriptor.binding << ";\n";
520 
521         // The corresponding side effect.
522         descriptorsSideEffects << "    imageStore(storage" << descriptor.binding << ", ivec2(gl_FragCoord.xy), "
523                                << loadOp.str() << ");\n";
524     }
525 
526     std::ostringstream frag;
527     frag << "#version 450\n"
528          << "\n"
529          << "layout(location=0) out vec4 outColor;\n"
530          << "layout(push_constant, std430) uniform PushConstantBlock {\n"
531          << "    float colorR;\n"
532          << "    float colorG;\n"
533          << "    float colorB;\n"
534          << "    float colorA;\n"
535          << "    float depth;\n"
536          << "} pc;\n"
537          << "\n"
538          << descriptorsDecl.str() << "\n"
539          << "void main () {\n"
540          << descriptorsSideEffects.str() << "    outColor = vec4(pc.colorR, pc.colorG, pc.colorB, pc.colorA);\n"
541          << "}\n";
542 
543     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
544 }
545 
DepthStencilDescriptorInstance(Context & context,const TestParams & params)546 DepthStencilDescriptorInstance::DepthStencilDescriptorInstance(Context &context, const TestParams &params)
547     : vkt::TestInstance(context)
548     , m_params(params)
549 {
550 }
551 
getAspectStorageFormat(VkImageAspectFlagBits aspect)552 VkFormat getAspectStorageFormat(VkImageAspectFlagBits aspect)
553 {
554     return ((aspect == VK_IMAGE_ASPECT_DEPTH_BIT) ? getFloatStorageFormat() : getUintStorageFormat());
555 }
556 
getCopyBufferSize(const tcu::TextureFormat & format,const VkExtent3D & extent)557 VkDeviceSize getCopyBufferSize(const tcu::TextureFormat &format, const VkExtent3D &extent)
558 {
559     return static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(format)) * extent.width * extent.height *
560                                      extent.depth);
561 }
562 
iterate()563 tcu::TestStatus DepthStencilDescriptorInstance::iterate()
564 {
565     const auto &vkd   = m_context.getDeviceInterface();
566     const auto device = m_context.getDevice();
567     auto &alloc       = m_context.getDefaultAllocator();
568     const auto qIndex = m_context.getUniversalQueueFamilyIndex();
569     const auto queue  = m_context.getUniversalQueue();
570     const auto extent = getExtent();
571     const auto usage  = m_params.getUsageFlags();
572     const auto colorUsage =
573         (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
574     const auto colorFormat    = getColorBufferFormat();
575     const auto tcuColorFormat = mapVkFormat(colorFormat);
576     const auto storageUsage =
577         (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
578     const auto stageFlags      = VK_SHADER_STAGE_FRAGMENT_BIT;
579     const auto tcuFormat       = mapVkFormat(m_params.format);
580     const auto hasDepth        = tcu::hasDepthComponent(tcuFormat.order);
581     const auto hasStencil      = tcu::hasStencilComponent(tcuFormat.order);
582     const auto colorSRR        = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
583     const auto outputImgLayout = VK_IMAGE_LAYOUT_GENERAL;
584     const auto colorLayout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
585 
586     // Copy formats.
587     const auto tcuDepthFormat   = (hasDepth ? getDepthCopyFormat(m_params.format) : tcu::TextureFormat());
588     const auto tcuStencilFormat = (hasStencil ? getStencilCopyFormat(m_params.format) : tcu::TextureFormat());
589 
590     // These must match the depth test configuration when enabled.
591     const float depthClearValue = 0.5f;
592     const float depthFailValue  = 1.0f;
593     const float depthPassValue  = 0.0f;
594 
595     // These must match the stencil test configuration when enabled.
596     const uint32_t stencilClearVal = 100u;
597     const uint32_t stencilFailVal  = 200u;
598     const uint32_t stencilPassVal  = 10u;
599 
600     // For the color buffer.
601     const tcu::Vec4 colorClearVal(0.0f, 0.0f, 0.0f, 1.0f);
602     const tcu::Vec4 colorFailVal(1.0f, 0.0f, 0.0f, 1.0f);
603     const tcu::Vec4 colorPassVal(0.0f, 1.0f, 0.0f, 1.0f);
604 
605     // Will the test update the depth/stencil buffer?
606     const auto stencilWrites = (m_params.stencilAccess == AspectAccess::RW);
607     const auto depthWrites   = (m_params.depthAccess == AspectAccess::RW);
608 
609     // Create color attachment.
610     const VkImageCreateInfo colorBufferInfo = {
611         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
612         nullptr,                             // const void* pNext;
613         0u,                                  // VkImageCreateFlags flags;
614         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
615         colorFormat,                         // VkFormat format;
616         extent,                              // VkExtent3D extent;
617         1u,                                  // uint32_t mipLevels;
618         1u,                                  // uint32_t arrayLayers;
619         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
620         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
621         colorUsage,                          // VkImageUsageFlags usage;
622         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
623         0u,                                  // uint32_t queueFamilyIndexCount;
624         nullptr,                             // const uint32_t* pQueueFamilyIndices;
625         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
626     };
627     ImageWithMemory colorBuffer(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
628     const auto colorView = makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
629 
630     // Create depth/stencil image.
631     const VkImageCreateInfo dsImageInfo = {
632         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
633         nullptr,                             // const void* pNext;
634         0u,                                  // VkImageCreateFlags flags;
635         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
636         m_params.format,                     // VkFormat format;
637         extent,                              // VkExtent3D extent;
638         1u,                                  // uint32_t mipLevels;
639         1u,                                  // uint32_t arrayLayers;
640         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
641         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
642         usage,                               // VkImageUsageFlags usage;
643         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
644         0u,                                  // uint32_t queueFamilyIndexCount;
645         nullptr,                             // const uint32_t* pQueueFamilyIndices;
646         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
647     };
648     ImageWithMemory dsImage(vkd, device, alloc, dsImageInfo, MemoryRequirement::Any);
649     const auto depthStencilSRR = makeImageSubresourceRange(getImageAspectFlags(tcuFormat), 0u, 1u, 0u, 1u);
650     const auto depthSRR        = makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
651     const auto stencilSRR      = makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u);
652     const auto dsImageView =
653         makeImageView(vkd, device, dsImage.get(), VK_IMAGE_VIEW_TYPE_2D, m_params.format, depthStencilSRR);
654 
655     Move<VkImageView> depthOnlyView;
656     Move<VkImageView> stencilOnlyView;
657 
658     if (hasDepth)
659         depthOnlyView = makeImageView(vkd, device, dsImage.get(), VK_IMAGE_VIEW_TYPE_2D, m_params.format, depthSRR);
660 
661     if (hasStencil)
662         stencilOnlyView = makeImageView(vkd, device, dsImage.get(), VK_IMAGE_VIEW_TYPE_2D, m_params.format, stencilSRR);
663 
664     // Get expected descriptors and create output images for them.
665     const auto descriptors = m_params.getDescriptors();
666 
667     std::vector<de::MovePtr<ImageWithMemory>> outputImages;
668     std::vector<Move<VkImageView>> outputImageViews;
669 
670     outputImages.reserve(descriptors.size());
671     outputImageViews.reserve(descriptors.size());
672 
673     for (const auto &desc : descriptors)
674     {
675         // Floating point images to copy the depth aspect and unsigned int images to copy the stencil aspect.
676         const auto imageFormat = getAspectStorageFormat(desc.aspect);
677 
678         const VkImageCreateInfo createInfo = {
679             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
680             nullptr,                             // const void* pNext;
681             0u,                                  // VkImageCreateFlags flags;
682             VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
683             imageFormat,                         // VkFormat format;
684             extent,                              // VkExtent3D extent;
685             1u,                                  // uint32_t mipLevels;
686             1u,                                  // uint32_t arrayLayers;
687             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
688             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
689             storageUsage,                        // VkImageUsageFlags usage;
690             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
691             0u,                                  // uint32_t queueFamilyIndexCount;
692             nullptr,                             // const uint32_t* pQueueFamilyIndices;
693             VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
694         };
695 
696         outputImages.push_back(
697             de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, alloc, createInfo, MemoryRequirement::Any)));
698         outputImageViews.push_back(
699             makeImageView(vkd, device, outputImages.back()->get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR));
700     }
701 
702     // Create samplers.
703     Move<VkSampler> samplerFloat;
704     Move<VkSampler> samplerInt;
705     {
706         VkSamplerCreateInfo samplerCreateInfo = {
707             VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
708             nullptr,                               // const void* pNext;
709             0u,                                    // VkSamplerCreateFlags flags;
710             VK_FILTER_NEAREST,                     // VkFilter magFilter;
711             VK_FILTER_NEAREST,                     // VkFilter minFilter;
712             VK_SAMPLER_MIPMAP_MODE_NEAREST,        // VkSamplerMipmapMode mipmapMode;
713             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
714             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
715             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
716             0.0f,                                  // float mipLodBias;
717             VK_FALSE,                              // VkBool32 anisotropyEnable;
718             0.0f,                                  // float maxAnisotropy;
719             VK_FALSE,                              // VkBool32 compareEnable;
720             VK_COMPARE_OP_LAST,                    // VkCompareOp compareOp;
721             0.0f,                                  // float minLod;
722             0.0f,                                  // float maxLod;
723             VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,    // VkBorderColor borderColor;
724             VK_TRUE,                               // VkBool32 unnormalizedCoordinates;
725         };
726         // Note the samplers are created with unnormalizedCoordinates as per how they are used in shader code.
727         samplerFloat = createSampler(vkd, device, &samplerCreateInfo);
728 
729         samplerCreateInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
730         samplerInt                    = createSampler(vkd, device, &samplerCreateInfo);
731     }
732 
733     // Create input and output descriptor set layouts.
734     Move<VkDescriptorSetLayout> inputSetLayout;
735     Move<VkDescriptorSetLayout> outputSetLayout;
736     Move<VkDescriptorSetLayout> samplerSetLayout;
737 
738     {
739         DescriptorSetLayoutBuilder inputLayoutBuilder;
740         for (const auto &desc : descriptors)
741         {
742             if (static_cast<bool>(desc.inputAttachmentIndex))
743                 inputLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, stageFlags);
744             else
745                 inputLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
746         }
747         inputSetLayout = inputLayoutBuilder.build(vkd, device);
748     }
749     {
750         DescriptorSetLayoutBuilder outputLayoutBuilder;
751         for (size_t i = 0; i < descriptors.size(); ++i)
752             outputLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stageFlags);
753         outputSetLayout = outputLayoutBuilder.build(vkd, device);
754     }
755     {
756         DescriptorSetLayoutBuilder samplerLayoutBuilder;
757         samplerLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, stageFlags);
758         samplerLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, stageFlags);
759         samplerSetLayout = samplerLayoutBuilder.build(vkd, device);
760     }
761 
762     const std::vector<VkDescriptorSetLayout> setLayouts = {inputSetLayout.get(), outputSetLayout.get(),
763                                                            samplerSetLayout.get()};
764 
765     // Descriptor pool and descriptor sets.
766     Move<VkDescriptorPool> descriptorPool;
767     Move<VkDescriptorSet> inputSet;
768     Move<VkDescriptorSet> outputSet;
769     Move<VkDescriptorSet> samplerSet;
770     {
771         DescriptorPoolBuilder poolBuilder;
772 
773         // Input descriptors.
774         for (const auto &desc : descriptors)
775         {
776             if (static_cast<bool>(desc.inputAttachmentIndex))
777                 poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
778             else
779                 poolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
780         }
781 
782         // Output descriptors.
783         poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, static_cast<uint32_t>(descriptors.size()));
784 
785         // Global samplers.
786         poolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 2u);
787 
788         descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
789                                            static_cast<uint32_t>(setLayouts.size()));
790     }
791 
792     inputSet   = makeDescriptorSet(vkd, device, descriptorPool.get(), inputSetLayout.get());
793     outputSet  = makeDescriptorSet(vkd, device, descriptorPool.get(), outputSetLayout.get());
794     samplerSet = makeDescriptorSet(vkd, device, descriptorPool.get(), samplerSetLayout.get());
795 
796     const std::vector<VkDescriptorSet> descriptorSets = {inputSet.get(), outputSet.get(), samplerSet.get()};
797 
798     // Update descriptor sets.
799     {
800         DescriptorSetUpdateBuilder inputUpdateBuilder;
801         DescriptorSetUpdateBuilder outputUpdateBuilder;
802         DescriptorSetUpdateBuilder samplerUpdateBuilder;
803 
804         std::vector<VkDescriptorImageInfo> inputImgInfos;
805         std::vector<VkDescriptorImageInfo> outputImgInfos;
806         std::vector<VkDescriptorImageInfo> samplerImgInfos;
807 
808         // Make sure addresses are stable (pushing elements back while taking their addresses).
809         inputImgInfos.reserve(descriptors.size());
810         outputImgInfos.reserve(descriptors.size());
811         samplerImgInfos.reserve(2u);
812 
813         for (size_t descriptorIdx = 0u; descriptorIdx < descriptors.size(); ++descriptorIdx)
814         {
815             const auto &desc    = descriptors[descriptorIdx];
816             const auto isIA     = static_cast<bool>(desc.inputAttachmentIndex);
817             const auto location = DescriptorSetUpdateBuilder::Location::binding(desc.binding);
818 
819             // Input descriptors.
820             const auto inType = (isIA ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
821             const auto view =
822                 ((desc.aspect == VK_IMAGE_ASPECT_DEPTH_BIT) ? depthOnlyView.get() : stencilOnlyView.get());
823             inputImgInfos.push_back(makeDescriptorImageInfo(DE_NULL, view, m_params.layout));
824             inputUpdateBuilder.writeSingle(inputSet.get(), location, inType, &inputImgInfos.back());
825 
826             // Output descriptors.
827             outputImgInfos.push_back(
828                 makeDescriptorImageInfo(DE_NULL, outputImageViews[descriptorIdx].get(), outputImgLayout));
829             outputUpdateBuilder.writeSingle(outputSet.get(), location, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
830                                             &outputImgInfos.back());
831         }
832 
833         inputUpdateBuilder.update(vkd, device);
834         outputUpdateBuilder.update(vkd, device);
835 
836         // Samplers.
837         samplerImgInfos.push_back(makeDescriptorImageInfo(samplerFloat.get(), DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED));
838         samplerUpdateBuilder.writeSingle(samplerSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
839                                          VK_DESCRIPTOR_TYPE_SAMPLER, &samplerImgInfos.back());
840 
841         samplerImgInfos.push_back(makeDescriptorImageInfo(samplerInt.get(), DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED));
842         samplerUpdateBuilder.writeSingle(samplerSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u),
843                                          VK_DESCRIPTOR_TYPE_SAMPLER, &samplerImgInfos.back());
844 
845         samplerUpdateBuilder.update(vkd, device);
846     }
847 
848     PushConstantData pcData;
849     const auto pcStages = (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
850     const auto pcSize   = static_cast<uint32_t>(sizeof(pcData));
851     const auto pcRange  = makePushConstantRange(pcStages, 0u, pcSize);
852 
853     // Pipeline layout.
854     const auto pipelineLayout = makePipelineLayout(vkd, device, static_cast<uint32_t>(setLayouts.size()),
855                                                    de::dataOrNull(setLayouts), 1u, &pcRange);
856 
857     // Render pass.
858     Move<VkRenderPass> renderPass;
859 
860     {
861         std::vector<VkAttachmentDescription2> attachmentDescriptions;
862         std::vector<VkAttachmentReference2> attachmentReferences;
863 
864         const VkAttachmentDescription2 colorAttachmentDesc = {
865             VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
866             nullptr,                                    // const void* pNext;
867             0u,                                         // VkAttachmentDescriptionFlags flags;
868             colorFormat,                                // VkFormat format;
869             VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits samples;
870             VK_ATTACHMENT_LOAD_OP_LOAD,                 // VkAttachmentLoadOp loadOp;
871             VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp storeOp;
872             VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp stencilLoadOp;
873             VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp stencilStoreOp;
874             colorLayout,                                // VkImageLayout initialLayout;
875             colorLayout,                                // VkImageLayout finalLayout;
876         };
877         attachmentDescriptions.push_back(colorAttachmentDesc);
878 
879         const VkAttachmentReference2 colorAttachmentRef = {
880             VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
881             nullptr,                                  // const void* pNext;
882             0u,                                       // uint32_t attachment;
883             colorLayout,                              // VkImageLayout layout;
884             VK_IMAGE_ASPECT_COLOR_BIT,                // VkImageAspectFlags aspectMask;
885         };
886         attachmentReferences.push_back(colorAttachmentRef);
887 
888         const auto needsIA          = m_params.inputAttachmentNeeded();
889         const auto needsDepthBuffer = m_params.depthBufferNeeded();
890         DE_ASSERT(!(needsIA && needsDepthBuffer));
891 
892         if (m_params.dsAttachmentNeeded())
893         {
894             const VkAttachmentDescription2 dsAttachmentDesc = {
895                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
896                 nullptr,
897                 0u,
898                 m_params.format,
899                 VK_SAMPLE_COUNT_1_BIT,
900                 (hasDepth ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
901                 ((hasDepth && depthWrites) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),
902                 (hasStencil ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
903                 ((hasStencil && stencilWrites) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),
904                 m_params.layout,
905                 m_params.layout,
906             };
907             attachmentDescriptions.push_back(dsAttachmentDesc);
908 
909             const VkAttachmentReference2 dsAttachmentRef = {
910                 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
911                 nullptr,                                  // const void* pNext;
912                 1u,                                       // uint32_t attachment;
913                 m_params.layout,                          // VkImageLayout layout;
914                                                           // VkImageAspectFlags aspectMask;
915                 ((m_params.depthAsInputAttachment() ? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT) : 0u) |
916                  (m_params.stencilAsInputAttachment() ? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_STENCIL_BIT) :
917                                                         0u)),
918             };
919 
920             attachmentReferences.push_back(dsAttachmentRef);
921         }
922 
923         const VkSubpassDescription2 subpassDesc = {
924             VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,           // VkStructureType sType;
925             nullptr,                                           // const void* pNext;
926             0u,                                                // VkSubpassDescriptionFlags flags;
927             VK_PIPELINE_BIND_POINT_GRAPHICS,                   // VkPipelineBindPoint pipelineBindPoint;
928             0u,                                                // uint32_t viewMask;
929             (needsIA ? 1u : 0u),                               // uint32_t inputAttachmentCount;
930             (needsIA ? &attachmentReferences.at(1) : nullptr), // const VkAttachmentReference* pInputAttachments;
931             1u,                                                // uint32_t colorAttachmentCount;
932             &attachmentReferences.at(0),                       // const VkAttachmentReference* pColorAttachments;
933             nullptr,                                           // const VkAttachmentReference* pResolveAttachments;
934             (needsDepthBuffer ? &attachmentReferences.at(1) :
935                                 nullptr), // const VkAttachmentReference* pDepthStencilAttachment;
936             0u,                           // uint32_t preserveAttachmentCount;
937             nullptr,                      // const uint32_t* pPreserveAttachments;
938         };
939 
940         const VkRenderPassCreateInfo2 renderPassCreateInfo = {
941             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,          // VkStructureType sType;
942             nullptr,                                              // const void* pNext;
943             0u,                                                   // VkRenderPassCreateFlags flags;
944             static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
945             de::dataOrNull(attachmentDescriptions),               // const VkAttachmentDescription* pAttachments;
946             1u,                                                   // uint32_t subpassCount;
947             &subpassDesc,                                         // const VkSubpassDescription* pSubpasses;
948             0u,                                                   // uint32_t dependencyCount;
949             nullptr,                                              // const VkSubpassDependency* pDependencies;
950             0u,                                                   // uint32_t correlatedViewMaskCount;
951             nullptr,                                              // const uint32_t* pCorrelatedViewMasks;
952         };
953         renderPass = createRenderPass2(vkd, device, &renderPassCreateInfo);
954     }
955 
956     // Framebuffer.
957     std::vector<VkImageView> framebufferViews;
958 
959     framebufferViews.push_back(colorView.get());
960     if (m_params.dsAttachmentNeeded())
961         framebufferViews.push_back(dsImageView.get());
962 
963     const auto framebuffer =
964         makeFramebuffer(vkd, device, renderPass.get(), static_cast<uint32_t>(framebufferViews.size()),
965                         de::dataOrNull(framebufferViews), extent.width, extent.height);
966 
967     // Pipeline.
968     std::vector<Move<VkPipeline>> graphicsPipelines;
969     {
970         const auto vertModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
971         const auto fragModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
972 
973         const VkPipelineVertexInputStateCreateInfo vertexInputInfo = initVulkanStructure();
974         VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo   = initVulkanStructure();
975         VkPipelineViewportStateCreateInfo viewportInfo             = initVulkanStructure();
976         VkPipelineRasterizationStateCreateInfo rasterizationInfo   = initVulkanStructure();
977         VkPipelineMultisampleStateCreateInfo multisampleInfo       = initVulkanStructure();
978         VkPipelineDepthStencilStateCreateInfo dsStateInfo          = initVulkanStructure();
979         VkPipelineColorBlendStateCreateInfo colorBlendInfo         = initVulkanStructure();
980         VkPipelineColorBlendAttachmentState colorBlendAttState     = {};
981 
982         // Topology.
983         inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
984 
985         // Viewports and scissors.
986         const auto viewport        = makeViewport(extent);
987         const auto scissor         = makeRect2D(extent);
988         viewportInfo.viewportCount = 1u;
989         viewportInfo.pViewports    = &viewport;
990         viewportInfo.scissorCount  = 1u;
991         viewportInfo.pScissors     = &scissor;
992 
993         // Line width.
994         rasterizationInfo.lineWidth = 1.0f;
995 
996         // Multisample state.
997         multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
998 
999         // Depth/stencil state. This depends on the test parameters.
1000         if (m_params.needsDepthTest())
1001             dsStateInfo.depthTestEnable = VK_TRUE;
1002         if (depthWrites)
1003             dsStateInfo.depthWriteEnable = VK_TRUE;
1004         dsStateInfo.depthCompareOp = VK_COMPARE_OP_LESS;
1005         if (m_params.needsStencilTest())
1006             dsStateInfo.stencilTestEnable = VK_TRUE;
1007 
1008         const auto stencilOpState =
1009             makeStencilOpState(VK_STENCIL_OP_KEEP,                                           // failOp
1010                                (stencilWrites ? VK_STENCIL_OP_REPLACE : VK_STENCIL_OP_KEEP), // passOp
1011                                VK_STENCIL_OP_KEEP,                                           // depthFailOp
1012                                VK_COMPARE_OP_LESS,                                           // compareOp
1013                                0xFFu,                                                        // compareMask
1014                                (stencilWrites ? 0xFFu : 0u),                                 // writeMask
1015                                stencilFailVal);                                              // reference
1016         dsStateInfo.front = stencilOpState;
1017         dsStateInfo.back  = stencilOpState;
1018 
1019         colorBlendAttState.colorWriteMask =
1020             (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
1021         colorBlendAttState.blendEnable = VK_FALSE;
1022         colorBlendInfo.attachmentCount = 1u;
1023         colorBlendInfo.pAttachments    = &colorBlendAttState;
1024 
1025         graphicsPipelines.push_back(makeGraphicsPipeline(vkd, device, pipelineLayout.get(), vertModule.get(), DE_NULL,
1026                                                          DE_NULL, DE_NULL, fragModule.get(), // Shader modules.
1027                                                          renderPass.get(), 0u /*subpass*/, &vertexInputInfo,
1028                                                          &inputAssemblyInfo, nullptr, &viewportInfo, &rasterizationInfo,
1029                                                          &multisampleInfo, &dsStateInfo, &colorBlendInfo, nullptr));
1030 
1031         // When the stencil test is enabled, we need a second pipeline changing the reference value so the stencil test passes the second time.
1032         if (m_params.needsStencilTest())
1033         {
1034             dsStateInfo.front.reference = stencilPassVal;
1035             dsStateInfo.back.reference  = stencilPassVal;
1036 
1037             graphicsPipelines.push_back(makeGraphicsPipeline(
1038                 vkd, device, pipelineLayout.get(), vertModule.get(), DE_NULL, DE_NULL, DE_NULL,
1039                 fragModule.get(), // Shader modules.
1040                 renderPass.get(), 0u /*subpass*/, &vertexInputInfo, &inputAssemblyInfo, nullptr, &viewportInfo,
1041                 &rasterizationInfo, &multisampleInfo, &dsStateInfo, &colorBlendInfo, nullptr));
1042         }
1043     }
1044 
1045     // Command pool and buffer.
1046     const auto cmdPool      = makeCommandPool(vkd, device, qIndex);
1047     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1048     const auto cmdBuffer    = cmdBufferPtr.get();
1049     const auto renderArea   = makeRect2D(extent);
1050 
1051     // Output buffers to check the color attachment, depth/stencil attachment and output storage images.
1052     using BufferPtr = de::MovePtr<BufferWithMemory>;
1053 
1054     BufferPtr colorVerifBuffer;
1055     BufferPtr depthVerifBuffer;
1056     BufferPtr stencilVerifBuffer;
1057     std::vector<BufferPtr> storageVerifBuffers;
1058 
1059     {
1060         const auto colorVerifBufferSize = getCopyBufferSize(tcuColorFormat, extent);
1061         const auto colorVerifBufferInfo = makeBufferCreateInfo(colorVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1062         colorVerifBuffer =
1063             BufferPtr(new BufferWithMemory(vkd, device, alloc, colorVerifBufferInfo, MemoryRequirement::HostVisible));
1064     }
1065 
1066     if (hasDepth)
1067     {
1068         const auto depthVerifBufferSize = getCopyBufferSize(tcuDepthFormat, extent);
1069         const auto depthVerifBufferInfo = makeBufferCreateInfo(depthVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1070         depthVerifBuffer =
1071             BufferPtr(new BufferWithMemory(vkd, device, alloc, depthVerifBufferInfo, MemoryRequirement::HostVisible));
1072     }
1073 
1074     if (hasStencil)
1075     {
1076         const auto stencilVerifBufferSize = getCopyBufferSize(tcuStencilFormat, extent);
1077         const auto stencilVerifBufferInfo =
1078             makeBufferCreateInfo(stencilVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1079         stencilVerifBuffer =
1080             BufferPtr(new BufferWithMemory(vkd, device, alloc, stencilVerifBufferInfo, MemoryRequirement::HostVisible));
1081     }
1082 
1083     storageVerifBuffers.reserve(descriptors.size());
1084     for (const auto &desc : descriptors)
1085     {
1086         const auto storageFormat       = getAspectStorageFormat(desc.aspect);
1087         const auto tcuStorageFormat    = mapVkFormat(storageFormat);
1088         const auto descVerifBufferSize = getCopyBufferSize(tcuStorageFormat, extent);
1089         const auto descVerifBufferInfo = makeBufferCreateInfo(descVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1090         storageVerifBuffers.emplace_back(
1091             new BufferWithMemory(vkd, device, alloc, descVerifBufferInfo, MemoryRequirement::HostVisible));
1092     }
1093 
1094     beginCommandBuffer(vkd, cmdBuffer);
1095 
1096     // Transition layout for output images.
1097     std::vector<VkImageMemoryBarrier> outputImgBarriers;
1098     for (const auto &outputImg : outputImages)
1099         outputImgBarriers.push_back(makeImageMemoryBarrier(0u, (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT),
1100                                                            VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1101                                                            outputImg->get(), colorSRR));
1102     vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u,
1103                            nullptr, 0u, nullptr, static_cast<uint32_t>(outputImgBarriers.size()),
1104                            de::dataOrNull(outputImgBarriers));
1105 
1106     // Clear color and depth/stencil buffer.
1107     const auto colorPreTransferBarrier =
1108         makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1109                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, colorBuffer.get(), colorSRR);
1110     const auto dsPreTransferBarrier =
1111         makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1112                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dsImage.get(), depthStencilSRR);
1113     const std::vector<VkImageMemoryBarrier> preTransferBarriers = {colorPreTransferBarrier, dsPreTransferBarrier};
1114 
1115     vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1116                            nullptr, 0u, nullptr, static_cast<uint32_t>(preTransferBarriers.size()),
1117                            de::dataOrNull(preTransferBarriers));
1118 
1119     const auto colorClearValue = makeClearValueColorVec4(colorClearVal);
1120     const auto dsClearValue    = makeClearValueDepthStencil(depthClearValue, stencilClearVal);
1121 
1122     vkd.cmdClearColorImage(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colorClearValue.color,
1123                            1u, &colorSRR);
1124     vkd.cmdClearDepthStencilImage(cmdBuffer, dsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1125                                   &dsClearValue.depthStencil, 1u, &depthStencilSRR);
1126 
1127     const auto graphicsAccesses = (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1128                                    VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1129                                    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
1130     const auto colorPostTransferBarrier =
1131         makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, graphicsAccesses, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1132                                colorLayout, colorBuffer.get(), colorSRR);
1133     const auto dsPostTransferBarrier =
1134         makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, graphicsAccesses, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1135                                m_params.layout, dsImage.get(), depthStencilSRR);
1136     const std::vector<VkImageMemoryBarrier> postTransferBarriers = {colorPostTransferBarrier, dsPostTransferBarrier};
1137 
1138     vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u, 0u,
1139                            nullptr, 0u, nullptr, static_cast<uint32_t>(postTransferBarriers.size()),
1140                            de::dataOrNull(postTransferBarriers));
1141 
1142     // Render pass.
1143     beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea);
1144 
1145     vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u,
1146                               static_cast<uint32_t>(descriptorSets.size()), de::dataOrNull(descriptorSets), 0u,
1147                               nullptr);
1148 
1149     const auto useSecondDraw = m_params.depthBufferNeeded();
1150 
1151     vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelines.at(0).get());
1152     {
1153         if (useSecondDraw)
1154         {
1155             // Two draws: the first draw will use the red color.
1156             pcData = PushConstantData(colorFailVal, (m_params.needsDepthTest() ? depthFailValue : depthPassValue));
1157         }
1158         else
1159         {
1160             // If there will be no more draws, the first one needs to pass and use the right color.
1161             pcData = PushConstantData(colorPassVal, depthPassValue);
1162         }
1163 
1164         vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, pcSize, &pcData);
1165         vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1166     }
1167     if (useSecondDraw)
1168     {
1169         // The second draw, if used, always needs to pass and use the right color.
1170         if (m_params.needsStencilTest())
1171         {
1172             // Pipeline with a good stencil reference value.
1173             DE_ASSERT(graphicsPipelines.size() > 1);
1174             vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelines.at(1).get());
1175         }
1176         pcData = PushConstantData(colorPassVal, depthPassValue);
1177 
1178         vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, pcSize, &pcData);
1179         vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1180     }
1181 
1182     endRenderPass(vkd, cmdBuffer);
1183 
1184     // Copy color attachment.
1185     {
1186         const auto colorLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1187         const auto copyRegion  = makeBufferImageCopy(extent, colorLayers);
1188         const auto colorPostWriteBarrier =
1189             makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, colorLayout,
1190                                    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), colorSRR);
1191         vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1192                                0u, 0u, nullptr, 0u, nullptr, 1u, &colorPostWriteBarrier);
1193         vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1194                                  colorVerifBuffer->get(), 1u, &copyRegion);
1195     }
1196 
1197     // Copy aspects of DS attachment.
1198     {
1199         const auto dsPostWriteBarrier = makeImageMemoryBarrier(
1200             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, m_params.layout,
1201             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dsImage.get(), depthStencilSRR);
1202         const auto fragmentTestStages =
1203             (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1204         vkd.cmdPipelineBarrier(cmdBuffer, fragmentTestStages, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u,
1205                                nullptr, 1u, &dsPostWriteBarrier);
1206 
1207         if (hasDepth)
1208         {
1209             const auto depthLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u);
1210             const auto copyRegion  = makeBufferImageCopy(extent, depthLayers);
1211             vkd.cmdCopyImageToBuffer(cmdBuffer, dsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1212                                      depthVerifBuffer->get(), 1u, &copyRegion);
1213         }
1214 
1215         if (hasStencil)
1216         {
1217             const auto stencilLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u);
1218             const auto copyRegion    = makeBufferImageCopy(extent, stencilLayers);
1219             vkd.cmdCopyImageToBuffer(cmdBuffer, dsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1220                                      stencilVerifBuffer->get(), 1u, &copyRegion);
1221         }
1222     }
1223 
1224     // Copy storage images.
1225     {
1226         std::vector<VkImageMemoryBarrier> storagePostBarriers;
1227         storagePostBarriers.reserve(outputImages.size());
1228 
1229         for (const auto &outImg : outputImages)
1230             storagePostBarriers.push_back(
1231                 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
1232                                        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outImg->get(), colorSRR));
1233 
1234         vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1235                                nullptr, 0u, nullptr, static_cast<uint32_t>(storagePostBarriers.size()),
1236                                de::dataOrNull(storagePostBarriers));
1237 
1238         const auto colorLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1239         const auto copyRegion  = makeBufferImageCopy(extent, colorLayers);
1240 
1241         DE_ASSERT(outputImages.size() == storageVerifBuffers.size());
1242         for (size_t i = 0u; i < outputImages.size(); ++i)
1243             vkd.cmdCopyImageToBuffer(cmdBuffer, outputImages[i]->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1244                                      storageVerifBuffers[i]->get(), 1u, &copyRegion);
1245     }
1246 
1247     // Transfer to host barrier for buffers.
1248     const auto transferToHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1249     vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u,
1250                            &transferToHostBarrier, 0u, nullptr, 0u, nullptr);
1251 
1252     endCommandBuffer(vkd, cmdBuffer);
1253     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1254 
1255     // Verify the different buffers.
1256     const tcu::IVec3 iExtent(static_cast<int>(extent.width), static_cast<int>(extent.height),
1257                              static_cast<int>(extent.depth));
1258     auto &log = m_context.getTestContext().getLog();
1259 
1260     // Verify color buffer contents.
1261     {
1262         auto &verifAlloc = colorVerifBuffer->getAllocation();
1263         invalidateAlloc(vkd, device, verifAlloc);
1264 
1265         tcu::ConstPixelBufferAccess colorPixels(tcuColorFormat, iExtent, verifAlloc.getHostPtr());
1266         if (!tcu::floatThresholdCompare(log, "ColorResult", "", colorPassVal, colorPixels, tcu::Vec4(0.0f),
1267                                         tcu::COMPARE_LOG_ON_ERROR))
1268             TCU_FAIL("Unexpected color buffer contents; check log for details");
1269     }
1270 
1271     // Verify depth buffer contents.
1272     if (hasDepth)
1273     {
1274         auto &verifAlloc = depthVerifBuffer->getAllocation();
1275         invalidateAlloc(vkd, device, verifAlloc);
1276 
1277         tcu::TextureLevel referenceDepth(tcuDepthFormat, iExtent.x(), iExtent.y(), iExtent.z());
1278         auto referenceAccess   = referenceDepth.getAccess();
1279         const auto refDepthVal = (depthWrites ? depthPassValue : depthClearValue);
1280 
1281         for (int z = 0; z < iExtent.z(); ++z)
1282             for (int y = 0; y < iExtent.y(); ++y)
1283                 for (int x = 0; x < iExtent.x(); ++x)
1284                     referenceAccess.setPixDepth(refDepthVal, x, y, z);
1285 
1286         tcu::ConstPixelBufferAccess depthPixels(tcuDepthFormat, iExtent, verifAlloc.getHostPtr());
1287         if (!tcu::dsThresholdCompare(log, "DepthResult", "", referenceAccess, depthPixels, 0.1f,
1288                                      tcu::COMPARE_LOG_ON_ERROR))
1289             TCU_FAIL("Unexpected value in depth buffer; check log for details");
1290     }
1291 
1292     // Verify stencil buffer contents.
1293     if (hasStencil)
1294     {
1295         auto &verifAlloc = stencilVerifBuffer->getAllocation();
1296         invalidateAlloc(vkd, device, verifAlloc);
1297 
1298         tcu::TextureLevel referenceStencil(tcuStencilFormat, iExtent.x(), iExtent.y(), iExtent.z());
1299         auto referenceAccess     = referenceStencil.getAccess();
1300         const auto refStencilVal = static_cast<int>(stencilWrites ? stencilPassVal : stencilClearVal);
1301 
1302         for (int z = 0; z < iExtent.z(); ++z)
1303             for (int y = 0; y < iExtent.y(); ++y)
1304                 for (int x = 0; x < iExtent.x(); ++x)
1305                     referenceAccess.setPixStencil(refStencilVal, x, y, z);
1306 
1307         tcu::ConstPixelBufferAccess stencilPixels(tcuStencilFormat, iExtent, verifAlloc.getHostPtr());
1308         if (!tcu::dsThresholdCompare(log, "StencilResult", "", referenceAccess, stencilPixels, 0.0f,
1309                                      tcu::COMPARE_LOG_ON_ERROR))
1310             TCU_FAIL("Unexpected value in stencil buffer; check log for details");
1311     }
1312 
1313     // Verify output images.
1314     for (size_t bufferIdx = 0u; bufferIdx < storageVerifBuffers.size(); ++bufferIdx)
1315     {
1316         const auto &verifBuffer = storageVerifBuffers[bufferIdx];
1317         auto &verifAlloc        = verifBuffer->getAllocation();
1318         invalidateAlloc(vkd, device, verifAlloc);
1319 
1320         const auto bufferFormat    = getAspectStorageFormat(descriptors.at(bufferIdx).aspect);
1321         const auto tcuBufferFormat = mapVkFormat(bufferFormat);
1322         tcu::ConstPixelBufferAccess colorPixels(tcuBufferFormat, iExtent, verifAlloc.getHostPtr());
1323         const std::string resultName = "Storage" + de::toString(bufferIdx);
1324 
1325         if (descriptors.at(bufferIdx).aspect == VK_IMAGE_ASPECT_DEPTH_BIT)
1326         {
1327             if (!tcu::floatThresholdCompare(log, resultName.c_str(), "", tcu::Vec4(depthClearValue, 0.0f, 0.0f, 1.0f),
1328                                             colorPixels, tcu::Vec4(0.1f, 0.0f, 0.0f, 0.0f), tcu::COMPARE_LOG_ON_ERROR))
1329                 TCU_FAIL("Unexpected value in depth storage buffer " + de::toString(bufferIdx) +
1330                          "; check log for details");
1331         }
1332         else if (descriptors.at(bufferIdx).aspect == VK_IMAGE_ASPECT_STENCIL_BIT)
1333         {
1334             tcu::TextureLevel stencilRef(tcuBufferFormat, iExtent.x(), iExtent.y(), iExtent.z());
1335             auto colorPIxels = stencilRef.getAccess();
1336 
1337             for (int z = 0; z < iExtent.z(); ++z)
1338                 for (int y = 0; y < iExtent.y(); ++y)
1339                     for (int x = 0; x < iExtent.x(); ++x)
1340                         colorPIxels.setPixel(tcu::UVec4(stencilClearVal, 0u, 0u, 0u), x, y, z);
1341 
1342             if (!tcu::intThresholdCompare(log, resultName.c_str(), "", colorPIxels, colorPixels, tcu::UVec4(0u),
1343                                           tcu::COMPARE_LOG_ON_ERROR))
1344                 TCU_FAIL("Unexpected value in stencil storage buffer " + de::toString(bufferIdx) +
1345                          "; check log for details");
1346         }
1347         else
1348             DE_ASSERT(false);
1349     }
1350 
1351     return tcu::TestStatus::pass("Pass");
1352 }
1353 
1354 } // namespace
1355 
createImageDepthStencilDescriptorTests(tcu::TestContext & testCtx)1356 tcu::TestCaseGroup *createImageDepthStencilDescriptorTests(tcu::TestContext &testCtx)
1357 {
1358     using TestCaseGroupPtr = de::MovePtr<tcu::TestCaseGroup>;
1359 
1360     const VkFormat kDepthStencilFormats[] = {
1361         VK_FORMAT_D16_UNORM,         VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT,         VK_FORMAT_S8_UINT,
1362         VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_D32_SFLOAT_S8_UINT,
1363     };
1364 
1365     // Layouts used in these tests as VkDescriptorImageInfo::imageLayout.
1366     const VkImageLayout kTestedLayouts[] = {
1367         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
1368         VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
1369         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
1370         VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL,
1371     };
1372 
1373     // Types of read-only combinations to test.
1374     ROAccessVec kReadOnlyDSAttachment    = {ReadOnlyAccess::DS_ATTACHMENT};
1375     ROAccessVec kReadOnlyInputAttachment = {ReadOnlyAccess::INPUT_ATTACHMENT};
1376     ROAccessVec kReadOnlySampled         = {ReadOnlyAccess::SAMPLED};
1377     ROAccessVec kReadOnlyDSSampled       = {ReadOnlyAccess::DS_ATTACHMENT, ReadOnlyAccess::SAMPLED};
1378     ROAccessVec kReadOnlyInputSampled    = {ReadOnlyAccess::INPUT_ATTACHMENT, ReadOnlyAccess::SAMPLED};
1379 
1380     const ROAccessVec *kROAccessCases[] = {
1381         &kReadOnlyDSAttachment, &kReadOnlyInputAttachment, &kReadOnlySampled,
1382         &kReadOnlyDSSampled,    &kReadOnlyInputSampled,
1383     };
1384 
1385     const auto kLayoutPrefixLen = std::string("VK_IMAGE_LAYOUT_").size();
1386     const auto kFormatPrefixLen = std::string("VK_FORMAT_").size();
1387 
1388     // Tests using depth/stencil images as descriptors
1389     TestCaseGroupPtr mainGroup(new tcu::TestCaseGroup(testCtx, "depth_stencil_descriptor"));
1390 
1391     for (const auto &layout : kTestedLayouts)
1392     {
1393         const auto layoutStr       = de::toString(layout);
1394         const auto layoutGroupName = de::toLower(layoutStr.substr(kLayoutPrefixLen));
1395         const auto layoutGroupDesc = "Tests using the " + layoutStr + " layout";
1396 
1397         TestCaseGroupPtr layoutGroup(new tcu::TestCaseGroup(testCtx, layoutGroupName.c_str()));
1398 
1399         for (const auto &format : kDepthStencilFormats)
1400         {
1401             const auto formatStr       = de::toString(format);
1402             const auto formatGroupName = de::toLower(formatStr.substr(kFormatPrefixLen));
1403             const auto formatGroupDesc = "Tests using the " + formatStr + " format";
1404 
1405             TestCaseGroupPtr formatGroup(new tcu::TestCaseGroup(testCtx, formatGroupName.c_str()));
1406 
1407             const auto depthAccess   = getLegalAccess(layout, VK_IMAGE_ASPECT_DEPTH_BIT);
1408             const auto stencilAccess = getLegalAccess(layout, VK_IMAGE_ASPECT_STENCIL_BIT);
1409             const auto tcuFormat     = mapVkFormat(format);
1410 
1411             const auto hasDepthAccess   = (depthAccess != AspectAccess::NONE);
1412             const auto hasStencilAccess = (stencilAccess != AspectAccess::NONE);
1413             const auto hasDepth         = tcu::hasDepthComponent(tcuFormat.order);
1414             const auto hasStencil       = tcu::hasStencilComponent(tcuFormat.order);
1415 
1416             if (hasDepthAccess != hasDepth)
1417                 continue;
1418             if (hasStencilAccess != hasStencil)
1419                 continue;
1420 
1421             if (depthAccess == AspectAccess::RO)
1422             {
1423                 for (const auto &depthROCase : kROAccessCases)
1424                 {
1425                     const std::string depthPart = "depth_" + de::toString(*depthROCase);
1426                     if (stencilAccess == AspectAccess::RO)
1427                     {
1428                         for (const auto &stencilROCase : kROAccessCases)
1429                         {
1430                             if (incompatibleInputAttachmentAccess(depthAccess, depthROCase, stencilAccess,
1431                                                                   stencilROCase))
1432                                 continue;
1433 
1434                             const std::string stencilPart = "_stencil_" + de::toString(*stencilROCase);
1435                             const TestParams params       = {
1436                                 format,                    // VkFormat format;
1437                                 layout,                    // VkImageLayout layout;
1438                                 depthAccess,               // AspectAccess depthAccess;
1439                                 stencilAccess,             // AspectAccess stencilAccess;
1440                                 tcu::just(*depthROCase),   // tcu::Maybe<ROAccessVec> depthROAccesses;
1441                                 tcu::just(*stencilROCase), // tcu::Maybe<ROAccessVec> stencilROAccesses;
1442                             };
1443                             formatGroup->addChild(
1444                                 new DepthStencilDescriptorCase(testCtx, depthPart + stencilPart, params));
1445                         }
1446                     }
1447                     else
1448                     {
1449                         if (incompatibleInputAttachmentAccess(depthAccess, depthROCase, stencilAccess, nullptr))
1450                             continue;
1451 
1452                         const std::string stencilPart = "_stencil_" + de::toString(stencilAccess);
1453                         const TestParams params       = {
1454                             format,                  // VkFormat format;
1455                             layout,                  // VkImageLayout layout;
1456                             depthAccess,             // AspectAccess depthAccess;
1457                             stencilAccess,           // AspectAccess stencilAccess;
1458                             tcu::just(*depthROCase), // tcu::Maybe<ROAccessVec> depthROAccesses;
1459                             tcu::Nothing,            // tcu::Maybe<ROAccessVec> stencilROAccesses;
1460                         };
1461                         formatGroup->addChild(new DepthStencilDescriptorCase(testCtx, depthPart + stencilPart, params));
1462                     }
1463                 }
1464             }
1465             else
1466             {
1467                 const std::string depthPart = "depth_" + de::toString(depthAccess);
1468 
1469                 if (stencilAccess == AspectAccess::RO)
1470                 {
1471                     for (const auto &stencilROCase : kROAccessCases)
1472                     {
1473                         if (incompatibleInputAttachmentAccess(depthAccess, nullptr, stencilAccess, stencilROCase))
1474                             continue;
1475 
1476                         const std::string stencilPart = "_stencil_" + de::toString(*stencilROCase);
1477                         const TestParams params       = {
1478                             format,                    // VkFormat format;
1479                             layout,                    // VkImageLayout layout;
1480                             depthAccess,               // AspectAccess depthAccess;
1481                             stencilAccess,             // AspectAccess stencilAccess;
1482                             tcu::Nothing,              // tcu::Maybe<ROAccessVec> depthROAccesses;
1483                             tcu::just(*stencilROCase), // tcu::Maybe<ROAccessVec> stencilROAccesses;
1484                         };
1485                         formatGroup->addChild(new DepthStencilDescriptorCase(testCtx, depthPart + stencilPart, params));
1486                     }
1487                 }
1488                 else
1489                 {
1490                     if (incompatibleInputAttachmentAccess(depthAccess, nullptr, stencilAccess, nullptr))
1491                         continue;
1492 
1493                     const std::string stencilPart = "_stencil_" + de::toString(stencilAccess);
1494                     const TestParams params       = {
1495                         format,        // VkFormat format;
1496                         layout,        // VkImageLayout layout;
1497                         depthAccess,   // AspectAccess depthAccess;
1498                         stencilAccess, // AspectAccess stencilAccess;
1499                         tcu::Nothing,  // tcu::Maybe<ROAccessVec> depthROAccesses;
1500                         tcu::Nothing,  // tcu::Maybe<ROAccessVec> stencilROAccesses;
1501                     };
1502                     formatGroup->addChild(new DepthStencilDescriptorCase(testCtx, depthPart + stencilPart, params));
1503                 }
1504             }
1505 
1506             layoutGroup->addChild(formatGroup.release());
1507         }
1508 
1509         mainGroup->addChild(layoutGroup.release());
1510     }
1511 
1512     return mainGroup.release();
1513 }
1514 
1515 } // namespace image
1516 } // namespace vkt
1517