1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
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 vktPipelineFramebuferAttachmentTests.cpp
23  * \brief Render to a framebuffer with attachments of different sizes and with
24  *        no attachments at all
25  *
26  *//*--------------------------------------------------------------------*/
27 
28 #include "vktPipelineFramebufferAttachmentTests.hpp"
29 #include "vktPipelineMakeUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktTestCaseUtil.hpp"
32 #include "vktPipelineVertexUtil.hpp"
33 #include "vktTestGroupUtil.hpp"
34 
35 #include "vkMemUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkBuilderUtil.hpp"
41 #include "vkPrograms.hpp"
42 #include "vkImageUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
45 
46 #include "tcuTextureUtil.hpp"
47 #include "tcuImageCompare.hpp"
48 
49 #include "deUniquePtr.hpp"
50 #include "deSharedPtr.hpp"
51 
52 #include <string>
53 #include <vector>
54 
55 namespace vkt
56 {
57 namespace pipeline
58 {
59 namespace
60 {
61 using namespace vk;
62 using de::MovePtr;
63 using de::SharedPtr;
64 using de::UniquePtr;
65 using std::vector;
66 using tcu::IVec3;
67 using tcu::IVec4;
68 using tcu::UVec4;
69 using tcu::Vec4;
70 
71 static const VkFormat COLOR_FORMAT = VK_FORMAT_R8G8B8A8_UNORM;
72 
73 typedef SharedPtr<Unique<VkImageView>> SharedPtrVkImageView;
74 
75 enum MultiAttachmentsTestType
76 {
77     MULTI_ATTACHMENTS_NONE,
78     MULTI_ATTACHMENTS_DIFFERENT_SIZES,
79     MULTI_ATTACHMENTS_NOT_EXPORTED,
80 };
81 
82 struct CaseDef
83 {
84     PipelineConstructionType pipelineConstructionType;
85     VkImageViewType imageType;
86     IVec3 renderSize;
87     IVec3 attachmentSize;
88     uint32_t numLayers;
89     bool multisample;
90     MultiAttachmentsTestType multiAttachmentsTestType;
91 };
92 
93 template <typename T>
makeSharedPtr(Move<T> move)94 inline SharedPtr<Unique<T>> makeSharedPtr(Move<T> move)
95 {
96     return SharedPtr<Unique<T>>(new Unique<T>(move));
97 }
98 
99 template <typename T>
sizeInBytes(const vector<T> & vec)100 inline VkDeviceSize sizeInBytes(const vector<T> &vec)
101 {
102     return vec.size() * sizeof(vec[0]);
103 }
104 
getImageType(const VkImageViewType viewType)105 VkImageType getImageType(const VkImageViewType viewType)
106 {
107     switch (viewType)
108     {
109     case VK_IMAGE_VIEW_TYPE_1D:
110     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
111         return VK_IMAGE_TYPE_1D;
112 
113     case VK_IMAGE_VIEW_TYPE_2D:
114     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
115     case VK_IMAGE_VIEW_TYPE_CUBE:
116     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
117         return VK_IMAGE_TYPE_2D;
118 
119     case VK_IMAGE_VIEW_TYPE_3D:
120         return VK_IMAGE_TYPE_3D;
121 
122     default:
123         DE_ASSERT(0);
124         return VK_IMAGE_TYPE_LAST;
125     }
126 }
127 
128 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat,const uint32_t numLayers,const bool multisample)129 RenderPassWrapper makeRenderPass(const DeviceInterface &vk, const VkDevice device,
130                                  const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat,
131                                  const uint32_t numLayers, const bool multisample)
132 {
133     vector<VkAttachmentDescription> attachmentDescriptions(numLayers);
134     uint32_t attachmentIndex = 0;
135     vector<VkAttachmentReference> colorAttachmentReferences(numLayers);
136     vector<VkSubpassDescription> subpasses;
137 
138     for (uint32_t i = 0; i < numLayers; i++)
139     {
140         VkAttachmentDescription colorAttachmentDescription = {
141             (VkAttachmentDescriptionFlags)0,                              // VkAttachmentDescriptionFla flags;
142             colorFormat,                                                  // VkFormat format;
143             !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
144             VK_ATTACHMENT_LOAD_OP_LOAD,                                   // VkAttachmentLoadOp loadOp;
145             VK_ATTACHMENT_STORE_OP_STORE,                                 // VkAttachmentStoreOp storeOp;
146             VK_ATTACHMENT_LOAD_OP_DONT_CARE,                              // VkAttachmentLoadOp stencilLoadOp;
147             VK_ATTACHMENT_STORE_OP_DONT_CARE,                             // VkAttachmentStoreOp stencilStoreOp;
148             VK_IMAGE_LAYOUT_GENERAL,                                      // VkImageLayout initialLayout;
149             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                     // VkImageLayout finalLayout;
150         };
151         attachmentDescriptions[attachmentIndex++] = colorAttachmentDescription;
152     }
153 
154     // Create a subpass for each attachment (each attachment is a layer of an arrayed image).
155     for (uint32_t i = 0; i < numLayers; ++i)
156     {
157         const VkAttachmentReference attachmentRef = {
158             i,                                       // uint32_t attachment;
159             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
160         };
161         colorAttachmentReferences[i] = attachmentRef;
162 
163         const VkSubpassDescription subpassDescription = {
164             (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags flags;
165             VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
166             0u,                              // uint32_t inputAttachmentCount;
167             DE_NULL,                         // const VkAttachmentReference* pInputAttachments;
168             1u,                              // uint32_t colorAttachmentCount;
169             &colorAttachmentReferences[i],   // const VkAttachmentReference* pColorAttachments;
170             DE_NULL,                         // const VkAttachmentReference* pResolveAttachments;
171             DE_NULL,                         // const VkAttachmentReference* pDepthStencilAttachment;
172             0u,                              // uint32_t preserveAttachmentCount;
173             DE_NULL                          // const uint32_t* pPreserveAttachments;
174         };
175         subpasses.push_back(subpassDescription);
176     }
177 
178     const VkRenderPassCreateInfo renderPassInfo = {
179         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
180         DE_NULL,                                   // const void* pNext;
181         (VkRenderPassCreateFlags)0,                // VkRenderPassCreateFlags flags;
182         numLayers,                                 // uint32_t attachmentCount;
183         &attachmentDescriptions[0],                // const VkAttachmentDescription* pAttachments;
184         static_cast<uint32_t>(subpasses.size()),   // uint32_t subpassCount;
185         &subpasses[0],                             // const VkSubpassDescription* pSubpasses;
186         0u,                                        // uint32_t dependencyCount;
187         DE_NULL                                    // const VkSubpassDependency* pDependencies;
188     };
189 
190     return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
191 }
192 
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertexModule,const ShaderWrapper fragmentModule,const IVec3 renderSize,const VkPrimitiveTopology topology,const uint32_t subpass,const uint32_t numAttachments,const bool multisample)193 void preparePipelineWrapper(GraphicsPipelineWrapper &gpw, const PipelineLayoutWrapper &pipelineLayout,
194                             const VkRenderPass renderPass, const ShaderWrapper vertexModule,
195                             const ShaderWrapper fragmentModule, const IVec3 renderSize,
196                             const VkPrimitiveTopology topology, const uint32_t subpass, const uint32_t numAttachments,
197                             const bool multisample)
198 {
199     const std::vector<VkViewport> viewports{makeViewport(renderSize)};
200     const std::vector<VkRect2D> scissors{makeRect2D(renderSize)};
201 
202     const VkColorComponentFlags colorComponentsAll =
203         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
204 
205     const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo{
206         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                          sType;
207         DE_NULL,                                                  // const void*                              pNext;
208         (VkPipelineMultisampleStateCreateFlags)0,                 // VkPipelineMultisampleStateCreateFlags    flags;
209         multisample ? VK_SAMPLE_COUNT_4_BIT :
210                       VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits                    rasterizationSamples;
211         VK_FALSE,                            // VkBool32                                 sampleShadingEnable;
212         1.0f,                                // float                                    minSampleShading;
213         DE_NULL,                             // const VkSampleMask*                      pSampleMask;
214         VK_FALSE,                            // VkBool32                                 alphaToCoverageEnable;
215         VK_FALSE                             // VkBool32                                 alphaToOneEnable;
216     };
217 
218     const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState{
219         VK_FALSE,             // VkBool32                 blendEnable;
220         VK_BLEND_FACTOR_ONE,  // VkBlendFactor            srcColorBlendFactor;
221         VK_BLEND_FACTOR_ZERO, // VkBlendFactor            dstColorBlendFactor;
222         VK_BLEND_OP_ADD,      // VkBlendOp                colorBlendOp;
223         VK_BLEND_FACTOR_ONE,  // VkBlendFactor            srcAlphaBlendFactor;
224         VK_BLEND_FACTOR_ZERO, // VkBlendFactor            dstAlphaBlendFactor;
225         VK_BLEND_OP_ADD,      // VkBlendOp                alphaBlendOp;
226         colorComponentsAll    // VkColorComponentFlags    colorWriteMask;
227     };
228 
229     std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
230     for (uint32_t attachmentIdx = 0; attachmentIdx < numAttachments; attachmentIdx++)
231         colorBlendAttachmentStates.push_back(pipelineColorBlendAttachmentState);
232 
233     const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo{
234         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                              sType;
235         DE_NULL,                                                  // const void*                                  pNext;
236         (VkPipelineColorBlendStateCreateFlags)0,                  // VkPipelineColorBlendStateCreateFlags         flags;
237         VK_FALSE,         // VkBool32                                     logicOpEnable;
238         VK_LOGIC_OP_COPY, // VkLogicOp                                    logicOp;
239         numAttachments,   // uint32_t                                     attachmentCount;
240         numAttachments == 0 ?
241             DE_NULL :
242             &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState*   pAttachments;
243         {0.0f, 0.0f, 0.0f, 0.0f}            // float                                        blendConstants[4];
244     };
245 
246     gpw.setDefaultTopology(topology)
247         .setDefaultRasterizationState()
248         .setDefaultDepthStencilState()
249         .setupVertexInputState()
250         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, subpass, vertexModule)
251         .setupFragmentShaderState(pipelineLayout, renderPass, subpass, fragmentModule, DE_NULL,
252                                   &pipelineMultisampleStateInfo)
253         .setupFragmentOutputState(renderPass, subpass, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo)
254         .setMonolithicPipelineLayout(pipelineLayout)
255         .buildPipeline();
256 }
257 
makeImage(const DeviceInterface & vk,const VkDevice device,const VkImageCreateFlags flags,const VkImageType imageType,const VkFormat format,const IVec3 & size,const uint32_t numLayers,const VkImageUsageFlags usage,const bool multisample)258 Move<VkImage> makeImage(const DeviceInterface &vk, const VkDevice device, const VkImageCreateFlags flags,
259                         const VkImageType imageType, const VkFormat format, const IVec3 &size, const uint32_t numLayers,
260                         const VkImageUsageFlags usage, const bool multisample)
261 {
262     const VkImageCreateInfo imageParams = {
263         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                         // VkStructureType sType;
264         DE_NULL,                                                     // const void* pNext;
265         flags,                                                       // VkImageCreateFlags flags;
266         imageType,                                                   // VkImageType imageType;
267         format,                                                      // VkFormat format;
268         makeExtent3D(size),                                          // VkExtent3D extent;
269         1u,                                                          // uint32_t mipLevels;
270         numLayers,                                                   // uint32_t arrayLayers;
271         multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
272         VK_IMAGE_TILING_OPTIMAL,                                     // VkImageTiling tiling;
273         usage,                                                       // VkImageUsageFlags usage;
274         VK_SHARING_MODE_EXCLUSIVE,                                   // VkSharingMode sharingMode;
275         0u,                                                          // uint32_t queueFamilyIndexCount;
276         DE_NULL,                                                     // const uint32_t* pQueueFamilyIndices;
277         VK_IMAGE_LAYOUT_UNDEFINED,                                   // VkImageLayout initialLayout;
278     };
279 
280     return createImage(vk, device, &imageParams);
281 }
282 
genFullQuadVertices(const int subpassCount)283 vector<tcu::Vec4> genFullQuadVertices(const int subpassCount)
284 {
285     vector<tcu::Vec4> vectorData;
286     for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
287     {
288         vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
289         vectorData.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
290         vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
291         vectorData.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f));
292     }
293     return vectorData;
294 }
295 
initColorPrograms(SourceCollections & programCollection,const CaseDef)296 void initColorPrograms(SourceCollections &programCollection, const CaseDef)
297 {
298     // Vertex shader
299     {
300         std::ostringstream src;
301         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
302             << "\n"
303             << "layout(location = 0) in vec4 in_position;\n"
304             << "\n"
305             << "out gl_PerVertex {\n"
306             << "    vec4 gl_Position;\n"
307             << "};\n"
308             << "\n"
309             << "void main(void)\n"
310             << "{\n"
311             << "    gl_Position = in_position;\n"
312             << "}\n";
313 
314         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
315     }
316 
317     // Fragment shader
318     {
319         std::ostringstream src;
320         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
321             << "\n"
322             << "layout(location = 0) out vec4 o_color;\n"
323             << "\n"
324             << "void main(void)\n"
325             << "{\n"
326             << "    o_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
327             << "}\n";
328 
329         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
330     }
331 }
332 
getExpectedData(tcu::TextureLevel & textureLevel,const CaseDef & caseDef)333 tcu::PixelBufferAccess getExpectedData(tcu::TextureLevel &textureLevel, const CaseDef &caseDef)
334 {
335     const tcu::PixelBufferAccess expectedImage(textureLevel);
336     const int renderDepth = deMax32(caseDef.renderSize.z(), caseDef.numLayers);
337 
338     for (int z = 0; z < expectedImage.getDepth(); ++z)
339     {
340         for (int y = 0; y < expectedImage.getHeight(); ++y)
341         {
342             for (int x = 0; x < expectedImage.getWidth(); ++x)
343             {
344                 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth)
345                     expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
346                 else
347                     expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z);
348             }
349         }
350     }
351     return expectedImage;
352 }
353 
makeColorSubresourceRange(const uint32_t baseArrayLayer,const uint32_t layerCount)354 inline VkImageSubresourceRange makeColorSubresourceRange(const uint32_t baseArrayLayer, const uint32_t layerCount)
355 {
356     return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
357 }
358 
359 // Tests rendering to a a framebuffer with color attachments larger than the
360 // framebuffer dimensions and verifies that rendering does not affect the areas
361 // of the attachment outside the framebuffer dimensions. Tests both single-sample
362 // and multi-sample configurations.
test(Context & context,const CaseDef caseDef)363 tcu::TestStatus test(Context &context, const CaseDef caseDef)
364 {
365     const InstanceInterface &vki          = context.getInstanceInterface();
366     const DeviceInterface &vk             = context.getDeviceInterface();
367     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
368     const VkDevice device                 = context.getDevice();
369     const VkQueue queue                   = context.getUniversalQueue();
370     const uint32_t queueFamilyIndex       = context.getUniversalQueueFamilyIndex();
371     Allocator &allocator                  = context.getDefaultAllocator();
372 
373     // Color image for rendering in single-sample tests or resolve target for multi-sample tests
374     Move<VkImage> colorImage;
375     MovePtr<Allocation> colorImageAlloc;
376 
377     // For multisampled tests, this is the rendering target
378     Move<VkImage> msColorImage;
379     MovePtr<Allocation> msColorImageAlloc;
380 
381     // Host memory buffer where we will copy the rendered image for verification
382     const uint32_t att_size_x = caseDef.attachmentSize.x();
383     const uint32_t att_size_y = caseDef.attachmentSize.y();
384     const uint32_t att_size_z = caseDef.attachmentSize.z();
385     const VkDeviceSize colorBufferSize =
386         att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
387     const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
388     const UniquePtr<Allocation> colorBufferAlloc(
389         bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
390 
391     Move<VkBuffer> vertexBuffer;
392     MovePtr<Allocation> vertexBufferAlloc;
393 
394     vector<SharedPtrVkImageView> colorAttachments;
395     vector<VkImage> images;
396     vector<VkImageView> attachmentHandles;
397 
398     const PipelineLayoutWrapper pipelineLayout(caseDef.pipelineConstructionType, vk, device);
399     vector<GraphicsPipelineWrapper> pipeline;
400     RenderPassWrapper renderPass(makeRenderPass(vk, device, caseDef.pipelineConstructionType, COLOR_FORMAT,
401                                                 caseDef.numLayers, caseDef.multisample));
402 
403     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
404     const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
405 
406     const Unique<VkCommandPool> cmdPool(
407         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
408     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
409 
410     const VkImageViewType imageViewType =
411         caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ?
412             VK_IMAGE_VIEW_TYPE_2D :
413             caseDef.imageType;
414 
415     // create vertexBuffer
416     {
417         const vector<tcu::Vec4> vertices    = genFullQuadVertices(caseDef.numLayers);
418         const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
419 
420         vertexBuffer      = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
421         vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
422 
423         deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
424         flushAlloc(vk, device, *vertexBufferAlloc);
425     }
426 
427     // create colorImage (and msColorImage) using the configured attachmentsize
428     {
429         const VkImageUsageFlags colorImageUsage =
430             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
431 
432         colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
433                                caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
434         colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
435 
436         if (caseDef.multisample)
437         {
438             const VkImageUsageFlags msImageUsage =
439                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
440 
441             msColorImage      = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType),
442                                           COLOR_FORMAT, caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
443             msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
444         }
445     }
446 
447     // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
448     pipeline.reserve(caseDef.numLayers);
449     for (uint32_t layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
450     {
451         colorAttachments.push_back(
452             makeSharedPtr(makeImageView(vk, device, !caseDef.multisample ? *colorImage : *msColorImage, imageViewType,
453                                         COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
454         images.push_back(!caseDef.multisample ? *colorImage : *msColorImage);
455         attachmentHandles.push_back(**colorAttachments.back());
456 
457         pipeline.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
458                               caseDef.pipelineConstructionType);
459         preparePipelineWrapper(pipeline.back(), pipelineLayout, *renderPass, vertexModule, fragmentModule,
460                                caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u,
461                                caseDef.multisample);
462     }
463 
464     // create framebuffer
465     renderPass.createFramebuffer(vk, device, caseDef.numLayers, &images[0], &attachmentHandles[0],
466                                  static_cast<uint32_t>(caseDef.renderSize.x()),
467                                  static_cast<uint32_t>(caseDef.renderSize.y()));
468 
469     // record command buffer
470     beginCommandBuffer(vk, *cmdBuffer);
471     {
472         // Clear the entire image attachment to black
473         {
474             const VkImageMemoryBarrier imageLayoutBarriers[] = {
475                 {
476                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,            // VkStructureType sType;
477                     DE_NULL,                                           // const void* pNext;
478                     0u,                                                // VkAccessFlags srcAccessMask;
479                     VK_ACCESS_TRANSFER_WRITE_BIT,                      // VkAccessFlags dstAccessMask;
480                     VK_IMAGE_LAYOUT_UNDEFINED,                         // VkImageLayout oldLayout;
481                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,              // VkImageLayout newLayout;
482                     VK_QUEUE_FAMILY_IGNORED,                           // uint32_t srcQueueFamilyIndex;
483                     VK_QUEUE_FAMILY_IGNORED,                           // uint32_t destQueueFamilyIndex;
484                     caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
485                     makeColorSubresourceRange(0, caseDef.numLayers)    // VkImageSubresourceRange subresourceRange;
486                 },
487             };
488 
489             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
490                                   DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
491 
492             const VkImageSubresourceRange ranges = makeColorSubresourceRange(0, caseDef.numLayers);
493             const VkClearColorValue clearColor   = {{0.0f, 0.0f, 0.0f, 1.0f}};
494             vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage,
495                                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
496 
497             const VkImageMemoryBarrier imageClearBarriers[] = {
498                 {
499                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,            // VkStructureType sType;
500                     DE_NULL,                                           // const void* pNext;
501                     VK_ACCESS_TRANSFER_WRITE_BIT,                      // VkAccessFlags srcAccessMask;
502                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,               // VkAccessFlags dstAccessMask;
503                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,              // VkImageLayout oldLayout;
504                     VK_IMAGE_LAYOUT_GENERAL,                           // VkImageLayout newLayout;
505                     VK_QUEUE_FAMILY_IGNORED,                           // uint32_t srcQueueFamilyIndex;
506                     VK_QUEUE_FAMILY_IGNORED,                           // uint32_t destQueueFamilyIndex;
507                     caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
508                     makeColorSubresourceRange(0, caseDef.numLayers)    // VkImageSubresourceRange subresourceRange;
509                 },
510             };
511 
512             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
513                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u,
514                                   imageClearBarriers);
515         }
516 
517         // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
518         {
519             const VkDeviceSize vertexBufferOffset = 0ull;
520 
521             renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
522             {
523                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
524                 for (uint32_t layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
525                 {
526                     if (layerNdx != 0)
527                         renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
528 
529                     pipeline[layerNdx].bind(*cmdBuffer);
530                     vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx * 4u, 0u);
531                 }
532             }
533             renderPass.end(vk, *cmdBuffer);
534         }
535 
536         // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
537         if (caseDef.multisample)
538         {
539             // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
540             const VkImageMemoryBarrier imageBarriers[] = {
541                 {
542                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType sType;
543                     DE_NULL,                                        // const void* pNext;
544                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,           // VkAccessFlags srcAccessMask;
545                     VK_ACCESS_TRANSFER_READ_BIT,                    // VkAccessFlags dstAccessMask;
546                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout oldLayout;
547                     VK_IMAGE_LAYOUT_GENERAL,                        // VkImageLayout newLayout;
548                     VK_QUEUE_FAMILY_IGNORED,                        // uint32_t srcQueueFamilyIndex;
549                     VK_QUEUE_FAMILY_IGNORED,                        // uint32_t destQueueFamilyIndex;
550                     *msColorImage,                                  // VkImage image;
551                     makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
552                 },
553                 {
554                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType sType;
555                     DE_NULL,                                        // const void* pNext;
556                     (VkAccessFlags)0,                               // VkAccessFlags srcAccessMask;
557                     VK_ACCESS_TRANSFER_WRITE_BIT,                   // VkAccessFlags dstAccessMask;
558                     VK_IMAGE_LAYOUT_UNDEFINED,                      // VkImageLayout oldLayout;
559                     VK_IMAGE_LAYOUT_GENERAL,                        // VkImageLayout newLayout;
560                     VK_QUEUE_FAMILY_IGNORED,                        // uint32_t srcQueueFamilyIndex;
561                     VK_QUEUE_FAMILY_IGNORED,                        // uint32_t destQueueFamilyIndex;
562                     *colorImage,                                    // VkImage image;
563                     makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
564                 }};
565 
566             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
567                                   0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
568 
569             const VkImageResolve region = {
570                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
571                                            caseDef.numLayers), // VkImageSubresourceLayers    srcSubresource;
572                 makeOffset3D(0, 0, 0),                         // VkOffset3D                  srcOffset;
573                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
574                                            caseDef.numLayers), // VkImageSubresourceLayers    dstSubresource;
575                 makeOffset3D(0, 0, 0),                         // VkOffset3D                  dstOffset;
576                 makeExtent3D(caseDef.attachmentSize)           // VkExtent3D                  extent;
577             };
578 
579             vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL,
580                                1, &region);
581         }
582 
583         // copy colorImage to host visible colorBuffer
584         {
585             const VkImageMemoryBarrier imageBarriers[] = {{
586                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
587                 DE_NULL,                                // const void* pNext;
588                 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT :
589                                                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
590                 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
591                 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL :
592                                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
593                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                           // VkImageLayout newLayout;
594                 VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t srcQueueFamilyIndex;
595                 VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t destQueueFamilyIndex;
596                 *colorImage,                                                    // VkImage image;
597                 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
598             }};
599 
600             vk.cmdPipelineBarrier(*cmdBuffer,
601                                   caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT :
602                                                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
603                                   VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
604 
605             const VkBufferImageCopy region = {
606                 0ull, // VkDeviceSize                bufferOffset;
607                 0u,   // uint32_t                    bufferRowLength;
608                 0u,   // uint32_t                    bufferImageHeight;
609                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
610                                            caseDef.numLayers), // VkImageSubresourceLayers    imageSubresource;
611                 makeOffset3D(0, 0, 0),                         // VkOffset3D                  imageOffset;
612                 makeExtent3D(caseDef.attachmentSize),          // VkExtent3D                  imageExtent;
613             };
614 
615             vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u,
616                                     &region);
617 
618             const VkBufferMemoryBarrier bufferBarriers[] = {
619                 {
620                     VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType;
621                     DE_NULL,                                 // const void*        pNext;
622                     VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags      srcAccessMask;
623                     VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags      dstAccessMask;
624                     VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           srcQueueFamilyIndex;
625                     VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           dstQueueFamilyIndex;
626                     *colorBuffer,                            // VkBuffer           buffer;
627                     0ull,                                    // VkDeviceSize       offset;
628                     VK_WHOLE_SIZE,                           // VkDeviceSize       size;
629                 },
630             };
631 
632             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
633                                   DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
634         }
635     } // beginCommandBuffer
636 
637     endCommandBuffer(vk, *cmdBuffer);
638     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
639 
640     // Verify results
641     {
642         invalidateAlloc(vk, device, *colorBufferAlloc);
643         const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
644         const int depth                 = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
645         tcu::TextureLevel textureLevel(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
646         const tcu::PixelBufferAccess expectedImage = getExpectedData(textureLevel, caseDef);
647         const tcu::ConstPixelBufferAccess resultImage(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(),
648                                                       depth, colorBufferAlloc->getHostPtr());
649 
650         if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage,
651                                       resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
652             return tcu::TestStatus::fail("Fail");
653     }
654 
655     return tcu::TestStatus::pass("Pass");
656 }
657 
658 struct NoAttCaseDef
659 {
660     PipelineConstructionType pipelineConstructionType;
661     bool multisample;
662 };
663 
initImagePrograms(SourceCollections & programCollection,const NoAttCaseDef caseDef)664 void initImagePrograms(SourceCollections &programCollection, const NoAttCaseDef caseDef)
665 {
666     // Vertex shader
667     {
668         std::ostringstream src;
669         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
670             << "\n"
671             << "layout(location = 0) in vec4 in_position;\n"
672             << "\n"
673             << "out gl_PerVertex {\n"
674             << "    vec4 gl_Position;\n"
675             << "    float gl_PointSize;\n"
676             << "};\n"
677             << "\n"
678             << "void main(void)\n"
679             << "{\n"
680             << "    gl_Position = in_position;\n"
681             << "    gl_PointSize = 1.0f;\n"
682             << "}\n";
683 
684         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
685     }
686 
687     // Fragment shader
688     {
689         std::ostringstream src;
690         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
691             << "\n"
692             << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
693             << "\n"
694             << "void main(void)\n"
695             << "{\n";
696         if (!caseDef.multisample)
697             src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
698         else
699             src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
700         src << "}\n";
701 
702         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
703     }
704 }
705 
706 //! Make a render pass with no attachments
makeRenderPassNoAtt(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType)707 RenderPassWrapper makeRenderPassNoAtt(const DeviceInterface &vk, const VkDevice device,
708                                       const PipelineConstructionType pipelineConstructionType)
709 {
710     // Create a single subpass with no attachment references
711     vector<VkSubpassDescription> subpasses;
712 
713     const VkSubpassDescription subpassDescription = {
714         (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags flags;
715         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
716         0u,                              // uint32_t inputAttachmentCount;
717         DE_NULL,                         // const VkAttachmentReference* pInputAttachments;
718         0u,                              // uint32_t colorAttachmentCount;
719         DE_NULL,                         // const VkAttachmentReference* pColorAttachments;
720         DE_NULL,                         // const VkAttachmentReference* pResolveAttachments;
721         DE_NULL,                         // const VkAttachmentReference* pDepthStencilAttachment;
722         0u,                              // uint32_t preserveAttachmentCount;
723         DE_NULL                          // const uint32_t* pPreserveAttachments;
724     };
725     subpasses.push_back(subpassDescription);
726 
727     const VkRenderPassCreateInfo renderPassInfo = {
728         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
729         DE_NULL,                                   // const void* pNext;
730         (VkRenderPassCreateFlags)0,                // VkRenderPassCreateFlags flags;
731         0,                                         // uint32_t attachmentCount;
732         DE_NULL,                                   // const VkAttachmentDescription* pAttachments;
733         1,                                         // uint32_t subpassCount;
734         &subpasses[0],                             // const VkSubpassDescription* pSubpasses;
735         0u,                                        // uint32_t dependencyCount;
736         DE_NULL                                    // const VkSubpassDependency* pDependencies;
737     };
738 
739     return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
740 }
741 
getExpectedDataNoAtt(tcu::TextureLevel & textureLevel)742 tcu::PixelBufferAccess getExpectedDataNoAtt(tcu::TextureLevel &textureLevel)
743 {
744     const tcu::PixelBufferAccess expectedImage(textureLevel);
745     for (int z = 0; z < expectedImage.getDepth(); ++z)
746     {
747         for (int y = 0; y < expectedImage.getHeight(); ++y)
748         {
749             for (int x = 0; x < expectedImage.getWidth(); ++x)
750             {
751                 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
752             }
753         }
754     }
755     return expectedImage;
756 }
757 
genPointVertices(void)758 vector<tcu::Vec4> genPointVertices(void)
759 {
760     vector<tcu::Vec4> vectorData;
761     vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
762     vectorData.push_back(Vec4(-0.25f, 0.25f, 0, 1));
763     vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
764     vectorData.push_back(Vec4(0.25f, 0.25f, 0, 1));
765     return vectorData;
766 }
767 
768 // Tests rendering to a framebuffer without color attachments, checking that
769 // the fragment shader is run even in the absence of color output. In this case
770 // we render 4 point primitives and we make the fragment shader write to a
771 // different pixel of an image via an imageStore command. For the single-sampled
772 // configuration we use a 4x1 image to record the output and for the
773 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
774 // 4-sample multi-sampling
testNoAtt(Context & context,const NoAttCaseDef caseDef)775 tcu::TestStatus testNoAtt(Context &context, const NoAttCaseDef caseDef)
776 {
777     const InstanceInterface &vki          = context.getInstanceInterface();
778     const DeviceInterface &vk             = context.getDeviceInterface();
779     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
780     const VkDevice device                 = context.getDevice();
781     const VkQueue queue                   = context.getUniversalQueue();
782     const uint32_t queueFamilyIndex       = context.getUniversalQueueFamilyIndex();
783     Allocator &allocator                  = context.getDefaultAllocator();
784     const IVec3 renderSize(32, 32, 1);
785 
786     Move<VkBuffer> vertexBuffer;
787     MovePtr<Allocation> vertexBufferAlloc;
788 
789     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
790     const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
791 
792     // Create image where we will record the writes. For single-sampled cases this is a 4x1 image
793     // and for multi-sampled cases this is a 4x<num_samples> image.
794     const uint8_t numSamples           = caseDef.multisample ? 4 : 1;
795     const uint8_t imageWidth           = 4;
796     const uint8_t imageHeight          = numSamples;
797     const uint8_t imageDepth           = 1;
798     const uint8_t imageLayers          = 1;
799     const IVec3 imageDim               = IVec3(imageWidth, imageHeight, imageDepth);
800     const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
801     const Move<VkImage> image = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT,
802                                           imageDim, imageLayers, imageUsage, false);
803     const VkImageSubresourceRange imageSubresourceRange = makeColorSubresourceRange(0u, imageLayers);
804     const MovePtr<Allocation> imageAlloc = bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
805     const Move<VkImageView> imageView =
806         makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
807 
808     // Create a buffer where we will copy the image for verification
809     const VkDeviceSize colorBufferSize =
810         imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
811     const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
812     const UniquePtr<Allocation> colorBufferAlloc(
813         bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
814 
815     // Create pipeline descriptor set for the image
816     const Move<VkDescriptorSetLayout> descriptorSetLayout =
817         DescriptorSetLayoutBuilder()
818             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
819             .build(vk, device);
820 
821     const Move<VkDescriptorPool> descriptorPool =
822         DescriptorPoolBuilder()
823             .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
824             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
825 
826     const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
827     const VkDescriptorImageInfo descriptorImageInfo =
828         makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
829     DescriptorSetUpdateBuilder()
830         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
831                      VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
832         .update(vk, device);
833 
834     const PipelineLayoutWrapper pipelineLayout(caseDef.pipelineConstructionType, vk, device, *descriptorSetLayout);
835     GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
836                                      caseDef.pipelineConstructionType);
837     RenderPassWrapper renderPass = makeRenderPassNoAtt(vk, device, caseDef.pipelineConstructionType);
838 
839     const Unique<VkCommandPool> cmdPool(
840         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
841     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
842 
843     // create vertexBuffer
844     {
845         const vector<tcu::Vec4> vertices    = genPointVertices();
846         const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
847 
848         vertexBuffer      = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
849         vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
850         deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
851         flushAlloc(vk, device, *vertexBufferAlloc);
852     }
853 
854     // Create pipeline
855     preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, renderSize,
856                            VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, caseDef.multisample);
857     renderPass.createFramebuffer(vk, device, 0, DE_NULL, renderSize.x(), renderSize.y());
858 
859     // Record command buffer
860     beginCommandBuffer(vk, *cmdBuffer);
861     {
862         // shader image layout transition undefined -> general
863         {
864             const VkImageMemoryBarrier setImageLayoutBarrier =
865                 makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
866                                        VK_IMAGE_LAYOUT_GENERAL, *image, imageSubresourceRange);
867 
868             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
869                                   0, 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
870         }
871 
872         // Render pass
873         {
874             const VkDeviceSize vertexBufferOffset = 0ull;
875 
876             renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()));
877 
878             pipeline.bind(*cmdBuffer);
879             vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
880             vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
881                                      &descriptorSet.get(), 0u, DE_NULL);
882             vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
883 
884             renderPass.end(vk, *cmdBuffer);
885         }
886 
887         // copy image to host visible colorBuffer
888         {
889             const VkImageMemoryBarrier imageBarriers[] = {{
890                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
891                 DE_NULL,                                // const void* pNext;
892                 VK_ACCESS_SHADER_WRITE_BIT,             // VkAccessFlags srcAccessMask;
893                 VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags dstAccessMask;
894                 VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout oldLayout;
895                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout newLayout;
896                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
897                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t destQueueFamilyIndex;
898                 *image,                                 // VkImage image;
899                 makeColorSubresourceRange(0, 1)         // VkImageSubresourceRange subresourceRange;
900             }};
901 
902             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
903                                   0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
904 
905             const VkBufferImageCopy region = {
906                 0ull, // VkDeviceSize                bufferOffset;
907                 0u,   // uint32_t                    bufferRowLength;
908                 0u,   // uint32_t                    bufferImageHeight;
909                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
910                                            1), // VkImageSubresourceLayers    imageSubresource;
911                 makeOffset3D(0, 0, 0),         // VkOffset3D                  imageOffset;
912                 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)), // VkExtent3D                  imageExtent;
913             };
914 
915             vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u,
916                                     &region);
917 
918             const VkBufferMemoryBarrier bufferBarriers[] = {
919                 {
920                     VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType;
921                     DE_NULL,                                 // const void*        pNext;
922                     VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags      srcAccessMask;
923                     VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags      dstAccessMask;
924                     VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           srcQueueFamilyIndex;
925                     VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           dstQueueFamilyIndex;
926                     *colorBuffer,                            // VkBuffer           buffer;
927                     0ull,                                    // VkDeviceSize       offset;
928                     VK_WHOLE_SIZE,                           // VkDeviceSize       size;
929                 },
930             };
931 
932             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
933                                   DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
934         }
935     } // beginCommandBuffer
936 
937     endCommandBuffer(vk, *cmdBuffer);
938     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
939 
940     // Verify results
941     {
942         invalidateAlloc(vk, device, *colorBufferAlloc);
943         const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
944         tcu::TextureLevel textureLevel(format, imageWidth, imageHeight, imageDepth);
945         const tcu::PixelBufferAccess expectedImage = getExpectedDataNoAtt(textureLevel);
946         const tcu::ConstPixelBufferAccess resultImage(format, imageWidth, imageHeight, imageDepth,
947                                                       colorBufferAlloc->getHostPtr());
948 
949         if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage,
950                                       resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
951             return tcu::TestStatus::fail("Fail");
952     }
953 
954     return tcu::TestStatus::pass("Pass");
955 }
956 
957 //! Make a render pass with three color attachments
makeRenderPassMultiAttachments(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat,uint32_t numAttachments,const bool multisample)958 RenderPassWrapper makeRenderPassMultiAttachments(const DeviceInterface &vk, const VkDevice device,
959                                                  const PipelineConstructionType pipelineConstructionType,
960                                                  const VkFormat colorFormat, uint32_t numAttachments,
961                                                  const bool multisample)
962 {
963     vector<VkAttachmentDescription> attachmentDescriptions(numAttachments);
964     vector<VkAttachmentReference> colorAttachmentReferences(numAttachments);
965 
966     for (uint32_t i = 0; i < numAttachments; i++)
967     {
968         VkAttachmentDescription colorAttachmentDescription = {
969             (VkAttachmentDescriptionFlags)0,                              // VkAttachmentDescriptionFla flags;
970             colorFormat,                                                  // VkFormat format;
971             !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
972             VK_ATTACHMENT_LOAD_OP_LOAD,                                   // VkAttachmentLoadOp loadOp;
973             VK_ATTACHMENT_STORE_OP_STORE,                                 // VkAttachmentStoreOp storeOp;
974             VK_ATTACHMENT_LOAD_OP_DONT_CARE,                              // VkAttachmentLoadOp stencilLoadOp;
975             VK_ATTACHMENT_STORE_OP_DONT_CARE,                             // VkAttachmentStoreOp stencilStoreOp;
976             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                     // VkImageLayout initialLayout;
977             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                     // VkImageLayout finalLayout;
978         };
979         attachmentDescriptions[i] = colorAttachmentDescription;
980 
981         const VkAttachmentReference attachmentRef = {
982             i,                                       // uint32_t attachment;
983             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
984         };
985         colorAttachmentReferences[i] = attachmentRef;
986     }
987 
988     const VkSubpassDescription subpassDescription = {
989         (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags flags;
990         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
991         0u,                              // uint32_t inputAttachmentCount;
992         DE_NULL,                         // const VkAttachmentReference* pInputAttachments;
993         numAttachments,                  // uint32_t colorAttachmentCount;
994         &colorAttachmentReferences[0],   // const VkAttachmentReference* pColorAttachments;
995         DE_NULL,                         // const VkAttachmentReference* pResolveAttachments;
996         DE_NULL,                         // const VkAttachmentReference* pDepthStencilAttachment;
997         0u,                              // uint32_t preserveAttachmentCount;
998         DE_NULL                          // const uint32_t* pPreserveAttachments;
999     };
1000 
1001     const VkRenderPassCreateInfo renderPassInfo = {
1002         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1003         DE_NULL,                                   // const void* pNext;
1004         (VkRenderPassCreateFlags)0,                // VkRenderPassCreateFlags flags;
1005         numAttachments,                            // uint32_t attachmentCount;
1006         &attachmentDescriptions[0],                // const VkAttachmentDescription* pAttachments;
1007         1u,                                        // uint32_t subpassCount;
1008         &subpassDescription,                       // const VkSubpassDescription* pSubpasses;
1009         0u,                                        // uint32_t dependencyCount;
1010         DE_NULL                                    // const VkSubpassDependency* pDependencies;
1011     };
1012 
1013     return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
1014 }
1015 
1016 // Tests framebuffer with attachments of different sizes
testMultiAttachments(Context & context,const CaseDef caseDef)1017 tcu::TestStatus testMultiAttachments(Context &context, const CaseDef caseDef)
1018 {
1019     const InstanceInterface &vki          = context.getInstanceInterface();
1020     const DeviceInterface &vk             = context.getDeviceInterface();
1021     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1022     const VkDevice device                 = context.getDevice();
1023     const VkQueue queue                   = context.getUniversalQueue();
1024     const uint32_t queueFamilyIndex       = context.getUniversalQueueFamilyIndex();
1025     Allocator &allocator                  = context.getDefaultAllocator();
1026     const uint32_t numRenderTargets       = 3;
1027     const bool differentSizeTest          = caseDef.multiAttachmentsTestType == MULTI_ATTACHMENTS_DIFFERENT_SIZES;
1028     const bool notExportTest              = caseDef.multiAttachmentsTestType == MULTI_ATTACHMENTS_NOT_EXPORTED;
1029 
1030     // Color images for rendering in single-sample tests or resolve targets for multi-sample tests
1031     Move<VkImage> colorImages[numRenderTargets];
1032     MovePtr<Allocation> colorImageAllocs[numRenderTargets];
1033 
1034     // For multisampled tests, these are the rendering targets
1035     Move<VkImage> msColorImages[numRenderTargets];
1036     MovePtr<Allocation> msColorImageAllocs[numRenderTargets];
1037 
1038     Move<VkBuffer> colorBuffers[numRenderTargets];
1039     MovePtr<Allocation> colorBufferAllocs[numRenderTargets];
1040 
1041     // Vary attachment sizes by adding an offset to the base size.
1042     const IVec3 attachmentSizes[] = {caseDef.attachmentSize,
1043                                      caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0),
1044                                      caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0)};
1045 
1046     // Use unique clear color for each render target to verify no leaking happens between render target clears.
1047     const VkClearColorValue clearColors[] = {
1048         {{1.0f, 0.0f, 0.0f, 1.0f}}, {{0.0f, 1.0f, 0.0f, 1.0f}}, {{0.0f, 0.0f, 1.0f, 1.0f}}};
1049 
1050     Move<VkBuffer> vertexBuffer;
1051     MovePtr<Allocation> vertexBufferAlloc;
1052 
1053     vector<SharedPtrVkImageView> colorAttachments;
1054     vector<VkImage> images;
1055     vector<VkImageView> attachmentHandles;
1056 
1057     const PipelineLayoutWrapper pipelineLayout(caseDef.pipelineConstructionType, vk, device);
1058     GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1059                                      caseDef.pipelineConstructionType);
1060     RenderPassWrapper renderPass(makeRenderPassMultiAttachments(vk, device, caseDef.pipelineConstructionType,
1061                                                                 COLOR_FORMAT, numRenderTargets, caseDef.multisample));
1062 
1063     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
1064     const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
1065 
1066     const Unique<VkCommandPool> cmdPool(
1067         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1068     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1069 
1070     const VkImageViewType imageViewType =
1071         caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ?
1072             VK_IMAGE_VIEW_TYPE_2D :
1073             caseDef.imageType;
1074 
1075     const VkImageSubresourceRange range = makeColorSubresourceRange(0, 1);
1076 
1077     // create color buffers
1078     for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1079     {
1080         const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1081 
1082         // Host memory buffer where we will copy the rendered image for verification
1083         const uint32_t att_size_x = attachmentSize.x();
1084         const uint32_t att_size_y = attachmentSize.y();
1085         const uint32_t att_size_z = attachmentSize.z();
1086         const VkDeviceSize colorBufferSize =
1087             att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1088         colorBuffers[renderTargetIdx] = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1089         colorBufferAllocs[renderTargetIdx] =
1090             bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible);
1091     }
1092 
1093     // create vertexBuffer
1094     {
1095         const vector<tcu::Vec4> vertices    = genFullQuadVertices(1);
1096         const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1097 
1098         vertexBuffer      = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1099         vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1100 
1101         deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1102         flushAlloc(vk, device, *vertexBufferAlloc);
1103     }
1104 
1105     // create colorImages (and msColorImages) using the configured attachmentsize
1106     for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1107     {
1108         const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1109 
1110         const VkImageUsageFlags colorImageUsage =
1111             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1112         colorImages[renderTargetIdx] = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType),
1113                                                  COLOR_FORMAT, attachmentSize, 1, colorImageUsage, false);
1114         colorImageAllocs[renderTargetIdx] =
1115             bindImage(vk, device, allocator, *colorImages[renderTargetIdx], MemoryRequirement::Any);
1116 
1117         if (caseDef.multisample)
1118         {
1119             const VkImageUsageFlags msImageUsage =
1120                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1121 
1122             msColorImages[renderTargetIdx] =
1123                 makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
1124                           attachmentSize, 1, msImageUsage, true);
1125             msColorImageAllocs[renderTargetIdx] =
1126                 bindImage(vk, device, allocator, *msColorImages[renderTargetIdx], MemoryRequirement::Any);
1127         }
1128     }
1129 
1130     // create attachmentHandles. We use the renderSize for viewport and scissor
1131     for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1132     {
1133         colorAttachments.push_back(makeSharedPtr(makeImageView(
1134             vk, device, !caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx],
1135             imageViewType, COLOR_FORMAT, range)));
1136         images.push_back(!caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx]);
1137         attachmentHandles.push_back(**colorAttachments.back());
1138     }
1139 
1140     preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, caseDef.renderSize,
1141                            VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, numRenderTargets, caseDef.multisample);
1142 
1143     // create framebuffer
1144     renderPass.createFramebuffer(vk, device, numRenderTargets, &images[0], &attachmentHandles[0],
1145                                  static_cast<uint32_t>(caseDef.renderSize.x()),
1146                                  static_cast<uint32_t>(caseDef.renderSize.y()));
1147 
1148     // record command buffer
1149     beginCommandBuffer(vk, *cmdBuffer);
1150 
1151     // Clear image attachments
1152     for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1153     {
1154         {
1155             const VkImageMemoryBarrier imageLayoutBarriers[] = {
1156                 {
1157                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1158                     DE_NULL,                                // const void* pNext;
1159                     0u,                                     // VkAccessFlags srcAccessMask;
1160                     VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
1161                     VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
1162                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
1163                     VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
1164                     VK_QUEUE_FAMILY_IGNORED,                // uint32_t destQueueFamilyIndex;
1165                     caseDef.multisample ? *msColorImages[renderTargetIdx] :
1166                                           *colorImages[renderTargetIdx], // VkImage image;
1167                     range                                                // VkImageSubresourceRange subresourceRange;
1168                 },
1169             };
1170 
1171             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1172                                   DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
1173 
1174             vk.cmdClearColorImage(*cmdBuffer,
1175                                   caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx],
1176                                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColors[renderTargetIdx], 1u, &range);
1177 
1178             const VkImageMemoryBarrier imageClearBarriers[] = {
1179                 {
1180                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType sType;
1181                     DE_NULL,                                  // const void* pNext;
1182                     VK_ACCESS_TRANSFER_WRITE_BIT,             // VkAccessFlags srcAccessMask;
1183                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,      // VkAccessFlags dstAccessMask;
1184                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,     // VkImageLayout oldLayout;
1185                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1186                     VK_QUEUE_FAMILY_IGNORED,                  // uint32_t srcQueueFamilyIndex;
1187                     VK_QUEUE_FAMILY_IGNORED,                  // uint32_t destQueueFamilyIndex;
1188                     caseDef.multisample ? *msColorImages[renderTargetIdx] :
1189                                           *colorImages[renderTargetIdx], // VkImage image;
1190                     range                                                // VkImageSubresourceRange subresourceRange;
1191                 },
1192             };
1193 
1194             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1195                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u,
1196                                   imageClearBarriers);
1197         }
1198     }
1199 
1200     // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1201     {
1202         const VkDeviceSize vertexBufferOffset = 0ull;
1203 
1204         renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
1205         {
1206             vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1207             pipeline.bind(*cmdBuffer);
1208             vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1209         }
1210         renderPass.end(vk, *cmdBuffer);
1211     }
1212 
1213     // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
1214     if (caseDef.multisample)
1215     {
1216         for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1217         {
1218             const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1219 
1220             // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
1221             const VkImageMemoryBarrier imageBarriers[] = {
1222                 {
1223                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType sType;
1224                     DE_NULL,                                  // const void* pNext;
1225                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // VkAccessFlags srcAccessMask;
1226                     VK_ACCESS_TRANSFER_READ_BIT,              // VkAccessFlags dstAccessMask;
1227                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1228                     VK_IMAGE_LAYOUT_GENERAL,                  // VkImageLayout newLayout;
1229                     VK_QUEUE_FAMILY_IGNORED,                  // uint32_t srcQueueFamilyIndex;
1230                     VK_QUEUE_FAMILY_IGNORED,                  // uint32_t destQueueFamilyIndex;
1231                     *msColorImages[renderTargetIdx],          // VkImage image;
1232                     range                                     // VkImageSubresourceRange subresourceRange;
1233                 },
1234                 {
1235                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1236                     DE_NULL,                                // const void* pNext;
1237                     (VkAccessFlags)0,                       // VkAccessFlags srcAccessMask;
1238                     VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
1239                     VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
1240                     VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
1241                     VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
1242                     VK_QUEUE_FAMILY_IGNORED,                // uint32_t destQueueFamilyIndex;
1243                     *colorImages[renderTargetIdx],          // VkImage image;
1244                     range                                   // VkImageSubresourceRange subresourceRange;
1245                 }};
1246 
1247             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1248                                   0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1249 
1250             const VkImageResolve region = {
1251                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
1252                                            1), // VkImageSubresourceLayers    srcSubresource;
1253                 makeOffset3D(0, 0, 0),         // VkOffset3D                  srcOffset;
1254                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
1255                                            1), // VkImageSubresourceLayers    dstSubresource;
1256                 makeOffset3D(0, 0, 0),         // VkOffset3D                  dstOffset;
1257                 makeExtent3D(attachmentSize)   // VkExtent3D                  extent;
1258             };
1259 
1260             vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL,
1261                                *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, &region);
1262         }
1263     }
1264 
1265     for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1266     {
1267         const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1268 
1269         // copy colorImage to host visible colorBuffer
1270         const VkImageMemoryBarrier imageBarrier = {
1271             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1272             DE_NULL,                                // const void* pNext;
1273             (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT :
1274                                                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1275             VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1276             caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL :
1277                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1278             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                           // VkImageLayout newLayout;
1279             VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t srcQueueFamilyIndex;
1280             VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t destQueueFamilyIndex;
1281             *colorImages[renderTargetIdx],                                  // VkImage image;
1282             range                                                           // VkImageSubresourceRange subresourceRange;
1283         };
1284 
1285         vk.cmdPipelineBarrier(*cmdBuffer,
1286                               caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT :
1287                                                     VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1288                               VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1289 
1290         const VkBufferImageCopy region = {
1291             0ull, // VkDeviceSize                bufferOffset;
1292             0u,   // uint32_t                    bufferRowLength;
1293             0u,   // uint32_t                    bufferImageHeight;
1294             makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
1295                                        1u), // VkImageSubresourceLayers    imageSubresource;
1296             makeOffset3D(0, 0, 0),          // VkOffset3D                  imageOffset;
1297             makeExtent3D(attachmentSize),   // VkExtent3D                  imageExtent;
1298         };
1299 
1300         vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1301                                 *colorBuffers[renderTargetIdx], 1u, &region);
1302 
1303         const VkBufferMemoryBarrier bufferBarrier = {
1304             VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType;
1305             DE_NULL,                                 // const void*        pNext;
1306             VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags      srcAccessMask;
1307             VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags      dstAccessMask;
1308             VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           srcQueueFamilyIndex;
1309             VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           dstQueueFamilyIndex;
1310             *colorBuffers[renderTargetIdx],          // VkBuffer           buffer;
1311             0ull,                                    // VkDeviceSize       offset;
1312             VK_WHOLE_SIZE,                           // VkDeviceSize       size;
1313         };
1314 
1315         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
1316                               1u, &bufferBarrier, 0u, DE_NULL);
1317     }
1318 
1319     endCommandBuffer(vk, *cmdBuffer);
1320     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1321 
1322     // Verify results
1323     const uint32_t skippedRenderTarget = notExportTest ? 1 : numRenderTargets;
1324     const tcu::Vec4 expectedColors[]   = {tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f), tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f),
1325                                           tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f)};
1326 
1327     for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1328     {
1329         const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
1330         const IVec3 size                = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1331         tcu::TextureLevel textureLevel(format, size.x(), size.y(), size.z());
1332         const tcu::PixelBufferAccess expectedImage(textureLevel);
1333 
1334         // Doesn't need to check the output of unused MRT, that may be undefined.
1335         if (notExportTest && (renderTargetIdx == skippedRenderTarget))
1336             continue;
1337 
1338         invalidateAlloc(vk, device, *colorBufferAllocs[renderTargetIdx]);
1339 
1340         for (int z = 0; z < expectedImage.getDepth(); ++z)
1341         {
1342             for (int y = 0; y < expectedImage.getHeight(); ++y)
1343             {
1344                 for (int x = 0; x < expectedImage.getWidth(); ++x)
1345                 {
1346                     if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1347                         expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z);
1348                     else
1349                         expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z);
1350                 }
1351             }
1352         }
1353         const tcu::ConstPixelBufferAccess resultImage(format, size.x(), size.y(), size.z(),
1354                                                       colorBufferAllocs[renderTargetIdx]->getHostPtr());
1355 
1356         if (!tcu::intThresholdCompare(
1357                 context.getTestContext().getLog(),
1358                 (std::string("Image Comparison of render target ") + de::toString(renderTargetIdx)).c_str(), "",
1359                 expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1360             return tcu::TestStatus::fail("Fail");
1361     }
1362 
1363     return tcu::TestStatus::pass("Pass");
1364 }
1365 
initInputResolveSameAttachmentPrograms(SourceCollections & programCollection,const CaseDef caseDef)1366 void initInputResolveSameAttachmentPrograms(SourceCollections &programCollection, const CaseDef caseDef)
1367 {
1368     DE_UNREF(caseDef);
1369 
1370     // Vertex shader
1371     {
1372         std::ostringstream src;
1373         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1374             << "\n"
1375             << "layout(location = 0) in vec4 in_position;\n"
1376             << "\n"
1377             << "out gl_PerVertex {\n"
1378             << "    vec4 gl_Position;\n"
1379             << "};\n"
1380             << "\n"
1381             << "void main(void)\n"
1382             << "{\n"
1383             << "    gl_Position = in_position;\n"
1384             << "}\n";
1385 
1386         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1387     }
1388 
1389     // Fragment shader
1390     {
1391         std::ostringstream src;
1392         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1393             << "\n"
1394             << "layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;\n"
1395             << "layout(location = 0) out vec4 o_color0;\n"
1396             << "\n"
1397             << "void main(void)\n"
1398             << "{\n"
1399             << "    vec4 in_color = subpassLoad(inputColor);\n"
1400             << "    o_color0 = vec4(1.0, in_color.y, 0.25, 1.0);\n"
1401             << "}\n";
1402 
1403         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1404     }
1405 }
1406 
makeRenderPassInputResolveSameAttachment(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat)1407 RenderPassWrapper makeRenderPassInputResolveSameAttachment(const DeviceInterface &vk, const VkDevice device,
1408                                                            const PipelineConstructionType pipelineConstructionType,
1409                                                            const VkFormat colorFormat)
1410 {
1411     std::vector<VkAttachmentDescription> attachmentDescriptions;
1412     VkAttachmentDescription colorAttachmentDescription = {
1413         (VkAttachmentDescriptionFlags)0,          // VkAttachmentDescriptionFla flags;
1414         colorFormat,                              // VkFormat format;
1415         VK_SAMPLE_COUNT_4_BIT,                    // VkSampleCountFlagBits samples;
1416         VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp loadOp;
1417         VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
1418         VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
1419         VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
1420         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
1421         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1422     };
1423 
1424     attachmentDescriptions.push_back(colorAttachmentDescription);
1425 
1426     VkAttachmentDescription inputAttachmentDescription = {
1427         (VkAttachmentDescriptionFlags)0,  // VkAttachmentDescriptionFla flags;
1428         colorFormat,                      // VkFormat format;
1429         VK_SAMPLE_COUNT_1_BIT,            // VkSampleCountFlagBits samples;
1430         VK_ATTACHMENT_LOAD_OP_LOAD,       // VkAttachmentLoadOp loadOp;
1431         VK_ATTACHMENT_STORE_OP_STORE,     // VkAttachmentStoreOp storeOp;
1432         VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // VkAttachmentLoadOp stencilLoadOp;
1433         VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1434         VK_IMAGE_LAYOUT_GENERAL,          // VkImageLayout initialLayout;
1435         VK_IMAGE_LAYOUT_GENERAL,          // VkImageLayout finalLayout;
1436     };
1437 
1438     attachmentDescriptions.push_back(inputAttachmentDescription);
1439 
1440     const VkAttachmentReference colorAttachmentRef = {
1441         0u,                                      // uint32_t attachment;
1442         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
1443     };
1444 
1445     const VkAttachmentReference inputAttachmentRef = {
1446         1u,                     // uint32_t attachment;
1447         VK_IMAGE_LAYOUT_GENERAL // VkImageLayout layout;
1448     };
1449 
1450     const VkSubpassDescription subpassDescription = {
1451         (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags flags;
1452         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1453         1u,                              // uint32_t inputAttachmentCount;
1454         &inputAttachmentRef,             // const VkAttachmentReference* pInputAttachments;
1455         1u,                              // uint32_t colorAttachmentCount;
1456         &colorAttachmentRef,             // const VkAttachmentReference* pColorAttachments;
1457         &inputAttachmentRef,             // const VkAttachmentReference* pResolveAttachments;
1458         DE_NULL,                         // const VkAttachmentReference* pDepthStencilAttachment;
1459         0u,                              // uint32_t preserveAttachmentCount;
1460         DE_NULL                          // const uint32_t* pPreserveAttachments;
1461     };
1462 
1463     const VkRenderPassCreateInfo renderPassInfo = {
1464         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1465         DE_NULL,                                   // const void* pNext;
1466         (VkRenderPassCreateFlags)0,                // VkRenderPassCreateFlags flags;
1467         (uint32_t)attachmentDescriptions.size(),   // uint32_t attachmentCount;
1468         &attachmentDescriptions[0],                // const VkAttachmentDescription* pAttachments;
1469         1u,                                        // uint32_t subpassCount;
1470         &subpassDescription,                       // const VkSubpassDescription* pSubpasses;
1471         0u,                                        // uint32_t dependencyCount;
1472         DE_NULL                                    // const VkSubpassDependency* pDependencies;
1473     };
1474 
1475     return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
1476 }
1477 
testInputResolveSameAttachment(Context & context,const CaseDef caseDef)1478 tcu::TestStatus testInputResolveSameAttachment(Context &context, const CaseDef caseDef)
1479 {
1480     const InstanceInterface &vki          = context.getInstanceInterface();
1481     const DeviceInterface &vk             = context.getDeviceInterface();
1482     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1483     const VkDevice device                 = context.getDevice();
1484     const VkQueue queue                   = context.getUniversalQueue();
1485     const uint32_t queueFamilyIndex       = context.getUniversalQueueFamilyIndex();
1486     Allocator &allocator                  = context.getDefaultAllocator();
1487 
1488     // Use unique clear color for each render target to verify no leaking happens between render target clears.
1489     const VkClearColorValue clearColor[] = {{{1.0f, 0.0f, 0.0f, 1.0f}}, {{0.0f, 0.5f, 0.0f, 1.0f}}};
1490 
1491     Move<VkBuffer> vertexBuffer;
1492     MovePtr<Allocation> vertexBufferAlloc;
1493 
1494     vector<SharedPtrVkImageView> colorAttachments;
1495     vector<VkImage> images;
1496     vector<VkImageView> attachmentHandles;
1497 
1498     // Create pipeline descriptor set for the image
1499     const Move<VkDescriptorSetLayout> descriptorSetLayout =
1500         DescriptorSetLayoutBuilder()
1501             .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
1502             .build(vk, device);
1503 
1504     const Move<VkDescriptorPool> descriptorPool =
1505         DescriptorPoolBuilder()
1506             .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1)
1507             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1508 
1509     const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1510 
1511     const PipelineLayoutWrapper pipelineLayout(caseDef.pipelineConstructionType, vk, device, *descriptorSetLayout);
1512     GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1513                                      caseDef.pipelineConstructionType);
1514     RenderPassWrapper renderPass(
1515         makeRenderPassInputResolveSameAttachment(vk, device, caseDef.pipelineConstructionType, COLOR_FORMAT));
1516 
1517     const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
1518     const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
1519 
1520     const Unique<VkCommandPool> cmdPool(
1521         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1522     const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1523 
1524     const VkImageViewType imageViewType = caseDef.imageType;
1525 
1526     const VkImageSubresourceRange range = makeColorSubresourceRange(0, 1);
1527 
1528     // create color buffer
1529     const IVec3 attachmentSize = caseDef.attachmentSize;
1530     const VkDeviceSize colorBufferSize =
1531         attachmentSize.x() * attachmentSize.y() * attachmentSize.z() * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1532     auto colorBuffer = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1533     MovePtr<Allocation> colorBufferAlloc =
1534         bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible);
1535 
1536     // create vertexBuffer
1537     {
1538         const vector<tcu::Vec4> vertices    = genFullQuadVertices(1);
1539         const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1540 
1541         vertexBuffer      = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1542         vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1543 
1544         deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1545         flushAlloc(vk, device, *vertexBufferAlloc);
1546     }
1547 
1548     // create colorImages (and msColorImages)
1549     const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1550                                               VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1551     Move<VkImage> colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType),
1552                                          COLOR_FORMAT, attachmentSize, 1, colorImageUsage, false);
1553     MovePtr<Allocation> colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1554 
1555     const VkImageUsageFlags msImageUsage =
1556         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1557     Move<VkImage> msColorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType),
1558                                            COLOR_FORMAT, attachmentSize, 1, msImageUsage, true);
1559     MovePtr<Allocation> msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
1560 
1561     // create attachmentHandles. We use the renderSize for viewport and scissor
1562     colorAttachments.push_back(
1563         makeSharedPtr(makeImageView(vk, device, *msColorImage, imageViewType, COLOR_FORMAT, range)));
1564     images.push_back(*msColorImage);
1565     attachmentHandles.push_back(**colorAttachments.back());
1566 
1567     colorAttachments.push_back(
1568         makeSharedPtr(makeImageView(vk, device, *colorImage, imageViewType, COLOR_FORMAT, range)));
1569     images.push_back(*colorImage);
1570     attachmentHandles.push_back(**colorAttachments.back());
1571 
1572     const VkDescriptorImageInfo descriptorImageInfo =
1573         makeDescriptorImageInfo(DE_NULL, attachmentHandles[1], VK_IMAGE_LAYOUT_GENERAL);
1574     DescriptorSetUpdateBuilder()
1575         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1576                      VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorImageInfo)
1577         .update(vk, device);
1578 
1579     preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, caseDef.renderSize,
1580                            VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 1u, true);
1581 
1582     // create framebuffer
1583     renderPass.createFramebuffer(vk, device, 2u, &images[0], &attachmentHandles[0],
1584                                  static_cast<uint32_t>(caseDef.renderSize.x()),
1585                                  static_cast<uint32_t>(caseDef.renderSize.y()));
1586 
1587     // record command buffer
1588     beginCommandBuffer(vk, *cmdBuffer);
1589 
1590     // Clear image attachments
1591     {
1592         const VkImageMemoryBarrier imageLayoutBarriers[] = {
1593             {
1594                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1595                 DE_NULL,                                // const void* pNext;
1596                 0u,                                     // VkAccessFlags srcAccessMask;
1597                 VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
1598                 VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
1599                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
1600                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
1601                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t destQueueFamilyIndex;
1602                 *msColorImage,                          // VkImage image;
1603                 range                                   // VkImageSubresourceRange subresourceRange;
1604             },
1605             {
1606                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1607                 DE_NULL,                                // const void* pNext;
1608                 (VkAccessFlags)0,                       // VkAccessFlags srcAccessMask;
1609                 VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
1610                 VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
1611                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
1612                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
1613                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t destQueueFamilyIndex;
1614                 *colorImage,                            // VkImage image;
1615                 range                                   // VkImageSubresourceRange subresourceRange;
1616             }};
1617 
1618         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1619                               DE_NULL, 0u, DE_NULL, 2u, imageLayoutBarriers);
1620 
1621         vk.cmdClearColorImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor[0], 1u,
1622                               &range);
1623         vk.cmdClearColorImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor[1], 1u,
1624                               &range);
1625 
1626         const VkImageMemoryBarrier imageClearBarriers[] = {
1627             {
1628                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType sType;
1629                 DE_NULL,                                  // const void* pNext;
1630                 VK_ACCESS_TRANSFER_WRITE_BIT,             // VkAccessFlags srcAccessMask;
1631                 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,      // VkAccessFlags dstAccessMask;
1632                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,     // VkImageLayout oldLayout;
1633                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1634                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t srcQueueFamilyIndex;
1635                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t destQueueFamilyIndex;
1636                 *msColorImage,                            // VkImage image;
1637                 range                                     // VkImageSubresourceRange subresourceRange;
1638             },
1639             {
1640                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1641                 DE_NULL,                                // const void* pNext;
1642                 VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
1643                 VK_ACCESS_SHADER_READ_BIT,              // VkAccessFlags dstAccessMask;
1644                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout oldLayout;
1645                 VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
1646                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
1647                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t destQueueFamilyIndex;
1648                 *colorImage,                            // VkImage image;
1649                 range                                   // VkImageSubresourceRange subresourceRange;
1650             }};
1651 
1652         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1653                               0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageClearBarriers[0]);
1654 
1655         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u,
1656                               DE_NULL, 0u, DE_NULL, 1u, &imageClearBarriers[1]);
1657     }
1658 
1659     // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1660     {
1661         const VkDeviceSize vertexBufferOffset = 0ull;
1662 
1663         renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
1664         {
1665             vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1666             pipeline.bind(*cmdBuffer);
1667             vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
1668                                      &descriptorSet.get(), 0u, DE_NULL);
1669             vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1670         }
1671         renderPass.end(vk, *cmdBuffer);
1672     }
1673 
1674     // copy colorImage to host visible colorBuffer
1675     const VkImageMemoryBarrier imageBarrier = {
1676         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1677         DE_NULL,                                // const void* pNext;
1678         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,   // VkAccessFlags srcAccessMask;
1679         VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags dstAccessMask;
1680         VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout oldLayout;
1681         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout newLayout;
1682         VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
1683         VK_QUEUE_FAMILY_IGNORED,                // uint32_t destQueueFamilyIndex;
1684         *colorImage,                            // VkImage image;
1685         range                                   // VkImageSubresourceRange subresourceRange;
1686     };
1687 
1688     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1689                           0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1690 
1691     const VkBufferImageCopy regionBufferImageCopy = {
1692         0ull, // VkDeviceSize                bufferOffset;
1693         0u,   // uint32_t                    bufferRowLength;
1694         0u,   // uint32_t                    bufferImageHeight;
1695         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
1696                                    1u), // VkImageSubresourceLayers    imageSubresource;
1697         makeOffset3D(0, 0, 0),          // VkOffset3D                  imageOffset;
1698         makeExtent3D(attachmentSize),   // VkExtent3D                  imageExtent;
1699     };
1700 
1701     vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u,
1702                             &regionBufferImageCopy);
1703 
1704     const VkBufferMemoryBarrier bufferBarrier = {
1705         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType;
1706         DE_NULL,                                 // const void*        pNext;
1707         VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags      srcAccessMask;
1708         VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags      dstAccessMask;
1709         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           srcQueueFamilyIndex;
1710         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t           dstQueueFamilyIndex;
1711         *colorBuffer,                            // VkBuffer           buffer;
1712         0ull,                                    // VkDeviceSize       offset;
1713         VK_WHOLE_SIZE,                           // VkDeviceSize       size;
1714     };
1715 
1716     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u,
1717                           &bufferBarrier, 0u, DE_NULL);
1718 
1719     endCommandBuffer(vk, *cmdBuffer);
1720     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1721 
1722     // Verify results
1723     const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
1724     tcu::TextureLevel textureLevel(format, attachmentSize.x(), attachmentSize.y(), attachmentSize.z());
1725     const tcu::PixelBufferAccess expectedImage(textureLevel);
1726 
1727     const tcu::Vec4 expectedColor = tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f);
1728 
1729     invalidateAlloc(vk, device, *colorBufferAlloc);
1730 
1731     for (int z = 0; z < expectedImage.getDepth(); ++z)
1732     {
1733         for (int y = 0; y < expectedImage.getHeight(); ++y)
1734         {
1735             for (int x = 0; x < expectedImage.getWidth(); ++x)
1736             {
1737                 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1738                     expectedImage.setPixel(expectedColor, x, y, z);
1739                 else
1740                     expectedImage.setPixel(tcu::Vec4(clearColor[0].float32), x, y, z);
1741             }
1742         }
1743     }
1744     const tcu::ConstPixelBufferAccess resultImage(format, attachmentSize.x(), attachmentSize.y(), attachmentSize.z(),
1745                                                   colorBufferAlloc->getHostPtr());
1746 
1747     if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage,
1748                                   tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1749         return tcu::TestStatus::fail("Fail");
1750 
1751     return tcu::TestStatus::pass("Pass");
1752 }
1753 
testUnusedAtt(Context & context,PipelineConstructionType pipelineConstructionType)1754 tcu::TestStatus testUnusedAtt(Context &context, PipelineConstructionType pipelineConstructionType)
1755 {
1756     const DeviceInterface &vk = context.getDeviceInterface();
1757     const VkDevice device     = context.getDevice();
1758     const Move<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1759                                                         context.getUniversalQueueFamilyIndex()));
1760     const Move<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1761 
1762     const VkAttachmentReference attRef = {VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
1763 
1764     const VkSubpassDescription subpass = {
1765         0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, DE_NULL, 1, &attRef, DE_NULL, DE_NULL, 0, DE_NULL};
1766 
1767     const VkRenderPassCreateInfo renderPassCreateInfo = {
1768         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, DE_NULL, 0, 0, DE_NULL, 1, &subpass, 0, DE_NULL};
1769 
1770     RenderPassWrapper renderPass(pipelineConstructionType, vk, device, &renderPassCreateInfo);
1771 
1772     const VkFramebufferCreateInfo framebufferCreateInfo = {
1773         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, DE_NULL, 0, *renderPass, 0, DE_NULL, 32, 32, 1};
1774 
1775     renderPass.createFramebuffer(vk, device, &framebufferCreateInfo, VK_NULL_HANDLE);
1776 
1777     beginCommandBuffer(vk, *cmdBuffer);
1778     renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, 32u, 32u));
1779     renderPass.end(vk, *cmdBuffer);
1780     endCommandBuffer(vk, *cmdBuffer);
1781 
1782     return tcu::TestStatus::pass("Pass");
1783 }
1784 
initDifferentAttachmentSizesPrograms(SourceCollections & programCollection,const CaseDef caseDef)1785 void initDifferentAttachmentSizesPrograms(SourceCollections &programCollection, const CaseDef caseDef)
1786 {
1787     DE_UNREF(caseDef);
1788 
1789     // Vertex shader
1790     {
1791         std::ostringstream src;
1792         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1793             << "\n"
1794             << "layout(location = 0) in vec4 in_position;\n"
1795             << "\n"
1796             << "out gl_PerVertex {\n"
1797             << "    vec4 gl_Position;\n"
1798             << "};\n"
1799             << "\n"
1800             << "void main(void)\n"
1801             << "{\n"
1802             << "    gl_Position = in_position;\n"
1803             << "}\n";
1804 
1805         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1806     }
1807 
1808     // Fragment shader
1809     {
1810         std::ostringstream src;
1811         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1812             << "\n"
1813             << "layout(location = 0) out vec4 o_color0;\n"
1814             << "layout(location = 1) out vec4 o_color1;\n"
1815             << "layout(location = 2) out vec4 o_color2;\n"
1816             << "\n"
1817             << "void main(void)\n"
1818             << "{\n"
1819             << "    o_color0 = vec4(1.0,  0.5, 0.25, 1.0);\n"
1820             << "    o_color1 = vec4(0.5,  1.0, 0.25, 1.0);\n"
1821             << "    o_color2 = vec4(0.25, 0.5, 1.0,  1.0);\n"
1822             << "}\n";
1823 
1824         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1825     }
1826 }
1827 
initMultiAttachmentsNotExportPrograms(SourceCollections & programCollection,const CaseDef caseDef)1828 void initMultiAttachmentsNotExportPrograms(SourceCollections &programCollection, const CaseDef caseDef)
1829 {
1830     DE_UNREF(caseDef);
1831 
1832     // Vertex shader
1833     {
1834         std::ostringstream src;
1835         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1836             << "\n"
1837             << "layout(location = 0) in vec4 in_position;\n"
1838             << "\n"
1839             << "out gl_PerVertex {\n"
1840             << "    vec4 gl_Position;\n"
1841             << "};\n"
1842             << "\n"
1843             << "void main(void)\n"
1844             << "{\n"
1845             << "    gl_Position = in_position;\n"
1846             << "}\n";
1847 
1848         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1849     }
1850 
1851     // Fragment shader
1852     {
1853         std::ostringstream src;
1854         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1855             << "\n"
1856             << "layout(location = 0) out vec4 o_color0;\n"
1857             << "layout(location = 1) out vec4 o_color1;\n"
1858             << "layout(location = 2) out vec4 o_color2;\n"
1859             << "\n"
1860             << "void main(void)\n"
1861             << "{\n"
1862             << "    o_color0 = vec4(1.0,  0.5, 0.25, 1.0);\n"
1863             << "    o_color2 = vec4(0.25, 0.5, 1.0,  1.0);\n"
1864             << "}\n";
1865 
1866         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1867     }
1868 }
1869 
getShortImageViewTypeName(const VkImageViewType imageViewType)1870 std::string getShortImageViewTypeName(const VkImageViewType imageViewType)
1871 {
1872     std::string s(getImageViewTypeName(imageViewType));
1873     return de::toLower(s.substr(19));
1874 }
1875 
getSizeString(const CaseDef & caseDef)1876 std::string getSizeString(const CaseDef &caseDef)
1877 {
1878     std::ostringstream str;
1879 
1880     str << caseDef.renderSize.x();
1881     if (caseDef.renderSize.y() > 1)
1882         str << "x" << caseDef.renderSize.y();
1883     if (caseDef.renderSize.z() > 1)
1884         str << "x" << caseDef.renderSize.z();
1885 
1886     str << "_" << caseDef.attachmentSize.x();
1887 
1888     if (caseDef.attachmentSize.y() > 1)
1889         str << "x" << caseDef.attachmentSize.y();
1890     if (caseDef.attachmentSize.z() > 1)
1891         str << "x" << caseDef.attachmentSize.z();
1892     if (caseDef.numLayers > 1)
1893         str << "_" << caseDef.numLayers;
1894 
1895     return str.str();
1896 }
1897 
getTestCaseString(const CaseDef & caseDef)1898 std::string getTestCaseString(const CaseDef &caseDef)
1899 {
1900     std::ostringstream str;
1901 
1902     str << getShortImageViewTypeName(caseDef.imageType).c_str();
1903     str << "_";
1904     str << getSizeString(caseDef);
1905 
1906     if (caseDef.multisample)
1907         str << "_ms";
1908 
1909     return str.str();
1910 }
1911 
checkConstructionTypeSupport(Context & context,PipelineConstructionType pipelineConstructionType)1912 void checkConstructionTypeSupport(Context &context, PipelineConstructionType pipelineConstructionType)
1913 {
1914     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1915                                           pipelineConstructionType);
1916 }
1917 
checkSupport(Context & context,const CaseDef caseDef)1918 void checkSupport(Context &context, const CaseDef caseDef)
1919 {
1920     checkConstructionTypeSupport(context, caseDef.pipelineConstructionType);
1921 }
1922 
checkSupportNoAtt(Context & context,const NoAttCaseDef caseDef)1923 void checkSupportNoAtt(Context &context, const NoAttCaseDef caseDef)
1924 {
1925     const auto &features = context.getDeviceFeatures();
1926 
1927     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1928 
1929     if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
1930         throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
1931 
1932     if (caseDef.multisample)
1933         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); // MS shader uses gl_SampleID
1934 
1935     checkConstructionTypeSupport(context, caseDef.pipelineConstructionType);
1936 }
1937 
addAttachmentTestCasesWithFunctions(tcu::TestCaseGroup * group,PipelineConstructionType pipelineConstructionType)1938 void addAttachmentTestCasesWithFunctions(tcu::TestCaseGroup *group, PipelineConstructionType pipelineConstructionType)
1939 {
1940     // Add test cases for attachment strictly sizes larger than the framebuffer
1941     const CaseDef caseDef[] = {
1942         // Single-sample test cases
1943         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false,
1944          MULTI_ATTACHMENTS_NONE},
1945         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false,
1946          MULTI_ATTACHMENTS_NONE},
1947         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false,
1948          MULTI_ATTACHMENTS_NONE},
1949         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false,
1950          MULTI_ATTACHMENTS_NONE},
1951 
1952         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(64, 1, 1), 4, false,
1953          MULTI_ATTACHMENTS_NONE},
1954         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(48, 1, 1), 4, false,
1955          MULTI_ATTACHMENTS_NONE},
1956         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(39, 1, 1), 4, false,
1957          MULTI_ATTACHMENTS_NONE},
1958         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(19, 1, 1), IVec3(32, 1, 1), 4, false,
1959          MULTI_ATTACHMENTS_NONE},
1960 
1961         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false,
1962          MULTI_ATTACHMENTS_NONE},
1963         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false,
1964          MULTI_ATTACHMENTS_NONE},
1965         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false,
1966          MULTI_ATTACHMENTS_NONE},
1967         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false,
1968          MULTI_ATTACHMENTS_NONE},
1969 
1970         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, false,
1971          MULTI_ATTACHMENTS_NONE},
1972         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, false,
1973          MULTI_ATTACHMENTS_NONE},
1974         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, false,
1975          MULTI_ATTACHMENTS_NONE},
1976         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, false,
1977          MULTI_ATTACHMENTS_NONE},
1978 
1979         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(64, 64, 1), 6, false,
1980          MULTI_ATTACHMENTS_NONE},
1981         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(48, 48, 1), 6, false,
1982          MULTI_ATTACHMENTS_NONE},
1983         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(39, 41, 1), 6, false,
1984          MULTI_ATTACHMENTS_NONE},
1985         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE, IVec3(19, 27, 1), IVec3(32, 32, 1), 6, false,
1986          MULTI_ATTACHMENTS_NONE},
1987 
1988         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 6 * 2, false,
1989          MULTI_ATTACHMENTS_NONE},
1990         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 6 * 2, false,
1991          MULTI_ATTACHMENTS_NONE},
1992         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 6 * 2, false,
1993          MULTI_ATTACHMENTS_NONE},
1994         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 6 * 2, false,
1995          MULTI_ATTACHMENTS_NONE},
1996 
1997         // Multi-sample test cases
1998         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true,
1999          MULTI_ATTACHMENTS_NONE},
2000         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true,
2001          MULTI_ATTACHMENTS_NONE},
2002         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true,
2003          MULTI_ATTACHMENTS_NONE},
2004         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true,
2005          MULTI_ATTACHMENTS_NONE},
2006 
2007         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, true,
2008          MULTI_ATTACHMENTS_NONE},
2009         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, true,
2010          MULTI_ATTACHMENTS_NONE},
2011         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, true,
2012          MULTI_ATTACHMENTS_NONE},
2013         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, true,
2014          MULTI_ATTACHMENTS_NONE},
2015     };
2016 
2017     for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
2018         addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), checkSupport, initColorPrograms,
2019                                     test, caseDef[sizeNdx]);
2020 
2021     // Add tests for the case where there are no color attachments but the
2022     // fragment shader writes to an image via imageStore().
2023     NoAttCaseDef noAttCaseDef{pipelineConstructionType, false};
2024     addFunctionCaseWithPrograms(group, "no_attachments", checkSupportNoAtt, initImagePrograms, testNoAtt, noAttCaseDef);
2025     noAttCaseDef.multisample = true;
2026     addFunctionCaseWithPrograms(group, "no_attachments_ms", checkSupportNoAtt, initImagePrograms, testNoAtt,
2027                                 noAttCaseDef);
2028 
2029     // Test render pass with attachment set as unused.
2030     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ||
2031         pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV)
2032         addFunctionCase(group, "unused_attachment", checkConstructionTypeSupport, testUnusedAtt,
2033                         pipelineConstructionType);
2034 
2035     // Tests with multiple attachments that have different sizes.
2036     const CaseDef differentAttachmentSizesCaseDef[] = {
2037         // Single-sample test cases
2038         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false,
2039          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2040         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false,
2041          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2042         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false,
2043          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2044         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false,
2045          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2046 
2047         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false,
2048          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2049         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false,
2050          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2051         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false,
2052          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2053         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false,
2054          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2055 
2056         // Multi-sample test cases
2057         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true,
2058          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2059         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true,
2060          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2061         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true,
2062          MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2063         {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true,
2064          MULTI_ATTACHMENTS_DIFFERENT_SIZES}};
2065 
2066     for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx)
2067         addFunctionCaseWithPrograms(
2068             group,
2069             (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(),
2070             checkSupport, initDifferentAttachmentSizesPrograms, testMultiAttachments,
2071             differentAttachmentSizesCaseDef[sizeNdx]);
2072 
2073     // Tests with same attachment for input and resolving.
2074     const CaseDef resolveInputSameAttachmentCaseDef = {
2075         pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(64, 64, 1), IVec3(64, 64, 1), 1, true,
2076         MULTI_ATTACHMENTS_NONE};
2077     // Input attachments are not supported with dynamic rendering
2078     if (!vk::isConstructionTypeShaderObject(pipelineConstructionType))
2079     {
2080         addFunctionCaseWithPrograms(group, "resolve_input_same_attachment", checkSupport,
2081                                     initInputResolveSameAttachmentPrograms, testInputResolveSameAttachment,
2082                                     resolveInputSameAttachmentCaseDef);
2083     }
2084 
2085     // Tests with multiple attachments, which some of them are not used in FS.
2086     const CaseDef AttachmentCaseDef[] = {// Single-sample test case
2087                                          {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(64, 64, 1),
2088                                           IVec3(64, 64, 1), 1, false, MULTI_ATTACHMENTS_NOT_EXPORTED},
2089                                          // Multi-sample test case
2090                                          {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(64, 64, 1),
2091                                           IVec3(64, 64, 1), 1, true, MULTI_ATTACHMENTS_NOT_EXPORTED}};
2092 
2093     for (int Ndx = 0; Ndx < DE_LENGTH_OF_ARRAY(AttachmentCaseDef); ++Ndx)
2094         addFunctionCaseWithPrograms(
2095             group, (std::string("multi_attachments_not_exported_") + getTestCaseString(AttachmentCaseDef[Ndx])).c_str(),
2096             checkSupport, initMultiAttachmentsNotExportPrograms, testMultiAttachments, AttachmentCaseDef[Ndx]);
2097 }
2098 
2099 } // namespace
2100 
createFramebufferAttachmentTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2101 tcu::TestCaseGroup *createFramebufferAttachmentTests(tcu::TestContext &testCtx,
2102                                                      PipelineConstructionType pipelineConstructionType)
2103 {
2104     return createTestGroup(testCtx, "framebuffer_attachment", addAttachmentTestCasesWithFunctions,
2105                            pipelineConstructionType);
2106 }
2107 
2108 } // namespace pipeline
2109 } // namespace vkt
2110