xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/renderpass/vktRenderPassTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief RenderPass tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRenderPassTests.hpp"
25 #include "vktRenderPassTestsUtil.hpp"
26 #include "vktRenderPassGroupParams.hpp"
27 #include "vktRenderPassMultisampleTests.hpp"
28 #include "vktRenderPassMultisampleResolveTests.hpp"
29 #include "vktRenderPassSampleReadTests.hpp"
30 #ifndef CTS_USES_VULKANSC
31 #include "vktRenderPassSparseRenderTargetTests.hpp"
32 #endif // CTS_USES_VULKANSC
33 #include "vktRenderPassSubpassDependencyTests.hpp"
34 #include "vktRenderPassUnusedAttachmentTests.hpp"
35 #include "vktRenderPassUnusedClearAttachmentTests.hpp"
36 #include "vktRenderPassDepthStencilResolveTests.hpp"
37 #include "vktRenderPassUnusedAttachmentSparseFillingTests.hpp"
38 #include "vktRenderPassFragmentDensityMapTests.hpp"
39 #include "vktRenderPassMultipleSubpassesMultipleCommandBuffersTests.hpp"
40 #ifndef CTS_USES_VULKANSC
41 #include "vktRenderPassLoadStoreOpNoneTests.hpp"
42 #include "vktDynamicRenderingTests.hpp"
43 #include "vktDynamicRenderingLocalReadTests.hpp"
44 #include "vktDynamicRenderingDepthStencilResolveTests.hpp"
45 #endif // CTS_USES_VULKANSC
46 #include "vktRenderPassDepthStencilWriteConditionsTests.hpp"
47 #include "vktRenderPassSubpassMergeFeedbackTests.hpp"
48 #include "vktDynamicRenderingRandomTests.hpp"
49 #include "vktRenderPassDitheringTests.hpp"
50 #include "vktDynamicRenderingUnusedAttachmentsTests.hpp"
51 
52 #include "vktTestCaseUtil.hpp"
53 #include "vktTestGroupUtil.hpp"
54 
55 #include "vkDefs.hpp"
56 #include "vkDeviceUtil.hpp"
57 #include "vkImageUtil.hpp"
58 #include "vkMemUtil.hpp"
59 #include "vkPlatform.hpp"
60 #include "vkPrograms.hpp"
61 #include "vkQueryUtil.hpp"
62 #include "vkRef.hpp"
63 #include "vkRefUtil.hpp"
64 #include "vkStrUtil.hpp"
65 #include "vkTypeUtil.hpp"
66 #include "vkCmdUtil.hpp"
67 #include "vkObjUtil.hpp"
68 #include "vkBufferWithMemory.hpp"
69 #include "vkImageWithMemory.hpp"
70 #include "vkBarrierUtil.hpp"
71 
72 #include "tcuFloat.hpp"
73 #include "tcuFormatUtil.hpp"
74 #include "tcuMaybe.hpp"
75 #include "tcuResultCollector.hpp"
76 #include "tcuTestLog.hpp"
77 #include "tcuTextureUtil.hpp"
78 #include "tcuVectorUtil.hpp"
79 
80 #include "deRandom.hpp"
81 #include "deSTLUtil.hpp"
82 #include "deSharedPtr.hpp"
83 #include "deStringUtil.hpp"
84 #include "deUniquePtr.hpp"
85 
86 #include <limits>
87 #include <set>
88 #include <string>
89 #include <vector>
90 #include <numeric>
91 #include <memory>
92 #include <algorithm>
93 #include <iterator>
94 
95 using namespace vk;
96 
97 using tcu::BVec4;
98 using tcu::IVec2;
99 using tcu::IVec4;
100 using tcu::UVec2;
101 using tcu::UVec4;
102 using tcu::Vec2;
103 using tcu::Vec4;
104 
105 using tcu::just;
106 using tcu::Maybe;
107 
108 using tcu::ConstPixelBufferAccess;
109 using tcu::PixelBufferAccess;
110 
111 using tcu::TestLog;
112 
113 using de::UniquePtr;
114 
115 using std::pair;
116 using std::set;
117 using std::string;
118 using std::vector;
119 
120 namespace vkt
121 {
122 namespace
123 {
124 using namespace renderpass;
125 
126 typedef vector<uint8_t> DepthValuesArray;
127 
128 static const uint8_t DEPTH_VALUES[] = {0u, 255u, 1u};
129 
getShaderNumChannels(tcu::TextureFormat::ChannelOrder order)130 int getShaderNumChannels(tcu::TextureFormat::ChannelOrder order)
131 {
132     if (order == tcu::TextureFormat::A)
133         return 4;
134     return tcu::getNumUsedChannels(order);
135 }
136 
137 enum AllocationKind
138 {
139     ALLOCATION_KIND_SUBALLOCATED,
140     ALLOCATION_KIND_DEDICATED,
141 };
142 
143 struct TestConfigExternal
144 {
TestConfigExternalvkt::__anon33b72dba0111::TestConfigExternal145     TestConfigExternal(AllocationKind allocationKind_, const SharedGroupParams groupParams_)
146         : allocationKind(allocationKind_)
147         , groupParams(groupParams_)
148     {
149     }
150 
151     AllocationKind allocationKind;
152     const SharedGroupParams groupParams;
153 };
154 
allocateBuffer(const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice & physDevice,const VkDevice device,const VkBuffer & buffer,const MemoryRequirement requirement,Allocator & allocator,AllocationKind allocationKind)155 de::MovePtr<Allocation> allocateBuffer(const InstanceInterface &vki, const DeviceInterface &vkd,
156                                        const VkPhysicalDevice &physDevice, const VkDevice device,
157                                        const VkBuffer &buffer, const MemoryRequirement requirement,
158                                        Allocator &allocator, AllocationKind allocationKind)
159 {
160     switch (allocationKind)
161     {
162     case ALLOCATION_KIND_SUBALLOCATED:
163     {
164         const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer);
165 
166         return allocator.allocate(memoryRequirements, requirement);
167     }
168 
169     case ALLOCATION_KIND_DEDICATED:
170     {
171         return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
172     }
173 
174     default:
175     {
176         TCU_THROW(InternalError, "Invalid allocation kind");
177     }
178     }
179 }
180 
allocateImage(const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice & physDevice,const VkDevice device,const VkImage & image,const MemoryRequirement requirement,Allocator & allocator,AllocationKind allocationKind)181 de::MovePtr<Allocation> allocateImage(const InstanceInterface &vki, const DeviceInterface &vkd,
182                                       const VkPhysicalDevice &physDevice, const VkDevice device, const VkImage &image,
183                                       const MemoryRequirement requirement, Allocator &allocator,
184                                       AllocationKind allocationKind)
185 {
186     switch (allocationKind)
187     {
188     case ALLOCATION_KIND_SUBALLOCATED:
189     {
190         const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image);
191 
192         return allocator.allocate(memoryRequirements, requirement);
193     }
194 
195     case ALLOCATION_KIND_DEDICATED:
196     {
197         return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
198     }
199 
200     default:
201     {
202         TCU_THROW(InternalError, "Invalid allocation kind");
203     }
204     }
205 }
206 
207 enum BoolOp
208 {
209     BOOLOP_AND,
210     BOOLOP_OR,
211     BOOLOP_EQ,
212     BOOLOP_NEQ
213 };
214 
boolOpToString(BoolOp op)215 const char *boolOpToString(BoolOp op)
216 {
217     switch (op)
218     {
219     case BOOLOP_OR:
220         return "||";
221 
222     case BOOLOP_AND:
223         return "&&";
224 
225     case BOOLOP_EQ:
226         return "==";
227 
228     case BOOLOP_NEQ:
229         return "!=";
230 
231     default:
232         DE_FATAL("Unknown boolean operation.");
233         return DE_NULL;
234     }
235 }
236 
performBoolOp(BoolOp op,bool a,bool b)237 bool performBoolOp(BoolOp op, bool a, bool b)
238 {
239     switch (op)
240     {
241     case BOOLOP_OR:
242         return a || b;
243 
244     case BOOLOP_AND:
245         return a && b;
246 
247     case BOOLOP_EQ:
248         return a == b;
249 
250     case BOOLOP_NEQ:
251         return a != b;
252 
253     default:
254         DE_FATAL("Unknown boolean operation.");
255         return false;
256     }
257 }
258 
boolOpFromIndex(size_t index)259 BoolOp boolOpFromIndex(size_t index)
260 {
261     const BoolOp ops[] = {BOOLOP_OR, BOOLOP_AND, BOOLOP_EQ, BOOLOP_NEQ};
262 
263     return ops[index % DE_LENGTH_OF_ARRAY(ops)];
264 }
265 
requiredDepthEpsilon(VkFormat format)266 static float requiredDepthEpsilon(VkFormat format)
267 {
268     // Possible precision loss in the unorm depth pipeline means that we need to check depths
269     // that go in and back out of the depth buffer with an epsilon rather than an exact match
270     uint32_t unormBits = 0;
271 
272     switch (format)
273     {
274     case VK_FORMAT_D16_UNORM:
275         unormBits = 16;
276         break;
277     case VK_FORMAT_X8_D24_UNORM_PACK32:
278     case VK_FORMAT_D24_UNORM_S8_UINT:
279         unormBits = 24;
280         break;
281     case VK_FORMAT_D32_SFLOAT:
282     case VK_FORMAT_D32_SFLOAT_S8_UINT:
283     default:
284         unormBits = 0;
285         break;
286     }
287 
288     if (unormBits > 0)
289         return 1.0f / (float)((1 << unormBits) - 1);
290 
291     return 0.0f; // Require exact match
292 }
293 
depthsEqual(float a,float b,float epsilon)294 static bool depthsEqual(float a, float b, float epsilon)
295 {
296     return fabs(a - b) <= epsilon;
297 }
298 
createFramebuffer(const DeviceInterface & vk,VkDevice device,VkFramebufferCreateFlags pCreateInfo_flags,VkRenderPass pCreateInfo_renderPass,uint32_t pCreateInfo_attachmentCount,const VkImageView * pCreateInfo_pAttachments,uint32_t pCreateInfo_width,uint32_t pCreateInfo_height,uint32_t pCreateInfo_layers)299 Move<VkFramebuffer> createFramebuffer(const DeviceInterface &vk, VkDevice device,
300                                       VkFramebufferCreateFlags pCreateInfo_flags, VkRenderPass pCreateInfo_renderPass,
301                                       uint32_t pCreateInfo_attachmentCount, const VkImageView *pCreateInfo_pAttachments,
302                                       uint32_t pCreateInfo_width, uint32_t pCreateInfo_height,
303                                       uint32_t pCreateInfo_layers)
304 {
305     const VkFramebufferCreateInfo pCreateInfo = {
306         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
307         DE_NULL,
308         pCreateInfo_flags,
309         pCreateInfo_renderPass,
310         pCreateInfo_attachmentCount,
311         pCreateInfo_pAttachments,
312         pCreateInfo_width,
313         pCreateInfo_height,
314         pCreateInfo_layers,
315     };
316     return createFramebuffer(vk, device, &pCreateInfo);
317 }
318 
createImage(const DeviceInterface & vk,VkDevice device,VkImageCreateFlags pCreateInfo_flags,VkImageType pCreateInfo_imageType,VkFormat pCreateInfo_format,VkExtent3D pCreateInfo_extent,uint32_t pCreateInfo_mipLevels,uint32_t pCreateInfo_arrayLayers,VkSampleCountFlagBits pCreateInfo_samples,VkImageTiling pCreateInfo_tiling,VkImageUsageFlags pCreateInfo_usage,VkSharingMode pCreateInfo_sharingMode,uint32_t pCreateInfo_queueFamilyCount,const uint32_t * pCreateInfo_pQueueFamilyIndices,VkImageLayout pCreateInfo_initialLayout)319 Move<VkImage> createImage(const DeviceInterface &vk, VkDevice device, VkImageCreateFlags pCreateInfo_flags,
320                           VkImageType pCreateInfo_imageType, VkFormat pCreateInfo_format, VkExtent3D pCreateInfo_extent,
321                           uint32_t pCreateInfo_mipLevels, uint32_t pCreateInfo_arrayLayers,
322                           VkSampleCountFlagBits pCreateInfo_samples, VkImageTiling pCreateInfo_tiling,
323                           VkImageUsageFlags pCreateInfo_usage, VkSharingMode pCreateInfo_sharingMode,
324                           uint32_t pCreateInfo_queueFamilyCount, const uint32_t *pCreateInfo_pQueueFamilyIndices,
325                           VkImageLayout pCreateInfo_initialLayout)
326 {
327     const VkImageCreateInfo pCreateInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
328                                            DE_NULL,
329                                            pCreateInfo_flags,
330                                            pCreateInfo_imageType,
331                                            pCreateInfo_format,
332                                            pCreateInfo_extent,
333                                            pCreateInfo_mipLevels,
334                                            pCreateInfo_arrayLayers,
335                                            pCreateInfo_samples,
336                                            pCreateInfo_tiling,
337                                            pCreateInfo_usage,
338                                            pCreateInfo_sharingMode,
339                                            pCreateInfo_queueFamilyCount,
340                                            pCreateInfo_pQueueFamilyIndices,
341                                            pCreateInfo_initialLayout};
342     return createImage(vk, device, &pCreateInfo);
343 }
344 
bindBufferMemory(const DeviceInterface & vk,VkDevice device,VkBuffer buffer,VkDeviceMemory mem,VkDeviceSize memOffset)345 void bindBufferMemory(const DeviceInterface &vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem,
346                       VkDeviceSize memOffset)
347 {
348     VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
349 }
350 
bindImageMemory(const DeviceInterface & vk,VkDevice device,VkImage image,VkDeviceMemory mem,VkDeviceSize memOffset)351 void bindImageMemory(const DeviceInterface &vk, VkDevice device, VkImage image, VkDeviceMemory mem,
352                      VkDeviceSize memOffset)
353 {
354     VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
355 }
356 
createImageView(const DeviceInterface & vk,VkDevice device,VkImageViewCreateFlags pCreateInfo_flags,VkImage pCreateInfo_image,VkImageViewType pCreateInfo_viewType,VkFormat pCreateInfo_format,VkComponentMapping pCreateInfo_components,VkImageSubresourceRange pCreateInfo_subresourceRange)357 Move<VkImageView> createImageView(const DeviceInterface &vk, VkDevice device, VkImageViewCreateFlags pCreateInfo_flags,
358                                   VkImage pCreateInfo_image, VkImageViewType pCreateInfo_viewType,
359                                   VkFormat pCreateInfo_format, VkComponentMapping pCreateInfo_components,
360                                   VkImageSubresourceRange pCreateInfo_subresourceRange)
361 {
362     const VkImageViewCreateInfo pCreateInfo = {
363         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
364         DE_NULL,
365         pCreateInfo_flags,
366         pCreateInfo_image,
367         pCreateInfo_viewType,
368         pCreateInfo_format,
369         pCreateInfo_components,
370         pCreateInfo_subresourceRange,
371     };
372     return createImageView(vk, device, &pCreateInfo);
373 }
374 
createBuffer(const DeviceInterface & vk,VkDevice device,VkBufferCreateFlags pCreateInfo_flags,VkDeviceSize pCreateInfo_size,VkBufferUsageFlags pCreateInfo_usage,VkSharingMode pCreateInfo_sharingMode,uint32_t pCreateInfo_queueFamilyCount,const uint32_t * pCreateInfo_pQueueFamilyIndices)375 Move<VkBuffer> createBuffer(const DeviceInterface &vk, VkDevice device, VkBufferCreateFlags pCreateInfo_flags,
376                             VkDeviceSize pCreateInfo_size, VkBufferUsageFlags pCreateInfo_usage,
377                             VkSharingMode pCreateInfo_sharingMode, uint32_t pCreateInfo_queueFamilyCount,
378                             const uint32_t *pCreateInfo_pQueueFamilyIndices)
379 {
380     const VkBufferCreateInfo pCreateInfo = {
381         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
382         DE_NULL,
383         pCreateInfo_flags,
384         pCreateInfo_size,
385         pCreateInfo_usage,
386         pCreateInfo_sharingMode,
387         pCreateInfo_queueFamilyCount,
388         pCreateInfo_pQueueFamilyIndices,
389     };
390     return createBuffer(vk, device, &pCreateInfo);
391 }
392 
createRenderPassBeginInfo(VkRenderPass pRenderPassBegin_renderPass,VkFramebuffer pRenderPassBegin_framebuffer,VkRect2D pRenderPassBegin_renderArea,uint32_t pRenderPassBegin_clearValueCount,const VkClearValue * pRenderPassBegin_pAttachmentClearValues)393 VkRenderPassBeginInfo createRenderPassBeginInfo(VkRenderPass pRenderPassBegin_renderPass,
394                                                 VkFramebuffer pRenderPassBegin_framebuffer,
395                                                 VkRect2D pRenderPassBegin_renderArea,
396                                                 uint32_t pRenderPassBegin_clearValueCount,
397                                                 const VkClearValue *pRenderPassBegin_pAttachmentClearValues)
398 {
399     const VkRenderPassBeginInfo renderPassBeginInfo = {
400         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
401         DE_NULL,
402         pRenderPassBegin_renderPass,
403         pRenderPassBegin_framebuffer,
404         pRenderPassBegin_renderArea,
405         pRenderPassBegin_clearValueCount,
406         pRenderPassBegin_pAttachmentClearValues,
407     };
408 
409     return renderPassBeginInfo;
410 }
411 
queueSubmit(const DeviceInterface & vk,VkQueue queue,uint32_t cmdBufferCount,const VkCommandBuffer * pCmdBuffers,VkFence fence)412 void queueSubmit(const DeviceInterface &vk, VkQueue queue, uint32_t cmdBufferCount, const VkCommandBuffer *pCmdBuffers,
413                  VkFence fence)
414 {
415     const VkSubmitInfo submitInfo = {
416         VK_STRUCTURE_TYPE_SUBMIT_INFO,
417         DE_NULL,
418         0u,                           // waitSemaphoreCount
419         (const VkSemaphore *)DE_NULL, // pWaitSemaphores
420         (const VkPipelineStageFlags *)DE_NULL,
421         cmdBufferCount, // commandBufferCount
422         pCmdBuffers,
423         0u,                           // signalSemaphoreCount
424         (const VkSemaphore *)DE_NULL, // pSignalSemaphores
425     };
426     VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence));
427 }
428 
waitForFences(const DeviceInterface & vk,VkDevice device,uint32_t fenceCount,const VkFence * pFences,VkBool32 waitAll,uint64_t timeout)429 void waitForFences(const DeviceInterface &vk, VkDevice device, uint32_t fenceCount, const VkFence *pFences,
430                    VkBool32 waitAll, uint64_t timeout)
431 {
432     VK_CHECK(vk.waitForFences(device, fenceCount, pFences, waitAll, timeout));
433 }
434 
getImageAspectFlags(VkFormat vkFormat)435 VkImageAspectFlags getImageAspectFlags(VkFormat vkFormat)
436 {
437     const tcu::TextureFormat format = mapVkFormat(vkFormat);
438 
439     DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 22);
440 
441     switch (format.order)
442     {
443     case tcu::TextureFormat::DS:
444         return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
445 
446     case tcu::TextureFormat::D:
447         return VK_IMAGE_ASPECT_DEPTH_BIT;
448 
449     case tcu::TextureFormat::S:
450         return VK_IMAGE_ASPECT_STENCIL_BIT;
451 
452     default:
453         return VK_IMAGE_ASPECT_COLOR_BIT;
454     }
455 }
456 
getAllMemoryReadFlags(void)457 VkAccessFlags getAllMemoryReadFlags(void)
458 {
459     return VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_HOST_READ_BIT |
460            VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
461            VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
462            VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
463 }
464 
getAllMemoryWriteFlags(void)465 VkAccessFlags getAllMemoryWriteFlags(void)
466 {
467     return VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT |
468            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
469 }
470 
getMemoryFlagsForLayout(const VkImageLayout layout)471 VkAccessFlags getMemoryFlagsForLayout(const VkImageLayout layout)
472 {
473     switch (layout)
474     {
475     case VK_IMAGE_LAYOUT_GENERAL:
476         return getAllMemoryReadFlags() | getAllMemoryWriteFlags();
477     case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
478         return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
479     case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
480         return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
481     case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
482         return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
483     case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
484         return VK_ACCESS_SHADER_READ_BIT;
485     case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
486         return VK_ACCESS_TRANSFER_READ_BIT;
487     case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
488         return VK_ACCESS_TRANSFER_WRITE_BIT;
489     case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
490         return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
491                VK_ACCESS_SHADER_READ_BIT;
492     case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
493         return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
494                VK_ACCESS_SHADER_READ_BIT;
495     default:
496         return (VkAccessFlags)0;
497     }
498 }
499 
getAllPipelineStageFlags(void)500 VkPipelineStageFlags getAllPipelineStageFlags(void)
501 {
502     /* All relevant flags for a pipeline containing VS+PS. */
503     return VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
504            VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
505            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
506            VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
507            VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_HOST_BIT;
508 }
509 
510 class AttachmentReference
511 {
512 public:
AttachmentReference(uint32_t attachment,VkImageLayout layout,VkImageAspectFlags aspectMask=static_cast<VkImageAspectFlags> (0u))513     AttachmentReference(uint32_t attachment, VkImageLayout layout,
514                         VkImageAspectFlags aspectMask = static_cast<VkImageAspectFlags>(0u))
515         : m_attachment(attachment)
516         , m_layout(layout)
517         , m_aspectMask(aspectMask)
518     {
519     }
520 
getAttachment(void) const521     uint32_t getAttachment(void) const
522     {
523         return m_attachment;
524     }
getImageLayout(void) const525     VkImageLayout getImageLayout(void) const
526     {
527         return m_layout;
528     }
getAspectMask(void) const529     VkImageAspectFlags getAspectMask(void) const
530     {
531         return m_aspectMask;
532     }
setImageLayout(VkImageLayout layout)533     void setImageLayout(VkImageLayout layout)
534     {
535         m_layout = layout;
536     }
537 
538 private:
539     uint32_t m_attachment;
540     VkImageLayout m_layout;
541     VkImageAspectFlags m_aspectMask;
542 };
543 
544 class Subpass
545 {
546 public:
Subpass(VkPipelineBindPoint pipelineBindPoint,VkSubpassDescriptionFlags flags,const vector<AttachmentReference> & inputAttachments,const vector<AttachmentReference> & colorAttachments,const vector<AttachmentReference> & resolveAttachments,AttachmentReference depthStencilAttachment,const vector<uint32_t> & preserveAttachments,bool omitBlendState=false)547     Subpass(VkPipelineBindPoint pipelineBindPoint, VkSubpassDescriptionFlags flags,
548             const vector<AttachmentReference> &inputAttachments, const vector<AttachmentReference> &colorAttachments,
549             const vector<AttachmentReference> &resolveAttachments, AttachmentReference depthStencilAttachment,
550             const vector<uint32_t> &preserveAttachments, bool omitBlendState = false)
551         : m_pipelineBindPoint(pipelineBindPoint)
552         , m_flags(flags)
553         , m_inputAttachments(inputAttachments)
554         , m_colorAttachments(colorAttachments)
555         , m_resolveAttachments(resolveAttachments)
556         , m_depthStencilAttachment(depthStencilAttachment)
557         , m_preserveAttachments(preserveAttachments)
558         , m_omitBlendState(omitBlendState)
559     {
560     }
561 
getPipelineBindPoint(void) const562     VkPipelineBindPoint getPipelineBindPoint(void) const
563     {
564         return m_pipelineBindPoint;
565     }
getFlags(void) const566     VkSubpassDescriptionFlags getFlags(void) const
567     {
568         return m_flags;
569     }
getInputAttachments(void) const570     const vector<AttachmentReference> &getInputAttachments(void) const
571     {
572         return m_inputAttachments;
573     }
getColorAttachments(void) const574     const vector<AttachmentReference> &getColorAttachments(void) const
575     {
576         return m_colorAttachments;
577     }
getResolveAttachments(void) const578     const vector<AttachmentReference> &getResolveAttachments(void) const
579     {
580         return m_resolveAttachments;
581     }
getDepthStencilAttachment(void) const582     const AttachmentReference &getDepthStencilAttachment(void) const
583     {
584         return m_depthStencilAttachment;
585     }
getPreserveAttachments(void) const586     const vector<uint32_t> &getPreserveAttachments(void) const
587     {
588         return m_preserveAttachments;
589     }
getOmitBlendState(void) const590     bool getOmitBlendState(void) const
591     {
592         return m_omitBlendState;
593     }
594 
595 private:
596     VkPipelineBindPoint m_pipelineBindPoint;
597     VkSubpassDescriptionFlags m_flags;
598 
599     vector<AttachmentReference> m_inputAttachments;
600     vector<AttachmentReference> m_colorAttachments;
601     vector<AttachmentReference> m_resolveAttachments;
602     AttachmentReference m_depthStencilAttachment;
603 
604     vector<uint32_t> m_preserveAttachments;
605     bool m_omitBlendState;
606 };
607 
608 class SubpassDependency
609 {
610 public:
SubpassDependency(uint32_t srcPass,uint32_t dstPass,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags srcAccessMask,VkAccessFlags dstAccessMask,VkDependencyFlags flags)611     SubpassDependency(uint32_t srcPass, uint32_t dstPass,
612 
613                       VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
614 
615                       VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
616 
617                       VkDependencyFlags flags)
618         : m_srcPass(srcPass)
619         , m_dstPass(dstPass)
620 
621         , m_srcStageMask(srcStageMask)
622         , m_dstStageMask(dstStageMask)
623 
624         , m_srcAccessMask(srcAccessMask)
625         , m_dstAccessMask(dstAccessMask)
626         , m_flags(flags)
627     {
628     }
629 
getSrcPass(void) const630     uint32_t getSrcPass(void) const
631     {
632         return m_srcPass;
633     }
getDstPass(void) const634     uint32_t getDstPass(void) const
635     {
636         return m_dstPass;
637     }
638 
getSrcStageMask(void) const639     VkPipelineStageFlags getSrcStageMask(void) const
640     {
641         return m_srcStageMask;
642     }
getDstStageMask(void) const643     VkPipelineStageFlags getDstStageMask(void) const
644     {
645         return m_dstStageMask;
646     }
647 
getSrcAccessMask(void) const648     VkAccessFlags getSrcAccessMask(void) const
649     {
650         return m_srcAccessMask;
651     }
getDstAccessMask(void) const652     VkAccessFlags getDstAccessMask(void) const
653     {
654         return m_dstAccessMask;
655     }
656 
getFlags(void) const657     VkDependencyFlags getFlags(void) const
658     {
659         return m_flags;
660     }
661 
setSrcAccessMask(const VkAccessFlags & flags)662     void setSrcAccessMask(const VkAccessFlags &flags)
663     {
664         m_srcAccessMask = flags;
665     }
setDstAccessMask(const VkAccessFlags & flags)666     void setDstAccessMask(const VkAccessFlags &flags)
667     {
668         m_dstAccessMask = flags;
669     }
670 
671 private:
672     uint32_t m_srcPass;
673     uint32_t m_dstPass;
674 
675     VkPipelineStageFlags m_srcStageMask;
676     VkPipelineStageFlags m_dstStageMask;
677 
678     VkAccessFlags m_srcAccessMask;
679     VkAccessFlags m_dstAccessMask;
680     VkDependencyFlags m_flags;
681 };
682 
683 class Attachment
684 {
685 public:
Attachment(VkFormat format,VkSampleCountFlagBits samples,VkAttachmentLoadOp loadOp,VkAttachmentStoreOp storeOp,VkAttachmentLoadOp stencilLoadOp,VkAttachmentStoreOp stencilStoreOp,VkImageLayout initialLayout,VkImageLayout finalLayout)686     Attachment(VkFormat format, VkSampleCountFlagBits samples,
687 
688                VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp,
689 
690                VkAttachmentLoadOp stencilLoadOp, VkAttachmentStoreOp stencilStoreOp,
691 
692                VkImageLayout initialLayout, VkImageLayout finalLayout)
693         : m_format(format)
694         , m_samples(samples)
695 
696         , m_loadOp(loadOp)
697         , m_storeOp(storeOp)
698 
699         , m_stencilLoadOp(stencilLoadOp)
700         , m_stencilStoreOp(stencilStoreOp)
701 
702         , m_initialLayout(initialLayout)
703         , m_finalLayout(finalLayout)
704     {
705     }
706 
getFormat(void) const707     VkFormat getFormat(void) const
708     {
709         return m_format;
710     }
getSamples(void) const711     VkSampleCountFlagBits getSamples(void) const
712     {
713         return m_samples;
714     }
715 
getLoadOp(void) const716     VkAttachmentLoadOp getLoadOp(void) const
717     {
718         return m_loadOp;
719     }
getStoreOp(void) const720     VkAttachmentStoreOp getStoreOp(void) const
721     {
722         return m_storeOp;
723     }
724 
getStencilLoadOp(void) const725     VkAttachmentLoadOp getStencilLoadOp(void) const
726     {
727         return m_stencilLoadOp;
728     }
getStencilStoreOp(void) const729     VkAttachmentStoreOp getStencilStoreOp(void) const
730     {
731         return m_stencilStoreOp;
732     }
733 
getInitialLayout(void) const734     VkImageLayout getInitialLayout(void) const
735     {
736         return m_initialLayout;
737     }
getFinalLayout(void) const738     VkImageLayout getFinalLayout(void) const
739     {
740         return m_finalLayout;
741     }
742 
743 private:
744     VkFormat m_format;
745     VkSampleCountFlagBits m_samples;
746 
747     VkAttachmentLoadOp m_loadOp;
748     VkAttachmentStoreOp m_storeOp;
749 
750     VkAttachmentLoadOp m_stencilLoadOp;
751     VkAttachmentStoreOp m_stencilStoreOp;
752 
753     VkImageLayout m_initialLayout;
754     VkImageLayout m_finalLayout;
755 };
756 
757 class RenderPass
758 {
759 public:
RenderPass(const vector<Attachment> & attachments,const vector<Subpass> & subpasses,const vector<SubpassDependency> & dependencies,const vector<VkInputAttachmentAspectReference> inputAspects=vector<VkInputAttachmentAspectReference> ())760     RenderPass(const vector<Attachment> &attachments, const vector<Subpass> &subpasses,
761                const vector<SubpassDependency> &dependencies,
762                const vector<VkInputAttachmentAspectReference> inputAspects = vector<VkInputAttachmentAspectReference>())
763         : m_attachments(attachments)
764         , m_subpasses(subpasses)
765         , m_dependencies(dependencies)
766         , m_inputAspects(inputAspects)
767     {
768     }
769 
getAttachments(void) const770     const vector<Attachment> &getAttachments(void) const
771     {
772         return m_attachments;
773     }
getSubpasses(void) const774     const vector<Subpass> &getSubpasses(void) const
775     {
776         return m_subpasses;
777     }
getDependencies(void) const778     const vector<SubpassDependency> &getDependencies(void) const
779     {
780         return m_dependencies;
781     }
getInputAspects(void) const782     const vector<VkInputAttachmentAspectReference> &getInputAspects(void) const
783     {
784         return m_inputAspects;
785     }
786 
787 private:
788     const vector<Attachment> m_attachments;
789     const vector<Subpass> m_subpasses;
790     const vector<SubpassDependency> m_dependencies;
791     const vector<VkInputAttachmentAspectReference> m_inputAspects;
792 };
793 
794 struct TestConfig
795 {
796     enum RenderTypes
797     {
798         RENDERTYPES_NONE  = 0,
799         RENDERTYPES_CLEAR = (1 << 1),
800         RENDERTYPES_DRAW  = (1 << 2)
801     };
802 
803     enum CommandBufferTypes
804     {
805         COMMANDBUFFERTYPES_INLINE    = (1 << 0),
806         COMMANDBUFFERTYPES_SECONDARY = (1 << 1)
807     };
808 
809     enum ImageMemory
810     {
811         IMAGEMEMORY_STRICT = (1 << 0),
812         IMAGEMEMORY_LAZY   = (1 << 1)
813     };
814 
TestConfigvkt::__anon33b72dba0111::TestConfig815     TestConfig(const RenderPass &renderPass_, RenderTypes renderTypes_, CommandBufferTypes commandBufferTypes_,
816                ImageMemory imageMemory_, const UVec2 &targetSize_, const UVec2 &renderPos_, const UVec2 &renderSize_,
817                bool useFormatCompCount_, uint32_t seed_, uint32_t drawStartNdx_, AllocationKind allocationKind_,
818                SharedGroupParams groupParams_,
819                vector<DeviceCoreFeature> requiredFeatures_ = vector<DeviceCoreFeature>())
820         : renderPass(renderPass_)
821         , renderTypes(renderTypes_)
822         , commandBufferTypes(commandBufferTypes_)
823         , imageMemory(imageMemory_)
824         , targetSize(targetSize_)
825         , renderPos(renderPos_)
826         , renderSize(renderSize_)
827         , useFormatCompCount(useFormatCompCount_)
828         , seed(seed_)
829         , drawStartNdx(drawStartNdx_)
830         , allocationKind(allocationKind_)
831         , groupParams(groupParams_)
832         , requiredFeatures(requiredFeatures_)
833     {
834         DepthValuesArray shuffledDepthValues(&DEPTH_VALUES[0], &DEPTH_VALUES[DE_LENGTH_OF_ARRAY(DEPTH_VALUES)]);
835         de::Random rng(seed + 1);
836 
837         rng.shuffle(shuffledDepthValues.begin(), shuffledDepthValues.end());
838 
839         depthValues.push_back(shuffledDepthValues[0]);
840         depthValues.push_back(shuffledDepthValues[1]);
841     }
842 
843     RenderPass renderPass;
844     RenderTypes renderTypes;
845     CommandBufferTypes commandBufferTypes;
846     ImageMemory imageMemory;
847     UVec2 targetSize;
848     UVec2 renderPos;
849     UVec2 renderSize;
850     bool useFormatCompCount;
851     uint32_t seed;
852     uint32_t drawStartNdx;
853     AllocationKind allocationKind;
854     SharedGroupParams groupParams;
855     vector<DeviceCoreFeature> requiredFeatures;
856     DepthValuesArray depthValues;
857 };
858 
operator |(TestConfig::RenderTypes a,TestConfig::RenderTypes b)859 TestConfig::RenderTypes operator|(TestConfig::RenderTypes a, TestConfig::RenderTypes b)
860 {
861     return (TestConfig::RenderTypes)(((uint32_t)a) | ((uint32_t)b));
862 }
863 
operator |(TestConfig::CommandBufferTypes a,TestConfig::CommandBufferTypes b)864 TestConfig::CommandBufferTypes operator|(TestConfig::CommandBufferTypes a, TestConfig::CommandBufferTypes b)
865 {
866     return (TestConfig::CommandBufferTypes)(((uint32_t)a) | ((uint32_t)b));
867 }
868 
operator |(TestConfig::ImageMemory a,TestConfig::ImageMemory b)869 TestConfig::ImageMemory operator|(TestConfig::ImageMemory a, TestConfig::ImageMemory b)
870 {
871     return (TestConfig::ImageMemory)(((uint32_t)a) | ((uint32_t)b));
872 }
873 
checkSupport(Context & context,TestConfig config)874 void checkSupport(Context &context, TestConfig config)
875 {
876     for (size_t featureNdx = 0; featureNdx < config.requiredFeatures.size(); featureNdx++)
877         context.requireDeviceCoreFeature(config.requiredFeatures[featureNdx]);
878 }
879 
logRenderPassInfo(TestLog & log,const RenderPass & renderPass)880 void logRenderPassInfo(TestLog &log, const RenderPass &renderPass)
881 {
882     const bool useExternalInputAspect = !renderPass.getInputAspects().empty();
883     const tcu::ScopedLogSection section(log, "RenderPass", "RenderPass");
884 
885     {
886         const tcu::ScopedLogSection attachmentsSection(log, "Attachments", "Attachments");
887         const vector<Attachment> &attachments = renderPass.getAttachments();
888 
889         for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
890         {
891             const tcu::ScopedLogSection attachmentSection(log, "Attachment" + de::toString(attachmentNdx),
892                                                           "Attachment " + de::toString(attachmentNdx));
893             const Attachment &attachment = attachments[attachmentNdx];
894 
895             log << TestLog::Message << "Format: " << attachment.getFormat() << TestLog::EndMessage;
896             log << TestLog::Message << "Samples: " << attachment.getSamples() << TestLog::EndMessage;
897 
898             log << TestLog::Message << "LoadOp: " << attachment.getLoadOp() << TestLog::EndMessage;
899             log << TestLog::Message << "StoreOp: " << attachment.getStoreOp() << TestLog::EndMessage;
900 
901             log << TestLog::Message << "StencilLoadOp: " << attachment.getStencilLoadOp() << TestLog::EndMessage;
902             log << TestLog::Message << "StencilStoreOp: " << attachment.getStencilStoreOp() << TestLog::EndMessage;
903 
904             log << TestLog::Message << "InitialLayout: " << attachment.getInitialLayout() << TestLog::EndMessage;
905             log << TestLog::Message << "FinalLayout: " << attachment.getFinalLayout() << TestLog::EndMessage;
906         }
907     }
908 
909     if (useExternalInputAspect)
910     {
911         const tcu::ScopedLogSection inputAspectSection(log, "InputAspects", "InputAspects");
912 
913         for (size_t aspectNdx = 0; aspectNdx < renderPass.getInputAspects().size(); aspectNdx++)
914         {
915             const VkInputAttachmentAspectReference &inputAspect(renderPass.getInputAspects()[aspectNdx]);
916 
917             log << TestLog::Message << "Subpass: " << inputAspect.subpass << TestLog::EndMessage;
918             log << TestLog::Message << "InputAttachmentIndex: " << inputAspect.inputAttachmentIndex
919                 << TestLog::EndMessage;
920             log << TestLog::Message << "AspectFlags: " << getImageAspectFlagsStr(inputAspect.aspectMask)
921                 << TestLog::EndMessage;
922         }
923     }
924 
925     {
926         const tcu::ScopedLogSection subpassesSection(log, "Subpasses", "Subpasses");
927         const vector<Subpass> &subpasses = renderPass.getSubpasses();
928 
929         for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
930         {
931             const tcu::ScopedLogSection subpassSection(log, "Subpass" + de::toString(subpassNdx),
932                                                        "Subpass " + de::toString(subpassNdx));
933             const Subpass &subpass = subpasses[subpassNdx];
934 
935             const vector<AttachmentReference> &inputAttachments   = subpass.getInputAttachments();
936             const vector<AttachmentReference> &colorAttachments   = subpass.getColorAttachments();
937             const vector<AttachmentReference> &resolveAttachments = subpass.getResolveAttachments();
938             const vector<uint32_t> &preserveAttachments           = subpass.getPreserveAttachments();
939 
940             if (!inputAttachments.empty())
941             {
942                 const tcu::ScopedLogSection inputAttachmentsSection(log, "Inputs", "Inputs");
943 
944                 for (size_t inputNdx = 0; inputNdx < inputAttachments.size(); inputNdx++)
945                 {
946                     const tcu::ScopedLogSection inputAttachmentSection(log, "Input" + de::toString(inputNdx),
947                                                                        "Input " + de::toString(inputNdx));
948                     const AttachmentReference &inputAttachment = inputAttachments[inputNdx];
949 
950                     log << TestLog::Message << "Attachment: " << inputAttachment.getAttachment() << TestLog::EndMessage;
951                     log << TestLog::Message << "Layout: " << inputAttachment.getImageLayout() << TestLog::EndMessage;
952                     if (!useExternalInputAspect)
953                         log << TestLog::Message << "AspectMask: " << inputAttachment.getAspectMask()
954                             << TestLog::EndMessage;
955                 }
956             }
957 
958             if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
959             {
960                 const tcu::ScopedLogSection depthStencilAttachmentSection(log, "DepthStencil", "DepthStencil");
961                 const AttachmentReference &depthStencilAttachment = subpass.getDepthStencilAttachment();
962 
963                 log << TestLog::Message << "Attachment: " << depthStencilAttachment.getAttachment()
964                     << TestLog::EndMessage;
965                 log << TestLog::Message << "Layout: " << depthStencilAttachment.getImageLayout() << TestLog::EndMessage;
966             }
967 
968             if (!colorAttachments.empty())
969             {
970                 const tcu::ScopedLogSection colorAttachmentsSection(log, "Colors", "Colors");
971 
972                 for (size_t colorNdx = 0; colorNdx < colorAttachments.size(); colorNdx++)
973                 {
974                     const tcu::ScopedLogSection colorAttachmentSection(log, "Color" + de::toString(colorNdx),
975                                                                        "Color " + de::toString(colorNdx));
976                     const AttachmentReference &colorAttachment = colorAttachments[colorNdx];
977 
978                     log << TestLog::Message << "Attachment: " << colorAttachment.getAttachment() << TestLog::EndMessage;
979                     log << TestLog::Message << "Layout: " << colorAttachment.getImageLayout() << TestLog::EndMessage;
980                 }
981             }
982 
983             if (!resolveAttachments.empty())
984             {
985                 const tcu::ScopedLogSection resolveAttachmentsSection(log, "Resolves", "Resolves");
986 
987                 for (size_t resolveNdx = 0; resolveNdx < resolveAttachments.size(); resolveNdx++)
988                 {
989                     const tcu::ScopedLogSection resolveAttachmentSection(log, "Resolve" + de::toString(resolveNdx),
990                                                                          "Resolve " + de::toString(resolveNdx));
991                     const AttachmentReference &resolveAttachment = resolveAttachments[resolveNdx];
992 
993                     log << TestLog::Message << "Attachment: " << resolveAttachment.getAttachment()
994                         << TestLog::EndMessage;
995                     log << TestLog::Message << "Layout: " << resolveAttachment.getImageLayout() << TestLog::EndMessage;
996                 }
997             }
998 
999             if (!preserveAttachments.empty())
1000             {
1001                 const tcu::ScopedLogSection preserveAttachmentsSection(log, "Preserves", "Preserves");
1002 
1003                 for (size_t preserveNdx = 0; preserveNdx < preserveAttachments.size(); preserveNdx++)
1004                 {
1005                     const tcu::ScopedLogSection preserveAttachmentSection(log, "Preserve" + de::toString(preserveNdx),
1006                                                                           "Preserve " + de::toString(preserveNdx));
1007                     const uint32_t preserveAttachment = preserveAttachments[preserveNdx];
1008 
1009                     log << TestLog::Message << "Attachment: " << preserveAttachment << TestLog::EndMessage;
1010                 }
1011             }
1012         }
1013     }
1014 
1015     if (!renderPass.getDependencies().empty())
1016     {
1017         const tcu::ScopedLogSection dependenciesSection(log, "Dependencies", "Dependencies");
1018 
1019         for (size_t depNdx = 0; depNdx < renderPass.getDependencies().size(); depNdx++)
1020         {
1021             const tcu::ScopedLogSection dependencySection(log, "Dependency" + de::toString(depNdx),
1022                                                           "Dependency " + de::toString(depNdx));
1023             const SubpassDependency &dep = renderPass.getDependencies()[depNdx];
1024 
1025             log << TestLog::Message << "Source: " << dep.getSrcPass() << TestLog::EndMessage;
1026             log << TestLog::Message << "Destination: " << dep.getDstPass() << TestLog::EndMessage;
1027 
1028             log << TestLog::Message << "Source Stage Mask: " << dep.getSrcStageMask() << TestLog::EndMessage;
1029             log << TestLog::Message << "Destination Stage Mask: " << dep.getDstStageMask() << TestLog::EndMessage;
1030 
1031             log << TestLog::Message << "Input Mask: " << dep.getDstAccessMask() << TestLog::EndMessage;
1032             log << TestLog::Message << "Output Mask: " << dep.getSrcAccessMask() << TestLog::EndMessage;
1033             log << TestLog::Message << "Dependency Flags: " << getDependencyFlagsStr(dep.getFlags())
1034                 << TestLog::EndMessage;
1035         }
1036     }
1037 }
1038 
clearColorToString(VkFormat vkFormat,VkClearColorValue value,bool useFormatCompCount)1039 std::string clearColorToString(VkFormat vkFormat, VkClearColorValue value, bool useFormatCompCount)
1040 {
1041     const tcu::TextureFormat format             = mapVkFormat(vkFormat);
1042     const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
1043     const tcu::BVec4 channelMask                = tcu::getTextureFormatChannelMask(format);
1044     const auto numUsedChannels                  = static_cast<uint32_t>(getShaderNumChannels(format.order));
1045     const uint32_t componentCount               = (useFormatCompCount ? numUsedChannels : 4u);
1046 
1047     std::ostringstream stream;
1048 
1049     stream << "(";
1050 
1051     switch (channelClass)
1052     {
1053     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1054         for (uint32_t i = 0; i < componentCount; i++)
1055         {
1056             if (i > 0)
1057                 stream << ", ";
1058 
1059             if (channelMask[i])
1060                 stream << value.int32[i];
1061             else
1062                 stream << "Undef";
1063         }
1064         break;
1065 
1066     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1067         for (uint32_t i = 0; i < componentCount; i++)
1068         {
1069             if (i > 0)
1070                 stream << ", ";
1071 
1072             if (channelMask[i])
1073                 stream << value.uint32[i];
1074             else
1075                 stream << "Undef";
1076         }
1077         break;
1078 
1079     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1080     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1081     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1082         for (uint32_t i = 0; i < componentCount; i++)
1083         {
1084             if (i > 0)
1085                 stream << ", ";
1086 
1087             if (channelMask[i])
1088                 stream << value.float32[i];
1089             else
1090                 stream << "Undef";
1091         }
1092         break;
1093 
1094     default:
1095         DE_FATAL("Unknown channel class");
1096     }
1097 
1098     stream << ")";
1099 
1100     return stream.str();
1101 }
1102 
clearValueToString(VkFormat vkFormat,VkClearValue value,bool useFormatCompCount)1103 std::string clearValueToString(VkFormat vkFormat, VkClearValue value, bool useFormatCompCount)
1104 {
1105     const tcu::TextureFormat format = mapVkFormat(vkFormat);
1106 
1107     if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
1108     {
1109         std::ostringstream stream;
1110 
1111         stream << "(";
1112 
1113         if (tcu::hasStencilComponent(format.order))
1114             stream << "stencil: " << value.depthStencil.stencil;
1115 
1116         if (tcu::hasStencilComponent(format.order) && tcu::hasDepthComponent(format.order))
1117             stream << ", ";
1118 
1119         if (tcu::hasDepthComponent(format.order))
1120             stream << "depth: " << value.depthStencil.depth;
1121 
1122         stream << ")";
1123 
1124         return stream.str();
1125     }
1126     else
1127         return clearColorToString(vkFormat, value.color, useFormatCompCount);
1128 }
1129 
randomColorClearValue(const Attachment & attachment,de::Random & rng,bool useFormatCompCount)1130 VkClearColorValue randomColorClearValue(const Attachment &attachment, de::Random &rng, bool useFormatCompCount)
1131 {
1132     const float clearNan                        = tcu::Float32::nan().asFloat();
1133     const tcu::TextureFormat format             = mapVkFormat(attachment.getFormat());
1134     const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
1135     const tcu::BVec4 channelMask                = tcu::getTextureFormatChannelMask(format);
1136     const auto numUsedChannels                  = static_cast<uint32_t>(getShaderNumChannels(format.order));
1137     const uint32_t componentCount               = (useFormatCompCount ? numUsedChannels : 4u);
1138     VkClearColorValue clearColor;
1139 
1140     switch (channelClass)
1141     {
1142     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1143     {
1144         for (uint32_t ndx = 0; ndx < componentCount; ndx++)
1145         {
1146             if (!channelMask[ndx])
1147                 clearColor.int32[ndx] = std::numeric_limits<int32_t>::min();
1148             else
1149                 clearColor.uint32[ndx] = rng.getBool() ? 1u : 0u;
1150         }
1151         break;
1152     }
1153 
1154     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1155     {
1156         for (uint32_t ndx = 0; ndx < componentCount; ndx++)
1157         {
1158             if (!channelMask[ndx])
1159                 clearColor.uint32[ndx] = std::numeric_limits<uint32_t>::max();
1160             else
1161                 clearColor.uint32[ndx] = rng.getBool() ? 1u : 0u;
1162         }
1163         break;
1164     }
1165 
1166     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1167     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1168     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1169     {
1170         for (uint32_t ndx = 0; ndx < componentCount; ndx++)
1171         {
1172             if (!channelMask[ndx])
1173                 clearColor.float32[ndx] = clearNan;
1174             else
1175                 clearColor.float32[ndx] = rng.getBool() ? 1.0f : 0.0f;
1176         }
1177         break;
1178     }
1179 
1180     default:
1181         DE_FATAL("Unknown channel class");
1182     }
1183 
1184     return clearColor;
1185 }
1186 
1187 template <typename AttachmentDesc>
createAttachmentDescription(const Attachment & attachment)1188 AttachmentDesc createAttachmentDescription(const Attachment &attachment)
1189 {
1190     const AttachmentDesc
1191         attachmentDescription //  VkAttachmentDescription                                        ||  VkAttachmentDescription2KHR
1192         (
1193             //  ||  VkStructureType sType;
1194             DE_NULL,                 //   ||  const void* pNext;
1195             0u,                      //  VkAttachmentDescriptionFlags flags; ||  VkAttachmentDescriptionFlags flags;
1196             attachment.getFormat(),  //  VkFormat format; ||  VkFormat format;
1197             attachment.getSamples(), //  VkSampleCountFlagBits samples; ||  VkSampleCountFlagBits samples;
1198             attachment.getLoadOp(),  //  VkAttachmentLoadOp loadOp; ||  VkAttachmentLoadOp loadOp;
1199             attachment.getStoreOp(), //  VkAttachmentStoreOp storeOp; ||  VkAttachmentStoreOp storeOp;
1200             attachment.getStencilLoadOp(), //  VkAttachmentLoadOp stencilLoadOp; ||  VkAttachmentLoadOp stencilLoadOp;
1201             attachment
1202                 .getStencilStoreOp(), //  VkAttachmentStoreOp stencilStoreOp; ||  VkAttachmentStoreOp stencilStoreOp;
1203             attachment.getInitialLayout(), //  VkImageLayout initialLayout; ||  VkImageLayout initialLayout;
1204             attachment.getFinalLayout()    //  VkImageLayout finalLayout; ||  VkImageLayout finalLayout;
1205         );
1206 
1207     return attachmentDescription;
1208 }
1209 
1210 template <typename AttachmentRef>
createAttachmentReference(const AttachmentReference & referenceInfo)1211 AttachmentRef createAttachmentReference(const AttachmentReference &referenceInfo)
1212 {
1213     const AttachmentRef
1214         reference //  VkAttachmentReference                                        ||  VkAttachmentReference2KHR
1215         (
1216             //  ||  VkStructureType sType;
1217             DE_NULL,                        //   ||  const void* pNext;
1218             referenceInfo.getAttachment(),  //  uint32_t attachment; ||  uint32_t attachment;
1219             referenceInfo.getImageLayout(), //  VkImageLayout layout; ||  VkImageLayout layout;
1220             referenceInfo.getAspectMask()   // ||  VkImageAspectFlags aspectMask;
1221         );
1222 
1223     return reference;
1224 }
1225 
1226 template <typename SubpassDesc, typename AttachmentRef>
createSubpassDescription(const Subpass & subpass,vector<AttachmentRef> * attachmentReferenceLists,vector<uint32_t> * preserveAttachmentReferences)1227 SubpassDesc createSubpassDescription(const Subpass &subpass, vector<AttachmentRef> *attachmentReferenceLists,
1228                                      vector<uint32_t> *preserveAttachmentReferences)
1229 {
1230     vector<AttachmentRef> &inputAttachmentReferences        = attachmentReferenceLists[0];
1231     vector<AttachmentRef> &colorAttachmentReferences        = attachmentReferenceLists[1];
1232     vector<AttachmentRef> &resolveAttachmentReferences      = attachmentReferenceLists[2];
1233     vector<AttachmentRef> &depthStencilAttachmentReferences = attachmentReferenceLists[3];
1234 
1235     for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
1236         colorAttachmentReferences.push_back(
1237             createAttachmentReference<AttachmentRef>(subpass.getColorAttachments()[attachmentNdx]));
1238 
1239     for (size_t attachmentNdx = 0; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++)
1240         inputAttachmentReferences.push_back(
1241             createAttachmentReference<AttachmentRef>(subpass.getInputAttachments()[attachmentNdx]));
1242 
1243     for (size_t attachmentNdx = 0; attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++)
1244         resolveAttachmentReferences.push_back(
1245             createAttachmentReference<AttachmentRef>(subpass.getResolveAttachments()[attachmentNdx]));
1246 
1247     depthStencilAttachmentReferences.push_back(
1248         createAttachmentReference<AttachmentRef>(subpass.getDepthStencilAttachment()));
1249 
1250     for (size_t attachmentNdx = 0; attachmentNdx < subpass.getPreserveAttachments().size(); attachmentNdx++)
1251         preserveAttachmentReferences->push_back(subpass.getPreserveAttachments()[attachmentNdx]);
1252 
1253     DE_ASSERT(resolveAttachmentReferences.empty() ||
1254               colorAttachmentReferences.size() == resolveAttachmentReferences.size());
1255 
1256     {
1257         const SubpassDesc
1258             subpassDescription //  VkSubpassDescription                                        ||  VkSubpassDescription2KHR
1259             (
1260                 //  ||  VkStructureType sType;
1261                 DE_NULL,            //   ||  const void* pNext;
1262                 subpass.getFlags(), //  VkSubpassDescriptionFlags flags; ||  VkSubpassDescriptionFlags flags;
1263                 subpass
1264                     .getPipelineBindPoint(), //  VkPipelineBindPoint pipelineBindPoint; ||  VkPipelineBindPoint pipelineBindPoint;
1265                 0u,                          //   ||  uint32_t viewMask;
1266                 (uint32_t)inputAttachmentReferences
1267                     .size(), //  uint32_t inputAttachmentCount; ||  uint32_t inputAttachmentCount;
1268                 inputAttachmentReferences.empty() ?
1269                     DE_NULL :
1270                     &inputAttachmentReferences
1271                         [0], //  const VkAttachmentReference* pInputAttachments; ||  const VkAttachmentReference2KHR* pInputAttachments;
1272                 (uint32_t)colorAttachmentReferences
1273                     .size(), //  uint32_t colorAttachmentCount; ||  uint32_t colorAttachmentCount;
1274                 colorAttachmentReferences.empty() ?
1275                     DE_NULL :
1276                     &colorAttachmentReferences
1277                         [0], //  const VkAttachmentReference* pColorAttachments; ||  const VkAttachmentReference2KHR* pColorAttachments;
1278                 resolveAttachmentReferences.empty() ?
1279                     DE_NULL :
1280                     &resolveAttachmentReferences
1281                         [0], //  const VkAttachmentReference* pResolveAttachments; ||  const VkAttachmentReference2KHR* pResolveAttachments;
1282                 &depthStencilAttachmentReferences
1283                     [0], //  const VkAttachmentReference* pDepthStencilAttachment; ||  const VkAttachmentReference2KHR* pDepthStencilAttachment;
1284                 (uint32_t)preserveAttachmentReferences
1285                     ->size(), //  uint32_t preserveAttachmentCount; ||  uint32_t preserveAttachmentCount;
1286                 preserveAttachmentReferences->empty() ?
1287                     DE_NULL :
1288                     &(*preserveAttachmentReferences)
1289                         [0] //  const uint32_t* pPreserveAttachments; ||  const uint32_t* pPreserveAttachments;
1290             );
1291 
1292         return subpassDescription;
1293     }
1294 }
1295 
1296 template <typename SubpassDep>
createSubpassDependency(const SubpassDependency & dependencyInfo)1297 SubpassDep createSubpassDependency(const SubpassDependency &dependencyInfo)
1298 {
1299     const SubpassDep
1300         dependency //  VkSubpassDependency                                            ||  VkSubpassDependency2KHR
1301         (
1302             //  || VkStructureType sType;
1303             DE_NULL,                     //   || const void* pNext;
1304             dependencyInfo.getSrcPass(), //  uint32_t srcSubpass; || uint32_t srcSubpass;
1305             dependencyInfo.getDstPass(), //  uint32_t dstSubpass; || uint32_t dstSubpass;
1306             dependencyInfo
1307                 .getSrcStageMask(), //  VkPipelineStageFlags srcStageMask; || VkPipelineStageFlags srcStageMask;
1308             dependencyInfo
1309                 .getDstStageMask(), //  VkPipelineStageFlags dstStageMask; || VkPipelineStageFlags dstStageMask;
1310             dependencyInfo.getSrcAccessMask(), //  VkAccessFlags srcAccessMask; || VkAccessFlags srcAccessMask;
1311             dependencyInfo.getDstAccessMask(), //  VkAccessFlags dstAccessMask; || VkAccessFlags dstAccessMask;
1312             dependencyInfo.getFlags(), //  VkDependencyFlags dependencyFlags; || VkDependencyFlags dependencyFlags;
1313             0u                         //    || int32_t viewOffset;
1314         );
1315 
1316     return dependency;
1317 }
1318 
createRenderPassInputAttachmentAspectCreateInfo(const RenderPass & renderPassInfo)1319 de::MovePtr<VkRenderPassInputAttachmentAspectCreateInfo> createRenderPassInputAttachmentAspectCreateInfo(
1320     const RenderPass &renderPassInfo)
1321 {
1322     de::MovePtr<VkRenderPassInputAttachmentAspectCreateInfo> result(DE_NULL);
1323 
1324     if (!renderPassInfo.getInputAspects().empty())
1325     {
1326         const VkRenderPassInputAttachmentAspectCreateInfo inputAspectCreateInfo = {
1327             VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO,
1328             DE_NULL,
1329 
1330             (uint32_t)renderPassInfo.getInputAspects().size(),
1331             renderPassInfo.getInputAspects().data(),
1332         };
1333 
1334         result = de::MovePtr<VkRenderPassInputAttachmentAspectCreateInfo>(
1335             new VkRenderPassInputAttachmentAspectCreateInfo(inputAspectCreateInfo));
1336     }
1337 
1338     return result;
1339 }
1340 
1341 template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
1342           typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice device,const RenderPass & renderPassInfo)1343 Move<VkRenderPass> createRenderPass(const DeviceInterface &vk, VkDevice device, const RenderPass &renderPassInfo)
1344 {
1345     const size_t perSubpassAttachmentReferenceLists = 4;
1346     vector<AttachmentDesc> attachments;
1347     vector<SubpassDesc> subpasses;
1348     vector<SubpassDep> dependencies;
1349     vector<vector<AttachmentRef>> attachmentReferenceLists(renderPassInfo.getSubpasses().size() *
1350                                                            perSubpassAttachmentReferenceLists);
1351     vector<vector<uint32_t>> preserveAttachments(renderPassInfo.getSubpasses().size());
1352     de::MovePtr<VkRenderPassInputAttachmentAspectCreateInfo> inputAspectCreateInfo(
1353         createRenderPassInputAttachmentAspectCreateInfo(renderPassInfo));
1354 
1355     for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
1356         attachments.push_back(
1357             createAttachmentDescription<AttachmentDesc>(renderPassInfo.getAttachments()[attachmentNdx]));
1358 
1359     for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
1360         subpasses.push_back(createSubpassDescription<SubpassDesc>(
1361             renderPassInfo.getSubpasses()[subpassNdx],
1362             &(attachmentReferenceLists[subpassNdx * perSubpassAttachmentReferenceLists]),
1363             &preserveAttachments[subpassNdx]));
1364 
1365     for (size_t depNdx = 0; depNdx < renderPassInfo.getDependencies().size(); depNdx++)
1366         dependencies.push_back(createSubpassDependency<SubpassDep>(renderPassInfo.getDependencies()[depNdx]));
1367 
1368     const RenderPassCreateInfo
1369         renderPassCreator //  VkRenderPassCreateInfo                                        ||  VkRenderPassCreateInfo2KHR
1370         (
1371             //  VkStructureType sType; ||  VkStructureType sType;
1372             inputAspectCreateInfo.get(),  //  const void* pNext; ||  const void* pNext;
1373             (VkRenderPassCreateFlags)0u,  //  VkRenderPassCreateFlags flags; ||  VkRenderPassCreateFlags flags;
1374             (uint32_t)attachments.size(), //  uint32_t attachmentCount; ||  uint32_t attachmentCount;
1375             (attachments.empty() ?
1376                  DE_NULL :
1377                  &attachments
1378                      [0]), //  const VkAttachmentDescription* pAttachments; ||  const VkAttachmentDescription2KHR* pAttachments;
1379             (uint32_t)subpasses.size(), //  uint32_t subpassCount; ||  uint32_t subpassCount;
1380             (subpasses.empty() ?
1381                  DE_NULL :
1382                  &subpasses
1383                      [0]), //  const VkSubpassDescription* pSubpasses; ||  const VkSubpassDescription2KHR* pSubpasses;
1384             (uint32_t)dependencies.size(), //  uint32_t dependencyCount; ||  uint32_t dependencyCount;
1385             (dependencies.empty() ?
1386                  DE_NULL :
1387                  &dependencies
1388                      [0]), //  const VkSubpassDependency* pDependencies; ||  const VkSubpassDependency2KHR* pDependencies;
1389             0u,            //   ||  uint32_t correlatedViewMaskCount;
1390             DE_NULL        //  ||  const uint32_t* pCorrelatedViewMasks;
1391         );
1392 
1393     return renderPassCreator.createRenderPass(vk, device);
1394 }
1395 
createRenderPass(const DeviceInterface & vk,VkDevice device,const RenderPass & renderPassInfo,const RenderingType renderPassType)1396 Move<VkRenderPass> createRenderPass(const DeviceInterface &vk, VkDevice device, const RenderPass &renderPassInfo,
1397                                     const RenderingType renderPassType)
1398 {
1399     switch (renderPassType)
1400     {
1401     case RENDERING_TYPE_RENDERPASS_LEGACY:
1402         return createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1,
1403                                 RenderPassCreateInfo1>(vk, device, renderPassInfo);
1404     case RENDERING_TYPE_RENDERPASS2:
1405         return createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2,
1406                                 RenderPassCreateInfo2>(vk, device, renderPassInfo);
1407     default:
1408         TCU_THROW(InternalError, "Impossible");
1409     }
1410 }
1411 
createFramebuffer(const DeviceInterface & vk,VkDevice device,VkRenderPass renderPass,const UVec2 & size,const vector<VkImageView> & attachments)1412 Move<VkFramebuffer> createFramebuffer(const DeviceInterface &vk, VkDevice device, VkRenderPass renderPass,
1413                                       const UVec2 &size, const vector<VkImageView> &attachments)
1414 {
1415     return createFramebuffer(vk, device, 0u, renderPass, (uint32_t)attachments.size(),
1416                              attachments.empty() ? DE_NULL : &attachments[0], size.x(), size.y(), 1u);
1417 }
1418 
createAttachmentImage(const DeviceInterface & vk,VkDevice device,uint32_t queueIndex,const UVec2 & size,VkFormat format,VkSampleCountFlagBits samples,VkImageUsageFlags usageFlags,VkImageLayout layout)1419 Move<VkImage> createAttachmentImage(const DeviceInterface &vk, VkDevice device, uint32_t queueIndex, const UVec2 &size,
1420                                     VkFormat format, VkSampleCountFlagBits samples, VkImageUsageFlags usageFlags,
1421                                     VkImageLayout layout)
1422 {
1423     VkImageUsageFlags targetUsageFlags     = 0;
1424     const tcu::TextureFormat textureFormat = mapVkFormat(format);
1425 
1426     DE_ASSERT(!(tcu::hasDepthComponent(vk::mapVkFormat(format).order) ||
1427                 tcu::hasStencilComponent(vk::mapVkFormat(format).order)) ||
1428               ((usageFlags & vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0));
1429 
1430     DE_ASSERT((tcu::hasDepthComponent(vk::mapVkFormat(format).order) ||
1431                tcu::hasStencilComponent(vk::mapVkFormat(format).order)) ||
1432               ((usageFlags & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0));
1433 
1434     if (tcu::hasDepthComponent(textureFormat.order) || tcu::hasStencilComponent(textureFormat.order))
1435         targetUsageFlags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1436     else
1437         targetUsageFlags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1438 
1439     return createImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, format,
1440                        vk::makeExtent3D(size.x(), size.y(), 1u), 1u /* mipLevels */, 1u /* arraySize */, samples,
1441                        VK_IMAGE_TILING_OPTIMAL, usageFlags | targetUsageFlags, VK_SHARING_MODE_EXCLUSIVE, 1,
1442                        &queueIndex, layout);
1443 }
1444 
createImageMemory(const InstanceInterface & vki,const VkPhysicalDevice & vkd,const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkImage image,bool lazy,AllocationKind allocationKind)1445 de::MovePtr<Allocation> createImageMemory(const InstanceInterface &vki, const VkPhysicalDevice &vkd,
1446                                           const DeviceInterface &vk, VkDevice device, Allocator &allocator,
1447                                           VkImage image, bool lazy, AllocationKind allocationKind)
1448 {
1449     const MemoryRequirement memoryRequirement = lazy ? MemoryRequirement::LazilyAllocated : MemoryRequirement::Any;
1450     de::MovePtr<Allocation> allocation =
1451         allocateImage(vki, vk, vkd, device, image, memoryRequirement, allocator, allocationKind);
1452 
1453     bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
1454 
1455     return allocation;
1456 }
1457 
createImageAttachmentView(const DeviceInterface & vk,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)1458 Move<VkImageView> createImageAttachmentView(const DeviceInterface &vk, VkDevice device, VkImage image, VkFormat format,
1459                                             VkImageAspectFlags aspect)
1460 {
1461     const VkImageSubresourceRange range = {aspect, 0, 1, 0, 1};
1462 
1463     return createImageView(vk, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
1464 }
1465 
randomClearValue(const Attachment & attachment,de::Random & rng,bool useFormatCompCount,const DepthValuesArray & depthValues)1466 VkClearValue randomClearValue(const Attachment &attachment, de::Random &rng, bool useFormatCompCount,
1467                               const DepthValuesArray &depthValues)
1468 {
1469     const float clearNan            = tcu::Float32::nan().asFloat();
1470     const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
1471 
1472     if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
1473     {
1474         VkClearValue clearValue;
1475 
1476         clearValue.depthStencil.depth   = clearNan;
1477         clearValue.depthStencil.stencil = 0xCDu;
1478 
1479         if (tcu::hasStencilComponent(format.order))
1480             clearValue.depthStencil.stencil = rng.getBool() ? 0xFFu : 0x0u;
1481 
1482         if (tcu::hasDepthComponent(format.order))
1483             clearValue.depthStencil.depth = float(depthValues[rng.getBool() ? 1 : 0]) / 255.0f;
1484 
1485         return clearValue;
1486     }
1487     else
1488     {
1489         VkClearValue clearValue;
1490 
1491         clearValue.color = randomColorClearValue(attachment, rng, useFormatCompCount);
1492 
1493         return clearValue;
1494     }
1495 }
1496 
1497 class AttachmentResources
1498 {
1499 public:
AttachmentResources(const InstanceInterface & vki,const VkPhysicalDevice & physDevice,const DeviceInterface & vk,VkDevice device,Allocator & allocator,uint32_t queueIndex,const UVec2 & size,const Attachment & attachmentInfo,VkImageUsageFlags usageFlags,const AllocationKind allocationKind)1500     AttachmentResources(const InstanceInterface &vki, const VkPhysicalDevice &physDevice, const DeviceInterface &vk,
1501                         VkDevice device, Allocator &allocator, uint32_t queueIndex, const UVec2 &size,
1502                         const Attachment &attachmentInfo, VkImageUsageFlags usageFlags,
1503                         const AllocationKind allocationKind)
1504         : m_image(createAttachmentImage(vk, device, queueIndex, size, attachmentInfo.getFormat(),
1505                                         attachmentInfo.getSamples(), usageFlags, VK_IMAGE_LAYOUT_UNDEFINED))
1506         , m_imageMemory(createImageMemory(vki, physDevice, vk, device, allocator, *m_image,
1507                                           ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0),
1508                                           allocationKind))
1509         , m_attachmentView(createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(),
1510                                                      getImageAspectFlags(attachmentInfo.getFormat())))
1511     {
1512         const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
1513         const bool isDepthFormat        = tcu::hasDepthComponent(format.order);
1514         const bool isStencilFormat      = tcu::hasStencilComponent(format.order);
1515 
1516         if (isDepthFormat && isStencilFormat)
1517         {
1518             m_depthInputAttachmentView =
1519                 createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(), VK_IMAGE_ASPECT_DEPTH_BIT);
1520             m_stencilInputAttachmentView = createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(),
1521                                                                      VK_IMAGE_ASPECT_STENCIL_BIT);
1522 
1523             m_inputAttachmentViews = std::make_pair(*m_depthInputAttachmentView, *m_stencilInputAttachmentView);
1524         }
1525         else
1526             m_inputAttachmentViews = std::make_pair(*m_attachmentView, (vk::VkImageView)0u);
1527 
1528         if ((usageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) == 0)
1529         {
1530             if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
1531             {
1532                 const tcu::TextureFormat depthFormat   = getDepthCopyFormat(attachmentInfo.getFormat());
1533                 const tcu::TextureFormat stencilFormat = getStencilCopyFormat(attachmentInfo.getFormat());
1534 
1535                 m_bufferSize          = size.x() * size.y() * depthFormat.getPixelSize();
1536                 m_secondaryBufferSize = size.x() * size.y() * stencilFormat.getPixelSize();
1537 
1538                 m_buffer       = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1539                                               VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1540                 m_bufferMemory = allocateBuffer(vki, vk, physDevice, device, *m_buffer, MemoryRequirement::HostVisible,
1541                                                 allocator, allocationKind);
1542 
1543                 bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
1544 
1545                 m_secondaryBuffer = createBuffer(vk, device, 0, m_secondaryBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1546                                                  VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1547                 m_secondaryBufferMemory = allocateBuffer(vki, vk, physDevice, device, *m_secondaryBuffer,
1548                                                          MemoryRequirement::HostVisible, allocator, allocationKind);
1549 
1550                 bindBufferMemory(vk, device, *m_secondaryBuffer, m_secondaryBufferMemory->getMemory(),
1551                                  m_secondaryBufferMemory->getOffset());
1552             }
1553             else
1554             {
1555                 m_bufferSize = size.x() * size.y() * format.getPixelSize();
1556 
1557                 m_buffer       = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1558                                               VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1559                 m_bufferMemory = allocateBuffer(vki, vk, physDevice, device, *m_buffer, MemoryRequirement::HostVisible,
1560                                                 allocator, allocationKind);
1561 
1562                 bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
1563             }
1564         }
1565     }
1566 
getInputAttachmentViews(void) const1567     const pair<VkImageView, VkImageView> &getInputAttachmentViews(void) const
1568     {
1569         return m_inputAttachmentViews;
1570     }
1571 
~AttachmentResources(void)1572     ~AttachmentResources(void)
1573     {
1574     }
1575 
getAttachmentView(void) const1576     VkImageView getAttachmentView(void) const
1577     {
1578         return *m_attachmentView;
1579     }
1580 
getImage(void) const1581     VkImage getImage(void) const
1582     {
1583         return *m_image;
1584     }
1585 
getBuffer(void) const1586     VkBuffer getBuffer(void) const
1587     {
1588         DE_ASSERT(*m_buffer != DE_NULL);
1589         return *m_buffer;
1590     }
1591 
getBufferSize(void) const1592     VkDeviceSize getBufferSize(void) const
1593     {
1594         DE_ASSERT(*m_buffer != DE_NULL);
1595         return m_bufferSize;
1596     }
1597 
getResultMemory(void) const1598     const Allocation &getResultMemory(void) const
1599     {
1600         DE_ASSERT(m_bufferMemory);
1601         return *m_bufferMemory;
1602     }
1603 
getSecondaryBuffer(void) const1604     VkBuffer getSecondaryBuffer(void) const
1605     {
1606         DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1607         return *m_secondaryBuffer;
1608     }
1609 
getSecondaryBufferSize(void) const1610     VkDeviceSize getSecondaryBufferSize(void) const
1611     {
1612         DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1613         return m_secondaryBufferSize;
1614     }
1615 
getSecondaryResultMemory(void) const1616     const Allocation &getSecondaryResultMemory(void) const
1617     {
1618         DE_ASSERT(m_secondaryBufferMemory);
1619         return *m_secondaryBufferMemory;
1620     }
1621 
1622 private:
1623     const Unique<VkImage> m_image;
1624     const UniquePtr<Allocation> m_imageMemory;
1625     const Unique<VkImageView> m_attachmentView;
1626 
1627     Move<VkImageView> m_depthInputAttachmentView;
1628     Move<VkImageView> m_stencilInputAttachmentView;
1629     pair<VkImageView, VkImageView> m_inputAttachmentViews;
1630 
1631     Move<VkBuffer> m_buffer;
1632     VkDeviceSize m_bufferSize;
1633     de::MovePtr<Allocation> m_bufferMemory;
1634 
1635     Move<VkBuffer> m_secondaryBuffer;
1636     VkDeviceSize m_secondaryBufferSize;
1637     de::MovePtr<Allocation> m_secondaryBufferMemory;
1638 };
1639 
uploadBufferData(const DeviceInterface & vk,VkDevice device,const Allocation & memory,size_t size,const void * data,VkDeviceSize nonCoherentAtomSize)1640 void uploadBufferData(const DeviceInterface &vk, VkDevice device, const Allocation &memory, size_t size,
1641                       const void *data, VkDeviceSize nonCoherentAtomSize)
1642 {
1643     // Expand the range to flush to account for the nonCoherentAtomSize
1644     const VkDeviceSize roundedOffset = de::roundDown(memory.getOffset(), nonCoherentAtomSize);
1645     const VkDeviceSize roundedSize =
1646         de::roundUp(memory.getOffset() - roundedOffset + static_cast<VkDeviceSize>(size), nonCoherentAtomSize);
1647 
1648     const VkMappedMemoryRange range = {
1649         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType;
1650         DE_NULL,                               // pNext;
1651         memory.getMemory(),                    // mem;
1652         roundedOffset,                         // offset;
1653         roundedSize,                           // size;
1654     };
1655     void *const ptr = memory.getHostPtr();
1656 
1657     deMemcpy(ptr, data, size);
1658     VK_CHECK(vk.flushMappedMemoryRanges(device, 1, &range));
1659 }
1660 
getPrimaryImageAspect(tcu::TextureFormat::ChannelOrder order)1661 VkImageAspectFlagBits getPrimaryImageAspect(tcu::TextureFormat::ChannelOrder order)
1662 {
1663     DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 22);
1664 
1665     switch (order)
1666     {
1667     case tcu::TextureFormat::D:
1668     case tcu::TextureFormat::DS:
1669         return VK_IMAGE_ASPECT_DEPTH_BIT;
1670 
1671     case tcu::TextureFormat::S:
1672         return VK_IMAGE_ASPECT_STENCIL_BIT;
1673 
1674     default:
1675         return VK_IMAGE_ASPECT_COLOR_BIT;
1676     }
1677 }
1678 
getAttachmentNdx(const vector<AttachmentReference> & colorAttachments,size_t ndx)1679 uint32_t getAttachmentNdx(const vector<AttachmentReference> &colorAttachments, size_t ndx)
1680 {
1681     return (colorAttachments[ndx].getAttachment() == VK_ATTACHMENT_UNUSED) ? (uint32_t)ndx :
1682                                                                              colorAttachments[ndx].getAttachment();
1683 }
1684 
1685 class RenderQuad
1686 {
1687 public:
RenderQuad(const Vec2 & posA,const Vec2 & posB)1688     RenderQuad(const Vec2 &posA, const Vec2 &posB) : m_vertices(6)
1689     {
1690         m_vertices[0] = posA;
1691         m_vertices[1] = Vec2(posA[0], posB[1]);
1692         m_vertices[2] = posB;
1693 
1694         m_vertices[3] = posB;
1695         m_vertices[4] = Vec2(posB[0], posA[1]);
1696         m_vertices[5] = posA;
1697     }
1698 
getCornerA(void) const1699     const Vec2 &getCornerA(void) const
1700     {
1701         return m_vertices[0];
1702     }
1703 
getCornerB(void) const1704     const Vec2 &getCornerB(void) const
1705     {
1706         return m_vertices[2];
1707     }
1708 
getVertexPointer(void) const1709     const void *getVertexPointer(void) const
1710     {
1711         return &m_vertices[0];
1712     }
1713 
getVertexDataSize(void) const1714     size_t getVertexDataSize(void) const
1715     {
1716         return sizeof(Vec2) * m_vertices.size();
1717     }
1718 
1719 private:
1720     vector<Vec2> m_vertices;
1721 };
1722 
1723 class ColorClear
1724 {
1725 public:
ColorClear(const UVec2 & offset,const UVec2 & size,const VkClearColorValue & color)1726     ColorClear(const UVec2 &offset, const UVec2 &size, const VkClearColorValue &color)
1727         : m_offset(offset)
1728         , m_size(size)
1729         , m_color(color)
1730     {
1731     }
1732 
getOffset(void) const1733     const UVec2 &getOffset(void) const
1734     {
1735         return m_offset;
1736     }
getSize(void) const1737     const UVec2 &getSize(void) const
1738     {
1739         return m_size;
1740     }
getColor(void) const1741     const VkClearColorValue &getColor(void) const
1742     {
1743         return m_color;
1744     }
1745 
1746 private:
1747     UVec2 m_offset;
1748     UVec2 m_size;
1749     VkClearColorValue m_color;
1750 };
1751 
1752 class DepthStencilClear
1753 {
1754 public:
DepthStencilClear(const UVec2 & offset,const UVec2 & size,float depth,uint32_t stencil)1755     DepthStencilClear(const UVec2 &offset, const UVec2 &size, float depth, uint32_t stencil)
1756         : m_offset(offset)
1757         , m_size(size)
1758         , m_depth(depth)
1759         , m_stencil(stencil)
1760     {
1761     }
1762 
getOffset(void) const1763     const UVec2 &getOffset(void) const
1764     {
1765         return m_offset;
1766     }
getSize(void) const1767     const UVec2 &getSize(void) const
1768     {
1769         return m_size;
1770     }
getDepth(void) const1771     float getDepth(void) const
1772     {
1773         return m_depth;
1774     }
getStencil(void) const1775     uint32_t getStencil(void) const
1776     {
1777         return m_stencil;
1778     }
1779 
1780 private:
1781     const UVec2 m_offset;
1782     const UVec2 m_size;
1783 
1784     const float m_depth;
1785     const uint32_t m_stencil;
1786 };
1787 
1788 class SubpassRenderInfo
1789 {
1790 public:
SubpassRenderInfo(const RenderPass & renderPass,uint32_t subpassIndex,uint32_t drawStartNdx,bool isSecondary_,bool omitBlendState_,const UVec2 & viewportOffset,const UVec2 & viewportSize,const Maybe<RenderQuad> & renderQuad,const vector<ColorClear> & colorClears,const Maybe<DepthStencilClear> & depthStencilClear)1791     SubpassRenderInfo(const RenderPass &renderPass, uint32_t subpassIndex, uint32_t drawStartNdx,
1792 
1793                       bool isSecondary_, bool omitBlendState_,
1794 
1795                       const UVec2 &viewportOffset, const UVec2 &viewportSize,
1796 
1797                       const Maybe<RenderQuad> &renderQuad, const vector<ColorClear> &colorClears,
1798                       const Maybe<DepthStencilClear> &depthStencilClear)
1799         : m_viewportOffset(viewportOffset)
1800         , m_viewportSize(viewportSize)
1801         , m_subpassIndex(subpassIndex)
1802         , m_drawStartNdx(drawStartNdx)
1803         , m_isSecondary(isSecondary_)
1804         , m_omitBlendState(omitBlendState_)
1805         , m_flags(renderPass.getSubpasses()[subpassIndex].getFlags())
1806         , m_renderQuad(renderQuad)
1807         , m_colorClears(colorClears)
1808         , m_depthStencilClear(depthStencilClear)
1809         , m_colorAttachments(renderPass.getSubpasses()[subpassIndex].getColorAttachments())
1810         , m_inputAttachments(renderPass.getSubpasses()[subpassIndex].getInputAttachments())
1811     {
1812         for (uint32_t attachmentNdx = 0; attachmentNdx < (uint32_t)m_colorAttachments.size(); attachmentNdx++)
1813             m_colorAttachmentInfo.push_back(
1814                 renderPass.getAttachments()[getAttachmentNdx(m_colorAttachments, attachmentNdx)]);
1815 
1816         if (renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
1817         {
1818             m_depthStencilAttachment = tcu::just(renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment());
1819             m_depthStencilAttachmentInfo =
1820                 tcu::just(renderPass.getAttachments()
1821                               [renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment()]);
1822         }
1823     }
1824 
getViewportOffset(void) const1825     const UVec2 &getViewportOffset(void) const
1826     {
1827         return m_viewportOffset;
1828     }
getViewportSize(void) const1829     const UVec2 &getViewportSize(void) const
1830     {
1831         return m_viewportSize;
1832     }
1833 
getSubpassIndex(void) const1834     uint32_t getSubpassIndex(void) const
1835     {
1836         return m_subpassIndex;
1837     }
getDrawStartNdx(void) const1838     uint32_t getDrawStartNdx(void) const
1839     {
1840         return m_drawStartNdx;
1841     }
isSecondary(void) const1842     bool isSecondary(void) const
1843     {
1844         return m_isSecondary;
1845     }
getOmitBlendState(void) const1846     bool getOmitBlendState(void) const
1847     {
1848         return m_omitBlendState;
1849     }
1850 
getRenderQuad(void) const1851     const Maybe<RenderQuad> &getRenderQuad(void) const
1852     {
1853         return m_renderQuad;
1854     }
getColorClears(void) const1855     const vector<ColorClear> &getColorClears(void) const
1856     {
1857         return m_colorClears;
1858     }
getDepthStencilClear(void) const1859     const Maybe<DepthStencilClear> &getDepthStencilClear(void) const
1860     {
1861         return m_depthStencilClear;
1862     }
1863 
getInputAttachmentCount(void) const1864     uint32_t getInputAttachmentCount(void) const
1865     {
1866         return (uint32_t)m_inputAttachments.size();
1867     }
getInputAttachmentIndex(uint32_t attachmentNdx) const1868     uint32_t getInputAttachmentIndex(uint32_t attachmentNdx) const
1869     {
1870         return m_inputAttachments[attachmentNdx].getAttachment();
1871     }
getInputAttachmentLayout(uint32_t attachmentNdx) const1872     VkImageLayout getInputAttachmentLayout(uint32_t attachmentNdx) const
1873     {
1874         return m_inputAttachments[attachmentNdx].getImageLayout();
1875     }
1876 
getColorAttachmentCount(void) const1877     uint32_t getColorAttachmentCount(void) const
1878     {
1879         return (uint32_t)m_colorAttachments.size();
1880     }
getColorAttachmentLayout(uint32_t attachmentNdx) const1881     VkImageLayout getColorAttachmentLayout(uint32_t attachmentNdx) const
1882     {
1883         return m_colorAttachments[attachmentNdx].getImageLayout();
1884     }
getColorAttachmentIndex(uint32_t attachmentNdx) const1885     uint32_t getColorAttachmentIndex(uint32_t attachmentNdx) const
1886     {
1887         return m_colorAttachments[attachmentNdx].getAttachment();
1888     }
getColorAttachment(uint32_t attachmentNdx) const1889     const Attachment &getColorAttachment(uint32_t attachmentNdx) const
1890     {
1891         return m_colorAttachmentInfo[attachmentNdx];
1892     }
getDepthStencilAttachmentLayout(void) const1893     Maybe<VkImageLayout> getDepthStencilAttachmentLayout(void) const
1894     {
1895         return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getImageLayout()) : tcu::Nothing;
1896     }
getDepthStencilAttachmentIndex(void) const1897     Maybe<uint32_t> getDepthStencilAttachmentIndex(void) const
1898     {
1899         return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getAttachment()) : tcu::Nothing;
1900     }
getDepthStencilAttachment(void) const1901     const Maybe<Attachment> &getDepthStencilAttachment(void) const
1902     {
1903         return m_depthStencilAttachmentInfo;
1904     }
getSubpassFlags(void) const1905     VkSubpassDescriptionFlags getSubpassFlags(void) const
1906     {
1907         return m_flags;
1908     }
1909 
1910 private:
1911     UVec2 m_viewportOffset;
1912     UVec2 m_viewportSize;
1913 
1914     uint32_t m_subpassIndex;
1915     uint32_t m_drawStartNdx;
1916     bool m_isSecondary;
1917     bool m_omitBlendState;
1918     VkSubpassDescriptionFlags m_flags;
1919 
1920     Maybe<RenderQuad> m_renderQuad;
1921     vector<ColorClear> m_colorClears;
1922     Maybe<DepthStencilClear> m_depthStencilClear;
1923 
1924     vector<AttachmentReference> m_colorAttachments;
1925     vector<Attachment> m_colorAttachmentInfo;
1926 
1927     Maybe<AttachmentReference> m_depthStencilAttachment;
1928     Maybe<Attachment> m_depthStencilAttachmentInfo;
1929 
1930     vector<AttachmentReference> m_inputAttachments;
1931 };
1932 
findColorAttachments(const RenderPass & renderPassInfo,std::vector<uint32_t> & colorAttachmentIndices,std::vector<VkFormat> & colorAttachmentFormats)1933 void findColorAttachments(const RenderPass &renderPassInfo, std::vector<uint32_t> &colorAttachmentIndices,
1934                           std::vector<VkFormat> &colorAttachmentFormats)
1935 {
1936     // make sure that colorAttachmentIndices and colorAttachmentFormats are empty
1937     DE_ASSERT(colorAttachmentIndices.empty() && colorAttachmentFormats.empty());
1938 
1939     const auto &allAttachments = renderPassInfo.getAttachments();
1940     const auto &allSubapsses   = renderPassInfo.getSubpasses();
1941 
1942     // find all unique color attachments
1943     for (const auto &subpass : allSubapsses)
1944     {
1945         for (const auto &colorAttachment : subpass.getColorAttachments())
1946         {
1947             uint32_t index = colorAttachment.getAttachment();
1948 
1949             // skip unused attachments
1950             if (index == VK_ATTACHMENT_UNUSED)
1951                 continue;
1952 
1953             // skip attachments that were already memorized
1954             if (std::find(colorAttachmentIndices.begin(), colorAttachmentIndices.end(), index) !=
1955                 colorAttachmentIndices.end())
1956                 continue;
1957 
1958             colorAttachmentIndices.push_back(index);
1959             colorAttachmentFormats.push_back(allAttachments[index].getFormat());
1960         }
1961     }
1962 }
1963 
1964 #ifndef CTS_USES_VULKANSC
1965 
findDepthStencilAttachments(const vector<Attachment> & allAttachments,VkFormat & depthFormat,VkFormat & stencilFormat,uint32_t & gloabalDepthAttachmentIndex,uint32_t & gloabalStencilAttachmentIndex)1966 void findDepthStencilAttachments(const vector<Attachment> &allAttachments, VkFormat &depthFormat,
1967                                  VkFormat &stencilFormat, uint32_t &gloabalDepthAttachmentIndex,
1968                                  uint32_t &gloabalStencilAttachmentIndex)
1969 {
1970     for (uint32_t i = 0; i < allAttachments.size(); ++i)
1971     {
1972         const auto &attachment = allAttachments[i];
1973         VkFormat vkFormat      = attachment.getFormat();
1974         const auto format      = mapVkFormat(vkFormat);
1975 
1976         if (tcu::hasDepthComponent(format.order))
1977         {
1978             depthFormat                 = vkFormat;
1979             gloabalDepthAttachmentIndex = i;
1980         }
1981         if (tcu::hasStencilComponent(format.order))
1982         {
1983             stencilFormat                 = vkFormat;
1984             gloabalStencilAttachmentIndex = i;
1985         }
1986     }
1987 }
1988 
fillRenderingAttachmentLocationsInfo(const std::vector<AttachmentReference> & subpassColorAttachments,const std::vector<uint32_t> & colorAttachmentIndices,std::vector<uint32_t> & colorAttachmentLocations,VkRenderingAttachmentLocationInfoKHR & renderingAttachmentLocationInfo)1989 void fillRenderingAttachmentLocationsInfo(const std::vector<AttachmentReference> &subpassColorAttachments,
1990                                           const std::vector<uint32_t> &colorAttachmentIndices,
1991                                           std::vector<uint32_t> &colorAttachmentLocations,
1992                                           VkRenderingAttachmentLocationInfoKHR &renderingAttachmentLocationInfo)
1993 {
1994     // make sure that colorAttachmentLocations vector has proper size
1995     DE_ASSERT(colorAttachmentLocations.size() == colorAttachmentIndices.size());
1996 
1997     renderingAttachmentLocationInfo.colorAttachmentCount      = (uint32_t)colorAttachmentLocations.size();
1998     renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocations.data();
1999 
2000     // fill color attachment locations for specified subpass
2001     for (uint32_t i = 0; i < (uint32_t)subpassColorAttachments.size(); ++i)
2002     {
2003         // translate index from list of all attachments to index in list of color attachments
2004         uint32_t index = subpassColorAttachments[i].getAttachment();
2005         for (uint32_t cai = 0; cai < (uint32_t)colorAttachmentIndices.size(); ++cai)
2006         {
2007             if (index != colorAttachmentIndices[cai])
2008                 continue;
2009             colorAttachmentLocations[cai] = i;
2010             break;
2011         }
2012     }
2013 }
2014 
fillRenderingInputAttachmentIndexInfo(const std::vector<AttachmentReference> & subpassInputAttachments,const std::vector<uint32_t> & colorAttachmentIndices,uint32_t globalDdepthAttachmentIndex,uint32_t globalStencilAttachmentIndex,uint32_t & localDepthAttachmentIndex,uint32_t & localStencilAttachmentIndex,std::vector<uint32_t> & colorAttachmentInputIndices,VkRenderingInputAttachmentIndexInfoKHR & renderingInputAttachmentIndexInfo)2015 void fillRenderingInputAttachmentIndexInfo(const std::vector<AttachmentReference> &subpassInputAttachments,
2016                                            const std::vector<uint32_t> &colorAttachmentIndices,
2017                                            uint32_t globalDdepthAttachmentIndex, uint32_t globalStencilAttachmentIndex,
2018                                            uint32_t &localDepthAttachmentIndex, uint32_t &localStencilAttachmentIndex,
2019                                            std::vector<uint32_t> &colorAttachmentInputIndices,
2020                                            VkRenderingInputAttachmentIndexInfoKHR &renderingInputAttachmentIndexInfo)
2021 {
2022     localDepthAttachmentIndex   = VK_ATTACHMENT_UNUSED;
2023     localStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
2024 
2025     for (uint32_t i = 0; i < (uint32_t)subpassInputAttachments.size(); ++i)
2026     {
2027         uint32_t index = subpassInputAttachments[i].getAttachment();
2028 
2029         if (index == globalDdepthAttachmentIndex)
2030             localDepthAttachmentIndex = i;
2031         if (index == globalStencilAttachmentIndex)
2032             localStencilAttachmentIndex = i;
2033 
2034         // translate index from list of all attachments to index in list of color attachments
2035         for (uint32_t cai = 0; cai < (uint32_t)colorAttachmentIndices.size(); ++cai)
2036         {
2037             if (index != colorAttachmentIndices[cai])
2038                 continue;
2039             colorAttachmentInputIndices[cai] = i;
2040             break;
2041         }
2042     }
2043 
2044     renderingInputAttachmentIndexInfo.colorAttachmentCount         = (uint32_t)colorAttachmentInputIndices.size();
2045     renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentInputIndices.data();
2046     renderingInputAttachmentIndexInfo.pDepthInputAttachmentIndex =
2047         (globalDdepthAttachmentIndex == VK_ATTACHMENT_UNUSED) ? DE_NULL : &localDepthAttachmentIndex;
2048     renderingInputAttachmentIndexInfo.pStencilInputAttachmentIndex =
2049         (globalStencilAttachmentIndex == VK_ATTACHMENT_UNUSED) ? DE_NULL : &localStencilAttachmentIndex;
2050 }
2051 
prepareAttachmentRemapping(const Subpass & subpass,const std::vector<Attachment> & allAttachments,const std::vector<uint32_t> & colorAttachmentIndices,std::vector<uint32_t> & colorAttachmentLocations,std::vector<uint32_t> & colorAttachmentInputIndices,uint32_t & localDepthAttachmentIndex,uint32_t & localStencilAttachmentIndex,VkRenderingAttachmentLocationInfoKHR & renderingAttachmentLocationInfo,VkRenderingInputAttachmentIndexInfoKHR & renderingInputAttachmentIndexInfo)2052 void prepareAttachmentRemapping(const Subpass &subpass, const std::vector<Attachment> &allAttachments,
2053                                 const std::vector<uint32_t> &colorAttachmentIndices,
2054                                 std::vector<uint32_t> &colorAttachmentLocations,
2055                                 std::vector<uint32_t> &colorAttachmentInputIndices, uint32_t &localDepthAttachmentIndex,
2056                                 uint32_t &localStencilAttachmentIndex,
2057                                 VkRenderingAttachmentLocationInfoKHR &renderingAttachmentLocationInfo,
2058                                 VkRenderingInputAttachmentIndexInfoKHR &renderingInputAttachmentIndexInfo)
2059 {
2060     VkFormat depthFormat                  = VK_FORMAT_UNDEFINED;
2061     VkFormat stencilFormat                = VK_FORMAT_UNDEFINED;
2062     uint32_t globalDepthAttachmentIndex   = VK_ATTACHMENT_UNUSED;
2063     uint32_t globalStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
2064 
2065     findDepthStencilAttachments(allAttachments, depthFormat, stencilFormat, globalDepthAttachmentIndex,
2066                                 globalStencilAttachmentIndex);
2067 
2068     fillRenderingAttachmentLocationsInfo(subpass.getColorAttachments(), colorAttachmentIndices,
2069                                          colorAttachmentLocations, renderingAttachmentLocationInfo);
2070 
2071     fillRenderingInputAttachmentIndexInfo(subpass.getInputAttachments(), colorAttachmentIndices,
2072                                           globalDepthAttachmentIndex, globalStencilAttachmentIndex,
2073                                           localDepthAttachmentIndex, localStencilAttachmentIndex,
2074                                           colorAttachmentInputIndices, renderingInputAttachmentIndexInfo);
2075 }
2076 
2077 #endif // CTS_USES_VULKANSC
2078 
beginCommandBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkRenderPass pInheritanceInfo_renderPass,uint32_t pInheritanceInfo_subpass,VkFramebuffer pInheritanceInfo_framebuffer,VkBool32 pInheritanceInfo_occlusionQueryEnable,VkQueryControlFlags pInheritanceInfo_queryFlags,VkQueryPipelineStatisticFlags pInheritanceInfo_pipelineStatistics,const RenderPass * pRenderPassInfo=0,const SubpassRenderInfo * pSubpassInfo=0,bool dynamicRenderPass=false,bool secondaryCmdBufferCompletelyContainsRenderpass=false)2079 void beginCommandBuffer(const DeviceInterface &vk, VkCommandBuffer cmdBuffer, VkRenderPass pInheritanceInfo_renderPass,
2080                         uint32_t pInheritanceInfo_subpass, VkFramebuffer pInheritanceInfo_framebuffer,
2081                         VkBool32 pInheritanceInfo_occlusionQueryEnable, VkQueryControlFlags pInheritanceInfo_queryFlags,
2082                         VkQueryPipelineStatisticFlags pInheritanceInfo_pipelineStatistics,
2083                         const RenderPass *pRenderPassInfo = 0, const SubpassRenderInfo *pSubpassInfo = 0,
2084                         bool dynamicRenderPass = false, bool secondaryCmdBufferCompletelyContainsRenderpass = false)
2085 {
2086     VkCommandBufferUsageFlags usageFlags = (VkCommandBufferUsageFlags)0;
2087     VkCommandBufferInheritanceInfo pInheritanceInfo{
2088         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
2089         DE_NULL,
2090         pInheritanceInfo_renderPass,
2091         pInheritanceInfo_subpass,
2092         pInheritanceInfo_framebuffer,
2093         pInheritanceInfo_occlusionQueryEnable,
2094         pInheritanceInfo_queryFlags,
2095         pInheritanceInfo_pipelineStatistics,
2096     };
2097 
2098 #ifndef CTS_USES_VULKANSC
2099 
2100     VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo  = initVulkanStructure();
2101     VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
2102     VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo =
2103         initVulkanStructure(&renderingAttachmentLocationInfo);
2104     std::vector<uint32_t> colorAttachmentIndices;
2105     std::vector<VkFormat> colorAttachmentFormats;
2106     std::vector<uint32_t> colorAttachmentLocations;
2107     std::vector<uint32_t> colorAttachmentInputIndices;
2108     uint32_t localDepthAttachmentIndex   = VK_ATTACHMENT_UNUSED;
2109     uint32_t localStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
2110 
2111     if (dynamicRenderPass && pSubpassInfo)
2112     {
2113         findColorAttachments(*pRenderPassInfo, colorAttachmentIndices, colorAttachmentFormats);
2114 
2115         const auto subpassIndex       = pSubpassInfo->getSubpassIndex();
2116         const auto &allAttachments    = pRenderPassInfo->getAttachments();
2117         const auto &subpass           = pRenderPassInfo->getSubpasses()[subpassIndex];
2118         uint32_t colorAttachmentCount = (uint32_t)colorAttachmentIndices.size();
2119 
2120         for (uint32_t i = 0; i < colorAttachmentCount; ++i)
2121         {
2122             colorAttachmentLocations.push_back(VK_ATTACHMENT_UNUSED);
2123             colorAttachmentInputIndices.push_back(VK_ATTACHMENT_UNUSED);
2124         }
2125 
2126         if (secondaryCmdBufferCompletelyContainsRenderpass)
2127             inheritanceRenderingInfo.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
2128         else
2129             usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
2130 
2131         inheritanceRenderingInfo.colorAttachmentCount    = static_cast<uint32_t>(colorAttachmentFormats.size());
2132         inheritanceRenderingInfo.pColorAttachmentFormats = colorAttachmentFormats.data();
2133         if (pSubpassInfo->getDepthStencilAttachment())
2134         {
2135             const VkFormat dsFormat = pSubpassInfo->getDepthStencilAttachment()->getFormat();
2136             inheritanceRenderingInfo.depthAttachmentFormat =
2137                 tcu::hasDepthComponent(mapVkFormat(dsFormat).order) ? dsFormat : VK_FORMAT_UNDEFINED;
2138             inheritanceRenderingInfo.stencilAttachmentFormat =
2139                 tcu::hasStencilComponent(mapVkFormat(dsFormat).order) ? dsFormat : VK_FORMAT_UNDEFINED;
2140         }
2141 
2142         if (pSubpassInfo->getColorAttachmentCount())
2143             inheritanceRenderingInfo.rasterizationSamples = pSubpassInfo->getColorAttachment(0).getSamples();
2144         else if (pSubpassInfo->getDepthStencilAttachment())
2145             inheritanceRenderingInfo.rasterizationSamples = pSubpassInfo->getDepthStencilAttachment()->getSamples();
2146         else
2147             inheritanceRenderingInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
2148 
2149         pInheritanceInfo.pNext = &inheritanceRenderingInfo;
2150 
2151         if (subpassIndex > 0)
2152         {
2153             prepareAttachmentRemapping(subpass, allAttachments, colorAttachmentIndices, colorAttachmentLocations,
2154                                        colorAttachmentInputIndices, localDepthAttachmentIndex,
2155                                        localStencilAttachmentIndex, renderingAttachmentLocationInfo,
2156                                        renderingInputAttachmentIndexInfo);
2157 
2158             inheritanceRenderingInfo.pNext = &renderingInputAttachmentIndexInfo;
2159         }
2160     }
2161     else if (!secondaryCmdBufferCompletelyContainsRenderpass)
2162         usageFlags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
2163 #else
2164 
2165     DE_UNREF(pRenderPassInfo);
2166     DE_UNREF(pSubpassInfo);
2167     DE_UNREF(dynamicRenderPass);
2168     DE_UNREF(secondaryCmdBufferCompletelyContainsRenderpass);
2169 
2170     usageFlags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
2171 
2172 #endif // CTS_USES_VULKANSC
2173 
2174     const VkCommandBufferBeginInfo pBeginInfo{
2175         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2176         DE_NULL,
2177         usageFlags,
2178         &pInheritanceInfo,
2179     };
2180     VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &pBeginInfo));
2181 }
2182 
2183 #ifndef CTS_USES_VULKANSC
beginDynamicRendering(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const RenderPass & renderPassInfo,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const VkRect2D & renderArea,const vector<Maybe<VkClearValue>> & renderPassClearValues,const VkRenderingFlagsKHR renderingFlags=0u)2184 void beginDynamicRendering(const DeviceInterface &vk, VkCommandBuffer commandBuffer, const RenderPass &renderPassInfo,
2185                            const vector<de::SharedPtr<AttachmentResources>> &attachmentResources,
2186                            const VkRect2D &renderArea, const vector<Maybe<VkClearValue>> &renderPassClearValues,
2187                            const VkRenderingFlagsKHR renderingFlags = 0u)
2188 {
2189     const float clearNan             = tcu::Float32::nan().asFloat();
2190     const VkClearValue clearValueNan = makeClearValueColorF32(clearNan, clearNan, clearNan, clearNan);
2191     const auto &allSubpasses         = renderPassInfo.getSubpasses();
2192 
2193     // define helper lambda that will check if attachment is used as an input for one of subpasses
2194     auto isAttachmentUsedAsInput = [&allSubpasses](uint32_t attachment)
2195     {
2196         for (const auto &subpass : allSubpasses)
2197         {
2198             for (const auto &inputAttachment : subpass.getInputAttachments())
2199             {
2200                 if (inputAttachment.getAttachment() == attachment)
2201                     return true;
2202             }
2203         }
2204         return false;
2205     };
2206 
2207     // find all color attachments and their resolve attachments
2208     struct ColorAttachmentData
2209     {
2210         uint32_t colorAttachmentIndex;
2211         VkImageLayout colorImageLayout;
2212         uint32_t resolveAttachmentIndex;
2213         VkImageLayout resolveImageLayout;
2214 
2215         // constructor needed for emplace_back
2216         ColorAttachmentData(uint32_t ci, VkImageLayout cl, uint32_t ri, VkImageLayout rl)
2217             : colorAttachmentIndex(ci)
2218             , colorImageLayout(cl)
2219             , resolveAttachmentIndex(ri)
2220             , resolveImageLayout(rl)
2221         {
2222         }
2223     };
2224     std::vector<ColorAttachmentData> colorAttachmentsData;
2225     for (const auto &subpass : allSubpasses)
2226     {
2227         const auto &colorAttachmentsInfo   = subpass.getColorAttachments();
2228         const auto &resolveAttachmentsInfo = subpass.getResolveAttachments();
2229 
2230         for (uint32_t i = 0; i < (uint32_t)colorAttachmentsInfo.size(); ++i)
2231         {
2232             const AttachmentReference *colorAttachment = &colorAttachmentsInfo[i];
2233             uint32_t colorAttachmentIndex              = colorAttachment->getAttachment();
2234 
2235             // check if this attachment is already in colorAttachmentsData,
2236             // we are interested only in first occurrence
2237             bool skipAttachement = false;
2238             for (const auto &cad : colorAttachmentsData)
2239             {
2240                 skipAttachement = (colorAttachmentIndex == cad.colorAttachmentIndex);
2241                 if (skipAttachement)
2242                     break;
2243             }
2244             if (skipAttachement)
2245                 continue;
2246 
2247             VkImageLayout colorImageLayout = colorAttachment->getImageLayout();
2248             if (isAttachmentUsedAsInput(colorAttachmentIndex))
2249                 colorImageLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
2250 
2251             uint32_t resolveAttachmentIndex  = VK_ATTACHMENT_UNUSED;
2252             VkImageLayout resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
2253             if (!resolveAttachmentsInfo.empty())
2254             {
2255                 // assume that if there are resolve attachments then there will be
2256                 // as much of them as there are color attachments and index will match
2257                 DE_ASSERT(colorAttachmentsInfo.size() == resolveAttachmentsInfo.size());
2258 
2259                 resolveAttachmentIndex = resolveAttachmentsInfo[i].getAttachment();
2260                 resolveImageLayout     = resolveAttachmentsInfo[i].getImageLayout();
2261                 if (isAttachmentUsedAsInput(resolveAttachmentIndex))
2262                     resolveImageLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
2263             }
2264 
2265             colorAttachmentsData.emplace_back(colorAttachmentIndex, colorImageLayout, resolveAttachmentIndex,
2266                                               resolveImageLayout);
2267         }
2268     }
2269 
2270     // alocate space for all needed rendering attachments
2271     VkRenderingAttachmentInfoKHR depthAttachment{
2272         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
2273         DE_NULL,                                             // const void* pNext;
2274         DE_NULL,                                             // VkImageView imageView;
2275         VK_IMAGE_LAYOUT_UNDEFINED,                           // VkImageLayout imageLayout;
2276         VK_RESOLVE_MODE_NONE,                                // VkResolveModeFlagBits resolveMode;
2277         DE_NULL,                                             // VkImageView resolveImageView;
2278         VK_IMAGE_LAYOUT_UNDEFINED,                           // VkImageLayout resolveImageLayout;
2279         VK_ATTACHMENT_LOAD_OP_LOAD,                          // VkAttachmentLoadOp loadOp;
2280         VK_ATTACHMENT_STORE_OP_STORE,                        // VkAttachmentStoreOp storeOp;
2281         clearValueNan                                        // VkClearValue clearValue;
2282     };
2283     VkRenderingAttachmentInfoKHR stencilAttachment = depthAttachment;
2284     std::vector<vk::VkRenderingAttachmentInfoKHR> colorAttachmentVect(colorAttachmentsData.size(), depthAttachment);
2285 
2286     // translate structures that were prepared to construct renderpass object to structures needed for dynamic rendering
2287     const auto &allAttachments = renderPassInfo.getAttachments();
2288     for (uint32_t i = 0; i < (uint32_t)colorAttachmentsData.size(); ++i)
2289     {
2290         auto &colorAttachment                 = colorAttachmentVect[i];
2291         const auto &colorAttachmentData       = colorAttachmentsData[i];
2292         const uint32_t colorAttachmentIndex   = colorAttachmentData.colorAttachmentIndex;
2293         const uint32_t resolveAttachmentIndex = colorAttachmentData.resolveAttachmentIndex;
2294 
2295         colorAttachment.imageView   = attachmentResources[colorAttachmentIndex]->getAttachmentView();
2296         colorAttachment.imageLayout = colorAttachmentData.colorImageLayout;
2297         colorAttachment.loadOp      = allAttachments[colorAttachmentIndex].getLoadOp();
2298         colorAttachment.storeOp     = allAttachments[colorAttachmentIndex].getStoreOp();
2299 
2300         if (renderPassClearValues[colorAttachmentIndex])
2301             colorAttachment.clearValue = *renderPassClearValues[colorAttachmentIndex];
2302 
2303         if (resolveAttachmentIndex != VK_ATTACHMENT_UNUSED)
2304         {
2305             colorAttachment.resolveMode        = VK_RESOLVE_MODE_AVERAGE_BIT;
2306             colorAttachment.resolveImageView   = attachmentResources[resolveAttachmentIndex]->getAttachmentView();
2307             colorAttachment.resolveImageLayout = colorAttachmentData.resolveImageLayout;
2308         }
2309     }
2310 
2311     uint32_t dsAttachmentIndex                       = VK_ATTACHMENT_UNUSED;
2312     VkImageLayout dsAttachmentLayout                 = VK_IMAGE_LAYOUT_UNDEFINED;
2313     VkRenderingAttachmentInfoKHR *pDepthAttachment   = DE_NULL;
2314     VkRenderingAttachmentInfoKHR *pStencilAttachment = DE_NULL;
2315 
2316     // find depth/stencil attachment and translate its data to dynamic rendering attachment
2317     for (const Subpass &subpass : allSubpasses)
2318     {
2319         const auto &depthStencilAttachmentReference = subpass.getDepthStencilAttachment();
2320         dsAttachmentIndex                           = depthStencilAttachmentReference.getAttachment();
2321         dsAttachmentLayout                          = depthStencilAttachmentReference.getImageLayout();
2322         if (dsAttachmentIndex != VK_ATTACHMENT_UNUSED)
2323             break;
2324     }
2325 
2326     if (dsAttachmentIndex != VK_ATTACHMENT_UNUSED)
2327     {
2328         const Attachment &dsAttachmentInfo = allAttachments[dsAttachmentIndex];
2329         const tcu::TextureFormat format    = mapVkFormat(dsAttachmentInfo.getFormat());
2330 
2331         if (tcu::hasDepthComponent(format.order))
2332         {
2333             depthAttachment.imageView   = attachmentResources[dsAttachmentIndex]->getAttachmentView();
2334             depthAttachment.imageLayout = dsAttachmentLayout;
2335             depthAttachment.loadOp      = dsAttachmentInfo.getLoadOp();
2336             depthAttachment.storeOp     = dsAttachmentInfo.getStoreOp();
2337 
2338             if (isAttachmentUsedAsInput(dsAttachmentIndex))
2339                 depthAttachment.imageLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
2340             if (renderPassClearValues[dsAttachmentIndex])
2341                 depthAttachment.clearValue = *renderPassClearValues[dsAttachmentIndex];
2342 
2343             pDepthAttachment = &depthAttachment;
2344         }
2345 
2346         if (tcu::hasStencilComponent(format.order))
2347         {
2348             stencilAttachment.imageView   = attachmentResources[dsAttachmentIndex]->getAttachmentView();
2349             stencilAttachment.imageLayout = dsAttachmentLayout;
2350             stencilAttachment.loadOp      = dsAttachmentInfo.getStencilLoadOp();
2351             stencilAttachment.storeOp     = dsAttachmentInfo.getStencilStoreOp();
2352 
2353             if (isAttachmentUsedAsInput(dsAttachmentIndex))
2354                 stencilAttachment.imageLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
2355             if (renderPassClearValues[dsAttachmentIndex])
2356                 stencilAttachment.clearValue = *renderPassClearValues[dsAttachmentIndex];
2357 
2358             pStencilAttachment = &stencilAttachment;
2359         }
2360     }
2361 
2362     VkRenderingInfoKHR renderingInfo{
2363         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
2364         DE_NULL,
2365         renderingFlags,                                    // VkRenderingFlagsKHR flags;
2366         renderArea,                                        // VkRect2D renderArea;
2367         1u,                                                // uint32_t layerCount;
2368         0u,                                                // uint32_t viewMask;
2369         static_cast<uint32_t>(colorAttachmentVect.size()), // uint32_t colorAttachmentCount;
2370         de::dataOrNull(colorAttachmentVect),               // const VkRenderingAttachmentInfoKHR* pColorAttachments;
2371         pDepthAttachment,                                  // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
2372         pStencilAttachment                                 // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
2373     };
2374 
2375     vk.cmdBeginRendering(commandBuffer, &renderingInfo);
2376 }
2377 
endDynamicRendering(const DeviceInterface & vk,VkCommandBuffer commandBuffer)2378 void endDynamicRendering(const DeviceInterface &vk, VkCommandBuffer commandBuffer)
2379 {
2380     vk.cmdEndRendering(commandBuffer);
2381 }
2382 
2383 #endif // CTS_USES_VULKANSC
2384 
2385 class SubpassRenderer
2386 {
2387 public:
SubpassRenderer(Context & context,const DeviceInterface & vk,VkDevice device,Allocator & allocator,const RenderPass & renderPassInfo,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const VkRect2D & renderArea,const vector<Maybe<VkClearValue>> & renderPassClearValues,VkRenderPass renderPass,VkFramebuffer framebuffer,VkCommandPool commandBufferPool,uint32_t queueFamilyIndex,const vector<VkImage> & attachmentImages,const vector<pair<VkImageView,VkImageView>> & attachmentViews,const SubpassRenderInfo & renderInfo,const TestConfig & config)2388     SubpassRenderer(Context &context, const DeviceInterface &vk, VkDevice device, Allocator &allocator,
2389                     const RenderPass &renderPassInfo,
2390                     const vector<de::SharedPtr<AttachmentResources>> &attachmentResources, const VkRect2D &renderArea,
2391                     const vector<Maybe<VkClearValue>> &renderPassClearValues, VkRenderPass renderPass,
2392                     VkFramebuffer framebuffer, VkCommandPool commandBufferPool, uint32_t queueFamilyIndex,
2393                     const vector<VkImage> &attachmentImages,
2394                     const vector<pair<VkImageView, VkImageView>> &attachmentViews, const SubpassRenderInfo &renderInfo,
2395                     const TestConfig &config)
2396         : m_renderInfo(renderInfo)
2397         , m_renderPassInfo(renderPassInfo)
2398         , m_pipeline(context.getInstanceInterface(), vk, context.getPhysicalDevice(), device,
2399                      context.getDeviceExtensions(), config.groupParams->pipelineConstructionType)
2400     {
2401         // unreference values not used by Vulkan SC, no need to put this under ifdef
2402         DE_UNREF(attachmentResources);
2403         DE_UNREF(renderArea);
2404         DE_UNREF(renderPassClearValues);
2405 
2406         const InstanceInterface &vki              = context.getInstanceInterface();
2407         const VkPhysicalDevice &physDevice        = context.getPhysicalDevice();
2408         const vector<Attachment> &attachmentInfos = m_renderPassInfo.getAttachments();
2409         const uint32_t subpassIndex               = renderInfo.getSubpassIndex();
2410         const bool dynamicRendering(config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING);
2411         vector<VkDescriptorSetLayoutBinding> bindings;
2412 
2413         for (uint32_t colorAttachmentNdx = 0; colorAttachmentNdx < renderInfo.getColorAttachmentCount();
2414              colorAttachmentNdx++)
2415         {
2416             const uint32_t attachmentNdx =
2417                 (renderInfo.getColorAttachmentIndex(colorAttachmentNdx) == VK_ATTACHMENT_UNUSED) ?
2418                     colorAttachmentNdx :
2419                     renderInfo.getColorAttachmentIndex(colorAttachmentNdx);
2420 
2421             m_colorAttachmentImages.push_back(attachmentImages[attachmentNdx]);
2422         }
2423 
2424         if (renderInfo.getDepthStencilAttachmentIndex())
2425             m_depthStencilAttachmentImage = attachmentImages[*renderInfo.getDepthStencilAttachmentIndex()];
2426 
2427         if (renderInfo.getRenderQuad())
2428         {
2429             const RenderQuad &renderQuad = *renderInfo.getRenderQuad();
2430 
2431             if (renderInfo.getInputAttachmentCount() > 0)
2432             {
2433                 uint32_t bindingIndex = 0;
2434 
2435                 for (uint32_t inputAttachmentNdx = 0; inputAttachmentNdx < renderInfo.getInputAttachmentCount();
2436                      inputAttachmentNdx++)
2437                 {
2438                     const Attachment attachmentInfo =
2439                         attachmentInfos[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)];
2440                     const VkImageLayout layout      = renderInfo.getInputAttachmentLayout(inputAttachmentNdx);
2441                     const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
2442                     const bool isDepthFormat        = tcu::hasDepthComponent(format.order);
2443                     const bool isStencilFormat      = tcu::hasStencilComponent(format.order);
2444                     const uint32_t bindingCount =
2445                         (isDepthFormat && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) &&
2446                                 (isStencilFormat &&
2447                                  layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) ?
2448                             2u :
2449                             1u;
2450 
2451                     for (uint32_t bindingNdx = 0; bindingNdx < bindingCount; bindingNdx++)
2452                     {
2453                         const VkDescriptorSetLayoutBinding binding = {bindingIndex,
2454                                                                       vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u,
2455                                                                       vk::VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL};
2456 
2457                         bindings.push_back(binding);
2458                         bindingIndex++;
2459                     }
2460                 }
2461 
2462                 const VkDescriptorSetLayoutCreateInfo createInfo = {
2463                     vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, DE_NULL,
2464 
2465                     0u, (uint32_t)bindings.size(), &bindings[0]};
2466 
2467                 m_descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &createInfo);
2468             }
2469 
2470             const VkDescriptorSetLayout descriptorSetLayout = *m_descriptorSetLayout;
2471 
2472             m_vertexShaderModule =
2473                 ShaderWrapper(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-vert"), 0u);
2474             m_fragmentShaderModule =
2475                 ShaderWrapper(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-frag"), 0u);
2476             m_pipelineLayout = PipelineLayoutWrapper(config.groupParams->pipelineConstructionType, vk, device,
2477                                                      (m_descriptorSetLayout ? descriptorSetLayout : DE_NULL));
2478             createSubpassPipeline(renderPass);
2479 
2480             // Round up the vertex buffer size to honor nonCoherentAtomSize.
2481             const auto properties =
2482                 vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2483             const auto vertexBufferSize = de::roundUp(static_cast<VkDeviceSize>(renderQuad.getVertexDataSize()),
2484                                                       properties.limits.nonCoherentAtomSize);
2485 
2486             m_vertexBuffer       = createBuffer(vk, device, 0u, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2487                                                 VK_SHARING_MODE_EXCLUSIVE, 1u, &queueFamilyIndex);
2488             m_vertexBufferMemory = allocateBuffer(vki, vk, physDevice, device, *m_vertexBuffer,
2489                                                   MemoryRequirement::HostVisible, allocator, config.allocationKind);
2490 
2491             bindBufferMemory(vk, device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(),
2492                              m_vertexBufferMemory->getOffset());
2493 
2494             uploadBufferData(vk, device, *m_vertexBufferMemory, renderQuad.getVertexDataSize(),
2495                              renderQuad.getVertexPointer(), properties.limits.nonCoherentAtomSize);
2496 
2497             if (renderInfo.getInputAttachmentCount() > 0)
2498             {
2499                 {
2500                     const VkDescriptorPoolSize poolSize = {
2501                         vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
2502                         // \note Reserve 2 per input attachment since depthStencil attachments require 2.
2503                         renderInfo.getInputAttachmentCount() * 2u};
2504                     const VkDescriptorPoolCreateInfo createInfo = {
2505                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, DE_NULL,
2506                         VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
2507 
2508                         // \note Reserve 2 per input attachment since depthStencil attachments require 2.
2509                         renderInfo.getInputAttachmentCount() * 2u, 1u, &poolSize};
2510 
2511                     m_descriptorPool = vk::createDescriptorPool(vk, device, &createInfo);
2512                 }
2513                 {
2514                     const VkDescriptorSetAllocateInfo allocateInfo = {
2515                         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
2516 
2517                         *m_descriptorPool, 1u, &descriptorSetLayout};
2518 
2519                     m_descriptorSet = vk::allocateDescriptorSet(vk, device, &allocateInfo);
2520                 }
2521                 {
2522                     vector<VkWriteDescriptorSet> writes(bindings.size());
2523                     vector<VkDescriptorImageInfo> imageInfos(bindings.size());
2524                     uint32_t bindingIndex = 0;
2525 
2526                     for (uint32_t inputAttachmentNdx = 0; inputAttachmentNdx < renderInfo.getInputAttachmentCount();
2527                          inputAttachmentNdx++)
2528                     {
2529                         const Attachment attachmentInfo =
2530                             attachmentInfos[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)];
2531                         const tcu::TextureFormat format     = mapVkFormat(attachmentInfo.getFormat());
2532                         const bool isDepthFormat            = tcu::hasDepthComponent(format.order);
2533                         const bool isStencilFormat          = tcu::hasStencilComponent(format.order);
2534                         VkImageLayout inputAttachmentLayout = renderInfo.getInputAttachmentLayout(inputAttachmentNdx);
2535 
2536                         if (isDepthFormat && isStencilFormat)
2537                         {
2538                             if (inputAttachmentLayout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
2539                             {
2540                                 imageInfos[bindingIndex] = {
2541                                     (VkSampler)0,
2542                                     attachmentViews[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)].first,
2543                                     inputAttachmentLayout};
2544 #ifndef CTS_USES_VULKANSC
2545                                 if (dynamicRendering)
2546                                     imageInfos[bindingIndex].imageLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
2547 #endif
2548                                 {
2549                                     const VkWriteDescriptorSet write = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2550                                                                         DE_NULL,
2551 
2552                                                                         *m_descriptorSet,
2553                                                                         bindingIndex,
2554                                                                         0u,
2555                                                                         1u,
2556                                                                         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
2557                                                                         &imageInfos[bindingIndex],
2558                                                                         DE_NULL,
2559                                                                         DE_NULL};
2560                                     writes[bindingIndex]             = write;
2561 
2562                                     bindingIndex++;
2563                                 }
2564                             }
2565 
2566                             if (inputAttachmentLayout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
2567                             {
2568                                 imageInfos[bindingIndex] = {
2569                                     (VkSampler)0,
2570                                     attachmentViews[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)].second,
2571                                     inputAttachmentLayout};
2572 #ifndef CTS_USES_VULKANSC
2573                                 if (dynamicRendering)
2574                                     imageInfos[bindingIndex].imageLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
2575 #endif
2576                                 {
2577                                     const VkWriteDescriptorSet write = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2578                                                                         DE_NULL,
2579 
2580                                                                         *m_descriptorSet,
2581                                                                         bindingIndex,
2582                                                                         0u,
2583                                                                         1u,
2584                                                                         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
2585                                                                         &imageInfos[bindingIndex],
2586                                                                         DE_NULL,
2587                                                                         DE_NULL};
2588                                     writes[bindingIndex]             = write;
2589 
2590                                     bindingIndex++;
2591                                 }
2592                             }
2593                         }
2594                         else
2595                         {
2596                             imageInfos[bindingIndex] = {
2597                                 (VkSampler)0,
2598                                 attachmentViews[renderInfo.getInputAttachmentIndex(inputAttachmentNdx)].first,
2599                                 inputAttachmentLayout};
2600 #ifndef CTS_USES_VULKANSC
2601                             if (dynamicRendering)
2602                                 imageInfos[bindingIndex].imageLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
2603 #endif
2604                             {
2605                                 const VkWriteDescriptorSet write = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2606                                                                     DE_NULL,
2607 
2608                                                                     *m_descriptorSet,
2609                                                                     bindingIndex,
2610                                                                     0u,
2611                                                                     1u,
2612                                                                     VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
2613                                                                     &imageInfos[bindingIndex],
2614                                                                     DE_NULL,
2615                                                                     DE_NULL};
2616                                 writes[bindingIndex]             = write;
2617 
2618                                 bindingIndex++;
2619                             }
2620                         }
2621                     }
2622 
2623                     vk.updateDescriptorSets(device, (uint32_t)writes.size(), &writes[0], 0u, DE_NULL);
2624                 }
2625             }
2626         }
2627 
2628         if (renderInfo.isSecondary())
2629         {
2630             bool secondaryCmdBufferCompletelyContainsDynamicRenderpass =
2631                 (config.commandBufferTypes == TestConfig::COMMANDBUFFERTYPES_SECONDARY) &&
2632                 config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass;
2633 
2634             m_commandBuffer = allocateCommandBuffer(vk, device, commandBufferPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2635 
2636             beginCommandBuffer(vk, *m_commandBuffer, renderPass, subpassIndex, framebuffer, VK_FALSE,
2637                                (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0, &m_renderPassInfo, &renderInfo,
2638                                dynamicRendering, secondaryCmdBufferCompletelyContainsDynamicRenderpass);
2639 
2640             if (dynamicRendering && secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2641             {
2642 #ifndef CTS_USES_VULKANSC
2643                 beginDynamicRendering(vk, *m_commandBuffer, m_renderPassInfo, attachmentResources, renderArea,
2644                                       renderPassClearValues);
2645                 pushRenderCommands(vk, *m_commandBuffer, true, dynamicRendering);
2646                 endDynamicRendering(vk, *m_commandBuffer);
2647 #endif // CTS_USES_VULKANSC
2648             }
2649             else
2650                 pushRenderCommands(vk, *m_commandBuffer, true, dynamicRendering);
2651 
2652             endCommandBuffer(vk, *m_commandBuffer);
2653         }
2654     }
2655 
isSecondary(void) const2656     bool isSecondary(void) const
2657     {
2658         return !!m_commandBuffer;
2659     }
2660 
getCommandBuffer(void) const2661     VkCommandBuffer getCommandBuffer(void) const
2662     {
2663         DE_ASSERT(isSecondary());
2664         return *m_commandBuffer;
2665     }
2666 
pushRenderCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const bool secondaryCommandBuffer,const bool dynamicRendering)2667     void pushRenderCommands(const DeviceInterface &vk, VkCommandBuffer commandBuffer, const bool secondaryCommandBuffer,
2668                             const bool dynamicRendering)
2669     {
2670         DE_UNREF(secondaryCommandBuffer);
2671 
2672         VkImageLayout inputAttachmenLayout = VK_IMAGE_LAYOUT_GENERAL;
2673 
2674         std::vector<uint32_t> colorAttachmentIndices;
2675         std::vector<VkFormat> colorAttachmentFormats;
2676         findColorAttachments(m_renderPassInfo, colorAttachmentIndices, colorAttachmentFormats);
2677 
2678 #ifndef CTS_USES_VULKANSC
2679         if (dynamicRendering && (m_renderPassInfo.getSubpasses().size() > 1u))
2680         {
2681             inputAttachmenLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
2682             if (!secondaryCommandBuffer)
2683             {
2684                 const uint32_t subpassIndex              = m_renderInfo.getSubpassIndex();
2685                 const std::vector<Subpass> &allSubapsses = m_renderPassInfo.getSubpasses();
2686                 const auto &allAttachments               = m_renderPassInfo.getAttachments();
2687                 const auto &subpass                      = allSubapsses[subpassIndex];
2688                 uint32_t colorAttachmentCount            = (uint32_t)colorAttachmentIndices.size();
2689                 std::vector<uint32_t> colorAttachmentLocations(colorAttachmentCount, VK_ATTACHMENT_UNUSED);
2690                 std::vector<uint32_t> colorAttachmentInputIndices(colorAttachmentCount, VK_ATTACHMENT_UNUSED);
2691                 uint32_t localDepthAttachmentIndex                                       = VK_ATTACHMENT_UNUSED;
2692                 uint32_t localStencilAttachmentIndex                                     = VK_ATTACHMENT_UNUSED;
2693                 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo     = initVulkanStructure();
2694                 VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo = initVulkanStructure();
2695 
2696                 prepareAttachmentRemapping(subpass, allAttachments, colorAttachmentIndices, colorAttachmentLocations,
2697                                            colorAttachmentInputIndices, localDepthAttachmentIndex,
2698                                            localStencilAttachmentIndex, renderingAttachmentLocationInfo,
2699                                            renderingInputAttachmentIndexInfo);
2700 
2701                 vk.cmdSetRenderingAttachmentLocationsKHR(commandBuffer, &renderingAttachmentLocationInfo);
2702                 vk.cmdSetRenderingInputAttachmentIndicesKHR(commandBuffer, &renderingInputAttachmentIndexInfo);
2703             }
2704         }
2705 #endif // CTS_USES_VULKANSC
2706 
2707         if (!m_renderInfo.getColorClears().empty())
2708         {
2709             const vector<ColorClear> &colorClears(m_renderInfo.getColorClears());
2710 
2711             for (uint32_t attachmentNdx = 0; attachmentNdx < m_renderInfo.getColorAttachmentCount(); attachmentNdx++)
2712             {
2713                 uint32_t colorAttachment = attachmentNdx;
2714 
2715                 // for dynamic rendering we need to translate color attachment index from list of all attachments
2716                 // to index related to all color attachments specified in dynammic renderpass
2717                 if (dynamicRendering)
2718                 {
2719                     for (colorAttachment = 0; colorAttachment < colorAttachmentIndices.size(); colorAttachment++)
2720                     {
2721                         if (colorAttachmentIndices[colorAttachment] ==
2722                             m_renderInfo.getColorAttachmentIndex(attachmentNdx))
2723                             break;
2724                     }
2725                 }
2726 
2727                 const ColorClear &colorClear = colorClears[attachmentNdx];
2728                 const VkClearAttachment attachment{
2729                     VK_IMAGE_ASPECT_COLOR_BIT,
2730                     colorAttachment,
2731                     makeClearValue(colorClear.getColor()),
2732                 };
2733                 const VkClearRect rect{
2734                     {{(int32_t)colorClear.getOffset().x(), (int32_t)colorClear.getOffset().y()},
2735                      {colorClear.getSize().x(), colorClear.getSize().y()}}, // rect
2736                     0u,                                                     // baseArrayLayer
2737                     1u,                                                     // layerCount
2738                 };
2739 
2740                 vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
2741             }
2742         }
2743 
2744         if (m_renderInfo.getDepthStencilClear())
2745         {
2746             const DepthStencilClear &depthStencilClear = *m_renderInfo.getDepthStencilClear();
2747             const uint32_t attachmentNdx               = m_renderInfo.getColorAttachmentCount();
2748             tcu::TextureFormat format          = mapVkFormat(m_renderInfo.getDepthStencilAttachment()->getFormat());
2749             const VkImageLayout layout         = *m_renderInfo.getDepthStencilAttachmentLayout();
2750             const VkClearAttachment attachment = {
2751                 (VkImageAspectFlags)((hasDepthComponent(format.order) &&
2752                                               layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL ?
2753                                           VK_IMAGE_ASPECT_DEPTH_BIT :
2754                                           0) |
2755                                      (hasStencilComponent(format.order) &&
2756                                               layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ?
2757                                           VK_IMAGE_ASPECT_STENCIL_BIT :
2758                                           0)),
2759                 attachmentNdx,
2760                 makeClearValueDepthStencil(depthStencilClear.getDepth(), depthStencilClear.getStencil())};
2761             const VkClearRect rect = {
2762                 {{(int32_t)depthStencilClear.getOffset().x(), (int32_t)depthStencilClear.getOffset().y()},
2763                  {depthStencilClear.getSize().x(), depthStencilClear.getSize().y()}}, // rect
2764                 0u,                                                                   // baseArrayLayer
2765                 1u,                                                                   // layerCount
2766             };
2767 
2768             if ((tcu::hasDepthComponent(format.order) &&
2769                  layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL) ||
2770                 (tcu::hasStencilComponent(format.order) &&
2771                  layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL))
2772             {
2773                 vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
2774             }
2775         }
2776 
2777         vector<VkImageMemoryBarrier> selfDeps;
2778         VkPipelineStageFlags srcStages = 0;
2779         VkPipelineStageFlags dstStages = 0;
2780 
2781         for (uint32_t inputAttachmentNdx = 0; inputAttachmentNdx < m_renderInfo.getInputAttachmentCount();
2782              inputAttachmentNdx++)
2783         {
2784             for (uint32_t colorAttachmentNdx = 0; colorAttachmentNdx < m_renderInfo.getColorAttachmentCount();
2785                  colorAttachmentNdx++)
2786             {
2787                 if (m_renderInfo.getInputAttachmentIndex(inputAttachmentNdx) ==
2788                     m_renderInfo.getColorAttachmentIndex(colorAttachmentNdx))
2789                 {
2790                     const VkImageMemoryBarrier barrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
2791                                                        DE_NULL,                                // pNext
2792 
2793                                                        VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
2794                                                        VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,  // dstAccessMask
2795 
2796                                                        inputAttachmenLayout, // oldLayout
2797                                                        inputAttachmenLayout, // newLayout
2798 
2799                                                        VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
2800                                                        VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
2801 
2802                                                        m_colorAttachmentImages[colorAttachmentNdx], // image
2803                                                        {
2804                                                            // subresourceRange
2805                                                            VK_IMAGE_ASPECT_COLOR_BIT, // aspect
2806                                                            0,                         // baseMipLevel
2807                                                            1,                         // mipLevels
2808                                                            0,                         // baseArraySlice
2809                                                            1                          // arraySize
2810                                                        }};
2811 
2812                     srcStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2813                     dstStages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
2814 
2815                     selfDeps.push_back(barrier);
2816                 }
2817             }
2818 
2819             if (m_renderInfo.getDepthStencilAttachmentIndex() &&
2820                 (m_renderInfo.getInputAttachmentIndex(inputAttachmentNdx) ==
2821                  *m_renderInfo.getDepthStencilAttachmentIndex()))
2822             {
2823                 const tcu::TextureFormat format    = mapVkFormat(m_renderInfo.getDepthStencilAttachment()->getFormat());
2824                 const bool hasDepth                = hasDepthComponent(format.order);
2825                 const bool hasStencil              = hasStencilComponent(format.order);
2826                 const VkImageMemoryBarrier barrier = {
2827                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
2828                     DE_NULL,                                // pNext;
2829 
2830                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // srcAccessMask
2831                     VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,          // dstAccessMask
2832 
2833                     m_renderInfo.getInputAttachmentLayout(inputAttachmentNdx), // oldLayout
2834                     m_renderInfo.getInputAttachmentLayout(inputAttachmentNdx), // newLayout;
2835 
2836                     VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex;
2837                     VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex;
2838 
2839                     m_depthStencilAttachmentImage, // image;
2840                     {
2841                         // subresourceRange;
2842                         (hasDepth ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
2843                             (hasStencil ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u), // aspect;
2844                         0,                                                                       // baseMipLevel;
2845                         1,                                                                       // mipLevels;
2846                         0,                                                                       // baseArraySlice;
2847                         1                                                                        // arraySize;
2848                     }};
2849 
2850                 srcStages |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
2851                 dstStages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
2852 
2853                 selfDeps.push_back(barrier);
2854             }
2855         }
2856 
2857         if (!selfDeps.empty())
2858         {
2859             DE_ASSERT(srcStages != 0);
2860             DE_ASSERT(dstStages != 0);
2861             vk.cmdPipelineBarrier(commandBuffer, srcStages, dstStages, VK_DEPENDENCY_BY_REGION_BIT, 0, DE_NULL, 0,
2862                                   DE_NULL, (uint32_t)selfDeps.size(), &selfDeps[0]);
2863         }
2864 
2865         if (m_renderInfo.getRenderQuad())
2866         {
2867             const VkDeviceSize offset   = 0;
2868             const VkBuffer vertexBuffer = *m_vertexBuffer;
2869 
2870             vk.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.getPipeline());
2871 
2872             if (m_descriptorSet)
2873             {
2874                 const VkDescriptorSet descriptorSet = *m_descriptorSet;
2875                 vk.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u,
2876                                          &descriptorSet, 0u, NULL);
2877             }
2878 
2879             vk.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &vertexBuffer, &offset);
2880             vk.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
2881         }
2882     }
2883 
2884 protected:
createSubpassPipeline(VkRenderPass renderPass)2885     void createSubpassPipeline(VkRenderPass renderPass)
2886     {
2887         // At this point we dont know how many blend states we will need
2888         // so we just create maximal number of potentialy needed states
2889         vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(
2890             m_renderPassInfo.getAttachments().size(),
2891             {
2892                 VK_FALSE,                            // blendEnable
2893                 VK_BLEND_FACTOR_SRC_ALPHA,           // srcBlendColor
2894                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // destBlendColor
2895                 VK_BLEND_OP_ADD,                     // blendOpColor
2896                 VK_BLEND_FACTOR_ONE,                 // srcBlendAlpha
2897                 VK_BLEND_FACTOR_ONE,                 // destBlendAlpha
2898                 VK_BLEND_OP_ADD,                     // blendOpAlpha
2899                 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
2900                     VK_COLOR_COMPONENT_A_BIT // colorWriteMask
2901             });
2902 
2903         Maybe<VkSampleCountFlagBits> rasterSamples;
2904         for (uint32_t attachmentNdx = 0; attachmentNdx < m_renderInfo.getColorAttachmentCount(); attachmentNdx++)
2905         {
2906             const Attachment &attachment = m_renderInfo.getColorAttachment(attachmentNdx);
2907 
2908             DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
2909 
2910             rasterSamples = attachment.getSamples();
2911 
2912             if (attachmentNdx < m_renderInfo.getDrawStartNdx())
2913                 attachmentBlendStates[attachmentNdx].colorWriteMask = (uint32_t)0;
2914         }
2915 
2916         if (m_renderInfo.getDepthStencilAttachment())
2917         {
2918             const Attachment &attachment = *m_renderInfo.getDepthStencilAttachment();
2919 
2920             DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
2921             rasterSamples = attachment.getSamples();
2922         }
2923 
2924         // If there are no attachment use single sample
2925         if (!rasterSamples)
2926             rasterSamples = VK_SAMPLE_COUNT_1_BIT;
2927 
2928         const VkVertexInputBindingDescription vertexBinding{
2929             0u,                          // binding
2930             (uint32_t)sizeof(tcu::Vec2), // strideInBytes
2931             VK_VERTEX_INPUT_RATE_VERTEX, // stepRate
2932         };
2933 
2934         const VkVertexInputAttributeDescription vertexAttrib{
2935             0u,                      // location
2936             0u,                      // binding
2937             VK_FORMAT_R32G32_SFLOAT, // format
2938             0u,                      // offsetInBytes
2939         };
2940 
2941         const VkPipelineVertexInputStateCreateInfo vertexInputState{
2942             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, //    sType
2943             DE_NULL,                                                   //    pNext
2944             (VkPipelineVertexInputStateCreateFlags)0u,
2945             1u,             //    bindingCount
2946             &vertexBinding, //    pVertexBindingDescriptions
2947             1u,             //    attributeCount
2948             &vertexAttrib,  //    pVertexAttributeDescriptions
2949         };
2950 
2951         const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState{
2952             VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                            sType
2953             DE_NULL,                             // const void*                                pNext
2954             0u,                                  // VkPipelineInputAssemblyStateCreateFlags    flags
2955             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology                        topology
2956             VK_FALSE                             // VkBool32                                    primitiveRestartEnable
2957         };
2958 
2959         const std::vector<VkViewport> viewports{
2960             {(float)m_renderInfo.getViewportOffset().x(), (float)m_renderInfo.getViewportOffset().y(),
2961              (float)m_renderInfo.getViewportSize().x(), (float)m_renderInfo.getViewportSize().y(), 0.0f, 1.0f}};
2962 
2963         const std::vector<VkRect2D> scissors{
2964             {{(int32_t)m_renderInfo.getViewportOffset().x(), (int32_t)m_renderInfo.getViewportOffset().y()},
2965              {m_renderInfo.getViewportSize().x(), m_renderInfo.getViewportSize().y()}}};
2966 
2967         const VkPipelineRasterizationStateCreateInfo rasterizationState{
2968             VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                            sType
2969             DE_NULL,                         // const void*                                pNext
2970             0u,                              // VkPipelineRasterizationStateCreateFlags    flags
2971             VK_FALSE,                        // VkBool32                                    depthClampEnable
2972             VK_FALSE,                        // VkBool32                                    rasterizerDiscardEnable
2973             VK_POLYGON_MODE_FILL,            // VkPolygonMode                            polygonMode
2974             VK_CULL_MODE_NONE,               // VkCullModeFlags                            cullMode
2975             VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace                                frontFace
2976             VK_FALSE,                        // VkBool32                                    depthBiasEnable
2977             0.0f,                            // float                                    depthBiasConstantFactor
2978             0.0f,                            // float                                    depthBiasClamp
2979             0.0f,                            // float                                    depthBiasSlopeFactor
2980             1.0f                             // float                                    lineWidth
2981         };
2982 
2983         const VkPipelineMultisampleStateCreateInfo multisampleState{
2984             VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType
2985             DE_NULL,                                                  // pNext
2986             (VkPipelineMultisampleStateCreateFlags)0u,
2987             *rasterSamples, // rasterSamples
2988             VK_FALSE,       // sampleShadingEnable
2989             0.0f,           // minSampleShading
2990             DE_NULL,        // pSampleMask
2991             VK_FALSE,       // alphaToCoverageEnable
2992             VK_FALSE,       // alphaToOneEnable
2993         };
2994         const uint32_t subpassIndex = m_renderInfo.getSubpassIndex();
2995 
2996         const VkBool32 writeDepth = m_renderInfo.getDepthStencilAttachmentLayout() &&
2997                                             *m_renderInfo.getDepthStencilAttachmentLayout() !=
2998                                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
2999                                             *m_renderInfo.getDepthStencilAttachmentLayout() !=
3000                                                 VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL ?
3001                                         VK_TRUE :
3002                                         VK_FALSE;
3003 
3004         const VkBool32 writeStencil = m_renderInfo.getDepthStencilAttachmentLayout() &&
3005                                               *m_renderInfo.getDepthStencilAttachmentLayout() !=
3006                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
3007                                               *m_renderInfo.getDepthStencilAttachmentLayout() !=
3008                                                   VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ?
3009                                           VK_TRUE :
3010                                           VK_FALSE;
3011 
3012         VkStencilOp stencilOp = writeStencil ? VK_STENCIL_OP_REPLACE : VK_STENCIL_OP_KEEP;
3013 
3014         const VkPipelineDepthStencilStateCreateInfo depthStencilState{
3015             VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType
3016             DE_NULL,                                                    // pNext
3017             (VkPipelineDepthStencilStateCreateFlags)0u,
3018             writeDepth,           // depthTestEnable
3019             writeDepth,           // depthWriteEnable
3020             VK_COMPARE_OP_ALWAYS, // depthCompareOp
3021             VK_FALSE,             // depthBoundsEnable
3022             writeStencil,         // stencilTestEnable
3023             {
3024                 stencilOp,                               // stencilFailOp
3025                 stencilOp,                               // stencilPassOp
3026                 stencilOp,                               // stencilDepthFailOp
3027                 VK_COMPARE_OP_ALWAYS,                    // stencilCompareOp
3028                 ~0u,                                     // stencilCompareMask
3029                 ~0u,                                     // stencilWriteMask
3030                 ((subpassIndex % 2) == 0) ? ~0x0u : 0x0u // stencilReference
3031             },                                           // front
3032             {
3033                 stencilOp,                               // stencilFailOp
3034                 stencilOp,                               // stencilPassOp
3035                 stencilOp,                               // stencilDepthFailOp
3036                 VK_COMPARE_OP_ALWAYS,                    // stencilCompareOp
3037                 ~0u,                                     // stencilCompareMask
3038                 ~0u,                                     // stencilWriteMask
3039                 ((subpassIndex % 2) == 0) ? ~0x0u : 0x0u // stencilReference
3040             },                                           // back
3041 
3042             0.0f, // minDepthBounds;
3043             1.0f  // maxDepthBounds;
3044         };
3045 
3046         VkPipelineColorBlendStateCreateInfo blendState{
3047             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType
3048             DE_NULL,                                                  // pNext
3049             (VkPipelineColorBlendStateCreateFlags)0u,
3050             VK_FALSE,                                         // logicOpEnable
3051             VK_LOGIC_OP_COPY,                                 // logicOp
3052             (uint32_t)m_renderInfo.getColorAttachmentCount(), // attachmentCount
3053             de::dataOrNull(attachmentBlendStates),            // pAttachments
3054             {0.0f, 0.0f, 0.0f, 0.0f}                          // blendConst
3055         };
3056 
3057         PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
3058         RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfoWrapper;
3059         RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfoWrapper;
3060 
3061 #ifndef CTS_USES_VULKANSC
3062 
3063         std::vector<uint32_t> colorAttachmentIndices;
3064         std::vector<VkFormat> colorAttachmentFormats;
3065         findColorAttachments(m_renderPassInfo, colorAttachmentIndices, colorAttachmentFormats);
3066 
3067         uint32_t colorAttachmentCount = (uint32_t)colorAttachmentFormats.size();
3068         std::vector<uint32_t> colorAttachmentLocations(colorAttachmentCount, VK_ATTACHMENT_UNUSED);
3069         std::vector<uint32_t> colorAttachmentInputIndices(colorAttachmentCount, VK_ATTACHMENT_UNUSED);
3070 
3071         VkFormat depthFormat                   = VK_FORMAT_UNDEFINED;
3072         VkFormat stencilFormat                 = VK_FORMAT_UNDEFINED;
3073         uint32_t gloabalDepthAttachmentIndex   = VK_ATTACHMENT_UNUSED;
3074         uint32_t gloabalStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
3075         uint32_t localDepthAttachmentIndex     = VK_ATTACHMENT_UNUSED;
3076         uint32_t localStencilAttachmentIndex   = VK_ATTACHMENT_UNUSED;
3077 
3078         VkPipelineRenderingCreateInfoKHR renderingCreateInfo                     = initVulkanStructure();
3079         VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo     = initVulkanStructure();
3080         VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo = initVulkanStructure();
3081 
3082         if (renderPass == DE_NULL)
3083         {
3084             findDepthStencilAttachments(m_renderPassInfo.getAttachments(), depthFormat, stencilFormat,
3085                                         gloabalDepthAttachmentIndex, gloabalStencilAttachmentIndex);
3086 
3087             renderingCreateInfo.colorAttachmentCount    = colorAttachmentCount;
3088             renderingCreateInfo.pColorAttachmentFormats = colorAttachmentFormats.data();
3089             renderingCreateInfo.depthAttachmentFormat   = depthFormat;
3090             renderingCreateInfo.stencilAttachmentFormat = stencilFormat;
3091             renderingCreateInfoWrapper.ptr              = &renderingCreateInfo;
3092 
3093             // pColorBlendState->attachmentCount must be equal to VkPipelineRenderingCreateInfo::colorAttachmentCount
3094             blendState.attachmentCount = colorAttachmentCount;
3095 
3096             // remap attachments for multi pass tests
3097             const std::vector<Subpass> &allSubapsses = m_renderPassInfo.getSubpasses();
3098             if (allSubapsses.size() > 1u)
3099             {
3100                 const auto &subpass = allSubapsses[subpassIndex];
3101                 fillRenderingAttachmentLocationsInfo(subpass.getColorAttachments(), colorAttachmentIndices,
3102                                                      colorAttachmentLocations, renderingAttachmentLocationInfo);
3103 
3104                 fillRenderingInputAttachmentIndexInfo(subpass.getInputAttachments(), colorAttachmentIndices,
3105                                                       gloabalDepthAttachmentIndex, gloabalStencilAttachmentIndex,
3106                                                       localDepthAttachmentIndex, localStencilAttachmentIndex,
3107                                                       colorAttachmentInputIndices, renderingInputAttachmentIndexInfo);
3108 
3109                 renderingAttachmentLocationInfoWrapper.ptr   = &renderingAttachmentLocationInfo;
3110                 renderingInputAttachmentIndexInfoWrapper.ptr = &renderingInputAttachmentIndexInfo;
3111             }
3112         }
3113 #endif // CTS_USES_VULKANSC
3114 
3115         m_pipeline.setupVertexInputState(&vertexInputState, &inputAssemblyState)
3116             .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayout, renderPass, subpassIndex,
3117                                               m_vertexShaderModule, &rasterizationState, ShaderWrapper(),
3118                                               ShaderWrapper(), ShaderWrapper(), DE_NULL, DE_NULL,
3119                                               renderingCreateInfoWrapper)
3120             .setupFragmentShaderState(m_pipelineLayout, renderPass, subpassIndex, m_fragmentShaderModule,
3121                                       &depthStencilState, &multisampleState, 0, 0, {},
3122                                       renderingInputAttachmentIndexInfoWrapper)
3123             .setupFragmentOutputState(renderPass, subpassIndex,
3124                                       (m_renderInfo.getOmitBlendState() ? DE_NULL : &blendState), &multisampleState, 0,
3125                                       0, renderingAttachmentLocationInfoWrapper)
3126             .setMonolithicPipelineLayout(m_pipelineLayout)
3127             .buildPipeline();
3128     }
3129 
3130 private:
3131     const SubpassRenderInfo m_renderInfo;
3132     const RenderPass &m_renderPassInfo;
3133     Move<VkCommandBuffer> m_commandBuffer;
3134     GraphicsPipelineWrapper m_pipeline;
3135     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
3136     PipelineLayoutWrapper m_pipelineLayout;
3137 
3138     ShaderWrapper m_vertexShaderModule;
3139     ShaderWrapper m_fragmentShaderModule;
3140 
3141     Move<VkDescriptorPool> m_descriptorPool;
3142     Move<VkDescriptorSet> m_descriptorSet;
3143     Move<VkBuffer> m_vertexBuffer;
3144     de::MovePtr<Allocation> m_vertexBufferMemory;
3145     vector<VkImage> m_colorAttachmentImages;
3146     VkImage m_depthStencilAttachmentImage;
3147 };
3148 
pushImageInitializationCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const vector<Attachment> & attachmentInfo,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,uint32_t queueIndex,const vector<Maybe<VkClearValue>> & clearValues)3149 void pushImageInitializationCommands(const DeviceInterface &vk, VkCommandBuffer commandBuffer,
3150                                      const vector<Attachment> &attachmentInfo,
3151                                      const vector<de::SharedPtr<AttachmentResources>> &attachmentResources,
3152                                      uint32_t queueIndex, const vector<Maybe<VkClearValue>> &clearValues)
3153 {
3154     {
3155         vector<VkImageMemoryBarrier> initializeLayouts;
3156 
3157         for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
3158         {
3159             if (!clearValues[attachmentNdx])
3160                 continue;
3161 
3162             const VkImageMemoryBarrier barrier = {
3163                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
3164                 DE_NULL,                                // pNext;
3165 
3166                 (VkAccessFlags)0,                                       // srcAccessMask
3167                 getAllMemoryReadFlags() | VK_ACCESS_TRANSFER_WRITE_BIT, // dstAccessMask
3168 
3169                 VK_IMAGE_LAYOUT_UNDEFINED,            // oldLayout
3170                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout;
3171 
3172                 queueIndex, // srcQueueFamilyIndex;
3173                 queueIndex, // destQueueFamilyIndex;
3174 
3175                 attachmentResources[attachmentNdx]->getImage(), // image;
3176                 {
3177                     // subresourceRange;
3178                     getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
3179                     0,                                                              // baseMipLevel;
3180                     1,                                                              // mipLevels;
3181                     0,                                                              // baseArraySlice;
3182                     1                                                               // arraySize;
3183                 }};
3184 
3185             initializeLayouts.push_back(barrier);
3186         }
3187 
3188         if (!initializeLayouts.empty())
3189             vk.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
3190                                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
3191                                   0, (const VkMemoryBarrier *)DE_NULL, 0, (const VkBufferMemoryBarrier *)DE_NULL,
3192                                   (uint32_t)initializeLayouts.size(), &initializeLayouts[0]);
3193     }
3194 
3195     for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
3196     {
3197         if (!clearValues[attachmentNdx])
3198             continue;
3199 
3200         const tcu::TextureFormat format = mapVkFormat(attachmentInfo[attachmentNdx].getFormat());
3201 
3202         if (hasStencilComponent(format.order) || hasDepthComponent(format.order))
3203         {
3204             const float clearNan =
3205                 0.f; // The use of NaN here would require VK_EXT_depth_range_unrestricted; however, just use 0
3206                      // since This value is only used for channels that are not used (e.g., for the depth channel
3207                      // if the format is stencil-only) and the value of unused channels are never read and
3208                      // verified on the host.
3209             const float clearDepth =
3210                 hasDepthComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.depth : clearNan;
3211             const uint32_t clearStencil =
3212                 hasStencilComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.stencil : 0xDEu;
3213             const VkClearDepthStencilValue depthStencil = {clearDepth, clearStencil};
3214             const VkImageSubresourceRange range         = {
3215                 (VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
3216                                      (hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
3217                 0, 1, 0, 1};
3218 
3219             vk.cmdClearDepthStencilImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(),
3220                                          VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthStencil, 1, &range);
3221         }
3222         else
3223         {
3224             const VkImageSubresourceRange range = {
3225                 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask;
3226                 0,                         // baseMipLevel;
3227                 1,                         // mipLevels;
3228                 0,                         // baseArrayLayer;
3229                 1                          // layerCount;
3230             };
3231             const VkClearColorValue clearColor = clearValues[attachmentNdx]->color;
3232 
3233             vk.cmdClearColorImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(),
3234                                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range);
3235         }
3236     }
3237 
3238     {
3239         vector<VkImageMemoryBarrier> renderPassLayouts;
3240 
3241         for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
3242         {
3243             const VkImageLayout oldLayout =
3244                 clearValues[attachmentNdx] ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
3245             const VkImageMemoryBarrier barrier = {
3246                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
3247                 DE_NULL,                                // pNext;
3248 
3249                 getMemoryFlagsForLayout(oldLayout), // srcAccessMask
3250                 getAllMemoryReadFlags() |
3251                     getMemoryFlagsForLayout(attachmentInfo[attachmentNdx].getInitialLayout()), // dstAccessMask
3252 
3253                 oldLayout,                                        // oldLayout
3254                 attachmentInfo[attachmentNdx].getInitialLayout(), // newLayout;
3255 
3256                 queueIndex, // srcQueueFamilyIndex;
3257                 queueIndex, // destQueueFamilyIndex;
3258 
3259                 attachmentResources[attachmentNdx]->getImage(), // image;
3260                 {
3261                     // subresourceRange;
3262                     getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
3263                     0,                                                              // baseMipLevel;
3264                     1,                                                              // mipLevels;
3265                     0,                                                              // baseArraySlice;
3266                     1                                                               // arraySize;
3267                 }};
3268 
3269             renderPassLayouts.push_back(barrier);
3270         }
3271 
3272         if (!renderPassLayouts.empty())
3273             vk.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
3274                                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
3275                                   0, (const VkMemoryBarrier *)DE_NULL, 0, (const VkBufferMemoryBarrier *)DE_NULL,
3276                                   (uint32_t)renderPassLayouts.size(), &renderPassLayouts[0]);
3277     }
3278 }
3279 
3280 template <typename RenderpassSubpass>
pushRenderPassCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,VkRenderPass renderPass,VkFramebuffer framebuffer,const vector<de::SharedPtr<SubpassRenderer>> & subpassRenderers,const VkRect2D & renderArea,const vector<Maybe<VkClearValue>> & renderPassClearValues,const TestConfig & config)3281 void pushRenderPassCommands(const DeviceInterface &vk, VkCommandBuffer commandBuffer, VkRenderPass renderPass,
3282                             VkFramebuffer framebuffer, const vector<de::SharedPtr<SubpassRenderer>> &subpassRenderers,
3283                             const VkRect2D &renderArea, const vector<Maybe<VkClearValue>> &renderPassClearValues,
3284                             const TestConfig &config)
3285 {
3286     const float clearNan = tcu::Float32::nan().asFloat();
3287     vector<VkClearValue> attachmentClearValues;
3288     const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
3289 
3290     for (size_t attachmentNdx = 0; attachmentNdx < renderPassClearValues.size(); attachmentNdx++)
3291     {
3292         if (renderPassClearValues[attachmentNdx])
3293             attachmentClearValues.push_back(*renderPassClearValues[attachmentNdx]);
3294         else
3295             attachmentClearValues.push_back(makeClearValueColorF32(clearNan, clearNan, clearNan, clearNan));
3296     }
3297 
3298     {
3299         for (size_t subpassNdx = 0; subpassNdx < subpassRenderers.size(); subpassNdx++)
3300         {
3301             const VkSubpassContents contents = subpassRenderers[subpassNdx]->isSecondary() ?
3302                                                    VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS :
3303                                                    VK_SUBPASS_CONTENTS_INLINE;
3304             const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, contents);
3305             const VkRenderPassBeginInfo renderPassBeginInfo =
3306                 createRenderPassBeginInfo(renderPass, framebuffer, renderArea, (uint32_t)attachmentClearValues.size(),
3307                                           attachmentClearValues.empty() ? DE_NULL : &attachmentClearValues[0]);
3308 
3309             if (subpassNdx == 0)
3310                 RenderpassSubpass::cmdBeginRenderPass(vk, commandBuffer, &renderPassBeginInfo, &subpassBeginInfo);
3311             else
3312                 RenderpassSubpass::cmdNextSubpass(vk, commandBuffer, &subpassBeginInfo, &subpassEndInfo);
3313 
3314             if (config.renderTypes)
3315             {
3316                 if (contents == VK_SUBPASS_CONTENTS_INLINE)
3317                 {
3318                     subpassRenderers[subpassNdx]->pushRenderCommands(vk, commandBuffer, false, false);
3319                 }
3320                 else if (contents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS)
3321                 {
3322                     const VkCommandBuffer cmd = subpassRenderers[subpassNdx]->getCommandBuffer();
3323                     vk.cmdExecuteCommands(commandBuffer, 1, &cmd);
3324                 }
3325                 else
3326                     DE_FATAL("Invalid contents");
3327             }
3328         }
3329 
3330         RenderpassSubpass::cmdEndRenderPass(vk, commandBuffer, &subpassEndInfo);
3331     }
3332 }
3333 
3334 #ifndef CTS_USES_VULKANSC
pushDynamicRenderingCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,const RenderPass & renderPassInfo,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const vector<de::SharedPtr<SubpassRenderer>> & subpassRenderers,const VkRect2D & renderArea,const vector<Maybe<VkClearValue>> & renderPassClearValues,uint32_t queueIndex,const TestConfig & config,bool secondaryCmdBufferCompletelyContainsDynamicRenderpass)3335 void pushDynamicRenderingCommands(const DeviceInterface &vk, VkCommandBuffer commandBuffer,
3336                                   const RenderPass &renderPassInfo,
3337                                   const vector<de::SharedPtr<AttachmentResources>> &attachmentResources,
3338                                   const vector<de::SharedPtr<SubpassRenderer>> &subpassRenderers,
3339                                   const VkRect2D &renderArea, const vector<Maybe<VkClearValue>> &renderPassClearValues,
3340                                   uint32_t queueIndex, const TestConfig &config,
3341                                   bool secondaryCmdBufferCompletelyContainsDynamicRenderpass)
3342 {
3343     // helper lambda that returns true when attachment is input attachment for specified subpass
3344     auto isAttachmentUsedAsSubpassInput = [](uint32_t attachmentIndex, const Subpass &subpass)
3345     {
3346         for (const AttachmentReference &inputAttachment : subpass.getInputAttachments())
3347         {
3348             if (attachmentIndex == inputAttachment.getAttachment())
3349                 return true;
3350         }
3351         return false;
3352     };
3353 
3354     VkImageMemoryBarrier defaultBarrier = initVulkanStructure();
3355     defaultBarrier.srcQueueFamilyIndex  = queueIndex;
3356     defaultBarrier.dstQueueFamilyIndex  = queueIndex;
3357     defaultBarrier.subresourceRange     = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
3358 
3359     const std::vector<Attachment> &allAttachments(renderPassInfo.getAttachments());
3360     const uint32_t allAttachmentsCount((uint32_t)allAttachments.size());
3361     vector<VkImageMemoryBarrier> imageBarriersBeforeRendering(allAttachmentsCount, defaultBarrier);
3362     vector<VkImageMemoryBarrier> imageBarriersAfterRendering(allAttachmentsCount, defaultBarrier);
3363 
3364     for (uint32_t attachmentIndex = 0; attachmentIndex < allAttachmentsCount; ++attachmentIndex)
3365     {
3366         const Attachment &attachment   = allAttachments[attachmentIndex];
3367         const VkFormat format          = attachment.getFormat();
3368         const auto textureFormat       = mapVkFormat(format);
3369         const bool isDepthAttachment   = hasDepthComponent(textureFormat.order);
3370         const bool isStencilAttachment = hasStencilComponent(textureFormat.order);
3371 
3372         VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3373         VkImageLayout initialLayout   = attachment.getInitialLayout();
3374         VkImageLayout renderingLayout = VK_IMAGE_LAYOUT_UNDEFINED;
3375         VkImageLayout finalLayout     = attachment.getFinalLayout();
3376 
3377         if (isDepthAttachment || isStencilAttachment)
3378         {
3379             aspectMask =
3380                 (isDepthAttachment * VK_IMAGE_ASPECT_DEPTH_BIT) | (isStencilAttachment * VK_IMAGE_ASPECT_STENCIL_BIT);
3381 
3382             // iterate over all subpasses
3383             for (const Subpass &subpass : renderPassInfo.getSubpasses())
3384             {
3385                 if (renderingLayout == VK_IMAGE_LAYOUT_UNDEFINED)
3386                 {
3387                     // find first subpass in which ds attachment is used
3388                     const AttachmentReference &dsAttachmentReference = subpass.getDepthStencilAttachment();
3389                     if (attachmentIndex == dsAttachmentReference.getAttachment())
3390                         renderingLayout = dsAttachmentReference.getImageLayout();
3391                 }
3392                 else if (isAttachmentUsedAsSubpassInput(attachmentIndex, subpass))
3393                 {
3394                     renderingLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
3395                     break;
3396                 }
3397             }
3398         }
3399         else
3400         {
3401             // iterate over all subpasses
3402             for (const Subpass &subpass : renderPassInfo.getSubpasses())
3403             {
3404                 if (renderingLayout == VK_IMAGE_LAYOUT_UNDEFINED)
3405                 {
3406                     // find first subpass in which ds attachment is used
3407                     for (const AttachmentReference &attachmentReference : subpass.getColorAttachments())
3408                     {
3409                         if (attachmentIndex == attachmentReference.getAttachment())
3410                         {
3411                             renderingLayout = attachmentReference.getImageLayout();
3412                             break;
3413                         }
3414                     }
3415                 }
3416                 else if (isAttachmentUsedAsSubpassInput(attachmentIndex, subpass))
3417                 {
3418                     renderingLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
3419                     break;
3420                 }
3421             }
3422         }
3423 
3424         // handle attachment that is not used by any subpass
3425         if (renderingLayout == VK_IMAGE_LAYOUT_UNDEFINED)
3426             renderingLayout = VK_IMAGE_LAYOUT_GENERAL;
3427 
3428         VkImageMemoryBarrier &beforeBarrier       = imageBarriersBeforeRendering[attachmentIndex];
3429         beforeBarrier.srcAccessMask               = getAllMemoryWriteFlags() | getMemoryFlagsForLayout(initialLayout);
3430         beforeBarrier.dstAccessMask               = getMemoryFlagsForLayout(renderingLayout);
3431         beforeBarrier.oldLayout                   = initialLayout;
3432         beforeBarrier.newLayout                   = renderingLayout;
3433         beforeBarrier.image                       = attachmentResources[attachmentIndex]->getImage();
3434         beforeBarrier.subresourceRange.aspectMask = aspectMask;
3435 
3436         VkImageMemoryBarrier &afterBarrier       = imageBarriersAfterRendering[attachmentIndex];
3437         afterBarrier.srcAccessMask               = getMemoryFlagsForLayout(renderingLayout);
3438         afterBarrier.dstAccessMask               = getAllMemoryReadFlags() | getMemoryFlagsForLayout(finalLayout);
3439         afterBarrier.oldLayout                   = renderingLayout;
3440         afterBarrier.newLayout                   = finalLayout;
3441         afterBarrier.image                       = beforeBarrier.image;
3442         afterBarrier.subresourceRange.aspectMask = aspectMask;
3443     }
3444 
3445     if (!imageBarriersBeforeRendering.empty())
3446         vk.cmdPipelineBarrier(commandBuffer, getAllPipelineStageFlags(), getAllPipelineStageFlags(),
3447                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3448                               (const VkBufferMemoryBarrier *)DE_NULL, allAttachmentsCount,
3449                               imageBarriersBeforeRendering.data());
3450 
3451     bool executeRenderCommands = (config.renderTypes != TestConfig::RENDERTYPES_NONE);
3452 
3453     if (secondaryCmdBufferCompletelyContainsDynamicRenderpass)
3454     {
3455         // when secondary command buffer completely contains dynamic renderpass
3456         // then we need to execute it even when render type is none
3457         executeRenderCommands = true;
3458     }
3459     else
3460     {
3461         VkRenderingFlagsKHR renderingFlags = 0u;
3462         if (subpassRenderers[0]->isSecondary())
3463             renderingFlags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR;
3464 
3465         beginDynamicRendering(vk, commandBuffer, renderPassInfo, attachmentResources, renderArea, renderPassClearValues,
3466                               renderingFlags);
3467     }
3468 
3469     if (executeRenderCommands)
3470     {
3471         for (size_t subpassNdx = 0; subpassNdx < subpassRenderers.size(); subpassNdx++)
3472         {
3473             if (subpassNdx != 0)
3474             {
3475                 const auto &subpass          = renderPassInfo.getSubpasses()[subpassNdx];
3476                 const auto &inputAttachments = subpass.getInputAttachments();
3477                 VkMemoryBarrier memoryBarrier =
3478                     makeMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT);
3479                 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
3480 
3481                 // check if one of inputs is depth/stencil format
3482                 for (const auto &inputAttachment : inputAttachments)
3483                 {
3484                     VkFormat format          = allAttachments[inputAttachment.getAttachment()].getFormat();
3485                     const auto textureFormat = mapVkFormat(format);
3486                     if (hasDepthComponent(textureFormat.order) || hasStencilComponent(textureFormat.order))
3487                     {
3488                         srcStageMask                = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
3489                         memoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
3490                         break;
3491                     }
3492                 }
3493 
3494                 if (!inputAttachments.empty())
3495                 {
3496                     vk.cmdPipelineBarrier(commandBuffer, srcStageMask, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
3497                                           VK_DEPENDENCY_BY_REGION_BIT, 1u, &memoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
3498                 }
3499             }
3500 
3501             if (subpassRenderers[subpassNdx]->isSecondary())
3502             {
3503                 if (subpassNdx > 0)
3504                 {
3505                     std::vector<uint32_t> colorAttachmentIndices;
3506                     std::vector<VkFormat> colorAttachmentFormats;
3507 
3508                     findColorAttachments(renderPassInfo, colorAttachmentIndices, colorAttachmentFormats);
3509 
3510                     uint32_t colorAttachmentCount((uint32_t)colorAttachmentIndices.size());
3511                     std::vector<uint32_t> colorAttachmentLocations(colorAttachmentCount, VK_ATTACHMENT_UNUSED);
3512                     std::vector<uint32_t> colorAttachmentInputIndices(colorAttachmentCount, VK_ATTACHMENT_UNUSED);
3513                     uint32_t localDepthAttachmentIndex                                       = VK_ATTACHMENT_UNUSED;
3514                     uint32_t localStencilAttachmentIndex                                     = VK_ATTACHMENT_UNUSED;
3515                     VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo     = initVulkanStructure();
3516                     VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo = initVulkanStructure();
3517 
3518                     prepareAttachmentRemapping(renderPassInfo.getSubpasses()[subpassNdx], allAttachments,
3519                                                colorAttachmentIndices, colorAttachmentLocations,
3520                                                colorAttachmentInputIndices, localDepthAttachmentIndex,
3521                                                localStencilAttachmentIndex, renderingAttachmentLocationInfo,
3522                                                renderingInputAttachmentIndexInfo);
3523 
3524                     vk.cmdSetRenderingAttachmentLocationsKHR(commandBuffer, &renderingAttachmentLocationInfo);
3525                     vk.cmdSetRenderingInputAttachmentIndicesKHR(commandBuffer, &renderingInputAttachmentIndexInfo);
3526                 }
3527 
3528                 const VkCommandBuffer cmd = subpassRenderers[subpassNdx]->getCommandBuffer();
3529                 vk.cmdExecuteCommands(commandBuffer, 1, &cmd);
3530             }
3531             else
3532                 subpassRenderers[subpassNdx]->pushRenderCommands(vk, commandBuffer, false, true);
3533         }
3534     }
3535 
3536     if (!secondaryCmdBufferCompletelyContainsDynamicRenderpass)
3537         endDynamicRendering(vk, commandBuffer);
3538 
3539     if (!imageBarriersAfterRendering.empty())
3540         vk.cmdPipelineBarrier(commandBuffer, getAllPipelineStageFlags(), getAllPipelineStageFlags(),
3541                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3542                               (const VkBufferMemoryBarrier *)DE_NULL, allAttachmentsCount,
3543                               imageBarriersAfterRendering.data());
3544 }
3545 #endif // CTS_USES_VULKANSC
3546 
pushRenderPassCommands(const DeviceInterface & vk,VkCommandBuffer commandBuffer,VkRenderPass renderPass,const RenderPass & renderPassInfo,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,VkFramebuffer framebuffer,const vector<de::SharedPtr<SubpassRenderer>> & subpassRenderers,const VkRect2D & renderArea,const vector<Maybe<VkClearValue>> & renderPassClearValues,uint32_t queueIndex,const TestConfig & config,bool secondaryCmdBufferCompletelyContainsDynamicRenderpass)3547 void pushRenderPassCommands(const DeviceInterface &vk, VkCommandBuffer commandBuffer, VkRenderPass renderPass,
3548                             const RenderPass &renderPassInfo,
3549                             const vector<de::SharedPtr<AttachmentResources>> &attachmentResources,
3550                             VkFramebuffer framebuffer, const vector<de::SharedPtr<SubpassRenderer>> &subpassRenderers,
3551                             const VkRect2D &renderArea, const vector<Maybe<VkClearValue>> &renderPassClearValues,
3552                             uint32_t queueIndex, const TestConfig &config,
3553                             bool secondaryCmdBufferCompletelyContainsDynamicRenderpass)
3554 {
3555     // unreference arguments not used by Vulkan SC, no need to put them under ifdef
3556     DE_UNREF(renderPassInfo);
3557     DE_UNREF(attachmentResources);
3558     DE_UNREF(queueIndex);
3559     DE_UNREF(secondaryCmdBufferCompletelyContainsDynamicRenderpass);
3560 
3561     switch (config.groupParams->renderingType)
3562     {
3563     case RENDERING_TYPE_RENDERPASS_LEGACY:
3564         return pushRenderPassCommands<RenderpassSubpass1>(vk, commandBuffer, renderPass, framebuffer, subpassRenderers,
3565                                                           renderArea, renderPassClearValues, config);
3566     case RENDERING_TYPE_RENDERPASS2:
3567         return pushRenderPassCommands<RenderpassSubpass2>(vk, commandBuffer, renderPass, framebuffer, subpassRenderers,
3568                                                           renderArea, renderPassClearValues, config);
3569 
3570 #ifndef CTS_USES_VULKANSC
3571     case RENDERING_TYPE_DYNAMIC_RENDERING:
3572         return pushDynamicRenderingCommands(vk, commandBuffer, renderPassInfo, attachmentResources, subpassRenderers,
3573                                             renderArea, renderPassClearValues, queueIndex, config,
3574                                             secondaryCmdBufferCompletelyContainsDynamicRenderpass);
3575 #endif // CTS_USES_VULKANSC
3576 
3577     default:
3578         TCU_THROW(InternalError, "Impossible");
3579     }
3580 }
3581 
pushReadImagesToBuffers(const DeviceInterface & vk,VkCommandBuffer commandBuffer,uint32_t queueIndex,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const vector<Attachment> & attachmentInfo,const vector<bool> & isLazy,const UVec2 & targetSize)3582 void pushReadImagesToBuffers(const DeviceInterface &vk, VkCommandBuffer commandBuffer, uint32_t queueIndex,
3583 
3584                              const vector<de::SharedPtr<AttachmentResources>> &attachmentResources,
3585                              const vector<Attachment> &attachmentInfo, const vector<bool> &isLazy,
3586 
3587                              const UVec2 &targetSize)
3588 {
3589     {
3590         vector<VkImageMemoryBarrier> imageBarriers;
3591 
3592         for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
3593         {
3594             if (isLazy[attachmentNdx])
3595                 continue;
3596 
3597             const VkImageLayout oldLayout      = attachmentInfo[attachmentNdx].getFinalLayout();
3598             const VkImageMemoryBarrier barrier = {
3599                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
3600                 DE_NULL,                                // pNext
3601 
3602                 getAllMemoryWriteFlags() | getMemoryFlagsForLayout(oldLayout), // srcAccessMask
3603                 getAllMemoryReadFlags(),                                       // dstAccessMask
3604 
3605                 oldLayout,                            // oldLayout
3606                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
3607 
3608                 queueIndex, // srcQueueFamilyIndex
3609                 queueIndex, // destQueueFamilyIndex
3610 
3611                 attachmentResources[attachmentNdx]->getImage(), // image
3612                 {
3613                     // subresourceRange
3614                     getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
3615                     0,                                                              // baseMipLevel
3616                     1,                                                              // mipLevels
3617                     0,                                                              // baseArraySlice
3618                     1                                                               // arraySize
3619                 }};
3620 
3621             imageBarriers.push_back(barrier);
3622         }
3623 
3624         if (!imageBarriers.empty())
3625             vk.cmdPipelineBarrier(commandBuffer, getAllPipelineStageFlags(), getAllPipelineStageFlags(),
3626                                   (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
3627                                   (const VkBufferMemoryBarrier *)DE_NULL, (uint32_t)imageBarriers.size(),
3628                                   &imageBarriers[0]);
3629     }
3630 
3631     for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
3632     {
3633         if (isLazy[attachmentNdx])
3634             continue;
3635 
3636         const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
3637         const VkBufferImageCopy rect                 = {
3638             0, // bufferOffset
3639             0, // bufferRowLength
3640             0, // bufferImageHeight
3641             {
3642                 // imageSubresource
3643                 (vk::VkImageAspectFlags)getPrimaryImageAspect(
3644                     mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order), // aspect
3645                 0,                                                                 // mipLevel
3646                 0,                                                                 // arraySlice
3647                 1                                                                  // arraySize
3648             },
3649             {0, 0, 0},                           // imageOffset
3650             {targetSize.x(), targetSize.y(), 1u} // imageExtent
3651         };
3652 
3653         vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(),
3654                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getBuffer(),
3655                                 1, &rect);
3656 
3657         if (tcu::TextureFormat::DS == order)
3658         {
3659             const VkBufferImageCopy stencilRect = {
3660                 0, // bufferOffset
3661                 0, // bufferRowLength
3662                 0, // bufferImageHeight
3663                 {
3664                     // imageSubresource
3665                     VK_IMAGE_ASPECT_STENCIL_BIT, // aspect
3666                     0,                           // mipLevel
3667                     0,                           // arraySlice
3668                     1                            // arraySize
3669                 },
3670                 {0, 0, 0},                           // imageOffset
3671                 {targetSize.x(), targetSize.y(), 1u} // imageExtent
3672             };
3673 
3674             vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(),
3675                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3676                                     attachmentResources[attachmentNdx]->getSecondaryBuffer(), 1, &stencilRect);
3677         }
3678     }
3679 
3680     {
3681         vector<VkBufferMemoryBarrier> bufferBarriers;
3682 
3683         for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
3684         {
3685             if (isLazy[attachmentNdx])
3686                 continue;
3687 
3688             const tcu::TextureFormat::ChannelOrder order = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
3689             const VkBufferMemoryBarrier bufferBarrier    = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3690                                                             DE_NULL,
3691 
3692                                                             getAllMemoryWriteFlags(),
3693                                                             getAllMemoryReadFlags(),
3694 
3695                                                             queueIndex,
3696                                                             queueIndex,
3697 
3698                                                             attachmentResources[attachmentNdx]->getBuffer(),
3699                                                             0,
3700                                                             attachmentResources[attachmentNdx]->getBufferSize()};
3701 
3702             bufferBarriers.push_back(bufferBarrier);
3703 
3704             if (tcu::TextureFormat::DS == order)
3705             {
3706                 const VkBufferMemoryBarrier secondaryBufferBarrier = {
3707                     VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3708                     DE_NULL,
3709 
3710                     getAllMemoryWriteFlags(),
3711                     getAllMemoryReadFlags(),
3712 
3713                     queueIndex,
3714                     queueIndex,
3715 
3716                     attachmentResources[attachmentNdx]->getSecondaryBuffer(),
3717                     0,
3718                     attachmentResources[attachmentNdx]->getSecondaryBufferSize()};
3719 
3720                 bufferBarriers.push_back(secondaryBufferBarrier);
3721             }
3722         }
3723 
3724         if (!bufferBarriers.empty())
3725             vk.cmdPipelineBarrier(commandBuffer, getAllPipelineStageFlags(), getAllPipelineStageFlags(),
3726                                   (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL,
3727                                   (uint32_t)bufferBarriers.size(), &bufferBarriers[0], 0,
3728                                   (const VkImageMemoryBarrier *)DE_NULL);
3729     }
3730 }
3731 
3732 class PixelValue
3733 {
3734 public:
3735     PixelValue(const Maybe<bool> &x = tcu::Nothing, const Maybe<bool> &y = tcu::Nothing,
3736                const Maybe<bool> &z = tcu::Nothing, const Maybe<bool> &w = tcu::Nothing);
3737 
3738     void setUndefined(size_t ndx);
3739     void setValue(size_t ndx, bool value);
3740     Maybe<bool> getValue(size_t ndx) const;
3741 
3742 private:
3743     uint16_t m_status;
3744 };
3745 
PixelValue(const Maybe<bool> & x,const Maybe<bool> & y,const Maybe<bool> & z,const Maybe<bool> & w)3746 PixelValue::PixelValue(const Maybe<bool> &x, const Maybe<bool> &y, const Maybe<bool> &z, const Maybe<bool> &w)
3747     : m_status(0)
3748 {
3749     const Maybe<bool> values[] = {x, y, z, w};
3750 
3751     for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(values); ndx++)
3752     {
3753         if (values[ndx])
3754             setValue(ndx, *values[ndx]);
3755         else
3756             setUndefined(ndx);
3757     }
3758 
3759     DE_ASSERT(m_status <= 0xFFu);
3760 }
3761 
setUndefined(size_t ndx)3762 void PixelValue::setUndefined(size_t ndx)
3763 {
3764     DE_ASSERT(ndx < 4);
3765     DE_ASSERT(m_status <= 0xFFu);
3766 
3767     m_status &= (uint16_t) ~(0x1u << (uint16_t)(ndx * 2));
3768     DE_ASSERT(m_status <= 0xFFu);
3769 }
3770 
setValue(size_t ndx,bool value)3771 void PixelValue::setValue(size_t ndx, bool value)
3772 {
3773     DE_ASSERT(ndx < 4);
3774     DE_ASSERT(m_status <= 0xFFu);
3775 
3776     m_status = (uint16_t)(m_status | (uint16_t)(0x1u << (ndx * 2)));
3777 
3778     if (value)
3779         m_status = (uint16_t)(m_status | (uint16_t)(0x1u << (ndx * 2 + 1)));
3780     else
3781         m_status &= (uint16_t) ~(0x1u << (uint16_t)(ndx * 2 + 1));
3782 
3783     DE_ASSERT(m_status <= 0xFFu);
3784 }
3785 
getValue(size_t ndx) const3786 Maybe<bool> PixelValue::getValue(size_t ndx) const
3787 {
3788     DE_ASSERT(ndx < 4);
3789     DE_ASSERT(m_status <= 0xFFu);
3790 
3791     if ((m_status & (0x1u << (uint16_t)(ndx * 2))) != 0)
3792     {
3793         return just((m_status & (0x1u << (uint32_t)(ndx * 2 + 1))) != 0);
3794     }
3795     else
3796         return tcu::Nothing;
3797 }
3798 
clearReferenceValues(vector<PixelValue> & values,const UVec2 & targetSize,const UVec2 & offset,const UVec2 & size,const BVec4 & mask,const PixelValue & value)3799 void clearReferenceValues(vector<PixelValue> &values, const UVec2 &targetSize, const UVec2 &offset, const UVec2 &size,
3800                           const BVec4 &mask, const PixelValue &value)
3801 {
3802     DE_ASSERT(targetSize.x() * targetSize.y() == (uint32_t)values.size());
3803     DE_ASSERT(offset.x() + size.x() <= targetSize.x());
3804     DE_ASSERT(offset.y() + size.y() <= targetSize.y());
3805 
3806     for (uint32_t y = offset.y(); y < offset.y() + size.y(); y++)
3807         for (uint32_t x = offset.x(); x < offset.x() + size.x(); x++)
3808         {
3809             for (int compNdx = 0; compNdx < 4; compNdx++)
3810             {
3811                 if (mask[compNdx])
3812                 {
3813                     if (value.getValue(compNdx))
3814                         values[x + y * targetSize.x()].setValue(compNdx, *value.getValue(compNdx));
3815                     else
3816                         values[x + y * targetSize.x()].setUndefined(compNdx);
3817                 }
3818             }
3819         }
3820 }
3821 
markUndefined(vector<PixelValue> & values,const BVec4 & mask,const UVec2 & targetSize,const UVec2 & offset,const UVec2 & size)3822 void markUndefined(vector<PixelValue> &values, const BVec4 &mask, const UVec2 &targetSize, const UVec2 &offset,
3823                    const UVec2 &size)
3824 {
3825     DE_ASSERT(targetSize.x() * targetSize.y() == (uint32_t)values.size());
3826 
3827     for (uint32_t y = offset.y(); y < offset.y() + size.y(); y++)
3828         for (uint32_t x = offset.x(); x < offset.x() + size.x(); x++)
3829         {
3830             for (int compNdx = 0; compNdx < 4; compNdx++)
3831             {
3832                 if (mask[compNdx])
3833                     values[x + y * targetSize.x()].setUndefined(compNdx);
3834             }
3835         }
3836 }
3837 
clearValueToPixelValue(const VkClearValue & value,const tcu::TextureFormat & format,const DepthValuesArray & depthValues)3838 PixelValue clearValueToPixelValue(const VkClearValue &value, const tcu::TextureFormat &format,
3839                                   const DepthValuesArray &depthValues)
3840 {
3841     const bool isDepthAttachment          = hasDepthComponent(format.order);
3842     const bool isStencilAttachment        = hasStencilComponent(format.order);
3843     const bool isDepthOrStencilAttachment = isDepthAttachment || isStencilAttachment;
3844     PixelValue pixelValue;
3845 
3846     if (isDepthOrStencilAttachment)
3847     {
3848         if (isDepthAttachment)
3849         {
3850             if (value.depthStencil.depth == float(depthValues[1]) / 255.0f)
3851                 pixelValue.setValue(0, true);
3852             else if (value.depthStencil.depth == float(depthValues[0]) / 255.0f)
3853                 pixelValue.setValue(0, false);
3854             else
3855                 DE_FATAL("Unknown depth value");
3856         }
3857 
3858         if (isStencilAttachment)
3859         {
3860             if (value.depthStencil.stencil == 0xFFu)
3861                 pixelValue.setValue(1, true);
3862             else if (value.depthStencil.stencil == 0x0u)
3863                 pixelValue.setValue(1, false);
3864             else
3865                 DE_FATAL("Unknown stencil value");
3866         }
3867     }
3868     else
3869     {
3870         const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
3871         const tcu::BVec4 channelMask                = tcu::getTextureFormatChannelMask(format);
3872 
3873         switch (channelClass)
3874         {
3875         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
3876             for (int i = 0; i < 4; i++)
3877             {
3878                 if (channelMask[i])
3879                 {
3880                     if (value.color.int32[i] == 1)
3881                         pixelValue.setValue(i, true);
3882                     else if (value.color.int32[i] == 0)
3883                         pixelValue.setValue(i, false);
3884                     else
3885                         DE_FATAL("Unknown clear color value");
3886                 }
3887             }
3888             break;
3889 
3890         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
3891             for (int i = 0; i < 4; i++)
3892             {
3893                 if (channelMask[i])
3894                 {
3895                     if (value.color.uint32[i] == 1u)
3896                         pixelValue.setValue(i, true);
3897                     else if (value.color.uint32[i] == 0u)
3898                         pixelValue.setValue(i, false);
3899                     else
3900                         DE_FATAL("Unknown clear color value");
3901                 }
3902             }
3903             break;
3904 
3905         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
3906         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
3907         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
3908             for (int i = 0; i < 4; i++)
3909             {
3910                 if (channelMask[i])
3911                 {
3912                     if (value.color.float32[i] == 1.0f)
3913                         pixelValue.setValue(i, true);
3914                     else if (value.color.float32[i] == 0.0f)
3915                         pixelValue.setValue(i, false);
3916                     else
3917                         DE_FATAL("Unknown clear color value");
3918                 }
3919             }
3920             break;
3921 
3922         default:
3923             DE_FATAL("Unknown channel class");
3924         }
3925     }
3926 
3927     return pixelValue;
3928 }
3929 
renderReferenceValues(vector<vector<PixelValue>> & referenceAttachments,const RenderPass & renderPassInfo,const UVec2 & targetSize,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo,const UVec2 & renderPos,const UVec2 & renderSize,const uint32_t drawStartNdx,const DepthValuesArray & depthValues)3930 void renderReferenceValues(vector<vector<PixelValue>> &referenceAttachments, const RenderPass &renderPassInfo,
3931                            const UVec2 &targetSize, const vector<Maybe<VkClearValue>> &imageClearValues,
3932                            const vector<Maybe<VkClearValue>> &renderPassClearValues,
3933                            const vector<SubpassRenderInfo> &subpassRenderInfo, const UVec2 &renderPos,
3934                            const UVec2 &renderSize, const uint32_t drawStartNdx, const DepthValuesArray &depthValues)
3935 {
3936     const vector<Subpass> &subpasses = renderPassInfo.getSubpasses();
3937     vector<bool> attachmentUsed(renderPassInfo.getAttachments().size(), false);
3938 
3939     referenceAttachments.resize(renderPassInfo.getAttachments().size());
3940 
3941     for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3942     {
3943         const Attachment attachment     = renderPassInfo.getAttachments()[attachmentNdx];
3944         const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
3945         vector<PixelValue> &reference   = referenceAttachments[attachmentNdx];
3946 
3947         reference.resize(targetSize.x() * targetSize.y());
3948 
3949         if (imageClearValues[attachmentNdx])
3950             clearReferenceValues(reference, targetSize, UVec2(0, 0), targetSize, BVec4(true),
3951                                  clearValueToPixelValue(*imageClearValues[attachmentNdx], format, depthValues));
3952     }
3953 
3954     for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
3955     {
3956         const Subpass &subpass                              = subpasses[subpassNdx];
3957         const SubpassRenderInfo &renderInfo                 = subpassRenderInfo[subpassNdx];
3958         const vector<AttachmentReference> &colorAttachments = subpass.getColorAttachments();
3959 
3960         // Apply load op if attachment was used for the first time
3961         for (size_t attachmentNdx = 0; attachmentNdx < colorAttachments.size(); attachmentNdx++)
3962         {
3963             const uint32_t attachmentIndex = getAttachmentNdx(colorAttachments, attachmentNdx);
3964 
3965             if (!attachmentUsed[attachmentIndex] &&
3966                 colorAttachments[attachmentNdx].getAttachment() != VK_ATTACHMENT_UNUSED)
3967             {
3968                 const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
3969                 vector<PixelValue> &reference   = referenceAttachments[attachmentIndex];
3970                 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
3971 
3972                 DE_ASSERT(!tcu::hasDepthComponent(format.order));
3973                 DE_ASSERT(!tcu::hasStencilComponent(format.order));
3974 
3975                 if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3976                     clearReferenceValues(
3977                         reference, targetSize, renderPos, renderSize, BVec4(true),
3978                         clearValueToPixelValue(*renderPassClearValues[attachmentIndex], format, depthValues));
3979                 else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3980                     markUndefined(reference, BVec4(true), targetSize, renderPos, renderSize);
3981 
3982                 attachmentUsed[attachmentIndex] = true;
3983             }
3984         }
3985 
3986         // Apply load op to depth/stencil attachment if it was used for the first time
3987         if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
3988         {
3989             const uint32_t attachmentIndex = subpass.getDepthStencilAttachment().getAttachment();
3990 
3991             // Apply load op if attachment was used for the first time
3992             if (!attachmentUsed[attachmentIndex])
3993             {
3994                 const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
3995                 vector<PixelValue> &reference   = referenceAttachments[attachmentIndex];
3996                 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
3997 
3998                 if (tcu::hasDepthComponent(format.order))
3999                 {
4000                     if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
4001                         clearReferenceValues(
4002                             reference, targetSize, renderPos, renderSize, BVec4(true, false, false, false),
4003                             clearValueToPixelValue(*renderPassClearValues[attachmentIndex], format, depthValues));
4004                     else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
4005                         markUndefined(reference, BVec4(true, false, false, false), targetSize, renderPos, renderSize);
4006                 }
4007 
4008                 if (tcu::hasStencilComponent(format.order))
4009                 {
4010                     if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
4011                         clearReferenceValues(
4012                             reference, targetSize, renderPos, renderSize, BVec4(false, true, false, false),
4013                             clearValueToPixelValue(*renderPassClearValues[attachmentIndex], format, depthValues));
4014                     else if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
4015                         markUndefined(reference, BVec4(false, true, false, false), targetSize, renderPos, renderSize);
4016                 }
4017 
4018                 attachmentUsed[attachmentIndex] = true;
4019             }
4020         }
4021 
4022         for (size_t colorClearNdx = 0; colorClearNdx < renderInfo.getColorClears().size(); colorClearNdx++)
4023         {
4024             const ColorClear &colorClear    = renderInfo.getColorClears()[colorClearNdx];
4025             const UVec2 offset              = colorClear.getOffset();
4026             const UVec2 size                = colorClear.getSize();
4027             const uint32_t attachmentIndex  = subpass.getColorAttachments()[colorClearNdx].getAttachment();
4028             const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
4029             const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4030             vector<PixelValue> &reference   = referenceAttachments[attachmentIndex];
4031             VkClearValue value;
4032 
4033             value.color = colorClear.getColor();
4034 
4035             clearReferenceValues(reference, targetSize, offset, size, BVec4(true),
4036                                  clearValueToPixelValue(value, format, depthValues));
4037         }
4038 
4039         if (renderInfo.getDepthStencilClear())
4040         {
4041             const DepthStencilClear &dsClear = *renderInfo.getDepthStencilClear();
4042             const UVec2 offset               = dsClear.getOffset();
4043             const UVec2 size                 = dsClear.getSize();
4044             const uint32_t attachmentIndex   = subpass.getDepthStencilAttachment().getAttachment();
4045             const VkImageLayout layout       = subpass.getDepthStencilAttachment().getImageLayout();
4046             const Attachment &attachment     = renderPassInfo.getAttachments()[attachmentIndex];
4047             const tcu::TextureFormat format  = mapVkFormat(attachment.getFormat());
4048             const bool hasStencil            = tcu::hasStencilComponent(format.order) &&
4049                                     layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
4050             const bool hasDepth = tcu::hasDepthComponent(format.order) &&
4051                                   layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
4052             vector<PixelValue> &reference = referenceAttachments[attachmentIndex];
4053             VkClearValue value;
4054 
4055             value.depthStencil.depth   = dsClear.getDepth();
4056             value.depthStencil.stencil = dsClear.getStencil();
4057 
4058             clearReferenceValues(reference, targetSize, offset, size, BVec4(hasDepth, hasStencil, false, false),
4059                                  clearValueToPixelValue(value, format, depthValues));
4060         }
4061 
4062         if (renderInfo.getRenderQuad())
4063         {
4064             const RenderQuad &renderQuad = *renderInfo.getRenderQuad();
4065             const Vec2 posA              = renderQuad.getCornerA();
4066             const Vec2 posB              = renderQuad.getCornerB();
4067             const Vec2 origin =
4068                 Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) +
4069                 Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
4070             const Vec2 p =
4071                 Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
4072             const IVec2 posAI(deRoundFloatToInt32(origin.x() + (p.x() * posA.x())),
4073                               deRoundFloatToInt32(origin.y() + (p.y() * posA.y())));
4074             const IVec2 posBI(deRoundFloatToInt32(origin.x() + (p.x() * posB.x())),
4075                               deRoundFloatToInt32(origin.y() + (p.y() * posB.y())));
4076 
4077             DE_ASSERT(posAI.x() < posBI.x());
4078             DE_ASSERT(posAI.y() < posBI.y());
4079 
4080             if (subpass.getInputAttachments().empty())
4081             {
4082                 for (size_t attachmentRefNdx = drawStartNdx; attachmentRefNdx < subpass.getColorAttachments().size();
4083                      attachmentRefNdx++)
4084                 {
4085                     const uint32_t attachmentIndex = subpass.getColorAttachments()[attachmentRefNdx].getAttachment();
4086 
4087                     if (attachmentIndex == VK_ATTACHMENT_UNUSED)
4088                         continue;
4089 
4090                     const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
4091                     const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4092                     const tcu::BVec4 channelMask    = tcu::getTextureFormatChannelMask(format);
4093                     vector<PixelValue> &reference   = referenceAttachments[attachmentIndex];
4094 
4095                     for (int y = posAI.y(); y < (int)posBI.y(); y++)
4096                         for (int x = posAI.x(); x < (int)posBI.x(); x++)
4097                         {
4098                             for (int compNdx = 0; compNdx < 4; compNdx++)
4099                             {
4100                                 const size_t index = subpassNdx + attachmentIndex + compNdx;
4101                                 const BoolOp op    = boolOpFromIndex(index);
4102                                 const bool boolX   = x % 2 == (int)(index % 2);
4103                                 const bool boolY   = y % 2 == (int)((index / 2) % 2);
4104 
4105                                 if (channelMask[compNdx])
4106                                     reference[x + y * targetSize.x()].setValue(compNdx,
4107                                                                                performBoolOp(op, boolX, boolY));
4108                             }
4109                         }
4110                 }
4111 
4112                 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
4113                 {
4114                     const uint32_t attachmentIndex  = subpass.getDepthStencilAttachment().getAttachment();
4115                     const VkImageLayout layout      = subpass.getDepthStencilAttachment().getImageLayout();
4116                     const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
4117                     const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4118                     vector<PixelValue> &reference   = referenceAttachments[attachmentIndex];
4119 
4120                     for (int y = posAI.y(); y < (int)posBI.y(); y++)
4121                         for (int x = posAI.x(); x < (int)posBI.x(); x++)
4122                         {
4123                             if (tcu::hasDepthComponent(format.order) &&
4124                                 layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
4125                                 layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
4126                             {
4127                                 const size_t index = subpassNdx + 1;
4128                                 const BoolOp op    = boolOpFromIndex(index);
4129                                 const bool boolX   = x % 2 == (int)(index % 2);
4130                                 const bool boolY   = y % 2 == (int)((index / 2) % 2);
4131 
4132                                 reference[x + y * targetSize.x()].setValue(0, performBoolOp(op, boolX, boolY));
4133                             }
4134 
4135                             if (tcu::hasStencilComponent(format.order) &&
4136                                 layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
4137                                 layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
4138                             {
4139                                 const size_t index = subpassNdx;
4140                                 reference[x + y * targetSize.x()].setValue(1, (index % 2) == 0);
4141                             }
4142                         }
4143                 }
4144             }
4145             else
4146             {
4147                 size_t outputComponentCount = 0;
4148                 vector<Maybe<bool>> inputs;
4149 
4150                 DE_ASSERT(posAI.x() < posBI.x());
4151                 DE_ASSERT(posAI.y() < posBI.y());
4152 
4153                 for (size_t attachmentRefNdx = 0; attachmentRefNdx < subpass.getColorAttachments().size();
4154                      attachmentRefNdx++)
4155                 {
4156                     const uint32_t attachmentIndex  = subpass.getColorAttachments()[attachmentRefNdx].getAttachment();
4157                     const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
4158                     const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4159                     const int componentCount        = getShaderNumChannels(format.order);
4160 
4161                     outputComponentCount += (size_t)componentCount;
4162                 }
4163 
4164                 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED &&
4165                     subpass.getDepthStencilAttachment().getImageLayout() !=
4166                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
4167                     subpass.getDepthStencilAttachment().getImageLayout() !=
4168                         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
4169                 {
4170                     const Attachment &attachment(
4171                         renderPassInfo.getAttachments()[subpass.getDepthStencilAttachment().getAttachment()]);
4172                     const tcu::TextureFormat format(mapVkFormat(attachment.getFormat()));
4173 
4174                     if (tcu::hasDepthComponent(format.order))
4175                         outputComponentCount++;
4176                 }
4177 
4178                 if (outputComponentCount > 0)
4179                 {
4180                     for (int y = posAI.y(); y < (int)posBI.y(); y++)
4181                         for (int x = posAI.x(); x < (int)posBI.x(); x++)
4182                         {
4183                             for (size_t inputAttachmentNdx = 0;
4184                                  inputAttachmentNdx < subpass.getInputAttachments().size(); inputAttachmentNdx++)
4185                             {
4186                                 const uint32_t attachmentIndex =
4187                                     subpass.getInputAttachments()[inputAttachmentNdx].getAttachment();
4188                                 const VkImageLayout layout =
4189                                     subpass.getInputAttachments()[inputAttachmentNdx].getImageLayout();
4190                                 const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
4191                                 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4192                                 const int componentCount        = getShaderNumChannels(format.order);
4193 
4194                                 for (int compNdx = 0; compNdx < componentCount; compNdx++)
4195                                 {
4196                                     if ((compNdx != 0 ||
4197                                          layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL) &&
4198                                         (compNdx != 1 ||
4199                                          layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL))
4200                                     {
4201                                         inputs.push_back(
4202                                             referenceAttachments[attachmentIndex][x + y * targetSize.x()].getValue(
4203                                                 compNdx));
4204                                     }
4205                                 }
4206                             }
4207 
4208                             const size_t inputsPerOutput = inputs.size() >= outputComponentCount ?
4209                                                                ((inputs.size() / outputComponentCount) +
4210                                                                 ((inputs.size() % outputComponentCount) != 0 ? 1 : 0)) :
4211                                                                1;
4212 
4213                             size_t outputValueNdx = 0;
4214 
4215                             for (size_t attachmentRefNdx = 0; attachmentRefNdx < subpass.getColorAttachments().size();
4216                                  attachmentRefNdx++)
4217                             {
4218                                 const uint32_t attachmentIndex =
4219                                     subpass.getColorAttachments()[attachmentRefNdx].getAttachment();
4220                                 const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
4221                                 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4222                                 vector<PixelValue> &reference   = referenceAttachments[attachmentIndex];
4223                                 const int componentCount        = getShaderNumChannels(format.order);
4224 
4225                                 for (int compNdx = 0; compNdx < componentCount; compNdx++)
4226                                 {
4227                                     const size_t index = subpassNdx + attachmentIndex + outputValueNdx;
4228                                     const BoolOp op    = boolOpFromIndex(index);
4229                                     const bool boolX   = x % 2 == (int)(index % 2);
4230                                     const bool boolY   = y % 2 == (int)((index / 2) % 2);
4231                                     Maybe<bool> output = tcu::just(performBoolOp(op, boolX, boolY));
4232 
4233                                     for (size_t i = 0; i < inputsPerOutput; i++)
4234                                     {
4235                                         if (!output)
4236                                             break;
4237                                         else if (!inputs[((outputValueNdx + compNdx) * inputsPerOutput + i) %
4238                                                          inputs.size()])
4239                                             output = tcu::Nothing;
4240                                         else
4241                                             output = (*output) ==
4242                                                      (*inputs[((outputValueNdx + compNdx) * inputsPerOutput + i) %
4243                                                               inputs.size()]);
4244                                     }
4245 
4246                                     if (output)
4247                                         reference[x + y * targetSize.x()].setValue(compNdx, *output);
4248                                     else
4249                                         reference[x + y * targetSize.x()].setUndefined(compNdx);
4250                                 }
4251 
4252                                 outputValueNdx += componentCount;
4253                             }
4254 
4255                             if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED &&
4256                                 subpass.getDepthStencilAttachment().getImageLayout() !=
4257                                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
4258                                 subpass.getDepthStencilAttachment().getImageLayout() !=
4259                                     VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
4260                             {
4261                                 const uint32_t attachmentIndex = subpass.getDepthStencilAttachment().getAttachment();
4262                                 vector<PixelValue> &reference  = referenceAttachments[attachmentIndex];
4263                                 const size_t index             = subpassNdx + attachmentIndex;
4264                                 const BoolOp op                = boolOpFromIndex(index);
4265                                 const bool boolX               = x % 2 == (int)(index % 2);
4266                                 const bool boolY               = y % 2 == (int)((index / 2) % 2);
4267                                 Maybe<bool> output             = tcu::just(performBoolOp(op, boolX, boolY));
4268 
4269                                 for (size_t i = 0; i < inputsPerOutput; i++)
4270                                 {
4271                                     if (!output)
4272                                         break;
4273                                     else if (inputs[(outputValueNdx * inputsPerOutput + i) % inputs.size()])
4274                                         output = (*output) ==
4275                                                  (*inputs[(outputValueNdx * inputsPerOutput + i) % inputs.size()]);
4276                                     else
4277                                         output = tcu::Nothing;
4278                                 }
4279 
4280                                 if (output)
4281                                     reference[x + y * targetSize.x()].setValue(0, *output);
4282                                 else
4283                                     reference[x + y * targetSize.x()].setUndefined(0);
4284                             }
4285 
4286                             inputs.clear();
4287                         }
4288                 }
4289 
4290                 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED &&
4291                     subpass.getDepthStencilAttachment().getImageLayout() !=
4292                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
4293                     subpass.getDepthStencilAttachment().getImageLayout() !=
4294                         VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
4295                 {
4296                     const uint32_t attachmentIndex  = subpass.getDepthStencilAttachment().getAttachment();
4297                     const Attachment &attachment    = renderPassInfo.getAttachments()[attachmentIndex];
4298                     const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4299                     vector<PixelValue> &reference   = referenceAttachments[attachmentIndex];
4300 
4301                     if (tcu::hasStencilComponent(format.order))
4302                     {
4303                         for (int y = posAI.y(); y < (int)posBI.y(); y++)
4304                             for (int x = posAI.x(); x < (int)posBI.x(); x++)
4305                             {
4306                                 const size_t index = subpassNdx;
4307                                 reference[x + y * targetSize.x()].setValue(1, (index % 2) == 0);
4308                             }
4309                     }
4310                 }
4311             }
4312         }
4313     }
4314 
4315     // Mark all attachments that were used but not stored as undefined
4316     for (size_t attachmentIndex = 0; attachmentIndex < renderPassInfo.getAttachments().size(); attachmentIndex++)
4317     {
4318         const Attachment attachment           = renderPassInfo.getAttachments()[attachmentIndex];
4319         const tcu::TextureFormat format       = mapVkFormat(attachment.getFormat());
4320         vector<PixelValue> &reference         = referenceAttachments[attachmentIndex];
4321         const bool isStencilAttachment        = hasStencilComponent(format.order);
4322         const bool isDepthOrStencilAttachment = hasDepthComponent(format.order) || isStencilAttachment;
4323 
4324         if (attachmentUsed[attachmentIndex] &&
4325             renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
4326         {
4327             if (isDepthOrStencilAttachment)
4328                 markUndefined(reference, BVec4(true, false, false, false), targetSize, renderPos, renderSize);
4329             else
4330                 markUndefined(reference, BVec4(true), targetSize, renderPos, renderSize);
4331         }
4332 
4333         if (attachmentUsed[attachmentIndex] && isStencilAttachment &&
4334             renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
4335             markUndefined(reference, BVec4(false, true, false, false), targetSize, renderPos, renderSize);
4336     }
4337 }
4338 
renderReferenceImagesFromValues(vector<tcu::TextureLevel> & referenceImages,const vector<vector<PixelValue>> & referenceValues,const UVec2 & targetSize,const RenderPass & renderPassInfo,const DepthValuesArray & depthValues)4339 void renderReferenceImagesFromValues(vector<tcu::TextureLevel> &referenceImages,
4340                                      const vector<vector<PixelValue>> &referenceValues, const UVec2 &targetSize,
4341                                      const RenderPass &renderPassInfo, const DepthValuesArray &depthValues)
4342 {
4343     referenceImages.resize(referenceValues.size());
4344 
4345     for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
4346     {
4347         const Attachment attachment         = renderPassInfo.getAttachments()[attachmentNdx];
4348         const tcu::TextureFormat format     = mapVkFormat(attachment.getFormat());
4349         const vector<PixelValue> &reference = referenceValues[attachmentNdx];
4350         const bool hasDepth                 = tcu::hasDepthComponent(format.order);
4351         const bool hasStencil               = tcu::hasStencilComponent(format.order);
4352         const bool hasDepthOrStencil        = hasDepth || hasStencil;
4353         tcu::TextureLevel &referenceImage   = referenceImages[attachmentNdx];
4354 
4355         referenceImage.setStorage(format, targetSize.x(), targetSize.y());
4356 
4357         if (hasDepthOrStencil)
4358         {
4359             if (hasDepth)
4360             {
4361                 const PixelBufferAccess depthAccess(
4362                     tcu::getEffectiveDepthStencilAccess(referenceImage.getAccess(), tcu::Sampler::MODE_DEPTH));
4363 
4364                 for (uint32_t y = 0; y < targetSize.y(); y++)
4365                     for (uint32_t x = 0; x < targetSize.x(); x++)
4366                     {
4367                         if (reference[x + y * targetSize.x()].getValue(0))
4368                         {
4369                             if (*reference[x + y * targetSize.x()].getValue(0))
4370                                 depthAccess.setPixDepth(float(depthValues[1]) / 255.0f, x, y);
4371                             else
4372                                 depthAccess.setPixDepth(float(depthValues[0]) / 255.0f, x, y);
4373                         }
4374                         else // Fill with 3x3 grid
4375                             depthAccess.setPixDepth(((x / 3) % 2) == ((y / 3) % 2) ? 0.33f : 0.66f, x, y);
4376                     }
4377             }
4378 
4379             if (hasStencil)
4380             {
4381                 const PixelBufferAccess stencilAccess(
4382                     tcu::getEffectiveDepthStencilAccess(referenceImage.getAccess(), tcu::Sampler::MODE_STENCIL));
4383 
4384                 for (uint32_t y = 0; y < targetSize.y(); y++)
4385                     for (uint32_t x = 0; x < targetSize.x(); x++)
4386                     {
4387                         if (reference[x + y * targetSize.x()].getValue(1))
4388                         {
4389                             if (*reference[x + y * targetSize.x()].getValue(1))
4390                                 stencilAccess.setPixStencil(0xFFu, x, y);
4391                             else
4392                                 stencilAccess.setPixStencil(0x0u, x, y);
4393                         }
4394                         else // Fill with 3x3 grid
4395                             stencilAccess.setPixStencil(((x / 3) % 2) == ((y / 3) % 2) ? 85 : 170, x, y);
4396                     }
4397             }
4398         }
4399         else
4400         {
4401             for (uint32_t y = 0; y < targetSize.y(); y++)
4402                 for (uint32_t x = 0; x < targetSize.x(); x++)
4403                 {
4404                     tcu::Vec4 color;
4405 
4406                     for (int compNdx = 0; compNdx < 4; compNdx++)
4407                     {
4408                         if (reference[x + y * targetSize.x()].getValue(compNdx))
4409                         {
4410                             if (*reference[x + y * targetSize.x()].getValue(compNdx))
4411                                 color[compNdx] = 1.0f;
4412                             else
4413                                 color[compNdx] = 0.0f;
4414                         }
4415                         else // Fill with 3x3 grid
4416                             color[compNdx] = ((compNdx + (x / 3)) % 2) == ((y / 3) % 2) ? 0.33f : 0.66f;
4417                     }
4418 
4419                     referenceImage.getAccess().setPixel(color, x, y);
4420                 }
4421         }
4422     }
4423 }
4424 
verifyColorAttachment(const vector<PixelValue> & reference,const ConstPixelBufferAccess & result,const PixelBufferAccess & errorImage,const bool useFormatCompCount)4425 bool verifyColorAttachment(const vector<PixelValue> &reference, const ConstPixelBufferAccess &result,
4426                            const PixelBufferAccess &errorImage, const bool useFormatCompCount)
4427 {
4428     const Vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
4429     const Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
4430     bool ok = true;
4431 
4432     DE_ASSERT(result.getWidth() * result.getHeight() == (int)reference.size());
4433     DE_ASSERT(result.getWidth() == errorImage.getWidth());
4434     DE_ASSERT(result.getHeight() == errorImage.getHeight());
4435 
4436     for (int y = 0; y < result.getHeight(); y++)
4437         for (int x = 0; x < result.getWidth(); x++)
4438         {
4439             const Vec4 resultColor           = result.getPixel(x, y);
4440             const PixelValue &referenceValue = reference[x + y * result.getWidth()];
4441             bool pixelOk                     = true;
4442             const uint32_t componentCount =
4443                 useFormatCompCount ? static_cast<uint32_t>(getShaderNumChannels(result.getFormat().order)) : 4;
4444 
4445             for (uint32_t compNdx = 0; compNdx < componentCount; compNdx++)
4446             {
4447                 const Maybe<bool> maybeValue = referenceValue.getValue(compNdx);
4448 
4449                 if (maybeValue)
4450                 {
4451                     const bool value = *maybeValue;
4452 
4453                     if ((value && (resultColor[compNdx] != 1.0f)) || (!value && resultColor[compNdx] != 0.0f))
4454                         pixelOk = false;
4455                 }
4456             }
4457 
4458             if (!pixelOk)
4459             {
4460                 errorImage.setPixel(red, x, y);
4461                 ok = false;
4462             }
4463             else
4464                 errorImage.setPixel(green, x, y);
4465         }
4466 
4467     return ok;
4468 }
4469 
4470 // Setting the alpha value to 1.0f by default helps visualization when the alpha channel is not used.
4471 const tcu::Vec4 kDefaultColorForLog{0.0f, 0.0f, 0.0f, 1.0f};
4472 const float kTrueComponent      = 1.0f;
4473 const float kFalseComponent     = 0.5f;
4474 const float kUnsetComponentLow  = 0.0f;
4475 const float kUnsetComponentHigh = 0.25f;
4476 
renderColorImageForLog(const ConstPixelBufferAccess & image,int numChannels)4477 std::unique_ptr<tcu::TextureLevel> renderColorImageForLog(const ConstPixelBufferAccess &image, int numChannels)
4478 {
4479     // Same channel order, but using UNORM_INT8 for the color format.
4480     const auto order = image.getFormat().order;
4481     const tcu::TextureFormat loggableFormat{order, tcu::TextureFormat::UNORM_INT8};
4482     const int width  = image.getWidth();
4483     const int height = image.getHeight();
4484     std::unique_ptr<tcu::TextureLevel> result{new tcu::TextureLevel{loggableFormat, width, height}};
4485     auto access        = result->getAccess();
4486     tcu::Vec4 outColor = kDefaultColorForLog;
4487 
4488     for (int x = 0; x < width; ++x)
4489         for (int y = 0; y < height; ++y)
4490         {
4491             const auto value = image.getPixel(x, y);
4492             for (int c = 0; c < numChannels; ++c)
4493             {
4494                 if (value[c] == 1.0f)
4495                     outColor[c] = kTrueComponent;
4496                 else
4497                     outColor[c] = kFalseComponent;
4498             }
4499             access.setPixel(outColor, x, y);
4500         }
4501 
4502     return result;
4503 }
4504 
renderColorImageForLog(const vector<PixelValue> & reference,const UVec2 & targetSize,int numChannels)4505 std::unique_ptr<tcu::TextureLevel> renderColorImageForLog(const vector<PixelValue> &reference, const UVec2 &targetSize,
4506                                                           int numChannels)
4507 {
4508     const tcu::TextureFormat loggableFormat{tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8};
4509     const int width  = static_cast<int>(targetSize.x());
4510     const int height = static_cast<int>(targetSize.y());
4511     std::unique_ptr<tcu::TextureLevel> result{new tcu::TextureLevel{loggableFormat, width, height}};
4512     auto access        = result->getAccess();
4513     tcu::Vec4 outColor = kDefaultColorForLog;
4514 
4515     for (int x = 0; x < width; ++x)
4516         for (int y = 0; y < height; ++y)
4517         {
4518             const int index = x + y * width;
4519             for (int c = 0; c < numChannels; ++c)
4520             {
4521                 const auto maybeValue = reference[index].getValue(c);
4522                 if (maybeValue)
4523                     outColor[c] = ((*maybeValue) ? kTrueComponent : kFalseComponent);
4524                 else
4525                     outColor[c] = ((((x / 3) % 2) == ((y / 3) % 2)) ? kUnsetComponentLow : kUnsetComponentHigh);
4526             }
4527             access.setPixel(outColor, x, y);
4528         }
4529 
4530     return result;
4531 }
4532 
verifyDepthAttachment(const vector<PixelValue> & reference,const ConstPixelBufferAccess & result,const PixelBufferAccess & errorImage,const DepthValuesArray & depthValues,float epsilon)4533 bool verifyDepthAttachment(const vector<PixelValue> &reference, const ConstPixelBufferAccess &result,
4534                            const PixelBufferAccess &errorImage, const DepthValuesArray &depthValues, float epsilon)
4535 {
4536     const Vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
4537     const Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
4538     bool ok = true;
4539 
4540     DE_ASSERT(result.getWidth() * result.getHeight() == (int)reference.size());
4541     DE_ASSERT(result.getWidth() == errorImage.getWidth());
4542     DE_ASSERT(result.getHeight() == errorImage.getHeight());
4543 
4544     for (int y = 0; y < result.getHeight(); y++)
4545         for (int x = 0; x < result.getWidth(); x++)
4546         {
4547             bool pixelOk = true;
4548 
4549             const float resultDepth          = result.getPixDepth(x, y);
4550             const PixelValue &referenceValue = reference[x + y * result.getWidth()];
4551             const Maybe<bool> maybeValue     = referenceValue.getValue(0);
4552 
4553             if (maybeValue)
4554             {
4555                 const bool value = *maybeValue;
4556 
4557                 if ((value && !depthsEqual(resultDepth, float(depthValues[1]) / 255.0f, epsilon)) ||
4558                     (!value && !depthsEqual(resultDepth, float(depthValues[0]) / 255.0f, epsilon)))
4559                     pixelOk = false;
4560             }
4561 
4562             if (!pixelOk)
4563             {
4564                 errorImage.setPixel(red, x, y);
4565                 ok = false;
4566             }
4567             else
4568                 errorImage.setPixel(green, x, y);
4569         }
4570 
4571     return ok;
4572 }
4573 
verifyStencilAttachment(const vector<PixelValue> & reference,const ConstPixelBufferAccess & result,const PixelBufferAccess & errorImage)4574 bool verifyStencilAttachment(const vector<PixelValue> &reference, const ConstPixelBufferAccess &result,
4575                              const PixelBufferAccess &errorImage)
4576 {
4577     const Vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
4578     const Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
4579     bool ok = true;
4580 
4581     DE_ASSERT(result.getWidth() * result.getHeight() == (int)reference.size());
4582     DE_ASSERT(result.getWidth() == errorImage.getWidth());
4583     DE_ASSERT(result.getHeight() == errorImage.getHeight());
4584 
4585     for (int y = 0; y < result.getHeight(); y++)
4586         for (int x = 0; x < result.getWidth(); x++)
4587         {
4588             bool pixelOk = true;
4589 
4590             const uint32_t resultStencil     = result.getPixStencil(x, y);
4591             const PixelValue &referenceValue = reference[x + y * result.getWidth()];
4592             const Maybe<bool> maybeValue     = referenceValue.getValue(1);
4593 
4594             if (maybeValue)
4595             {
4596                 const bool value = *maybeValue;
4597 
4598                 if ((value && (resultStencil != 0xFFu)) || (!value && resultStencil != 0x0u))
4599                     pixelOk = false;
4600             }
4601 
4602             if (!pixelOk)
4603             {
4604                 errorImage.setPixel(red, x, y);
4605                 ok = false;
4606             }
4607             else
4608                 errorImage.setPixel(green, x, y);
4609         }
4610 
4611     return ok;
4612 }
4613 
logAndVerifyImages(TestLog & log,const DeviceInterface & vk,VkDevice device,const vector<de::SharedPtr<AttachmentResources>> & attachmentResources,const vector<bool> & attachmentIsLazy,const RenderPass & renderPassInfo,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo,const UVec2 & targetSize,const TestConfig & config)4614 bool logAndVerifyImages(TestLog &log, const DeviceInterface &vk, VkDevice device,
4615                         const vector<de::SharedPtr<AttachmentResources>> &attachmentResources,
4616                         const vector<bool> &attachmentIsLazy, const RenderPass &renderPassInfo,
4617                         const vector<Maybe<VkClearValue>> &renderPassClearValues,
4618                         const vector<Maybe<VkClearValue>> &imageClearValues,
4619                         const vector<SubpassRenderInfo> &subpassRenderInfo, const UVec2 &targetSize,
4620                         const TestConfig &config)
4621 {
4622     vector<vector<PixelValue>> referenceValues;
4623     vector<tcu::TextureLevel> referenceAttachments;
4624     bool isOk = true;
4625 
4626     log << TestLog::Message << "Reference images fill undefined pixels with 3x3 grid pattern." << TestLog::EndMessage;
4627 
4628     renderReferenceValues(referenceValues, renderPassInfo, targetSize, imageClearValues, renderPassClearValues,
4629                           subpassRenderInfo, config.renderPos, config.renderSize, config.drawStartNdx,
4630                           config.depthValues);
4631     renderReferenceImagesFromValues(referenceAttachments, referenceValues, targetSize, renderPassInfo,
4632                                     config.depthValues);
4633 
4634     for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
4635     {
4636         if (!attachmentIsLazy[attachmentNdx])
4637         {
4638             bool attachmentOK               = true;
4639             const Attachment attachment     = renderPassInfo.getAttachments()[attachmentNdx];
4640             const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4641 
4642             if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
4643             {
4644                 const tcu::TextureFormat depthFormat = getDepthCopyFormat(attachment.getFormat());
4645                 void *const depthPtr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
4646 
4647                 const tcu::TextureFormat stencilFormat = getStencilCopyFormat(attachment.getFormat());
4648                 void *const stencilPtr = attachmentResources[attachmentNdx]->getSecondaryResultMemory().getHostPtr();
4649 
4650                 invalidateAlloc(vk, device, attachmentResources[attachmentNdx]->getResultMemory());
4651                 invalidateAlloc(vk, device, attachmentResources[attachmentNdx]->getSecondaryResultMemory());
4652 
4653                 {
4654                     bool depthOK   = true;
4655                     bool stencilOK = true;
4656                     const ConstPixelBufferAccess depthAccess(depthFormat, targetSize.x(), targetSize.y(), 1, depthPtr);
4657                     const ConstPixelBufferAccess stencilAccess(stencilFormat, targetSize.x(), targetSize.y(), 1,
4658                                                                stencilPtr);
4659                     tcu::TextureLevel depthErrorImage(
4660                         tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(),
4661                         targetSize.y());
4662                     tcu::TextureLevel stencilErrorImage(
4663                         tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(),
4664                         targetSize.y());
4665 
4666                     if (renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE &&
4667                         !verifyDepthAttachment(referenceValues[attachmentNdx], depthAccess, depthErrorImage.getAccess(),
4668                                                config.depthValues, requiredDepthEpsilon(attachment.getFormat())))
4669                     {
4670                         depthOK = false;
4671                     }
4672 
4673                     if (renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() ==
4674                             VK_ATTACHMENT_STORE_OP_STORE &&
4675                         !verifyStencilAttachment(referenceValues[attachmentNdx], stencilAccess,
4676                                                  stencilErrorImage.getAccess()))
4677                     {
4678                         stencilOK = false;
4679                     }
4680 
4681                     if (!depthOK || !stencilOK)
4682                     {
4683                         const auto attachmentNdxStr = de::toString(attachmentNdx);
4684 
4685                         // Output images.
4686                         log << TestLog::ImageSet("OutputAttachments" + attachmentNdxStr,
4687                                                  "Output depth and stencil attachments " + attachmentNdxStr);
4688                         log << TestLog::Image("Attachment" + attachmentNdxStr + "Depth",
4689                                               "Attachment " + attachmentNdxStr + " Depth", depthAccess);
4690                         log << TestLog::Image("Attachment" + attachmentNdxStr + "Stencil",
4691                                               "Attachment " + attachmentNdxStr + " Stencil", stencilAccess);
4692                         log << TestLog::EndImageSet;
4693 
4694                         // Reference images. These will be logged as image sets due to having depth and stencil aspects.
4695                         log << TestLog::Image("AttachmentReferences" + attachmentNdxStr,
4696                                               "Reference images " + attachmentNdxStr,
4697                                               referenceAttachments[attachmentNdx].getAccess());
4698 
4699                         // Error masks.
4700                         log << TestLog::ImageSet("ErrorMasks" + attachmentNdxStr, "Error masks " + attachmentNdxStr);
4701                         if (!depthOK)
4702                             log << TestLog::Image("DepthAttachmentError" + attachmentNdxStr,
4703                                                   "Depth Attachment Error " + attachmentNdxStr,
4704                                                   depthErrorImage.getAccess());
4705                         if (!stencilOK)
4706                             log << TestLog::Image("StencilAttachmentError" + attachmentNdxStr,
4707                                                   "Stencil Attachment Error " + attachmentNdxStr,
4708                                                   stencilErrorImage.getAccess());
4709                         log << TestLog::EndImageSet;
4710 
4711                         attachmentOK = false;
4712                     }
4713                 }
4714             }
4715             else
4716             {
4717                 void *const ptr = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
4718 
4719                 invalidateAlloc(vk, device, attachmentResources[attachmentNdx]->getResultMemory());
4720 
4721                 bool depthOK   = true;
4722                 bool stencilOK = true;
4723                 bool colorOK   = true;
4724                 const ConstPixelBufferAccess access(format, targetSize.x(), targetSize.y(), 1, ptr);
4725                 tcu::TextureLevel errorImage(
4726                     tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(),
4727                     targetSize.y());
4728 
4729                 if (tcu::hasDepthComponent(format.order))
4730                 {
4731                     if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE ||
4732                          renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() ==
4733                              VK_ATTACHMENT_STORE_OP_STORE) &&
4734                         !verifyDepthAttachment(referenceValues[attachmentNdx], access, errorImage.getAccess(),
4735                                                config.depthValues, requiredDepthEpsilon(attachment.getFormat())))
4736                     {
4737                         depthOK = false;
4738                     }
4739                 }
4740                 else if (tcu::hasStencilComponent(format.order))
4741                 {
4742                     if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE ||
4743                          renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() ==
4744                              VK_ATTACHMENT_STORE_OP_STORE) &&
4745                         !verifyStencilAttachment(referenceValues[attachmentNdx], access, errorImage.getAccess()))
4746                     {
4747                         stencilOK = false;
4748                     }
4749                 }
4750                 else
4751                 {
4752                     if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE ||
4753                          renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() ==
4754                              VK_ATTACHMENT_STORE_OP_STORE) &&
4755                         !verifyColorAttachment(referenceValues[attachmentNdx], access, errorImage.getAccess(),
4756                                                config.useFormatCompCount))
4757                     {
4758                         colorOK = false;
4759                     }
4760                 }
4761 
4762                 if (!depthOK || !stencilOK || !colorOK)
4763                 {
4764                     log << TestLog::ImageSet("TestImages", "Output attachment, reference image and error mask");
4765                     if (!depthOK || !stencilOK)
4766                     {
4767                         // Log without conversions.
4768                         log << TestLog::Image("Attachment" + de::toString(attachmentNdx),
4769                                               "Attachment " + de::toString(attachmentNdx), access);
4770                         log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx),
4771                                               "Attachment reference " + de::toString(attachmentNdx),
4772                                               referenceAttachments[attachmentNdx].getAccess());
4773                     }
4774                     else
4775                     {
4776                         // Convert color images to better reflect test status and output in any format.
4777                         const auto numChannels      = getShaderNumChannels(access.getFormat().order);
4778                         const auto attachmentForLog = renderColorImageForLog(access, numChannels);
4779                         const auto referenceForLog =
4780                             renderColorImageForLog(referenceValues[attachmentNdx], targetSize, numChannels);
4781 
4782                         log << TestLog::Message
4783                             << "Check the attachment formats and test data to verify which components affect the test "
4784                                "result."
4785                             << TestLog::EndMessage;
4786                         log << TestLog::Message
4787                             << "In the reference image, unset pixel components are marked with a 3x3 grid storing "
4788                                "values 0.0 and 0.25, pixel components set to false are stored as 0.5 and pixel "
4789                                "components set to true are stored as 1.0."
4790                             << TestLog::EndMessage;
4791                         log << TestLog::Message
4792                             << "Output attachment pixel components are always set to 0.5 or 1.0 but may not be taken "
4793                                "into account if not set in the reference image."
4794                             << TestLog::EndMessage;
4795 
4796                         log << TestLog::Image("Attachment" + de::toString(attachmentNdx),
4797                                               "Attachment " + de::toString(attachmentNdx),
4798                                               attachmentForLog->getAccess());
4799                         log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx),
4800                                               "Attachment reference " + de::toString(attachmentNdx),
4801                                               referenceForLog->getAccess());
4802                     }
4803                     log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx),
4804                                           "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
4805                     log << TestLog::EndImageSet;
4806 
4807                     attachmentOK = false;
4808                 }
4809             }
4810 
4811             if (!attachmentOK)
4812                 isOk = false;
4813         }
4814     }
4815 
4816     return isOk;
4817 }
4818 
getInputAttachmentType(VkFormat vkFormat)4819 std::string getInputAttachmentType(VkFormat vkFormat)
4820 {
4821     const tcu::TextureFormat format             = mapVkFormat(vkFormat);
4822     const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
4823 
4824     switch (channelClass)
4825     {
4826     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
4827         return "isubpassInput";
4828 
4829     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
4830         return "usubpassInput";
4831 
4832     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
4833     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
4834     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
4835         return "subpassInput";
4836 
4837     default:
4838         DE_FATAL("Unknown channel class");
4839         return "";
4840     }
4841 }
4842 
getAttachmentType(VkFormat vkFormat,bool useFormatCompCount)4843 std::string getAttachmentType(VkFormat vkFormat, bool useFormatCompCount)
4844 {
4845     const tcu::TextureFormat format             = mapVkFormat(vkFormat);
4846     const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
4847     const size_t componentCount                 = (size_t)getShaderNumChannels(format.order);
4848 
4849     switch (channelClass)
4850     {
4851     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
4852         if (useFormatCompCount)
4853             return (componentCount == 1 ? "int" : "ivec" + de::toString(componentCount));
4854         else
4855             return "ivec4";
4856 
4857     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
4858         if (useFormatCompCount)
4859             return (componentCount == 1 ? "uint" : "uvec" + de::toString(componentCount));
4860         else
4861             return "uvec4";
4862 
4863     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
4864     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
4865     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
4866         if (useFormatCompCount)
4867             return (componentCount == 1 ? "float" : "vec" + de::toString(componentCount));
4868         else
4869             return "vec4";
4870 
4871     default:
4872         DE_FATAL("Unknown channel class");
4873         return "";
4874     }
4875 }
4876 
createTestShaders(SourceCollections & dst,TestConfig config)4877 void createTestShaders(SourceCollections &dst, TestConfig config)
4878 {
4879     if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
4880     {
4881         const vector<Subpass> &subpasses = config.renderPass.getSubpasses();
4882 
4883         for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
4884         {
4885             const Subpass &subpass          = subpasses[subpassNdx];
4886             uint32_t inputAttachmentBinding = 0;
4887             std::ostringstream vertexShader;
4888             std::ostringstream fragmentShader;
4889 
4890             vertexShader << "#version 310 es\n"
4891                          << "layout(location = 0) in highp vec2 a_position;\n"
4892                          << "void main (void) {\n"
4893                          << "\tgl_Position = vec4(a_position, 1.0, 1.0);\n"
4894                          << "}\n";
4895 
4896             fragmentShader << "#version 310 es\n"
4897                            << "precision highp float;\n";
4898 
4899             bool hasAnyDepthFormats = false;
4900 
4901             for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getInputAttachments().size();
4902                  attachmentNdx++)
4903             {
4904                 const uint32_t attachmentIndex  = subpass.getInputAttachments()[attachmentNdx].getAttachment();
4905                 const VkImageLayout layout      = subpass.getInputAttachments()[attachmentNdx].getImageLayout();
4906                 const Attachment attachment     = config.renderPass.getAttachments()[attachmentIndex];
4907                 const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4908                 const bool isDepthFormat        = tcu::hasDepthComponent(format.order);
4909                 const bool isStencilFormat      = tcu::hasStencilComponent(format.order);
4910 
4911                 if (isDepthFormat || isStencilFormat)
4912                 {
4913                     if (isDepthFormat && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
4914                     {
4915                         hasAnyDepthFormats = true;
4916                         fragmentShader << "layout(input_attachment_index = " << attachmentNdx
4917                                        << ", set=0, binding=" << inputAttachmentBinding
4918                                        << ") uniform highp subpassInput i_depth" << attachmentNdx << ";\n";
4919                         inputAttachmentBinding++;
4920                     }
4921 
4922                     if (isStencilFormat && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
4923                     {
4924                         fragmentShader << "layout(input_attachment_index = " << attachmentNdx
4925                                        << ", set=0, binding=" << inputAttachmentBinding
4926                                        << ") uniform highp usubpassInput i_stencil" << attachmentNdx << ";\n";
4927                         inputAttachmentBinding++;
4928                     }
4929                 }
4930                 else
4931                 {
4932                     const std::string attachmentType = getInputAttachmentType(attachment.getFormat());
4933 
4934                     fragmentShader << "layout(input_attachment_index = " << attachmentNdx
4935                                    << ", set=0, binding=" << inputAttachmentBinding << ") uniform highp "
4936                                    << attachmentType << " i_color" << attachmentNdx << ";\n";
4937                     inputAttachmentBinding++;
4938                 }
4939             }
4940 
4941             for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getColorAttachments().size();
4942                  attachmentNdx++)
4943             {
4944                 const std::string attachmentType = getAttachmentType(
4945                     config.renderPass.getAttachments()[getAttachmentNdx(subpass.getColorAttachments(), attachmentNdx)]
4946                         .getFormat(),
4947                     config.useFormatCompCount);
4948                 fragmentShader << "layout(location = " << attachmentNdx << ") out highp " << attachmentType
4949                                << " o_color" << attachmentNdx << ";\n";
4950             }
4951 
4952             if (hasAnyDepthFormats)
4953                 fragmentShader << "\nbool depthsEqual(float a, float b, float epsilon) {\n"
4954                                << "\treturn abs(a - b) <= epsilon;\n}\n\n";
4955 
4956             fragmentShader << "void main (void) {\n";
4957 
4958             if (subpass.getInputAttachments().empty())
4959             {
4960                 for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getColorAttachments().size();
4961                      attachmentNdx++)
4962                 {
4963                     const uint32_t attachmentIndex = subpass.getColorAttachments()[attachmentNdx].getAttachment();
4964 
4965                     if (attachmentIndex == VK_ATTACHMENT_UNUSED)
4966                         continue;
4967 
4968                     const Attachment attachment     = config.renderPass.getAttachments()[attachmentIndex];
4969                     const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
4970                     const size_t componentCount =
4971                         config.useFormatCompCount ? (size_t)getShaderNumChannels(format.order) : 4;
4972                     const std::string attachmentType =
4973                         getAttachmentType(attachment.getFormat(), config.useFormatCompCount);
4974 
4975                     fragmentShader << "\to_color" << attachmentNdx << " = " << attachmentType << "("
4976                                    << attachmentType + "(";
4977 
4978                     for (size_t compNdx = 0; compNdx < componentCount; compNdx++)
4979                     {
4980                         const size_t index = subpassNdx + attachmentIndex + compNdx;
4981                         const BoolOp op    = boolOpFromIndex(index);
4982 
4983                         if (compNdx > 0)
4984                             fragmentShader << ",\n\t\t";
4985 
4986                         fragmentShader << "((int(gl_FragCoord.x) % 2 == " << (index % 2) << ") " << boolOpToString(op)
4987                                        << " ("
4988                                        << "int(gl_FragCoord.y) % 2 == " << ((index / 2) % 2) << ") ? 1.0 : 0.0)";
4989                     }
4990 
4991                     fragmentShader << "));\n";
4992                 }
4993 
4994                 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED &&
4995                     subpass.getDepthStencilAttachment().getImageLayout() !=
4996                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
4997                     subpass.getDepthStencilAttachment().getImageLayout() !=
4998                         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
4999                 {
5000                     const size_t index = subpassNdx + 1;
5001                     const BoolOp op    = boolOpFromIndex(index);
5002 
5003                     fragmentShader << "\tgl_FragDepth = ((int(gl_FragCoord.x) % 2 == " << (index % 2) << ") "
5004                                    << boolOpToString(op) << " ("
5005                                    << "int(gl_FragCoord.y) % 2 == " << ((index / 2) % 2) << ") ? "
5006                                    << uint32_t(config.depthValues[1])
5007                                    << ".0f/255.0f : " << uint32_t(config.depthValues[0]) << ".0f/255.0f);\n";
5008                 }
5009             }
5010             else
5011             {
5012                 size_t inputComponentCount  = 0;
5013                 size_t outputComponentCount = 0;
5014 
5015                 for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getInputAttachments().size();
5016                      attachmentNdx++)
5017                 {
5018                     const uint32_t attachmentIndex  = subpass.getInputAttachments()[attachmentNdx].getAttachment();
5019                     const VkImageLayout layout      = subpass.getInputAttachments()[attachmentNdx].getImageLayout();
5020                     const Attachment attachment     = config.renderPass.getAttachments()[attachmentIndex];
5021                     const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
5022                     const size_t componentCount     = (size_t)getShaderNumChannels(format.order);
5023 
5024                     if (layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5025                         inputComponentCount += 1;
5026                     else if (layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
5027                         inputComponentCount += 1;
5028                     else
5029                         inputComponentCount += componentCount;
5030                 }
5031 
5032                 for (size_t attachmentNdx = config.drawStartNdx; attachmentNdx < subpass.getColorAttachments().size();
5033                      attachmentNdx++)
5034                 {
5035                     const uint32_t attachmentIndex  = subpass.getColorAttachments()[attachmentNdx].getAttachment();
5036                     const Attachment attachment     = config.renderPass.getAttachments()[attachmentIndex];
5037                     const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
5038                     const size_t componentCount     = (size_t)getShaderNumChannels(format.order);
5039 
5040                     outputComponentCount += componentCount;
5041                 }
5042 
5043                 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED &&
5044                     subpass.getDepthStencilAttachment().getImageLayout() !=
5045                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
5046                     subpass.getDepthStencilAttachment().getImageLayout() !=
5047                         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5048                 {
5049                     outputComponentCount++;
5050                 }
5051 
5052                 if (outputComponentCount > 0)
5053                 {
5054                     const size_t inputsPerOutput = inputComponentCount >= outputComponentCount ?
5055                                                        ((inputComponentCount / outputComponentCount) +
5056                                                         ((inputComponentCount % outputComponentCount) != 0 ? 1 : 0)) :
5057                                                        1;
5058 
5059                     fragmentShader << "\tbool inputs[" << inputComponentCount << "];\n";
5060 
5061                     if (outputComponentCount > 0)
5062                         fragmentShader << "\tbool outputs[" << outputComponentCount << "];\n";
5063 
5064                     size_t inputValueNdx = 0;
5065 
5066                     for (size_t attachmentNdx = config.drawStartNdx;
5067                          attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++)
5068                     {
5069                         const char *const components[]  = {"x", "y", "z", "w"};
5070                         const uint32_t attachmentIndex  = subpass.getInputAttachments()[attachmentNdx].getAttachment();
5071                         const VkImageLayout layout      = subpass.getInputAttachments()[attachmentNdx].getImageLayout();
5072                         const Attachment attachment     = config.renderPass.getAttachments()[attachmentIndex];
5073                         const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
5074                         const size_t componentCount     = (size_t)getShaderNumChannels(format.order);
5075                         const bool isDepthFormat        = tcu::hasDepthComponent(format.order);
5076                         const bool isStencilFormat      = tcu::hasStencilComponent(format.order);
5077 
5078                         if (isDepthFormat || isStencilFormat)
5079                         {
5080                             if (isDepthFormat && layout != VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
5081                             {
5082                                 fragmentShader << "\tinputs[" << inputValueNdx << "] = depthsEqual("
5083                                                << uint32_t(config.depthValues[1])
5084                                                << ".0f/255.0f, float(subpassLoad(i_depth" << attachmentNdx << ").x), "
5085                                                << std::fixed << std::setprecision(12)
5086                                                << requiredDepthEpsilon(attachment.getFormat()) << ");\n";
5087                                 inputValueNdx++;
5088                             }
5089 
5090                             if (isStencilFormat && layout != VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5091                             {
5092                                 fragmentShader << "\tinputs[" << inputValueNdx << "] = 255u == subpassLoad(i_stencil"
5093                                                << attachmentNdx << ").x;\n";
5094                                 inputValueNdx++;
5095                             }
5096                         }
5097                         else
5098                         {
5099                             for (size_t compNdx = 0; compNdx < componentCount; compNdx++)
5100                             {
5101                                 fragmentShader << "\tinputs[" << inputValueNdx << "] = 1.0 == float(subpassLoad(i_color"
5102                                                << attachmentNdx << ")." << components[compNdx] << ");\n";
5103                                 inputValueNdx++;
5104                             }
5105                         }
5106                     }
5107 
5108                     size_t outputValueNdx = 0;
5109 
5110                     for (size_t attachmentNdx = config.drawStartNdx;
5111                          attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
5112                     {
5113                         const uint32_t attachmentIndex   = subpass.getColorAttachments()[attachmentNdx].getAttachment();
5114                         const Attachment attachment      = config.renderPass.getAttachments()[attachmentIndex];
5115                         const std::string attachmentType = getAttachmentType(
5116                             config.renderPass.getAttachments()[attachmentIndex].getFormat(), config.useFormatCompCount);
5117                         const tcu::TextureFormat format = mapVkFormat(attachment.getFormat());
5118                         const size_t componentCount     = (size_t)getShaderNumChannels(format.order);
5119 
5120                         for (size_t compNdx = 0; compNdx < componentCount; compNdx++)
5121                         {
5122                             const size_t index = subpassNdx + attachmentIndex + outputValueNdx;
5123                             const BoolOp op    = boolOpFromIndex(index);
5124 
5125                             fragmentShader << "\toutputs[" << outputValueNdx + compNdx << "] = "
5126                                            << "(int(gl_FragCoord.x) % 2 == " << (index % 2) << ") "
5127                                            << boolOpToString(op) << " ("
5128                                            << "int(gl_FragCoord.y) % 2 == " << ((index / 2) % 2) << ");\n";
5129 
5130                             for (size_t i = 0; i < inputsPerOutput; i++)
5131                                 fragmentShader
5132                                     << "\toutputs[" << outputValueNdx + compNdx << "] = outputs["
5133                                     << outputValueNdx + compNdx << "] == inputs["
5134                                     << ((outputValueNdx + compNdx) * inputsPerOutput + i) % inputComponentCount
5135                                     << "];\n";
5136                         }
5137 
5138                         fragmentShader << "\to_color" << attachmentNdx << " = " << attachmentType << "(";
5139 
5140                         for (size_t compNdx = 0; compNdx < (config.useFormatCompCount ? componentCount : 4); compNdx++)
5141                         {
5142                             if (compNdx > 0)
5143                                 fragmentShader << ", ";
5144 
5145                             if (compNdx < componentCount)
5146                                 fragmentShader << "outputs[" << outputValueNdx + compNdx << "]";
5147                             else
5148                                 fragmentShader << "0";
5149                         }
5150 
5151                         outputValueNdx += componentCount;
5152 
5153                         fragmentShader << ");\n";
5154                     }
5155 
5156                     if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED &&
5157                         subpass.getDepthStencilAttachment().getImageLayout() !=
5158                             VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL &&
5159                         subpass.getDepthStencilAttachment().getImageLayout() !=
5160                             VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5161                     {
5162                         const uint32_t attachmentIndex = subpass.getDepthStencilAttachment().getAttachment();
5163                         const size_t index             = subpassNdx + attachmentIndex;
5164                         const BoolOp op                = boolOpFromIndex(index);
5165 
5166                         fragmentShader << "\toutputs[" << outputValueNdx << "] = "
5167                                        << "(int(gl_FragCoord.x) % 2 == " << (index % 2) << ") " << boolOpToString(op)
5168                                        << " ("
5169                                        << "int(gl_FragCoord.y) % 2 == " << ((index / 2) % 2) << ");\n";
5170 
5171                         for (size_t i = 0; i < inputsPerOutput; i++)
5172                             fragmentShader << "\toutputs[" << outputValueNdx << "] = outputs[" << outputValueNdx
5173                                            << "] == inputs["
5174                                            << (outputValueNdx * inputsPerOutput + i) % inputComponentCount << "];\n";
5175 
5176                         fragmentShader << "\tgl_FragDepth = outputs[" << outputValueNdx << "] ? "
5177                                        << uint32_t(config.depthValues[1])
5178                                        << ".0f/255.0f : " << uint32_t(config.depthValues[0]) << ".0f/255.0f;\n";
5179                     }
5180                 }
5181             }
5182 
5183             fragmentShader << "}\n";
5184 
5185             dst.glslSources.add(de::toString(subpassNdx) + "-vert") << glu::VertexSource(vertexShader.str());
5186             dst.glslSources.add(de::toString(subpassNdx) + "-frag") << glu::FragmentSource(fragmentShader.str());
5187         }
5188     }
5189 }
5190 
initializeAttachmentIsLazy(vector<bool> & attachmentIsLazy,const vector<Attachment> & attachments,TestConfig::ImageMemory imageMemory)5191 void initializeAttachmentIsLazy(vector<bool> &attachmentIsLazy, const vector<Attachment> &attachments,
5192                                 TestConfig::ImageMemory imageMemory)
5193 {
5194     bool lastAttachmentWasLazy = false;
5195 
5196     for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
5197     {
5198         if (attachments[attachmentNdx].getLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD &&
5199             attachments[attachmentNdx].getStoreOp() != VK_ATTACHMENT_STORE_OP_STORE &&
5200             attachments[attachmentNdx].getStencilLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD &&
5201             attachments[attachmentNdx].getStencilStoreOp() != VK_ATTACHMENT_STORE_OP_STORE)
5202         {
5203             if (imageMemory == TestConfig::IMAGEMEMORY_LAZY ||
5204                 (imageMemory & TestConfig::IMAGEMEMORY_LAZY && !lastAttachmentWasLazy))
5205             {
5206                 attachmentIsLazy.push_back(true);
5207 
5208                 lastAttachmentWasLazy = true;
5209             }
5210             else if (imageMemory & TestConfig::IMAGEMEMORY_STRICT)
5211             {
5212                 attachmentIsLazy.push_back(false);
5213                 lastAttachmentWasLazy = false;
5214             }
5215             else
5216                 DE_FATAL("Unknown imageMemory");
5217         }
5218         else
5219             attachmentIsLazy.push_back(false);
5220     }
5221 }
5222 
5223 enum AttachmentRefType
5224 {
5225     ATTACHMENTREFTYPE_COLOR,
5226     ATTACHMENTREFTYPE_DEPTH_STENCIL,
5227     ATTACHMENTREFTYPE_INPUT,
5228     ATTACHMENTREFTYPE_RESOLVE,
5229 };
5230 
getImageUsageFromLayout(VkImageLayout layout)5231 VkImageUsageFlags getImageUsageFromLayout(VkImageLayout layout)
5232 {
5233     switch (layout)
5234     {
5235     case VK_IMAGE_LAYOUT_GENERAL:
5236     case VK_IMAGE_LAYOUT_PREINITIALIZED:
5237         return 0;
5238 
5239     case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
5240         return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
5241 
5242     case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
5243     case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
5244         return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
5245 
5246     case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
5247         return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
5248 
5249     case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
5250         return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
5251 
5252     case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
5253         return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
5254 
5255     default:
5256         DE_FATAL("Unexpected image layout");
5257         return 0;
5258     }
5259 }
5260 
getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags> & attachmentImageUsage,AttachmentRefType refType,size_t count,const AttachmentReference * references)5261 void getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags> &attachmentImageUsage, AttachmentRefType refType,
5262                                            size_t count, const AttachmentReference *references)
5263 {
5264     for (size_t referenceNdx = 0; referenceNdx < count; ++referenceNdx)
5265     {
5266         const uint32_t attachment = references[referenceNdx].getAttachment();
5267 
5268         if (attachment != VK_ATTACHMENT_UNUSED)
5269         {
5270             VkImageUsageFlags usage;
5271 
5272             switch (refType)
5273             {
5274             case ATTACHMENTREFTYPE_COLOR:
5275             case ATTACHMENTREFTYPE_RESOLVE:
5276                 usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
5277                 break;
5278 
5279             case ATTACHMENTREFTYPE_DEPTH_STENCIL:
5280                 usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
5281                 break;
5282 
5283             case ATTACHMENTREFTYPE_INPUT:
5284                 usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
5285                 break;
5286 
5287             default:
5288                 DE_FATAL("Unexpected attachment reference type");
5289                 usage = 0;
5290                 break;
5291             }
5292 
5293             attachmentImageUsage[attachment] |= usage;
5294         }
5295     }
5296 }
5297 
getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags> & attachmentImageUsage,AttachmentRefType refType,const vector<AttachmentReference> & references)5298 void getImageUsageFromAttachmentReferences(vector<VkImageUsageFlags> &attachmentImageUsage, AttachmentRefType refType,
5299                                            const vector<AttachmentReference> &references)
5300 {
5301     if (!references.empty())
5302     {
5303         getImageUsageFromAttachmentReferences(attachmentImageUsage, refType, references.size(), &references[0]);
5304     }
5305 }
5306 
initializeAttachmentImageUsage(Context & context,vector<VkImageUsageFlags> & attachmentImageUsage,const RenderPass & renderPassInfo,const vector<bool> & attachmentIsLazy,const vector<Maybe<VkClearValue>> & clearValues)5307 void initializeAttachmentImageUsage(Context &context, vector<VkImageUsageFlags> &attachmentImageUsage,
5308                                     const RenderPass &renderPassInfo, const vector<bool> &attachmentIsLazy,
5309                                     const vector<Maybe<VkClearValue>> &clearValues)
5310 {
5311     attachmentImageUsage.resize(renderPassInfo.getAttachments().size(), VkImageUsageFlags(0));
5312 
5313     for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); ++subpassNdx)
5314     {
5315         const Subpass &subpass = renderPassInfo.getSubpasses()[subpassNdx];
5316 
5317         getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_COLOR,
5318                                               subpass.getColorAttachments());
5319         getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_DEPTH_STENCIL, 1,
5320                                               &subpass.getDepthStencilAttachment());
5321         getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_INPUT,
5322                                               subpass.getInputAttachments());
5323         getImageUsageFromAttachmentReferences(attachmentImageUsage, ATTACHMENTREFTYPE_RESOLVE,
5324                                               subpass.getResolveAttachments());
5325     }
5326 
5327     for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
5328     {
5329         const Attachment &attachment              = renderPassInfo.getAttachments()[attachmentNdx];
5330         const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(
5331             context.getInstanceInterface(), context.getPhysicalDevice(), attachment.getFormat());
5332         const VkFormatFeatureFlags supportedFeatures = formatProperties.optimalTilingFeatures;
5333 
5334         if ((supportedFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0)
5335             attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_SAMPLED_BIT;
5336 
5337         if ((supportedFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0)
5338             attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_STORAGE_BIT;
5339 
5340         attachmentImageUsage[attachmentNdx] |= getImageUsageFromLayout(attachment.getInitialLayout());
5341         attachmentImageUsage[attachmentNdx] |= getImageUsageFromLayout(attachment.getFinalLayout());
5342 
5343         if (!attachmentIsLazy[attachmentNdx])
5344         {
5345             if (clearValues[attachmentNdx])
5346                 attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
5347 
5348             attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
5349         }
5350         else
5351         {
5352             const VkImageUsageFlags allowedTransientBits = static_cast<VkImageUsageFlags>(
5353                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
5354                 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
5355 
5356             attachmentImageUsage[attachmentNdx] &= allowedTransientBits;
5357             attachmentImageUsage[attachmentNdx] |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
5358         }
5359     }
5360 }
5361 
initializeSubpassIsSecondary(vector<bool> & subpassIsSecondary,const vector<Subpass> & subpasses,TestConfig::CommandBufferTypes commandBuffer)5362 void initializeSubpassIsSecondary(vector<bool> &subpassIsSecondary, const vector<Subpass> &subpasses,
5363                                   TestConfig::CommandBufferTypes commandBuffer)
5364 {
5365     bool lastSubpassWasSecondary = false;
5366 
5367     for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
5368     {
5369         if (commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY ||
5370             (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary))
5371         {
5372             subpassIsSecondary.push_back(true);
5373             lastSubpassWasSecondary = true;
5374         }
5375         else if (commandBuffer & TestConfig::COMMANDBUFFERTYPES_INLINE)
5376         {
5377             subpassIsSecondary.push_back(false);
5378             lastSubpassWasSecondary = false;
5379         }
5380         else
5381             DE_FATAL("Unknown commandBuffer");
5382     }
5383 }
5384 
initializeImageClearValues(de::Random & rng,vector<Maybe<VkClearValue>> & clearValues,const vector<Attachment> & attachments,const vector<bool> & isLazy,bool useFormatCompCount,const DepthValuesArray & depthValues)5385 void initializeImageClearValues(de::Random &rng, vector<Maybe<VkClearValue>> &clearValues,
5386                                 const vector<Attachment> &attachments, const vector<bool> &isLazy,
5387                                 bool useFormatCompCount, const DepthValuesArray &depthValues)
5388 {
5389     for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
5390     {
5391         if (!isLazy[attachmentNdx])
5392             clearValues.push_back(
5393                 just(randomClearValue(attachments[attachmentNdx], rng, useFormatCompCount, depthValues)));
5394         else
5395             clearValues.push_back(tcu::Nothing);
5396     }
5397 }
5398 
initializeRenderPassClearValues(de::Random & rng,vector<Maybe<VkClearValue>> & clearValues,const vector<Attachment> & attachments,bool useFormatCompCount,const DepthValuesArray & depthValues)5399 void initializeRenderPassClearValues(de::Random &rng, vector<Maybe<VkClearValue>> &clearValues,
5400                                      const vector<Attachment> &attachments, bool useFormatCompCount,
5401                                      const DepthValuesArray &depthValues)
5402 {
5403     for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
5404     {
5405         if (attachments[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR ||
5406             attachments[attachmentNdx].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
5407         {
5408             clearValues.push_back(
5409                 just(randomClearValue(attachments[attachmentNdx], rng, useFormatCompCount, depthValues)));
5410         }
5411         else
5412             clearValues.push_back(tcu::Nothing);
5413     }
5414 }
5415 
logSubpassRenderInfo(TestLog & log,const SubpassRenderInfo & info,TestConfig config)5416 void logSubpassRenderInfo(TestLog &log, const SubpassRenderInfo &info, TestConfig config)
5417 {
5418     log << TestLog::Message << "Viewport, offset: " << info.getViewportOffset() << ", size: " << info.getViewportSize()
5419         << TestLog::EndMessage;
5420 
5421     if (info.isSecondary())
5422         log << TestLog::Message << "Subpass uses secondary command buffers" << TestLog::EndMessage;
5423     else
5424         log << TestLog::Message << "Subpass uses inlined commands" << TestLog::EndMessage;
5425 
5426     for (uint32_t attachmentNdx = 0; attachmentNdx < info.getColorClears().size(); attachmentNdx++)
5427     {
5428         const ColorClear &colorClear = info.getColorClears()[attachmentNdx];
5429 
5430         log << TestLog::Message << "Clearing color attachment " << attachmentNdx
5431             << ". Offset: " << colorClear.getOffset() << ", Size: " << colorClear.getSize() << ", Color: "
5432             << clearColorToString(info.getColorAttachment(attachmentNdx).getFormat(), colorClear.getColor(),
5433                                   config.useFormatCompCount)
5434             << TestLog::EndMessage;
5435     }
5436 
5437     if (info.getDepthStencilClear())
5438     {
5439         const DepthStencilClear &depthStencilClear = *info.getDepthStencilClear();
5440 
5441         log << TestLog::Message << "Clearing depth stencil attachment"
5442             << ". Offset: " << depthStencilClear.getOffset() << ", Size: " << depthStencilClear.getSize()
5443             << ", Depth: " << depthStencilClear.getDepth() << ", Stencil: " << depthStencilClear.getStencil()
5444             << TestLog::EndMessage;
5445     }
5446 
5447     if (info.getRenderQuad())
5448     {
5449         const RenderQuad &renderQuad = *info.getRenderQuad();
5450 
5451         log << TestLog::Message << "Rendering grid quad to " << renderQuad.getCornerA() << " -> "
5452             << renderQuad.getCornerB() << TestLog::EndMessage;
5453     }
5454 }
5455 
logTestCaseInfo(TestLog & log,const TestConfig & config,const vector<bool> & attachmentIsLazy,const vector<Maybe<VkClearValue>> & imageClearValues,const vector<Maybe<VkClearValue>> & renderPassClearValues,const vector<SubpassRenderInfo> & subpassRenderInfo)5456 void logTestCaseInfo(TestLog &log, const TestConfig &config, const vector<bool> &attachmentIsLazy,
5457                      const vector<Maybe<VkClearValue>> &imageClearValues,
5458                      const vector<Maybe<VkClearValue>> &renderPassClearValues,
5459                      const vector<SubpassRenderInfo> &subpassRenderInfo)
5460 {
5461     const RenderPass &renderPass = config.renderPass;
5462 
5463     logRenderPassInfo(log, renderPass);
5464 
5465     DE_ASSERT(attachmentIsLazy.size() == renderPass.getAttachments().size());
5466     DE_ASSERT(imageClearValues.size() == renderPass.getAttachments().size());
5467     DE_ASSERT(renderPassClearValues.size() == renderPass.getAttachments().size());
5468 
5469     log << TestLog::Message << "TargetSize: " << config.targetSize << TestLog::EndMessage;
5470     log << TestLog::Message << "Render area, Offset: " << config.renderPos << ", Size: " << config.renderSize
5471         << TestLog::EndMessage;
5472 
5473     for (size_t attachmentNdx = 0; attachmentNdx < attachmentIsLazy.size(); attachmentNdx++)
5474     {
5475         const tcu::ScopedLogSection section(log, "Attachment" + de::toString(attachmentNdx),
5476                                             "Attachment " + de::toString(attachmentNdx));
5477 
5478         if (attachmentIsLazy[attachmentNdx])
5479             log << TestLog::Message << "Is lazy." << TestLog::EndMessage;
5480 
5481         if (imageClearValues[attachmentNdx])
5482             log << TestLog::Message << "Image is cleared to "
5483                 << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(),
5484                                       *imageClearValues[attachmentNdx], config.useFormatCompCount)
5485                 << " before rendering." << TestLog::EndMessage;
5486 
5487         if (renderPass.getAttachments()[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR &&
5488             renderPassClearValues[attachmentNdx])
5489             log << TestLog::Message << "Attachment is cleared to "
5490                 << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(),
5491                                       *renderPassClearValues[attachmentNdx], config.useFormatCompCount)
5492                 << " in the beginning of the render pass." << TestLog::EndMessage;
5493     }
5494 
5495     for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
5496     {
5497         const tcu::ScopedLogSection section(log, "Subpass" + de::toString(subpassNdx),
5498                                             "Subpass " + de::toString(subpassNdx));
5499 
5500         logSubpassRenderInfo(log, subpassRenderInfo[subpassNdx], config);
5501     }
5502 }
5503 
roundToViewport(float x,uint32_t offset,uint32_t size)5504 float roundToViewport(float x, uint32_t offset, uint32_t size)
5505 {
5506     const float origin = (float)(offset) + ((float(size) / 2.0f));
5507     const float p      = (float)(size) / 2.0f;
5508     const int32_t xi   = deRoundFloatToInt32(origin + (p * x));
5509 
5510     return (((float)xi) - origin) / p;
5511 }
5512 
initializeSubpassRenderInfo(vector<SubpassRenderInfo> & renderInfos,de::Random & rng,const RenderPass & renderPass,const TestConfig & config)5513 void initializeSubpassRenderInfo(vector<SubpassRenderInfo> &renderInfos, de::Random &rng, const RenderPass &renderPass,
5514                                  const TestConfig &config)
5515 {
5516     const TestConfig::CommandBufferTypes commandBuffer = config.commandBufferTypes;
5517     const vector<Subpass> &subpasses                   = renderPass.getSubpasses();
5518     bool lastSubpassWasSecondary                       = false;
5519 
5520     // mixing using secondary command buffers and recording draw calls inline
5521     // is legal with renderpasses (as the render pass contents was set per subpass),
5522     // but for dynamic rendering the contents flag is set on the whole dynamic render
5523     const bool isMultiPassDynamicRendering =
5524         (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) && (subpasses.size() > 1u);
5525     const bool alternateSecondaryCmdBuff =
5526         (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY) && !isMultiPassDynamicRendering;
5527 
5528     for (uint32_t subpassNdx = 0; subpassNdx < (uint32_t)subpasses.size(); subpassNdx++)
5529     {
5530         const Subpass &subpass        = subpasses[subpassNdx];
5531         const bool subpassIsSecondary = commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY ||
5532                                                 (alternateSecondaryCmdBuff && !lastSubpassWasSecondary) ?
5533                                             true :
5534                                             false;
5535         const bool omitBlendState     = subpass.getOmitBlendState();
5536         const UVec2 viewportSize((config.renderSize * UVec2(2)) / UVec2(3));
5537         const UVec2 viewportOffset(config.renderPos.x() + (subpassNdx % 2) * (config.renderSize.x() / 3),
5538                                    config.renderPos.y() + ((subpassNdx / 2) % 2) * (config.renderSize.y() / 3));
5539 
5540         vector<ColorClear> colorClears;
5541         Maybe<DepthStencilClear> depthStencilClear;
5542         Maybe<RenderQuad> renderQuad;
5543 
5544         lastSubpassWasSecondary = subpassIsSecondary;
5545 
5546         if (config.renderTypes & TestConfig::RENDERTYPES_CLEAR)
5547         {
5548             const vector<AttachmentReference> &colorAttachments = subpass.getColorAttachments();
5549 
5550             for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
5551             {
5552                 const AttachmentReference &attachmentRef = colorAttachments[attachmentRefNdx];
5553                 const Attachment &attachment             = renderPass.getAttachments()[attachmentRef.getAttachment()];
5554                 const UVec2 size((viewportSize * UVec2(2)) / UVec2(3));
5555                 const UVec2 offset(viewportOffset.x() + ((uint32_t)attachmentRefNdx % 2u) * (viewportSize.x() / 3u),
5556                                    viewportOffset.y() +
5557                                        (((uint32_t)attachmentRefNdx / 2u) % 2u) * (viewportSize.y() / 3u));
5558                 const VkClearColorValue color = randomColorClearValue(attachment, rng, config.useFormatCompCount);
5559 
5560                 colorClears.push_back(ColorClear(offset, size, color));
5561             }
5562 
5563             if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
5564             {
5565                 const Attachment &attachment =
5566                     renderPass.getAttachments()[subpass.getDepthStencilAttachment().getAttachment()];
5567                 const UVec2 size((viewportSize * UVec2(2)) / UVec2(3));
5568                 const UVec2 offset(
5569                     viewportOffset.x() + ((uint32_t)colorAttachments.size() % 2u) * (viewportSize.x() / 3u),
5570                     viewportOffset.y() + (((uint32_t)colorAttachments.size() / 2u) % 2u) * (viewportSize.y() / 3u));
5571                 const VkClearValue value =
5572                     randomClearValue(attachment, rng, config.useFormatCompCount, config.depthValues);
5573 
5574                 depthStencilClear =
5575                     tcu::just(DepthStencilClear(offset, size, value.depthStencil.depth, value.depthStencil.stencil));
5576             }
5577         }
5578 
5579         if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
5580         {
5581             const float w = (subpassNdx % 2) == 0 ? 1.0f : 1.25f;
5582             const float h = (subpassNdx % 2) == 0 ? 1.25f : 1.0f;
5583 
5584             const float x0 =
5585                 roundToViewport((subpassNdx % 2) == 0 ? 1.0f - w : -1.0f, viewportOffset.x(), viewportSize.x());
5586             const float x1 =
5587                 roundToViewport((subpassNdx % 2) == 0 ? 1.0f : -1.0f + w, viewportOffset.x(), viewportSize.x());
5588 
5589             const float y0 =
5590                 roundToViewport(((subpassNdx / 2) % 2) == 0 ? 1.0f - h : -1.0f, viewportOffset.y(), viewportSize.y());
5591             const float y1 =
5592                 roundToViewport(((subpassNdx / 2) % 2) == 0 ? 1.0f : -1.0f + h, viewportOffset.y(), viewportSize.y());
5593 
5594             renderQuad = tcu::just(RenderQuad(tcu::Vec2(x0, y0), tcu::Vec2(x1, y1)));
5595         }
5596 
5597         renderInfos.push_back(SubpassRenderInfo(renderPass, subpassNdx, config.drawStartNdx, subpassIsSecondary,
5598                                                 omitBlendState, viewportOffset, viewportSize, renderQuad, colorClears,
5599                                                 depthStencilClear));
5600     }
5601 }
5602 
checkTextureFormatSupport(TestLog & log,const InstanceInterface & vk,VkPhysicalDevice device,const vector<Attachment> & attachments)5603 void checkTextureFormatSupport(TestLog &log, const InstanceInterface &vk, VkPhysicalDevice device,
5604                                const vector<Attachment> &attachments)
5605 {
5606     bool supported = true;
5607 
5608     for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
5609     {
5610         const Attachment &attachment          = attachments[attachmentNdx];
5611         const tcu::TextureFormat format       = mapVkFormat(attachment.getFormat());
5612         const bool isDepthOrStencilAttachment = hasDepthComponent(format.order) || hasStencilComponent(format.order);
5613         const VkFormatFeatureFlags flags = isDepthOrStencilAttachment ? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT :
5614                                                                         VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
5615         VkFormatProperties properties;
5616 
5617         vk.getPhysicalDeviceFormatProperties(device, attachment.getFormat(), &properties);
5618 
5619         if ((properties.optimalTilingFeatures & flags) != flags)
5620         {
5621             supported = false;
5622             log << TestLog::Message << "Format: " << attachment.getFormat() << " not supported as "
5623                 << (isDepthOrStencilAttachment ? "depth stencil attachment" : "color attachment")
5624                 << TestLog::EndMessage;
5625         }
5626     }
5627 
5628     if (!supported)
5629         TCU_THROW(NotSupportedError, "Format not supported");
5630 }
5631 
renderPassTest(Context & context,TestConfig config)5632 tcu::TestStatus renderPassTest(Context &context, TestConfig config)
5633 {
5634     const UVec2 targetSize             = config.targetSize;
5635     const UVec2 renderPos              = config.renderPos;
5636     const UVec2 renderSize             = config.renderSize;
5637     const RenderPass &renderPassInfo   = config.renderPass;
5638     const InstanceInterface &vki       = context.getInstanceInterface();
5639     const VkPhysicalDevice &physDevice = context.getPhysicalDevice();
5640     const auto &properties             = getPhysicalDeviceProperties(vki, physDevice);
5641 
5642     TestLog &log = context.getTestContext().getLog();
5643     de::Random rng(config.seed);
5644 
5645     vector<bool> attachmentIsLazy;
5646     vector<VkImageUsageFlags> attachmentImageUsage;
5647     vector<Maybe<VkClearValue>> imageClearValues;
5648     vector<Maybe<VkClearValue>> renderPassClearValues;
5649 
5650     vector<bool> subpassIsSecondary;
5651     vector<SubpassRenderInfo> subpassRenderInfo;
5652 
5653 #ifndef CTS_USES_VULKANSC
5654     for (const auto &att : renderPassInfo.getAttachments())
5655     {
5656         if (att.getFormat() == VK_FORMAT_A8_UNORM_KHR)
5657         {
5658             context.requireDeviceFunctionality("VK_KHR_maintenance5");
5659             break;
5660         }
5661     }
5662 #endif // CTS_USES_VULKANSC
5663 
5664     if (config.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
5665         context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
5666 
5667     if (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
5668     {
5669         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
5670 
5671         // check if thare are multiple subpasses
5672         if (renderPassInfo.getSubpasses().size() > 1u)
5673         {
5674             context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
5675 
5676             std::vector<uint32_t> colorAttachmentIndices;
5677             std::vector<VkFormat> colorAttachmentFormats;
5678             findColorAttachments(renderPassInfo, colorAttachmentIndices, colorAttachmentFormats);
5679             if (colorAttachmentIndices.size() > (size_t)properties.limits.maxColorAttachments)
5680                 TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
5681         }
5682     }
5683 
5684     if (config.allocationKind == ALLOCATION_KIND_DEDICATED)
5685     {
5686         if (!context.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation"))
5687             TCU_THROW(NotSupportedError, "VK_KHR_dedicated_allocation is not supported");
5688     }
5689 
5690     if (!renderPassInfo.getInputAspects().empty())
5691     {
5692         if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance2"))
5693             TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance2 not supported.");
5694     }
5695 
5696     checkPipelineConstructionRequirements(vki, physDevice, config.groupParams->pipelineConstructionType);
5697 
5698     {
5699         bool requireDepthStencilLayout = false;
5700 
5701         for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
5702         {
5703             if (renderPassInfo.getAttachments()[attachmentNdx].getInitialLayout() ==
5704                     VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
5705                 renderPassInfo.getAttachments()[attachmentNdx].getInitialLayout() ==
5706                     VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL ||
5707                 renderPassInfo.getAttachments()[attachmentNdx].getFinalLayout() ==
5708                     VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
5709                 renderPassInfo.getAttachments()[attachmentNdx].getFinalLayout() ==
5710                     VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5711             {
5712                 requireDepthStencilLayout = true;
5713                 break;
5714             }
5715         }
5716 
5717         for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size() && !requireDepthStencilLayout;
5718              subpassNdx++)
5719         {
5720             const Subpass &subpass(renderPassInfo.getSubpasses()[subpassNdx]);
5721 
5722             for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
5723             {
5724                 if (subpass.getColorAttachments()[attachmentNdx].getImageLayout() ==
5725                         VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
5726                     subpass.getColorAttachments()[attachmentNdx].getImageLayout() ==
5727                         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5728                 {
5729                     requireDepthStencilLayout = true;
5730                     break;
5731                 }
5732             }
5733 
5734             for (size_t attachmentNdx = 0;
5735                  !requireDepthStencilLayout && attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++)
5736             {
5737                 if (subpass.getInputAttachments()[attachmentNdx].getImageLayout() ==
5738                         VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
5739                     subpass.getInputAttachments()[attachmentNdx].getImageLayout() ==
5740                         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5741                 {
5742                     requireDepthStencilLayout = true;
5743                     break;
5744                 }
5745             }
5746 
5747             for (size_t attachmentNdx = 0;
5748                  !requireDepthStencilLayout && attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++)
5749             {
5750                 if (subpass.getResolveAttachments()[attachmentNdx].getImageLayout() ==
5751                         VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
5752                     subpass.getResolveAttachments()[attachmentNdx].getImageLayout() ==
5753                         VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5754                 {
5755                     requireDepthStencilLayout = true;
5756                     break;
5757                 }
5758             }
5759 
5760             if (subpass.getDepthStencilAttachment().getImageLayout() ==
5761                     VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL ||
5762                 subpass.getDepthStencilAttachment().getImageLayout() ==
5763                     VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
5764             {
5765                 requireDepthStencilLayout = true;
5766                 break;
5767             }
5768         }
5769 
5770         if (requireDepthStencilLayout && !context.isDeviceFunctionalitySupported("VK_KHR_maintenance2"))
5771             TCU_THROW(NotSupportedError, "VK_KHR_maintenance2 is not supported");
5772     }
5773 
5774     initializeAttachmentIsLazy(attachmentIsLazy, renderPassInfo.getAttachments(), config.imageMemory);
5775     initializeImageClearValues(rng, imageClearValues, renderPassInfo.getAttachments(), attachmentIsLazy,
5776                                config.useFormatCompCount, config.depthValues);
5777     initializeAttachmentImageUsage(context, attachmentImageUsage, renderPassInfo, attachmentIsLazy, imageClearValues);
5778     initializeRenderPassClearValues(rng, renderPassClearValues, renderPassInfo.getAttachments(),
5779                                     config.useFormatCompCount, config.depthValues);
5780 
5781     initializeSubpassIsSecondary(subpassIsSecondary, renderPassInfo.getSubpasses(), config.commandBufferTypes);
5782     initializeSubpassRenderInfo(subpassRenderInfo, rng, renderPassInfo, config);
5783 
5784     logTestCaseInfo(log, config, attachmentIsLazy, imageClearValues, renderPassClearValues, subpassRenderInfo);
5785 
5786     checkTextureFormatSupport(log, vki, physDevice, config.renderPass.getAttachments());
5787 
5788     {
5789         log << TestLog::Message << "Max color attachments: " << properties.limits.maxColorAttachments
5790             << TestLog::EndMessage;
5791 
5792         for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
5793         {
5794             if (renderPassInfo.getSubpasses()[subpassNdx].getColorAttachments().size() >
5795                 (size_t)properties.limits.maxColorAttachments)
5796                 TCU_THROW(NotSupportedError, "Subpass uses more than maxColorAttachments.");
5797         }
5798     }
5799 
5800     {
5801         const VkDevice device     = context.getDevice();
5802         const DeviceInterface &vk = context.getDeviceInterface();
5803         const VkQueue queue       = context.getUniversalQueue();
5804         const uint32_t queueIndex = context.getUniversalQueueFamilyIndex();
5805         Allocator &allocator      = context.getDefaultAllocator();
5806 
5807         const Unique<VkCommandPool> commandBufferPool(createCommandPool(vk, device, 0, queueIndex));
5808         const Unique<VkCommandBuffer> initializeImagesCommandBuffer(
5809             allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
5810         const Unique<VkCommandBuffer> renderCommandBuffer(
5811             allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
5812         const Unique<VkCommandBuffer> readImagesToBuffersCommandBuffer(
5813             allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
5814 
5815         vector<de::SharedPtr<AttachmentResources>> attachmentResources;
5816         vector<de::SharedPtr<SubpassRenderer>> subpassRenderers;
5817         vector<VkImage> attachmentImages;
5818         vector<VkImageView> attachmentViews;
5819         vector<pair<VkImageView, VkImageView>> inputAttachmentViews;
5820 
5821         Move<VkRenderPass> renderPass;
5822         if (config.groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
5823             renderPass = createRenderPass(vk, device, renderPassInfo, config.groupParams->renderingType);
5824 
5825         for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
5826         {
5827             const Attachment &attachmentInfo = renderPassInfo.getAttachments()[attachmentNdx];
5828 
5829             attachmentResources.push_back(de::SharedPtr<AttachmentResources>(
5830                 new AttachmentResources(vki, physDevice, vk, device, allocator, queueIndex, targetSize, attachmentInfo,
5831                                         attachmentImageUsage[attachmentNdx], config.allocationKind)));
5832             attachmentViews.push_back(attachmentResources[attachmentNdx]->getAttachmentView());
5833             attachmentImages.push_back(attachmentResources[attachmentNdx]->getImage());
5834 
5835             inputAttachmentViews.push_back(attachmentResources[attachmentNdx]->getInputAttachmentViews());
5836         }
5837 
5838         beginCommandBuffer(vk, *initializeImagesCommandBuffer, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0,
5839                            (VkQueryPipelineStatisticFlags)0);
5840         pushImageInitializationCommands(vk, *initializeImagesCommandBuffer, renderPassInfo.getAttachments(),
5841                                         attachmentResources, queueIndex, imageClearValues);
5842         endCommandBuffer(vk, *initializeImagesCommandBuffer);
5843 
5844         {
5845             Move<VkFramebuffer> framebuffer;
5846             if (config.groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
5847                 framebuffer = createFramebuffer(vk, device, *renderPass, targetSize, attachmentViews);
5848 
5849             const VkRect2D renderArea{{(int32_t)renderPos.x(), (int32_t)renderPos.y()},
5850                                       {renderSize.x(), renderSize.y()}};
5851             const bool secondaryCmdBufferCompletelyContainsDynamicRenderpass =
5852                 (config.commandBufferTypes == TestConfig::COMMANDBUFFERTYPES_SECONDARY) &&
5853                 config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass;
5854 
5855             for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
5856             {
5857                 subpassRenderers.push_back(de::SharedPtr<SubpassRenderer>(new SubpassRenderer(
5858                     context, vk, device, allocator, renderPassInfo, attachmentResources, renderArea,
5859                     renderPassClearValues, *renderPass, *framebuffer, *commandBufferPool, queueIndex, attachmentImages,
5860                     inputAttachmentViews, subpassRenderInfo[subpassNdx], config)));
5861             }
5862 
5863             beginCommandBuffer(vk, *renderCommandBuffer, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0,
5864                                (VkQueryPipelineStatisticFlags)0);
5865             pushRenderPassCommands(vk, *renderCommandBuffer, *renderPass, renderPassInfo, attachmentResources,
5866                                    *framebuffer, subpassRenderers, renderArea, renderPassClearValues, queueIndex,
5867                                    config, secondaryCmdBufferCompletelyContainsDynamicRenderpass);
5868             endCommandBuffer(vk, *renderCommandBuffer);
5869 
5870             beginCommandBuffer(vk, *readImagesToBuffersCommandBuffer, DE_NULL, 0, DE_NULL, VK_FALSE,
5871                                (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
5872             pushReadImagesToBuffers(vk, *readImagesToBuffersCommandBuffer, queueIndex, attachmentResources,
5873                                     renderPassInfo.getAttachments(), attachmentIsLazy, targetSize);
5874             endCommandBuffer(vk, *readImagesToBuffersCommandBuffer);
5875             {
5876                 const VkCommandBuffer commandBuffers[] = {*initializeImagesCommandBuffer, *renderCommandBuffer,
5877                                                           *readImagesToBuffersCommandBuffer};
5878                 const Unique<VkFence> fence(createFence(vk, device, 0u));
5879 
5880                 queueSubmit(vk, queue, DE_LENGTH_OF_ARRAY(commandBuffers), commandBuffers, *fence);
5881                 waitForFences(vk, device, 1, &fence.get(), VK_TRUE, ~0ull);
5882             }
5883         }
5884 #ifdef CTS_USES_VULKANSC
5885         if (!context.getTestContext().getCommandLine().isSubProcess())
5886             return tcu::TestStatus::pass("Pass");
5887 #endif
5888         if (logAndVerifyImages(log, vk, device, attachmentResources, attachmentIsLazy, renderPassInfo,
5889                                renderPassClearValues, imageClearValues, subpassRenderInfo, targetSize, config))
5890             return tcu::TestStatus::pass("Pass");
5891         else
5892             return tcu::TestStatus::fail("Result verification failed");
5893     }
5894 }
5895 
5896 class RenderPassNoDrawLoadStoreTestCase : public vkt::TestCase
5897 {
5898 public:
5899     RenderPassNoDrawLoadStoreTestCase(tcu::TestContext &context, const std::string &name,
5900                                       const SharedGroupParams groupParams);
5901     TestInstance *createInstance(Context &context) const override;
5902     void checkSupport(Context &context) const override;
5903 
5904 private:
5905     const SharedGroupParams m_groupParams;
5906 };
5907 
5908 class RenderPassNoDrawLoadStoreTestInstance : public vkt::TestInstance
5909 {
5910 public:
5911     RenderPassNoDrawLoadStoreTestInstance(Context &context, const SharedGroupParams groupParams);
5912 
5913     template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
5914               typename RenderPassCreateInfo>
5915     Move<VkRenderPass> createRenderPass(const DeviceInterface &vk, VkDevice vkDevice, RenderingType type);
5916     virtual tcu::TestStatus iterate(void);
5917 
5918 private:
5919     const SharedGroupParams m_groupParams;
5920 };
5921 
RenderPassNoDrawLoadStoreTestCase(tcu::TestContext & context,const std::string & name,const SharedGroupParams groupParams)5922 RenderPassNoDrawLoadStoreTestCase::RenderPassNoDrawLoadStoreTestCase(tcu::TestContext &context, const std::string &name,
5923                                                                      const SharedGroupParams groupParams)
5924     : vkt::TestCase(context, name)
5925     , m_groupParams(groupParams)
5926 {
5927 }
5928 
RenderPassNoDrawLoadStoreTestInstance(Context & context,const SharedGroupParams groupParams)5929 RenderPassNoDrawLoadStoreTestInstance::RenderPassNoDrawLoadStoreTestInstance(Context &context,
5930                                                                              const SharedGroupParams groupParams)
5931     : vkt::TestInstance(context)
5932     , m_groupParams(groupParams)
5933 {
5934 }
5935 
createInstance(Context & context) const5936 TestInstance *RenderPassNoDrawLoadStoreTestCase::createInstance(Context &context) const
5937 {
5938     return new RenderPassNoDrawLoadStoreTestInstance(context, m_groupParams);
5939 }
5940 
checkSupport(Context & context) const5941 void RenderPassNoDrawLoadStoreTestCase::checkSupport(Context &context) const
5942 {
5943     if (m_groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
5944         context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
5945 
5946     if (m_groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
5947         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
5948 }
5949 
5950 template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
5951           typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice,RenderingType type)5952 Move<VkRenderPass> RenderPassNoDrawLoadStoreTestInstance::createRenderPass(const DeviceInterface &vk, VkDevice vkDevice,
5953                                                                            RenderingType type)
5954 {
5955     const VkImageAspectFlags aspectMask = type == RENDERING_TYPE_RENDERPASS_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
5956 
5957     const AttachmentDesc attachmentDescription =
5958         // Result attachment
5959         AttachmentDesc(nullptr,                                 // const void*                        pNext
5960                        (VkAttachmentDescriptionFlags)0,         // VkAttachmentDescriptionFlags        flags
5961                        VK_FORMAT_R8G8B8A8_UNORM,                // VkFormat                            format
5962                        VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits            samples
5963                        VK_ATTACHMENT_LOAD_OP_CLEAR,             // VkAttachmentLoadOp                loadOp
5964                        VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp                storeOp
5965                        VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp                stencilLoadOp
5966                        VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp                stencilStoreOp
5967                        VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout                    initialLayout
5968                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout                    finalLayout
5969         );
5970 
5971     const AttachmentRef resultAttachmentRefSubpass0(
5972         nullptr,                                  // const void*            pNext
5973         0u,                                       // uint32_t                attachment
5974         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
5975         aspectMask                                // VkImageAspectFlags    aspectMask
5976     );
5977 
5978     const SubpassDesc subpassDescription =
5979         SubpassDesc(nullptr,
5980                     (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags        flags
5981                     VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint                pipelineBindPoint
5982                     0u,                              // uint32_t                            viewMask
5983                     0u,                              // uint32_t                            inputAttachmentCount
5984                     nullptr,                         // const VkAttachmentReference*        pInputAttachments
5985                     1u,                              // uint32_t                            colorAttachmentCount
5986                     &resultAttachmentRefSubpass0,    // const VkAttachmentReference*        pColorAttachments
5987                     nullptr,                         // const VkAttachmentReference*        pResolveAttachments
5988                     nullptr,                         // const VkAttachmentReference*        pDepthStencilAttachment
5989                     0u,                              // uint32_t                            preserveAttachmentCount
5990                     nullptr                          // const uint32_t*                    pPreserveAttachments
5991         );
5992 
5993     const RenderPassCreateInfo renderPassInfo(nullptr,                    // const void*                        pNext
5994                                               (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags            flags
5995                                               1u, // uint32_t                            attachmentCount
5996                                               &attachmentDescription, // const VkAttachmentDescription*    pAttachments
5997                                               1u,                  // uint32_t                            subpassCount
5998                                               &subpassDescription, // const VkSubpassDescription*        pSubpasses
5999                                               0u,      // uint32_t                            dependencyCount
6000                                               nullptr, // const VkSubpassDependency*        pDependencies
6001                                               0u,      // uint32_t                            correlatedViewMaskCount
6002                                               nullptr  // const uint32_t*                    pCorrelatedViewMasks
6003     );
6004     return renderPassInfo.createRenderPass(vk, vkDevice);
6005 }
6006 
iterate()6007 tcu::TestStatus RenderPassNoDrawLoadStoreTestInstance::iterate()
6008 {
6009     const auto &vkd   = m_context.getDeviceInterface();
6010     const auto device = m_context.getDevice();
6011     auto &alloc       = m_context.getDefaultAllocator();
6012 
6013     auto imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
6014     auto imageExtent = makeExtent3D(1, 1, 1u);
6015 
6016     const tcu::IVec3 imageDim(static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height),
6017                               static_cast<int>(imageExtent.depth));
6018     const tcu::IVec2 imageSize(imageDim.x(), imageDim.y());
6019 
6020     const std::vector<VkViewport> viewports{makeViewport(imageExtent)};
6021     const std::vector<VkRect2D> scissors{makeRect2D(imageExtent)};
6022 
6023     de::MovePtr<ImageWithMemory> colorAttachment;
6024 
6025     const auto qIndex = m_context.getUniversalQueueFamilyIndex();
6026 
6027     const auto subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
6028     const auto imageUsage =
6029         static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
6030     const VkImageCreateInfo imageCreateInfo = {
6031         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
6032         nullptr,                             // const void* pNext;
6033         0u,                                  // VkImageCreateFlags flags;
6034         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
6035         imageFormat,                         // VkFormat format;
6036         imageExtent,                         // VkExtent3D extent;
6037         1u,                                  // uint32_t mipLevels;
6038         1u,                                  // uint32_t arrayLayers;
6039         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
6040         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
6041         imageUsage,                          // VkImageUsageFlags usage;
6042         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
6043         0u,                                  // uint32_t queueFamilyIndexCount;
6044         nullptr,                             // const uint32_t* pQueueFamilyIndices;
6045         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
6046     };
6047 
6048     colorAttachment =
6049         de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, alloc, imageCreateInfo, MemoryRequirement::Any));
6050     auto colorAttachmentView =
6051         makeImageView(vkd, device, colorAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange);
6052 
6053     const auto tcuFormat     = mapVkFormat(imageFormat);
6054     const auto outBufferSize = static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) *
6055                                                          imageExtent.width * imageExtent.height);
6056 
6057     BufferWithMemory outBuffer(vkd, device, alloc,
6058                                makeBufferCreateInfo(outBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
6059                                MemoryRequirement::HostVisible);
6060     auto &outBufferAlloc = outBuffer.getAllocation();
6061     void *outBufferData  = outBufferAlloc.getHostPtr();
6062 
6063     Move<VkRenderPass> renderPass;
6064     if (m_groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
6065     {
6066         renderPass =
6067             createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1,
6068                              RenderPassCreateInfo1>(vkd, device, RENDERING_TYPE_RENDERPASS_LEGACY);
6069     }
6070     else if (m_groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
6071     {
6072         renderPass =
6073             createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2,
6074                              RenderPassCreateInfo2>(vkd, device, RENDERING_TYPE_RENDERPASS2);
6075     }
6076 
6077     // Framebuffer.
6078     Move<VkFramebuffer> framebuffer;
6079     if (m_groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
6080         framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorAttachmentView.get(), imageExtent.width,
6081                                       imageExtent.height);
6082 
6083     const auto clearValueColor = makeClearValueColor(tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
6084 
6085     auto graphicsPipelineLayout = makePipelineLayout(vkd, device);
6086     auto commandPool            = createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, qIndex);
6087     auto commandBuffer = allocateCommandBuffer(vkd, device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
6088 
6089     beginCommandBuffer(vkd, commandBuffer.get());
6090 
6091 #ifndef CTS_USES_VULKANSC
6092     if (m_groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
6093     {
6094         VkRenderingAttachmentInfo colorAttachmentInfo{
6095             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
6096             DE_NULL,                                     // const void* pNext;
6097             colorAttachmentView.get(),                   // VkImageView imageView;
6098             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,    // VkImageLayout imageLayout;
6099             VK_RESOLVE_MODE_NONE,                        // VkResolveModeFlagBits resolveMode;
6100             DE_NULL,                                     // VkImageView resolveImageView;
6101             VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout resolveImageLayout;
6102             VK_ATTACHMENT_LOAD_OP_CLEAR,                 // VkAttachmentLoadOp loadOp;
6103             VK_ATTACHMENT_STORE_OP_STORE,                // VkAttachmentStoreOp storeOp;
6104             clearValueColor                              // VkClearValue clearValue;
6105         };
6106         VkRenderingInfo renderingInfo{
6107             VK_STRUCTURE_TYPE_RENDERING_INFO,
6108             DE_NULL,
6109             0u,                   // VkRenderingFlagsKHR flags;
6110             scissors[0],          // VkRect2D renderArea;
6111             1u,                   // uint32_t layerCount;
6112             0u,                   // uint32_t viewMask;
6113             1u,                   // uint32_t colorAttachmentCount;
6114             &colorAttachmentInfo, // const VkRenderingAttachmentInfoKHR* pColorAttachments;
6115             DE_NULL,              // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
6116             DE_NULL               // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
6117         };
6118 
6119         VkImageMemoryBarrier imageBarrier =
6120             makeImageMemoryBarrier(0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
6121                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, **colorAttachment, subresourceRange);
6122         vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
6123                                VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0u, DE_NULL, 0u,
6124                                DE_NULL, 1u, &imageBarrier);
6125 
6126         vkd.cmdBeginRendering(*commandBuffer, &renderingInfo);
6127         vkd.cmdEndRendering(*commandBuffer);
6128     }
6129     else
6130 #endif // CTS_USES_VULKANSC
6131     {
6132         const VkRenderPassBeginInfo renderPassBeginInfo{
6133             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
6134             nullptr,                                  // const void* pNext;
6135             *renderPass,                              // VkRenderPass renderPass;
6136             *framebuffer,                             // VkFramebuffer framebuffer;
6137             scissors.at(0),                           // VkRect2D renderArea;
6138             1,                                        // uint32_t clearValueCount;
6139             &clearValueColor,                         // const VkClearValue* pClearValues;
6140         };
6141         vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
6142         vkd.cmdEndRenderPass(*commandBuffer);
6143     }
6144 
6145     auto barrier = makeImageMemoryBarrier(
6146         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
6147         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, colorAttachment->get(), subresourceRange);
6148     cmdPipelineImageMemoryBarrier(vkd, *commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
6149                                   VK_PIPELINE_STAGE_TRANSFER_BIT, &barrier);
6150     copyImageToBuffer(vkd, commandBuffer.get(), colorAttachment.get()->get(), outBuffer.get(), imageSize);
6151     endCommandBuffer(vkd, commandBuffer.get());
6152     submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), commandBuffer.get());
6153     invalidateAlloc(vkd, device, outBufferAlloc);
6154 
6155     tcu::ConstPixelBufferAccess outPixels(tcuFormat, imageDim, outBufferData);
6156     auto pixel    = outPixels.getPixel(0, 0);
6157     auto expected = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f);
6158 
6159     if (pixel != expected)
6160     {
6161         std::stringstream output("Pixel isn't equal to clear color: ");
6162         output << pixel << " instead of " << expected;
6163         return tcu::TestStatus::fail(output.str());
6164     }
6165 
6166     return tcu::TestStatus::pass("Pass");
6167 }
6168 
6169 static const VkFormat s_coreColorFormats[] = {VK_FORMAT_R5G6B5_UNORM_PACK16,
6170                                               VK_FORMAT_R8_UNORM,
6171                                               VK_FORMAT_R8_SNORM,
6172                                               VK_FORMAT_R8_UINT,
6173                                               VK_FORMAT_R8_SINT,
6174                                               VK_FORMAT_R8G8_UNORM,
6175                                               VK_FORMAT_R8G8_SNORM,
6176                                               VK_FORMAT_R8G8_UINT,
6177                                               VK_FORMAT_R8G8_SINT,
6178                                               VK_FORMAT_R8G8B8A8_UNORM,
6179                                               VK_FORMAT_R8G8B8A8_SNORM,
6180                                               VK_FORMAT_R8G8B8A8_UINT,
6181                                               VK_FORMAT_R8G8B8A8_SINT,
6182                                               VK_FORMAT_R8G8B8A8_SRGB,
6183                                               VK_FORMAT_A8B8G8R8_UNORM_PACK32,
6184                                               VK_FORMAT_A8B8G8R8_SNORM_PACK32,
6185                                               VK_FORMAT_A8B8G8R8_UINT_PACK32,
6186                                               VK_FORMAT_A8B8G8R8_SINT_PACK32,
6187                                               VK_FORMAT_A8B8G8R8_SRGB_PACK32,
6188                                               VK_FORMAT_B8G8R8A8_UNORM,
6189                                               VK_FORMAT_B8G8R8A8_SRGB,
6190                                               VK_FORMAT_A2R10G10B10_UNORM_PACK32,
6191                                               VK_FORMAT_A2B10G10R10_UNORM_PACK32,
6192                                               VK_FORMAT_A2B10G10R10_UINT_PACK32,
6193                                               VK_FORMAT_R16_UNORM,
6194                                               VK_FORMAT_R16_SNORM,
6195                                               VK_FORMAT_R16_UINT,
6196                                               VK_FORMAT_R16_SINT,
6197                                               VK_FORMAT_R16_SFLOAT,
6198                                               VK_FORMAT_R16G16_UNORM,
6199                                               VK_FORMAT_R16G16_SNORM,
6200                                               VK_FORMAT_R16G16_UINT,
6201                                               VK_FORMAT_R16G16_SINT,
6202                                               VK_FORMAT_R16G16_SFLOAT,
6203                                               VK_FORMAT_R16G16B16A16_UNORM,
6204                                               VK_FORMAT_R16G16B16A16_SNORM,
6205                                               VK_FORMAT_R16G16B16A16_UINT,
6206                                               VK_FORMAT_R16G16B16A16_SINT,
6207                                               VK_FORMAT_R16G16B16A16_SFLOAT,
6208                                               VK_FORMAT_R32_UINT,
6209                                               VK_FORMAT_R32_SINT,
6210                                               VK_FORMAT_R32_SFLOAT,
6211                                               VK_FORMAT_R32G32_UINT,
6212                                               VK_FORMAT_R32G32_SINT,
6213                                               VK_FORMAT_R32G32_SFLOAT,
6214                                               VK_FORMAT_R32G32B32A32_UINT,
6215                                               VK_FORMAT_R32G32B32A32_SINT,
6216                                               VK_FORMAT_R32G32B32A32_SFLOAT};
6217 
6218 static const VkFormat s_coreDepthStencilFormats[] = {VK_FORMAT_D16_UNORM,
6219 
6220                                                      VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT,
6221 
6222                                                      VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
6223 
addAttachmentTests(tcu::TestCaseGroup * group,const TestConfigExternal testConfigExternal)6224 void addAttachmentTests(tcu::TestCaseGroup *group, const TestConfigExternal testConfigExternal)
6225 {
6226     const uint32_t attachmentCounts[]  = {1, 3, 4, 8};
6227     const VkAttachmentLoadOp loadOps[] = {VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR,
6228                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE};
6229 
6230     const VkAttachmentStoreOp storeOps[] = {VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_DONT_CARE};
6231 
6232     const VkImageLayout initialAndFinalColorLayouts[] = {
6233         VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
6234         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL};
6235 
6236     const VkImageLayout initialAndFinalColorLayoutsLazy[] = {
6237         VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
6238 
6239     const VkImageLayout initialAndFinalDepthStencilLayouts[] = {VK_IMAGE_LAYOUT_GENERAL,
6240                                                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
6241                                                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
6242                                                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
6243                                                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
6244                                                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL};
6245 
6246     const VkImageLayout initialAndFinalDepthStencilLayoutsLazy[] = {
6247         VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
6248         VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
6249 
6250     const VkImageLayout subpassLayouts[] = {VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
6251 
6252     const VkImageLayout depthStencilLayouts[] = {VK_IMAGE_LAYOUT_GENERAL,
6253                                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
6254 
6255     const TestConfig::RenderTypes renderCommands[] = {
6256         TestConfig::RENDERTYPES_NONE,
6257         TestConfig::RENDERTYPES_CLEAR,
6258         TestConfig::RENDERTYPES_DRAW,
6259         TestConfig::RENDERTYPES_CLEAR | TestConfig::RENDERTYPES_DRAW,
6260     };
6261 
6262     const TestConfig::CommandBufferTypes commandBuffers[] = {
6263         TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::COMMANDBUFFERTYPES_SECONDARY,
6264         TestConfig::COMMANDBUFFERTYPES_INLINE | TestConfig::COMMANDBUFFERTYPES_SECONDARY};
6265 
6266     const TestConfig::ImageMemory imageMemories[] = {TestConfig::IMAGEMEMORY_STRICT, TestConfig::IMAGEMEMORY_LAZY,
6267                                                      TestConfig::IMAGEMEMORY_STRICT | TestConfig::IMAGEMEMORY_LAZY};
6268 
6269     const UVec2 targetSizes[] = {UVec2(64, 64), UVec2(63, 65)};
6270 
6271     const UVec2 renderPositions[] = {UVec2(0, 0), UVec2(3, 17)};
6272 
6273     const UVec2 renderSizes[] = {UVec2(32, 32), UVec2(60, 47)};
6274 
6275     tcu::TestContext &testCtx(group->getTestContext());
6276     bool useDynamicRendering(testConfigExternal.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING);
6277     de::Random rng(1433774382u);
6278 
6279     for (size_t attachmentCountNdx = 0; attachmentCountNdx < DE_LENGTH_OF_ARRAY(attachmentCounts); attachmentCountNdx++)
6280     {
6281         const uint32_t attachmentCount = attachmentCounts[attachmentCountNdx];
6282         const uint32_t testCaseCount   = (attachmentCount == 1 ? 100 : 200);
6283         de::MovePtr<tcu::TestCaseGroup> attachmentCountGroup(
6284             new tcu::TestCaseGroup(testCtx, de::toString(attachmentCount).c_str()));
6285 
6286         for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
6287         {
6288             const bool useDepthStencil = rng.getBool();
6289             const TestConfig::ImageMemory imageMemory =
6290                 rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
6291             VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_GENERAL;
6292             vector<Attachment> attachments;
6293             vector<AttachmentReference> colorAttachmentReferences;
6294 
6295             // we want to make sure that dynamic rendering test cases have corresponding renderpass
6296             // cases as this will allow drivers to easily compare GPU batches; since configurations
6297             // for those tests are generated we need to generate configurations for all cases
6298             // even when we know earlier that for dynamic rendering we will skip it
6299             bool executeForDynamicRendering = true;
6300 
6301             for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
6302             {
6303                 const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
6304                 const VkFormat format =
6305                     rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
6306                 const VkAttachmentLoadOp loadOp =
6307                     rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
6308                 const VkAttachmentStoreOp storeOp =
6309                     rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
6310 
6311                 const VkImageLayout initialLayout =
6312                     (imageMemory == TestConfig::IMAGEMEMORY_STRICT) ?
6313                         rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts),
6314                                                   DE_ARRAY_END(initialAndFinalColorLayouts)) :
6315                         rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayoutsLazy),
6316                                                   DE_ARRAY_END(initialAndFinalColorLayoutsLazy));
6317                 VkImageLayout finalizeLayout =
6318                     (imageMemory == TestConfig::IMAGEMEMORY_STRICT) ?
6319                         rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts),
6320                                                   DE_ARRAY_END(initialAndFinalColorLayouts)) :
6321                         rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayoutsLazy),
6322                                                   DE_ARRAY_END(initialAndFinalColorLayoutsLazy));
6323                 const VkImageLayout subpassLayout =
6324                     rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
6325 
6326                 const VkAttachmentLoadOp stencilLoadOp =
6327                     rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
6328                 const VkAttachmentStoreOp stencilStoreOp =
6329                     rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
6330 
6331                 if (useDynamicRendering)
6332                 {
6333                     // with renderpass we can have automatic layout transitions; to do the same with dynamic rendering cases
6334                     // we would need to add addtional barries but since those tests won't add coverage we are skipping them
6335                     if ((initialLayout == VK_IMAGE_LAYOUT_GENERAL) ||
6336                         (initialLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL))
6337                         finalizeLayout = initialLayout;
6338                     else
6339                         executeForDynamicRendering = false;
6340                 }
6341 
6342                 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp,
6343                                                  initialLayout, finalizeLayout));
6344                 colorAttachmentReferences.push_back(AttachmentReference((uint32_t)attachmentNdx, subpassLayout));
6345             }
6346 
6347             if (useDepthStencil)
6348             {
6349                 const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
6350                 const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreDepthStencilFormats),
6351                                                              DE_ARRAY_END(s_coreDepthStencilFormats));
6352                 const VkAttachmentLoadOp loadOp =
6353                     rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
6354                 const VkAttachmentStoreOp storeOp =
6355                     rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
6356 
6357                 const VkImageLayout initialLayout =
6358                     (imageMemory == TestConfig::IMAGEMEMORY_STRICT) ?
6359                         rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts),
6360                                                   DE_ARRAY_END(initialAndFinalDepthStencilLayouts)) :
6361                         rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayoutsLazy),
6362                                                   DE_ARRAY_END(initialAndFinalDepthStencilLayoutsLazy));
6363                 VkImageLayout finalizeLayout =
6364                     (imageMemory == TestConfig::IMAGEMEMORY_STRICT) ?
6365                         rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts),
6366                                                   DE_ARRAY_END(initialAndFinalDepthStencilLayouts)) :
6367                         rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayoutsLazy),
6368                                                   DE_ARRAY_END(initialAndFinalDepthStencilLayoutsLazy));
6369 
6370                 const VkAttachmentLoadOp stencilLoadOp =
6371                     rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
6372                 const VkAttachmentStoreOp stencilStoreOp =
6373                     rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
6374 
6375                 if (useDynamicRendering)
6376                 {
6377                     if ((initialLayout == VK_IMAGE_LAYOUT_GENERAL) ||
6378                         (initialLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) ||
6379                         (initialLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL))
6380                         finalizeLayout = initialLayout;
6381                     else
6382                         executeForDynamicRendering = false;
6383                 }
6384 
6385                 depthStencilLayout =
6386                     rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(depthStencilLayouts), DE_ARRAY_END(depthStencilLayouts));
6387                 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp,
6388                                                  initialLayout, finalizeLayout));
6389             }
6390 
6391             {
6392                 const TestConfig::RenderTypes render =
6393                     rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
6394                 const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(
6395                     DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
6396                 const vector<Subpass> subpasses(
6397                     1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
6398                                colorAttachmentReferences, vector<AttachmentReference>(),
6399                                AttachmentReference(
6400                                    (useDepthStencil ? (uint32_t)(attachments.size() - 1) : VK_ATTACHMENT_UNUSED),
6401                                    depthStencilLayout),
6402                                vector<uint32_t>()));
6403                 const vector<SubpassDependency> deps;
6404                 const string testCaseName = de::toString(attachmentCountNdx * testCaseCount + testCaseNdx);
6405                 const RenderPass renderPass(attachments, subpasses, deps);
6406                 const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
6407                 const UVec2 renderPos =
6408                     rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
6409                 const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
6410 
6411                 if (useDynamicRendering)
6412                 {
6413                     // skip dynamic rendering cases (that don't add coverage) this can be done not earlier than after grabbing all
6414                     // random numbers as we need to make sure that those tests that will be created for dynamic rendering have
6415                     // corresponding renderpass tests with the same name
6416                     if (!executeForDynamicRendering)
6417                         continue;
6418 
6419                     // dont repeat non secondary buffer cases when testing secondaryCmdBufferCompletelyContainsDynamicRenderpass flag
6420                     if (testConfigExternal.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass &&
6421                         (commandBuffer != TestConfig::COMMANDBUFFERTYPES_SECONDARY))
6422                     {
6423                         continue;
6424                     }
6425                 }
6426 
6427                 const TestConfig testConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos,
6428                                             renderSize, false, 1293809, 0, testConfigExternal.allocationKind,
6429                                             testConfigExternal.groupParams);
6430 
6431                 addFunctionCaseWithPrograms<TestConfig>(attachmentCountGroup.get(), testCaseName.c_str(),
6432                                                         createTestShaders, renderPassTest, testConfig);
6433             }
6434         }
6435 
6436         group->addChild(attachmentCountGroup.release());
6437     }
6438 }
6439 
addAttachmentWriteMaskTests(tcu::TestCaseGroup * group,const TestConfigExternal testConfigExternal)6440 void addAttachmentWriteMaskTests(tcu::TestCaseGroup *group, const TestConfigExternal testConfigExternal)
6441 {
6442     const uint32_t attachmentCounts[] = {1, 2, 3, 4, 8};
6443 
6444     const VkFormat attachmentFormats[] = {VK_FORMAT_R8G8B8A8_UINT, VK_FORMAT_R8G8B8A8_UNORM,
6445                                           VK_FORMAT_R5G6B5_UNORM_PACK16, VK_FORMAT_R8G8_UNORM};
6446 
6447     tcu::TestContext &testCtx = group->getTestContext();
6448 
6449     for (uint32_t attachmentCountNdx = 0; attachmentCountNdx < DE_LENGTH_OF_ARRAY(attachmentCounts);
6450          attachmentCountNdx++)
6451     {
6452         const uint32_t attachmentCount = attachmentCounts[attachmentCountNdx];
6453         const string groupName         = "attachment_count_" + de::toString(attachmentCount);
6454 
6455         de::MovePtr<tcu::TestCaseGroup> attachmentCountGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str()));
6456 
6457         for (uint32_t drawStartNdx = 0; drawStartNdx < (attachmentCount); drawStartNdx++)
6458         {
6459             uint32_t formatNdx = 0;
6460             vector<Attachment> attachments;
6461             vector<AttachmentReference> colorAttachmentReferences;
6462 
6463             for (uint32_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
6464             {
6465                 const VkFormat format                    = attachmentFormats[formatNdx];
6466                 const VkSampleCountFlagBits sampleCount  = VK_SAMPLE_COUNT_1_BIT;
6467                 const VkAttachmentLoadOp loadOp          = VK_ATTACHMENT_LOAD_OP_CLEAR;
6468                 const VkAttachmentStoreOp storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
6469                 const VkAttachmentLoadOp stencilLoadOp   = VK_ATTACHMENT_LOAD_OP_CLEAR;
6470                 const VkAttachmentStoreOp stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
6471                 const VkImageLayout initialLayout        = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
6472                 const VkImageLayout finalizeLayout =
6473                     (testConfigExternal.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) ?
6474                         initialLayout :
6475                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
6476                 const VkImageLayout subpassLayout = VK_IMAGE_LAYOUT_GENERAL;
6477 
6478                 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp,
6479                                                  initialLayout, finalizeLayout));
6480                 colorAttachmentReferences.push_back(AttachmentReference((uint32_t)attachmentNdx, subpassLayout));
6481 
6482                 if (++formatNdx == DE_LENGTH_OF_ARRAY(attachmentFormats))
6483                     formatNdx = 0;
6484             }
6485 
6486             {
6487                 const VkImageLayout depthStencilLayout = VK_IMAGE_LAYOUT_GENERAL;
6488                 const vector<Subpass> subpass(
6489                     1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
6490                                colorAttachmentReferences, vector<AttachmentReference>(),
6491                                AttachmentReference(VK_ATTACHMENT_UNUSED, depthStencilLayout), vector<uint32_t>()));
6492                 const vector<SubpassDependency> deps;
6493 
6494                 const string testCaseName = "start_index_" + de::toString(drawStartNdx);
6495                 const RenderPass renderPass(attachments, subpass, deps);
6496 
6497                 const TestConfig::RenderTypes render               = TestConfig::RENDERTYPES_DRAW;
6498                 const TestConfig::CommandBufferTypes commandBuffer = TestConfig::COMMANDBUFFERTYPES_INLINE;
6499                 const TestConfig::ImageMemory imageMemory          = TestConfig::IMAGEMEMORY_LAZY;
6500                 const UVec2 targetSize                             = UVec2(64, 64);
6501                 const UVec2 renderPos                              = UVec2(0, 0);
6502                 const UVec2 renderSize                             = UVec2(64, 64);
6503                 const bool useFormatCompCount                      = true;
6504                 const vector<DeviceCoreFeature> requiredFeatures   = {DEVICE_CORE_FEATURE_INDEPENDENT_BLEND};
6505                 const TestConfig testConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos,
6506                                             renderSize, useFormatCompCount, 1293809, drawStartNdx,
6507                                             testConfigExternal.allocationKind, testConfigExternal.groupParams,
6508                                             requiredFeatures);
6509 
6510                 addFunctionCaseWithPrograms<TestConfig>(attachmentCountGroup.get(), testCaseName.c_str(), checkSupport,
6511                                                         createTestShaders, renderPassTest, testConfig);
6512             }
6513         }
6514 
6515         group->addChild(attachmentCountGroup.release());
6516     }
6517 }
6518 
6519 template <typename T>
chooseRandom(de::Random & rng,const set<T> & values)6520 T chooseRandom(de::Random &rng, const set<T> &values)
6521 {
6522     size_t ndx                           = ((size_t)rng.getUint32()) % values.size();
6523     typename set<T>::const_iterator iter = values.begin();
6524 
6525     for (; ndx > 0; ndx--)
6526         iter++;
6527 
6528     return *iter;
6529 }
6530 
addAttachmentAllocationTests(tcu::TestCaseGroup * group,const TestConfigExternal testConfigExternal)6531 void addAttachmentAllocationTests(tcu::TestCaseGroup *group, const TestConfigExternal testConfigExternal)
6532 {
6533     const uint32_t attachmentCounts[]  = {4, 8};
6534     const VkAttachmentLoadOp loadOps[] = {VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR,
6535                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE};
6536 
6537     const VkAttachmentStoreOp storeOps[] = {VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_STORE_OP_DONT_CARE};
6538 
6539     const VkImageLayout initialAndFinalColorLayouts[] = {
6540         VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
6541         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL};
6542 
6543     const VkImageLayout initialAndFinalColorLayoutsLazy[] = {
6544         VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
6545 
6546     const VkImageLayout initialAndFinalDepthStencilLayouts[] = {VK_IMAGE_LAYOUT_GENERAL,
6547                                                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
6548                                                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
6549                                                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
6550                                                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
6551                                                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL};
6552 
6553     const VkImageLayout subpassLayoutsColor[] = {VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
6554 
6555     const VkImageLayout subpassLayoutsDepthStencil[] = {VK_IMAGE_LAYOUT_GENERAL,
6556                                                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
6557 
6558     const VkImageLayout subpassLayoutsInput[] = {VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
6559 
6560     enum AllocationType
6561     {
6562         // Each pass uses one more attachmen than previous one
6563         ALLOCATIONTYPE_GROW,
6564         // Each pass uses one less attachment than previous one
6565         ALLOCATIONTYPE_SHRINK,
6566         // Each pass drops one attachment and picks up new one
6567         ALLOCATIONTYPE_ROLL,
6568         // Start by growing and end by shrinking
6569         ALLOCATIONTYPE_GROW_SHRINK,
6570         // Each subpass has single input and single output attachment
6571         ALLOCATIONTYPE_IO_CHAIN,
6572         // Each subpass has multiple inputs and multiple outputs attachment
6573         ALLOCATIONTYPE_IO_GENERIC
6574     };
6575 
6576     const AllocationType allocationTypes[] = {ALLOCATIONTYPE_GROW,     ALLOCATIONTYPE_SHRINK,
6577                                               ALLOCATIONTYPE_ROLL,     ALLOCATIONTYPE_GROW_SHRINK,
6578                                               ALLOCATIONTYPE_IO_CHAIN, ALLOCATIONTYPE_IO_GENERIC};
6579 
6580     const char *const allocationTypeStr[] = {
6581         "grow", "shrink", "roll", "grow_shrink", "input_output_chain", "input_output",
6582     };
6583 
6584     const TestConfig::RenderTypes renderCommands[] = {
6585         TestConfig::RENDERTYPES_NONE,
6586         TestConfig::RENDERTYPES_CLEAR,
6587         TestConfig::RENDERTYPES_DRAW,
6588         TestConfig::RENDERTYPES_CLEAR | TestConfig::RENDERTYPES_DRAW,
6589     };
6590 
6591     const TestConfig::CommandBufferTypes commandBuffers[] = {
6592         TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::COMMANDBUFFERTYPES_SECONDARY,
6593         TestConfig::COMMANDBUFFERTYPES_INLINE | TestConfig::COMMANDBUFFERTYPES_SECONDARY};
6594 
6595     const TestConfig::ImageMemory imageMemories[] = {TestConfig::IMAGEMEMORY_STRICT, TestConfig::IMAGEMEMORY_LAZY,
6596                                                      TestConfig::IMAGEMEMORY_STRICT | TestConfig::IMAGEMEMORY_LAZY};
6597 
6598     const UVec2 targetSizes[] = {UVec2(64, 64), UVec2(63, 65)};
6599 
6600     const UVec2 renderPositions[] = {UVec2(0, 0), UVec2(3, 17)};
6601 
6602     const UVec2 renderSizes[] = {UVec2(32, 32), UVec2(60, 47)};
6603 
6604     tcu::TestContext &testCtx = group->getTestContext();
6605     de::Random rng(3700649827u);
6606 
6607     for (size_t allocationTypeNdx = 0; allocationTypeNdx < DE_LENGTH_OF_ARRAY(allocationTypes); allocationTypeNdx++)
6608     {
6609         const AllocationType allocationType = allocationTypes[allocationTypeNdx];
6610         const size_t testCaseCount          = 100;
6611         de::MovePtr<tcu::TestCaseGroup> allocationTypeGroup(
6612             new tcu::TestCaseGroup(testCtx, allocationTypeStr[allocationTypeNdx]));
6613 
6614         for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
6615         {
6616             const TestConfig::ImageMemory imageMemory =
6617                 rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
6618             if (allocationType == ALLOCATIONTYPE_IO_GENERIC)
6619             {
6620                 const uint32_t attachmentCount = 4u + rng.getUint32() % 31u;
6621                 const uint32_t subpassCount    = 4u + rng.getUint32() % 31u;
6622                 vector<Attachment> attachments;
6623 
6624                 set<uint32_t> definedAttachments;
6625 
6626                 vector<Subpass> subpasses;
6627                 set<uint32_t> colorAttachments;
6628                 set<uint32_t> depthStencilAttachments;
6629 
6630                 for (uint32_t attachmentIndex = 0; attachmentIndex < attachmentCount; attachmentIndex++)
6631                 {
6632                     const bool isDepthStencilAttachment     = rng.getFloat() < 0.01f;
6633                     const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
6634                     const VkAttachmentLoadOp loadOp =
6635                         rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
6636                     const VkAttachmentStoreOp storeOp =
6637                         rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
6638 
6639                     const VkImageLayout initialLayout =
6640                         isDepthStencilAttachment ?
6641                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts),
6642                                                       DE_ARRAY_END(initialAndFinalDepthStencilLayouts)) :
6643                         (imageMemory == TestConfig::IMAGEMEMORY_STRICT) ?
6644                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts),
6645                                                       DE_ARRAY_END(initialAndFinalColorLayouts)) :
6646                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayoutsLazy),
6647                                                       DE_ARRAY_END(initialAndFinalColorLayoutsLazy));
6648                     const VkImageLayout finalizeLayout =
6649                         isDepthStencilAttachment ?
6650                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts),
6651                                                       DE_ARRAY_END(initialAndFinalDepthStencilLayouts)) :
6652                         (imageMemory == TestConfig::IMAGEMEMORY_STRICT) ?
6653                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts),
6654                                                       DE_ARRAY_END(initialAndFinalColorLayouts)) :
6655                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayoutsLazy),
6656                                                       DE_ARRAY_END(initialAndFinalColorLayoutsLazy));
6657 
6658                     const VkAttachmentLoadOp stencilLoadOp =
6659                         rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
6660                     const VkAttachmentStoreOp stencilStoreOp =
6661                         rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
6662 
6663                     if (isDepthStencilAttachment)
6664                     {
6665                         const VkFormat format = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreDepthStencilFormats),
6666                                                                      DE_ARRAY_END(s_coreDepthStencilFormats));
6667 
6668                         if (loadOp == VK_ATTACHMENT_LOAD_OP_LOAD || loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ||
6669                             stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD || stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
6670                             definedAttachments.insert(attachmentIndex);
6671 
6672                         depthStencilAttachments.insert(attachmentIndex);
6673 
6674                         attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp,
6675                                                          stencilStoreOp, initialLayout, finalizeLayout));
6676                     }
6677                     else
6678                     {
6679                         const VkFormat format =
6680                             rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
6681 
6682                         if (loadOp == VK_ATTACHMENT_LOAD_OP_LOAD || loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
6683                             definedAttachments.insert(attachmentIndex);
6684 
6685                         colorAttachments.insert(attachmentIndex);
6686 
6687                         attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp,
6688                                                          stencilStoreOp, initialLayout, finalizeLayout));
6689                     }
6690                 }
6691                 vector<Maybe<uint32_t>> lastUseOfAttachment(attachments.size(), tcu::Nothing);
6692                 vector<SubpassDependency> deps;
6693 
6694                 for (uint32_t subpassIndex = 0; subpassIndex < subpassCount; subpassIndex++)
6695                 {
6696                     const uint32_t colorAttachmentCount =
6697                         depthStencilAttachments.empty() ?
6698                             1 + rng.getUint32() % de::min(4u, (uint32_t)colorAttachments.size()) :
6699                             rng.getUint32() % (de::min(4u, (uint32_t)colorAttachments.size()) + 1u);
6700                     const uint32_t inputAttachmentCount =
6701                         rng.getUint32() % (uint32_t)(de::min<size_t>(4, definedAttachments.size()) + 1);
6702                     const bool useDepthStencilAttachment =
6703                         !depthStencilAttachments.empty() && (colorAttachmentCount == 0 || rng.getBool());
6704                     std::vector<uint32_t> subpassColorAttachments(colorAttachmentCount);
6705                     std::vector<uint32_t> subpassInputAttachments(inputAttachmentCount);
6706                     Maybe<uint32_t> depthStencilAttachment(
6707                         useDepthStencilAttachment ? just(chooseRandom(rng, depthStencilAttachments)) : tcu::Nothing);
6708                     std::vector<uint32_t> subpassPreserveAttachments;
6709 
6710                     rng.choose(colorAttachments.begin(), colorAttachments.end(), subpassColorAttachments.begin(),
6711                                colorAttachmentCount);
6712                     rng.choose(definedAttachments.begin(), definedAttachments.end(), subpassInputAttachments.begin(),
6713                                inputAttachmentCount);
6714 
6715                     for (size_t colorAttachmentNdx = 0; colorAttachmentNdx < subpassColorAttachments.size();
6716                          colorAttachmentNdx++)
6717                         definedAttachments.insert(subpassColorAttachments[colorAttachmentNdx]);
6718 
6719                     if (depthStencilAttachment)
6720                         definedAttachments.insert(*depthStencilAttachment);
6721 
6722                     {
6723                         std::vector<AttachmentReference> inputAttachmentReferences;
6724                         std::vector<AttachmentReference> colorAttachmentReferences;
6725                         AttachmentReference depthStencilAttachmentReference(VK_ATTACHMENT_UNUSED,
6726                                                                             VK_IMAGE_LAYOUT_GENERAL);
6727 
6728                         for (size_t colorAttachmentNdx = 0; colorAttachmentNdx < subpassColorAttachments.size();
6729                              colorAttachmentNdx++)
6730                         {
6731                             const uint32_t colorAttachmentIndex = subpassColorAttachments[colorAttachmentNdx];
6732 
6733                             if (lastUseOfAttachment[colorAttachmentIndex])
6734                             {
6735                                 bool foundDuplicate = false;
6736 
6737                                 const uint32_t srcPass = *lastUseOfAttachment[colorAttachmentIndex];
6738                                 const uint32_t dstPass = subpassIndex;
6739                                 const VkDependencyFlags dependencyFlags =
6740                                     rng.getBool() ? (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT : 0u;
6741 
6742                                 const SubpassDependency newDependency(
6743                                     srcPass, dstPass,
6744                                     VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
6745                                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
6746                                         VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
6747                                         VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6748 
6749                                     VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
6750                                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
6751                                         VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
6752                                         VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6753 
6754                                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
6755 
6756                                     dependencyFlags);
6757 
6758                                 for (SubpassDependency &dependency : deps)
6759                                 {
6760                                     if (dependency.getSrcPass() == srcPass && dependency.getDstPass() == dstPass)
6761                                     {
6762                                         const VkAccessFlags newDstFlags =
6763                                             dependency.getDstAccessMask() | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
6764                                         dependency.setDstAccessMask(newDstFlags);
6765                                         foundDuplicate = true;
6766                                         break;
6767                                     }
6768                                 }
6769 
6770                                 if (!foundDuplicate)
6771                                 {
6772                                     deps.push_back(newDependency);
6773                                 }
6774                             }
6775 
6776                             lastUseOfAttachment[colorAttachmentIndex] = just(subpassIndex);
6777 
6778                             colorAttachmentReferences.push_back(AttachmentReference(
6779                                 (uint32_t)subpassColorAttachments[colorAttachmentNdx], VK_IMAGE_LAYOUT_GENERAL));
6780                         }
6781 
6782                         for (size_t inputAttachmentNdx = 0; inputAttachmentNdx < subpassInputAttachments.size();
6783                              inputAttachmentNdx++)
6784                         {
6785                             const uint32_t inputAttachmentIndex = subpassInputAttachments[inputAttachmentNdx];
6786 
6787                             if (lastUseOfAttachment[inputAttachmentIndex])
6788                             {
6789                                 bool foundDuplicate = false;
6790 
6791                                 const uint32_t srcPass = *lastUseOfAttachment[inputAttachmentIndex];
6792                                 const uint32_t dstPass = subpassIndex;
6793                                 const VkDependencyFlags dependencyFlags =
6794                                     ((srcPass == subpassIndex) || rng.getBool()) ?
6795                                         (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT :
6796                                         0u;
6797 
6798                                 const SubpassDependency newDependency(
6799                                     srcPass, dstPass,
6800                                     VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
6801                                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
6802                                         VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
6803                                         VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6804 
6805                                     VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
6806                                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
6807                                         VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
6808                                         VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6809 
6810                                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
6811                                     VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
6812 
6813                                     dependencyFlags);
6814                                 for (SubpassDependency &dependency : deps)
6815                                 {
6816                                     if (dependency.getSrcPass() == srcPass && dependency.getDstPass() == dstPass)
6817                                     {
6818                                         const VkAccessFlags newSrcFlags = dependency.getSrcAccessMask() |
6819                                                                           VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
6820                                         const VkAccessFlags newDstFlags =
6821                                             dependency.getDstAccessMask() | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
6822                                         dependency.setDstAccessMask(newSrcFlags);
6823                                         dependency.setDstAccessMask(newDstFlags);
6824                                         foundDuplicate = true;
6825                                         break;
6826                                     }
6827                                 }
6828 
6829                                 if (!foundDuplicate)
6830                                 {
6831                                     deps.push_back(newDependency);
6832                                 }
6833 
6834                                 lastUseOfAttachment[inputAttachmentIndex] = just(subpassIndex);
6835 
6836                                 VkImageAspectFlags aspect = 0u;
6837                                 if (testConfigExternal.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
6838                                 {
6839                                     bool col = colorAttachments.find(inputAttachmentIndex) != colorAttachments.end();
6840                                     aspect   = col ? VK_IMAGE_ASPECT_COLOR_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
6841                                 }
6842                                 inputAttachmentReferences.push_back(
6843                                     AttachmentReference((uint32_t)subpassInputAttachments[inputAttachmentNdx],
6844                                                         VK_IMAGE_LAYOUT_GENERAL, aspect));
6845                             }
6846                         }
6847 
6848                         if (depthStencilAttachment)
6849                         {
6850                             if (lastUseOfAttachment[*depthStencilAttachment])
6851                             {
6852                                 bool foundDuplicate = false;
6853 
6854                                 const uint32_t srcPass = *lastUseOfAttachment[*depthStencilAttachment];
6855                                 const uint32_t dstPass = subpassIndex;
6856                                 const VkDependencyFlags dependencyFlags =
6857                                     ((srcPass == subpassIndex) || rng.getBool()) ?
6858                                         (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT :
6859                                         0u;
6860 
6861                                 const SubpassDependency newDependency(
6862                                     srcPass, dstPass,
6863                                     VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
6864                                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
6865                                         VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
6866                                         VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6867 
6868                                     VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
6869                                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
6870                                         VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
6871                                         VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6872 
6873                                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
6874                                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
6875 
6876                                     dependencyFlags);
6877                                 for (SubpassDependency &dependency : deps)
6878                                 {
6879                                     if (dependency.getSrcPass() == srcPass && dependency.getDstPass() == dstPass)
6880                                     {
6881                                         const VkAccessFlags newSrcFlags = dependency.getSrcAccessMask() |
6882                                                                           VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
6883                                         const VkAccessFlags newDstFlags = dependency.getDstAccessMask() |
6884                                                                           VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
6885                                                                           VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
6886                                         dependency.setDstAccessMask(newSrcFlags);
6887                                         dependency.setDstAccessMask(newDstFlags);
6888                                         foundDuplicate = true;
6889                                         break;
6890                                     }
6891                                 }
6892 
6893                                 if (!foundDuplicate)
6894                                 {
6895                                     deps.push_back(newDependency);
6896                                 }
6897                             }
6898 
6899                             lastUseOfAttachment[*depthStencilAttachment] = just(subpassIndex);
6900 
6901                             depthStencilAttachmentReference =
6902                                 AttachmentReference(*depthStencilAttachment, VK_IMAGE_LAYOUT_GENERAL);
6903                         }
6904                         else
6905                             depthStencilAttachmentReference =
6906                                 AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL);
6907 
6908                         vector<uint32_t> preserveAttachments;
6909                         for (uint32_t attachmentIndex = 0; attachmentIndex < (uint32_t)attachments.size();
6910                              attachmentIndex++)
6911                         {
6912                             if (lastUseOfAttachment[attachmentIndex] &&
6913                                 (*lastUseOfAttachment[attachmentIndex]) != subpassIndex)
6914                                 preserveAttachments.push_back(attachmentIndex);
6915                         }
6916 
6917                         // Use random image layout when possible
6918                         for (size_t colorRefIdx = 0; colorRefIdx < colorAttachmentReferences.size(); ++colorRefIdx)
6919                         {
6920                             bool usedAsInput = false;
6921                             for (size_t inputRefIdx = 0; inputRefIdx < inputAttachmentReferences.size(); ++inputRefIdx)
6922                                 if (colorAttachmentReferences[colorRefIdx].getAttachment() ==
6923                                     inputAttachmentReferences[inputRefIdx].getAttachment())
6924                                     usedAsInput = true;
6925 
6926                             if (!usedAsInput)
6927                                 colorAttachmentReferences[colorRefIdx].setImageLayout(rng.choose<VkImageLayout>(
6928                                     DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor)));
6929                         }
6930                         for (size_t inputRefIdx = 0; inputRefIdx < inputAttachmentReferences.size(); ++inputRefIdx)
6931                         {
6932                             bool usedAsDepthStencil = inputAttachmentReferences[inputRefIdx].getAttachment() ==
6933                                                       depthStencilAttachmentReference.getAttachment();
6934                             bool usedAsColor = false;
6935                             for (size_t colorRefIdx = 0; colorRefIdx < colorAttachmentReferences.size(); ++colorRefIdx)
6936                                 if (inputAttachmentReferences[inputRefIdx].getAttachment() ==
6937                                     colorAttachmentReferences[colorRefIdx].getAttachment())
6938                                     usedAsColor = true;
6939 
6940                             if (!usedAsColor && !usedAsDepthStencil)
6941                                 inputAttachmentReferences[inputRefIdx].setImageLayout(rng.choose<VkImageLayout>(
6942                                     DE_ARRAY_BEGIN(subpassLayoutsInput), DE_ARRAY_END(subpassLayoutsInput)));
6943                         }
6944                         {
6945                             bool usedAsInput = false;
6946                             for (size_t inputRefIdx = 0; inputRefIdx < inputAttachmentReferences.size(); ++inputRefIdx)
6947                                 if (depthStencilAttachmentReference.getAttachment() ==
6948                                     inputAttachmentReferences[inputRefIdx].getAttachment())
6949                                     usedAsInput = true;
6950 
6951                             if (!usedAsInput)
6952                                 depthStencilAttachmentReference.setImageLayout(
6953                                     rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsDepthStencil),
6954                                                               DE_ARRAY_END(subpassLayoutsDepthStencil)));
6955                         }
6956 
6957                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, inputAttachmentReferences,
6958                                                     colorAttachmentReferences, vector<AttachmentReference>(),
6959                                                     depthStencilAttachmentReference, preserveAttachments));
6960                     }
6961                 }
6962                 {
6963                     const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(
6964                         DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
6965                     const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(
6966                         DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
6967 
6968                     const string testCaseName = de::toString(testCaseNdx);
6969                     const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
6970                     const UVec2 renderPos =
6971                         rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
6972                     const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
6973 
6974                     const RenderPass renderPass(attachments, subpasses, deps);
6975                     const TestConfig testConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos,
6976                                                 renderSize, false, 80329, 0, testConfigExternal.allocationKind,
6977                                                 testConfigExternal.groupParams);
6978 
6979                     addFunctionCaseWithPrograms<TestConfig>(allocationTypeGroup.get(), testCaseName.c_str(),
6980                                                             createTestShaders, renderPassTest, testConfig);
6981                 }
6982             }
6983             else
6984             {
6985                 const uint32_t attachmentCount =
6986                     rng.choose<uint32_t>(DE_ARRAY_BEGIN(attachmentCounts), DE_ARRAY_END(attachmentCounts));
6987                 vector<Attachment> attachments;
6988                 vector<Subpass> subpasses;
6989 
6990                 for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
6991                 {
6992                     const VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
6993                     const VkFormat format =
6994                         rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
6995 
6996                     const VkAttachmentLoadOp loadOp =
6997                         rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
6998                     const VkAttachmentStoreOp storeOp =
6999                         rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
7000 
7001                     const VkImageLayout initialLayout =
7002                         (imageMemory == TestConfig::IMAGEMEMORY_STRICT) ?
7003                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts),
7004                                                       DE_ARRAY_END(initialAndFinalColorLayouts)) :
7005                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayoutsLazy),
7006                                                       DE_ARRAY_END(initialAndFinalColorLayoutsLazy));
7007 
7008                     const VkImageLayout finalizeLayout =
7009                         (imageMemory == TestConfig::IMAGEMEMORY_STRICT) ?
7010                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts),
7011                                                       DE_ARRAY_END(initialAndFinalColorLayouts)) :
7012                             rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayoutsLazy),
7013                                                       DE_ARRAY_END(initialAndFinalColorLayoutsLazy));
7014 
7015                     const VkAttachmentLoadOp stencilLoadOp =
7016                         rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
7017                     const VkAttachmentStoreOp stencilStoreOp =
7018                         rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
7019 
7020                     attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp,
7021                                                      stencilStoreOp, initialLayout, finalizeLayout));
7022                 }
7023 
7024                 if (allocationType == ALLOCATIONTYPE_GROW)
7025                 {
7026                     for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
7027                     {
7028                         vector<AttachmentReference> colorAttachmentReferences;
7029 
7030                         for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
7031                         {
7032                             const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(
7033                                 DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor));
7034 
7035                             colorAttachmentReferences.push_back(
7036                                 AttachmentReference((uint32_t)attachmentNdx, subpassLayout));
7037                         }
7038 
7039                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7040                                                     colorAttachmentReferences, vector<AttachmentReference>(),
7041                                                     AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7042                                                     vector<uint32_t>()));
7043                     }
7044                 }
7045                 else if (allocationType == ALLOCATIONTYPE_SHRINK)
7046                 {
7047                     for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
7048                     {
7049                         vector<AttachmentReference> colorAttachmentReferences;
7050 
7051                         for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
7052                         {
7053                             const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(
7054                                 DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor));
7055 
7056                             colorAttachmentReferences.push_back(
7057                                 AttachmentReference((uint32_t)attachmentNdx, subpassLayout));
7058                         }
7059 
7060                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7061                                                     colorAttachmentReferences, vector<AttachmentReference>(),
7062                                                     AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7063                                                     vector<uint32_t>()));
7064                     }
7065                 }
7066                 else if (allocationType == ALLOCATIONTYPE_ROLL)
7067                 {
7068                     for (size_t subpassNdx = 0; subpassNdx < attachmentCount / 2; subpassNdx++)
7069                     {
7070                         vector<AttachmentReference> colorAttachmentReferences;
7071 
7072                         for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount / 2; attachmentNdx++)
7073                         {
7074                             const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(
7075                                 DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor));
7076 
7077                             colorAttachmentReferences.push_back(
7078                                 AttachmentReference((uint32_t)(subpassNdx + attachmentNdx), subpassLayout));
7079                         }
7080 
7081                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7082                                                     colorAttachmentReferences, vector<AttachmentReference>(),
7083                                                     AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7084                                                     vector<uint32_t>()));
7085                     }
7086                 }
7087                 else if (allocationType == ALLOCATIONTYPE_GROW_SHRINK)
7088                 {
7089                     for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
7090                     {
7091                         vector<AttachmentReference> colorAttachmentReferences;
7092 
7093                         for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
7094                         {
7095                             const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(
7096                                 DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor));
7097 
7098                             colorAttachmentReferences.push_back(
7099                                 AttachmentReference((uint32_t)attachmentNdx, subpassLayout));
7100                         }
7101 
7102                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7103                                                     colorAttachmentReferences, vector<AttachmentReference>(),
7104                                                     AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7105                                                     vector<uint32_t>()));
7106                     }
7107                     for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
7108                     {
7109                         vector<AttachmentReference> colorAttachmentReferences;
7110 
7111                         for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
7112                         {
7113                             const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(
7114                                 DE_ARRAY_BEGIN(subpassLayoutsColor), DE_ARRAY_END(subpassLayoutsColor));
7115 
7116                             colorAttachmentReferences.push_back(
7117                                 AttachmentReference((uint32_t)attachmentNdx, subpassLayout));
7118                         }
7119 
7120                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7121                                                     colorAttachmentReferences, vector<AttachmentReference>(),
7122                                                     AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7123                                                     vector<uint32_t>()));
7124                     }
7125                 }
7126                 else if (allocationType == ALLOCATIONTYPE_IO_CHAIN)
7127                 {
7128                     subpasses.push_back(Subpass(
7129                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7130                         vector<AttachmentReference>(
7131                             1, AttachmentReference(0, rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor),
7132                                                                                 DE_ARRAY_END(subpassLayoutsColor)))),
7133                         vector<AttachmentReference>(),
7134                         AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<uint32_t>()));
7135 
7136                     for (size_t subpassNdx = 1; subpassNdx < attachmentCount; subpassNdx++)
7137                     {
7138                         const VkImageAspectFlags inputAttachmentAspectMask =
7139                             (testConfigExternal.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2) ?
7140                                 VK_IMAGE_ASPECT_COLOR_BIT :
7141                                 static_cast<VkImageAspectFlagBits>(0);
7142                         subpasses.push_back(Subpass(
7143                             VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
7144                             vector<AttachmentReference>(1, AttachmentReference((uint32_t)(subpassNdx - 1),
7145                                                                                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
7146                                                                                inputAttachmentAspectMask)),
7147                             vector<AttachmentReference>(
7148                                 1, AttachmentReference((uint32_t)(subpassNdx),
7149                                                        rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayoutsColor),
7150                                                                                  DE_ARRAY_END(subpassLayoutsColor)))),
7151                             vector<AttachmentReference>(),
7152                             AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<uint32_t>()));
7153                     }
7154                 }
7155                 else
7156                     DE_FATAL("Unknown allocation type");
7157 
7158                 {
7159                     const TestConfig::RenderTypes render = rng.choose<TestConfig::RenderTypes>(
7160                         DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
7161                     const TestConfig::CommandBufferTypes commandBuffer = rng.choose<TestConfig::CommandBufferTypes>(
7162                         DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
7163 
7164                     const string testCaseName = de::toString(testCaseNdx);
7165                     const UVec2 targetSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
7166                     const UVec2 renderPos =
7167                         rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
7168                     const UVec2 renderSize = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
7169 
7170                     vector<SubpassDependency> deps;
7171 
7172                     for (size_t subpassNdx = 0; subpassNdx < subpasses.size() - 1; subpassNdx++)
7173                     {
7174                         const bool byRegion = rng.getBool();
7175                         deps.push_back(SubpassDependency(
7176                             (uint32_t)subpassNdx, (uint32_t)subpassNdx + 1,
7177                             VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
7178                                 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
7179 
7180                             VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
7181                                 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
7182 
7183                             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
7184                             (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT),
7185 
7186                             byRegion ? (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT : 0u));
7187                     }
7188 
7189                     const RenderPass renderPass(attachments, subpasses, deps);
7190                     const TestConfig testConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos,
7191                                                 renderSize, false, 80329, 0, testConfigExternal.allocationKind,
7192                                                 testConfigExternal.groupParams);
7193 
7194                     addFunctionCaseWithPrograms<TestConfig>(allocationTypeGroup.get(), testCaseName.c_str(),
7195                                                             createTestShaders, renderPassTest, testConfig);
7196                 }
7197             }
7198         }
7199         group->addChild(allocationTypeGroup.release());
7200     }
7201 }
7202 
addSimpleTests(tcu::TestCaseGroup * group,const TestConfigExternal testConfigExternal)7203 void addSimpleTests(tcu::TestCaseGroup *group, const TestConfigExternal testConfigExternal)
7204 {
7205     const UVec2 targetSize(64, 64);
7206     const UVec2 renderPos(0, 0);
7207     const UVec2 renderSize(64, 64);
7208 
7209     // color
7210     {
7211         const RenderPass renderPass(
7212             vector<Attachment>(1,
7213                                Attachment(VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
7214                                           VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7215                                           VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7216                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7217             vector<Subpass>(
7218                 1, Subpass(
7219                        VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7220                        vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7221                        vector<AttachmentReference>(),
7222                        AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<uint32_t>())),
7223             vector<SubpassDependency>());
7224         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7225                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7226                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7227 
7228         addFunctionCaseWithPrograms<TestConfig>(group, "color", createTestShaders, renderPassTest, testConfig);
7229     }
7230 
7231     // depth
7232     {
7233         const RenderPass renderPass(
7234             vector<Attachment>(1, Attachment(VK_FORMAT_X8_D24_UNORM_PACK32, VK_SAMPLE_COUNT_1_BIT,
7235                                              VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
7236                                              VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7237                                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7238                                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
7239             vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7240                                        vector<AttachmentReference>(), vector<AttachmentReference>(),
7241                                        AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7242                                        vector<uint32_t>())),
7243             vector<SubpassDependency>());
7244         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7245                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7246                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7247 
7248         addFunctionCaseWithPrograms<TestConfig>(group, "depth", createTestShaders, renderPassTest, testConfig);
7249     }
7250 
7251     // stencil
7252     {
7253         const RenderPass renderPass(
7254             vector<Attachment>(1, Attachment(VK_FORMAT_S8_UINT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7255                                              VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_CLEAR,
7256                                              VK_ATTACHMENT_STORE_OP_STORE,
7257                                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7258                                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
7259             vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7260                                        vector<AttachmentReference>(), vector<AttachmentReference>(),
7261                                        AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7262                                        vector<uint32_t>())),
7263             vector<SubpassDependency>());
7264         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7265                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7266                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7267 
7268         addFunctionCaseWithPrograms<TestConfig>(group, "stencil", createTestShaders, renderPassTest, testConfig);
7269     }
7270 
7271     // depth_stencil
7272     {
7273         const RenderPass renderPass(
7274             vector<Attachment>(1, Attachment(VK_FORMAT_D24_UNORM_S8_UINT, VK_SAMPLE_COUNT_1_BIT,
7275                                              VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
7276                                              VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
7277                                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7278                                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
7279             vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7280                                        vector<AttachmentReference>(), vector<AttachmentReference>(),
7281                                        AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7282                                        vector<uint32_t>())),
7283             vector<SubpassDependency>());
7284         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7285                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7286                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7287 
7288         addFunctionCaseWithPrograms<TestConfig>(group, "depth_stencil", createTestShaders, renderPassTest, testConfig);
7289     }
7290 
7291     // color_depth
7292     {
7293         const Attachment attachments[] = {
7294             Attachment(VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
7295                        VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7296                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
7297             Attachment(VK_FORMAT_X8_D24_UNORM_PACK32, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
7298                        VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7299                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7300                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7301         };
7302 
7303         const RenderPass renderPass(
7304             vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
7305             vector<Subpass>(
7306                 1, Subpass(
7307                        VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7308                        vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7309                        vector<AttachmentReference>(),
7310                        AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), vector<uint32_t>())),
7311             vector<SubpassDependency>());
7312         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7313                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7314                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7315 
7316         addFunctionCaseWithPrograms<TestConfig>(group, "color_depth", createTestShaders, renderPassTest, testConfig);
7317     }
7318 
7319     // color_stencil
7320     {
7321         const Attachment attachments[] = {
7322             Attachment(VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
7323                        VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7324                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
7325             Attachment(VK_FORMAT_S8_UINT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7326                        VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
7327                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7328                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7329         };
7330 
7331         const RenderPass renderPass(
7332             vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
7333             vector<Subpass>(
7334                 1, Subpass(
7335                        VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7336                        vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7337                        vector<AttachmentReference>(),
7338                        AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), vector<uint32_t>())),
7339             vector<SubpassDependency>());
7340         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7341                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7342                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7343 
7344         addFunctionCaseWithPrograms<TestConfig>(group, "color_stencil", createTestShaders, renderPassTest, testConfig);
7345     }
7346 
7347     // color_depth_stencil
7348     {
7349         const Attachment attachments[] = {
7350             Attachment(VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
7351                        VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7352                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
7353             Attachment(VK_FORMAT_D24_UNORM_S8_UINT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
7354                        VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
7355                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7356                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7357         };
7358 
7359         const RenderPass renderPass(
7360             vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
7361             vector<Subpass>(
7362                 1, Subpass(
7363                        VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7364                        vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7365                        vector<AttachmentReference>(),
7366                        AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL), vector<uint32_t>())),
7367             vector<SubpassDependency>());
7368         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7369                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7370                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7371 
7372         // Color, depth and stencil attachment case.
7373         addFunctionCaseWithPrograms<TestConfig>(group, "color_depth_stencil", createTestShaders, renderPassTest,
7374                                                 testConfig);
7375     }
7376 
7377     // no attachments
7378     {
7379         const RenderPass renderPass(
7380             vector<Attachment>(),
7381             vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7382                                        vector<AttachmentReference>(), vector<AttachmentReference>(),
7383                                        AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7384                                        vector<uint32_t>())),
7385             vector<SubpassDependency>());
7386         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7387                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7388                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7389 
7390         // No attachments case.
7391         addFunctionCaseWithPrograms<TestConfig>(group, "no_attachments", createTestShaders, renderPassTest, testConfig);
7392     }
7393 
7394     // color_unused_omit_blend_state
7395     if (testConfigExternal.groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
7396     {
7397         vector<Subpass> subpasses;
7398 
7399         // First subpass: use color attachment, create pipeline with color blend state
7400         subpasses.push_back(
7401             Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7402                     vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7403                     vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7404                     vector<uint32_t>(), false));
7405 
7406         // Second subpass: don't use color attachment, create pipeline without color blend state
7407         subpasses.push_back(
7408             Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7409                     vector<AttachmentReference>(
7410                         1, AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7411                     vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7412                     vector<uint32_t>(), true));
7413 
7414         const RenderPass renderPass(
7415             vector<Attachment>(1,
7416                                Attachment(VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
7417                                           VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7418                                           VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7419                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7420             subpasses, vector<SubpassDependency>());
7421 
7422         const TestConfig testConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE,
7423                                     TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7424                                     testConfigExternal.allocationKind, testConfigExternal.groupParams);
7425         // Two unused color attachment case without blend state
7426         addFunctionCaseWithPrograms<TestConfig>(group, "color_unused_omit_blend_state", createTestShaders,
7427                                                 renderPassTest, testConfig);
7428     }
7429 }
7430 
formatToName(VkFormat format)7431 std::string formatToName(VkFormat format)
7432 {
7433     const std::string formatStr = de::toString(format);
7434     const std::string prefix    = "VK_FORMAT_";
7435 
7436     DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
7437 
7438     return de::toLower(formatStr.substr(prefix.length()));
7439 }
7440 
addFormatTests(tcu::TestCaseGroup * group,const TestConfigExternal testConfigExternal)7441 void addFormatTests(tcu::TestCaseGroup *group, const TestConfigExternal testConfigExternal)
7442 {
7443     tcu::TestContext &testCtx = group->getTestContext();
7444 
7445     const UVec2 targetSize(64, 64);
7446     const UVec2 renderPos(0, 0);
7447     const UVec2 renderSize(64, 64);
7448 
7449     const struct
7450     {
7451         const char *const str;
7452         const VkAttachmentStoreOp op;
7453     } storeOps[] = {{"store", VK_ATTACHMENT_STORE_OP_STORE}, {"dont_care", VK_ATTACHMENT_STORE_OP_DONT_CARE}};
7454 
7455     const struct
7456     {
7457         const char *const str;
7458         const VkAttachmentLoadOp op;
7459     } loadOps[] = {{"clear", VK_ATTACHMENT_LOAD_OP_CLEAR},
7460                    {"load", VK_ATTACHMENT_LOAD_OP_LOAD},
7461                    {"dont_care", VK_ATTACHMENT_LOAD_OP_DONT_CARE}};
7462 
7463     const struct
7464     {
7465         const char *const str;
7466         const TestConfig::RenderTypes types;
7467     } renderTypes[] = {{"clear", TestConfig::RENDERTYPES_CLEAR},
7468                        {"draw", TestConfig::RENDERTYPES_DRAW},
7469                        {"clear_draw", TestConfig::RENDERTYPES_CLEAR | TestConfig::RENDERTYPES_DRAW}};
7470 
7471     std::vector<VkFormat> colorFormatsToTest(s_coreColorFormats,
7472                                              s_coreColorFormats + de::arrayLength(s_coreColorFormats));
7473 #ifndef CTS_USES_VULKANSC
7474     colorFormatsToTest.push_back(VK_FORMAT_A8_UNORM_KHR);
7475 #endif // CTS_USES_VULKANSC
7476 
7477     // Color formats
7478     for (const auto &format : colorFormatsToTest)
7479     {
7480         de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatToName(format).c_str()));
7481 
7482         for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
7483         {
7484             const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op;
7485             de::MovePtr<tcu::TestCaseGroup> loadOpGroup(new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str));
7486 
7487             for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
7488             {
7489                 const RenderPass renderPass(
7490                     vector<Attachment>(1,
7491                                        Attachment(format, VK_SAMPLE_COUNT_1_BIT, loadOp, VK_ATTACHMENT_STORE_OP_STORE,
7492                                                   VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7493                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7494                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7495                     vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7496                                                vector<AttachmentReference>(
7497                                                    1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7498                                                vector<AttachmentReference>(),
7499                                                AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7500                                                vector<uint32_t>())),
7501                     vector<SubpassDependency>());
7502                 const TestConfig testConfig(renderPass, renderTypes[renderTypeNdx].types,
7503                                             TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
7504                                             targetSize, renderPos, renderSize, false, 90239, 0,
7505                                             testConfigExternal.allocationKind, testConfigExternal.groupParams);
7506 
7507                 addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str,
7508                                                         createTestShaders, renderPassTest, testConfig);
7509             }
7510 
7511             formatGroup->addChild(loadOpGroup.release());
7512         }
7513 
7514         {
7515             // Test attachment format as input
7516             de::MovePtr<tcu::TestCaseGroup> inputGroup(new tcu::TestCaseGroup(testCtx, "input"));
7517 
7518             for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
7519             {
7520                 const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op;
7521                 de::MovePtr<tcu::TestCaseGroup> loadOpGroup(new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str));
7522 
7523                 for (size_t storeOpNdx = 0; storeOpNdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpNdx++)
7524                 {
7525                     const VkImageAspectFlags inputAttachmentAspectMask =
7526                         (testConfigExternal.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2) ?
7527                             static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT) :
7528                             static_cast<VkImageAspectFlags>(0);
7529                     const VkAttachmentStoreOp storeOp = storeOps[storeOpNdx].op;
7530                     de::MovePtr<tcu::TestCaseGroup> storeOpGroup(
7531                         new tcu::TestCaseGroup(testCtx, storeOps[storeOpNdx].str));
7532 
7533                     for (size_t useInputAspectNdx = 0; useInputAspectNdx < 2; useInputAspectNdx++)
7534                     {
7535                         const bool useInputAspect = useInputAspectNdx != 0;
7536 
7537                         if (testConfigExternal.groupParams->renderingType != RENDERING_TYPE_RENDERPASS_LEGACY &&
7538                             useInputAspect)
7539                             continue;
7540 
7541                         for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
7542                         {
7543                             {
7544                                 vector<Attachment> attachments;
7545                                 vector<Subpass> subpasses;
7546                                 vector<SubpassDependency> deps;
7547                                 vector<VkInputAttachmentAspectReference> inputAspects;
7548 
7549                                 attachments.push_back(Attachment(
7550                                     format, VK_SAMPLE_COUNT_1_BIT, loadOp, storeOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7551                                     VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7552                                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
7553 
7554                                 attachments.push_back(
7555                                     Attachment(vk::VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
7556                                                VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
7557                                                VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7558                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7559                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
7560 
7561                                 subpasses.push_back(
7562                                     Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7563                                             vector<AttachmentReference>(
7564                                                 1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7565                                             vector<AttachmentReference>(),
7566                                             AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7567                                             vector<uint32_t>()));
7568                                 subpasses.push_back(
7569                                     Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
7570                                             vector<AttachmentReference>(
7571                                                 1, AttachmentReference(0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
7572                                                                        inputAttachmentAspectMask)),
7573                                             vector<AttachmentReference>(
7574                                                 1, AttachmentReference(1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7575                                             vector<AttachmentReference>(),
7576                                             AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7577                                             vector<uint32_t>()));
7578 
7579                                 deps.push_back(SubpassDependency(0, 1,
7580 
7581                                                                  vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
7582                                                                  vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
7583 
7584                                                                  vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
7585                                                                  vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
7586                                                                  vk::VK_DEPENDENCY_BY_REGION_BIT));
7587 
7588                                 if (useInputAspect)
7589                                 {
7590                                     const VkInputAttachmentAspectReference inputAspect = {1u, 0u,
7591                                                                                           VK_IMAGE_ASPECT_COLOR_BIT};
7592 
7593                                     inputAspects.push_back(inputAspect);
7594                                 }
7595 
7596                                 {
7597                                     const RenderPass renderPass(attachments, subpasses, deps, inputAspects);
7598                                     const TestConfig testConfig(
7599                                         renderPass, renderTypes[renderTypeNdx].types,
7600                                         TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
7601                                         targetSize, renderPos, renderSize, false, 89246, 0,
7602                                         testConfigExternal.allocationKind, testConfigExternal.groupParams);
7603                                     const string testName(renderTypes[renderTypeNdx].str +
7604                                                           string(useInputAspect ? "_use_input_aspect" : ""));
7605 
7606                                     addFunctionCaseWithPrograms<TestConfig>(
7607                                         storeOpGroup.get(), testName, createTestShaders, renderPassTest, testConfig);
7608                                 }
7609                             }
7610                             {
7611                                 vector<Attachment> attachments;
7612                                 vector<Subpass> subpasses;
7613                                 vector<SubpassDependency> deps;
7614                                 vector<VkInputAttachmentAspectReference> inputAspects;
7615 
7616                                 attachments.push_back(Attachment(
7617                                     format, VK_SAMPLE_COUNT_1_BIT, loadOp, storeOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7618                                     VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7619                                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
7620 
7621                                 subpasses.push_back(
7622                                     Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7623                                             vector<AttachmentReference>(
7624                                                 1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7625                                             vector<AttachmentReference>(),
7626                                             AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7627                                             vector<uint32_t>()));
7628                                 subpasses.push_back(Subpass(
7629                                     VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
7630                                     vector<AttachmentReference>(
7631                                         1, AttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL, inputAttachmentAspectMask)),
7632                                     vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL)),
7633                                     vector<AttachmentReference>(),
7634                                     AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7635                                     vector<uint32_t>()));
7636 
7637                                 deps.push_back(SubpassDependency(
7638                                     0, 1, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
7639                                     vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
7640 
7641                                     vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
7642                                     vk::VK_DEPENDENCY_BY_REGION_BIT));
7643 
7644                                 deps.push_back(SubpassDependency(
7645                                     1, 1, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
7646                                     vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
7647 
7648                                     vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
7649                                     vk::VK_DEPENDENCY_BY_REGION_BIT));
7650 
7651                                 if (useInputAspect)
7652                                 {
7653                                     const VkInputAttachmentAspectReference inputAspect = {1u, 0u,
7654                                                                                           VK_IMAGE_ASPECT_COLOR_BIT};
7655 
7656                                     inputAspects.push_back(inputAspect);
7657                                 }
7658 
7659                                 {
7660                                     const RenderPass renderPass(attachments, subpasses, deps, inputAspects);
7661                                     const TestConfig testConfig(
7662                                         renderPass, renderTypes[renderTypeNdx].types,
7663                                         TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
7664                                         targetSize, renderPos, renderSize, false, 89246, 0,
7665                                         testConfigExternal.allocationKind, testConfigExternal.groupParams);
7666                                     const string testName(string("self_dep_") + renderTypes[renderTypeNdx].str +
7667                                                           (useInputAspect ? "_use_input_aspect" : ""));
7668 
7669                                     addFunctionCaseWithPrograms<TestConfig>(
7670                                         storeOpGroup.get(), testName, createTestShaders, renderPassTest, testConfig);
7671                                 }
7672                             }
7673                         }
7674                     }
7675 
7676                     loadOpGroup->addChild(storeOpGroup.release());
7677                 }
7678 
7679                 inputGroup->addChild(loadOpGroup.release());
7680             }
7681 
7682             formatGroup->addChild(inputGroup.release());
7683         }
7684 
7685         group->addChild(formatGroup.release());
7686     }
7687 
7688     // Depth stencil formats
7689     for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreDepthStencilFormats); formatNdx++)
7690     {
7691         const VkFormat vkFormat         = s_coreDepthStencilFormats[formatNdx];
7692         const tcu::TextureFormat format = mapVkFormat(vkFormat);
7693         const bool isStencilAttachment  = hasStencilComponent(format.order);
7694         const bool isDepthAttachment    = hasDepthComponent(format.order);
7695         const VkImageAspectFlags formatAspectFlags =
7696             (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
7697             (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT : 0u);
7698         de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatToName(vkFormat).c_str()));
7699 
7700         for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
7701         {
7702             const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op;
7703             de::MovePtr<tcu::TestCaseGroup> loadOpGroup(new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str));
7704 
7705             for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
7706             {
7707                 {
7708                     const RenderPass renderPass(
7709                         vector<Attachment>(1, Attachment(vkFormat, VK_SAMPLE_COUNT_1_BIT,
7710                                                          isDepthAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7711                                                          isDepthAttachment ? VK_ATTACHMENT_STORE_OP_STORE :
7712                                                                              VK_ATTACHMENT_STORE_OP_DONT_CARE,
7713                                                          isStencilAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7714                                                          isStencilAttachment ? VK_ATTACHMENT_STORE_OP_STORE :
7715                                                                                VK_ATTACHMENT_STORE_OP_DONT_CARE,
7716                                                          VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7717                                                          VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
7718                         vector<Subpass>(
7719                             1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7720                                        vector<AttachmentReference>(), vector<AttachmentReference>(),
7721                                        AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7722                                        vector<uint32_t>())),
7723                         vector<SubpassDependency>());
7724                     const TestConfig testConfig(renderPass, renderTypes[renderTypeNdx].types,
7725                                                 TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
7726                                                 targetSize, renderPos, renderSize, false, 90239, 0,
7727                                                 testConfigExternal.allocationKind, testConfigExternal.groupParams);
7728 
7729                     addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str,
7730                                                             createTestShaders, renderPassTest, testConfig);
7731                 }
7732 
7733                 if (isStencilAttachment && isDepthAttachment && loadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
7734                 {
7735                     {
7736                         const RenderPass renderPass(
7737                             vector<Attachment>(
7738                                 1, Attachment(vkFormat, VK_SAMPLE_COUNT_1_BIT,
7739                                               isDepthAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7740                                               isDepthAttachment ? VK_ATTACHMENT_STORE_OP_STORE :
7741                                                                   VK_ATTACHMENT_STORE_OP_DONT_CARE,
7742                                               isStencilAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7743                                               isStencilAttachment ? VK_ATTACHMENT_STORE_OP_STORE :
7744                                                                     VK_ATTACHMENT_STORE_OP_DONT_CARE,
7745                                               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7746                                               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
7747                             vector<Subpass>(1,
7748                                             Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7749                                                     vector<AttachmentReference>(), vector<AttachmentReference>(),
7750                                                     AttachmentReference(
7751                                                         0, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL),
7752                                                     vector<uint32_t>())),
7753                             vector<SubpassDependency>());
7754                         const TestConfig testConfig(
7755                             renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE,
7756                             TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7757                             testConfigExternal.allocationKind, testConfigExternal.groupParams);
7758                         const string testName(string(renderTypes[renderTypeNdx].str) + "_depth_read_only");
7759 
7760                         addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), testName, createTestShaders,
7761                                                                 renderPassTest, testConfig);
7762                     }
7763 
7764                     {
7765                         const RenderPass renderPass(
7766                             vector<Attachment>(
7767                                 1, Attachment(vkFormat, VK_SAMPLE_COUNT_1_BIT,
7768                                               isDepthAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7769                                               isDepthAttachment ? VK_ATTACHMENT_STORE_OP_STORE :
7770                                                                   VK_ATTACHMENT_STORE_OP_DONT_CARE,
7771                                               isStencilAttachment ? loadOp : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7772                                               isStencilAttachment ? VK_ATTACHMENT_STORE_OP_STORE :
7773                                                                     VK_ATTACHMENT_STORE_OP_DONT_CARE,
7774                                               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7775                                               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
7776                             vector<Subpass>(1,
7777                                             Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7778                                                     vector<AttachmentReference>(), vector<AttachmentReference>(),
7779                                                     AttachmentReference(
7780                                                         0, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL),
7781                                                     vector<uint32_t>())),
7782                             vector<SubpassDependency>());
7783                         const TestConfig testConfig(
7784                             renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE,
7785                             TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, false, 90239, 0,
7786                             testConfigExternal.allocationKind, testConfigExternal.groupParams);
7787                         const string testName(string(renderTypes[renderTypeNdx].str) + "_stencil_read_only");
7788 
7789                         addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), testName, createTestShaders,
7790                                                                 renderPassTest, testConfig);
7791                     }
7792                 }
7793             }
7794 
7795             formatGroup->addChild(loadOpGroup.release());
7796         }
7797 
7798         {
7799             de::MovePtr<tcu::TestCaseGroup> inputGroup(new tcu::TestCaseGroup(testCtx, "input"));
7800 
7801             for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
7802             {
7803                 const VkAttachmentLoadOp loadOp = loadOps[loadOpNdx].op;
7804                 de::MovePtr<tcu::TestCaseGroup> loadOpGroup(new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str));
7805 
7806                 for (size_t storeOpNdx = 0; storeOpNdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpNdx++)
7807                 {
7808                     const VkImageAspectFlags inputAttachmentAspectMask =
7809                         (testConfigExternal.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2) ?
7810                             formatAspectFlags :
7811                             static_cast<VkImageAspectFlags>(0);
7812                     const VkAttachmentStoreOp storeOp = storeOps[storeOpNdx].op;
7813                     de::MovePtr<tcu::TestCaseGroup> storeOpGroup(
7814                         new tcu::TestCaseGroup(testCtx, storeOps[storeOpNdx].str));
7815 
7816                     for (size_t useInputAspectNdx = 0; useInputAspectNdx < 2; useInputAspectNdx++)
7817                     {
7818                         const bool useInputAspect = useInputAspectNdx != 0;
7819 
7820                         if (testConfigExternal.groupParams->renderingType != RENDERING_TYPE_RENDERPASS_LEGACY &&
7821                             useInputAspect)
7822                             continue;
7823 
7824                         for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
7825                         {
7826                             {
7827                                 vector<Attachment> attachments;
7828                                 vector<Subpass> subpasses;
7829                                 vector<SubpassDependency> deps;
7830                                 vector<VkInputAttachmentAspectReference> inputAspects;
7831 
7832                                 attachments.push_back(Attachment(vkFormat, VK_SAMPLE_COUNT_1_BIT, loadOp, storeOp,
7833                                                                  loadOp, storeOp,
7834                                                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7835                                                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
7836 
7837                                 attachments.push_back(
7838                                     Attachment(vk::VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
7839                                                VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
7840                                                VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7841                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7842                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
7843 
7844                                 subpasses.push_back(
7845                                     Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7846                                             vector<AttachmentReference>(), vector<AttachmentReference>(),
7847                                             AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7848                                             vector<uint32_t>()));
7849                                 subpasses.push_back(
7850                                     Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
7851                                             vector<AttachmentReference>(
7852                                                 1, AttachmentReference(0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
7853                                                                        inputAttachmentAspectMask)),
7854                                             vector<AttachmentReference>(
7855                                                 1, AttachmentReference(1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7856                                             vector<AttachmentReference>(),
7857                                             AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7858                                             vector<uint32_t>()));
7859 
7860                                 deps.push_back(SubpassDependency(0, 1,
7861                                                                  vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
7862                                                                      vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
7863                                                                  vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
7864 
7865                                                                  vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
7866                                                                  vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, 0u));
7867 
7868                                 if (useInputAspect)
7869                                 {
7870                                     const VkInputAttachmentAspectReference inputAspect = {
7871                                         1u, 0u,
7872                                         (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
7873                                             (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT :
7874                                                                    0u)};
7875 
7876                                     inputAspects.push_back(inputAspect);
7877                                 }
7878 
7879                                 {
7880                                     const RenderPass renderPass(attachments, subpasses, deps, inputAspects);
7881                                     const TestConfig testConfig(
7882                                         renderPass, renderTypes[renderTypeNdx].types,
7883                                         TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
7884                                         targetSize, renderPos, renderSize, false, 89246, 0,
7885                                         testConfigExternal.allocationKind, testConfigExternal.groupParams);
7886                                     const string testName(renderTypes[renderTypeNdx].str +
7887                                                           string(useInputAspect ? "_use_input_aspect" : ""));
7888 
7889                                     addFunctionCaseWithPrograms<TestConfig>(
7890                                         storeOpGroup.get(), testName, createTestShaders, renderPassTest, testConfig);
7891                                 }
7892                             }
7893                             {
7894                                 vector<Attachment> attachments;
7895                                 vector<Subpass> subpasses;
7896                                 vector<SubpassDependency> deps;
7897                                 vector<VkInputAttachmentAspectReference> inputAspects;
7898 
7899                                 attachments.push_back(Attachment(
7900                                     vkFormat, VK_SAMPLE_COUNT_1_BIT, loadOp, storeOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
7901                                     VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7902                                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
7903 
7904                                 subpasses.push_back(
7905                                     Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7906                                             vector<AttachmentReference>(), vector<AttachmentReference>(),
7907                                             AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7908                                             vector<uint32_t>()));
7909                                 subpasses.push_back(Subpass(
7910                                     VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
7911                                     vector<AttachmentReference>(
7912                                         1, AttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL, inputAttachmentAspectMask)),
7913                                     vector<AttachmentReference>(), vector<AttachmentReference>(),
7914                                     AttachmentReference(0, VK_IMAGE_LAYOUT_GENERAL), vector<uint32_t>()));
7915 
7916                                 deps.push_back(SubpassDependency(0, 1,
7917                                                                  vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
7918                                                                      vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
7919                                                                  vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
7920 
7921                                                                  vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
7922                                                                  vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
7923                                                                  vk::VK_DEPENDENCY_BY_REGION_BIT));
7924 
7925                                 deps.push_back(SubpassDependency(1, 1,
7926                                                                  vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
7927                                                                      vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
7928                                                                  vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
7929                                                                  vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
7930                                                                  vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
7931                                                                  vk::VK_DEPENDENCY_BY_REGION_BIT));
7932 
7933                                 if (useInputAspect)
7934                                 {
7935                                     const VkInputAttachmentAspectReference inputAspect = {
7936                                         1u, 0u,
7937 
7938                                         (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
7939                                             (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT :
7940                                                                    0u)};
7941 
7942                                     inputAspects.push_back(inputAspect);
7943                                 }
7944 
7945                                 {
7946                                     const RenderPass renderPass(attachments, subpasses, deps, inputAspects);
7947                                     const TestConfig testConfig(
7948                                         renderPass, renderTypes[renderTypeNdx].types,
7949                                         TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
7950                                         targetSize, renderPos, renderSize, false, 89246, 0,
7951                                         testConfigExternal.allocationKind, testConfigExternal.groupParams);
7952                                     const string testName(string("self_dep_") + renderTypes[renderTypeNdx].str +
7953                                                           (useInputAspect ? "_use_input_aspect" : ""));
7954 
7955                                     addFunctionCaseWithPrograms<TestConfig>(
7956                                         storeOpGroup.get(), testName, createTestShaders, renderPassTest, testConfig);
7957                                 }
7958                             }
7959 
7960                             if (isStencilAttachment && isDepthAttachment)
7961                             {
7962                                 // Depth read only
7963                                 {
7964                                     vector<Attachment> attachments;
7965                                     vector<Subpass> subpasses;
7966                                     vector<SubpassDependency> deps;
7967                                     vector<VkInputAttachmentAspectReference> inputAspects;
7968 
7969                                     attachments.push_back(Attachment(vkFormat, VK_SAMPLE_COUNT_1_BIT, loadOp, storeOp,
7970                                                                      loadOp, storeOp,
7971                                                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
7972                                                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
7973 
7974                                     attachments.push_back(
7975                                         Attachment(vk::VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
7976                                                    VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
7977                                                    VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
7978                                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
7979                                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
7980 
7981                                     subpasses.push_back(Subpass(
7982                                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
7983                                         vector<AttachmentReference>(), vector<AttachmentReference>(),
7984                                         AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
7985                                         vector<uint32_t>()));
7986                                     subpasses.push_back(Subpass(
7987                                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
7988                                         vector<AttachmentReference>(
7989                                             1, AttachmentReference(
7990                                                    0, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
7991                                                    inputAttachmentAspectMask)),
7992                                         vector<AttachmentReference>(
7993                                             1, AttachmentReference(1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
7994                                         vector<AttachmentReference>(),
7995                                         AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
7996                                         vector<uint32_t>()));
7997 
7998                                     deps.push_back(SubpassDependency(0, 1,
7999                                                                      vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
8000                                                                          vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
8001                                                                      vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
8002 
8003                                                                      vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
8004                                                                      vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, 0u));
8005 
8006                                     if (useInputAspect)
8007                                     {
8008                                         const VkInputAttachmentAspectReference inputAspect = {
8009                                             1u, 0u,
8010 
8011                                             (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
8012                                                 (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT :
8013                                                                        0u)};
8014 
8015                                         inputAspects.push_back(inputAspect);
8016                                     }
8017 
8018                                     {
8019                                         const RenderPass renderPass(attachments, subpasses, deps, inputAspects);
8020                                         const TestConfig testConfig(
8021                                             renderPass, renderTypes[renderTypeNdx].types,
8022                                             TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
8023                                             targetSize, renderPos, renderSize, false, 89246, 0,
8024                                             testConfigExternal.allocationKind, testConfigExternal.groupParams);
8025                                         const string testName(renderTypes[renderTypeNdx].str +
8026                                                               string(useInputAspect ? "_use_input_aspect" : "") +
8027                                                               "_depth_read_only");
8028 
8029                                         addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName,
8030                                                                                 createTestShaders, renderPassTest,
8031                                                                                 testConfig);
8032                                     }
8033                                 }
8034                                 {
8035                                     vector<Attachment> attachments;
8036                                     vector<Subpass> subpasses;
8037                                     vector<SubpassDependency> deps;
8038                                     vector<VkInputAttachmentAspectReference> inputAspects;
8039 
8040                                     attachments.push_back(Attachment(vkFormat, VK_SAMPLE_COUNT_1_BIT, loadOp, storeOp,
8041                                                                      loadOp, storeOp,
8042                                                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
8043                                                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
8044 
8045                                     subpasses.push_back(Subpass(
8046                                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
8047                                         vector<AttachmentReference>(), vector<AttachmentReference>(),
8048                                         AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
8049                                         vector<uint32_t>()));
8050                                     subpasses.push_back(Subpass(
8051                                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
8052                                         vector<AttachmentReference>(
8053                                             1, AttachmentReference(
8054                                                    0, VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
8055                                                    inputAttachmentAspectMask)),
8056                                         vector<AttachmentReference>(), vector<AttachmentReference>(),
8057                                         AttachmentReference(0,
8058                                                             VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL),
8059                                         vector<uint32_t>()));
8060 
8061                                     deps.push_back(SubpassDependency(0, 1,
8062                                                                      vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
8063                                                                          vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
8064                                                                      vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
8065 
8066                                                                      vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
8067                                                                      vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
8068                                                                      vk::VK_DEPENDENCY_BY_REGION_BIT));
8069 
8070                                     deps.push_back(SubpassDependency(1, 1,
8071                                                                      vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
8072                                                                          vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
8073                                                                      vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
8074 
8075                                                                      vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
8076                                                                      vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
8077                                                                      vk::VK_DEPENDENCY_BY_REGION_BIT));
8078 
8079                                     if (useInputAspect)
8080                                     {
8081                                         const VkInputAttachmentAspectReference inputAspect = {
8082                                             1u, 0u,
8083 
8084                                             (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
8085                                                 (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT :
8086                                                                        0u)};
8087 
8088                                         inputAspects.push_back(inputAspect);
8089                                     }
8090 
8091                                     {
8092                                         const RenderPass renderPass(attachments, subpasses, deps, inputAspects);
8093                                         const TestConfig testConfig(
8094                                             renderPass, renderTypes[renderTypeNdx].types,
8095                                             TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
8096                                             targetSize, renderPos, renderSize, false, 89246, 0,
8097                                             testConfigExternal.allocationKind, testConfigExternal.groupParams);
8098                                         const string testName(string("self_dep_") + renderTypes[renderTypeNdx].str +
8099                                                               (useInputAspect ? "_use_input_aspect" : "") +
8100                                                               "_depth_read_only");
8101 
8102                                         addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName,
8103                                                                                 createTestShaders, renderPassTest,
8104                                                                                 testConfig);
8105                                     }
8106                                 }
8107                                 // Stencil read only
8108                                 {
8109                                     vector<Attachment> attachments;
8110                                     vector<Subpass> subpasses;
8111                                     vector<SubpassDependency> deps;
8112                                     vector<VkInputAttachmentAspectReference> inputAspects;
8113 
8114                                     attachments.push_back(Attachment(vkFormat, VK_SAMPLE_COUNT_1_BIT, loadOp, storeOp,
8115                                                                      loadOp, storeOp,
8116                                                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
8117                                                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
8118 
8119                                     attachments.push_back(
8120                                         Attachment(vk::VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
8121                                                    VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE,
8122                                                    VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
8123                                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
8124                                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
8125 
8126                                     subpasses.push_back(Subpass(
8127                                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
8128                                         vector<AttachmentReference>(), vector<AttachmentReference>(),
8129                                         AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
8130                                         vector<uint32_t>()));
8131                                     subpasses.push_back(Subpass(
8132                                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
8133                                         vector<AttachmentReference>(
8134                                             1, AttachmentReference(
8135                                                    0, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
8136                                                    inputAttachmentAspectMask)),
8137                                         vector<AttachmentReference>(
8138                                             1, AttachmentReference(1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
8139                                         vector<AttachmentReference>(),
8140                                         AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
8141                                         vector<uint32_t>()));
8142 
8143                                     deps.push_back(
8144                                         SubpassDependency(0, 1,
8145                                                           vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
8146                                                               vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
8147                                                               vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
8148                                                           vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
8149 
8150                                                           vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
8151                                                               VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
8152                                                           vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, 0u));
8153 
8154                                     if (useInputAspect)
8155                                     {
8156                                         const VkInputAttachmentAspectReference inputAspect = {
8157                                             1u, 0u,
8158 
8159                                             (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
8160                                                 (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT :
8161                                                                        0u)};
8162 
8163                                         inputAspects.push_back(inputAspect);
8164                                     }
8165 
8166                                     {
8167                                         const RenderPass renderPass(attachments, subpasses, deps, inputAspects);
8168                                         const TestConfig testConfig(
8169                                             renderPass, renderTypes[renderTypeNdx].types,
8170                                             TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
8171                                             targetSize, renderPos, renderSize, false, 89246, 0,
8172                                             testConfigExternal.allocationKind, testConfigExternal.groupParams);
8173                                         const string testName(renderTypes[renderTypeNdx].str +
8174                                                               string(useInputAspect ? "_use_input_aspect" : "") +
8175                                                               "_stencil_read_only");
8176 
8177                                         addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName,
8178                                                                                 createTestShaders, renderPassTest,
8179                                                                                 testConfig);
8180                                     }
8181                                 }
8182                                 {
8183                                     vector<Attachment> attachments;
8184                                     vector<Subpass> subpasses;
8185                                     vector<SubpassDependency> deps;
8186                                     vector<VkInputAttachmentAspectReference> inputAspects;
8187 
8188                                     attachments.push_back(Attachment(vkFormat, VK_SAMPLE_COUNT_1_BIT, loadOp, storeOp,
8189                                                                      loadOp, storeOp,
8190                                                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
8191                                                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
8192 
8193                                     subpasses.push_back(Subpass(
8194                                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(),
8195                                         vector<AttachmentReference>(), vector<AttachmentReference>(),
8196                                         AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
8197                                         vector<uint32_t>()));
8198                                     subpasses.push_back(Subpass(
8199                                         VK_PIPELINE_BIND_POINT_GRAPHICS, 0u,
8200                                         vector<AttachmentReference>(
8201                                             1, AttachmentReference(
8202                                                    0, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
8203                                                    inputAttachmentAspectMask)),
8204                                         vector<AttachmentReference>(), vector<AttachmentReference>(),
8205                                         AttachmentReference(0,
8206                                                             VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL),
8207                                         vector<uint32_t>()));
8208 
8209                                     deps.push_back(SubpassDependency(0, 1,
8210                                                                      vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
8211                                                                          vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
8212                                                                      vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
8213 
8214                                                                      vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
8215                                                                      vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
8216                                                                      vk::VK_DEPENDENCY_BY_REGION_BIT));
8217 
8218                                     deps.push_back(SubpassDependency(1, 1,
8219                                                                      vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
8220                                                                          vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
8221                                                                      vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
8222 
8223                                                                      vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
8224                                                                      vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
8225                                                                      vk::VK_DEPENDENCY_BY_REGION_BIT));
8226 
8227                                     if (useInputAspect)
8228                                     {
8229                                         const VkInputAttachmentAspectReference inputAspect = {
8230                                             1u, 0u,
8231 
8232                                             (isDepthAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT : 0u) |
8233                                                 (isStencilAttachment ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT :
8234                                                                        0u)};
8235 
8236                                         inputAspects.push_back(inputAspect);
8237                                     }
8238 
8239                                     {
8240                                         const RenderPass renderPass(attachments, subpasses, deps, inputAspects);
8241                                         const TestConfig testConfig(
8242                                             renderPass, renderTypes[renderTypeNdx].types,
8243                                             TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT,
8244                                             targetSize, renderPos, renderSize, false, 89246, 0,
8245                                             testConfigExternal.allocationKind, testConfigExternal.groupParams);
8246                                         const string testName(string("self_dep_") + renderTypes[renderTypeNdx].str +
8247                                                               (useInputAspect ? "_use_input_aspect" : "") +
8248                                                               "_stencil_read_only");
8249 
8250                                         addFunctionCaseWithPrograms<TestConfig>(storeOpGroup.get(), testName,
8251                                                                                 createTestShaders, renderPassTest,
8252                                                                                 testConfig);
8253                                     }
8254                                 }
8255                             }
8256                         }
8257                     }
8258 
8259                     loadOpGroup->addChild(storeOpGroup.release());
8260                 }
8261 
8262                 inputGroup->addChild(loadOpGroup.release());
8263             }
8264 
8265             formatGroup->addChild(inputGroup.release());
8266         }
8267 
8268         group->addChild(formatGroup.release());
8269     }
8270 }
8271 
addRenderPassTests(tcu::TestCaseGroup * group,const AllocationKind allocationKind,const SharedGroupParams groupParams)8272 void addRenderPassTests(tcu::TestCaseGroup *group, const AllocationKind allocationKind,
8273                         const SharedGroupParams groupParams)
8274 {
8275     // tests added by this function have both primary and secondary cases and there is no need to repeat them for useSecondaryCmdBuffer flag;
8276     // but cases defined in other files that are later added to those groups in createRenderPassTestsInternal had to be adjusted and run
8277     // for useSecondaryCmdBuffer flag
8278     if (groupParams->useSecondaryCmdBuffer && !groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
8279         return;
8280 
8281     const TestConfigExternal testConfigExternal(allocationKind, groupParams);
8282 
8283     // don't repeat cases that don't use CommandBufferTypes::COMMANDBUFFERTYPES_SECONDARY
8284     if (!groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
8285     {
8286         // Simple basic render pass tests
8287         addTestGroup(group, "simple", addSimpleTests, testConfigExternal);
8288         // Tests for different image formats.
8289         addTestGroup(group, "formats", addFormatTests, testConfigExternal);
8290     }
8291 
8292     // Attachment format and count tests with load and store ops and image layouts
8293     addTestGroup(group, "attachment", addAttachmentTests, testConfigExternal);
8294 
8295     // don't repeat cases that don't use CommandBufferTypes::COMMANDBUFFERTYPES_SECONDARY
8296     if (!groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
8297         // Attachment write mask tests
8298         addTestGroup(group, "attachment_write_mask", addAttachmentWriteMaskTests, testConfigExternal);
8299 
8300     // this tests use many subpasses but when secondaries are tested then each subbpass is recorded to separate secondary command buffer;
8301     // we can't test dynamic_rendering_local_read and at the same time have begin/endRendering in each secondary command buffer
8302     if (!testConfigExternal.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
8303         addTestGroup(group, "attachment_allocation", addAttachmentAllocationTests, testConfigExternal);
8304 }
8305 
createSuballocationTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)8306 de::MovePtr<tcu::TestCaseGroup> createSuballocationTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
8307 {
8308     // Suballocation RenderPass Tests
8309     de::MovePtr<tcu::TestCaseGroup> suballocationTestsGroup(new tcu::TestCaseGroup(testCtx, "suballocation"));
8310 
8311     addRenderPassTests(suballocationTestsGroup.get(), ALLOCATION_KIND_SUBALLOCATED, groupParams);
8312 
8313     return suballocationTestsGroup;
8314 }
8315 
createDedicatedAllocationTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)8316 de::MovePtr<tcu::TestCaseGroup> createDedicatedAllocationTests(tcu::TestContext &testCtx,
8317                                                                const SharedGroupParams groupParams)
8318 {
8319     de::MovePtr<tcu::TestCaseGroup> dedicatedAllocationTestsGroup(
8320         new tcu::TestCaseGroup(testCtx, "dedicated_allocation"));
8321 
8322     addRenderPassTests(dedicatedAllocationTestsGroup.get(), ALLOCATION_KIND_DEDICATED, groupParams);
8323 
8324     return dedicatedAllocationTestsGroup;
8325 }
8326 
createRenderPassTestsInternal(tcu::TestContext & testCtx,const char * groupName,const SharedGroupParams groupParams)8327 tcu::TestCaseGroup *createRenderPassTestsInternal(tcu::TestContext &testCtx, const char *groupName,
8328                                                   const SharedGroupParams groupParams)
8329 {
8330     de::MovePtr<tcu::TestCaseGroup> renderingTests(new tcu::TestCaseGroup(testCtx, groupName));
8331     de::MovePtr<tcu::TestCaseGroup> suballocationTestGroup       = createSuballocationTests(testCtx, groupParams);
8332     de::MovePtr<tcu::TestCaseGroup> dedicatedAllocationTestGroup = createDedicatedAllocationTests(testCtx, groupParams);
8333     de::MovePtr<tcu::TestCaseGroup> noDrawGroup{new tcu::TestCaseGroup{testCtx, "no_draws"}};
8334     const RenderingType renderingType = groupParams->renderingType;
8335 
8336     switch (renderingType)
8337     {
8338     case RENDERING_TYPE_RENDERPASS_LEGACY:
8339 #ifndef CTS_USES_VULKANSC
8340         renderingTests->addChild(createDepthStencilWriteConditionsTests(testCtx));
8341 #endif // CTS_USES_VULKANSC
8342         renderingTests->addChild(createRenderPassMultipleSubpassesMultipleCommandBuffersTests(testCtx));
8343         break;
8344 
8345     case RENDERING_TYPE_RENDERPASS2:
8346 #ifndef CTS_USES_VULKANSC
8347         suballocationTestGroup->addChild(createRenderPassSubpassMergeFeedbackTests(testCtx, renderingType));
8348 #endif // CTS_USES_VULKANSC
8349         renderingTests->addChild(createRenderPass2DepthStencilResolveTests(testCtx));
8350 
8351         break;
8352 
8353 #ifndef CTS_USES_VULKANSC
8354     case RENDERING_TYPE_DYNAMIC_RENDERING:
8355         // we are repeating only some multi-pass tests for pipeline libraries
8356         if (groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
8357             break;
8358 
8359         renderingTests->addChild(createDynamicRenderingDepthStencilResolveTests(testCtx, groupParams));
8360 
8361         // we are repeating some multi-pass tests for secondaries
8362         if (groupParams->useSecondaryCmdBuffer == false)
8363         {
8364             renderingTests->addChild(createDynamicRenderingRandomTests(testCtx));
8365             renderingTests->addChild(createDynamicRenderingBasicTests(testCtx));
8366             renderingTests->addChild(createDynamicRenderingUnusedAttachmentsTests(testCtx, false));
8367             renderingTests->addChild(createDynamicRenderingLocalReadTests(testCtx));
8368         }
8369         else if (!groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
8370         {
8371             renderingTests->addChild(createDynamicRenderingUnusedAttachmentsTests(testCtx, true));
8372         }
8373         break;
8374 #endif // CTS_USES_VULKANSC
8375 
8376     default:
8377         break;
8378     }
8379 
8380     // attachment mapping from dynamic_rendering_local_read can't be used when
8381     // secondary command buffer doesn't compleately contain dynamic renderpass
8382     if ((renderingType != RENDERING_TYPE_DYNAMIC_RENDERING) ||
8383         (groupParams->useSecondaryCmdBuffer == groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass))
8384     {
8385         suballocationTestGroup->addChild(createRenderPassSampleReadTests(testCtx, groupParams));
8386         suballocationTestGroup->addChild(createRenderPassMultisampleTests(testCtx, groupParams));
8387         suballocationTestGroup->addChild(createRenderPassUnusedAttachmentTests(testCtx, groupParams));
8388     }
8389 
8390     suballocationTestGroup->addChild(createRenderPassUnusedAttachmentSparseFillingTests(testCtx, groupParams));
8391     suballocationTestGroup->addChild(createRenderPassSubpassDependencyTests(testCtx, groupParams));
8392     suballocationTestGroup->addChild(createRenderPassMultisampleResolveTests(testCtx, groupParams));
8393 #ifndef CTS_USES_VULKANSC
8394     suballocationTestGroup->addChild(createRenderPassLoadStoreOpNoneTests(testCtx, groupParams));
8395 #endif // CTS_USES_VULKANSC
8396 
8397     if (groupParams->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
8398     {
8399         // repeat only dynamic_rendering_local_read tests for GPL
8400         suballocationTestGroup->addChild(createRenderPassUnusedClearAttachmentTests(testCtx, groupParams));
8401 
8402 #ifndef CTS_USES_VULKANSC
8403         suballocationTestGroup->addChild(createRenderPassSparseRenderTargetTests(testCtx, groupParams));
8404 
8405         renderingTests->addChild(createRenderPassDitheringTests(testCtx, groupParams));
8406         renderingTests->addChild(createFragmentDensityMapTests(testCtx, groupParams));
8407 #endif // CTS_USES_VULKANSC
8408 
8409         if (groupParams->useSecondaryCmdBuffer == false)
8410             noDrawGroup->addChild(
8411                 new RenderPassNoDrawLoadStoreTestCase(testCtx, "no_draw_clear_load_store", groupParams));
8412     }
8413 
8414     renderingTests->addChild(suballocationTestGroup.release());
8415     renderingTests->addChild(dedicatedAllocationTestGroup.release());
8416     renderingTests->addChild(noDrawGroup.release());
8417 
8418     return renderingTests.release();
8419 }
8420 
8421 } // namespace
8422 
createRenderPassTests(tcu::TestContext & testCtx,const std::string & name)8423 tcu::TestCaseGroup *createRenderPassTests(tcu::TestContext &testCtx, const std::string &name)
8424 {
8425     SharedGroupParams groupParams(new GroupParams{
8426         RENDERING_TYPE_RENDERPASS_LEGACY,      // RenderingType renderingType;
8427         false,                                 // bool useSecondaryCmdBuffer;
8428         false,                                 // bool secondaryCmdBufferCompletelyContainsDynamicRenderpass;
8429         PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, // bool useGraphicsPipelineLibrary;
8430     });
8431     return createRenderPassTestsInternal(testCtx, name.c_str(), groupParams);
8432 }
8433 
createRenderPass2Tests(tcu::TestContext & testCtx,const std::string & name)8434 tcu::TestCaseGroup *createRenderPass2Tests(tcu::TestContext &testCtx, const std::string &name)
8435 {
8436     SharedGroupParams groupParams(new GroupParams{
8437         RENDERING_TYPE_RENDERPASS2,            // RenderingType renderingType;
8438         false,                                 // bool useSecondaryCmdBuffer;
8439         false,                                 // bool secondaryCmdBufferCompletelyContainsDynamicRenderpass;
8440         PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, // PipelineConstructionType pipelineConstructionType;
8441     });
8442     return createRenderPassTestsInternal(testCtx, name.c_str(), groupParams);
8443 }
8444 
createDynamicRenderingTests(tcu::TestContext & testCtx,const std::string & name)8445 tcu::TestCaseGroup *createDynamicRenderingTests(tcu::TestContext &testCtx, const std::string &name)
8446 {
8447     // Draw using VK_KHR_dynamic_rendering
8448     de::MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup(new tcu::TestCaseGroup(testCtx, name.c_str()));
8449 
8450     dynamicRenderingGroup->addChild(createRenderPassTestsInternal(
8451         testCtx, "primary_cmd_buff",
8452         SharedGroupParams(new GroupParams{
8453             RENDERING_TYPE_DYNAMIC_RENDERING,      // RenderingType renderingType;
8454             false,                                 // bool useSecondaryCmdBuffer;
8455             false,                                 // bool secondaryCmdBufferCompletelyContainsDynamicRenderpass;
8456             PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, // PipelineConstructionType pipelineConstructionType;
8457         })));
8458     dynamicRenderingGroup->addChild(createRenderPassTestsInternal(
8459         testCtx, "partial_secondary_cmd_buff",
8460         SharedGroupParams(new GroupParams{
8461             RENDERING_TYPE_DYNAMIC_RENDERING,      // RenderingType renderingType;
8462             true,                                  // bool useSecondaryCmdBuffer;
8463             false,                                 // bool secondaryCmdBufferCompletelyContainsDynamicRenderpass;
8464             PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, // PipelineConstructionType pipelineConstructionType;
8465         })));
8466     dynamicRenderingGroup->addChild(createRenderPassTestsInternal(
8467         testCtx, "complete_secondary_cmd_buff",
8468         SharedGroupParams(new GroupParams{
8469             RENDERING_TYPE_DYNAMIC_RENDERING,      // RenderingType renderingType;
8470             true,                                  // bool useSecondaryCmdBuffer;
8471             true,                                  // bool secondaryCmdBufferCompletelyContainsDynamicRenderpass;
8472             PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, // PipelineConstructionType pipelineConstructionType;
8473         })));
8474 
8475     // on some implementations fast-link GPL generates fragment shader epilogs and we need to test this for dynamic_rendering_local_read
8476     dynamicRenderingGroup->addChild(createRenderPassTestsInternal(
8477         testCtx, "graphics_pipeline_library",
8478         SharedGroupParams(new GroupParams{
8479             RENDERING_TYPE_DYNAMIC_RENDERING, // RenderingType renderingType;
8480             false,                            // bool useSecondaryCmdBuffer;
8481             false,                            // bool secondaryCmdBufferCompletelyContainsDynamicRenderpass;
8482             PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY, // PipelineConstructionType pipelineConstructionType;
8483         })));
8484 
8485     return dynamicRenderingGroup.release();
8486 }
8487 
8488 } // namespace vkt
8489