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