1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 Valve Corporation.
6  * Copyright (c) 2023 LunarG, Inc.
7  * Copyright (c) 2023 Nintendo
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief VK_EXT_attachment_feedback_loop_layout Tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineAttachmentFeedbackLoopLayoutTests.hpp"
27 #include "vktPipelineImageSamplingInstance.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktPipelineClearUtil.hpp"
32 
33 #include "vkImageUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkBarrierUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkImageWithMemory.hpp"
42 #include "vkBufferWithMemory.hpp"
43 
44 #include "tcuPlatform.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuMaybe.hpp"
49 
50 #include "deStringUtil.hpp"
51 #include "deMemory.h"
52 
53 #include <iomanip>
54 #include <sstream>
55 #include <vector>
56 #include <string>
57 #include <memory>
58 #include <utility>
59 #include <algorithm>
60 
61 namespace vkt
62 {
63 namespace pipeline
64 {
65 
66 using namespace vk;
67 using de::MovePtr;
68 
69 namespace
70 {
71 
72 enum TestMode
73 {
74     TEST_MODE_READ_ONLY             = 0,
75     TEST_MODE_WRITE_ONLY            = 1,
76     TEST_MODE_READ_WRITE_SAME_PIXEL = 2, // Sample from and write to the same pixel
77     TEST_MODE_READ_WRITE_DIFFERENT_AREAS =
78         3, // Sample from one half of the image and write the values to the other half
79 };
80 
81 enum ImageAspectTestMode
82 {
83     IMAGE_ASPECT_TEST_COLOR   = 0,
84     IMAGE_ASPECT_TEST_DEPTH   = 1,
85     IMAGE_ASPECT_TEST_STENCIL = 2,
86 };
87 
testModeToAspectFlags(ImageAspectTestMode testMode)88 VkImageAspectFlagBits testModeToAspectFlags(ImageAspectTestMode testMode)
89 {
90     switch (testMode)
91     {
92     case IMAGE_ASPECT_TEST_COLOR:
93         return VK_IMAGE_ASPECT_COLOR_BIT;
94     case IMAGE_ASPECT_TEST_DEPTH:
95         return VK_IMAGE_ASPECT_DEPTH_BIT;
96     case IMAGE_ASPECT_TEST_STENCIL:
97         return VK_IMAGE_ASPECT_STENCIL_BIT;
98     default:
99         break;
100     }
101 
102     DE_ASSERT(false);
103     return VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM;
104 }
105 
106 enum class PipelineStateMode
107 {
108     STATIC = 0,                        // Static only.
109     DYNAMIC_WITH_ZERO_STATIC,          // Dynamic, with static flags 0.
110     DYNAMIC_WITH_CONTRADICTORY_STATIC, // Dynamic, with static flags contradicting the dynamic state (see below).
111 };
112 
aspectFlagsToPipelineCreateFlags(VkImageAspectFlags aspectFlags)113 VkPipelineCreateFlags aspectFlagsToPipelineCreateFlags(VkImageAspectFlags aspectFlags)
114 {
115     VkPipelineCreateFlags pipelineFlags = 0u;
116 
117     if ((aspectFlags & VK_IMAGE_ASPECT_COLOR_BIT) != 0u)
118         pipelineFlags |= VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
119 
120     if ((aspectFlags & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0u)
121         pipelineFlags |= VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
122 
123     return pipelineFlags;
124 }
125 
getStaticPipelineCreateFlags(VkImageAspectFlags usedFlags,PipelineStateMode stateMode)126 VkPipelineCreateFlags getStaticPipelineCreateFlags(VkImageAspectFlags usedFlags, PipelineStateMode stateMode)
127 {
128     if (stateMode == PipelineStateMode::STATIC)
129         return aspectFlagsToPipelineCreateFlags(usedFlags);
130 
131     if (stateMode == PipelineStateMode::DYNAMIC_WITH_ZERO_STATIC)
132         return 0u;
133 
134     // Statically include all flags which are not present in the used flags that will be set dynamically.
135     VkPipelineCreateFlags pipelineStaticFlags = (VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
136                                                  VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
137     VkPipelineCreateFlags pipelineUsedFlags   = aspectFlagsToPipelineCreateFlags(usedFlags);
138 
139     pipelineStaticFlags &= (~pipelineUsedFlags);
140     return pipelineStaticFlags;
141 }
142 
143 // Output images are a square of this size
144 const int outputImageSize = 256;
145 
getImageAspectTestMode(const VkFormat format)146 ImageAspectTestMode getImageAspectTestMode(const VkFormat format)
147 {
148     if (tcu::hasDepthComponent(mapVkFormat(format).order))
149         return IMAGE_ASPECT_TEST_DEPTH;
150 
151     if (tcu::hasStencilComponent(mapVkFormat(format).order))
152         return IMAGE_ASPECT_TEST_STENCIL;
153 
154     return IMAGE_ASPECT_TEST_COLOR;
155 };
156 
157 class SamplerViewType
158 {
159 public:
SamplerViewType(vk::VkImageViewType type,bool normalized=true)160     SamplerViewType(vk::VkImageViewType type, bool normalized = true) : m_viewType(type), m_normalized(normalized)
161     {
162         if (!normalized)
163             DE_ASSERT(type == vk::VK_IMAGE_VIEW_TYPE_2D || type == vk::VK_IMAGE_VIEW_TYPE_1D);
164     }
165 
operator vk::VkImageViewType() const166     operator vk::VkImageViewType() const
167     {
168         return m_viewType;
169     }
170 
isNormalized() const171     bool isNormalized() const
172     {
173         return m_normalized;
174     }
175 
176 private:
177     vk::VkImageViewType m_viewType;
178     bool m_normalized;
179 };
180 
allocateImage(const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice & physDevice,const VkDevice device,const VkImage & image,const MemoryRequirement requirement,Allocator & allocator,AllocationKind allocationKind)181 de::MovePtr<Allocation> allocateImage(const InstanceInterface &vki, const DeviceInterface &vkd,
182                                       const VkPhysicalDevice &physDevice, const VkDevice device, const VkImage &image,
183                                       const MemoryRequirement requirement, Allocator &allocator,
184                                       AllocationKind allocationKind)
185 {
186     switch (allocationKind)
187     {
188     case ALLOCATION_KIND_SUBALLOCATED:
189     {
190         const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image);
191 
192         return allocator.allocate(memoryRequirements, requirement);
193     }
194 
195     case ALLOCATION_KIND_DEDICATED:
196     {
197         return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
198     }
199 
200     default:
201     {
202         TCU_THROW(InternalError, "Invalid allocation kind");
203     }
204     }
205 }
206 
allocateBuffer(const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice & physDevice,const VkDevice device,const VkBuffer & buffer,const MemoryRequirement requirement,Allocator & allocator,AllocationKind allocationKind)207 de::MovePtr<Allocation> allocateBuffer(const InstanceInterface &vki, const DeviceInterface &vkd,
208                                        const VkPhysicalDevice &physDevice, const VkDevice device,
209                                        const VkBuffer &buffer, const MemoryRequirement requirement,
210                                        Allocator &allocator, AllocationKind allocationKind)
211 {
212     switch (allocationKind)
213     {
214     case ALLOCATION_KIND_SUBALLOCATED:
215     {
216         const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer);
217 
218         return allocator.allocate(memoryRequirements, requirement);
219     }
220 
221     case ALLOCATION_KIND_DEDICATED:
222     {
223         return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
224     }
225 
226     default:
227     {
228         TCU_THROW(InternalError, "Invalid allocation kind");
229     }
230     }
231 }
232 
getCompatibleImageType(VkImageViewType viewType)233 static VkImageType getCompatibleImageType(VkImageViewType viewType)
234 {
235     switch (viewType)
236     {
237     case VK_IMAGE_VIEW_TYPE_1D:
238         return VK_IMAGE_TYPE_1D;
239     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
240         return VK_IMAGE_TYPE_1D;
241     case VK_IMAGE_VIEW_TYPE_2D:
242         return VK_IMAGE_TYPE_2D;
243     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
244         return VK_IMAGE_TYPE_2D;
245     case VK_IMAGE_VIEW_TYPE_3D:
246         return VK_IMAGE_TYPE_3D;
247     case VK_IMAGE_VIEW_TYPE_CUBE:
248         return VK_IMAGE_TYPE_2D;
249     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
250         return VK_IMAGE_TYPE_2D;
251     default:
252         break;
253     }
254 
255     DE_ASSERT(false);
256     return VK_IMAGE_TYPE_1D;
257 }
258 
259 template <typename TcuFormatType>
createTestTexture(const TcuFormatType format,VkImageViewType viewType,const tcu::IVec3 & size,int layerCount)260 static MovePtr<TestTexture> createTestTexture(const TcuFormatType format, VkImageViewType viewType,
261                                               const tcu::IVec3 &size, int layerCount)
262 {
263     MovePtr<TestTexture> texture;
264     const VkImageType imageType = getCompatibleImageType(viewType);
265 
266     switch (imageType)
267     {
268     case VK_IMAGE_TYPE_1D:
269         if (layerCount == 1)
270             texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
271         else
272             texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
273 
274         break;
275 
276     case VK_IMAGE_TYPE_2D:
277         if (layerCount == 1)
278         {
279             texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
280         }
281         else
282         {
283             if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
284             {
285                 if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE)
286                 {
287                     texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
288                 }
289                 else
290                 {
291                     DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
292 
293                     texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
294                 }
295             }
296             else
297             {
298                 texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
299             }
300         }
301 
302         break;
303 
304     case VK_IMAGE_TYPE_3D:
305         texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
306         break;
307 
308     default:
309         DE_ASSERT(false);
310     }
311 
312     return texture;
313 }
314 
getAspectFlags(tcu::TextureFormat format)315 VkImageAspectFlags getAspectFlags(tcu::TextureFormat format)
316 {
317     VkImageAspectFlags aspectFlag = 0;
318     aspectFlag |= (tcu::hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0);
319     aspectFlag |= (tcu::hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
320 
321     if (!aspectFlag)
322         aspectFlag = VK_IMAGE_ASPECT_COLOR_BIT;
323 
324     return aspectFlag;
325 }
326 
getAspectFlags(VkFormat format)327 VkImageAspectFlags getAspectFlags(VkFormat format)
328 {
329     if (isCompressedFormat(format))
330         return VK_IMAGE_ASPECT_COLOR_BIT;
331     else
332         return getAspectFlags(mapVkFormat(format));
333 }
334 
getSizeCompatibleTcuTextureFormat(VkFormat format)335 tcu::TextureFormat getSizeCompatibleTcuTextureFormat(VkFormat format)
336 {
337     if (isCompressedFormat(format))
338         return (getBlockSizeInBytes(format) == 8) ? mapVkFormat(VK_FORMAT_R16G16B16A16_UINT) :
339                                                     mapVkFormat(VK_FORMAT_R32G32B32A32_UINT);
340     else
341         return mapVkFormat(format);
342 }
343 
344 // Utilities to create test nodes
getFormatCaseName(const VkFormat format)345 std::string getFormatCaseName(const VkFormat format)
346 {
347     const std::string fullName = getFormatName(format);
348 
349     DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
350 
351     return de::toLower(fullName.substr(10));
352 }
353 
354 class AttachmentFeedbackLoopLayoutImageSamplingInstance : public ImageSamplingInstance
355 {
356 public:
357     AttachmentFeedbackLoopLayoutImageSamplingInstance(Context &context, ImageSamplingInstanceParams params,
358                                                       bool useImageAsColorOrDSAttachment_,
359                                                       bool useDifferentAreasSampleWrite_,
360                                                       bool interleaveReadWriteComponents_,
361                                                       ImageAspectTestMode imageAspectTestMode,
362                                                       PipelineStateMode pipelineStateMode, bool useMaintenance5_);
363 
364     virtual ~AttachmentFeedbackLoopLayoutImageSamplingInstance(void);
365 
366     virtual tcu::TestStatus iterate(void) override;
367 
368 protected:
369     virtual tcu::TestStatus verifyImage(void) override;
370     virtual void setup(void) override;
371 
372     ImageSamplingInstanceParams m_params;
373     const bool m_useImageAsColorOrDSAttachment;
374     const bool m_useDifferentAreasSampleWrite;
375     const bool m_interleaveReadWriteComponents;
376     const ImageAspectTestMode m_imageAspectTestMode;
377     const PipelineStateMode m_pipelineStateMode;
378     const bool m_useMaintenance5;
379 };
380 
381 class AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance
382     : public AttachmentFeedbackLoopLayoutImageSamplingInstance
383 {
384 public:
385     AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(
386         Context &context, ImageSamplingInstanceParams params, bool useImageAsColorOrDSAttachment_,
387         bool useDifferentAreasSampleWrite_, bool interleaveReadWriteComponents_,
388         ImageAspectTestMode imageAspectTestMode, PipelineStateMode pipelineStateMode, bool useMaintenance5_);
389 
390     virtual ~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(void);
391 
392     virtual tcu::TestStatus iterate(void) override;
393 
394 protected:
395     virtual tcu::TestStatus verifyImage(void) override;
396     virtual void setup(void) override;
397 
398     bool m_separateStencilUsage;
399 
400     std::vector<SharedImagePtr> m_dsImages;
401     std::vector<SharedAllocPtr> m_dsImageAllocs;
402     std::vector<SharedImageViewPtr> m_dsAttachmentViews;
403 };
404 
AttachmentFeedbackLoopLayoutImageSamplingInstance(Context & context,ImageSamplingInstanceParams params,bool useImageAsColorOrDSAttachment_,bool useDifferentAreasSampleWrite_,bool interleaveReadWriteComponents_,ImageAspectTestMode imageAspectTestMode,PipelineStateMode pipelineStateMode,bool useMaintenance5_)405 AttachmentFeedbackLoopLayoutImageSamplingInstance::AttachmentFeedbackLoopLayoutImageSamplingInstance(
406     Context &context, ImageSamplingInstanceParams params, bool useImageAsColorOrDSAttachment_,
407     bool useDifferentAreasSampleWrite_, bool interleaveReadWriteComponents_, ImageAspectTestMode imageAspectTestMode,
408     PipelineStateMode pipelineStateMode, bool useMaintenance5_)
409     : ImageSamplingInstance(context, params)
410     , m_params(params)
411     , m_useImageAsColorOrDSAttachment(useImageAsColorOrDSAttachment_)
412     , m_useDifferentAreasSampleWrite(useDifferentAreasSampleWrite_)
413     , m_interleaveReadWriteComponents(interleaveReadWriteComponents_)
414     , m_imageAspectTestMode(imageAspectTestMode)
415     , m_pipelineStateMode(pipelineStateMode)
416     , m_useMaintenance5(useMaintenance5_)
417 {
418 }
419 
setup(void)420 void AttachmentFeedbackLoopLayoutImageSamplingInstance::setup(void)
421 {
422     const InstanceInterface &vki      = m_context.getInstanceInterface();
423     const DeviceInterface &vk         = m_context.getDeviceInterface();
424     const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
425     const VkDevice vkDevice           = m_context.getDevice();
426     const VkQueue queue               = m_context.getUniversalQueue();
427     const uint32_t queueFamilyIndex   = m_context.getUniversalQueueFamilyIndex();
428     SimpleAllocator memAlloc(
429         vk, vkDevice,
430         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
431     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
432                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
433     tcu::UVec2 renderSize                         = m_useImageAsColorOrDSAttachment ?
434                                                         tcu::UVec2({(unsigned)m_imageSize.x(), (unsigned)m_imageSize.y()}) :
435                                                         m_renderSize;
436 
437     DE_ASSERT(m_samplerParams.pNext == DE_NULL);
438 
439     // Create texture images, views and samplers
440     {
441         VkImageCreateFlags imageFlags = 0u;
442 
443         if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
444             imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
445 
446         // Initialize texture data
447         if (isCompressedFormat(m_imageFormat))
448             m_texture =
449                 createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
450         else
451             m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
452 
453         VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
454                                             VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
455                                             VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
456 
457         if (isDepthStencilFormat(m_imageFormat))
458             imageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
459         else
460             imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
461 
462         const VkImageCreateInfo imageParams = {
463             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,     // VkStructureType sType;
464             DE_NULL,                                 // const void* pNext;
465             imageFlags,                              // VkImageCreateFlags flags;
466             getCompatibleImageType(m_imageViewType), // VkImageType imageType;
467             m_imageFormat,                           // VkFormat format;
468             {                                        // VkExtent3D extent;
469              (uint32_t)m_imageSize.x(), (uint32_t)m_imageSize.y(), (uint32_t)m_imageSize.z()},
470             (uint32_t)m_texture->getNumLevels(), // uint32_t mipLevels;
471             (uint32_t)m_layerCount,              // uint32_t arrayLayers;
472             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
473             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
474             imageUsageFlags,                     // VkImageUsageFlags usage;
475             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
476             1u,                                  // uint32_t queueFamilyIndexCount;
477             &queueFamilyIndex,                   // const uint32_t* pQueueFamilyIndices;
478             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
479         };
480 
481         checkImageSupport(vki, physDevice, imageParams);
482 
483         m_images.resize(m_imageCount);
484         m_imageAllocs.resize(m_imageCount);
485         m_imageViews.resize(m_imageCount);
486 
487         // Create command pool
488         m_cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
489         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
490 
491         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
492         {
493             m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
494             m_imageAllocs[imgNdx] =
495                 SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx],
496                                                              MemoryRequirement::Any, memAlloc, m_allocationKind)));
497             VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(),
498                                         (*m_imageAllocs[imgNdx])->getOffset()));
499 
500             // Upload texture data
501             uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx],
502                               m_imageLayout);
503 
504             // Create image view and sampler
505             const VkImageViewCreateInfo imageViewParams = {
506                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
507                 DE_NULL,                                  // const void* pNext;
508                 0u,                                       // VkImageViewCreateFlags flags;
509                 **m_images[imgNdx],                       // VkImage image;
510                 m_imageViewType,                          // VkImageViewType viewType;
511                 m_imageFormat,                            // VkFormat format;
512                 m_componentMapping,                       // VkComponentMapping components;
513                 m_subresourceRange,                       // VkImageSubresourceRange subresourceRange;
514             };
515 
516             m_imageViews[imgNdx] =
517                 SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
518         }
519 
520         m_sampler = createSampler(vk, vkDevice, &m_samplerParams);
521     }
522 
523     // Create descriptor set for image and sampler
524     {
525         DescriptorPoolBuilder descriptorPoolBuilder;
526         if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
527             descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
528         descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
529         m_descriptorPool = descriptorPoolBuilder.build(
530             vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
531             m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
532 
533         DescriptorSetLayoutBuilder setLayoutBuilder;
534         if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
535             setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
536         setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
537         m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
538 
539         const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
540             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
541             DE_NULL,                                        // const void* pNext;
542             *m_descriptorPool,                              // VkDescriptorPool descriptorPool;
543             1u,                                             // uint32_t setLayoutCount;
544             &m_descriptorSetLayout.get()                    // const VkDescriptorSetLayout* pSetLayouts;
545         };
546 
547         m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
548 
549         const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
550         std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
551         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
552         {
553             descriptorImageInfo[imgNdx].sampler     = sampler;                // VkSampler sampler;
554             descriptorImageInfo[imgNdx].imageView   = **m_imageViews[imgNdx]; // VkImageView imageView;
555             descriptorImageInfo[imgNdx].imageLayout = m_imageLayout;          // VkImageLayout imageLayout;
556         }
557 
558         DescriptorSetUpdateBuilder setUpdateBuilder;
559         if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
560         {
561             const VkDescriptorImageInfo descriptorSamplerInfo = {
562                 *m_sampler,    // VkSampler sampler;
563                 DE_NULL,       // VkImageView imageView;
564                 m_imageLayout, // VkImageLayout imageLayout;
565             };
566             setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0),
567                                          VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
568         }
569 
570         const uint32_t binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
571         setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding),
572                                     m_samplingType, m_imageCount, descriptorImageInfo.data());
573         setUpdateBuilder.update(vk, vkDevice);
574     }
575 
576     // Create color images and views
577     {
578         const VkImageCreateInfo colorImageParams = {
579             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
580             DE_NULL,                                                               // const void* pNext;
581             0u,                                                                    // VkImageCreateFlags flags;
582             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
583             m_colorFormat,                                                         // VkFormat format;
584             {(uint32_t)renderSize.x(), (uint32_t)renderSize.y(), 1u},              // VkExtent3D extent;
585             1u,                                                                    // uint32_t mipLevels;
586             1u,                                                                    // uint32_t arrayLayers;
587             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
588             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
589             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
590             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
591             1u,                                                                    // uint32_t queueFamilyIndexCount;
592             &queueFamilyIndex,        // const uint32_t* pQueueFamilyIndices;
593             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
594         };
595 
596         checkImageSupport(vki, physDevice, colorImageParams);
597 
598         m_colorImages.resize(m_imageCount);
599         m_colorImageAllocs.resize(m_imageCount);
600         m_colorAttachmentViews.resize(m_imageCount);
601 
602         if (m_useImageAsColorOrDSAttachment)
603         {
604             for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
605             {
606                 m_colorImages[imgNdx]          = m_images[imgNdx];
607                 m_colorImageAllocs[imgNdx]     = m_imageAllocs[imgNdx];
608                 m_colorAttachmentViews[imgNdx] = m_imageViews[imgNdx];
609             }
610         }
611         else
612         {
613             for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
614             {
615                 m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams)));
616                 m_colorImageAllocs[imgNdx] =
617                     SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_colorImages[imgNdx],
618                                                                  MemoryRequirement::Any, memAlloc, m_allocationKind)));
619                 VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx],
620                                             (*m_colorImageAllocs[imgNdx])->getMemory(),
621                                             (*m_colorImageAllocs[imgNdx])->getOffset()));
622 
623                 const VkImageViewCreateInfo colorAttachmentViewParams = {
624                     VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
625                     DE_NULL,                                    // const void* pNext;
626                     0u,                                         // VkImageViewCreateFlags flags;
627                     **m_colorImages[imgNdx],                    // VkImage image;
628                     VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
629                     m_colorFormat,                              // VkFormat format;
630                     componentMappingRGBA,                       // VkComponentMapping components;
631                     {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
632                 };
633 
634                 m_colorAttachmentViews[imgNdx] =
635                     SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams)));
636             }
637         }
638     }
639 
640     // Create render pass
641     {
642         std::vector<VkAttachmentDescription> attachmentDescriptions(m_imageCount);
643         std::vector<VkAttachmentReference> attachmentReferences(m_imageCount);
644 
645         VkAttachmentLoadOp loadOp =
646             m_useImageAsColorOrDSAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
647         VkImageLayout imageLayout =
648             m_useImageAsColorOrDSAttachment ? m_imageLayout : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
649 
650         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
651         {
652             attachmentDescriptions[imgNdx].flags = 0u; // VkAttachmentDescriptionFlags flags;
653             attachmentDescriptions[imgNdx].format =
654                 m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat;  // VkFormat format;
655             attachmentDescriptions[imgNdx].samples       = VK_SAMPLE_COUNT_1_BIT; // VkSampleCountFlagBits samples;
656             attachmentDescriptions[imgNdx].loadOp        = loadOp;                // VkAttachmentLoadOp loadOp;
657             attachmentDescriptions[imgNdx].storeOp       = VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp storeOp;
658             attachmentDescriptions[imgNdx].stencilLoadOp = loadOp; // VkAttachmentLoadOp stencilLoadOp;
659             attachmentDescriptions[imgNdx].stencilStoreOp =
660                 VK_ATTACHMENT_STORE_OP_STORE;                           // VkAttachmentStoreOp stencilStoreOp;
661             attachmentDescriptions[imgNdx].initialLayout = imageLayout; // VkImageLayout initialLayout;
662             attachmentDescriptions[imgNdx].finalLayout   = imageLayout; // VkImageLayout finalLayout;
663 
664             attachmentReferences[imgNdx].attachment = (uint32_t)imgNdx; // uint32_t attachment;
665             attachmentReferences[imgNdx].layout     = imageLayout;      // VkImageLayout layout;
666         }
667 
668         const VkSubpassDescription subpassDescription = {
669             0u,                              // VkSubpassDescriptionFlags flags;
670             VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
671             0u,                              // uint32_t inputAttachmentCount;
672             DE_NULL,                         // const VkAttachmentReference* pInputAttachments;
673             (uint32_t)m_imageCount,          // uint32_t colorAttachmentCount;
674             &attachmentReferences[0],        // const VkAttachmentReference* pColorAttachments;
675             DE_NULL,                         // const VkAttachmentReference* pResolveAttachments;
676             DE_NULL,                         // const VkAttachmentReference* pDepthStencilAttachment;
677             0u,                              // uint32_t preserveAttachmentCount;
678             DE_NULL                          // const VkAttachmentReference* pPreserveAttachments;
679         };
680 
681         std::vector<VkSubpassDependency> subpassDependencies;
682 
683         if (m_useImageAsColorOrDSAttachment)
684         {
685             const VkSubpassDependency spdVal = {
686                 0u,                                                                // uint32_t srcSubpass;
687                 0u,                                                                // uint32_t dstSubpass;
688                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,                             // VkPipelineStageFlags srcStageMask;
689                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,                     // VkPipelineStageFlags dstStageMask;
690                 VK_ACCESS_SHADER_READ_BIT,                                         // VkAccessFlags srcAccessMask;
691                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                              // VkAccessFlags dstAccessMask;
692                 VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT | VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
693             };
694 
695             subpassDependencies.push_back(spdVal);
696         }
697 
698         const VkRenderPassCreateInfo renderPassParams = {
699             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,         // VkStructureType sType;
700             DE_NULL,                                           // const void* pNext;
701             0u,                                                // VkRenderPassCreateFlags flags;
702             (uint32_t)attachmentDescriptions.size(),           // uint32_t attachmentCount;
703             &attachmentDescriptions[0],                        // const VkAttachmentDescription* pAttachments;
704             1u,                                                // uint32_t subpassCount;
705             &subpassDescription,                               // const VkSubpassDescription* pSubpasses;
706             static_cast<uint32_t>(subpassDependencies.size()), // uint32_t dependencyCount;
707             de::dataOrNull(subpassDependencies),               // const VkSubpassDependency* pDependencies;
708         };
709 
710         m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
711     }
712 
713     // Create framebuffer
714     {
715         std::vector<VkImage> images(m_imageCount);
716         std::vector<VkImageView> pAttachments(m_imageCount);
717         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
718         {
719             images[imgNdx]       = m_colorImages[imgNdx]->get();
720             pAttachments[imgNdx] = m_colorAttachmentViews[imgNdx]->get();
721         }
722 
723         const VkFramebufferCreateInfo framebufferParams = {
724             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
725             DE_NULL,                                   // const void* pNext;
726             0u,                                        // VkFramebufferCreateFlags flags;
727             *m_renderPass,                             // VkRenderPass renderPass;
728             (uint32_t)m_imageCount,                    // uint32_t attachmentCount;
729             &pAttachments[0],                          // const VkImageView* pAttachments;
730             (uint32_t)renderSize.x(),                  // uint32_t width;
731             (uint32_t)renderSize.y(),                  // uint32_t height;
732             1u                                         // uint32_t layers;
733         };
734 
735         m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
736     }
737 
738     // Create pipeline layouts
739     {
740         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
741             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // VkStructureType sType;
742             DE_NULL,                                            // const void* pNext;
743             VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, // VkPipelineLayoutCreateFlags flags;
744             0u,                                                 // uint32_t setLayoutCount;
745             DE_NULL,                                            // const VkDescriptorSetLayout* pSetLayouts;
746             0u,                                                 // uint32_t pushConstantRangeCount;
747             DE_NULL                                             // const VkPushConstantRange* pPushConstantRanges;
748         };
749 
750         m_preRasterizationStatePipelineLayout =
751             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
752     }
753     {
754         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
755             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // VkStructureType sType;
756             DE_NULL,                                            // const void* pNext;
757             VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, // VkPipelineLayoutCreateFlags flags;
758             1u,                                                 // uint32_t setLayoutCount;
759             &m_descriptorSetLayout.get(),                       // const VkDescriptorSetLayout* pSetLayouts;
760             0u,                                                 // uint32_t pushConstantRangeCount;
761             DE_NULL                                             // const VkPushConstantRange* pPushConstantRanges;
762         };
763 
764         m_fragmentStatePipelineLayout =
765             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
766     }
767 
768     m_vertexShaderModule   = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
769     m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
770 
771     // Create pipeline
772     {
773         const VkVertexInputBindingDescription vertexInputBindingDescription = {
774             0u,                         // uint32_t binding;
775             sizeof(Vertex4Tex4),        // uint32_t strideInBytes;
776             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
777         };
778 
779         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
780             {
781                 0u,                            // uint32_t location;
782                 0u,                            // uint32_t binding;
783                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
784                 0u                             // uint32_t offset;
785             },
786             {
787                 1u,                              // uint32_t location;
788                 0u,                              // uint32_t binding;
789                 VK_FORMAT_R32G32B32A32_SFLOAT,   // VkFormat format;
790                 offsetof(Vertex4Tex4, texCoord), // uint32_t offset;
791             }};
792 
793         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
794             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
795             DE_NULL,                                                   // const void* pNext;
796             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
797             1u,                                                        // uint32_t vertexBindingDescriptionCount;
798             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
799             2u,                              // uint32_t vertexAttributeDescriptionCount;
800             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
801         };
802 
803         const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
804         const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
805 
806         std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_imageCount);
807 
808         VkColorComponentFlags colorComponents =
809             VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
810 
811         if (m_interleaveReadWriteComponents)
812             colorComponents = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_B_BIT;
813 
814         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
815         {
816             colorBlendAttachmentStates[imgNdx].blendEnable = false; // VkBool32 blendEnable;
817             colorBlendAttachmentStates[imgNdx].srcColorBlendFactor =
818                 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcColorBlendFactor;
819             colorBlendAttachmentStates[imgNdx].dstColorBlendFactor =
820                 VK_BLEND_FACTOR_ZERO;                                          // VkBlendFactor dstColorBlendFactor;
821             colorBlendAttachmentStates[imgNdx].colorBlendOp = VK_BLEND_OP_ADD; // VkBlendOp colorBlendOp;
822             colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor =
823                 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcAlphaBlendFactor;
824             colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor =
825                 VK_BLEND_FACTOR_ZERO;                                          // VkBlendFactor dstAlphaBlendFactor;
826             colorBlendAttachmentStates[imgNdx].alphaBlendOp = VK_BLEND_OP_ADD; // VkBlendOp alphaBlendOp;
827             colorBlendAttachmentStates[imgNdx].colorWriteMask =
828                 colorComponents; // VkColorComponentFlags colorWriteMask;
829         }
830 
831         const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
832             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
833             DE_NULL,                                                  // const void* pNext;
834             0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
835             false,                                                    // VkBool32 logicOpEnable;
836             VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
837             (uint32_t)m_imageCount,                                   // uint32_t attachmentCount;
838             &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
839             {0.0f, 0.0f, 0.0f, 0.0f}        // float blendConstants[4];
840         };
841 
842         std::vector<VkDynamicState> dynamicStates;
843         if (m_pipelineStateMode != PipelineStateMode::STATIC)
844             dynamicStates.push_back(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
845 
846         const VkPipelineDynamicStateCreateInfo dynamicStateInfo = {
847             VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
848             nullptr,
849             0u,
850             de::sizeU32(dynamicStates),
851             de::dataOrNull(dynamicStates),
852         };
853 
854         if (m_useMaintenance5)
855             m_graphicsPipeline.setPipelineCreateFlags2(translateCreateFlag(m_params.pipelineCreateFlags));
856 
857         m_graphicsPipeline.setDynamicState(&dynamicStateInfo)
858             .setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
859             .setDefaultDepthStencilState()
860             .setDefaultRasterizationState()
861             .setDefaultMultisampleState()
862             .setupVertexInputState(&vertexInputStateParams)
863             .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
864                                               0u, m_vertexShaderModule)
865             .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
866             .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
867             .buildPipeline();
868     }
869 
870     // Create vertex buffer
871     {
872         const VkDeviceSize vertexBufferSize         = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
873         const VkBufferCreateInfo vertexBufferParams = {
874             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
875             DE_NULL,                              // const void* pNext;
876             0u,                                   // VkBufferCreateFlags flags;
877             vertexBufferSize,                     // VkDeviceSize size;
878             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,    // VkBufferUsageFlags usage;
879             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
880             1u,                                   // uint32_t queueFamilyIndexCount;
881             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
882         };
883 
884         DE_ASSERT(vertexBufferSize > 0);
885 
886         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
887         m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer,
888                                              MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
889         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
890                                      m_vertexBufferAlloc->getOffset()));
891 
892         // Load vertices into vertex buffer
893         deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
894         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
895     }
896 
897     // Create command buffer
898     {
899         VkFormat clearFormat = m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat;
900         const std::vector<VkClearValue> attachmentClearValues(m_imageCount, defaultClearValue(clearFormat));
901 
902         std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
903 
904         VkAccessFlags dstAccessMask             = isDepthStencilFormat(m_imageFormat) ?
905                                                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT :
906                                                       VK_ACCESS_SHADER_READ_BIT;
907         VkPipelineStageFlags pipelineStageFlags = isDepthStencilFormat(m_imageFormat) ?
908                                                       VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT :
909                                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
910 
911         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
912         {
913             preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
914             preAttachmentBarriers[imgNdx].pNext = DE_NULL;                                // const void* pNext;
915             preAttachmentBarriers[imgNdx].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; // VkAccessFlags srcAccessMask;
916             preAttachmentBarriers[imgNdx].dstAccessMask = dstAccessMask;                // VkAccessFlags dstAccessMask;
917             preAttachmentBarriers[imgNdx].oldLayout     = m_imageLayout;                // VkImageLayout oldLayout;
918             preAttachmentBarriers[imgNdx].newLayout     = m_imageLayout;                // VkImageLayout newLayout;
919             preAttachmentBarriers[imgNdx].srcQueueFamilyIndex =
920                 VK_QUEUE_FAMILY_IGNORED; // uint32_t srcQueueFamilyIndex;
921             preAttachmentBarriers[imgNdx].dstQueueFamilyIndex =
922                 VK_QUEUE_FAMILY_IGNORED;                              // uint32_t dstQueueFamilyIndex;
923             preAttachmentBarriers[imgNdx].image = **m_images[imgNdx]; // VkImage image;
924             preAttachmentBarriers[imgNdx].subresourceRange =
925                 m_subresourceRange; // VkImageSubresourceRange subresourceRange;
926         }
927 
928         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
929 
930         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, pipelineStageFlags, (VkDependencyFlags)0,
931                               0u, DE_NULL, 0u, DE_NULL, (uint32_t)m_imageCount, &preAttachmentBarriers[0]);
932 
933         if (!m_useImageAsColorOrDSAttachment)
934         {
935             // Pipeline barrier for the color attachment, which is a different image than the sampled one.
936             for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
937             {
938                 preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
939                 preAttachmentBarriers[imgNdx].pNext = DE_NULL;                                // const void* pNext;
940                 preAttachmentBarriers[imgNdx].srcAccessMask = (VkAccessFlagBits)0u; // VkAccessFlags srcAccessMask;
941                 preAttachmentBarriers[imgNdx].dstAccessMask =
942                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;                            // VkAccessFlags dstAccessMask;
943                 preAttachmentBarriers[imgNdx].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; // VkImageLayout oldLayout;
944                 preAttachmentBarriers[imgNdx].newLayout =
945                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout newLayout;
946                 preAttachmentBarriers[imgNdx].srcQueueFamilyIndex =
947                     VK_QUEUE_FAMILY_IGNORED; // uint32_t srcQueueFamilyIndex;
948                 preAttachmentBarriers[imgNdx].dstQueueFamilyIndex =
949                     VK_QUEUE_FAMILY_IGNORED;                                   // uint32_t dstQueueFamilyIndex;
950                 preAttachmentBarriers[imgNdx].image = **m_colorImages[imgNdx]; // VkImage image;
951                 preAttachmentBarriers[imgNdx].subresourceRange.aspectMask =
952                     getAspectFlags(m_colorFormat); // VkImageSubresourceRange subresourceRange;
953                 preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel   = 0u;
954                 preAttachmentBarriers[imgNdx].subresourceRange.levelCount     = 1u;
955                 preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer = 0u;
956                 preAttachmentBarriers[imgNdx].subresourceRange.layerCount     = 1u;
957             }
958 
959             vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
960                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 0u,
961                                   DE_NULL, (uint32_t)m_imageCount, &preAttachmentBarriers[0]);
962 
963             m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()),
964                                (uint32_t)attachmentClearValues.size(), &attachmentClearValues[0]);
965         }
966         else
967         {
968             // Do not clear the color attachments as we are using the sampled texture as color attachment as well.
969             m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), 0u, DE_NULL);
970         }
971 
972         m_graphicsPipeline.bind(*m_cmdBuffer);
973 
974         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1,
975                                  &m_descriptorSet.get(), 0, DE_NULL);
976 
977         const VkDeviceSize vertexBufferOffset = 0;
978         vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
979 
980         if (m_pipelineStateMode != PipelineStateMode::STATIC)
981             vk.cmdSetAttachmentFeedbackLoopEnableEXT(*m_cmdBuffer, testModeToAspectFlags(m_imageAspectTestMode));
982 
983         vk.cmdDraw(*m_cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
984 
985         m_renderPass.end(vk, *m_cmdBuffer);
986         endCommandBuffer(vk, *m_cmdBuffer);
987     }
988 }
989 
990 AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::
AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(Context & context,ImageSamplingInstanceParams params,bool useImageAsColorOrDSAttachment_,bool useDifferentAreasSampleWrite_,bool interleaveReadWriteComponents_,ImageAspectTestMode imageAspectTestMode,PipelineStateMode pipelineStateMode,bool useMaintenance5_)991     AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(
992         Context &context, ImageSamplingInstanceParams params, bool useImageAsColorOrDSAttachment_,
993         bool useDifferentAreasSampleWrite_, bool interleaveReadWriteComponents_,
994         ImageAspectTestMode imageAspectTestMode, PipelineStateMode pipelineStateMode, bool useMaintenance5_)
995     : AttachmentFeedbackLoopLayoutImageSamplingInstance(context, params, useImageAsColorOrDSAttachment_,
996                                                         useDifferentAreasSampleWrite_, interleaveReadWriteComponents_,
997                                                         imageAspectTestMode, pipelineStateMode, useMaintenance5_)
998     , m_separateStencilUsage(params.separateStencilUsage)
999 {
1000 }
1001 
1002 AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::
~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(void)1003     ~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(void)
1004 {
1005 }
1006 
setup(void)1007 void AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::setup(void)
1008 {
1009     const InstanceInterface &vki      = m_context.getInstanceInterface();
1010     const DeviceInterface &vk         = m_context.getDeviceInterface();
1011     const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1012     const VkDevice vkDevice           = m_context.getDevice();
1013     const VkQueue queue               = m_context.getUniversalQueue();
1014     const uint32_t queueFamilyIndex   = m_context.getUniversalQueueFamilyIndex();
1015     SimpleAllocator memAlloc(
1016         vk, vkDevice,
1017         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1018     tcu::UVec2 renderSize = tcu::UVec2({(unsigned)m_imageSize.x(), (unsigned)m_imageSize.y()});
1019 
1020     DE_ASSERT(m_useImageAsColorOrDSAttachment && isDepthStencilFormat(m_imageFormat));
1021     DE_ASSERT(m_samplerParams.pNext == DE_NULL);
1022 
1023     // Create texture images, views
1024     {
1025         VkImageCreateFlags imageFlags = 0u;
1026 
1027         if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
1028             imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
1029 
1030         // Initialize texture data
1031         if (isCompressedFormat(m_imageFormat))
1032             m_texture =
1033                 createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
1034         else
1035             m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
1036 
1037         VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1038                                             VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
1039                                             VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1040                                             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1041 
1042         const VkImageCreateInfo imageParams = {
1043             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,     // VkStructureType sType;
1044             DE_NULL,                                 // const void* pNext;
1045             imageFlags,                              // VkImageCreateFlags flags;
1046             getCompatibleImageType(m_imageViewType), // VkImageType imageType;
1047             m_imageFormat,                           // VkFormat format;
1048             {                                        // VkExtent3D extent;
1049              (uint32_t)m_imageSize.x(), (uint32_t)m_imageSize.y(), (uint32_t)m_imageSize.z()},
1050             (uint32_t)m_texture->getNumLevels(), // uint32_t mipLevels;
1051             (uint32_t)m_layerCount,              // uint32_t arrayLayers;
1052             VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
1053             VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
1054             imageUsageFlags,                     // VkImageUsageFlags usage;
1055             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
1056             1u,                                  // uint32_t queueFamilyIndexCount;
1057             &queueFamilyIndex,                   // const uint32_t* pQueueFamilyIndices;
1058             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
1059         };
1060 
1061         checkImageSupport(vki, physDevice, imageParams);
1062 
1063         m_images.resize(m_imageCount);
1064         m_imageAllocs.resize(m_imageCount);
1065 
1066         // Create command pool
1067         m_cmdPool = createCommandPool(
1068             vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1069             queueFamilyIndex);
1070         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1071 
1072         int numImageViews = m_interleaveReadWriteComponents ? m_imageCount + 1 : m_imageCount;
1073         m_imageViews.resize(numImageViews);
1074 
1075         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1076         {
1077             m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
1078             m_imageAllocs[imgNdx] =
1079                 SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx],
1080                                                              MemoryRequirement::Any, memAlloc, m_allocationKind)));
1081             VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(),
1082                                         (*m_imageAllocs[imgNdx])->getOffset()));
1083 
1084             // Upload texture data
1085             uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx],
1086                               m_imageLayout);
1087         }
1088 
1089         for (int imgNdx = 0; imgNdx < numImageViews; ++imgNdx)
1090         {
1091             VkImage image = (m_interleaveReadWriteComponents && imgNdx == m_imageCount) ? **m_images[imgNdx - 1] :
1092                                                                                           **m_images[imgNdx];
1093 
1094             // Create image view and sampler
1095             VkImageViewCreateInfo imageViewParams = {
1096                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1097                 DE_NULL,                                  // const void* pNext;
1098                 0u,                                       // VkImageViewCreateFlags flags;
1099                 image,                                    // VkImage image;
1100                 m_imageViewType,                          // VkImageViewType viewType;
1101                 m_imageFormat,                            // VkFormat format;
1102                 m_componentMapping,                       // VkComponentMapping components;
1103                 m_subresourceRange,                       // VkImageSubresourceRange subresourceRange;
1104             };
1105 
1106             if (m_interleaveReadWriteComponents && imgNdx == m_imageCount)
1107             {
1108                 imageViewParams.subresourceRange.aspectMask = getImageAspectFlags(mapVkFormat(m_imageFormat));
1109             }
1110 
1111             m_imageViews[imgNdx] =
1112                 SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
1113         }
1114 
1115         m_sampler = createSampler(vk, vkDevice, &m_samplerParams);
1116     }
1117 
1118     // Create descriptor set for image and sampler
1119     {
1120         DescriptorPoolBuilder descriptorPoolBuilder;
1121         if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1122             descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
1123         descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
1124         m_descriptorPool = descriptorPoolBuilder.build(
1125             vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1126             m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
1127 
1128         DescriptorSetLayoutBuilder setLayoutBuilder;
1129         if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1130             setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
1131         setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
1132         m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
1133 
1134         const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
1135             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
1136             DE_NULL,                                        // const void* pNext;
1137             *m_descriptorPool,                              // VkDescriptorPool descriptorPool;
1138             1u,                                             // uint32_t setLayoutCount;
1139             &m_descriptorSetLayout.get()                    // const VkDescriptorSetLayout* pSetLayouts;
1140         };
1141 
1142         m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
1143 
1144         const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
1145         std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
1146         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1147         {
1148             descriptorImageInfo[imgNdx].sampler     = sampler;                // VkSampler sampler;
1149             descriptorImageInfo[imgNdx].imageView   = **m_imageViews[imgNdx]; // VkImageView imageView;
1150             descriptorImageInfo[imgNdx].imageLayout = m_imageLayout;          // VkImageLayout imageLayout;
1151         }
1152 
1153         DescriptorSetUpdateBuilder setUpdateBuilder;
1154         if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1155         {
1156             const VkDescriptorImageInfo descriptorSamplerInfo = {
1157                 *m_sampler,    // VkSampler sampler;
1158                 DE_NULL,       // VkImageView imageView;
1159                 m_imageLayout, // VkImageLayout imageLayout;
1160             };
1161             setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0),
1162                                          VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
1163         }
1164 
1165         const uint32_t binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
1166         setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding),
1167                                     m_samplingType, m_imageCount, descriptorImageInfo.data());
1168         setUpdateBuilder.update(vk, vkDevice);
1169     }
1170 
1171     // Create depth-stencil images and views, no color attachment
1172     {
1173         m_dsImages.resize(m_imageCount);
1174         m_dsImageAllocs.resize(m_imageCount);
1175         m_dsAttachmentViews.resize(m_imageCount);
1176 
1177         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1178         {
1179             m_dsImages[imgNdx]      = m_images[imgNdx];
1180             m_dsImageAllocs[imgNdx] = m_imageAllocs[imgNdx];
1181             m_dsAttachmentViews[imgNdx] =
1182                 m_interleaveReadWriteComponents ? m_imageViews[imgNdx + 1] : m_imageViews[imgNdx];
1183         }
1184     }
1185 
1186     // Create render pass
1187     {
1188         std::vector<VkAttachmentDescription> attachmentDescriptions(m_imageCount);
1189         std::vector<VkAttachmentReference> attachmentReferences(m_imageCount);
1190 
1191         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1192         {
1193             attachmentDescriptions[imgNdx].flags = 0u; // VkAttachmentDescriptionFlags flags;
1194             attachmentDescriptions[imgNdx].format =
1195                 m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat;   // VkFormat format;
1196             attachmentDescriptions[imgNdx].samples = VK_SAMPLE_COUNT_1_BIT;        // VkSampleCountFlagBits samples;
1197             attachmentDescriptions[imgNdx].loadOp  = VK_ATTACHMENT_LOAD_OP_LOAD;   // VkAttachmentLoadOp loadOp;
1198             attachmentDescriptions[imgNdx].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp storeOp;
1199             attachmentDescriptions[imgNdx].stencilLoadOp =
1200                 VK_ATTACHMENT_LOAD_OP_LOAD; // VkAttachmentLoadOp stencilLoadOp;
1201             attachmentDescriptions[imgNdx].stencilStoreOp =
1202                 VK_ATTACHMENT_STORE_OP_STORE;                             // VkAttachmentStoreOp stencilStoreOp;
1203             attachmentDescriptions[imgNdx].initialLayout = m_imageLayout; // VkImageLayout initialLayout;
1204             attachmentDescriptions[imgNdx].finalLayout   = m_imageLayout; // VkImageLayout finalLayout;
1205 
1206             attachmentReferences[imgNdx].attachment = (uint32_t)imgNdx; // uint32_t attachment;
1207             attachmentReferences[imgNdx].layout     = m_imageLayout;    // VkImageLayout layout;
1208         }
1209 
1210         const VkSubpassDescription subpassDescription = {
1211             0u,                              // VkSubpassDescriptionFlags flags;
1212             VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1213             0u,                              // uint32_t inputAttachmentCount;
1214             DE_NULL,                         // const VkAttachmentReference* pInputAttachments;
1215             0u,                              // uint32_t colorAttachmentCount;
1216             DE_NULL,                         // const VkAttachmentReference* pColorAttachments;
1217             DE_NULL,                         // const VkAttachmentReference* pResolveAttachments;
1218             &attachmentReferences[0],        // const VkAttachmentReference* pDepthStencilAttachment;
1219             0u,                              // uint32_t preserveAttachmentCount;
1220             DE_NULL                          // const VkAttachmentReference* pPreserveAttachments;
1221         };
1222 
1223         std::vector<VkSubpassDependency> subpassDependencies;
1224 
1225         if (m_useImageAsColorOrDSAttachment)
1226         {
1227             const auto srcStageMask  = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
1228             const auto srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
1229             const auto dstStageMask =
1230                 (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1231             const auto dstAccessMask =
1232                 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT);
1233 
1234             const VkSubpassDependency spdVal = {
1235                 0u,                                                                // uint32_t srcSubpass;
1236                 0u,                                                                // uint32_t dstSubpass;
1237                 srcStageMask,                                                      // VkPipelineStageFlags srcStageMask;
1238                 dstStageMask,                                                      // VkPipelineStageFlags dstStageMask;
1239                 srcAccessMask,                                                     // VkAccessFlags srcAccessMask;
1240                 dstAccessMask,                                                     // VkAccessFlags dstAccessMask;
1241                 VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT | VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
1242             };
1243 
1244             subpassDependencies.push_back(spdVal);
1245         }
1246 
1247         const VkRenderPassCreateInfo renderPassParams = {
1248             VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,         // VkStructureType sType;
1249             DE_NULL,                                           // const void* pNext;
1250             0u,                                                // VkRenderPassCreateFlags flags;
1251             (uint32_t)attachmentDescriptions.size(),           // uint32_t attachmentCount;
1252             &attachmentDescriptions[0],                        // const VkAttachmentDescription* pAttachments;
1253             1u,                                                // uint32_t subpassCount;
1254             &subpassDescription,                               // const VkSubpassDescription* pSubpasses;
1255             static_cast<uint32_t>(subpassDependencies.size()), // uint32_t dependencyCount;
1256             de::dataOrNull(subpassDependencies),               // const VkSubpassDependency* pDependencies;
1257         };
1258 
1259         m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
1260     }
1261 
1262     // Create framebuffer
1263     {
1264         std::vector<VkImage> images(m_imageCount);
1265         std::vector<VkImageView> pAttachments(m_imageCount);
1266         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1267         {
1268             images[imgNdx]       = m_dsImages[imgNdx]->get();
1269             pAttachments[imgNdx] = m_dsAttachmentViews[imgNdx]->get();
1270         }
1271 
1272         const VkFramebufferCreateInfo framebufferParams = {
1273             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1274             DE_NULL,                                   // const void* pNext;
1275             0u,                                        // VkFramebufferCreateFlags flags;
1276             *m_renderPass,                             // VkRenderPass renderPass;
1277             (uint32_t)m_imageCount,                    // uint32_t attachmentCount;
1278             &pAttachments[0],                          // const VkImageView* pAttachments;
1279             (uint32_t)renderSize.x(),                  // uint32_t width;
1280             (uint32_t)renderSize.y(),                  // uint32_t height;
1281             1u                                         // uint32_t layers;
1282         };
1283 
1284         m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
1285     }
1286 
1287     // Create pipeline layouts
1288     {
1289         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
1290             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1291             DE_NULL,                                       // const void* pNext;
1292             0u,                                            // VkPipelineLayoutCreateFlags flags;
1293             0u,                                            // uint32_t setLayoutCount;
1294             DE_NULL,                                       // const VkDescriptorSetLayout* pSetLayouts;
1295             0u,                                            // uint32_t pushConstantRangeCount;
1296             DE_NULL                                        // const VkPushConstantRange* pPushConstantRanges;
1297         };
1298 
1299         m_preRasterizationStatePipelineLayout =
1300             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1301     }
1302     {
1303         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
1304             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // VkStructureType sType;
1305             DE_NULL,                                            // const void* pNext;
1306             VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, // VkPipelineLayoutCreateFlags flags;
1307             0u,                                                 // uint32_t setLayoutCount;
1308             DE_NULL,                                            // const VkDescriptorSetLayout* pSetLayouts;
1309             0u,                                                 // uint32_t pushConstantRangeCount;
1310             DE_NULL                                             // const VkPushConstantRange* pPushConstantRanges;
1311         };
1312 
1313         m_preRasterizationStatePipelineLayout =
1314             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1315     }
1316     {
1317         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
1318             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // VkStructureType sType;
1319             DE_NULL,                                            // const void* pNext;
1320             VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, // VkPipelineLayoutCreateFlags flags;
1321             1u,                                                 // uint32_t setLayoutCount;
1322             &m_descriptorSetLayout.get(),                       // const VkDescriptorSetLayout* pSetLayouts;
1323             0u,                                                 // uint32_t pushConstantRangeCount;
1324             DE_NULL                                             // const VkPushConstantRange* pPushConstantRanges;
1325         };
1326 
1327         m_fragmentStatePipelineLayout =
1328             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1329     }
1330 
1331     m_vertexShaderModule   = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
1332     m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
1333 
1334     // Create pipeline
1335     {
1336         const VkVertexInputBindingDescription vertexInputBindingDescription = {
1337             0u,                         // uint32_t binding;
1338             sizeof(Vertex4Tex4),        // uint32_t strideInBytes;
1339             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
1340         };
1341 
1342         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
1343             {
1344                 0u,                            // uint32_t location;
1345                 0u,                            // uint32_t binding;
1346                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1347                 0u                             // uint32_t offset;
1348             },
1349             {
1350                 1u,                              // uint32_t location;
1351                 0u,                              // uint32_t binding;
1352                 VK_FORMAT_R32G32B32A32_SFLOAT,   // VkFormat format;
1353                 offsetof(Vertex4Tex4, texCoord), // uint32_t offset;
1354             }};
1355 
1356         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
1357             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1358             DE_NULL,                                                   // const void* pNext;
1359             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
1360             1u,                                                        // uint32_t vertexBindingDescriptionCount;
1361             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1362             2u,                              // uint32_t vertexAttributeDescriptionCount;
1363             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1364         };
1365 
1366         const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
1367         const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
1368 
1369         std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_imageCount);
1370 
1371         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1372         {
1373             colorBlendAttachmentStates[imgNdx].blendEnable = false; // VkBool32 blendEnable;
1374             colorBlendAttachmentStates[imgNdx].srcColorBlendFactor =
1375                 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcColorBlendFactor;
1376             colorBlendAttachmentStates[imgNdx].dstColorBlendFactor =
1377                 VK_BLEND_FACTOR_ZERO;                                          // VkBlendFactor dstColorBlendFactor;
1378             colorBlendAttachmentStates[imgNdx].colorBlendOp = VK_BLEND_OP_ADD; // VkBlendOp colorBlendOp;
1379             colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor =
1380                 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcAlphaBlendFactor;
1381             colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor =
1382                 VK_BLEND_FACTOR_ZERO;                                            // VkBlendFactor dstAlphaBlendFactor;
1383             colorBlendAttachmentStates[imgNdx].alphaBlendOp   = VK_BLEND_OP_ADD; // VkBlendOp alphaBlendOp;
1384             colorBlendAttachmentStates[imgNdx].colorWriteMask = 0u; // VkColorComponentFlags colorWriteMask;
1385         }
1386 
1387         const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
1388             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1389             DE_NULL,                                                  // const void* pNext;
1390             0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
1391             false,                                                    // VkBool32 logicOpEnable;
1392             VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
1393             0u,                                                       // uint32_t attachmentCount;
1394             DE_NULL,                 // const VkPipelineColorBlendAttachmentState* pAttachments;
1395             {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
1396         };
1397 
1398         VkBool32 depthTestEnable =
1399             ((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) && !m_interleaveReadWriteComponents) ||
1400             ((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && m_interleaveReadWriteComponents);
1401 
1402         VkBool32 stencilTestEnable =
1403             ((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && !m_interleaveReadWriteComponents) ||
1404             ((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) && m_interleaveReadWriteComponents);
1405 
1406         const auto stencilFrontOpState =
1407             makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_REPLACE, vk::VK_STENCIL_OP_KEEP,
1408                                vk::VK_COMPARE_OP_NEVER, 0xFFu, 0xFFu, 0u);
1409         const auto stencilBackOpState =
1410             makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_REPLACE, vk::VK_STENCIL_OP_KEEP,
1411                                vk::VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u);
1412 
1413         const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1414             VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                            sType
1415             DE_NULL,              // const void*                                pNext
1416             0u,                   // VkPipelineDepthStencilStateCreateFlags    flags
1417             depthTestEnable,      // VkBool32                                    depthTestEnable
1418             depthTestEnable,      // VkBool32                                    depthWriteEnable
1419             VK_COMPARE_OP_ALWAYS, // VkCompareOp                                depthCompareOp
1420             false,                // VkBool32                                    depthBoundsTestEnable
1421             stencilTestEnable,    // VkBool32                                    stencilTestEnable
1422             stencilFrontOpState,  // VkStencilOpState                            front
1423             stencilBackOpState,   // VkStencilOpState                            back
1424             0.0f,                 // float                                    minDepthBounds
1425             1.0f,                 // float maxDepthBounds;
1426         };
1427 
1428         std::vector<VkDynamicState> dynamicStates;
1429         if (m_pipelineStateMode != PipelineStateMode::STATIC)
1430             dynamicStates.push_back(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
1431 
1432         const VkPipelineDynamicStateCreateInfo dynamicStateInfo = {
1433             VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
1434             nullptr,
1435             0u,
1436             de::sizeU32(dynamicStates),
1437             de::dataOrNull(dynamicStates),
1438         };
1439 
1440         if (m_useMaintenance5)
1441             m_graphicsPipeline.setPipelineCreateFlags2(translateCreateFlag(m_params.pipelineCreateFlags));
1442 
1443         m_graphicsPipeline.setDynamicState(&dynamicStateInfo)
1444             .setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
1445             .setDefaultDepthStencilState()
1446             .setDefaultRasterizationState()
1447             .setDefaultMultisampleState()
1448             .setupVertexInputState(&vertexInputStateParams)
1449             .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
1450                                               0u, m_vertexShaderModule)
1451             .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
1452                                       &depthStencilStateCreateInfo)
1453             .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
1454             .buildPipeline();
1455     }
1456 
1457     // Create vertex buffer
1458     {
1459         const VkDeviceSize vertexBufferSize         = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
1460         const VkBufferCreateInfo vertexBufferParams = {
1461             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1462             DE_NULL,                              // const void* pNext;
1463             0u,                                   // VkBufferCreateFlags flags;
1464             vertexBufferSize,                     // VkDeviceSize size;
1465             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,    // VkBufferUsageFlags usage;
1466             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
1467             1u,                                   // uint32_t queueFamilyIndexCount;
1468             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
1469         };
1470 
1471         DE_ASSERT(vertexBufferSize > 0);
1472 
1473         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
1474         m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer,
1475                                              MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
1476         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
1477                                      m_vertexBufferAlloc->getOffset()));
1478 
1479         // Load vertices into vertex buffer
1480         deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
1481         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
1482     }
1483 
1484     // Create command buffer
1485     {
1486         std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
1487 
1488         for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1489         {
1490             preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
1491             preAttachmentBarriers[imgNdx].pNext = DE_NULL;                                // const void* pNext;
1492             preAttachmentBarriers[imgNdx].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; // VkAccessFlags srcAccessMask;
1493             preAttachmentBarriers[imgNdx].dstAccessMask =
1494                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1495                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;        // VkAccessFlags dstAccessMask;
1496             preAttachmentBarriers[imgNdx].oldLayout = m_imageLayout; // VkImageLayout oldLayout;
1497             preAttachmentBarriers[imgNdx].newLayout = m_imageLayout; // VkImageLayout newLayout;
1498             preAttachmentBarriers[imgNdx].srcQueueFamilyIndex =
1499                 VK_QUEUE_FAMILY_IGNORED; // uint32_t srcQueueFamilyIndex;
1500             preAttachmentBarriers[imgNdx].dstQueueFamilyIndex =
1501                 VK_QUEUE_FAMILY_IGNORED;                                // uint32_t dstQueueFamilyIndex;
1502             preAttachmentBarriers[imgNdx].image = **m_dsImages[imgNdx]; // VkImage image;
1503             preAttachmentBarriers[imgNdx].subresourceRange.aspectMask =
1504                 getAspectFlags(m_imageFormat); // VkImageSubresourceRange subresourceRange;
1505             preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel   = 0u;
1506             preAttachmentBarriers[imgNdx].subresourceRange.levelCount     = 1u;
1507             preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer = 0u;
1508             preAttachmentBarriers[imgNdx].subresourceRange.layerCount     = 1u;
1509         }
1510 
1511         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1512 
1513         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
1514                               (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, (uint32_t)m_imageCount,
1515                               &preAttachmentBarriers[0]);
1516 
1517         // Do not clear the color attachments as we are using the texture as color attachment.
1518         m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), 0u, DE_NULL);
1519 
1520         m_graphicsPipeline.bind(*m_cmdBuffer);
1521 
1522         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1,
1523                                  &m_descriptorSet.get(), 0, DE_NULL);
1524 
1525         const VkDeviceSize vertexBufferOffset = 0;
1526         vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1527 
1528         if (m_pipelineStateMode != PipelineStateMode::STATIC)
1529             vk.cmdSetAttachmentFeedbackLoopEnableEXT(*m_cmdBuffer, testModeToAspectFlags(m_imageAspectTestMode));
1530 
1531         vk.cmdDraw(*m_cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
1532 
1533         m_renderPass.end(vk, *m_cmdBuffer);
1534         endCommandBuffer(vk, *m_cmdBuffer);
1535     }
1536 }
1537 
verifyImage(void)1538 tcu::TestStatus AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::verifyImage(void)
1539 {
1540     const tcu::TextureFormat tcuFormat = getSizeCompatibleTcuTextureFormat(m_imageFormat);
1541     const bool isDepth =
1542         (!m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)) ||
1543         (m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT));
1544     const bool isStencil =
1545         (!m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) ||
1546         (m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT));
1547     // ImageSamplingInstance::verifyImage() doesn't support stencil sampling.
1548     if (!m_useImageAsColorOrDSAttachment && !isStencil)
1549         return ImageSamplingInstance::verifyImage();
1550 
1551     const tcu::Vec4 fThreshold(0.005f);
1552     const tcu::UVec4 uThreshold(
1553         0u); // Due to unsigned normalized fixed-point integers conversion to floats and viceversa.
1554     tcu::UVec2 renderSize = tcu::UVec2({(unsigned)m_imageSize.x(), (unsigned)m_imageSize.y()});
1555 
1556     de::MovePtr<tcu::TextureLevel> referenceTextureLevel = de::MovePtr<tcu::TextureLevel>(
1557         new tcu::TextureLevel(tcuFormat, m_imageSize.x(), m_imageSize.y(), m_imageSize.z()));
1558 
1559     for (int z = 0; z < m_imageSize.z(); z++)
1560         for (int y = 0; y < m_imageSize.y(); y++)
1561             for (int x = 0; x < m_imageSize.x(); x++)
1562             {
1563                 if (isDepth)
1564                 {
1565                     float depth = 0.0f;
1566                     if (m_interleaveReadWriteComponents)
1567                     {
1568                         int stencil = 1 + m_texture->getLevel(0, 0).getPixStencil(x, y, z);
1569                         depth       = static_cast<float>(stencil) / 255.0f;
1570                     }
1571                     else
1572                     {
1573                         if (m_useDifferentAreasSampleWrite && x < m_imageSize.x() / 2)
1574                             depth = m_texture->getLevel(0, 0).getPixDepth(x + (m_imageSize.x() / 2), y, z) + 0.1f;
1575                         else
1576                             depth = m_texture->getLevel(0, 0).getPixDepth(x, y, z);
1577 
1578                         if (!m_useDifferentAreasSampleWrite)
1579                             depth += 0.1f;
1580                     }
1581 
1582                     depth = deFloatClamp(depth, 0.0f, 1.0f);
1583                     referenceTextureLevel->getAccess().setPixDepth(depth, x, y, z);
1584                 }
1585                 if (isStencil)
1586                 {
1587                     int stencil = 0;
1588                     if (m_interleaveReadWriteComponents)
1589                     {
1590                         float depth = m_texture->getLevel(0, 0).getPixDepth(x, y, z) + 0.1f;
1591                         stencil     = static_cast<int>(depth * 255.0f);
1592                     }
1593                     else
1594                     {
1595                         if (m_useDifferentAreasSampleWrite && x < m_imageSize.x() / 2)
1596                             stencil = 1 + m_texture->getLevel(0, 0).getPixStencil(x + (m_imageSize.x() / 2), y, z);
1597                         else
1598                             stencil = m_texture->getLevel(0, 0).getPixStencil(x, y, z);
1599 
1600                         if (!m_useDifferentAreasSampleWrite)
1601                             stencil += 1;
1602 
1603                         stencil = deClamp32(stencil, 0, 255);
1604                     }
1605 
1606                     referenceTextureLevel->getAccess().setPixStencil(stencil, x, y, z);
1607                 }
1608             }
1609 
1610     for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1611     {
1612         if (isDepth)
1613         {
1614             // Read back result image
1615             de::MovePtr<tcu::TextureLevel> resultTexture(readDepthAttachment(
1616                 m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
1617                 m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), **m_dsImages[imgNdx],
1618                 m_imageFormat, renderSize, VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1619 
1620             const tcu::ConstPixelBufferAccess result      = resultTexture->getAccess();
1621             const tcu::Sampler::DepthStencilMode mode     = tcu::Sampler::MODE_DEPTH;
1622             const tcu::ConstPixelBufferAccess depthResult = tcu::getEffectiveDepthStencilAccess(result, mode);
1623             const tcu::ConstPixelBufferAccess expectedResult =
1624                 tcu::getEffectiveDepthStencilAccess(referenceTextureLevel->getAccess(), mode);
1625             bool isIntegerFormat = isUintFormat(mapTextureFormat(depthResult.getFormat())) ||
1626                                    isIntFormat(mapTextureFormat(depthResult.getFormat()));
1627 
1628             if (!isIntegerFormat)
1629             {
1630                 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1631                                                 expectedResult, depthResult, fThreshold, tcu::COMPARE_LOG_RESULT))
1632                     return tcu::TestStatus::fail("Failed depth");
1633             }
1634             else
1635             {
1636                 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1637                                               expectedResult, depthResult, uThreshold, tcu::COMPARE_LOG_RESULT))
1638                     return tcu::TestStatus::fail("Failed depth");
1639             }
1640         }
1641 
1642         if (isStencil)
1643         {
1644             // Read back result image
1645             de::MovePtr<tcu::TextureLevel> resultTexture(readStencilAttachment(
1646                 m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
1647                 m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), **m_dsImages[imgNdx],
1648                 m_imageFormat, renderSize, VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1649 
1650             const tcu::ConstPixelBufferAccess result        = resultTexture->getAccess();
1651             const tcu::Sampler::DepthStencilMode mode       = tcu::Sampler::MODE_STENCIL;
1652             const tcu::ConstPixelBufferAccess stencilResult = tcu::getEffectiveDepthStencilAccess(result, mode);
1653             const tcu::ConstPixelBufferAccess expectedResult =
1654                 tcu::getEffectiveDepthStencilAccess(referenceTextureLevel->getAccess(), mode);
1655             bool isIntegerFormat = isUintFormat(mapTextureFormat(stencilResult.getFormat())) ||
1656                                    isIntFormat(mapTextureFormat(stencilResult.getFormat()));
1657 
1658             if (!isIntegerFormat)
1659             {
1660                 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1661                                                 expectedResult, stencilResult, fThreshold, tcu::COMPARE_LOG_RESULT))
1662                     return tcu::TestStatus::fail("Failed stencil");
1663             }
1664             else
1665             {
1666                 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1667                                               expectedResult, stencilResult, uThreshold, tcu::COMPARE_LOG_RESULT))
1668                     return tcu::TestStatus::fail("Failed stencil");
1669             }
1670         }
1671     }
1672 
1673     return tcu::TestStatus::pass("Pass");
1674 }
1675 
iterate(void)1676 tcu::TestStatus AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::iterate(void)
1677 {
1678     const DeviceInterface &vk = m_context.getDeviceInterface();
1679     const VkDevice vkDevice   = m_context.getDevice();
1680     const VkQueue queue       = m_context.getUniversalQueue();
1681 
1682     setup();
1683     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1684 
1685     return verifyImage();
1686 }
1687 
verifyImage(void)1688 tcu::TestStatus AttachmentFeedbackLoopLayoutImageSamplingInstance::verifyImage(void)
1689 {
1690     if (!m_useImageAsColorOrDSAttachment)
1691         return ImageSamplingInstance::verifyImage();
1692 
1693     const tcu::Vec4 fThreshold(0.01f);
1694     const tcu::UVec4 uThreshold(1u);
1695     tcu::UVec2 renderSize = tcu::UVec2({(unsigned)m_imageSize.x(), (unsigned)m_imageSize.y()});
1696 
1697     const tcu::TextureFormat tcuFormat                   = getSizeCompatibleTcuTextureFormat(m_imageFormat);
1698     de::MovePtr<tcu::TextureLevel> referenceTextureLevel = de::MovePtr<tcu::TextureLevel>(
1699         new tcu::TextureLevel(tcuFormat, m_imageSize.x(), m_imageSize.y(), m_imageSize.z()));
1700 
1701     for (int z = 0; z < m_imageSize.z(); z++)
1702         for (int y = 0; y < m_imageSize.y(); y++)
1703             for (int x = 0; x < m_imageSize.x(); x++)
1704             {
1705                 tcu::Vec4 color = tcu::Vec4(1.0f);
1706 
1707                 if (m_useDifferentAreasSampleWrite && (x < m_imageSize.x() / 2))
1708                     color = m_texture->getLevel(0, 0).getPixel(x + (m_imageSize.x() / 2), y, z) + tcu::Vec4(0.1f);
1709                 else
1710                     color = m_texture->getLevel(0, 0).getPixel(x, y, z);
1711 
1712                 if (!m_useDifferentAreasSampleWrite)
1713                     color += tcu::Vec4(0.1f);
1714 
1715                 if (m_interleaveReadWriteComponents)
1716                 {
1717                     tcu::Vec4 sampledColor = m_texture->getLevel(0, 0).getPixel(x, y, z);
1718                     color.x()              = color.y();
1719                     color.y()              = sampledColor.y();
1720                     color.z()              = color.w();
1721                     color.w()              = sampledColor.w();
1722                 }
1723 
1724                 color.x() = deFloatClamp(color.x(), 0.0f, 1.0f);
1725                 color.y() = deFloatClamp(color.y(), 0.0f, 1.0f);
1726                 color.z() = deFloatClamp(color.z(), 0.0f, 1.0f);
1727                 color.w() = deFloatClamp(color.w(), 0.0f, 1.0f);
1728 
1729                 referenceTextureLevel->getAccess().setPixel(color, x, y, z);
1730             }
1731 
1732     for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1733     {
1734         // Read back result image
1735         de::MovePtr<tcu::TextureLevel> resultTexture(readColorAttachment(
1736             m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
1737             m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), **m_colorImages[imgNdx],
1738             m_colorFormat, renderSize, vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1739         const tcu::ConstPixelBufferAccess result = resultTexture->getAccess();
1740         const bool isIntegerFormat               = isUintFormat(m_imageFormat) || isIntFormat(m_imageFormat);
1741 
1742         if (!isIntegerFormat)
1743         {
1744             if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1745                                             referenceTextureLevel->getAccess(), result, fThreshold,
1746                                             tcu::COMPARE_LOG_RESULT))
1747                 return tcu::TestStatus::fail("Failed color");
1748         }
1749         else
1750         {
1751             if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1752                                           referenceTextureLevel->getAccess(), result, uThreshold,
1753                                           tcu::COMPARE_LOG_RESULT))
1754                 return tcu::TestStatus::fail("Failed color");
1755         }
1756     }
1757 
1758     return tcu::TestStatus::pass("Pass");
1759 }
1760 
~AttachmentFeedbackLoopLayoutImageSamplingInstance(void)1761 AttachmentFeedbackLoopLayoutImageSamplingInstance::~AttachmentFeedbackLoopLayoutImageSamplingInstance(void)
1762 {
1763 }
1764 
iterate(void)1765 tcu::TestStatus AttachmentFeedbackLoopLayoutImageSamplingInstance::iterate(void)
1766 {
1767     const DeviceInterface &vk = m_context.getDeviceInterface();
1768     const VkDevice vkDevice   = m_context.getDevice();
1769     const VkQueue queue       = m_context.getUniversalQueue();
1770 
1771     setup();
1772     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1773 
1774     return verifyImage();
1775 }
1776 
1777 class AttachmentFeedbackLoopLayoutSamplerTest : public vkt::TestCase
1778 {
1779 public:
1780     AttachmentFeedbackLoopLayoutSamplerTest(tcu::TestContext &testContext,
1781                                             vk::PipelineConstructionType pipelineConstructionType, const char *name,
1782                                             SamplerViewType imageViewType, VkFormat imageFormat, int imageSize,
1783                                             VkDescriptorType imageDescriptorType, float samplerLod, TestMode testMode,
1784                                             ImageAspectTestMode imageAspectTestMode, bool interleaveReadWriteComponents,
1785                                             PipelineStateMode pipelineStateMode, bool useMaintenance5);
~AttachmentFeedbackLoopLayoutSamplerTest(void)1786     virtual ~AttachmentFeedbackLoopLayoutSamplerTest(void)
1787     {
1788     }
1789 
1790     virtual ImageSamplingInstanceParams getImageSamplingInstanceParams(SamplerViewType imageViewType,
1791                                                                        VkFormat imageFormat, int imageSize,
1792                                                                        VkDescriptorType imageDescriptorType,
1793                                                                        float samplerLod) const;
1794 
1795     virtual void initPrograms(SourceCollections &sourceCollections) const;
1796     virtual void checkSupport(Context &context) const;
1797     virtual TestInstance *createInstance(Context &context) const;
1798     virtual tcu::UVec2 getRenderSize(SamplerViewType viewType) const;
1799     virtual std::vector<Vertex4Tex4> createVertices(void) const;
1800     virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
1801     virtual VkComponentMapping getComponentMapping(void) const;
1802 
1803     static std::string getGlslSamplerType(const tcu::TextureFormat &format, SamplerViewType type);
1804     static tcu::IVec3 getImageSize(SamplerViewType viewType, int size);
1805     static int getArraySize(SamplerViewType viewType);
1806 
1807     static std::string getGlslSampler(const tcu::TextureFormat &format, VkImageViewType type,
1808                                       VkDescriptorType samplingType, int imageCount);
1809     static std::string getGlslTextureType(const tcu::TextureFormat &format, VkImageViewType type);
1810     static std::string getGlslSamplerDecl(int imageCount);
1811     static std::string getGlslTextureDecl(int imageCount);
1812 
1813 protected:
1814     vk::PipelineConstructionType m_pipelineConstructionType;
1815     SamplerViewType m_imageViewType;
1816     VkFormat m_imageFormat;
1817     int m_imageSize;
1818     VkDescriptorType m_imageDescriptorType;
1819     float m_samplerLod;
1820     TestMode m_testMode;
1821     ImageAspectTestMode m_imageAspectTestMode;
1822     bool m_interleaveReadWriteComponents;
1823     PipelineStateMode m_pipelineStateMode;
1824     bool m_useMaintenance5;
1825 };
1826 
1827 // AttachmentFeedbackLoopLayoutSamplerTest
1828 
AttachmentFeedbackLoopLayoutSamplerTest(tcu::TestContext & testContext,vk::PipelineConstructionType pipelineConstructionType,const char * name,SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,VkDescriptorType imageDescriptorType,float samplerLod,TestMode testMode,ImageAspectTestMode imageAspectTestMode,bool interleaveReadWriteComponents,PipelineStateMode pipelineStateMode,bool useMaintenance5)1829 AttachmentFeedbackLoopLayoutSamplerTest::AttachmentFeedbackLoopLayoutSamplerTest(
1830     tcu::TestContext &testContext, vk::PipelineConstructionType pipelineConstructionType, const char *name,
1831     SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, VkDescriptorType imageDescriptorType,
1832     float samplerLod, TestMode testMode, ImageAspectTestMode imageAspectTestMode, bool interleaveReadWriteComponents,
1833     PipelineStateMode pipelineStateMode, bool useMaintenance5)
1834     : vkt::TestCase(testContext, name)
1835     , m_pipelineConstructionType(pipelineConstructionType)
1836     , m_imageViewType(imageViewType)
1837     , m_imageFormat(imageFormat)
1838     , m_imageSize(imageSize)
1839     , m_imageDescriptorType(imageDescriptorType)
1840     , m_samplerLod(samplerLod)
1841     , m_testMode(testMode)
1842     , m_imageAspectTestMode(imageAspectTestMode)
1843     , m_interleaveReadWriteComponents(interleaveReadWriteComponents)
1844     , m_pipelineStateMode(pipelineStateMode)
1845     , m_useMaintenance5(useMaintenance5)
1846 {
1847 }
1848 
getImageSamplingInstanceParams(SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,VkDescriptorType imageDescriptorType,float samplerLod) const1849 ImageSamplingInstanceParams AttachmentFeedbackLoopLayoutSamplerTest::getImageSamplingInstanceParams(
1850     SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, VkDescriptorType imageDescriptorType,
1851     float samplerLod) const
1852 {
1853     const tcu::UVec2 renderSize               = getRenderSize(imageViewType);
1854     const std::vector<Vertex4Tex4> vertices   = createVertices();
1855     const VkSamplerCreateInfo samplerParams   = getSamplerCreateInfo();
1856     const VkComponentMapping componentMapping = getComponentMapping();
1857 
1858     VkImageAspectFlags imageAspect            = 0u;
1859     VkPipelineCreateFlags pipelineCreateFlags = 0u;
1860 
1861     if (!isCompressedFormat(imageFormat))
1862     {
1863         if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR)
1864         {
1865             DE_ASSERT(!tcu::hasDepthComponent(mapVkFormat(imageFormat).order) &&
1866                       !tcu::hasStencilComponent(mapVkFormat(imageFormat).order));
1867         }
1868         else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH)
1869             DE_ASSERT(tcu::hasDepthComponent(mapVkFormat(imageFormat).order));
1870         else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL)
1871             DE_ASSERT(tcu::hasStencilComponent(mapVkFormat(imageFormat).order));
1872 
1873         imageAspect         = testModeToAspectFlags(m_imageAspectTestMode);
1874         pipelineCreateFlags = getStaticPipelineCreateFlags(imageAspect, m_pipelineStateMode);
1875     }
1876     else
1877     {
1878         imageAspect = VK_IMAGE_ASPECT_COLOR_BIT;
1879     }
1880 
1881     const VkImageSubresourceRange subresourceRange = {
1882         imageAspect,                          // VkImageAspectFlags aspectMask;
1883         0u,                                   // uint32_t baseMipLevel;
1884         1u,                                   // uint32_t mipLevels;
1885         0u,                                   // uint32_t baseArrayLayer;
1886         (uint32_t)getArraySize(imageViewType) // uint32_t arraySize;
1887     };
1888 
1889     return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat,
1890                                        getImageSize(imageViewType, imageSize), getArraySize(imageViewType),
1891                                        componentMapping, subresourceRange, samplerParams, samplerLod, vertices, false,
1892                                        imageDescriptorType, 1u, ALLOCATION_KIND_SUBALLOCATED,
1893                                        vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT, pipelineCreateFlags);
1894 }
1895 
checkSupport(Context & context) const1896 void AttachmentFeedbackLoopLayoutSamplerTest::checkSupport(Context &context) const
1897 {
1898     const auto &vki           = context.getInstanceInterface();
1899     const auto physicalDevice = context.getPhysicalDevice();
1900 
1901     checkPipelineConstructionRequirements(vki, physicalDevice, m_pipelineConstructionType);
1902 
1903     context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_layout");
1904 
1905     if (m_useMaintenance5)
1906         context.requireDeviceFunctionality("VK_KHR_maintenance5");
1907 
1908     if (m_pipelineStateMode != PipelineStateMode::STATIC || isConstructionTypeShaderObject(m_pipelineConstructionType))
1909         context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_dynamic_state");
1910 
1911     const auto imgParams = getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize,
1912                                                           m_imageDescriptorType, m_samplerLod);
1913     checkSupportImageSamplingInstance(context, imgParams);
1914 
1915     if (m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL) // Image as color or DS attachment.
1916     {
1917         VkFormatProperties formatProps;
1918         vki.getPhysicalDeviceFormatProperties(physicalDevice, imgParams.imageFormat, &formatProps);
1919 
1920         const auto attachmentFormatFeature        = isDepthStencilFormat(imgParams.imageFormat) ?
1921                                                         VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT :
1922                                                         VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1923         const VkFormatFeatureFlags neededFeatures = attachmentFormatFeature | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
1924                                                     VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
1925                                                     VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1926 
1927         if ((formatProps.optimalTilingFeatures & neededFeatures) != neededFeatures)
1928         {
1929             std::ostringstream msg;
1930             msg << "Format does not support required features: 0x" << std::hex << neededFeatures;
1931             TCU_THROW(NotSupportedError, msg.str());
1932         }
1933 
1934         if ((!m_interleaveReadWriteComponents && m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL) ||
1935             (m_interleaveReadWriteComponents && m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH))
1936             context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
1937     }
1938 }
1939 
getGlslTextureType(const tcu::TextureFormat & format,VkImageViewType type)1940 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslTextureType(const tcu::TextureFormat &format,
1941                                                                         VkImageViewType type)
1942 {
1943     std::ostringstream textureType;
1944 
1945     if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1946         textureType << "u";
1947     else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1948         textureType << "i";
1949 
1950     switch (type)
1951     {
1952     case VK_IMAGE_VIEW_TYPE_1D:
1953         textureType << "texture1D";
1954         break;
1955 
1956     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1957         textureType << "texture1DArray";
1958         break;
1959 
1960     case VK_IMAGE_VIEW_TYPE_2D:
1961         textureType << "texture2D";
1962         break;
1963 
1964     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1965         textureType << "texture2DArray";
1966         break;
1967 
1968     case VK_IMAGE_VIEW_TYPE_3D:
1969         textureType << "texture3D";
1970         break;
1971 
1972     case VK_IMAGE_VIEW_TYPE_CUBE:
1973         textureType << "textureCube";
1974         break;
1975 
1976     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1977         textureType << "textureCubeArray";
1978         break;
1979 
1980     default:
1981         DE_FATAL("Unknown image view type");
1982     }
1983 
1984     return textureType.str();
1985 }
1986 
getGlslSamplerDecl(int imageCount)1987 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSamplerDecl(int imageCount)
1988 {
1989     std::ostringstream samplerArray;
1990     samplerArray << "texSamplers[" << imageCount << "]";
1991 
1992     return imageCount > 1 ? samplerArray.str() : "texSampler";
1993 }
1994 
getGlslTextureDecl(int imageCount)1995 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslTextureDecl(int imageCount)
1996 {
1997     std::ostringstream textureArray;
1998     textureArray << "texImages[" << imageCount << "]";
1999 
2000     return imageCount > 1 ? textureArray.str() : "texImage";
2001 }
2002 
getGlslSampler(const tcu::TextureFormat & format,VkImageViewType type,VkDescriptorType samplingType,int imageCount)2003 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSampler(const tcu::TextureFormat &format,
2004                                                                     VkImageViewType type, VkDescriptorType samplingType,
2005                                                                     int imageCount)
2006 {
2007     std::string texSampler = imageCount > 1 ? "texSamplers[i]" : "texSampler";
2008     std::string texImage   = imageCount > 1 ? "texImages[i]" : "texImage";
2009 
2010     switch (samplingType)
2011     {
2012     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2013         return getGlslSamplerType(format, type) + "(" + texImage + ", texSampler)";
2014     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2015     default:
2016         return texSampler;
2017     }
2018 }
2019 
initPrograms(SourceCollections & sourceCollections) const2020 void AttachmentFeedbackLoopLayoutSamplerTest::initPrograms(SourceCollections &sourceCollections) const
2021 {
2022     std::ostringstream vertexSrc;
2023     std::ostringstream fragmentSrc;
2024     const char *texCoordSwizzle = DE_NULL;
2025     const VkFormat vkFormat = m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL ? VK_FORMAT_S8_UINT : m_imageFormat;
2026     const tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ?
2027                                           tcu::getUncompressedFormat(mapVkCompressedFormat(vkFormat)) :
2028                                           mapVkFormat(vkFormat);
2029     tcu::Vec4 lookupScale;
2030     tcu::Vec4 lookupBias;
2031 
2032     getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
2033 
2034     switch (m_imageViewType)
2035     {
2036     case VK_IMAGE_VIEW_TYPE_1D:
2037         texCoordSwizzle = "x";
2038         break;
2039     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2040     case VK_IMAGE_VIEW_TYPE_2D:
2041         texCoordSwizzle = "xy";
2042         break;
2043     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2044     case VK_IMAGE_VIEW_TYPE_3D:
2045     case VK_IMAGE_VIEW_TYPE_CUBE:
2046         texCoordSwizzle = "xyz";
2047         break;
2048     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2049         texCoordSwizzle = "xyzw";
2050         break;
2051     default:
2052         DE_ASSERT(false);
2053         break;
2054     }
2055 
2056     vertexSrc << "#version 440\n"
2057               << "layout(location = 0) in vec4 position;\n"
2058               << "layout(location = 1) in vec4 texCoords;\n"
2059               << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
2060               << "out gl_PerVertex {\n"
2061               << "    vec4 gl_Position;\n"
2062               << "};\n"
2063               << "void main (void)\n"
2064               << "{\n"
2065               << "    gl_Position = position;\n"
2066               << "    vtxTexCoords = texCoords;\n"
2067               << "}\n";
2068 
2069     fragmentSrc << "#version 440\n";
2070 
2071     if ((m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL) ||
2072         (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_interleaveReadWriteComponents))
2073     {
2074         fragmentSrc << "#extension GL_ARB_shader_stencil_export: require\n";
2075     }
2076 
2077     switch (m_imageDescriptorType)
2078     {
2079     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2080         fragmentSrc << "layout(set = 0, binding = 0) uniform highp sampler texSampler;\n"
2081                     << "layout(set = 0, binding = 1) uniform highp " << getGlslTextureType(format, m_imageViewType)
2082                     << " " << getGlslTextureDecl(1u) << ";\n";
2083         break;
2084     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2085     default:
2086         fragmentSrc << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType)
2087                     << " " << getGlslSamplerDecl(1u) << ";\n";
2088     }
2089 
2090     if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR || m_testMode == TEST_MODE_READ_ONLY)
2091         fragmentSrc << "layout(location = 0) out highp vec4 fragColor;\n";
2092 
2093     fragmentSrc << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
2094                 << "void main (void)\n"
2095                 << "{\n";
2096 
2097     if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode != TEST_MODE_READ_ONLY)
2098         fragmentSrc << "    uvec4 read_data = ";
2099     else
2100         fragmentSrc << "    vec4 read_data = ";
2101 
2102     if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2103     {
2104         fragmentSrc << "vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
2105 
2106         fragmentSrc << "    read_data.x = ";
2107         if (m_samplerLod > 0.0f)
2108         {
2109             DE_ASSERT(m_imageViewType.isNormalized());
2110             fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2111                         << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ").x";
2112         }
2113         else
2114         {
2115             if (m_imageViewType.isNormalized())
2116                 fragmentSrc << "texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2117                             << ", vtxTexCoords." << texCoordSwizzle << ").x" << std::fixed;
2118             else
2119                 fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2120                             << ", vtxTexCoords." << texCoordSwizzle << ", 0).x" << std::fixed;
2121         }
2122 
2123         fragmentSrc << " + 0.1f;\n";
2124     }
2125     else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode == TEST_MODE_READ_ONLY)
2126     {
2127         if (m_samplerLod > 0.0f)
2128         {
2129             DE_ASSERT(m_imageViewType.isNormalized());
2130             fragmentSrc << "vec4(textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2131                         << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod
2132                         << ").x / 255.0f, 0.0f, 0.0f, 1.0f)";
2133         }
2134         else
2135         {
2136             if (m_imageViewType.isNormalized())
2137                 fragmentSrc << "vec4(texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2138                             << ", vtxTexCoords." << texCoordSwizzle << ").x / 255.0f, 0.0f, 0.0f, 1.0f)" << std::fixed;
2139             else
2140                 fragmentSrc << "vec4(textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2141                             << ", vtxTexCoords." << texCoordSwizzle << ", 0).x / 255.0f, 0.0f, 0.0f, 1.0f)"
2142                             << std::fixed;
2143         }
2144 
2145         fragmentSrc << ";\n";
2146     }
2147     else
2148     {
2149         if (m_samplerLod > 0.0f)
2150         {
2151             DE_ASSERT(m_imageViewType.isNormalized());
2152             fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2153                         << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")";
2154         }
2155         else
2156         {
2157             if (m_imageViewType.isNormalized())
2158                 fragmentSrc << "texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2159                             << ", vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
2160             else
2161                 fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2162                             << ", vtxTexCoords." << texCoordSwizzle << ", 0)" << std::fixed;
2163         }
2164 
2165         if (m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2166         {
2167             if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL)
2168                 fragmentSrc << " + uvec4(1u, 0u, 0u, 0)";
2169             else
2170                 fragmentSrc << " + vec4(0.1f)";
2171         }
2172 
2173         fragmentSrc << ";\n";
2174     }
2175 
2176     if (m_interleaveReadWriteComponents)
2177     {
2178         if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR)
2179         {
2180             fragmentSrc << "    fragColor = vec4(1.0f);\n"
2181                         << "    fragColor.x = read_data.y;\n"
2182                         << "    fragColor.z = read_data.w;\n";
2183         }
2184         else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH)
2185         {
2186             fragmentSrc << "    gl_FragStencilRefARB = int(clamp(read_data.x * 255.0f, 0.0f, 255.0f));\n";
2187         }
2188         else
2189         {
2190             fragmentSrc << "    gl_FragDepth = clamp(float(read_data.x) / 255.0f, 0.0f, 1.0f);\n";
2191         }
2192     }
2193     else
2194     {
2195         if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2196         {
2197             fragmentSrc << "    gl_FragDepth = clamp(read_data.x, 0.0f, 1.0f);\n";
2198         }
2199         else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2200         {
2201             fragmentSrc << "    gl_FragStencilRefARB = int(clamp(read_data.x, 0u, 255u));\n";
2202         }
2203         else
2204         {
2205             fragmentSrc << "    fragColor = read_data;\n";
2206         }
2207     }
2208 
2209     fragmentSrc << "}\n";
2210 
2211     sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
2212     sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
2213 }
2214 
createInstance(Context & context) const2215 TestInstance *AttachmentFeedbackLoopLayoutSamplerTest::createInstance(Context &context) const
2216 {
2217     const bool useImageAsColorOrDSAttachment = m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL;
2218     const bool useDifferentAreasSampleWrite  = m_testMode == TEST_MODE_READ_WRITE_DIFFERENT_AREAS;
2219 
2220     if (m_imageAspectTestMode != IMAGE_ASPECT_TEST_COLOR && useImageAsColorOrDSAttachment)
2221         return new AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(
2222             context,
2223             getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_imageDescriptorType,
2224                                            m_samplerLod),
2225             useImageAsColorOrDSAttachment, useDifferentAreasSampleWrite, m_interleaveReadWriteComponents,
2226             m_imageAspectTestMode, m_pipelineStateMode, m_useMaintenance5);
2227     return new AttachmentFeedbackLoopLayoutImageSamplingInstance(
2228         context,
2229         getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_imageDescriptorType,
2230                                        m_samplerLod),
2231         useImageAsColorOrDSAttachment, useDifferentAreasSampleWrite, m_interleaveReadWriteComponents,
2232         m_imageAspectTestMode, m_pipelineStateMode, m_useMaintenance5);
2233 }
2234 
getRenderSize(SamplerViewType viewType) const2235 tcu::UVec2 AttachmentFeedbackLoopLayoutSamplerTest::getRenderSize(SamplerViewType viewType) const
2236 {
2237     if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
2238     {
2239         return tcu::UVec2(16u, 16u);
2240     }
2241     else
2242     {
2243         return tcu::UVec2(16u * 3u, 16u * 2u);
2244     }
2245 }
2246 
createFullscreenQuadArray(vk::VkImageViewType viewType,unsigned arraySize)2247 std::vector<Vertex4Tex4> createFullscreenQuadArray(vk::VkImageViewType viewType, unsigned arraySize)
2248 {
2249     using tcu::Vec4;
2250     std::vector<Vertex4Tex4> verticesArray;
2251 
2252     const Vertex4Tex4 lowerLeftVertex  = {Vec4(-1.0f, -1.0f, 0.0f, 1.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)};
2253     const Vertex4Tex4 upperLeftVertex  = {Vec4(-1.0f, 1.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 0.0f)};
2254     const Vertex4Tex4 lowerRightVertex = {Vec4(1.0f, -1.0f, 0.0f, 1.0f), Vec4(1.0f, 0.0f, 0.0f, 0.0f)};
2255     const Vertex4Tex4 upperRightVertex = {Vec4(1.0f, 1.0f, 0.0f, 1.0f), Vec4(1.0f, 1.0f, 0.0f, 0.0f)};
2256 
2257     for (unsigned arrayNdx = 0; arrayNdx < arraySize; arrayNdx++)
2258     {
2259         Vertex4Tex4 vertices[6] = {lowerLeftVertex, upperLeftVertex,  lowerRightVertex,
2260 
2261                                    upperLeftVertex, lowerRightVertex, upperRightVertex};
2262 
2263         for (int i = 0; i < 6; i++)
2264         {
2265             if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2266             {
2267                 vertices[i].position.y() = (float)arrayNdx;
2268                 vertices[i].texCoord.y() = (float)arrayNdx;
2269             }
2270             else
2271             {
2272                 vertices[i].position.z() = (float)arrayNdx;
2273                 vertices[i].texCoord.z() = (float)arrayNdx;
2274             }
2275             verticesArray.push_back(vertices[i]);
2276         }
2277     }
2278 
2279     return verticesArray;
2280 }
2281 
createTestQuadAttachmentFeedbackLoopLayout(vk::VkImageViewType viewType)2282 std::vector<Vertex4Tex4> createTestQuadAttachmentFeedbackLoopLayout(vk::VkImageViewType viewType)
2283 {
2284     std::vector<Vertex4Tex4> vertices;
2285 
2286     switch (viewType)
2287     {
2288     case vk::VK_IMAGE_VIEW_TYPE_1D:
2289     case vk::VK_IMAGE_VIEW_TYPE_2D:
2290         vertices = createFullscreenQuad();
2291         break;
2292 
2293     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2294         vertices = createFullscreenQuadArray(viewType, 6u);
2295         break;
2296 
2297     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2298     case vk::VK_IMAGE_VIEW_TYPE_3D:
2299     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
2300     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2301         vertices = createFullscreenQuadArray(viewType, 6u);
2302         break;
2303 
2304     default:
2305         DE_ASSERT(false);
2306         break;
2307     }
2308 
2309     return vertices;
2310 }
2311 
createVertices(void) const2312 std::vector<Vertex4Tex4> AttachmentFeedbackLoopLayoutSamplerTest::createVertices(void) const
2313 {
2314     std::vector<Vertex4Tex4> vertices = m_testMode != TEST_MODE_READ_WRITE_DIFFERENT_AREAS ?
2315                                             createTestQuadMosaic(m_imageViewType) :
2316                                             createTestQuadAttachmentFeedbackLoopLayout(m_imageViewType);
2317     for (unsigned int i = 0; i < vertices.size(); ++i)
2318     {
2319         if (m_testMode == TEST_MODE_READ_WRITE_DIFFERENT_AREAS)
2320         {
2321             vertices[i].texCoord.x() = std::max(vertices[i].texCoord.x(), 0.5f);
2322             vertices[i].position.x() = std::min(vertices[i].position.x(), 0.0f);
2323         }
2324         if (!m_imageViewType.isNormalized())
2325         {
2326             const float imageSize = static_cast<float>(m_imageSize);
2327             for (int j = 0; j < tcu::Vec4::SIZE; ++j)
2328                 vertices[i].texCoord[j] *= imageSize;
2329         }
2330     }
2331     return vertices;
2332 }
2333 
getSamplerCreateInfo(void) const2334 VkSamplerCreateInfo AttachmentFeedbackLoopLayoutSamplerTest::getSamplerCreateInfo(void) const
2335 {
2336     const VkSamplerCreateInfo defaultSamplerParams = {
2337         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,           // VkStructureType sType;
2338         DE_NULL,                                         // const void* pNext;
2339         0u,                                              // VkSamplerCreateFlags flags;
2340         VK_FILTER_NEAREST,                               // VkFilter magFilter;
2341         VK_FILTER_NEAREST,                               // VkFilter minFilter;
2342         VK_SAMPLER_MIPMAP_MODE_NEAREST,                  // VkSamplerMipmapMode mipmapMode;
2343         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,           // VkSamplerAddressMode addressModeU;
2344         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,           // VkSamplerAddressMode addressModeV;
2345         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,           // VkSamplerAddressMode addressModeW;
2346         0.0f,                                            // float mipLodBias;
2347         VK_FALSE,                                        // VkBool32 anisotropyEnable;
2348         1.0f,                                            // float maxAnisotropy;
2349         false,                                           // VkBool32 compareEnable;
2350         VK_COMPARE_OP_NEVER,                             // VkCompareOp compareOp;
2351         0.0f,                                            // float minLod;
2352         (m_imageViewType.isNormalized() ? 0.25f : 0.0f), // float maxLod;
2353         getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat,
2354                              false),     // VkBorderColor borderColor;
2355         !m_imageViewType.isNormalized(), // VkBool32 unnormalizedCoordinates;
2356     };
2357 
2358     return defaultSamplerParams;
2359 }
2360 
getComponentMapping(void) const2361 VkComponentMapping AttachmentFeedbackLoopLayoutSamplerTest::getComponentMapping(void) const
2362 {
2363     const VkComponentMapping componentMapping = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B,
2364                                                  VK_COMPONENT_SWIZZLE_A};
2365     return componentMapping;
2366 }
2367 
getGlslSamplerType(const tcu::TextureFormat & format,SamplerViewType type)2368 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSamplerType(const tcu::TextureFormat &format,
2369                                                                         SamplerViewType type)
2370 {
2371     std::ostringstream samplerType;
2372 
2373     if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
2374         samplerType << "u";
2375     else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
2376         samplerType << "i";
2377 
2378     switch (type)
2379     {
2380     case VK_IMAGE_VIEW_TYPE_1D:
2381         samplerType << "sampler1D";
2382         break;
2383 
2384     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2385         samplerType << "sampler1DArray";
2386         break;
2387 
2388     case VK_IMAGE_VIEW_TYPE_2D:
2389         samplerType << "sampler2D";
2390         break;
2391 
2392     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2393         samplerType << "sampler2DArray";
2394         break;
2395 
2396     case VK_IMAGE_VIEW_TYPE_3D:
2397         samplerType << "sampler3D";
2398         break;
2399 
2400     case VK_IMAGE_VIEW_TYPE_CUBE:
2401         samplerType << "samplerCube";
2402         break;
2403 
2404     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2405         samplerType << "samplerCubeArray";
2406         break;
2407 
2408     default:
2409         DE_FATAL("Unknown image view type");
2410         break;
2411     }
2412 
2413     return samplerType.str();
2414 }
2415 
getImageSize(SamplerViewType viewType,int size)2416 tcu::IVec3 AttachmentFeedbackLoopLayoutSamplerTest::getImageSize(SamplerViewType viewType, int size)
2417 {
2418     switch (viewType)
2419     {
2420     case VK_IMAGE_VIEW_TYPE_1D:
2421     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2422         return tcu::IVec3(size, 1, 1);
2423 
2424     case VK_IMAGE_VIEW_TYPE_3D:
2425         return tcu::IVec3(size, size, 4);
2426 
2427     default:
2428         break;
2429     }
2430 
2431     return tcu::IVec3(size, size, 1);
2432 }
2433 
getArraySize(SamplerViewType viewType)2434 int AttachmentFeedbackLoopLayoutSamplerTest::getArraySize(SamplerViewType viewType)
2435 {
2436     switch (viewType)
2437     {
2438     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2439     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2440     case VK_IMAGE_VIEW_TYPE_CUBE:
2441         return 6;
2442 
2443     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2444         return 36;
2445 
2446     default:
2447         break;
2448     }
2449 
2450     return 1;
2451 }
2452 
2453 // The idea behind this test is to reproduce a behavior that was causing GPU hangs on RADV.
2454 // * create a color attachment
2455 // * transition from UNDEFINED to COLOR_ATTACHMENT_OPTIMAL
2456 // * draw something
2457 // * transition from COLOR_ATTACHMENT_OPTIMAL to ATTACHMENT_FEEDBACK_LOOP_OPTIMAL
2458 // * draw something with a pipeline that has 0 color attachments
2459 // * GPU hanged
noColorAttachmentSupport(Context & context)2460 void noColorAttachmentSupport(Context &context)
2461 {
2462     context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_layout");
2463     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
2464 }
2465 
noColorAttachmentPrograms(SourceCollections & dst)2466 void noColorAttachmentPrograms(SourceCollections &dst)
2467 {
2468     std::ostringstream vert;
2469     vert << "#version 460\n"
2470          << "layout (location=0) in vec4 inPos;\n"
2471          << "void main (void) {\n"
2472          << "    gl_Position = inPos;\n"
2473          << "}\n";
2474     dst.glslSources.add("vert") << glu::VertexSource(vert.str());
2475 
2476     // For the initial draw, simple color.
2477     std::ostringstream frag1;
2478     frag1 << "#version 460\n"
2479           << "layout (location=0) out vec4 outColor;\n"
2480           << "layout (push_constant, std430) uniform PushConstantBlock {\n"
2481           << "    vec4 color;\n"
2482           << "} pc;\n"
2483           << "void main (void) {\n"
2484           << "    outColor = pc.color;\n"
2485           << "}\n";
2486     dst.glslSources.add("frag1") << glu::FragmentSource(frag1.str());
2487 
2488     // For the second draw, store without color attachments.
2489     std::ostringstream frag2;
2490     frag2 << "#version 460\n"
2491           << "layout (set=0, binding=0, std430) buffer BufferBlock {\n"
2492           << "    uint value;\n"
2493           << "} outBuffer;\n"
2494           << "void main (void) {\n"
2495           << "    atomicAdd(outBuffer.value, 1u);\n"
2496           << "}\n";
2497     dst.glslSources.add("frag2") << glu::FragmentSource(frag2.str());
2498 }
2499 
noColorAttachmentTest(Context & context)2500 tcu::TestStatus noColorAttachmentTest(Context &context)
2501 {
2502     const auto &ctx = context.getContextCommonData();
2503     const tcu::IVec3 fbExtent(544, 544, 1); // The image needs to be large-ish.
2504     const auto vkExtent  = makeExtent3D(fbExtent);
2505     const auto fbFormat  = VK_FORMAT_R8G8B8A8_UNORM;
2506     const auto tcuFormat = mapVkFormat(fbFormat);
2507     const auto fbUsage   = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2508                           VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
2509     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2510     const tcu::Vec4 geomColor1(0.0f, 0.0f, 1.0f, 1.0f);
2511     const tcu::Vec4 geomColor2(1.0f, 0.0f, 1.0f, 1.0f);
2512     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
2513     const auto descType   = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2514     const auto bindPoint  = VK_PIPELINE_BIND_POINT_GRAPHICS;
2515     const auto dataStages = VK_SHADER_STAGE_FRAGMENT_BIT;
2516     const auto colorSRR   = makeDefaultImageSubresourceRange();
2517 
2518     // Color buffer with verification buffer.
2519     ImageWithBuffer colorBuffer1(ctx.vkd, ctx.device, ctx.allocator, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
2520 
2521     // Second color buffer with verification buffer.
2522     ImageWithBuffer colorBuffer2(ctx.vkd, ctx.device, ctx.allocator, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
2523 
2524     // Vertices.
2525     const std::vector<tcu::Vec4> vertices{
2526         tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
2527         tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
2528         tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f),
2529         tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
2530     };
2531 
2532     // Indices.
2533     const std::vector<uint32_t> indices{
2534         0u, 1u, 2u, 2u, 1u, 3u,
2535     };
2536 
2537     // Vertex buffer
2538     const auto vbSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
2539     const auto vbInfo = makeBufferCreateInfo(vbSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
2540     BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vbInfo, MemoryRequirement::HostVisible);
2541     const auto vbAlloc  = vertexBuffer.getAllocation();
2542     void *vbData        = vbAlloc.getHostPtr();
2543     const auto vbOffset = static_cast<VkDeviceSize>(0);
2544 
2545     deMemcpy(vbData, de::dataOrNull(vertices), de::dataSize(vertices));
2546     flushAlloc(ctx.vkd, ctx.device, vbAlloc);
2547 
2548     // Index buffer.
2549     const auto ibSize = static_cast<VkDeviceSize>(de::dataSize(indices));
2550     const auto ibInfo = makeBufferCreateInfo(ibSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
2551     BufferWithMemory indexBuffer(ctx.vkd, ctx.device, ctx.allocator, ibInfo, MemoryRequirement::HostVisible);
2552     const auto ibAlloc  = indexBuffer.getAllocation();
2553     void *ibData        = ibAlloc.getHostPtr();
2554     const auto ibOffset = static_cast<VkDeviceSize>(0);
2555 
2556     deMemcpy(ibData, de::dataOrNull(indices), de::dataSize(indices));
2557     flushAlloc(ctx.vkd, ctx.device, ibAlloc);
2558 
2559     // Data buffer for the second fragment shader.
2560     const auto dbSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
2561     const auto dbInfo = makeBufferCreateInfo(dbSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2562     BufferWithMemory dataBuffer(ctx.vkd, ctx.device, ctx.allocator, dbInfo, MemoryRequirement::HostVisible);
2563     const auto dbAlloc  = dataBuffer.getAllocation();
2564     void *dbData        = dbAlloc.getHostPtr();
2565     const auto dbOffset = static_cast<VkDeviceSize>(0);
2566 
2567     deMemset(dbData, 0, sizeof(uint32_t));
2568     flushAlloc(ctx.vkd, ctx.device, dbAlloc);
2569 
2570     // Descriptor pool, set, layout, etc.
2571     DescriptorPoolBuilder poolBuilder;
2572     poolBuilder.addType(descType);
2573     const auto descriptorPool =
2574         poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2575 
2576     DescriptorSetLayoutBuilder layoutBuilder;
2577     layoutBuilder.addSingleBinding(descType, dataStages);
2578     const auto setLayout     = layoutBuilder.build(ctx.vkd, ctx.device);
2579     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *setLayout);
2580 
2581     DescriptorSetUpdateBuilder updateBuilder;
2582     const auto dbDescInfo = makeDescriptorBufferInfo(dataBuffer.get(), dbOffset, dbSize);
2583     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descType, &dbDescInfo);
2584     updateBuilder.update(ctx.vkd, ctx.device);
2585 
2586     // Push constant for the color attachment pipeline.
2587     const auto pcSize  = static_cast<uint32_t>(sizeof(geomColor1));
2588     const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
2589 
2590     // Two pipeline layouts: one without any descriptor and one with the single descriptor we use.
2591     const auto pipelineLayout1 = makePipelineLayout(ctx.vkd, ctx.device, VK_NULL_HANDLE, &pcRange);
2592     const auto pipelineLayout2 = makePipelineLayout(ctx.vkd, ctx.device, *setLayout);
2593 
2594     // Two render passes: one with one color attachment and one empty.
2595     const auto renderPass1 =
2596         makeRenderPass(ctx.vkd, ctx.device, fbFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
2597     const auto renderPass2 = makeRenderPass(ctx.vkd, ctx.device);
2598 
2599     // Three framebuffers: two with a color attachment and one empty with the same size.
2600     const auto framebuffer1 = makeFramebuffer(ctx.vkd, ctx.device, *renderPass1, colorBuffer1.getImageView(),
2601                                               vkExtent.width, vkExtent.height);
2602     const auto framebuffer2 =
2603         makeFramebuffer(ctx.vkd, ctx.device, *renderPass2, 0u, nullptr, vkExtent.width, vkExtent.height);
2604     const auto framebuffer3 = makeFramebuffer(ctx.vkd, ctx.device, *renderPass1, colorBuffer2.getImageView(),
2605                                               vkExtent.width, vkExtent.height);
2606 
2607     // Modules.
2608     const auto &binaries   = context.getBinaryCollection();
2609     const auto vertModule  = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
2610     const auto fragModule1 = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag1"));
2611     const auto fragModule2 = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag2"));
2612 
2613     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
2614     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
2615 
2616     // Two pipelines, with separate modules, layouts and render passes.
2617     const auto pipeline1 = makeGraphicsPipeline(
2618         ctx.vkd, ctx.device, *pipelineLayout1, *vertModule, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE,
2619         *fragModule1, *renderPass1, viewports,
2620         scissors); // The default values work for the current setup, including the vertex input data format.
2621 
2622     const auto pipeline2 =
2623         makeGraphicsPipeline(ctx.vkd, ctx.device, *pipelineLayout2, *vertModule, VK_NULL_HANDLE, VK_NULL_HANDLE,
2624                              VK_NULL_HANDLE, *fragModule2, *renderPass2, viewports, scissors); // Ditto.
2625 
2626     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
2627     const auto cmdBuffer = *cmd.cmdBuffer;
2628 
2629     beginCommandBuffer(ctx.vkd, cmdBuffer);
2630 
2631     // Transition color buffers to color attachment optimal.
2632     {
2633         const std::vector<VkImage> images{colorBuffer1.getImage(), colorBuffer2.getImage()};
2634         std::vector<VkImageMemoryBarrier> barriers;
2635         barriers.reserve(images.size());
2636 
2637         for (const auto &img : images)
2638         {
2639             const auto transitionBarrier = makeImageMemoryBarrier(
2640                 0u, (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
2641                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, img, colorSRR);
2642             barriers.push_back(transitionBarrier);
2643         }
2644         cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2645                                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, de::dataOrNull(barriers),
2646                                       barriers.size());
2647     }
2648 
2649     beginRenderPass(ctx.vkd, cmdBuffer, *renderPass1, *framebuffer1, scissors.at(0u), clearColor);
2650     ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
2651     ctx.vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer.get(), ibOffset, VK_INDEX_TYPE_UINT32);
2652     ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, *pipeline1);
2653     ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout1, dataStages, 0u, pcSize, &geomColor1);
2654     ctx.vkd.cmdDrawIndexed(cmdBuffer, de::sizeU32(indices), 1u, 0u, 0, 0u);
2655     endRenderPass(ctx.vkd, cmdBuffer);
2656 
2657     // Transition first color buffer to feedback loop layout optimal.
2658     {
2659         const auto transitionBarrier = makeImageMemoryBarrier(
2660             (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), 0u,
2661             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT,
2662             colorBuffer1.getImage(), colorSRR);
2663         cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2664                                       VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, &transitionBarrier);
2665     }
2666 
2667     // Draw with the empty framebuffer and the second pipeline, saving results to the storage buffer.
2668     beginRenderPass(ctx.vkd, cmdBuffer, *renderPass2, *framebuffer2, scissors.at(0u));
2669     ctx.vkd.cmdBindDescriptorSets(cmdBuffer, bindPoint, *pipelineLayout2, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2670     ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
2671     ctx.vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer.get(), ibOffset, VK_INDEX_TYPE_UINT32);
2672     ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, *pipeline2);
2673     ctx.vkd.cmdDrawIndexed(cmdBuffer, de::sizeU32(indices), 1u, 0u, 0, 0u);
2674     endRenderPass(ctx.vkd, cmdBuffer);
2675 
2676     // Barrier for the storage buffer.
2677     {
2678         const auto frag2hostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2679         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2680                                  &frag2hostBarrier);
2681     }
2682 
2683 #if 0
2684     // Transition color buffer back to color attachment optimal.
2685     {
2686         const auto transitionBarrier = makeImageMemoryBarrier(0u,
2687             (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
2688             VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT,
2689             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2690             colorBuffer1.getImage(), colorSRR);
2691         cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &transitionBarrier);
2692     }
2693 #endif
2694 
2695     beginRenderPass(ctx.vkd, cmdBuffer, *renderPass1, *framebuffer3, scissors.at(0u), clearColor);
2696     ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
2697     ctx.vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer.get(), ibOffset, VK_INDEX_TYPE_UINT32);
2698     ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, *pipeline1);
2699     ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout1, dataStages, 0u, pcSize, &geomColor2);
2700     ctx.vkd.cmdDrawIndexed(cmdBuffer, de::sizeU32(indices), 1u, 0u, 0, 0u);
2701     endRenderPass(ctx.vkd, cmdBuffer);
2702 
2703     copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer1.getImage(), colorBuffer1.getBuffer(), fbExtent.swizzle(0, 1), 0u,
2704                       VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT, 1u, VK_IMAGE_ASPECT_COLOR_BIT,
2705                       VK_IMAGE_ASPECT_COLOR_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
2706 
2707     copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer2.getImage(), colorBuffer2.getBuffer(), fbExtent.swizzle(0, 1),
2708                       (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
2709                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u, VK_IMAGE_ASPECT_COLOR_BIT,
2710                       VK_IMAGE_ASPECT_COLOR_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
2711 
2712     endCommandBuffer(ctx.vkd, cmdBuffer);
2713     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
2714 
2715     // Verify color outputs.
2716     invalidateAlloc(ctx.vkd, ctx.device, colorBuffer1.getBufferAllocation());
2717     invalidateAlloc(ctx.vkd, ctx.device, colorBuffer2.getBufferAllocation());
2718 
2719     tcu::PixelBufferAccess resultAccess1(tcuFormat, fbExtent, colorBuffer1.getBufferAllocation().getHostPtr());
2720     tcu::PixelBufferAccess resultAccess2(tcuFormat, fbExtent, colorBuffer2.getBufferAllocation().getHostPtr());
2721 
2722     tcu::TextureLevel referenceLevel1(tcuFormat, fbExtent.x(), fbExtent.y());
2723     auto referenceAccess1 = referenceLevel1.getAccess();
2724     tcu::clear(referenceAccess1, geomColor1);
2725 
2726     tcu::TextureLevel referenceLevel2(tcuFormat, fbExtent.x(), fbExtent.y());
2727     auto referenceAccess2 = referenceLevel2.getAccess();
2728     tcu::clear(referenceAccess2, geomColor2);
2729 
2730     auto &log = context.getTestContext().getLog();
2731 
2732     if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess1, resultAccess1, threshold,
2733                                     tcu::COMPARE_LOG_ON_ERROR))
2734         TCU_FAIL("Unexpected color in first result buffer; check log for details");
2735 
2736     if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess2, resultAccess2, threshold,
2737                                     tcu::COMPARE_LOG_ON_ERROR))
2738         TCU_FAIL("Unexpected color in second result buffer; check log for details");
2739 
2740     // Verify storage buffer.
2741     invalidateAlloc(ctx.vkd, ctx.device, dbAlloc);
2742     {
2743         uint32_t outputVal;
2744         const auto expectedVal = vkExtent.width * vkExtent.height;
2745 
2746         deMemcpy(&outputVal, dbData, sizeof(outputVal));
2747         if (outputVal != expectedVal)
2748             TCU_FAIL("Unexpected data buffer value: expected " + std::to_string(expectedVal) + " and found " +
2749                      std::to_string(outputVal));
2750     }
2751 
2752     return tcu::TestStatus::pass("Pass");
2753 }
2754 
2755 using TestCaseGroupPtr = de::MovePtr<tcu::TestCaseGroup>;
2756 
2757 } // namespace
2758 
createAttachmentFeedbackLoopLayoutSamplerTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)2759 tcu::TestCaseGroup *createAttachmentFeedbackLoopLayoutSamplerTests(
2760     tcu::TestContext &testCtx, vk::PipelineConstructionType pipelineConstructionType)
2761 {
2762     // TODO: implement layer rendering with a geometry shader to render to arrays, 3D and cube images.
2763     const struct
2764     {
2765         SamplerViewType type;
2766         const char *name;
2767         bool readOnly;
2768     } imageViewTypes[] = {{VK_IMAGE_VIEW_TYPE_1D, "1d", false},
2769                           {{VK_IMAGE_VIEW_TYPE_1D, false}, "1d_unnormalized", false},
2770                           {VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", true},
2771                           {VK_IMAGE_VIEW_TYPE_2D, "2d", false},
2772                           {{VK_IMAGE_VIEW_TYPE_2D, false}, "2d_unnormalized", false},
2773                           {VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", true},
2774                           {VK_IMAGE_VIEW_TYPE_3D, "3d", true},
2775                           {VK_IMAGE_VIEW_TYPE_CUBE, "cube", true},
2776                           {VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", true}};
2777 
2778     const VkFormat formats[] = {
2779         VK_FORMAT_R8G8B8A8_UNORM,    VK_FORMAT_D16_UNORM,          VK_FORMAT_D32_SFLOAT, VK_FORMAT_D16_UNORM_S8_UINT,
2780         VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_S8_UINT};
2781 
2782     TestCaseGroupPtr samplingTypeTests(new tcu::TestCaseGroup(testCtx, "sampler"));
2783 
2784     const struct
2785     {
2786         enum TestMode mode;
2787         const char *name;
2788     } testModes[] = {
2789         {TEST_MODE_READ_ONLY, "_read"},
2790         {TEST_MODE_READ_WRITE_SAME_PIXEL, "_read_write_same_pixel"},
2791         {TEST_MODE_READ_WRITE_DIFFERENT_AREAS, "_read_write_different_areas"},
2792     };
2793 
2794     const char *imageAspectTestModes[] = {"_color", "_depth", "_stencil"};
2795 
2796     const struct
2797     {
2798         VkDescriptorType type;
2799         const char *name;
2800     } imageDescriptorTypes[] = {
2801         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler"},
2802         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image"},
2803     };
2804 
2805     const struct
2806     {
2807         bool interleaveReadWriteComponents;
2808         const char *name;
2809     } interleaveReadWriteComponentsModes[] = {
2810         {false, ""},
2811         {true, "_interleave_read_write_components"},
2812     };
2813 
2814     const struct
2815     {
2816         const PipelineStateMode pipelineStateMode;
2817         const char *suffix;
2818     } pipelineStateModes[] = {
2819         {PipelineStateMode::STATIC, ""},
2820         {PipelineStateMode::DYNAMIC_WITH_ZERO_STATIC, "_dynamic_zero_static"},
2821         {PipelineStateMode::DYNAMIC_WITH_CONTRADICTORY_STATIC, "_dynamic_bad_static"},
2822     };
2823 
2824     for (int imageDescriptorTypeNdx = 0; imageDescriptorTypeNdx < DE_LENGTH_OF_ARRAY(imageDescriptorTypes);
2825          imageDescriptorTypeNdx++)
2826     {
2827         VkDescriptorType imageDescriptorType = imageDescriptorTypes[imageDescriptorTypeNdx].type;
2828         TestCaseGroupPtr imageDescriptorTypeGroup(
2829             new tcu::TestCaseGroup(testCtx, imageDescriptorTypes[imageDescriptorTypeNdx].name));
2830         TestCaseGroupPtr imageTypeTests(new tcu::TestCaseGroup(testCtx, "image_type"));
2831 
2832         for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
2833         {
2834             const SamplerViewType viewType = imageViewTypes[viewTypeNdx].type;
2835             TestCaseGroupPtr viewTypeGroup(new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name));
2836             TestCaseGroupPtr formatTests(new tcu::TestCaseGroup(testCtx, "format"));
2837 
2838             for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2839             {
2840                 const VkFormat format     = formats[formatNdx];
2841                 const bool isCompressed   = isCompressedFormat(format);
2842                 const bool isDepthStencil = !isCompressed && tcu::hasDepthComponent(mapVkFormat(format).order) &&
2843                                             tcu::hasStencilComponent(mapVkFormat(format).order);
2844                 ImageAspectTestMode imageAspectTestMode = getImageAspectTestMode(format);
2845 
2846                 if (isCompressed)
2847                 {
2848                     // Do not use compressed formats with 1D and 1D array textures.
2849                     if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2850                         break;
2851                 }
2852 
2853                 for (int testModeNdx = 0; testModeNdx < DE_LENGTH_OF_ARRAY(testModes); testModeNdx++)
2854                 {
2855                     if (imageViewTypes[viewTypeNdx].readOnly && testModes[testModeNdx].mode != TEST_MODE_READ_ONLY)
2856                         continue;
2857 
2858                     for (int restrictColorNdx = 0;
2859                          restrictColorNdx < DE_LENGTH_OF_ARRAY(interleaveReadWriteComponentsModes); restrictColorNdx++)
2860                     {
2861                         // Limit the interleaveReadWriteComponents test to the ones sampling and writing to the same pixel, to avoid having more tests that are not really adding coverage.
2862                         if (interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents &&
2863                             testModes[testModeNdx].mode != TEST_MODE_READ_WRITE_SAME_PIXEL)
2864                             continue;
2865 
2866                         // If the format is depth-only or stencil-only, do not read one component and write it to the other, as it is missing.
2867                         if (interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents &&
2868                             (tcu::hasDepthComponent(mapVkFormat(format).order) ||
2869                              tcu::hasStencilComponent(mapVkFormat(format).order)) &&
2870                             !isDepthStencil)
2871                             continue;
2872 
2873                         for (const auto &pipelineStateMode : pipelineStateModes)
2874                         {
2875                             // In shader object variants of the tests there's no static part, so the
2876                             // DYNAMIC_WITH_CONTRADICTORY_STATIC variants serve no purpose. We could keep just one of the variants,
2877                             // but we run both a static and a dynamic one because the command sequence is not exactly the same in
2878                             // both cases, and the flags used in vkCmdSetAttachmentFeedbackLoopEnableEXT also differ slightly.
2879                             //
2880                             // The static variant allows us to check a different sequence and that the code in the pipeline
2881                             // construction utils is working correctly.
2882                             //
2883                             // The dynamic variant sets the state later explicitly (see above) and uses more specific aspect flags.
2884                             //
2885                             if (pipelineStateMode.pipelineStateMode ==
2886                                     PipelineStateMode::DYNAMIC_WITH_CONTRADICTORY_STATIC &&
2887                                 isConstructionTypeShaderObject(pipelineConstructionType))
2888                                 continue;
2889 
2890                             std::string name = getFormatCaseName(format) + imageAspectTestModes[imageAspectTestMode] +
2891                                                testModes[testModeNdx].name +
2892                                                interleaveReadWriteComponentsModes[restrictColorNdx].name +
2893                                                pipelineStateMode.suffix;
2894                             formatTests->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(
2895                                 testCtx, pipelineConstructionType, name.c_str(), viewType, format, outputImageSize,
2896                                 imageDescriptorType, 0.0f, testModes[testModeNdx].mode, imageAspectTestMode,
2897                                 interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents,
2898                                 pipelineStateMode.pipelineStateMode, false));
2899 
2900                             if (!isCompressed && isDepthStencil)
2901                             {
2902                                 // Image is depth-stencil. Add the stencil case as well.
2903                                 std::string stencilTestName =
2904                                     getFormatCaseName(format) + imageAspectTestModes[IMAGE_ASPECT_TEST_STENCIL] +
2905                                     testModes[testModeNdx].name +
2906                                     interleaveReadWriteComponentsModes[restrictColorNdx].name +
2907                                     pipelineStateMode.suffix;
2908                                 formatTests->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(
2909                                     testCtx, pipelineConstructionType, stencilTestName.c_str(), viewType, format,
2910                                     outputImageSize, imageDescriptorType, 0.0f, testModes[testModeNdx].mode,
2911                                     IMAGE_ASPECT_TEST_STENCIL,
2912                                     interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents,
2913                                     pipelineStateMode.pipelineStateMode, false));
2914                             }
2915                         }
2916                     }
2917                 }
2918             }
2919 
2920             viewTypeGroup->addChild(formatTests.release());
2921             imageTypeTests->addChild(viewTypeGroup.release());
2922         }
2923         imageDescriptorTypeGroup->addChild(imageTypeTests.release());
2924         samplingTypeTests->addChild(imageDescriptorTypeGroup.release());
2925     }
2926 
2927     if (pipelineConstructionType == PipelineConstructionType::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2928     {
2929         TestCaseGroupPtr miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
2930         miscGroup->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(
2931             testCtx, pipelineConstructionType, "maintenance5_color_attachment", VK_IMAGE_VIEW_TYPE_2D,
2932             VK_FORMAT_R8G8B8A8_UNORM, outputImageSize, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0.0f, TEST_MODE_READ_ONLY,
2933             IMAGE_ASPECT_TEST_COLOR, false, PipelineStateMode::STATIC, true));
2934         miscGroup->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(
2935             testCtx, pipelineConstructionType, "maintenance5_ds_attachment", VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D16_UNORM,
2936             outputImageSize, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0.0f, TEST_MODE_READ_ONLY, IMAGE_ASPECT_TEST_DEPTH,
2937             false, PipelineStateMode::STATIC, true));
2938         samplingTypeTests->addChild(miscGroup.release());
2939     }
2940 
2941     return samplingTypeTests.release();
2942 }
2943 
createAttachmentFeedbackLoopLayoutTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)2944 tcu::TestCaseGroup *createAttachmentFeedbackLoopLayoutTests(tcu::TestContext &testCtx,
2945                                                             vk::PipelineConstructionType pipelineConstructionType)
2946 {
2947     TestCaseGroupPtr attachmentFeedbackLoopLayoutTests(
2948         new tcu::TestCaseGroup(testCtx, "attachment_feedback_loop_layout"));
2949     {
2950         attachmentFeedbackLoopLayoutTests->addChild(
2951             createAttachmentFeedbackLoopLayoutSamplerTests(testCtx, pipelineConstructionType));
2952     }
2953 
2954     TestCaseGroupPtr miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
2955     {
2956         if (pipelineConstructionType == PipelineConstructionType::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2957             addFunctionCaseWithPrograms(miscGroup.get(), "no_color_draw", noColorAttachmentSupport,
2958                                         noColorAttachmentPrograms, noColorAttachmentTest);
2959     }
2960 
2961     attachmentFeedbackLoopLayoutTests->addChild(miscGroup.release());
2962 
2963     return attachmentFeedbackLoopLayoutTests.release();
2964 }
2965 
2966 } // namespace pipeline
2967 } // namespace vkt
2968