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 ¶ms);
~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 ¶ms);
~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 ¶ms)
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 ¶ms)
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, ©Region);
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, ©Region);
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, ©Region);
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, ©Region);
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