1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 Google Inc.
7  * Copyright (c) 2015 Imagination Technologies Ltd.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Tests attachments unused by subpasses
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRenderPassUnusedAttachmentTests.hpp"
27 #include "pipeline/vktPipelineImageUtil.hpp"
28 #include "vktRenderPassTestsUtil.hpp"
29 #include "vkBarrierUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuPlatform.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuVectorUtil.hpp"
47 #include "deStringUtil.hpp"
48 #include "deUniquePtr.hpp"
49 #include "deRandom.hpp"
50 #include <cstring>
51 #include <set>
52 #include <sstream>
53 #include <vector>
54 
55 namespace vkt
56 {
57 namespace renderpass
58 {
59 
60 using namespace vk;
61 
62 namespace
63 {
64 
65 struct TestParams
66 {
67     VkAttachmentLoadOp loadOp;
68     VkAttachmentStoreOp storeOp;
69     VkAttachmentLoadOp stencilLoadOp;
70     VkAttachmentStoreOp stencilStoreOp;
71     SharedGroupParams groupParams;
72 };
73 
74 struct Vertex4RGBA
75 {
76     tcu::Vec4 position;
77     tcu::Vec4 color;
78 };
79 
createQuad(void)80 std::vector<Vertex4RGBA> createQuad(void)
81 {
82     std::vector<Vertex4RGBA> vertices;
83 
84     const float size = 0.8f;
85     const tcu::Vec4 color(0.2f, 0.3f, 0.1f, 1.0f);
86     const Vertex4RGBA lowerLeftVertex  = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
87     const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
88     const Vertex4RGBA upperLeftVertex  = {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
89     const Vertex4RGBA upperRightVertex = {tcu::Vec4(size, size, 0.0f, 1.0f), color};
90 
91     vertices.push_back(lowerLeftVertex);
92     vertices.push_back(lowerRightVertex);
93     vertices.push_back(upperLeftVertex);
94     vertices.push_back(upperLeftVertex);
95     vertices.push_back(lowerRightVertex);
96     vertices.push_back(upperRightVertex);
97 
98     return vertices;
99 }
100 
101 template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
102           typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice,const TestParams testParams)103 Move<VkRenderPass> createRenderPass(const DeviceInterface &vk, VkDevice vkDevice, const TestParams testParams)
104 {
105     const VkImageAspectFlags aspectMask =
106         testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
107     const AttachmentDesc attachmentDescriptions[] = {
108         // Result attachment
109         AttachmentDesc(DE_NULL,                                 // const void*                        pNext
110                        (VkAttachmentDescriptionFlags)0,         // VkAttachmentDescriptionFlags        flags
111                        VK_FORMAT_R8G8B8A8_UNORM,                // VkFormat                            format
112                        VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits            samples
113                        VK_ATTACHMENT_LOAD_OP_CLEAR,             // VkAttachmentLoadOp                loadOp
114                        VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp                storeOp
115                        VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp                stencilLoadOp
116                        VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp                stencilStoreOp
117                        VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout                    initialLayout
118                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout                    finalLayout
119                        ),
120         // Unused attachment
121         AttachmentDesc(DE_NULL,                                  // const void*                        pNext
122                        (VkAttachmentDescriptionFlags)0,          // VkAttachmentDescriptionFlags        flags
123                        VK_FORMAT_R8G8B8A8_UNORM,                 // VkFormat                            format
124                        VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits            samples
125                        testParams.loadOp,                        // VkAttachmentLoadOp                loadOp
126                        testParams.storeOp,                       // VkAttachmentStoreOp                storeOp
127                        testParams.stencilLoadOp,                 // VkAttachmentLoadOp                stencilLoadOp
128                        testParams.stencilStoreOp,                // VkAttachmentStoreOp                stencilStoreOp
129                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout                    initialLayout
130                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL  // VkImageLayout                    finalLayout
131                        ),
132         // Input attachment
133         AttachmentDesc(DE_NULL,                                 // const void*                        pNext
134                        (VkAttachmentDescriptionFlags)0,         // VkAttachmentDescriptionFlags        flags
135                        VK_FORMAT_R8G8B8A8_UNORM,                // VkFormat                            format
136                        VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits            samples
137                        VK_ATTACHMENT_LOAD_OP_CLEAR,             // VkAttachmentLoadOp                loadOp
138                        VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp                storeOp
139                        VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp                stencilLoadOp
140                        VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp                stencilStoreOp
141                        VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout                    initialLayout
142                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout                    finalLayout
143                        )};
144 
145     // Note: Attachment 1 is not referenced by any subpass.
146     const AttachmentRef resultAttachmentRefSubpass0(
147         DE_NULL,                                  // const void*            pNext
148         2u,                                       // uint32_t                attachment
149         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
150         aspectMask                                // VkImageAspectFlags    aspectMask
151     );
152 
153     const AttachmentRef resultAttachmentRefSubpass1(
154         DE_NULL,                                  // const void*            pNext
155         0u,                                       // uint32_t                attachment
156         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
157         aspectMask                                // VkImageAspectFlags    aspectMask
158     );
159 
160     const AttachmentRef inputAttachmentRefSubpass1(
161         DE_NULL,                                  // const void*            pNext
162         2u,                                       // uint32_t                attachment
163         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout        layout
164         aspectMask                                // VkImageAspectFlags    aspectMask
165     );
166 
167     const SubpassDesc subpassDescriptions[] = {
168         SubpassDesc(DE_NULL,
169                     (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags        flags
170                     VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint                pipelineBindPoint
171                     0u,                              // uint32_t                            viewMask
172                     0u,                              // uint32_t                            inputAttachmentCount
173                     DE_NULL,                         // const VkAttachmentReference*        pInputAttachments
174                     1u,                              // uint32_t                            colorAttachmentCount
175                     &resultAttachmentRefSubpass0,    // const VkAttachmentReference*        pColorAttachments
176                     DE_NULL,                         // const VkAttachmentReference*        pResolveAttachments
177                     DE_NULL,                         // const VkAttachmentReference*        pDepthStencilAttachment
178                     0u,                              // uint32_t                            preserveAttachmentCount
179                     DE_NULL                          // const uint32_t*                    pPreserveAttachments
180                     ),
181         SubpassDesc(DE_NULL,
182                     (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags        flags
183                     VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint                pipelineBindPoint
184                     0u,                              // uint32_t                            viewMask
185                     1u,                              // uint32_t                            inputAttachmentCount
186                     &inputAttachmentRefSubpass1,     // const VkAttachmentReference*        pInputAttachments
187                     1u,                              // uint32_t                            colorAttachmentCount
188                     &resultAttachmentRefSubpass1,    // const VkAttachmentReference*        pColorAttachments
189                     DE_NULL,                         // const VkAttachmentReference*        pResolveAttachments
190                     DE_NULL,                         // const VkAttachmentReference*        pDepthStencilAttachment
191                     0u,                              // uint32_t                            preserveAttachmentCount
192                     DE_NULL                          // const uint32_t*                    pPreserveAttachments
193                     )};
194 
195     const SubpassDep subpassDependency(
196         DE_NULL,                                       // const void*                pNext
197         0u,                                            // uint32_t                    srcSubpass
198         1u,                                            // uint32_t                    dstSubpass
199         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags        srcStageMask
200         VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,         // VkPipelineStageFlags        dstStageMask
201         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,          // VkAccessFlags            srcAccessMask
202         VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,           // VkAccessFlags            dstAccessMask
203         VK_DEPENDENCY_BY_REGION_BIT,                   // VkDependencyFlags        dependencyFlags
204         0u                                             // int32_t                    viewOffset
205     );
206 
207     const RenderPassCreateInfo renderPassInfo(DE_NULL,                    // const void*                        pNext
208                                               (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags            flags
209                                               3u, // uint32_t                            attachmentCount
210                                               attachmentDescriptions, // const VkAttachmentDescription*    pAttachments
211                                               2u,                  // uint32_t                            subpassCount
212                                               subpassDescriptions, // const VkSubpassDescription*        pSubpasses
213                                               1u,                 // uint32_t                            dependencyCount
214                                               &subpassDependency, // const VkSubpassDependency*        pDependencies
215                                               0u,     // uint32_t                            correlatedViewMaskCount
216                                               DE_NULL // const uint32_t*                    pCorrelatedViewMasks
217     );
218 
219     return renderPassInfo.createRenderPass(vk, vkDevice);
220 }
221 
chooseInputImageLayout(const SharedGroupParams groupParams)222 VkImageLayout chooseInputImageLayout(const SharedGroupParams groupParams)
223 {
224 #ifndef CTS_USES_VULKANSC
225     if (groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
226     {
227         // use general layout for local reads for some tests
228         if (groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
229             return VK_IMAGE_LAYOUT_GENERAL;
230         return VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
231     }
232 #else
233     DE_UNREF(groupParams);
234 #endif
235     return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
236 }
237 
238 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(const DeviceInterface & vk,VkCommandBuffer secCmdBuffer,const void * additionalInheritanceRenderingInfo)239 void beginSecondaryCmdBuffer(const DeviceInterface &vk, VkCommandBuffer secCmdBuffer,
240                              const void *additionalInheritanceRenderingInfo)
241 {
242     VkCommandBufferUsageFlags usageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
243     const std::vector<VkFormat> colorAttachmentFormats(3, VK_FORMAT_R8G8B8A8_UNORM);
244 
245     const VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
246         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
247         additionalInheritanceRenderingInfo,                              // const void* pNext;
248         0u,                                                              // VkRenderingFlagsKHR flags;
249         0u,                                                              // uint32_t viewMask;
250         3u,                                                              // uint32_t colorAttachmentCount;
251         colorAttachmentFormats.data(),                                   // const VkFormat* pColorAttachmentFormats;
252         VK_FORMAT_UNDEFINED,                                             // VkFormat depthAttachmentFormat;
253         VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
254         VK_SAMPLE_COUNT_1_BIT,                                           // VkSampleCountFlagBits rasterizationSamples;
255     };
256     const VkCommandBufferInheritanceInfo bufferInheritanceInfo{
257         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
258         &inheritanceRenderingInfo,                         // const void* pNext;
259         DE_NULL,                                           // VkRenderPass renderPass;
260         0u,                                                // uint32_t subpass;
261         DE_NULL,                                           // VkFramebuffer framebuffer;
262         VK_FALSE,                                          // VkBool32 occlusionQueryEnable;
263         (VkQueryControlFlags)0u,                           // VkQueryControlFlags queryFlags;
264         (VkQueryPipelineStatisticFlags)0u                  // VkQueryPipelineStatisticFlags pipelineStatistics;
265     };
266     const VkCommandBufferBeginInfo commandBufBeginParams{
267         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
268         DE_NULL,                                     // const void* pNext;
269         usageFlags,                                  // VkCommandBufferUsageFlags flags;
270         &bufferInheritanceInfo                       // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
271     };
272     VK_CHECK(vk.beginCommandBuffer(secCmdBuffer, &commandBufBeginParams));
273 }
274 #endif // CTS_USES_VULKANSC
275 
276 class UnusedAttachmentTest : public vkt::TestCase
277 {
278 public:
279     UnusedAttachmentTest(tcu::TestContext &testContext, const std::string &name, const TestParams &testParams);
280     virtual ~UnusedAttachmentTest(void) = default;
281     virtual void initPrograms(SourceCollections &sourceCollections) const;
282     virtual TestInstance *createInstance(Context &context) const;
283     void checkSupport(Context &context) const;
284 
285 private:
286     const TestParams m_testParams;
287 };
288 
289 class UnusedAttachmentTestInstance : public vkt::TestInstance
290 {
291 public:
292     UnusedAttachmentTestInstance(Context &context, const TestParams &testParams);
293     virtual ~UnusedAttachmentTestInstance(void) = default;
294     virtual tcu::TestStatus iterate(void);
295 
296 protected:
297     template <typename RenderpassSubpass>
298     void createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice);
299     void createCommandBufferDynamicRendering(const DeviceInterface &vk, VkDevice vkDevice);
300 
301 #ifndef CTS_USES_VULKANSC
302     void preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
303     void inbetweenRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
304 #endif // CTS_USES_VULKANSC
305     void drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
306     void drawSecondSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
307 
308 private:
309     tcu::TestStatus verifyImage(void);
310 
311     const TestParams m_testParams;
312     const tcu::UVec2 m_renderSize;
313 
314     Move<VkImage> m_colorImage;
315     de::MovePtr<Allocation> m_colorImageAlloc;
316     Move<VkImageView> m_colorAttachmentView;
317 
318     Move<VkImage> m_unusedImage;
319     de::MovePtr<Allocation> m_unusedImageAlloc;
320     Move<VkImageView> m_unusedAttachmentView;
321 
322     Move<VkImage> m_inputImage;
323     de::MovePtr<Allocation> m_inputImageAlloc;
324     Move<VkImageView> m_inputAttachmentView;
325     VkImageLayout m_inputImageReadLayout;
326 
327     Move<VkDescriptorSetLayout> m_descriptorSetLayoutSubpass0;
328     Move<VkDescriptorSetLayout> m_descriptorSetLayoutSubpass1;
329     Move<VkDescriptorPool> m_descriptorPool;
330     Move<VkDescriptorSet> m_descriptorSetSubpass1;
331     Move<VkRenderPass> m_renderPass;
332     Move<VkFramebuffer> m_framebuffer;
333 
334     ShaderWrapper m_vertexShaderModule;
335     ShaderWrapper m_fragmentShaderModuleSubpass0;
336     ShaderWrapper m_fragmentShaderModuleSubpass1;
337 
338     Move<VkBuffer> m_vertexBuffer;
339     std::vector<Vertex4RGBA> m_vertices;
340     de::MovePtr<Allocation> m_vertexBufferAlloc;
341 
342     Move<VkBuffer> m_backingBuffer;
343     de::MovePtr<Allocation> m_backingBufferAlloc;
344 
345     PipelineLayoutWrapper m_pipelineLayoutSubpass0;
346     PipelineLayoutWrapper m_pipelineLayoutSubpass1;
347     GraphicsPipelineWrapper m_graphicsPipelineSubpass0;
348     GraphicsPipelineWrapper m_graphicsPipelineSubpass1;
349 
350     Move<VkCommandPool> m_cmdPool;
351     Move<VkCommandBuffer> m_cmdBuffer;
352     Move<VkCommandBuffer> m_secCmdBuffer;
353 };
354 
UnusedAttachmentTest(tcu::TestContext & testContext,const std::string & name,const TestParams & testParams)355 UnusedAttachmentTest::UnusedAttachmentTest(tcu::TestContext &testContext, const std::string &name,
356                                            const TestParams &testParams)
357     : vkt::TestCase(testContext, name)
358     , m_testParams(testParams)
359 {
360 }
361 
createInstance(Context & context) const362 TestInstance *UnusedAttachmentTest::createInstance(Context &context) const
363 {
364     return new UnusedAttachmentTestInstance(context, m_testParams);
365 }
366 
checkSupport(Context & context) const367 void UnusedAttachmentTest::checkSupport(Context &context) const
368 {
369     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
370                                           m_testParams.groupParams->pipelineConstructionType);
371     if (m_testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
372         context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
373     else if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
374         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
375 }
376 
initPrograms(SourceCollections & sourceCollections) const377 void UnusedAttachmentTest::initPrograms(SourceCollections &sourceCollections) const
378 {
379     std::ostringstream fragmentSource;
380 
381     sourceCollections.glslSources.add("color_vert")
382         << glu::VertexSource("#version 450\n"
383                              "layout(location = 0) in highp vec4 position;\n"
384                              "layout(location = 1) in highp vec4 color;\n"
385                              "layout(location = 0) out highp vec4 vtxColor;\n"
386                              "void main (void)\n"
387                              "{\n"
388                              "    gl_Position = position;\n"
389                              "    vtxColor = color;\n"
390                              "}\n");
391 
392     sourceCollections.glslSources.add("color_frag_sb0")
393         << glu::FragmentSource("#version 450\n"
394                                "layout(location = 0) in highp vec4 vtxColor;\n"
395                                "layout(location = 0) out highp vec4 fragColor;\n"
396                                "void main (void)\n"
397                                "{\n"
398                                "    fragColor = vtxColor;\n"
399                                "}\n");
400 
401     sourceCollections.glslSources.add("color_frag_sb1") << glu::FragmentSource(
402         "#version 450\n"
403         "layout(location = 0) in highp vec4 vtxColor;\n"
404         "layout(location = 0) out highp vec4 fragColor;\n"
405         "layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;"
406         "void main (void)\n"
407         "{\n"
408         "    fragColor = subpassLoad(inputColor) + vtxColor;\n"
409         "}\n");
410 }
411 
UnusedAttachmentTestInstance(Context & context,const TestParams & testParams)412 UnusedAttachmentTestInstance::UnusedAttachmentTestInstance(Context &context, const TestParams &testParams)
413     : vkt::TestInstance(context)
414     , m_testParams(testParams)
415     , m_renderSize(32u, 32u)
416     , m_inputImageReadLayout(chooseInputImageLayout(testParams.groupParams))
417     , m_vertices(createQuad())
418     , m_graphicsPipelineSubpass0(context.getInstanceInterface(), context.getDeviceInterface(),
419                                  context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(),
420                                  m_testParams.groupParams->pipelineConstructionType)
421     , m_graphicsPipelineSubpass1(context.getInstanceInterface(), context.getDeviceInterface(),
422                                  context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(),
423                                  m_testParams.groupParams->pipelineConstructionType)
424 {
425     const DeviceInterface &vk       = m_context.getDeviceInterface();
426     const VkDevice vkDevice         = m_context.getDevice();
427     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
428     SimpleAllocator memAlloc(
429         vk, vkDevice,
430         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
431     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
432                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
433 
434     // Create color image
435     {
436         const VkImageCreateInfo colorImageParams = {
437             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
438             DE_NULL,                                                               // const void* pNext;
439             0u,                                                                    // VkImageCreateFlags flags;
440             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
441             VK_FORMAT_R8G8B8A8_UNORM,                                              // VkFormat format;
442             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
443             1u,                                                                    // uint32_t mipLevels;
444             1u,                                                                    // uint32_t arrayLayers;
445             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
446             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
447             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
448             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
449             1u,                                                                    // uint32_t queueFamilyIndexCount;
450             &queueFamilyIndex,        // const uint32_t* pQueueFamilyIndices;
451             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
452         };
453 
454         m_colorImage = createImage(vk, vkDevice, &colorImageParams);
455 
456         // Allocate and bind color image memory
457         m_colorImageAlloc =
458             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
459         VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
460                                     m_colorImageAlloc->getOffset()));
461     }
462 
463     // Create image which is not used by any subpass
464     {
465         const VkImageCreateInfo unusedImageParams = {
466             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,      // VkStructureType sType;
467             DE_NULL,                                  // const void* pNext;
468             0u,                                       // VkImageCreateFlags flags;
469             VK_IMAGE_TYPE_2D,                         // VkImageType imageType;
470             VK_FORMAT_R8G8B8A8_UNORM,                 // VkFormat format;
471             {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
472             1u,                                       // uint32_t mipLevels;
473             1u,                                       // uint32_t arrayLayers;
474             VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
475             VK_IMAGE_TILING_OPTIMAL,                  // VkImageTiling tiling;
476             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
477                 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
478             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
479             1u,                                  // uint32_t queueFamilyIndexCount;
480             &queueFamilyIndex,                   // const uint32_t* pQueueFamilyIndices;
481             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
482         };
483 
484         m_unusedImage = createImage(vk, vkDevice, &unusedImageParams);
485 
486         // Allocate and bind unused image memory
487         VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vk, vkDevice, *m_unusedImage);
488 
489         m_unusedImageAlloc = memAlloc.allocate(memoryRequirements, MemoryRequirement::Any);
490         VK_CHECK(vk.bindImageMemory(vkDevice, *m_unusedImage, m_unusedImageAlloc->getMemory(),
491                                     m_unusedImageAlloc->getOffset()));
492 
493         // Clear image with specific value to verify the contents don't change
494         {
495             const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
496             Move<VkCommandPool> cmdPool;
497             Move<VkCommandBuffer> cmdBuffer;
498 
499             VkClearValue clearValue;
500             clearValue.color.float32[0] = 0.1f;
501             clearValue.color.float32[1] = 0.2f;
502             clearValue.color.float32[2] = 0.3f;
503             clearValue.color.float32[3] = 0.4f;
504 
505             // Create command pool and buffer
506             cmdPool   = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
507             cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
508 
509             const VkImageMemoryBarrier preImageBarrier = {
510                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
511                 DE_NULL,                                // const void* pNext;
512                 0u,                                     // VkAccessFlags srcAccessMask;
513                 VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
514                 VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
515                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
516                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
517                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t dstQueueFamilyIndex;
518                 *m_unusedImage,                         // VkImage image;
519                 {
520                     // VkImageSubresourceRange subresourceRange;
521                     aspectMask, // VkImageAspect aspect;
522                     0u,         // uint32_t baseMipLevel;
523                     1u,         // uint32_t mipLevels;
524                     0u,         // uint32_t baseArraySlice;
525                     1u          // uint32_t arraySize;
526                 }};
527 
528             const VkImageMemoryBarrier postImageBarrier = {
529                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // VkStructureType sType;
530                 DE_NULL,                                  // const void* pNext;
531                 VK_ACCESS_TRANSFER_WRITE_BIT,             // VkAccessFlags srcAccessMask;
532                 VK_ACCESS_SHADER_READ_BIT,                // VkAccessFlags dstAccessMask;
533                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,     // VkImageLayout oldLayout;
534                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
535                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t srcQueueFamilyIndex;
536                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t dstQueueFamilyIndex;
537                 *m_unusedImage,                           // VkImage image;
538                 {
539                     // VkImageSubresourceRange subresourceRange;
540                     aspectMask, // VkImageAspect aspect;
541                     0u,         // uint32_t baseMipLevel;
542                     1u,         // uint32_t mipLevels;
543                     0u,         // uint32_t baseArraySlice;
544                     1u          // uint32_t arraySize;
545                 }};
546 
547             const VkImageSubresourceRange clearRange = {
548                 aspectMask, // VkImageAspectFlags aspectMask;
549                 0u,         // uint32_t baseMipLevel;
550                 1u,         // uint32_t levelCount;
551                 0u,         // uint32_t baseArrayLayer;
552                 1u          // uint32_t layerCount;
553             };
554 
555             // Clear image
556             beginCommandBuffer(vk, *cmdBuffer);
557             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
558                                   (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
559                                   (const VkBufferMemoryBarrier *)DE_NULL, 1, &preImageBarrier);
560             vk.cmdClearColorImage(*cmdBuffer, *m_unusedImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color,
561                                   1, &clearRange);
562             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
563                                   (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
564                                   (const VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
565             endCommandBuffer(vk, *cmdBuffer);
566 
567             submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
568         }
569     }
570 
571     // Create input image
572     {
573         const VkImageCreateInfo inputImageParams = {
574             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                       // VkStructureType sType;
575             DE_NULL,                                                                   // const void* pNext;
576             0u,                                                                        // VkImageCreateFlags flags;
577             VK_IMAGE_TYPE_2D,                                                          // VkImageType imageType;
578             VK_FORMAT_R8G8B8A8_UNORM,                                                  // VkFormat format;
579             {m_renderSize.x(), m_renderSize.y(), 1u},                                  // VkExtent3D extent;
580             1u,                                                                        // uint32_t mipLevels;
581             1u,                                                                        // uint32_t arrayLayers;
582             VK_SAMPLE_COUNT_1_BIT,                                                     // VkSampleCountFlagBits samples;
583             VK_IMAGE_TILING_OPTIMAL,                                                   // VkImageTiling tiling;
584             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, // VkImageUsageFlags usage;
585             VK_SHARING_MODE_EXCLUSIVE,                                                 // VkSharingMode sharingMode;
586             1u,                       // uint32_t queueFamilyIndexCount;
587             &queueFamilyIndex,        // const uint32_t* pQueueFamilyIndices;
588             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
589         };
590 
591         m_inputImage = createImage(vk, vkDevice, &inputImageParams);
592 
593         // Allocate and bind input image memory
594         m_inputImageAlloc =
595             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_inputImage), MemoryRequirement::Any);
596         VK_CHECK(vk.bindImageMemory(vkDevice, *m_inputImage, m_inputImageAlloc->getMemory(),
597                                     m_inputImageAlloc->getOffset()));
598     }
599 
600     // Create color attachment view
601     {
602         const VkImageViewCreateInfo colorAttachmentViewParams = {
603             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
604             DE_NULL,                                    // const void* pNext;
605             0u,                                         // VkImageViewCreateFlags flags;
606             *m_colorImage,                              // VkImage image;
607             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
608             VK_FORMAT_R8G8B8A8_UNORM,                   // VkFormat format;
609             componentMappingRGBA,                       // VkChannelMapping channels;
610             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
611         };
612 
613         m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
614     }
615 
616     // Create unused attachment view
617     {
618         const VkImageViewCreateInfo unusedAttachmentViewParams = {
619             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
620             DE_NULL,                                    // const void* pNext;
621             0u,                                         // VkImageViewCreateFlags flags;
622             *m_unusedImage,                             // VkImage image;
623             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
624             VK_FORMAT_R8G8B8A8_UNORM,                   // VkFormat format;
625             componentMappingRGBA,                       // VkChannelMapping channels;
626             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
627         };
628 
629         m_unusedAttachmentView = createImageView(vk, vkDevice, &unusedAttachmentViewParams);
630     }
631 
632     // Create input attachment view
633     {
634         const VkImageViewCreateInfo inputAttachmentViewParams = {
635             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
636             DE_NULL,                                    // const void* pNext;
637             0u,                                         // VkImageViewCreateFlags flags;
638             *m_inputImage,                              // VkImage image;
639             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
640             VK_FORMAT_R8G8B8A8_UNORM,                   // VkFormat format;
641             componentMappingRGBA,                       // VkChannelMapping channels;
642             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
643         };
644 
645         m_inputAttachmentView = createImageView(vk, vkDevice, &inputAttachmentViewParams);
646     }
647 
648     // Create render pass
649     if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
650         m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1,
651                                         SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
652     else if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
653         m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2,
654                                         SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
655     else
656         m_renderPass = Move<VkRenderPass>();
657 
658     // Create framebuffer if renderpass handle is valid
659     if (*m_renderPass != DE_NULL)
660     {
661         const VkImageView imageViews[] = {*m_colorAttachmentView, *m_unusedAttachmentView, *m_inputAttachmentView};
662 
663         const VkFramebufferCreateInfo framebufferParams = {
664             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
665             DE_NULL,                                   // const void* pNext;
666             0u,                                        // VkFramebufferCreateFlags flags;
667             *m_renderPass,                             // VkRenderPass renderPass;
668             3u,                                        // uint32_t attachmentCount;
669             imageViews,                                // const VkImageView* pAttachments;
670             (uint32_t)m_renderSize.x(),                // uint32_t width;
671             (uint32_t)m_renderSize.y(),                // uint32_t height;
672             1u                                         // uint32_t layers;
673         };
674 
675         m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
676     }
677 
678     // Create pipeline layout for subpass 0
679     {
680         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = {
681             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType
682             DE_NULL,                                             // const void*                            pNext
683             0u,                                                  // VkDescriptorSetLayoutCreateFlags        flags
684             0u,                                                  // uint32_t                                bindingCount
685             DE_NULL                                              // const VkDescriptorSetLayoutBinding*    pBindings
686         };
687         m_descriptorSetLayoutSubpass0 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
688         m_pipelineLayoutSubpass0 = PipelineLayoutWrapper(testParams.groupParams->pipelineConstructionType, vk, vkDevice,
689                                                          *m_descriptorSetLayoutSubpass0);
690     }
691 
692     // Create pipeline layout for subpass 1
693     {
694         const VkDescriptorSetLayoutBinding layoutBinding = {
695             0u,                                  // uint32_t binding;
696             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType;
697             1u,                                  // uint32_t descriptorCount;
698             VK_SHADER_STAGE_FRAGMENT_BIT,        // VkShaderStageFlags stageFlags;
699             DE_NULL                              // const VkSampler* pImmutableSamplers;
700         };
701 
702         const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = {
703             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType
704             DE_NULL,                                             // const void*                            pNext
705             0u,                                                  // VkDescriptorSetLayoutCreateFlags        flags
706             1u,                                                  // uint32_t                                bindingCount
707             &layoutBinding                                       // const VkDescriptorSetLayoutBinding*    pBindings
708         };
709         m_descriptorSetLayoutSubpass1 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
710         m_pipelineLayoutSubpass1 = PipelineLayoutWrapper(testParams.groupParams->pipelineConstructionType, vk, vkDevice,
711                                                          *m_descriptorSetLayoutSubpass1);
712     }
713 
714     // Update descriptor set
715     {
716         const VkDescriptorPoolSize descriptorPoolSize = {
717             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType type;
718             1u                                   // uint32_t descriptorCount;
719         };
720 
721         const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {
722             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,     // VkStructureType                sType
723             DE_NULL,                                           // const void*                    pNext
724             VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags    flags
725             1u,                                                // uint32_t                        maxSets
726             1u,                                                // uint32_t                        poolSizeCount
727             &descriptorPoolSize                                // const VkDescriptorPoolSize*    pPoolSizes
728         };
729 
730         m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
731 
732         const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
733             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                    sType
734             DE_NULL,                                        // const void*                        pNext
735             *m_descriptorPool,                              // VkDescriptorPool                    descriptorPool
736             1u,                                             // uint32_t                            descriptorSetCount
737             &m_descriptorSetLayoutSubpass1.get(),           // const VkDescriptorSetLayout*        pSetLayouts
738         };
739 
740         m_descriptorSetSubpass1 = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
741 
742         const VkDescriptorImageInfo inputImageInfo = {
743             DE_NULL,                // VkSampleri sampler;
744             *m_inputAttachmentView, // VkImageView imageView;
745             m_inputImageReadLayout  // VkImageLayout imageLayout;
746         };
747 
748         const VkWriteDescriptorSet descriptorWrite = {
749             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
750             DE_NULL,                                // const void* pNext;
751             *m_descriptorSetSubpass1,               // VkDescriptorSet dstSet;
752             0u,                                     // uint32_t dstBinding;
753             0u,                                     // uint32_t dstArrayElement;
754             1u,                                     // uint32_t descriptorCount;
755             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,    // VkDescriptorType descriptorType;
756             &inputImageInfo,                        // const VkDescriptorImageInfo* pImageInfo;
757             DE_NULL,                                // const VkDescriptorBufferInfo* pBufferInfo;
758             DE_NULL                                 // const VkBufferView* pTexelBufferView;
759         };
760 
761         vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
762     }
763 
764     m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
765     m_fragmentShaderModuleSubpass0 =
766         ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb0"), 0);
767     m_fragmentShaderModuleSubpass1 =
768         ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb1"), 0);
769 
770     // Create pipelines
771     {
772         const VkVertexInputBindingDescription vertexInputBindingDescription = {
773             0u,                         // uint32_t binding;
774             sizeof(Vertex4RGBA),        // uint32_t strideInBytes;
775             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
776         };
777 
778         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
779             {
780                 0u,                            // uint32_t location;
781                 0u,                            // uint32_t binding;
782                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
783                 0u                             // uint32_t offset;
784             },
785             {
786                 1u,                            // uint32_t location;
787                 0u,                            // uint32_t binding;
788                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
789                 (uint32_t)(sizeof(float) * 4), // uint32_t offset;
790             }};
791 
792         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
793             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
794             DE_NULL,                                                   // const void* pNext;
795             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
796             1u,                                                        // uint32_t vertexBindingDescriptionCount;
797             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
798             2u,                              // uint32_t vertexAttributeDescriptionCount;
799             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
800         };
801 
802         VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
803         deMemset(&colorBlendAttachmentState, 0x00, sizeof(VkPipelineColorBlendAttachmentState));
804         colorBlendAttachmentState.colorWriteMask = 0xF;
805 
806         uint32_t colorAttachmentsCount = (*m_renderPass == DE_NULL) ? 3u : 1u;
807         const std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(colorAttachmentsCount,
808                                                                                           colorBlendAttachmentState);
809         VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = initVulkanStructure();
810         colorBlendStateCreateInfo.attachmentCount                     = uint32_t(colorBlendAttachmentStates.size());
811         colorBlendStateCreateInfo.pAttachments                        = colorBlendAttachmentStates.data();
812 
813         PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
814         RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfoWrapper;
815         RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfoWrapper;
816         const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
817         const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
818 
819 #ifndef CTS_USES_VULKANSC
820         uint32_t colorAttachmentLocationsSubpass0[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, 0};
821         uint32_t colorAttachmentLocationsSubpass1[]{0, VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED};
822         VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
823         renderingAttachmentLocationInfo.colorAttachmentCount                 = colorAttachmentsCount;
824         renderingAttachmentLocationInfo.pColorAttachmentLocations            = colorAttachmentLocationsSubpass0;
825 
826         uint32_t colorAttachmentInputIndices[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, 0};
827         VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo{
828             VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR,
829             DE_NULL,
830             colorAttachmentsCount,       // uint32_t                    colorAttachmentCount
831             colorAttachmentInputIndices, // const uint32_t*            pColorAttachmentInputIndices
832             DE_NULL,                     // uint32_t                    depthInputAttachmentIndex
833             DE_NULL,                     // uint32_t                    stencilInputAttachmentIndex
834         };
835 
836         const std::vector<VkFormat> colorAttachmentFormats(colorAttachmentsCount, VK_FORMAT_R8G8B8A8_UNORM);
837         VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
838                                                           DE_NULL,
839                                                           0u,
840                                                           3u,
841                                                           colorAttachmentFormats.data(),
842                                                           VK_FORMAT_UNDEFINED,
843                                                           VK_FORMAT_UNDEFINED};
844 
845         if (*m_renderPass == DE_NULL)
846         {
847             renderingCreateInfoWrapper.ptr               = &renderingCreateInfo;
848             renderingAttachmentLocationInfoWrapper.ptr   = &renderingAttachmentLocationInfo;
849             renderingInputAttachmentIndexInfoWrapper.ptr = &renderingInputAttachmentIndexInfo;
850         }
851 #endif // CTS_USES_VULKANSC
852 
853         m_graphicsPipelineSubpass0.setDefaultMultisampleState()
854             .setDefaultDepthStencilState()
855             .setDefaultRasterizationState()
856             .setupVertexInputState(&vertexInputStateParams)
857             .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayoutSubpass0, *m_renderPass, 0u,
858                                               m_vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(),
859                                               ShaderWrapper(), DE_NULL, DE_NULL, renderingCreateInfoWrapper)
860             .setupFragmentShaderState(m_pipelineLayoutSubpass0, *m_renderPass, 0u, m_fragmentShaderModuleSubpass0)
861             .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfo, 0, 0, {},
862                                       renderingAttachmentLocationInfoWrapper)
863             .setMonolithicPipelineLayout(m_pipelineLayoutSubpass0)
864             .buildPipeline();
865 
866 #ifndef CTS_USES_VULKANSC
867         renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsSubpass1;
868 #endif // CTS_USES_VULKANSC
869 
870         m_graphicsPipelineSubpass1.setDefaultMultisampleState()
871             .setDefaultDepthStencilState()
872             .setDefaultRasterizationState()
873             .setupVertexInputState(&vertexInputStateParams)
874             .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayoutSubpass1, *m_renderPass, 1u,
875                                               m_vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(),
876                                               ShaderWrapper(), DE_NULL, DE_NULL, renderingCreateInfoWrapper)
877             .setupFragmentShaderState(m_pipelineLayoutSubpass1, *m_renderPass, 1u, m_fragmentShaderModuleSubpass1, 0, 0,
878                                       0, 0, {}, renderingInputAttachmentIndexInfoWrapper)
879             .setupFragmentOutputState(*m_renderPass, 1u, &colorBlendStateCreateInfo, 0, 0, {},
880                                       renderingAttachmentLocationInfoWrapper)
881             .setMonolithicPipelineLayout(m_pipelineLayoutSubpass1)
882             .buildPipeline();
883     }
884 
885     // Create vertex buffer
886     {
887         const VkBufferCreateInfo vertexBufferParams = {
888             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                    // VkStructureType sType;
889             DE_NULL,                                                 // const void* pNext;
890             0u,                                                      // VkBufferCreateFlags flags;
891             (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
892             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                       // VkBufferUsageFlags usage;
893             VK_SHARING_MODE_EXCLUSIVE,                               // VkSharingMode sharingMode;
894             1u,                                                      // uint32_t queueFamilyIndexCount;
895             &queueFamilyIndex                                        // const uint32_t* pQueueFamilyIndices;
896         };
897 
898         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
899         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
900                                                 MemoryRequirement::HostVisible);
901 
902         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
903                                      m_vertexBufferAlloc->getOffset()));
904 
905         // Upload vertex data
906         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
907         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
908     }
909 
910     // Create command pool
911     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
912 
913     // Create command buffer
914     if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
915         createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
916     else if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
917         createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
918     else
919         createCommandBufferDynamicRendering(vk, vkDevice);
920 }
921 
922 template <typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)923 void UnusedAttachmentTestInstance::createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice)
924 {
925     const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
926     const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
927 
928     const VkClearValue attachmentClearValues[] = {
929         makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f), // color
930         makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f), // unused
931         makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f)  // input
932     };
933 
934     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
935 
936     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
937 
938     const VkRenderPassBeginInfo renderPassBeginInfo{
939         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
940         DE_NULL,                                  // const void* pNext;
941         *m_renderPass,                            // VkRenderPass renderPass;
942         *m_framebuffer,                           // VkFramebuffer framebuffer;
943         makeRect2D(m_renderSize),                 // VkRect2D renderArea;
944         3u,                                       // uint32_t clearValueCount;
945         attachmentClearValues                     // const VkClearValue* pClearValues;
946     };
947     RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
948 
949     drawFirstSubpass(vk, *m_cmdBuffer);
950     vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
951     drawSecondSubpass(vk, *m_cmdBuffer);
952 
953     RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
954     endCommandBuffer(vk, *m_cmdBuffer);
955 }
956 
createCommandBufferDynamicRendering(const DeviceInterface & vk,VkDevice vkDevice)957 void UnusedAttachmentTestInstance::createCommandBufferDynamicRendering(const DeviceInterface &vk, VkDevice vkDevice)
958 {
959 #ifndef CTS_USES_VULKANSC
960     uint32_t colorAttachmentLocationsSubpass0[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, 0};
961     uint32_t colorAttachmentLocationsSubpass1[]{0, VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED};
962     VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
963     renderingAttachmentLocationInfo.colorAttachmentCount                 = 3u;
964     renderingAttachmentLocationInfo.pColorAttachmentLocations            = colorAttachmentLocationsSubpass0;
965 
966     uint32_t colorAttachmentInputIndicesSubpass0[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED};
967     uint32_t colorAttachmentInputIndicesSubpass1[]{VK_ATTACHMENT_UNUSED, VK_ATTACHMENT_UNUSED, 0};
968     VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo{
969         VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR,
970         DE_NULL,
971         3u,                                  // uint32_t                    colorAttachmentCount
972         colorAttachmentInputIndicesSubpass1, // const uint32_t*            pColorAttachmentInputIndices
973         DE_NULL,                             // uint32_t                    depthInputAttachmentIndex
974         DE_NULL,                             // uint32_t                    stencilInputAttachmentIndex
975     };
976 
977     std::vector<VkRenderingAttachmentInfo> colorAttachments(
978         3u,
979         {
980             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,   // VkStructureType sType;
981             DE_NULL,                                       // const void* pNext;
982             *m_colorAttachmentView,                        // VkImageView imageView;
983             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,      // VkImageLayout imageLayout;
984             VK_RESOLVE_MODE_NONE,                          // VkResolveModeFlagBits resolveMode;
985             DE_NULL,                                       // VkImageView resolveImageView;
986             VK_IMAGE_LAYOUT_UNDEFINED,                     // VkImageLayout resolveImageLayout;
987             VK_ATTACHMENT_LOAD_OP_CLEAR,                   // VkAttachmentLoadOp loadOp;
988             VK_ATTACHMENT_STORE_OP_STORE,                  // VkAttachmentStoreOp storeOp;
989             makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f) // VkClearValue clearValue;
990         });
991 
992     colorAttachments[1].imageView   = *m_unusedAttachmentView;
993     colorAttachments[1].loadOp      = m_testParams.loadOp;
994     colorAttachments[1].storeOp     = m_testParams.storeOp;
995     colorAttachments[2].imageView   = *m_inputAttachmentView;
996     colorAttachments[2].imageLayout = m_inputImageReadLayout;
997     colorAttachments[2].clearValue  = makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f);
998 
999     VkRenderingInfo renderingInfo{
1000         VK_STRUCTURE_TYPE_RENDERING_INFO,
1001         DE_NULL,
1002         0,                        // VkRenderingFlagsKHR flags;
1003         makeRect2D(m_renderSize), // VkRect2D renderArea;
1004         1u,                       // uint32_t layerCount;
1005         0u,                       // uint32_t viewMask;
1006         3u,                       // uint32_t colorAttachmentCount;
1007         colorAttachments.data(),  // const VkRenderingAttachmentInfoKHR* pColorAttachments;
1008         DE_NULL,                  // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
1009         DE_NULL,                  // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
1010     };
1011 
1012     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1013 
1014     if (m_testParams.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1015     {
1016         m_secCmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
1017         VkCommandBuffer secCmdBuffer = *m_secCmdBuffer;
1018 
1019         // record secondary command buffer
1020         renderingAttachmentLocationInfo.pNext = &renderingInputAttachmentIndexInfo;
1021         beginSecondaryCmdBuffer(vk, secCmdBuffer, &renderingAttachmentLocationInfo);
1022         vk.cmdBeginRendering(secCmdBuffer, &renderingInfo);
1023 
1024         renderingAttachmentLocationInfo.pNext                          = DE_NULL;
1025         renderingAttachmentLocationInfo.pColorAttachmentLocations      = colorAttachmentLocationsSubpass0;
1026         renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentInputIndicesSubpass0;
1027         vk.cmdSetRenderingAttachmentLocationsKHR(secCmdBuffer, &renderingAttachmentLocationInfo);
1028         vk.cmdSetRenderingInputAttachmentIndicesKHR(secCmdBuffer, &renderingInputAttachmentIndexInfo);
1029         drawFirstSubpass(vk, secCmdBuffer);
1030         inbetweenRenderCommands(vk, secCmdBuffer);
1031 
1032         renderingAttachmentLocationInfo.pColorAttachmentLocations      = colorAttachmentLocationsSubpass1;
1033         renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentInputIndicesSubpass1;
1034         vk.cmdSetRenderingAttachmentLocationsKHR(secCmdBuffer, &renderingAttachmentLocationInfo);
1035         vk.cmdSetRenderingInputAttachmentIndicesKHR(secCmdBuffer, &renderingInputAttachmentIndexInfo);
1036         drawSecondSubpass(vk, secCmdBuffer);
1037 
1038         vk.cmdEndRendering(secCmdBuffer);
1039         endCommandBuffer(vk, secCmdBuffer);
1040 
1041         // record primary command buffer
1042         beginCommandBuffer(vk, *m_cmdBuffer);
1043         preRenderCommands(vk, *m_cmdBuffer);
1044         vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &secCmdBuffer);
1045         endCommandBuffer(vk, *m_cmdBuffer);
1046     }
1047     else
1048     {
1049         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1050         preRenderCommands(vk, *m_cmdBuffer);
1051         vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
1052 
1053         vk.cmdSetRenderingAttachmentLocationsKHR(*m_cmdBuffer, &renderingAttachmentLocationInfo);
1054         drawFirstSubpass(vk, *m_cmdBuffer);
1055         inbetweenRenderCommands(vk, *m_cmdBuffer);
1056 
1057         renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsSubpass1;
1058         vk.cmdSetRenderingAttachmentLocationsKHR(*m_cmdBuffer, &renderingAttachmentLocationInfo);
1059         vk.cmdSetRenderingInputAttachmentIndicesKHR(*m_cmdBuffer, &renderingInputAttachmentIndexInfo);
1060         drawSecondSubpass(vk, *m_cmdBuffer);
1061 
1062         vk.cmdEndRendering(*m_cmdBuffer);
1063         endCommandBuffer(vk, *m_cmdBuffer);
1064     }
1065 #else
1066     DE_UNREF(vk);
1067     DE_UNREF(vkDevice);
1068 #endif // CTS_USES_VULKANSC
1069 }
1070 
1071 #ifndef CTS_USES_VULKANSC
preRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1072 void UnusedAttachmentTestInstance::preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1073 {
1074     const VkImageSubresourceRange subresourceRange(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1));
1075     const VkImageMemoryBarrier imageBarriers[]{
1076         makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1077                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *m_colorImage, subresourceRange),
1078         makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1079                                m_inputImageReadLayout, *m_inputImage, subresourceRange),
1080     };
1081 
1082     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1083                           0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1084 }
1085 
inbetweenRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1086 void UnusedAttachmentTestInstance::inbetweenRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1087 {
1088     const VkImageSubresourceRange subresourceRange(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1));
1089     VkImageMemoryBarrier imageBarrier(
1090         makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
1091                                m_inputImageReadLayout, m_inputImageReadLayout, *m_inputImage, subresourceRange));
1092     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1093                           VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0u, DE_NULL, 0u, DE_NULL,
1094                           1u, &imageBarrier);
1095 }
1096 #endif // CTS_USES_VULKANSC
1097 
drawFirstSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1098 void UnusedAttachmentTestInstance::drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1099 {
1100     const VkDeviceSize vertexBufferOffset = 0;
1101     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipelineSubpass0.getPipeline());
1102     vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1103     vk.cmdDraw(cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
1104 }
1105 
drawSecondSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1106 void UnusedAttachmentTestInstance::drawSecondSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1107 {
1108     const VkDeviceSize vertexBufferOffset = 0;
1109     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipelineSubpass1.getPipeline());
1110     vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1111     vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutSubpass1, 0, 1,
1112                              &m_descriptorSetSubpass1.get(), 0, DE_NULL);
1113     vk.cmdDraw(cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
1114 }
1115 
iterate(void)1116 tcu::TestStatus UnusedAttachmentTestInstance::iterate(void)
1117 {
1118     const DeviceInterface &vk = m_context.getDeviceInterface();
1119     const VkDevice vkDevice   = m_context.getDevice();
1120     const VkQueue queue       = m_context.getUniversalQueue();
1121 
1122     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1123 
1124     return verifyImage();
1125 }
1126 
verifyImage(void)1127 tcu::TestStatus UnusedAttachmentTestInstance::verifyImage(void)
1128 {
1129     const DeviceInterface &vk       = m_context.getDeviceInterface();
1130     const VkDevice vkDevice         = m_context.getDevice();
1131     const VkQueue queue             = m_context.getUniversalQueue();
1132     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1133     SimpleAllocator allocator(
1134         vk, vkDevice,
1135         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1136     de::UniquePtr<tcu::TextureLevel> textureLevelResult(
1137         pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage,
1138                                       VK_FORMAT_R8G8B8A8_UNORM, m_renderSize)
1139             .release());
1140     const tcu::ConstPixelBufferAccess &resultAccess = textureLevelResult->getAccess();
1141     de::UniquePtr<tcu::TextureLevel> textureLevelUnused(
1142         pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_unusedImage,
1143                                       VK_FORMAT_R8G8B8A8_UNORM, m_renderSize)
1144             .release());
1145     const tcu::ConstPixelBufferAccess &unusedAccess = textureLevelUnused->getAccess();
1146     tcu::TestLog &log                               = m_context.getTestContext().getLog();
1147     tcu::Vec4 refColor(0.1f, 0.2f, 0.3f, 0.4f);
1148 
1149     // Define helper lambda for checks if color is same as reference
1150     auto isColorValid = [](const tcu::Vec4 &color, const tcu::Vec4 &reference)
1151     { return tcu::boolAll(tcu::lessThan(tcu::absDiff(color, reference), tcu::Vec4(0.01f))); };
1152 
1153     // Log images
1154     log << tcu::TestLog::ImageSet("Result", "Result images")
1155         << tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
1156         << tcu::TestLog::Image("Unused", "Unused image", unusedAccess) << tcu::TestLog::EndImageSet;
1157 
1158     if ((m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) &&
1159         (m_testParams.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR))
1160     {
1161         // With renderpass object there could be attachment that is not listed as color attachment
1162         // for any subpass and in that case it would not be cleared even when op load clear is specified
1163         // in dynamic renderpass load operation will be done for all specified color attachments because we dont
1164         // know at vkCmdBeginRendering which color attachments are going to be used and which will be left unused
1165         if (m_testParams.storeOp == VK_ATTACHMENT_STORE_OP_STORE)
1166             refColor = tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f);
1167         else if (m_testParams.storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE)
1168         {
1169             // Unused attachment was cleared but we dont care if we store it or not and now two colors are valid.
1170             // If color at pixel (0, 0) is not refColor then we also should use clear color for verification.
1171             if (!isColorValid(unusedAccess.getPixel(0, 0), refColor))
1172                 refColor = tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f);
1173         }
1174     }
1175 
1176     // Check the unused image data.
1177     for (int y = 0; y < unusedAccess.getHeight(); y++)
1178         for (int x = 0; x < unusedAccess.getWidth(); x++)
1179         {
1180             if (!isColorValid(unusedAccess.getPixel(x, y), refColor))
1181                 return tcu::TestStatus::fail("Unused image contents has changed.");
1182         }
1183 
1184     // Check for rendered result. Just a quick check to see if correct color is found at the center of the quad.
1185     const tcu::Vec4 resultColor = resultAccess.getPixel(resultAccess.getWidth() / 2, resultAccess.getHeight() / 2);
1186     if (!isColorValid(resultColor, tcu::Vec4(0.4f, 0.6f, 0.2f, 1.0f)))
1187         return tcu::TestStatus::fail("Result image mismatch");
1188 
1189     return tcu::TestStatus::pass("Pass");
1190 }
1191 
loadOpToString(VkAttachmentLoadOp loadOp)1192 std::string loadOpToString(VkAttachmentLoadOp loadOp)
1193 {
1194     switch (loadOp)
1195     {
1196     case VK_ATTACHMENT_LOAD_OP_LOAD:
1197         return "load";
1198     case VK_ATTACHMENT_LOAD_OP_CLEAR:
1199         return "clear";
1200     case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
1201         return "dontcare";
1202     default:
1203         DE_FATAL("unexpected attachment load op");
1204         return "";
1205     }
1206 }
1207 
storeOpToString(VkAttachmentStoreOp storeOp)1208 std::string storeOpToString(VkAttachmentStoreOp storeOp)
1209 {
1210     switch (storeOp)
1211     {
1212     case VK_ATTACHMENT_STORE_OP_STORE:
1213         return "store";
1214     case VK_ATTACHMENT_STORE_OP_DONT_CARE:
1215         return "dontcare";
1216     default:
1217         DE_FATAL("unexpected attachment store op");
1218         return "";
1219     }
1220 }
1221 
1222 } // namespace
1223 
createRenderPassUnusedAttachmentTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1224 tcu::TestCaseGroup *createRenderPassUnusedAttachmentTests(tcu::TestContext &testCtx,
1225                                                           const SharedGroupParams groupParams)
1226 {
1227     // Unused attachment tests
1228     de::MovePtr<tcu::TestCaseGroup> unusedAttTests(new tcu::TestCaseGroup(testCtx, "unused_attachment"));
1229 
1230     const VkAttachmentLoadOp loadOps[] = {VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR,
1231                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE};
1232 
1233     const VkAttachmentStoreOp storeOps[] = {VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_DONT_CARE};
1234 
1235     uint32_t stencilLoadOpStartIdx  = 0;
1236     uint32_t stencilStoreOpStartIdx = 0;
1237     if (groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1238     {
1239         // in dynamic rendering cases we dont_care about stencil load/store
1240         stencilLoadOpStartIdx  = DE_LENGTH_OF_ARRAY(loadOps) - 1;
1241         stencilStoreOpStartIdx = DE_LENGTH_OF_ARRAY(storeOps) - 1;
1242     }
1243 
1244     for (uint32_t loadOpIdx = 0; loadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpIdx++)
1245     {
1246         de::MovePtr<tcu::TestCaseGroup> loadOpGroup(
1247             new tcu::TestCaseGroup(testCtx, (std::string("loadop") + loadOpToString(loadOps[loadOpIdx])).c_str()));
1248 
1249         for (uint32_t storeOpIdx = 0; storeOpIdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpIdx++)
1250         {
1251             // for dynamic rendering we need to skip LOAD_OP_DONT_CARE+STORE_OP_STORE case
1252             // because some implementations in that case will write random data to unused attachments
1253             if ((groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) &&
1254                 (loadOps[loadOpIdx] == VK_ATTACHMENT_LOAD_OP_DONT_CARE) &&
1255                 (storeOps[storeOpIdx] == VK_ATTACHMENT_STORE_OP_STORE))
1256             {
1257                 continue;
1258             }
1259 
1260             de::MovePtr<tcu::TestCaseGroup> storeOpGroup(new tcu::TestCaseGroup(
1261                 testCtx, (std::string("storeop") + storeOpToString(storeOps[storeOpIdx])).c_str()));
1262 
1263             for (uint32_t stencilLoadOpIdx = stencilLoadOpStartIdx; stencilLoadOpIdx < DE_LENGTH_OF_ARRAY(loadOps);
1264                  stencilLoadOpIdx++)
1265             {
1266                 de::MovePtr<tcu::TestCaseGroup> stencilLoadOpGroup(new tcu::TestCaseGroup(
1267                     testCtx, (std::string("stencilloadop") + loadOpToString(loadOps[stencilLoadOpIdx])).c_str()));
1268 
1269                 for (uint32_t stencilStoreOpIdx = stencilStoreOpStartIdx;
1270                      stencilStoreOpIdx < DE_LENGTH_OF_ARRAY(storeOps); stencilStoreOpIdx++)
1271                 {
1272                     TestParams params;
1273                     const std::string testName =
1274                         std::string("stencilstoreop") + storeOpToString(storeOps[stencilStoreOpIdx]);
1275 
1276                     params.loadOp         = loadOps[loadOpIdx];
1277                     params.storeOp        = storeOps[storeOpIdx];
1278                     params.stencilLoadOp  = loadOps[stencilLoadOpIdx];
1279                     params.stencilStoreOp = storeOps[stencilStoreOpIdx];
1280                     params.groupParams    = groupParams;
1281 
1282                     stencilLoadOpGroup->addChild(new UnusedAttachmentTest(testCtx, testName, params));
1283                 }
1284                 storeOpGroup->addChild(stencilLoadOpGroup.release());
1285             }
1286             loadOpGroup->addChild(storeOpGroup.release());
1287         }
1288         unusedAttTests->addChild(loadOpGroup.release());
1289     }
1290 
1291     return unusedAttTests.release();
1292 }
1293 
1294 } // namespace renderpass
1295 } // namespace vkt
1296