dEQP-VK.renderpass: Set IMAGE_USAGE_TRANSFER_SRC_BIT when needed
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / vktRenderPassTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and/or associated documentation files (the
9  * "Materials"), to deal in the Materials without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Materials, and to
12  * permit persons to whom the Materials are furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice(s) and this permission notice shall be
16  * included in all copies or substantial portions of the Materials.
17  *
18  * The Materials are Confidential Information as defined by the
19  * Khronos Membership Agreement until designated non-confidential by
20  * Khronos, at which point this condition clause shall be removed.
21  *
22  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
29  *
30  *//*!
31  * \file
32  * \brief RenderPass tests
33  *//*--------------------------------------------------------------------*/
34
35 #include "vktRenderPassTests.hpp"
36
37 #include "vktTestCaseUtil.hpp"
38
39 #include "vkDefs.hpp"
40 #include "vkDeviceUtil.hpp"
41 #include "vkImageUtil.hpp"
42 #include "vkMemUtil.hpp"
43 #include "vkPlatform.hpp"
44 #include "vkPrograms.hpp"
45 #include "vkQueryUtil.hpp"
46 #include "vkRef.hpp"
47 #include "vkRefUtil.hpp"
48 #include "vkStrUtil.hpp"
49 #include "vkTypeUtil.hpp"
50
51 #include "tcuTestLog.hpp"
52 #include "tcuResultCollector.hpp"
53 #include "tcuFormatUtil.hpp"
54 #include "tcuTextureUtil.hpp"
55 #include "tcuFloat.hpp"
56 #include "tcuMaybe.hpp"
57 #include "tcuVectorUtil.hpp"
58
59 #include "deUniquePtr.hpp"
60 #include "deSharedPtr.hpp"
61 #include "deStringUtil.hpp"
62 #include "deSTLUtil.hpp"
63 #include "deRandom.hpp"
64
65 #include <limits>
66
67 using namespace vk;
68
69 using tcu::Maybe;
70 using tcu::nothing;
71 using tcu::just;
72 using tcu::TestLog;
73 using tcu::Vec2;
74 using tcu::IVec2;
75 using tcu::UVec2;
76 using tcu::IVec4;
77 using tcu::UVec4;
78 using tcu::Vec4;
79 using tcu::BVec4;
80 using tcu::ConstPixelBufferAccess;
81 using tcu::PixelBufferAccess;
82
83 using de::UniquePtr;
84
85 using std::vector;
86 using std::string;
87
88 namespace vkt
89 {
90 namespace
91 {
92 enum
93 {
94         STENCIL_VALUE = 84u,
95         // Limit integer values that are representable as floats
96         MAX_INTEGER_VALUE = ((1u<<22u)-1u)
97 };
98
99 // Utility functions using flattened structs
100 Move<VkFence> createFence (const DeviceInterface& vk, VkDevice device, VkFenceCreateFlags flags)
101 {
102         const VkFenceCreateInfo pCreateInfo =
103         {
104                 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
105                 DE_NULL,
106
107                 flags
108         };
109         return createFence(vk, device, &pCreateInfo);
110 }
111
112 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&   vk,
113                                                                            VkDevice                                     device,
114                                                                            VkFramebufferCreateFlags     pCreateInfo_flags,
115                                                                            VkRenderPass                         pCreateInfo_renderPass,
116                                                                            deUint32                                     pCreateInfo_attachmentCount,
117                                                                            const VkImageView*           pCreateInfo_pAttachments,
118                                                                            deUint32                                     pCreateInfo_width,
119                                                                            deUint32                                     pCreateInfo_height,
120                                                                            deUint32                                     pCreateInfo_layers)
121 {
122         const VkFramebufferCreateInfo pCreateInfo =
123         {
124                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
125                 DE_NULL,
126                 pCreateInfo_flags,
127                 pCreateInfo_renderPass,
128                 pCreateInfo_attachmentCount,
129                 pCreateInfo_pAttachments,
130                 pCreateInfo_width,
131                 pCreateInfo_height,
132                 pCreateInfo_layers,
133         };
134         return createFramebuffer(vk, device, &pCreateInfo);
135 }
136
137 Move<VkImage> createImage (const DeviceInterface&       vk,
138                                                    VkDevice                                     device,
139                                                    VkImageCreateFlags           pCreateInfo_flags,
140                                                    VkImageType                          pCreateInfo_imageType,
141                                                    VkFormat                                     pCreateInfo_format,
142                                                    VkExtent3D                           pCreateInfo_extent,
143                                                    deUint32                                     pCreateInfo_mipLevels,
144                                                    deUint32                                     pCreateInfo_arrayLayers,
145                                                    VkSampleCountFlagBits        pCreateInfo_samples,
146                                                    VkImageTiling                        pCreateInfo_tiling,
147                                                    VkImageUsageFlags            pCreateInfo_usage,
148                                                    VkSharingMode                        pCreateInfo_sharingMode,
149                                                    deUint32                                     pCreateInfo_queueFamilyCount,
150                                                    const deUint32*                      pCreateInfo_pQueueFamilyIndices,
151                                                    VkImageLayout                        pCreateInfo_initialLayout)
152 {
153         const VkImageCreateInfo pCreateInfo =
154         {
155                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
156                 DE_NULL,
157                 pCreateInfo_flags,
158                 pCreateInfo_imageType,
159                 pCreateInfo_format,
160                 pCreateInfo_extent,
161                 pCreateInfo_mipLevels,
162                 pCreateInfo_arrayLayers,
163                 pCreateInfo_samples,
164                 pCreateInfo_tiling,
165                 pCreateInfo_usage,
166                 pCreateInfo_sharingMode,
167                 pCreateInfo_queueFamilyCount,
168                 pCreateInfo_pQueueFamilyIndices,
169                 pCreateInfo_initialLayout
170         };
171         return createImage(vk, device, &pCreateInfo);
172 }
173
174 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
175 {
176         VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
177 }
178
179 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
180 {
181         VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
182 }
183
184 Move<VkImageView> createImageView (const DeviceInterface&       vk,
185                                                                         VkDevice                                device,
186                                                                         VkImageViewCreateFlags  pCreateInfo_flags,
187                                                                         VkImage                                 pCreateInfo_image,
188                                                                         VkImageViewType                 pCreateInfo_viewType,
189                                                                         VkFormat                                pCreateInfo_format,
190                                                                         VkComponentMapping              pCreateInfo_components,
191                                                                         VkImageSubresourceRange pCreateInfo_subresourceRange)
192 {
193         const VkImageViewCreateInfo pCreateInfo =
194         {
195                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
196                 DE_NULL,
197                 pCreateInfo_flags,
198                 pCreateInfo_image,
199                 pCreateInfo_viewType,
200                 pCreateInfo_format,
201                 pCreateInfo_components,
202                 pCreateInfo_subresourceRange,
203         };
204         return createImageView(vk, device, &pCreateInfo);
205 }
206
207 Move<VkBuffer> createBuffer (const DeviceInterface&     vk,
208                                                          VkDevice                               device,
209                                                          VkBufferCreateFlags    pCreateInfo_flags,
210                                                          VkDeviceSize                   pCreateInfo_size,
211                                                          VkBufferUsageFlags             pCreateInfo_usage,
212                                                          VkSharingMode                  pCreateInfo_sharingMode,
213                                                          deUint32                               pCreateInfo_queueFamilyCount,
214                                                          const deUint32*                pCreateInfo_pQueueFamilyIndices)
215 {
216         const VkBufferCreateInfo pCreateInfo =
217         {
218                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
219                 DE_NULL,
220                 pCreateInfo_flags,
221                 pCreateInfo_size,
222                 pCreateInfo_usage,
223                 pCreateInfo_sharingMode,
224                 pCreateInfo_queueFamilyCount,
225                 pCreateInfo_pQueueFamilyIndices,
226         };
227         return createBuffer(vk, device, &pCreateInfo);
228 }
229
230 Move<VkCommandPool> createCommandPool (const DeviceInterface&   vk,
231                                                                            VkDevice                                     device,
232                                                                            VkCommandPoolCreateFlags     pCreateInfo_flags,
233                                                                            deUint32                                     pCreateInfo_queueFamilyIndex)
234 {
235         const VkCommandPoolCreateInfo pCreateInfo =
236         {
237                 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
238                 DE_NULL,
239                 pCreateInfo_flags,
240                 pCreateInfo_queueFamilyIndex,
241         };
242         return createCommandPool(vk, device, &pCreateInfo);
243 }
244
245 void cmdBeginRenderPass (const DeviceInterface& vk,
246                                                  VkCommandBuffer                cmdBuffer,
247                                                  VkRenderPass                   pRenderPassBegin_renderPass,
248                                                  VkFramebuffer                  pRenderPassBegin_framebuffer,
249                                                  VkRect2D                               pRenderPassBegin_renderArea,
250                                                  deUint32                               pRenderPassBegin_clearValueCount,
251                                                  const VkClearValue*    pRenderPassBegin_pAttachmentClearValues,
252                                                  VkSubpassContents              contents)
253 {
254         const VkRenderPassBeginInfo pRenderPassBegin =
255         {
256                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
257                 DE_NULL,
258                 pRenderPassBegin_renderPass,
259                 pRenderPassBegin_framebuffer,
260                 pRenderPassBegin_renderArea,
261                 pRenderPassBegin_clearValueCount,
262                 pRenderPassBegin_pAttachmentClearValues,
263         };
264         vk.cmdBeginRenderPass(cmdBuffer, &pRenderPassBegin, contents);
265 }
266
267 Move<VkCommandBuffer> allocateCommandBuffer (const DeviceInterface&     vk,
268                                                                                          VkDevice                               device,
269                                                                                          VkCommandPool                  pCreateInfo_commandPool,
270                                                                                          VkCommandBufferLevel   pCreateInfo_level)
271 {
272         const VkCommandBufferAllocateInfo pAllocateInfo =
273         {
274                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
275                 DE_NULL,
276                 pCreateInfo_commandPool,
277                 pCreateInfo_level,
278                 1u,                                                                                             // bufferCount
279         };
280         return allocateCommandBuffer(vk, device, &pAllocateInfo);
281 }
282
283 void beginCommandBuffer (const DeviceInterface&                 vk,
284                                                  VkCommandBuffer                                cmdBuffer,
285                                                  VkCommandBufferUsageFlags              pBeginInfo_flags,
286                                                  VkRenderPass                                   pBeginInfo_renderPass,
287                                                  deUint32                                               pBeginInfo_subpass,
288                                                  VkFramebuffer                                  pBeginInfo_framebuffer,
289                                                  VkBool32                                               pBeginInfo_occlusionQueryEnable,
290                                                  VkQueryControlFlags                    pBeginInfo_queryFlags,
291                                                  VkQueryPipelineStatisticFlags  pBeginInfo_pipelineStatistics)
292 {
293         const VkCommandBufferBeginInfo pBeginInfo =
294         {
295                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
296                 DE_NULL,
297                 pBeginInfo_flags,
298                 pBeginInfo_renderPass,
299                 pBeginInfo_subpass,
300                 pBeginInfo_framebuffer,
301                 pBeginInfo_occlusionQueryEnable,
302                 pBeginInfo_queryFlags,
303                 pBeginInfo_pipelineStatistics,
304         };
305         VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &pBeginInfo));
306 }
307
308 void endCommandBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer)
309 {
310         VK_CHECK(vk.endCommandBuffer(cmdBuffer));
311 }
312
313 void queueSubmit (const DeviceInterface& vk, VkQueue queue, deUint32 cmdBufferCount, const VkCommandBuffer* pCmdBuffers, VkFence fence)
314 {
315         const VkSubmitInfo submitInfo =
316         {
317                 VK_STRUCTURE_TYPE_SUBMIT_INFO,
318                 DE_NULL,
319                 0u,                                                             // waitSemaphoreCount
320                 (const VkSemaphore*)DE_NULL,    // pWaitSemaphores
321                 cmdBufferCount,                                 // commandBufferCount
322                 pCmdBuffers,
323                 0u,                                                             // signalSemaphoreCount
324                 (const VkSemaphore*)DE_NULL,    // pSignalSemaphores
325         };
326         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence));
327 }
328
329 void waitForFences (const DeviceInterface& vk, VkDevice device, deUint32 fenceCount, const VkFence* pFences, VkBool32 waitAll, deUint64 timeout)
330 {
331         VK_CHECK(vk.waitForFences(device, fenceCount, pFences, waitAll, timeout));
332 }
333
334 VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
335 {
336         const tcu::TextureFormat format = mapVkFormat(vkFormat);
337
338         DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21);
339
340         switch (format.order)
341         {
342                 case tcu::TextureFormat::DS:
343                         return VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
344
345                 case tcu::TextureFormat::D:
346                         return VK_IMAGE_ASPECT_DEPTH_BIT;
347
348                 case tcu::TextureFormat::S:
349                         return VK_IMAGE_ASPECT_STENCIL_BIT;
350
351                 default:
352                         return VK_IMAGE_ASPECT_COLOR_BIT;
353         }
354 }
355
356 VkAccessFlags getAllMemoryReadFlags (void)
357 {
358         return VK_ACCESS_TRANSFER_READ_BIT
359                    | VK_ACCESS_UNIFORM_READ_BIT
360                    | VK_ACCESS_HOST_READ_BIT
361                    | VK_ACCESS_INDEX_READ_BIT
362                    | VK_ACCESS_SHADER_READ_BIT
363                    | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
364                    | VK_ACCESS_INDIRECT_COMMAND_READ_BIT
365                    | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
366                    | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
367                    | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
368 }
369
370 VkAccessFlags getAllMemoryWriteFlags (void)
371 {
372         return VK_ACCESS_TRANSFER_WRITE_BIT
373                    | VK_ACCESS_HOST_WRITE_BIT
374                    | VK_ACCESS_SHADER_WRITE_BIT
375                    | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
376                    | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
377 }
378
379 VkPipelineStageFlags getAllPipelineStageFlags (void)
380 {
381         return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
382                    | VK_PIPELINE_STAGE_TRANSFER_BIT
383                    | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
384                    | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
385                    | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
386                    | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
387                    | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
388                    | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
389                    | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
390                    | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
391                    | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
392                    | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
393                    | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
394 }
395
396 class AttachmentReference
397 {
398 public:
399                                         AttachmentReference             (deUint32               attachment,
400                                                                                          VkImageLayout  layout)
401                 : m_attachment  (attachment)
402                 , m_layout              (layout)
403         {
404         }
405
406         deUint32                getAttachment                   (void) const { return m_attachment;     }
407         VkImageLayout   getImageLayout                  (void) const { return m_layout;         }
408
409 private:
410         deUint32                m_attachment;
411         VkImageLayout   m_layout;
412 };
413
414 class Subpass
415 {
416 public:
417                                                                                 Subpass                                         (VkPipelineBindPoint                            pipelineBindPoint,
418                                                                                                                                          VkSubpassDescriptionFlags                      flags,
419                                                                                                                                          const vector<AttachmentReference>&     inputAttachments,
420                                                                                                                                          const vector<AttachmentReference>&     colorAttachments,
421                                                                                                                                          const vector<AttachmentReference>&     resolveAttachments,
422                                                                                                                                          AttachmentReference                            depthStencilAttachment,
423                                                                                                                                          const vector<AttachmentReference>&     preserveAttachments)
424                 : m_pipelineBindPoint           (pipelineBindPoint)
425                 , m_flags                                       (flags)
426                 , m_inputAttachments            (inputAttachments)
427                 , m_colorAttachments            (colorAttachments)
428                 , m_resolveAttachments          (resolveAttachments)
429                 , m_depthStencilAttachment      (depthStencilAttachment)
430                 , m_preserveAttachments         (preserveAttachments)
431         {
432         }
433
434         VkPipelineBindPoint                                     getPipelineBindPoint            (void) const { return m_pipelineBindPoint;              }
435         VkSubpassDescriptionFlags                       getFlags                                        (void) const { return m_flags;                                  }
436         const vector<AttachmentReference>&      getInputAttachments                     (void) const { return m_inputAttachments;               }
437         const vector<AttachmentReference>&      getColorAttachments                     (void) const { return m_colorAttachments;               }
438         const vector<AttachmentReference>&      getResolveAttachments           (void) const { return m_resolveAttachments;             }
439         const AttachmentReference&                      getDepthStencilAttachment       (void) const { return m_depthStencilAttachment; }
440         const vector<AttachmentReference>&      getPreserveAttachments          (void) const { return m_preserveAttachments;    }
441
442 private:
443         VkPipelineBindPoint                                     m_pipelineBindPoint;
444         VkSubpassDescriptionFlags                       m_flags;
445
446         vector<AttachmentReference>                     m_inputAttachments;
447         vector<AttachmentReference>                     m_colorAttachments;
448         vector<AttachmentReference>                     m_resolveAttachments;
449         AttachmentReference                                     m_depthStencilAttachment;
450
451         vector<AttachmentReference>                     m_preserveAttachments;
452 };
453
454 class SubpassDependency
455 {
456 public:
457                                                         SubpassDependency       (deUint32                               srcPass,
458                                                                                                  deUint32                               dstPass,
459
460                                                                                                  VkPipelineStageFlags   srcStageMask,
461                                                                                                  VkPipelineStageFlags   dstStageMask,
462
463                                                                                                  VkAccessFlags                  outputMask,
464                                                                                                  VkAccessFlags                  inputMask,
465
466                                                                                                  VkDependencyFlags              flags)
467                 : m_srcPass                     (srcPass)
468                 , m_dstPass                     (dstPass)
469
470                 , m_srcStageMask        (srcStageMask)
471                 , m_dstStageMask        (dstStageMask)
472
473                 , m_outputMask          (outputMask)
474                 , m_inputMask           (inputMask)
475                 , m_flags                       (flags)
476         {
477         }
478
479         deUint32                                getSrcPass                      (void) const { return m_srcPass;                }
480         deUint32                                getDstPass                      (void) const { return m_dstPass;                }
481
482         VkPipelineStageFlags    getSrcStageMask         (void) const { return m_srcStageMask;   }
483         VkPipelineStageFlags    getDstStageMask         (void) const { return m_dstStageMask;   }
484
485         VkAccessFlags                   getOutputMask           (void) const { return m_outputMask;             }
486         VkAccessFlags                   getInputMask            (void) const { return m_inputMask;              }
487
488         VkDependencyFlags               getFlags                        (void) const { return m_flags;          }
489
490 private:
491         deUint32                                m_srcPass;
492         deUint32                                m_dstPass;
493
494         VkPipelineStageFlags    m_srcStageMask;
495         VkPipelineStageFlags    m_dstStageMask;
496
497         VkAccessFlags                   m_outputMask;
498         VkAccessFlags                   m_inputMask;
499         VkDependencyFlags               m_flags;
500 };
501
502 class Attachment
503 {
504 public:
505                                                 Attachment                      (VkFormat                               format,
506                                                                                          VkSampleCountFlagBits  samples,
507
508                                                                                          VkAttachmentLoadOp             loadOp,
509                                                                                          VkAttachmentStoreOp    storeOp,
510
511                                                                                          VkAttachmentLoadOp             stencilLoadOp,
512                                                                                          VkAttachmentStoreOp    stencilStoreOp,
513
514                                                                                          VkImageLayout                  initialLayout,
515                                                                                          VkImageLayout                  finalLayout)
516                 : m_format                      (format)
517                 , m_samples                     (samples)
518
519                 , m_loadOp                      (loadOp)
520                 , m_storeOp                     (storeOp)
521
522                 , m_stencilLoadOp       (stencilLoadOp)
523                 , m_stencilStoreOp      (stencilStoreOp)
524
525                 , m_initialLayout       (initialLayout)
526                 , m_finalLayout         (finalLayout)
527         {
528         }
529
530         VkFormat                                getFormat                       (void) const { return m_format;                 }
531         VkSampleCountFlagBits   getSamples                      (void) const { return m_samples;                }
532
533         VkAttachmentLoadOp              getLoadOp                       (void) const { return m_loadOp;                 }
534         VkAttachmentStoreOp             getStoreOp                      (void) const { return m_storeOp;                }
535
536
537         VkAttachmentLoadOp              getStencilLoadOp        (void) const { return m_stencilLoadOp;  }
538         VkAttachmentStoreOp             getStencilStoreOp       (void) const { return m_stencilStoreOp; }
539
540         VkImageLayout                   getInitialLayout        (void) const { return m_initialLayout;  }
541         VkImageLayout                   getFinalLayout          (void) const { return m_finalLayout;    }
542
543 private:
544         VkFormat                                m_format;
545         VkSampleCountFlagBits   m_samples;
546
547         VkAttachmentLoadOp              m_loadOp;
548         VkAttachmentStoreOp             m_storeOp;
549
550         VkAttachmentLoadOp              m_stencilLoadOp;
551         VkAttachmentStoreOp             m_stencilStoreOp;
552
553         VkImageLayout                   m_initialLayout;
554         VkImageLayout                   m_finalLayout;
555 };
556
557 class RenderPass
558 {
559 public:
560                                                                                 RenderPass              (const vector<Attachment>&                      attachments,
561                                                                                                                  const vector<Subpass>&                         subpasses,
562                                                                                                                  const vector<SubpassDependency>&       dependencies)
563                 : m_attachments         (attachments)
564                 , m_subpasses           (subpasses)
565                 , m_dependencies        (dependencies)
566         {
567         }
568
569         const vector<Attachment>&                       getAttachments  (void) const { return m_attachments;    }
570         const vector<Subpass>&                          getSubpasses    (void) const { return m_subpasses;              }
571         const vector<SubpassDependency>&        getDependencies (void) const { return m_dependencies;   }
572
573 private:
574         const vector<Attachment>                        m_attachments;
575         const vector<Subpass>                           m_subpasses;
576         const vector<SubpassDependency>         m_dependencies;
577 };
578
579 struct TestConfig
580 {
581         enum RenderTypes
582         {
583                 RENDERTYPES_NONE        = 0,
584                 RENDERTYPES_CLEAR       = (1<<1),
585                 RENDERTYPES_DRAW        = (1<<2)
586         };
587
588         enum CommandBufferTypes
589         {
590                 COMMANDBUFFERTYPES_INLINE               = (1<<0),
591                 COMMANDBUFFERTYPES_SECONDARY    = (1<<1)
592         };
593
594         enum ImageMemory
595         {
596                 IMAGEMEMORY_STRICT              = (1<<0),
597                 IMAGEMEMORY_LAZY                = (1<<1)
598         };
599
600         TestConfig (const RenderPass&   renderPass_,
601                                 RenderTypes                     renderTypes_,
602                                 CommandBufferTypes      commandBufferTypes_,
603                                 ImageMemory                     imageMemory_,
604                                 const UVec2&            targetSize_,
605                                 const UVec2&            renderPos_,
606                                 const UVec2&            renderSize_,
607                                 deUint32                        seed_)
608                 : renderPass                    (renderPass_)
609                 , renderTypes                   (renderTypes_)
610                 , commandBufferTypes    (commandBufferTypes_)
611                 , imageMemory                   (imageMemory_)
612                 , targetSize                    (targetSize_)
613                 , renderPos                             (renderPos_)
614                 , renderSize                    (renderSize_)
615                 , seed                                  (seed_)
616         {
617         }
618
619         RenderPass                      renderPass;
620         RenderTypes                     renderTypes;
621         CommandBufferTypes      commandBufferTypes;
622         ImageMemory                     imageMemory;
623         UVec2                           targetSize;
624         UVec2                           renderPos;
625         UVec2                           renderSize;
626         deUint32                        seed;
627 };
628
629 TestConfig::RenderTypes operator| (TestConfig::RenderTypes a, TestConfig::RenderTypes b)
630 {
631         return (TestConfig::RenderTypes)(((deUint32)a) | ((deUint32)b));
632 }
633
634 TestConfig::CommandBufferTypes operator| (TestConfig::CommandBufferTypes a, TestConfig::CommandBufferTypes b)
635 {
636         return (TestConfig::CommandBufferTypes)(((deUint32)a) | ((deUint32)b));
637 }
638
639 TestConfig::ImageMemory operator| (TestConfig::ImageMemory a, TestConfig::ImageMemory b)
640 {
641         return (TestConfig::ImageMemory)(((deUint32)a) | ((deUint32)b));
642 }
643
644 void logRenderPassInfo (TestLog&                        log,
645                                                 const RenderPass&       renderPass)
646 {
647         const tcu::ScopedLogSection section (log, "RenderPass", "RenderPass");
648
649         {
650                 const tcu::ScopedLogSection     attachmentsSection      (log, "Attachments", "Attachments");
651                 const vector<Attachment>&       attachments                     = renderPass.getAttachments();
652
653                 for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
654                 {
655                         const tcu::ScopedLogSection     attachmentSection       (log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
656                         const Attachment&                       attachment                      = attachments[attachmentNdx];
657
658                         log << TestLog::Message << "Format: " << attachment.getFormat() << TestLog::EndMessage;
659                         log << TestLog::Message << "Samples: " << attachment.getSamples() << TestLog::EndMessage;
660
661                         log << TestLog::Message << "LoadOp: " << attachment.getLoadOp() << TestLog::EndMessage;
662                         log << TestLog::Message << "StoreOp: " << attachment.getStoreOp() << TestLog::EndMessage;
663
664                         log << TestLog::Message << "StencilLoadOp: " << attachment.getStencilLoadOp() << TestLog::EndMessage;
665                         log << TestLog::Message << "StencilStoreOp: " << attachment.getStencilStoreOp() << TestLog::EndMessage;
666
667                         log << TestLog::Message << "InitialLayout: " << attachment.getInitialLayout() << TestLog::EndMessage;
668                         log << TestLog::Message << "FinalLayout: " << attachment.getFinalLayout() << TestLog::EndMessage;
669                 }
670         }
671
672         {
673                 const tcu::ScopedLogSection     subpassesSection        (log, "Subpasses", "Subpasses");
674                 const vector<Subpass>&          subpasses                       = renderPass.getSubpasses();
675
676                 for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
677                 {
678                         const tcu::ScopedLogSection                     subpassSection          (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
679                         const Subpass&                                          subpass                         = subpasses[subpassNdx];
680
681                         const vector<AttachmentReference>&      inputAttachments        = subpass.getInputAttachments();
682                         const vector<AttachmentReference>&      colorAttachments        = subpass.getColorAttachments();
683                         const vector<AttachmentReference>&      resolveAttachments      = subpass.getResolveAttachments();
684                         const vector<AttachmentReference>&      preserveAttachments     = subpass.getPreserveAttachments();
685
686                         if (!inputAttachments.empty())
687                         {
688                                 const tcu::ScopedLogSection             inputAttachmentsSection (log, "Inputs", "Inputs");
689
690                                 for (size_t inputNdx = 0; inputNdx < inputAttachments.size(); inputNdx++)
691                                 {
692                                         const tcu::ScopedLogSection             inputAttachmentSection  (log, "Input" + de::toString(inputNdx), "Input " + de::toString(inputNdx));
693                                         const AttachmentReference&              inputAttachment                 = inputAttachments[inputNdx];
694
695                                         log << TestLog::Message << "Attachment: " << inputAttachment.getAttachment() << TestLog::EndMessage;
696                                         log << TestLog::Message << "Layout: " << inputAttachment.getImageLayout() << TestLog::EndMessage;
697                                 }
698                         }
699
700                         if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
701                         {
702                                 const tcu::ScopedLogSection             depthStencilAttachmentSection   (log, "DepthStencil", "DepthStencil");
703                                 const AttachmentReference&              depthStencilAttachment                  = subpass.getDepthStencilAttachment();
704
705                                 log << TestLog::Message << "Attachment: " << depthStencilAttachment.getAttachment() << TestLog::EndMessage;
706                                 log << TestLog::Message << "Layout: " << depthStencilAttachment.getImageLayout() << TestLog::EndMessage;
707                         }
708
709                         if (!colorAttachments.empty())
710                         {
711                                 const tcu::ScopedLogSection             colorAttachmentsSection (log, "Colors", "Colors");
712
713                                 for (size_t colorNdx = 0; colorNdx < colorAttachments.size(); colorNdx++)
714                                 {
715                                         const tcu::ScopedLogSection             colorAttachmentSection  (log, "Color" + de::toString(colorNdx), "Color " + de::toString(colorNdx));
716                                         const AttachmentReference&              colorAttachment                 = colorAttachments[colorNdx];
717
718                                         log << TestLog::Message << "Attachment: " << colorAttachment.getAttachment() << TestLog::EndMessage;
719                                         log << TestLog::Message << "Layout: " << colorAttachment.getImageLayout() << TestLog::EndMessage;
720                                 }
721                         }
722
723                         if (!resolveAttachments.empty())
724                         {
725                                 const tcu::ScopedLogSection             resolveAttachmentsSection       (log, "Resolves", "Resolves");
726
727                                 for (size_t resolveNdx = 0; resolveNdx < resolveAttachments.size(); resolveNdx++)
728                                 {
729                                         const tcu::ScopedLogSection             resolveAttachmentSection        (log, "Resolve" + de::toString(resolveNdx), "Resolve " + de::toString(resolveNdx));
730                                         const AttachmentReference&              resolveAttachment                       = resolveAttachments[resolveNdx];
731
732                                         log << TestLog::Message << "Attachment: " << resolveAttachment.getAttachment() << TestLog::EndMessage;
733                                         log << TestLog::Message << "Layout: " << resolveAttachment.getImageLayout() << TestLog::EndMessage;
734                                 }
735                         }
736
737                         if (!preserveAttachments.empty())
738                         {
739                                 const tcu::ScopedLogSection             preserveAttachmentsSection      (log, "Preserves", "Preserves");
740
741                                 for (size_t preserveNdx = 0; preserveNdx < preserveAttachments.size(); preserveNdx++)
742                                 {
743                                         const tcu::ScopedLogSection             preserveAttachmentSection       (log, "Preserve" + de::toString(preserveNdx), "Preserve " + de::toString(preserveNdx));
744                                         const AttachmentReference&              preserveAttachment                      = preserveAttachments[preserveNdx];
745
746                                         log << TestLog::Message << "Attachment: " << preserveAttachment.getAttachment() << TestLog::EndMessage;
747                                         log << TestLog::Message << "Layout: " << preserveAttachment.getImageLayout() << TestLog::EndMessage;
748                                 }
749                         }
750                 }
751
752         }
753
754         if (!renderPass.getDependencies().empty())
755         {
756                 const tcu::ScopedLogSection     dependenciesSection     (log, "Dependencies", "Dependencies");
757
758                 for (size_t depNdx = 0; depNdx < renderPass.getDependencies().size(); depNdx++)
759                 {
760                         const tcu::ScopedLogSection     dependencySection       (log, "Dependency" + de::toString(depNdx), "Dependency " + de::toString(depNdx));
761                         const SubpassDependency&        dep                                     = renderPass.getDependencies()[depNdx];
762
763                         log << TestLog::Message << "Source: " << dep.getSrcPass() << TestLog::EndMessage;
764                         log << TestLog::Message << "Destination: " << dep.getDstPass() << TestLog::EndMessage;
765
766                         log << TestLog::Message << "Source Stage Mask: " << dep.getSrcStageMask() << TestLog::EndMessage;
767                         log << TestLog::Message << "Destination Stage Mask: " << dep.getDstStageMask() << TestLog::EndMessage;
768
769                         log << TestLog::Message << "Input Mask: " << dep.getInputMask() << TestLog::EndMessage;
770                         log << TestLog::Message << "Output Mask: " << dep.getOutputMask() << TestLog::EndMessage;
771                         log << TestLog::Message << "Dependency Flags: " << getDependencyFlagsStr(dep.getFlags()) << TestLog::EndMessage;
772                 }
773         }
774 }
775
776 std::string clearColorToString (VkFormat vkFormat, VkClearColorValue value)
777 {
778         const tcu::TextureFormat                format                  = mapVkFormat(vkFormat);
779         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(format.type);
780         const tcu::BVec4                                channelMask             = tcu::getTextureFormatChannelMask(format);
781
782         std::ostringstream                              stream;
783
784         stream << "(";
785
786         switch (channelClass)
787         {
788                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
789                         for (int i = 0; i < 4; i++)
790                         {
791                                 if (i > 0)
792                                         stream << ", ";
793
794                                 if (channelMask[i])
795                                         stream << value.int32[i];
796                                 else
797                                         stream << "Undef";
798                         }
799                         break;
800
801                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
802                         for (int i = 0; i < 4; i++)
803                         {
804                                 if (i > 0)
805                                         stream << ", ";
806
807                                 if (channelMask[i])
808                                         stream << value.uint32[i];
809                                 else
810                                         stream << "Undef";
811                         }
812                         break;
813
814                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
815                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
816                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
817                         for (int i = 0; i < 4; i++)
818                         {
819                                 if (i > 0)
820                                         stream << ", ";
821
822                                 if (channelMask[i])
823                                         stream << value.float32[i];
824                                 else
825                                         stream << "Undef";
826                         }
827                         break;
828
829                 default:
830                         DE_FATAL("Unknown channel class");
831         }
832
833         stream << ")";
834
835         return stream.str();
836 }
837
838 std::string clearValueToString (VkFormat vkFormat, VkClearValue value)
839 {
840         const tcu::TextureFormat        format  = mapVkFormat(vkFormat);
841
842         if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
843         {
844                 std::ostringstream stream;
845
846                 stream << "(";
847
848                 if (tcu::hasStencilComponent(format.order))
849                         stream << "stencil: " << value.depthStencil.stencil;
850
851                 if (tcu::hasStencilComponent(format.order) && tcu::hasDepthComponent(format.order))
852                         stream << ", ";
853
854                 if (tcu::hasDepthComponent(format.order))
855                         stream << "depth: " << value.depthStencil.depth;
856
857                 stream << ")";
858
859                 return stream.str();
860         }
861         else
862                 return clearColorToString(vkFormat, value.color);
863 }
864
865 VkClearColorValue randomColorClearValue (const Attachment& attachment, de::Random& rng)
866 {
867         const float                                             clearNan                = tcu::Float32::nan().asFloat();
868         const tcu::TextureFormat                format                  = mapVkFormat(attachment.getFormat());
869         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(format.type);
870         const tcu::BVec4                                channelMask             = tcu::getTextureFormatChannelMask(format);
871         VkClearColorValue                               clearColor;
872
873         switch (channelClass)
874         {
875                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
876                 {
877                         const tcu::IVec4 valueMin = tcu::getFormatMinIntValue(format);
878                         const tcu::IVec4 valueMax = tcu::getFormatMaxIntValue(format);
879
880                         for (int ndx = 0; ndx < 4; ndx++)
881                         {
882                                 if (!channelMask[ndx])
883                                         clearColor.int32[ndx] = std::numeric_limits<deInt32>::min();
884                                 else
885                                         clearColor.uint32[ndx] = rng.getInt(valueMin[ndx], valueMax[ndx]);
886                         }
887                         break;
888                 }
889
890                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
891                 {
892                         const UVec4 valueMax = tcu::getFormatMaxUintValue(format);
893
894                         for (int ndx = 0; ndx < 4; ndx++)
895                         {
896                                 if (!channelMask[ndx])
897                                         clearColor.uint32[ndx] = std::numeric_limits<deUint32>::max();
898                                 else
899                                         clearColor.uint32[ndx] = rng.getUint32() % valueMax[ndx];
900                         }
901                         break;
902                 }
903
904                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
905                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
906                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
907                 {
908                         const tcu::TextureFormatInfo    formatInfo              = tcu::getTextureFormatInfo(format);
909
910                         for (int ndx = 0; ndx < 4; ndx++)
911                         {
912                                 if (!channelMask[ndx])
913                                         clearColor.float32[ndx] = clearNan;
914                                 else
915                                         clearColor.float32[ndx] = formatInfo.valueMin[ndx] + rng.getFloat() * (formatInfo.valueMax[ndx] - formatInfo.valueMin[ndx]);
916                         }
917                         break;
918                 }
919
920                 default:
921                         DE_FATAL("Unknown channel class");
922         }
923
924         return clearColor;
925 }
926
927 VkAttachmentDescription createAttachmentDescription (const Attachment& attachment)
928 {
929         const VkAttachmentDescription attachmentDescription =
930         {
931                 0,                                                                                      // flags
932
933                 attachment.getFormat(),                                         // format
934                 attachment.getSamples(),                                        // samples
935
936                 attachment.getLoadOp(),                                         // loadOp
937                 attachment.getStoreOp(),                                        // storeOp
938
939                 attachment.getStencilLoadOp(),                          // stencilLoadOp
940                 attachment.getStencilStoreOp(),                         // stencilStoreOp
941
942                 attachment.getInitialLayout(),                          // initialLayout
943                 attachment.getFinalLayout(),                            // finalLayout
944         };
945
946         return attachmentDescription;
947 }
948
949 VkAttachmentReference createAttachmentReference (const AttachmentReference& referenceInfo)
950 {
951         const VkAttachmentReference reference =
952         {
953                 referenceInfo.getAttachment(),  // attachment;
954                 referenceInfo.getImageLayout()  // layout;
955         };
956
957         return reference;
958 }
959
960 VkSubpassDescription createSubpassDescription (const Subpass&                                   subpass,
961                                                                                            vector<VkAttachmentReference>*       attachmentReferenceLists)
962 {
963         vector<VkAttachmentReference>&  inputAttachmentReferences                       = attachmentReferenceLists[0];
964         vector<VkAttachmentReference>&  colorAttachmentReferences                       = attachmentReferenceLists[1];
965         vector<VkAttachmentReference>&  resolveAttachmentReferences                     = attachmentReferenceLists[2];
966         vector<VkAttachmentReference>&  depthStencilAttachmentReferences        = attachmentReferenceLists[3];
967         vector<VkAttachmentReference>&  preserveAttachmentReferences            = attachmentReferenceLists[4];
968
969         for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
970                 colorAttachmentReferences.push_back(createAttachmentReference(subpass.getColorAttachments()[attachmentNdx]));
971
972         for (size_t attachmentNdx = 0; attachmentNdx < subpass.getInputAttachments().size(); attachmentNdx++)
973                 inputAttachmentReferences.push_back(createAttachmentReference(subpass.getInputAttachments()[attachmentNdx]));
974
975         for (size_t attachmentNdx = 0; attachmentNdx < subpass.getResolveAttachments().size(); attachmentNdx++)
976                 resolveAttachmentReferences.push_back(createAttachmentReference(subpass.getResolveAttachments()[attachmentNdx]));
977
978         depthStencilAttachmentReferences.push_back(createAttachmentReference(subpass.getDepthStencilAttachment()));
979
980         for (size_t attachmentNdx = 0; attachmentNdx < subpass.getPreserveAttachments().size(); attachmentNdx++)
981                 preserveAttachmentReferences.push_back(createAttachmentReference(subpass.getPreserveAttachments()[attachmentNdx]));
982
983         DE_ASSERT(resolveAttachmentReferences.empty() || colorAttachmentReferences.size() == resolveAttachmentReferences.size());
984
985         {
986                 const VkSubpassDescription subpassDescription =
987                 {
988                         subpass.getFlags(),                                                                                                                                     // flags;
989                         subpass.getPipelineBindPoint(),                                                                                                         // pipelineBindPoint;
990
991                         (deUint32)inputAttachmentReferences.size(),                                                                                     // inputCount;
992                         inputAttachmentReferences.empty() ? DE_NULL : &inputAttachmentReferences[0],            // inputAttachments;
993
994                         (deUint32)colorAttachmentReferences.size(),                                                                                     // colorCount;
995                         colorAttachmentReferences.empty() ? DE_NULL :  &colorAttachmentReferences[0],           // colorAttachments;
996                         resolveAttachmentReferences.empty() ? DE_NULL : &resolveAttachmentReferences[0],        // resolveAttachments;
997
998                         &depthStencilAttachmentReferences[0],                                                                                           // pDepthStencilAttachment;
999                         (deUint32)preserveAttachmentReferences.size(),                                                                          // preserveCount;
1000                         preserveAttachmentReferences.empty() ? DE_NULL : &preserveAttachmentReferences[0]       // preserveAttachments;
1001                 };
1002
1003                 return subpassDescription;
1004         }
1005 }
1006
1007 VkSubpassDependency createSubpassDependency     (const SubpassDependency& dependencyInfo)
1008 {
1009         const VkSubpassDependency dependency =
1010         {
1011                 dependencyInfo.getSrcPass(),                    // srcSubpass;
1012                 dependencyInfo.getDstPass(),                    // destSubpass;
1013
1014                 dependencyInfo.getSrcStageMask(),               // srcStageMask;
1015                 dependencyInfo.getDstStageMask(),               // destStageMask;
1016
1017                 dependencyInfo.getOutputMask(),                 // outputMask;
1018                 dependencyInfo.getInputMask(),                  // inputMask;
1019
1020                 dependencyInfo.getFlags()                               // dependencyFlags;
1021         };
1022
1023         return dependency;
1024 }
1025
1026 Move<VkRenderPass> createRenderPass (const DeviceInterface&     vk,
1027                                                                          VkDevice                               device,
1028                                                                          const RenderPass&              renderPassInfo)
1029 {
1030         const size_t                                                    perSubpassAttachmentReferenceLists = 5;
1031         vector<VkAttachmentDescription>                 attachments;
1032         vector<VkSubpassDescription>                    subpasses;
1033         vector<VkSubpassDependency>                             dependencies;
1034         vector<vector<VkAttachmentReference> >  attachmentReferenceLists(renderPassInfo.getSubpasses().size() * perSubpassAttachmentReferenceLists);
1035
1036         for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
1037                 attachments.push_back(createAttachmentDescription(renderPassInfo.getAttachments()[attachmentNdx]));
1038
1039         for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
1040                 subpasses.push_back(createSubpassDescription(renderPassInfo.getSubpasses()[subpassNdx], &(attachmentReferenceLists[subpassNdx * perSubpassAttachmentReferenceLists])));
1041
1042         for (size_t depNdx = 0; depNdx < renderPassInfo.getDependencies().size(); depNdx++)
1043                 dependencies.push_back(createSubpassDependency(renderPassInfo.getDependencies()[depNdx]));
1044
1045         {
1046                 const VkRenderPassCreateInfo    createInfo      =
1047                 {
1048                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1049                         DE_NULL,
1050                         (VkRenderPassCreateFlags)0u,
1051                         (deUint32)attachments.size(),
1052                         (attachments.empty() ? DE_NULL : &attachments[0]),
1053                         (deUint32)subpasses.size(),
1054                         (subpasses.empty() ? DE_NULL : &subpasses[0]),
1055                         (deUint32)dependencies.size(),
1056                         (dependencies.empty() ? DE_NULL : &dependencies[0])
1057                 };
1058
1059                 return createRenderPass(vk, device, &createInfo);
1060         }
1061 }
1062
1063 Move<VkFramebuffer> createFramebuffer (const DeviceInterface&           vk,
1064                                                                            VkDevice                                             device,
1065                                                                            VkRenderPass                                 renderPass,
1066                                                                            const UVec2&                                 size,
1067                                                                            const vector<VkImageView>&   attachments)
1068 {
1069         return createFramebuffer(vk, device, 0u, renderPass, (deUint32)attachments.size(), attachments.empty() ? DE_NULL : &attachments[0], size.x(), size.y(), 1u);
1070 }
1071
1072 Move<VkImage> createAttachmentImage (const DeviceInterface&     vk,
1073                                                                          VkDevice                               device,
1074                                                                          deUint32                               queueIndex,
1075                                                                          const UVec2&                   size,
1076                                                                          VkFormat                               format,
1077                                                                          VkSampleCountFlagBits  samples,
1078                                                                          VkImageUsageFlags              usageFlags,
1079                                                                          VkImageLayout                  layout)
1080 {
1081         const VkExtent3D size_                                  = { (deInt32)size.x(), (deInt32)size.y(), 1 };
1082         VkImageUsageFlags targetUsageFlags              = 0;
1083         const tcu::TextureFormat textureFormat  = mapVkFormat(format);
1084
1085         if (tcu::hasDepthComponent(textureFormat.order) || tcu::hasStencilComponent(textureFormat.order))
1086         {
1087                 targetUsageFlags |= vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1088         }
1089         else
1090         {
1091                 targetUsageFlags |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1092         }
1093
1094         return createImage(vk, device,
1095                                            (VkImageCreateFlags)0,
1096                                            VK_IMAGE_TYPE_2D,
1097                                            format,
1098                                            size_,
1099                                            1u /* mipLevels */,
1100                                            1u /* arraySize */,
1101                                            samples,
1102                                            VK_IMAGE_TILING_OPTIMAL,
1103                                            usageFlags | targetUsageFlags,
1104                                            VK_SHARING_MODE_EXCLUSIVE,
1105                                            1,
1106                                            &queueIndex,
1107                                            layout);
1108 }
1109
1110 de::MovePtr<Allocation> createImageMemory (const DeviceInterface&       vk,
1111                                                                                    VkDevice                                     device,
1112                                                                                    Allocator&                           allocator,
1113                                                                                    VkImage                                      image,
1114                                                                                    bool                                         lazy)
1115 {
1116         de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), lazy ? MemoryRequirement::LazilyAllocated : MemoryRequirement::Any));
1117         bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
1118         return allocation;
1119 }
1120
1121 Move<VkImageView> createImageAttachmentView (const DeviceInterface&     vk,
1122                                                                                          VkDevice                               device,
1123                                                                                          VkImage                                image,
1124                                                                                          VkFormat                               format,
1125                                                                                          VkImageAspectFlags             aspect)
1126 {
1127         const VkImageSubresourceRange range =
1128         {
1129                 aspect,
1130                 0,
1131                 1,
1132                 0,
1133                 1
1134         };
1135
1136         return createImageView(vk, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
1137 }
1138
1139 VkClearValue randomClearValue (const Attachment& attachment, de::Random& rng)
1140 {
1141         const float                                     clearNan        = tcu::Float32::nan().asFloat();
1142         const tcu::TextureFormat        format          = mapVkFormat(attachment.getFormat());
1143
1144         if (tcu::hasStencilComponent(format.order) || tcu::hasDepthComponent(format.order))
1145         {
1146                 VkClearValue clearValue;
1147
1148                 clearValue.depthStencil.depth   = clearNan;
1149                 clearValue.depthStencil.stencil = 255;
1150
1151                 if (tcu::hasStencilComponent(format.order))
1152                         clearValue.depthStencil.stencil = rng.getInt(0, 255);
1153
1154                 if (tcu::hasDepthComponent(format.order))
1155                         clearValue.depthStencil.depth   = rng.getFloat();
1156
1157                 return clearValue;
1158         }
1159         else
1160         {
1161                 VkClearValue clearValue;
1162
1163                 clearValue.color = randomColorClearValue(attachment, rng);
1164
1165                 return clearValue;
1166         }
1167 }
1168
1169 class AttachmentResources
1170 {
1171 public:
1172         AttachmentResources (const DeviceInterface&             vk,
1173                                                  VkDevice                                       device,
1174                                                  Allocator&                                     allocator,
1175                                                  deUint32                                       queueIndex,
1176                                                  const UVec2&                           size,
1177                                                  const Attachment&                      attachmentInfo,
1178                                                  bool                                           lazy)
1179                 : m_image                       (createAttachmentImage(vk, device, queueIndex, size, attachmentInfo.getFormat(), attachmentInfo.getSamples(), lazy ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_UNDEFINED))
1180                 , m_imageMemory         (createImageMemory(vk, device, allocator, *m_image, lazy))
1181                 , m_attachmentView      (createImageAttachmentView(vk, device, *m_image, attachmentInfo.getFormat(), getImageAspectFlags(attachmentInfo.getFormat())))
1182         {
1183                 if (!lazy)
1184                 {
1185                         const tcu::TextureFormat format = mapVkFormat(attachmentInfo.getFormat());
1186
1187                         if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
1188                         {
1189                                 const tcu::TextureFormat        depthFormat             = getDepthCopyFormat(attachmentInfo.getFormat());
1190                                 const tcu::TextureFormat        stencilFormat   = getStencilCopyFormat(attachmentInfo.getFormat());
1191
1192                                 m_bufferSize                    = size.x() * size.y() * depthFormat.getPixelSize();
1193                                 m_secondaryBufferSize   = size.x() * size.y() * stencilFormat.getPixelSize();
1194
1195                                 m_buffer                                = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1196                                 m_bufferMemory                  = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
1197
1198                                 bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
1199
1200                                 m_secondaryBuffer               = createBuffer(vk, device, 0, m_secondaryBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1201                                 m_secondaryBufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_secondaryBuffer), MemoryRequirement::HostVisible);
1202
1203                                 bindBufferMemory(vk, device, *m_secondaryBuffer, m_secondaryBufferMemory->getMemory(), m_secondaryBufferMemory->getOffset());
1204                         }
1205                         else
1206                         {
1207                                 m_bufferSize    = size.x() * size.y() * format.getPixelSize();
1208
1209                                 m_buffer                = createBuffer(vk, device, 0, m_bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 1, &queueIndex);
1210                                 m_bufferMemory  = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), MemoryRequirement::HostVisible);
1211
1212                                 bindBufferMemory(vk, device, *m_buffer, m_bufferMemory->getMemory(), m_bufferMemory->getOffset());
1213                         }
1214                 }
1215         }
1216
1217         ~AttachmentResources (void)
1218         {
1219         }
1220
1221         VkImageView getAttachmentView (void) const
1222         {
1223                 return *m_attachmentView;
1224         }
1225
1226         VkImage getImage (void) const
1227         {
1228                 return *m_image;
1229         }
1230
1231         VkBuffer getBuffer (void) const
1232         {
1233                 DE_ASSERT(*m_buffer != DE_NULL);
1234                 return *m_buffer;
1235         }
1236
1237         VkDeviceSize getBufferSize (void) const
1238         {
1239                 DE_ASSERT(*m_buffer != DE_NULL);
1240                 return m_bufferSize;
1241         }
1242
1243         const Allocation& getResultMemory (void) const
1244         {
1245                 DE_ASSERT(m_bufferMemory);
1246                 return *m_bufferMemory;
1247         }
1248
1249         VkBuffer getSecondaryBuffer (void) const
1250         {
1251                 DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1252                 return *m_secondaryBuffer;
1253         }
1254
1255         VkDeviceSize getSecondaryBufferSize (void) const
1256         {
1257                 DE_ASSERT(*m_secondaryBuffer != DE_NULL);
1258                 return m_secondaryBufferSize;
1259         }
1260
1261         const Allocation& getSecondaryResultMemory (void) const
1262         {
1263                 DE_ASSERT(m_secondaryBufferMemory);
1264                 return *m_secondaryBufferMemory;
1265         }
1266
1267 private:
1268         const Unique<VkImage>                   m_image;
1269         const UniquePtr<Allocation>             m_imageMemory;
1270         const Unique<VkImageView>               m_attachmentView;
1271
1272         Move<VkBuffer>                                  m_buffer;
1273         VkDeviceSize                                    m_bufferSize;
1274         de::MovePtr<Allocation>                 m_bufferMemory;
1275
1276         Move<VkBuffer>                                  m_secondaryBuffer;
1277         VkDeviceSize                                    m_secondaryBufferSize;
1278         de::MovePtr<Allocation>                 m_secondaryBufferMemory;
1279 };
1280
1281 void uploadBufferData (const DeviceInterface&   vk,
1282                                            VkDevice                                     device,
1283                                            const Allocation&            memory,
1284                                            size_t                                       size,
1285                                            const void*                          data)
1286 {
1287         const VkMappedMemoryRange range =
1288         {
1289                 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,  // sType;
1290                 DE_NULL,                                                                // pNext;
1291                 memory.getMemory(),                                             // mem;
1292                 memory.getOffset(),                                             // offset;
1293                 (VkDeviceSize)size                                              // size;
1294         };
1295         void* const ptr = memory.getHostPtr();
1296
1297         deMemcpy(ptr, data, size);
1298         VK_CHECK(vk.flushMappedMemoryRanges(device, 1, &range));
1299 }
1300
1301 VkImageAspectFlagBits getPrimaryImageAspect (tcu::TextureFormat::ChannelOrder order)
1302 {
1303         DE_STATIC_ASSERT(tcu::TextureFormat::CHANNELORDER_LAST == 21);
1304
1305         switch (order)
1306         {
1307                 case tcu::TextureFormat::D:
1308                 case tcu::TextureFormat::DS:
1309                         return VK_IMAGE_ASPECT_DEPTH_BIT;
1310
1311                 case tcu::TextureFormat::S:
1312                         return VK_IMAGE_ASPECT_STENCIL_BIT;
1313
1314                 default:
1315                         return VK_IMAGE_ASPECT_COLOR_BIT;
1316         }
1317 }
1318
1319 class RenderQuad
1320 {
1321 public:
1322         RenderQuad (const Vec4& posA, const Vec4& posB)
1323                 : m_vertices(6)
1324         {
1325                 m_vertices[0] = posA;
1326                 m_vertices[1] = Vec4(posA[0], posB[1], posA[2], posA[3]);
1327                 m_vertices[2] = posB;
1328
1329                 m_vertices[3] = posB;
1330                 m_vertices[4] = Vec4(posB[0], posA[1], posB[2], posA[3]);
1331                 m_vertices[5] = posA;
1332         }
1333
1334         const Vec4&             getCornerA                      (void) const
1335         {
1336                 return m_vertices[0];
1337         }
1338
1339         const Vec4&             getCornerB                      (void) const
1340         {
1341                 return m_vertices[2];
1342         }
1343
1344         const void*             getVertexPointer        (void) const
1345         {
1346                 return &m_vertices[0];
1347         }
1348
1349         size_t                  getVertexDataSize       (void) const
1350         {
1351                 return sizeof(Vec4) * m_vertices.size();
1352         }
1353
1354 private:
1355         vector<Vec4>    m_vertices;
1356 };
1357
1358 class ColorClear
1359 {
1360 public:
1361         ColorClear      (const UVec2&                           offset,
1362                                  const UVec2&                           size,
1363                                  const VkClearColorValue&       color)
1364                 : m_offset      (offset)
1365                 , m_size        (size)
1366                 , m_color       (color)
1367         {
1368         }
1369
1370         const UVec2&                            getOffset               (void) const { return m_offset;         }
1371         const UVec2&                            getSize                 (void) const { return m_size;           }
1372         const VkClearColorValue&        getColor                (void) const { return m_color;          }
1373
1374 private:
1375         UVec2                           m_offset;
1376         UVec2                           m_size;
1377         VkClearColorValue       m_color;
1378 };
1379
1380 class DepthStencilClear
1381 {
1382 public:
1383         DepthStencilClear       (const UVec2&                           offset,
1384                                                  const UVec2&                           size,
1385                                                  float                                          depth,
1386                                                  deUint32                                       stencil)
1387                 : m_offset      (offset)
1388                 , m_size        (size)
1389                 , m_depth       (depth)
1390                 , m_stencil     (stencil)
1391         {
1392         }
1393
1394         const UVec2&            getOffset               (void) const { return m_offset;         }
1395         const UVec2&            getSize                 (void) const { return m_size;           }
1396         float                           getDepth                (void) const { return m_depth;          }
1397         deUint32                        getStencil              (void) const { return m_stencil;        }
1398
1399 private:
1400         UVec2                           m_offset;
1401         UVec2                           m_size;
1402
1403         float                           m_depth;
1404         deUint32                        m_stencil;
1405 };
1406
1407 class SubpassRenderInfo
1408 {
1409 public:
1410         SubpassRenderInfo       (const RenderPass&                                      renderPass,
1411                                                  deUint32                                                       subpassIndex,
1412
1413                                                  bool                                                           isSecondary_,
1414
1415                                                  const UVec2&                                           viewportOffset,
1416                                                  const UVec2&                                           viewportSize,
1417
1418                                                  const Maybe<RenderQuad>&                       renderQuad,
1419                                                  const vector<ColorClear>&                      colorClears,
1420                                                  const Maybe<DepthStencilClear>&        depthStencilClear)
1421                 : m_viewportOffset              (viewportOffset)
1422                 , m_viewportSize                (viewportSize)
1423                 , m_subpassIndex                (subpassIndex)
1424                 , m_isSecondary                 (isSecondary_)
1425                 , m_flags                               (renderPass.getSubpasses()[subpassIndex].getFlags())
1426                 , m_renderQuad                  (renderQuad)
1427                 , m_colorClears                 (colorClears)
1428                 , m_depthStencilClear   (depthStencilClear)
1429                 , m_colorAttachments    (renderPass.getSubpasses()[subpassIndex].getColorAttachments())
1430         {
1431                 for (deUint32 attachmentNdx = 0; attachmentNdx < (deUint32)m_colorAttachments.size(); attachmentNdx++)
1432                         m_colorAttachmentInfo.push_back(renderPass.getAttachments()[m_colorAttachments[attachmentNdx].getAttachment()]);
1433
1434                 if (renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
1435                 {
1436                         m_depthStencilAttachment                = tcu::just(renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment());
1437                         m_depthStencilAttachmentInfo    = tcu::just(renderPass.getAttachments()[renderPass.getSubpasses()[subpassIndex].getDepthStencilAttachment().getAttachment()]);
1438                 }
1439         }
1440
1441         const UVec2&                                            getViewportOffset                               (void) const { return m_viewportOffset;         }
1442         const UVec2&                                            getViewportSize                                 (void) const { return m_viewportSize;           }
1443
1444         deUint32                                                        getSubpassIndex                                 (void) const { return m_subpassIndex;           }
1445         bool                                                            isSecondary                                             (void) const { return m_isSecondary;            }
1446
1447         const Maybe<RenderQuad>&                        getRenderQuad                                   (void) const { return m_renderQuad;                     }
1448         const vector<ColorClear>&                       getColorClears                                  (void) const { return m_colorClears;            }
1449         const Maybe<DepthStencilClear>&         getDepthStencilClear                    (void) const { return m_depthStencilClear;      }
1450
1451         deUint32                                                        getColorAttachmentCount                 (void) const { return (deUint32)m_colorAttachments.size(); }
1452         VkImageLayout                                           getColorAttachmentLayout                (deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getImageLayout(); }
1453         deUint32                                                        getColorAttachmentIndex                 (deUint32 attachmentNdx) const { return m_colorAttachments[attachmentNdx].getAttachment(); }
1454         const Attachment&                                       getColorAttachment                              (deUint32 attachmentNdx) const { return m_colorAttachmentInfo[attachmentNdx]; }
1455         Maybe<VkImageLayout>                            getDepthStencilAttachmentLayout (void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getImageLayout()) : tcu::nothing<VkImageLayout>(); }
1456         Maybe<deUint32>                                         getDepthStencilAttachmentIndex  (void) const { return m_depthStencilAttachment ? tcu::just(m_depthStencilAttachment->getAttachment()) : tcu::nothing<deUint32>(); };
1457         const Maybe<Attachment>&                        getDepthStencilAttachment               (void) const { return m_depthStencilAttachmentInfo; }
1458         VkSubpassDescriptionFlags                       getSubpassFlags                                 (void) const { return m_flags; }
1459 private:
1460         UVec2                                                           m_viewportOffset;
1461         UVec2                                                           m_viewportSize;
1462
1463         deUint32                                                        m_subpassIndex;
1464         bool                                                            m_isSecondary;
1465         VkSubpassDescriptionFlags                       m_flags;
1466
1467         Maybe<RenderQuad>                                       m_renderQuad;
1468         vector<ColorClear>                                      m_colorClears;
1469         Maybe<DepthStencilClear>                        m_depthStencilClear;
1470
1471         vector<AttachmentReference>                     m_colorAttachments;
1472         vector<Attachment>                                      m_colorAttachmentInfo;
1473
1474         Maybe<AttachmentReference>                      m_depthStencilAttachment;
1475         Maybe<Attachment>                                       m_depthStencilAttachmentInfo;
1476 };
1477
1478 Move<VkPipeline> createSubpassPipeline (const DeviceInterface&          vk,
1479                                                                                 VkDevice                                        device,
1480                                                                                 VkRenderPass                            renderPass,
1481                                                                                 VkShaderModule                          vertexShaderModule,
1482                                                                                 VkShaderModule                          fragmentShaderModule,
1483                                                                                 VkPipelineLayout                        pipelineLayout,
1484                                                                                 const SubpassRenderInfo&        renderInfo)
1485 {
1486         const VkSpecializationInfo emptyShaderSpecializations =
1487         {
1488                 0u,                     // mapEntryCount
1489                 DE_NULL,        // pMap
1490                 0u,                     // dataSize
1491                 DE_NULL,        // pData
1492         };
1493
1494         Maybe<VkSampleCountFlagBits>                            rasterSamples;
1495         vector<VkPipelineColorBlendAttachmentState>     attachmentBlendStates;
1496
1497         for (deUint32 attachmentNdx = 0; attachmentNdx < renderInfo.getColorAttachmentCount(); attachmentNdx++)
1498         {
1499                 const Attachment&                       attachment              = renderInfo.getColorAttachment(attachmentNdx);
1500
1501                 DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
1502
1503                 rasterSamples = attachment.getSamples();
1504
1505                 {
1506                         const VkPipelineColorBlendAttachmentState       attachmentBlendState =
1507                         {
1508                                 VK_FALSE,                                                                                                                                                                                               // blendEnable
1509                                 VK_BLEND_FACTOR_SRC_ALPHA,                                                                                                                                                              // srcBlendColor
1510                                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,                                                                                                                                    // destBlendColor
1511                                 VK_BLEND_OP_ADD,                                                                                                                                                                                // blendOpColor
1512                                 VK_BLEND_FACTOR_ONE,                                                                                                                                                                    // srcBlendAlpha
1513                                 VK_BLEND_FACTOR_ONE,                                                                                                                                                                    // destBlendAlpha
1514                                 VK_BLEND_OP_ADD,                                                                                                                                                                                // blendOpAlpha
1515                                 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT,    // channelWriteMask
1516                         };
1517
1518                         attachmentBlendStates.push_back(attachmentBlendState);
1519                 }
1520         }
1521
1522         if (renderInfo.getDepthStencilAttachment())
1523         {
1524                 const Attachment& attachment = *renderInfo.getDepthStencilAttachment();
1525
1526                 DE_ASSERT(!rasterSamples || *rasterSamples == attachment.getSamples());
1527                 rasterSamples = attachment.getSamples();
1528         }
1529
1530         // If there are no attachment use single sample
1531         if (!rasterSamples)
1532                 rasterSamples = VK_SAMPLE_COUNT_1_BIT;
1533
1534         const VkPipelineShaderStageCreateInfo shaderStages[2] =
1535         {
1536                 {
1537                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // sType
1538                         DE_NULL,                                                                                                // pNext
1539                         (VkPipelineShaderStageCreateFlags)0u,
1540                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // stage
1541                         vertexShaderModule,                                                                             // shader
1542                         "main",
1543                         &emptyShaderSpecializations
1544                 },
1545                 {
1546                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // sType
1547                         DE_NULL,                                                                                                // pNext
1548                         (VkPipelineShaderStageCreateFlags)0u,
1549                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // stage
1550                         fragmentShaderModule,                                                                   // shader
1551                         "main",
1552                         &emptyShaderSpecializations
1553                 }
1554         };
1555         const VkVertexInputBindingDescription vertexBinding =
1556         {
1557                 0u,                                                                                                                     // binding
1558                 (deUint32)sizeof(tcu::Vec4),                                                            // strideInBytes
1559                 VK_VERTEX_INPUT_RATE_VERTEX,                                                            // stepRate
1560         };
1561         const VkVertexInputAttributeDescription vertexAttrib =
1562         {
1563                 0u,                                                                                                                     // location
1564                 0u,                                                                                                                     // binding
1565                 VK_FORMAT_R32G32B32A32_SFLOAT,                                                          // format
1566                 0u,                                                                                                                     // offsetInBytes
1567         };
1568         const VkPipelineVertexInputStateCreateInfo vertexInputState =
1569         {
1570                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      //      sType
1571                 DE_NULL,                                                                                                        //      pNext
1572                 (VkPipelineVertexInputStateCreateFlags)0u,
1573                 1u,                                                                                                                     //      bindingCount
1574                 &vertexBinding,                                                                                         //      pVertexBindingDescriptions
1575                 1u,                                                                                                                     //      attributeCount
1576                 &vertexAttrib,                                                                                          //      pVertexAttributeDescriptions
1577         };
1578         const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
1579         {
1580                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // sType
1581                 DE_NULL,                                                                                                                // pNext
1582                 (VkPipelineInputAssemblyStateCreateFlags)0u,
1583                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                                    // topology
1584                 VK_FALSE,                                                                                                               // primitiveRestartEnable
1585         };
1586         const VkViewport viewport =
1587         {
1588                 (float)renderInfo.getViewportOffset().x(),      (float)renderInfo.getViewportOffset().y(),
1589                 (float)renderInfo.getViewportSize().x(),        (float)renderInfo.getViewportSize().y(),
1590                 0.0f, 1.0f
1591         };
1592         const VkRect2D scissor =
1593         {
1594                 { (deInt32)renderInfo.getViewportOffset().x(),  (deInt32)renderInfo.getViewportOffset().y() },
1595                 { (deInt32)renderInfo.getViewportSize().x(),    (deInt32)renderInfo.getViewportSize().y() }
1596         };
1597         const VkPipelineViewportStateCreateInfo viewportState =
1598         {
1599                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
1600                 DE_NULL,
1601                 (VkPipelineViewportStateCreateFlags)0u,
1602                 1u,
1603                 &viewport,
1604                 1u,
1605                 &scissor
1606         };
1607         const VkPipelineRasterizationStateCreateInfo rasterState =
1608         {
1609                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // sType
1610                 DE_NULL,                                                                                                                // pNext
1611                 (VkPipelineRasterizationStateCreateFlags)0u,
1612                 VK_TRUE,                                                                                                                // depthClipEnable
1613                 VK_FALSE,                                                                                                               // rasterizerDiscardEnable
1614                 VK_POLYGON_MODE_FILL,                                                                                   // fillMode
1615                 VK_CULL_MODE_NONE,                                                                                              // cullMode
1616                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // frontFace
1617                 VK_FALSE,                                                                                                               // depthBiasEnable
1618                 0.0f,                                                                                                                   // depthBias
1619                 0.0f,                                                                                                                   // depthBiasClamp
1620                 0.0f,                                                                                                                   // slopeScaledDepthBias
1621                 1.0f                                                                                                                    // lineWidth
1622         };
1623         const VkPipelineMultisampleStateCreateInfo multisampleState =
1624         {
1625                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // sType
1626                 DE_NULL,                                                                                                                // pNext
1627                 (VkPipelineMultisampleStateCreateFlags)0u,
1628                 *rasterSamples,                                                                                                 // rasterSamples
1629                 VK_FALSE,                                                                                                               // sampleShadingEnable
1630                 0.0f,                                                                                                                   // minSampleShading
1631                 DE_NULL,                                                                                                                // pSampleMask
1632                 VK_FALSE,                                                                                                               // alphaToCoverageEnable
1633                 VK_FALSE,                                                                                                               // alphaToOneEnable
1634         };
1635         const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1636         {
1637                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // sType
1638                 DE_NULL,                                                                                                        // pNext
1639                 (VkPipelineDepthStencilStateCreateFlags)0u,
1640                 VK_TRUE,                                                                                                        // depthTestEnable
1641                 VK_TRUE,                                                                                                        // depthWriteEnable
1642                 VK_COMPARE_OP_ALWAYS,                                                                           // depthCompareOp
1643                 VK_FALSE,                                                                                                       // depthBoundsEnable
1644                 VK_TRUE,                                                                                                        // stencilTestEnable
1645                 {
1646                         VK_STENCIL_OP_REPLACE,                                                                  // stencilFailOp
1647                         VK_STENCIL_OP_REPLACE,                                                                  // stencilPassOp
1648                         VK_STENCIL_OP_REPLACE,                                                                  // stencilDepthFailOp
1649                         VK_COMPARE_OP_ALWAYS,                                                                   // stencilCompareOp
1650                         ~0u,                                                                                                    // stencilCompareMask
1651                         ~0u,                                                                                                    // stencilWriteMask
1652                         STENCIL_VALUE                                                                                   // stencilReference
1653                 },                                                                                                                      // front
1654                 {
1655                         VK_STENCIL_OP_REPLACE,                                                                  // stencilFailOp
1656                         VK_STENCIL_OP_REPLACE,                                                                  // stencilPassOp
1657                         VK_STENCIL_OP_REPLACE,                                                                  // stencilDepthFailOp
1658                         VK_COMPARE_OP_ALWAYS,                                                                   // stencilCompareOp
1659                         ~0u,                                                                                                    // stencilCompareMask
1660                         ~0u,                                                                                                    // stencilWriteMask
1661                         STENCIL_VALUE                                                                                   // stencilReference
1662                 },                                                                                                                      // back
1663
1664                 -1.0f,                                                                                                          // minDepthBounds;
1665                 1.0f                                                                                                            // maxDepthBounds;
1666         };
1667         const VkPipelineColorBlendStateCreateInfo blendState =
1668         {
1669                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,                       // sType
1670                 DE_NULL,                                                                                                                        // pNext
1671                 (VkPipelineColorBlendStateCreateFlags)0u,
1672                 VK_FALSE,                                                                                                                       // logicOpEnable
1673                 VK_LOGIC_OP_COPY,                                                                                                       // logicOp
1674                 (deUint32)attachmentBlendStates.size(),                                                         // attachmentCount
1675                 attachmentBlendStates.empty() ? DE_NULL : &attachmentBlendStates[0],// pAttachments
1676                 { 0.0f, 0.0f, 0.0f, 0.0f }                                                                                      // blendConst
1677         };
1678         const VkPipelineDynamicStateCreateInfo dynamicState =
1679         {
1680                 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
1681                 DE_NULL,
1682                 (VkPipelineDynamicStateCreateFlags)0u,
1683                 0,
1684                 DE_NULL
1685         };
1686         const VkGraphicsPipelineCreateInfo createInfo =
1687         {
1688                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                // sType
1689                 DE_NULL,                                                                                                // pNext
1690                 (VkPipelineCreateFlags)0u,
1691
1692                 2,                                                                                                              // stageCount
1693                 shaderStages,                                                                                   // pStages
1694
1695                 &vertexInputState,                                                                              // pVertexInputState
1696                 &inputAssemblyState,                                                                    // pInputAssemblyState
1697                 DE_NULL,                                                                                                // pTessellationState
1698                 &viewportState,                                                                                 // pViewportState
1699                 &rasterState,                                                                                   // pRasterState
1700                 &multisampleState,                                                                              // pMultisampleState
1701                 &depthStencilState,                                                                             // pDepthStencilState
1702                 &blendState,                                                                                    // pColorBlendState
1703                 &dynamicState,                                                                                  // pDynamicState
1704                 pipelineLayout,                                                                                 // layout
1705
1706                 renderPass,                                                                                             // renderPass
1707                 renderInfo.getSubpassIndex(),                                                   // subpass
1708                 DE_NULL,                                                                                                // basePipelineHandle
1709                 0u                                                                                                              // basePipelineIndex
1710         };
1711
1712         return createGraphicsPipeline(vk, device, DE_NULL, &createInfo);
1713 }
1714
1715 class SubpassRenderer
1716 {
1717 public:
1718         SubpassRenderer (Context&                                       context,
1719                                          const DeviceInterface&         vk,
1720                                          VkDevice                                       device,
1721                                          Allocator&                                     allocator,
1722                                          VkRenderPass                           renderPass,
1723                                          VkFramebuffer                          framebuffer,
1724                                          VkCommandPool                          commandBufferPool,
1725                                          deUint32                                       queueFamilyIndex,
1726                                          const SubpassRenderInfo&       renderInfo)
1727                 : m_renderInfo  (renderInfo)
1728         {
1729                 const deUint32 subpassIndex = renderInfo.getSubpassIndex();
1730
1731                 if (renderInfo.getRenderQuad())
1732                 {
1733                         const RenderQuad&                                       renderQuad                              = *renderInfo.getRenderQuad();
1734                         const VkPipelineLayoutCreateInfo        pipelineLayoutParams    =
1735                         {
1736                                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // sType;
1737                                 DE_NULL,                                                                                // pNext;
1738                                 (vk::VkPipelineLayoutCreateFlags)0,
1739                                 0u,                                                                                             // descriptorSetCount;
1740                                 DE_NULL,                                                                                // pSetLayouts;
1741                                 0u,                                                                                             // pushConstantRangeCount;
1742                                 DE_NULL,                                                                                // pPushConstantRanges;
1743                         };
1744
1745                         m_vertexShaderModule    = createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-vert"), 0u);
1746                         m_fragmentShaderModule  = createShaderModule(vk, device, context.getBinaryCollection().get(de::toString(subpassIndex) + "-frag"), 0u);
1747                         m_pipelineLayout                = createPipelineLayout(vk, device, &pipelineLayoutParams);
1748                         m_pipeline                              = createSubpassPipeline(vk, device, renderPass, *m_vertexShaderModule, *m_fragmentShaderModule, *m_pipelineLayout, m_renderInfo);
1749
1750                         m_vertexBuffer                  = createBuffer(vk, device, 0u, (VkDeviceSize)renderQuad.getVertexDataSize(), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE, 1u, &queueFamilyIndex);
1751                         m_vertexBufferMemory    = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_vertexBuffer), MemoryRequirement::HostVisible);
1752
1753                         bindBufferMemory(vk, device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset());
1754                         uploadBufferData(vk, device, *m_vertexBufferMemory, renderQuad.getVertexDataSize(), renderQuad.getVertexPointer());
1755                 }
1756
1757                 if (renderInfo.isSecondary())
1758                 {
1759                         m_commandBuffer = allocateCommandBuffer(vk, device, commandBufferPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
1760
1761                         beginCommandBuffer(vk, *m_commandBuffer, vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, renderPass, subpassIndex, framebuffer, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
1762                         pushRenderCommands(vk, *m_commandBuffer);
1763                         endCommandBuffer(vk, *m_commandBuffer);
1764                 }
1765         }
1766
1767         bool isSecondary (void) const
1768         {
1769                 return m_commandBuffer;
1770         }
1771
1772         VkCommandBuffer getCommandBuffer (void) const
1773         {
1774                 DE_ASSERT(isSecondary());
1775                 return *m_commandBuffer;
1776         }
1777
1778         void pushRenderCommands (const DeviceInterface&         vk,
1779                                                          VkCommandBuffer                        commandBuffer)
1780         {
1781                 if (!m_renderInfo.getColorClears().empty())
1782                 {
1783                         const vector<ColorClear>&       colorClears     (m_renderInfo.getColorClears());
1784
1785                         for (deUint32 attachmentNdx = 0; attachmentNdx < m_renderInfo.getColorAttachmentCount(); attachmentNdx++)
1786                         {
1787                                 const ColorClear&               colorClear      = colorClears[attachmentNdx];
1788                                 const VkClearAttachment attachment      =
1789                                 {
1790                                         VK_IMAGE_ASPECT_COLOR_BIT,
1791                                         attachmentNdx,
1792                                         makeClearValue(colorClear.getColor()),
1793                                 };
1794                                 const VkClearRect               rect            =
1795                                 {
1796                                         {
1797                                                 { (deInt32)colorClear.getOffset().x(),  (deInt32)colorClear.getOffset().y()     },
1798                                                 { (deInt32)colorClear.getSize().x(),    (deInt32)colorClear.getSize().y()       }
1799                                         },                                      // rect
1800                                         0u,                                     // baseArrayLayer
1801                                         1u,                                     // layerCount
1802                                 };
1803
1804                                 vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
1805                         }
1806                 }
1807
1808                 if (m_renderInfo.getDepthStencilClear())
1809                 {
1810                         const DepthStencilClear&                depthStencilClear       = *m_renderInfo.getDepthStencilClear();
1811                         const deUint32                                  attachmentNdx           = m_renderInfo.getColorAttachmentCount();
1812                         tcu::TextureFormat                              format                          = mapVkFormat(m_renderInfo.getDepthStencilAttachment()->getFormat());
1813                         const VkClearAttachment                 attachment                      =
1814                         {
1815                                 (VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0)
1816                                         | (hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
1817                                 attachmentNdx,
1818                                 makeClearValueDepthStencil(depthStencilClear.getDepth(), depthStencilClear.getStencil())
1819                         };
1820                         const VkClearRect                               rect                            =
1821                         {
1822                                 {
1823                                         { (deInt32)depthStencilClear.getOffset().x(),   (deInt32)depthStencilClear.getOffset().y()      },
1824                                         { (deInt32)depthStencilClear.getSize().x(),             (deInt32)depthStencilClear.getSize().y()        }
1825                                 },                                                      // rect
1826                                 0u,                                                     // baseArrayLayer
1827                                 1u,                                                     // layerCount
1828                         };
1829
1830                         vk.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
1831                 }
1832
1833                 if (m_renderInfo.getRenderQuad())
1834                 {
1835                         const VkDeviceSize      offset                  = 0;
1836                         const VkBuffer          vertexBuffer    = *m_vertexBuffer;
1837
1838                         vk.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1839                         vk.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &vertexBuffer, &offset);
1840                         vk.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
1841                 }
1842         }
1843
1844 private:
1845         const SubpassRenderInfo                         m_renderInfo;
1846         Move<VkCommandBuffer>                           m_commandBuffer;
1847         Move<VkPipeline>                                        m_pipeline;
1848         Move<VkPipelineLayout>                          m_pipelineLayout;
1849
1850         Move<VkShaderModule>                            m_vertexShaderModule;
1851
1852         Move<VkShaderModule>                            m_fragmentShaderModule;
1853
1854         Move<VkBuffer>                                          m_vertexBuffer;
1855         de::MovePtr<Allocation>                         m_vertexBufferMemory;
1856 };
1857
1858 void pushImageInitializationCommands (const DeviceInterface&                                                            vk,
1859                                                                           VkCommandBuffer                                                                               commandBuffer,
1860                                                                           const vector<Attachment>&                                                             attachmentInfo,
1861                                                                           const vector<de::SharedPtr<AttachmentResources> >&    attachmentResources,
1862                                                                           deUint32                                                                                              queueIndex,
1863                                                                           const vector<Maybe<VkClearValue> >&                                   clearValues)
1864 {
1865         {
1866                 vector<VkImageMemoryBarrier>    initializeLayouts;
1867
1868                 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1869                 {
1870                         if (!clearValues[attachmentNdx])
1871                                 continue;
1872
1873                         const VkImageMemoryBarrier barrier =
1874                         {
1875                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                         // sType;
1876                                 DE_NULL,                                                                                                                        // pNext;
1877
1878                                 getAllMemoryWriteFlags(),                                                                                       // srcAccessMask
1879                                 getAllMemoryReadFlags(),                                                                                        // dstAccessMask
1880
1881                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                                      // oldLayout
1882                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                                                           // newLayout;
1883
1884                                 queueIndex,                                                                                                                     // srcQueueFamilyIndex;
1885                                 queueIndex,                                                                                                                     // destQueueFamilyIndex;
1886
1887                                 attachmentResources[attachmentNdx]->getImage(),                                         // image;
1888                                 {                                                                                                                                       // subresourceRange;
1889                                         getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
1890                                         0,                                                                                                                              // baseMipLevel;
1891                                         1,                                                                                                                              // mipLevels;
1892                                         0,                                                                                                                              // baseArraySlice;
1893                                         1                                                                                                                               // arraySize;
1894                                 }
1895                         };
1896
1897                         initializeLayouts.push_back(barrier);
1898                 }
1899
1900                 if (!initializeLayouts.empty())
1901                 {
1902                         vector<VkImageMemoryBarrier*> initializeLayoutPtrs;
1903
1904                         for (size_t ndx = 0; ndx < initializeLayouts.size(); ndx++)
1905                                 initializeLayoutPtrs.push_back(&initializeLayouts[ndx]);
1906
1907                         vk.cmdPipelineBarrier(commandBuffer, 0, 0, VK_FALSE, (deUint32)initializeLayouts.size(), (const void* const*)&initializeLayoutPtrs[0]);
1908                 }
1909         }
1910
1911         for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1912         {
1913                 if (!clearValues[attachmentNdx])
1914                         continue;
1915
1916                 const tcu::TextureFormat format = mapVkFormat(attachmentInfo[attachmentNdx].getFormat());
1917
1918                 if (hasStencilComponent(format.order) || hasDepthComponent(format.order))
1919                 {
1920                         const float                                             clearNan                = tcu::Float32::nan().asFloat();
1921                         const float                                             clearDepth              = hasDepthComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.depth : clearNan;
1922                         const deUint32                                  clearStencil    = hasStencilComponent(format.order) ? clearValues[attachmentNdx]->depthStencil.stencil : ~0u;
1923                         const VkClearDepthStencilValue  depthStencil    =
1924                         {
1925                                 clearDepth,
1926                                 clearStencil
1927                         };
1928                         const VkImageSubresourceRange range =
1929                         {
1930                                 (VkImageAspectFlags)((hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0)
1931                                                                          | (hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)),
1932                                 0,
1933                                 1,
1934                                 0,
1935                                 1
1936                         };
1937
1938                         vk.cmdClearDepthStencilImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthStencil, 1, &range);
1939                 }
1940                 else
1941                 {
1942                         const VkImageSubresourceRange   range           =
1943                         {
1944                                 VK_IMAGE_ASPECT_COLOR_BIT,                              // aspectMask;
1945                                 0,                                                                              // baseMipLevel;
1946                                 1,                                                                              // mipLevels;
1947                                 0,                                                                              // baseArrayLayer;
1948                                 1                                                                               // layerCount;
1949                         };
1950                         const VkClearColorValue                 clearColor      = clearValues[attachmentNdx]->color;
1951
1952                         vk.cmdClearColorImage(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range);
1953                 }
1954         }
1955
1956         {
1957                 vector<VkImageMemoryBarrier>    renderPassLayouts;
1958
1959                 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
1960                 {
1961                         const VkImageMemoryBarrier barrier =
1962                         {
1963                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                         // sType;
1964                                 DE_NULL,                                                                                                                        // pNext;
1965
1966                                 getAllMemoryWriteFlags(),                                                                                       // srcAccessMask
1967                                 getAllMemoryReadFlags(),                                                                                        // dstAccessMask
1968
1969                                 clearValues[attachmentNdx] ?
1970                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
1971                                         : VK_IMAGE_LAYOUT_UNDEFINED,                                                                    // oldLayout
1972
1973                                 attachmentInfo[attachmentNdx].getInitialLayout(),                                       // newLayout;
1974
1975                                 queueIndex,                                                                                                                     // srcQueueFamilyIndex;
1976                                 queueIndex,                                                                                                                     // destQueueFamilyIndex;
1977
1978                                 attachmentResources[attachmentNdx]->getImage(),                                         // image;
1979                                 {                                                                                                                                       // subresourceRange;
1980                                         getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
1981                                         0,                                                                                                                              // baseMipLevel;
1982                                         1,                                                                                                                              // mipLevels;
1983                                         0,                                                                                                                              // baseArraySlice;
1984                                         1                                                                                                                               // arraySize;
1985                                 }
1986                         };
1987
1988                         renderPassLayouts.push_back(barrier);
1989                 }
1990
1991                 if (!renderPassLayouts.empty())
1992                 {
1993                         vector<VkImageMemoryBarrier*> renderPassLayoutPtrs;
1994
1995                         for (size_t ndx = 0; ndx < renderPassLayouts.size(); ndx++)
1996                                 renderPassLayoutPtrs.push_back(&renderPassLayouts[ndx]);
1997
1998                         vk.cmdPipelineBarrier(commandBuffer, 0, 0, VK_FALSE, (deUint32)renderPassLayouts.size(), (const void* const*)&renderPassLayoutPtrs[0]);
1999                 }
2000         }
2001 }
2002
2003 void pushRenderPassCommands (const DeviceInterface&                                                             vk,
2004                                                          VkCommandBuffer                                                                        commandBuffer,
2005                                                          VkRenderPass                                                                           renderPass,
2006                                                          VkFramebuffer                                                                          framebuffer,
2007                                                          const vector<de::SharedPtr<SubpassRenderer> >&         subpassRenderers,
2008                                                          const UVec2&                                                                           renderPos,
2009                                                          const UVec2&                                                                           renderSize,
2010                                                          const vector<Maybe<VkClearValue> >&                            renderPassClearValues,
2011                                                          TestConfig::RenderTypes                                                        render)
2012 {
2013         const float                             clearNan                                = tcu::Float32::nan().asFloat();
2014         vector<VkClearValue>    attachmentClearValues;
2015
2016         for (size_t attachmentNdx = 0; attachmentNdx < renderPassClearValues.size(); attachmentNdx++)
2017         {
2018                 if (renderPassClearValues[attachmentNdx])
2019                         attachmentClearValues.push_back(*renderPassClearValues[attachmentNdx]);
2020                 else
2021                         attachmentClearValues.push_back(makeClearValueColorF32(clearNan, clearNan, clearNan, clearNan));
2022         }
2023
2024         {
2025                 const VkRect2D renderArea =
2026                 {
2027                         { (deInt32)renderPos.x(),       (deInt32)renderPos.y() },
2028                         { (deInt32)renderSize.x(),      (deInt32)renderSize.y() }
2029                 };
2030
2031                 for (size_t subpassNdx = 0; subpassNdx < subpassRenderers.size(); subpassNdx++)
2032                 {
2033                         const VkSubpassContents contents = subpassRenderers[subpassNdx]->isSecondary() ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE;
2034
2035                         if (subpassNdx == 0)
2036                                 cmdBeginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea, (deUint32)attachmentClearValues.size(), attachmentClearValues.empty() ? DE_NULL : &attachmentClearValues[0], contents);
2037                         else
2038                                 vk.cmdNextSubpass(commandBuffer, contents);
2039
2040                         if (render)
2041                         {
2042                                 if (contents == VK_SUBPASS_CONTENTS_INLINE)
2043                                 {
2044                                         subpassRenderers[subpassNdx]->pushRenderCommands(vk, commandBuffer);
2045                                 }
2046                                 else if (contents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS)
2047                                 {
2048                                         const VkCommandBuffer cmd = subpassRenderers[subpassNdx]->getCommandBuffer();
2049                                         vk.cmdExecuteCommands(commandBuffer, 1, &cmd);
2050                                 }
2051                                 else
2052                                         DE_FATAL("Invalid contents");
2053                         }
2054                 }
2055
2056                 vk.cmdEndRenderPass(commandBuffer);
2057         }
2058 }
2059
2060 void pushReadImagesToBuffers (const DeviceInterface&                                                            vk,
2061                                                           VkCommandBuffer                                                                               commandBuffer,
2062                                                           deUint32                                                                                              queueIndex,
2063
2064                                                           const vector<de::SharedPtr<AttachmentResources> >&    attachmentResources,
2065                                                           const vector<Attachment>&                                                             attachmentInfo,
2066                                                           const vector<bool>&                                                                   isLazy,
2067
2068                                                           const UVec2&                                                                                  targetSize)
2069 {
2070         {
2071                 vector<VkImageMemoryBarrier>    imageBarriers;
2072
2073                 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2074                 {
2075                         if (isLazy[attachmentNdx])
2076                                 continue;
2077
2078                         const VkImageMemoryBarrier barrier =
2079                         {
2080                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // sType
2081                                 DE_NULL,                                                                                        // pNext
2082
2083                                 getAllMemoryWriteFlags(),                                                       // srcAccessMask
2084                                 getAllMemoryReadFlags(),                                                        // dstAccessMask
2085
2086                                 attachmentInfo[attachmentNdx].getFinalLayout(),         // oldLayout
2087                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                           // newLayout
2088
2089                                 queueIndex,                                                                                     // srcQueueFamilyIndex
2090                                 queueIndex,                                                                                     // destQueueFamilyIndex
2091
2092                                 attachmentResources[attachmentNdx]->getImage(),         // image
2093                                 {                                                                                                       // subresourceRange
2094                                         getImageAspectFlags(attachmentInfo[attachmentNdx].getFormat()), // aspect;
2095                                         0,                                                                              // baseMipLevel
2096                                         1,                                                                              // mipLevels
2097                                         0,                                                                              // baseArraySlice
2098                                         1                                                                               // arraySize
2099                                 }
2100                         };
2101
2102                         imageBarriers.push_back(barrier);
2103                 }
2104
2105                 if (!imageBarriers.empty())
2106                 {
2107                         vector<VkImageMemoryBarrier*> clearLayoutPtrs;
2108
2109                         for (size_t ndx = 0; ndx < imageBarriers.size(); ndx++)
2110                                 clearLayoutPtrs.push_back(&imageBarriers[ndx]);
2111
2112                         vk.cmdPipelineBarrier(commandBuffer, getAllPipelineStageFlags(),
2113                                                                                                  getAllPipelineStageFlags(),
2114                                                                                                  VK_FALSE, (deUint32)imageBarriers.size(), (const void* const*)&clearLayoutPtrs[0]);
2115                 }
2116         }
2117
2118         for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2119         {
2120                 if (isLazy[attachmentNdx])
2121                         continue;
2122
2123                 const tcu::TextureFormat::ChannelOrder  order   = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
2124                 const VkBufferImageCopy                                 rect    =
2125                 {
2126                         0, // bufferOffset
2127                         0, // bufferRowLength
2128                         0, // bufferImageHeight
2129                         {                                                       // imageSubresource
2130                                 getPrimaryImageAspect(mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order),    // aspect
2131                                 0,                                              // mipLevel
2132                                 0,                                              // arraySlice
2133                                 1                                               // arraySize
2134                         },
2135                         { 0, 0, 0 },                            // imageOffset
2136                         { (deInt32)targetSize.x(), (deInt32)targetSize.y(), 1 }         // imageExtent
2137                 };
2138
2139                 vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getBuffer(), 1, &rect);
2140
2141                 if (tcu::TextureFormat::DS == order)
2142                 {
2143                         const VkBufferImageCopy stencilRect =
2144                         {
2145                                 0, // bufferOffset
2146                                 0, // bufferRowLength
2147                                 0, // bufferImageHeight
2148                                 {                                                                       // imageSubresource
2149                                         VK_IMAGE_ASPECT_STENCIL_BIT,    // aspect
2150                                         0,                                                              // mipLevel
2151                                         0,                                                              // arraySlice
2152                                         1                                               // arraySize
2153                                 },
2154                                 { 0, 0, 0 },                            // imageOffset
2155                                 { (deInt32)targetSize.x(), (deInt32)targetSize.y(), 1 }         // imageExtent
2156                         };
2157
2158                         vk.cmdCopyImageToBuffer(commandBuffer, attachmentResources[attachmentNdx]->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, attachmentResources[attachmentNdx]->getSecondaryBuffer(), 1, &stencilRect);
2159                 }
2160         }
2161
2162         {
2163                 vector<VkBufferMemoryBarrier>   bufferBarriers;
2164
2165                 for (size_t attachmentNdx = 0; attachmentNdx < attachmentInfo.size(); attachmentNdx++)
2166                 {
2167                         if (isLazy[attachmentNdx])
2168                                 continue;
2169
2170                         const tcu::TextureFormat::ChannelOrder  order                   = mapVkFormat(attachmentInfo[attachmentNdx].getFormat()).order;
2171                         const VkBufferMemoryBarrier                             bufferBarrier   =
2172                         {
2173                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2174                                 DE_NULL,
2175
2176                                 getAllMemoryWriteFlags(),
2177                                 getAllMemoryReadFlags(),
2178
2179                                 queueIndex,
2180                                 queueIndex,
2181
2182                                 attachmentResources[attachmentNdx]->getBuffer(),
2183                                 0,
2184                                 attachmentResources[attachmentNdx]->getBufferSize()
2185                         };
2186
2187                         bufferBarriers.push_back(bufferBarrier);
2188
2189                         if (tcu::TextureFormat::DS == order)
2190                         {
2191                                 const VkBufferMemoryBarrier secondaryBufferBarrier =
2192                                 {
2193                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2194                                         DE_NULL,
2195
2196                                         getAllMemoryWriteFlags(),
2197                                         getAllMemoryReadFlags(),
2198
2199                                         queueIndex,
2200                                         queueIndex,
2201
2202                                         attachmentResources[attachmentNdx]->getSecondaryBuffer(),
2203                                         0,
2204                                         attachmentResources[attachmentNdx]->getSecondaryBufferSize()
2205                                 };
2206
2207                                 bufferBarriers.push_back(secondaryBufferBarrier);
2208                         }
2209
2210                         bufferBarriers.push_back(bufferBarrier);
2211                 }
2212
2213                 if (!bufferBarriers.empty())
2214                 {
2215                         vector<VkBufferMemoryBarrier*> clearLayoutPtrs;
2216
2217                         for (size_t ndx = 0; ndx < bufferBarriers.size(); ndx++)
2218                                 clearLayoutPtrs.push_back(&bufferBarriers[ndx]);
2219
2220                         vk.cmdPipelineBarrier(commandBuffer, getAllPipelineStageFlags(),
2221                                                                                                  getAllPipelineStageFlags(),
2222                                                                                                  VK_FALSE, (deUint32)bufferBarriers.size(), (const void* const*)&clearLayoutPtrs[0]);
2223                 }
2224         }
2225 }
2226
2227 void clear (const PixelBufferAccess& access, const VkClearValue& value)
2228 {
2229         const tcu::TextureFormat&       format  = access.getFormat();
2230
2231         if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
2232         {
2233                 if (tcu::hasDepthComponent(format.order))
2234                         tcu::clearDepth(access, value.depthStencil.depth);
2235
2236                 if (tcu::hasStencilComponent(format.order))
2237                         tcu::clearStencil(access, value.depthStencil.stencil);
2238         }
2239         else
2240         {
2241                 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT
2242                                 || tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
2243                                 || tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
2244                 {
2245                         const tcu::Vec4         color   (value.color.float32[0],
2246                                                                                  value.color.float32[1],
2247                                                                                  value.color.float32[2],
2248                                                                                  value.color.float32[3]);
2249
2250                         if (tcu::isSRGB(format))
2251                                 tcu::clear(access, tcu::linearToSRGB(color));
2252                         else
2253                                 tcu::clear(access, color);
2254                 }
2255                 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
2256                 {
2257                         const tcu::UVec4        color   (value.color.uint32[0],
2258                                                                                  value.color.uint32[1],
2259                                                                                  value.color.uint32[2],
2260                                                                                  value.color.uint32[3]);
2261
2262                         tcu::clear(access, color);
2263                 }
2264                 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
2265                 {
2266                         const tcu::IVec4        color   (value.color.int32[0],
2267                                                                                  value.color.int32[1],
2268                                                                                  value.color.int32[2],
2269                                                                                  value.color.int32[3]);
2270
2271                         tcu::clear(access, color);
2272                 }
2273                 else
2274                         DE_FATAL("Unknown channel class");
2275         }
2276 }
2277
2278 Vec4 computeUvs (const IVec2& posA, const IVec2& posB, const IVec2& pos)
2279 {
2280         const float u = de::clamp((float)(pos.x() - posA.x()) / (float)(posB.x() - posA.x()), 0.0f, 1.0f);
2281         const float v = de::clamp((float)(pos.y() - posA.y()) / (float)(posB.y() - posA.y()), 0.0f, 1.0f);
2282
2283         return Vec4(u, v, u * v, (u + v) / 2.0f);
2284 }
2285
2286 void renderReferenceImages (vector<tcu::TextureLevel>&                  referenceAttachments,
2287                                                         const RenderPass&                                       renderPassInfo,
2288                                                         const UVec2&                                            targetSize,
2289                                                         const vector<Maybe<VkClearValue> >&     imageClearValues,
2290                                                         const vector<Maybe<VkClearValue> >&     renderPassClearValues,
2291                                                         const vector<SubpassRenderInfo>&        subpassRenderInfo,
2292                                                         const UVec2&                                            renderPos,
2293                                                         const UVec2&                                            renderSize)
2294 {
2295         const vector<Subpass>&  subpasses               = renderPassInfo.getSubpasses();
2296         vector<bool>                    attachmentUsed  (renderPassInfo.getAttachments().size(), false);
2297
2298         referenceAttachments.resize(renderPassInfo.getAttachments().size());
2299
2300         for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
2301         {
2302                 const Attachment                                attachment                                      = renderPassInfo.getAttachments()[attachmentNdx];
2303                 const tcu::TextureFormat                format                                          = mapVkFormat(attachment.getFormat());
2304                 const tcu::TextureFormatInfo    textureInfo                                     = tcu::getTextureFormatInfo(format);
2305                 tcu::TextureLevel&                              reference                                       = referenceAttachments[attachmentNdx];
2306                 const bool                                              isDepthOrStencilAttachment      = hasDepthComponent(format.order) || hasStencilComponent(format.order);
2307
2308                 reference = tcu::TextureLevel(format, targetSize.x(), targetSize.y());
2309
2310                 if (imageClearValues[attachmentNdx])
2311                         clear(reference.getAccess(), *imageClearValues[attachmentNdx]);
2312                 else
2313                 {
2314                         // Fill with grid if image contentst are undefined before renderpass
2315                         if (isDepthOrStencilAttachment)
2316                         {
2317                                 if (tcu::hasDepthComponent(format.order))
2318                                         tcu::fillWithGrid(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), 2, textureInfo.valueMin, textureInfo.valueMax);
2319
2320                                 if (tcu::hasStencilComponent(format.order))
2321                                         tcu::fillWithGrid(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), 2, textureInfo.valueMin, textureInfo.valueMax);
2322                         }
2323                         else
2324                                 tcu::fillWithGrid(reference.getAccess(), 2, textureInfo.valueMin, textureInfo.valueMax);
2325                 }
2326         }
2327
2328         for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
2329         {
2330                 const Subpass&                                          subpass                         = subpasses[subpassNdx];
2331                 const SubpassRenderInfo&                        renderInfo                      = subpassRenderInfo[subpassNdx];
2332                 const vector<AttachmentReference>&      colorAttachments        = subpass.getColorAttachments();
2333
2334                 // Apply load op if attachment was used for the first time
2335                 for (size_t attachmentNdx = 0; attachmentNdx < colorAttachments.size(); attachmentNdx++)
2336                 {
2337                         const deUint32 attachmentIndex = colorAttachments[attachmentNdx].getAttachment();
2338
2339                         if (!attachmentUsed[attachmentIndex])
2340                         {
2341                                 const Attachment&       attachment      = renderPassInfo.getAttachments()[attachmentIndex];
2342                                 tcu::TextureLevel&      reference       = referenceAttachments[attachmentIndex];
2343
2344                                 DE_ASSERT(!tcu::hasDepthComponent(reference.getFormat().order));
2345                                 DE_ASSERT(!tcu::hasStencilComponent(reference.getFormat().order));
2346
2347                                 if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2348                                         clear(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2349                                 else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2350                                 {
2351                                         const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2352
2353                                         tcu::fillWithGrid(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2354                                 }
2355
2356                                 attachmentUsed[attachmentIndex] = true;
2357                         }
2358                 }
2359
2360                 // Apply load op to depth/stencil attachment if it was used for the first time
2361                 if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED && !attachmentUsed[subpass.getDepthStencilAttachment().getAttachment()])
2362                 {
2363                         const deUint32 attachmentIndex = subpass.getDepthStencilAttachment().getAttachment();
2364
2365                         // Apply load op if attachment was used for the first time
2366                         if (!attachmentUsed[attachmentIndex])
2367                         {
2368                                 const Attachment&       attachment      = renderPassInfo.getAttachments()[attachmentIndex];
2369                                 tcu::TextureLevel&      reference               = referenceAttachments[attachmentIndex];
2370
2371                                 if (tcu::hasDepthComponent(reference.getFormat().order))
2372                                 {
2373                                         if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2374                                                 clear(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2375                                         else if (attachment.getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2376                                         {
2377                                                 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2378
2379                                                 tcu::fillWithGrid(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_DEPTH), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2380                                         }
2381                                 }
2382
2383                                 if (tcu::hasStencilComponent(reference.getFormat().order))
2384                                 {
2385                                         if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
2386                                                 clear(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), *renderPassClearValues[attachmentIndex]);
2387                                         else if (attachment.getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
2388                                         {
2389                                                 const tcu::TextureFormatInfo textureInfo = tcu::getTextureFormatInfo(reference.getFormat());
2390
2391                                                 tcu::fillWithGrid(tcu::getSubregion(tcu::getEffectiveDepthStencilAccess(reference.getAccess(), tcu::Sampler::MODE_STENCIL), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2392                                         }
2393                                 }
2394                         }
2395
2396                         attachmentUsed[attachmentIndex] = true;
2397                 }
2398
2399                 for (size_t colorClearNdx = 0; colorClearNdx < renderInfo.getColorClears().size(); colorClearNdx++)
2400                 {
2401                         const ColorClear&       colorClear      = renderInfo.getColorClears()[colorClearNdx];
2402                         const UVec2                     offset          = colorClear.getOffset();
2403                         const UVec2                     size            = colorClear.getSize();
2404                         tcu::TextureLevel&      reference       = referenceAttachments[subpass.getColorAttachments()[colorClearNdx].getAttachment()];
2405                         VkClearValue            value;
2406
2407                         value.color = colorClear.getColor();
2408
2409                         clear(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), value);
2410                 }
2411
2412                 if (renderInfo.getDepthStencilClear())
2413                 {
2414                         const DepthStencilClear&        dsClear         = *renderInfo.getDepthStencilClear();
2415                         const UVec2                                     offset          = dsClear.getOffset();
2416                         const UVec2                                     size            = dsClear.getSize();
2417                         tcu::TextureLevel&                      reference       = referenceAttachments[subpass.getDepthStencilAttachment().getAttachment()];
2418
2419                         if (tcu::hasDepthComponent(reference.getFormat().order))
2420                                 clearDepth(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), dsClear.getDepth());
2421
2422                         if (tcu::hasStencilComponent(reference.getFormat().order))
2423                                 clearStencil(tcu::getSubregion(reference.getAccess(), offset.x(), offset.y(), 0, size.x(), size.y(), 1), dsClear.getStencil());
2424                 }
2425
2426                 if (renderInfo.getRenderQuad())
2427                 {
2428                         const RenderQuad&       renderQuad      = *renderInfo.getRenderQuad();
2429                         const Vec4                      posA            = renderQuad.getCornerA();
2430                         const Vec4                      posB            = renderQuad.getCornerB();
2431                         const Vec2                      origin          = Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
2432                         const Vec2                      p                       = Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
2433                         const IVec2                     posAI           ((deInt32)(origin.x() + (p.x() * posA.x())),
2434                                                                                          (deInt32)(origin.y() + (p.y() * posA.y())));
2435                         const IVec2                     posBI           ((deInt32)(origin.x() + (p.x() * posB.x())),
2436                                                                                          (deInt32)(origin.y() + (p.y() * posB.y())));
2437
2438                         for (size_t attachmentRefNdx = 0; attachmentRefNdx < subpass.getColorAttachments().size(); attachmentRefNdx++)
2439                         {
2440                                 const Attachment                                attachment                      = renderPassInfo.getAttachments()[subpass.getColorAttachments()[attachmentRefNdx].getAttachment()];
2441                                 const tcu::TextureFormatInfo    textureInfo                     = tcu::getTextureFormatInfo(mapVkFormat(attachment.getFormat()));
2442                                 tcu::TextureLevel&                              referenceTexture        = referenceAttachments[subpass.getColorAttachments()[attachmentRefNdx].getAttachment()];
2443                                 const bool                                              srgb                            = tcu::isSRGB(referenceTexture.getFormat());
2444                                 const PixelBufferAccess reference                       = referenceTexture.getAccess();
2445                                 const float                                             clampMin                        = (float)(-MAX_INTEGER_VALUE);
2446                                 const float                                             clampMax                        = (float)(MAX_INTEGER_VALUE);
2447                                 const Vec4                                              valueMax                        (de::clamp(textureInfo.valueMax[0], clampMin, clampMax),
2448                                                                                                                                          de::clamp(textureInfo.valueMax[1], clampMin, clampMax),
2449                                                                                                                                          de::clamp(textureInfo.valueMax[2], clampMin, clampMax),
2450                                                                                                                                          de::clamp(textureInfo.valueMax[3], clampMin, clampMax));
2451
2452                                 const Vec4                                              valueMin                        (de::clamp(textureInfo.valueMin[0], clampMin, clampMax),
2453                                                                                                                                          de::clamp(textureInfo.valueMin[1], clampMin, clampMax),
2454                                                                                                                                          de::clamp(textureInfo.valueMin[2], clampMin, clampMax),
2455                                                                                                                                          de::clamp(textureInfo.valueMin[3], clampMin, clampMax));
2456
2457                                 DE_ASSERT(posAI.x() < posBI.x());
2458                                 DE_ASSERT(posAI.y() < posBI.y());
2459
2460                                 for (int y = posAI.y(); y <= (int)posBI.y(); y++)
2461                                 for (int x = posAI.x(); x <= (int)posBI.x(); x++)
2462                                 {
2463                                         const Vec4      uvs             = computeUvs(posAI, posBI, IVec2(x, y));
2464                                         const Vec4      color   = valueMax * uvs + valueMin * (Vec4(1.0f) - uvs);
2465
2466                                         if (srgb)
2467                                                 reference.setPixel(tcu::linearToSRGB(color), x, y);
2468                                         else
2469                                                 reference.setPixel(color, x, y);
2470                                 }
2471                         }
2472
2473                         if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
2474                         {
2475                                 tcu::TextureLevel&                              referenceTexture        = referenceAttachments[subpass.getDepthStencilAttachment().getAttachment()];
2476                                 const PixelBufferAccess reference                       = referenceTexture.getAccess();
2477
2478                                 DE_ASSERT(posAI.x() < posBI.x());
2479                                 DE_ASSERT(posAI.y() < posBI.y());
2480
2481                                 for (int y = posAI.y(); y <= (int)posBI.y(); y++)
2482                                 for (int x = posAI.x(); x <= (int)posBI.x(); x++)
2483                                 {
2484                                         const Vec4 uvs = computeUvs(posAI, posBI, IVec2(x, y));
2485
2486                                         if (tcu::hasDepthComponent(reference.getFormat().order))
2487                                                 reference.setPixDepth(uvs.x(), x, y);
2488
2489                                         if (tcu::hasStencilComponent(reference.getFormat().order))
2490                                                 reference.setPixStencil(STENCIL_VALUE, x, y);
2491                                 }
2492                         }
2493                 }
2494         }
2495
2496         // Mark all attachments that were used but not stored as undefined
2497         for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
2498         {
2499                 const Attachment                                attachment      = renderPassInfo.getAttachments()[attachmentNdx];
2500                 const tcu::TextureFormat                format          = mapVkFormat(attachment.getFormat());
2501                 const tcu::TextureFormatInfo    textureInfo     = tcu::getTextureFormatInfo(format);
2502                 tcu::TextureLevel&                              reference       = referenceAttachments[attachmentNdx];
2503
2504                 if (attachmentUsed[attachmentNdx] && renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
2505                         tcu::fillWithGrid(tcu::getSubregion(reference.getAccess(), renderPos.x(), renderPos.y(), renderSize.x(), renderSize.y()), 2, textureInfo.valueMin, textureInfo.valueMax);
2506         }
2507 }
2508
2509 Maybe<deUint32> findColorAttachment (const Subpass&                             subpass,
2510                                                                          deUint32                                       attachmentIndex)
2511 {
2512         for (size_t colorAttachmentNdx = 0; colorAttachmentNdx < subpass.getColorAttachments().size(); colorAttachmentNdx++)
2513         {
2514                 if (subpass.getColorAttachments()[colorAttachmentNdx].getAttachment() == attachmentIndex)
2515                         return tcu::just((deUint32)colorAttachmentNdx);
2516         }
2517
2518         return tcu::nothing<deUint32>();
2519 }
2520
2521 int calcFloatDiff (float a, float b)
2522 {
2523         const deUint32          au              = tcu::Float32(a).bits();
2524         const deUint32          bu              = tcu::Float32(b).bits();
2525
2526         const bool                      asign   = (au & (0x1u << 31u)) != 0u;
2527         const bool                      bsign   = (bu & (0x1u << 31u)) != 0u;
2528
2529         const deUint32          avalue  = (au & ((0x1u << 31u) - 1u));
2530         const deUint32          bvalue  = (bu & ((0x1u << 31u) - 1u));
2531
2532         if (asign != bsign)
2533                 return avalue + bvalue + 1u;
2534         else if (avalue < bvalue)
2535                 return bvalue - avalue;
2536         else
2537                 return avalue - bvalue;
2538 }
2539
2540 bool comparePixelToDepthClearValue (const ConstPixelBufferAccess&       access,
2541                                                                         int                                                             x,
2542                                                                         int                                                             y,
2543                                                                         float                                                   ref)
2544 {
2545         const tcu::TextureFormat                format                  = tcu::getEffectiveDepthStencilTextureFormat(access.getFormat(), tcu::Sampler::MODE_DEPTH);
2546         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(format.type);
2547
2548         switch (channelClass)
2549         {
2550                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2551                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2552                 {
2553                         const int       bitDepth        = tcu::getTextureFormatBitDepth(format).x();
2554                         const float     depth           = access.getPixDepth(x, y);
2555                         const float     threshold       = 2.0f / (float)((1 << bitDepth) - 1);
2556
2557                         return deFloatAbs(depth - ref) <= threshold;
2558                 }
2559
2560                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2561                 {
2562                         const float     depth                   = access.getPixDepth(x, y);
2563                         const int       mantissaBits    = tcu::getTextureFormatMantissaBitDepth(format).x();
2564                         const int       threshold               = 10 * 1 << (23 - mantissaBits);
2565
2566                         DE_ASSERT(mantissaBits <= 23);
2567
2568                         return calcFloatDiff(depth, ref) <= threshold;
2569                 }
2570
2571                 default:
2572                         DE_FATAL("Invalid channel class");
2573                         return false;
2574         }
2575 }
2576
2577 bool comparePixelToStencilClearValue (const ConstPixelBufferAccess&     access,
2578                                                                           int                                                   x,
2579                                                                           int                                                   y,
2580                                                                           deUint32                                              ref)
2581 {
2582         const deUint32 stencil = access.getPixStencil(x, y);
2583
2584         return stencil == ref;
2585 }
2586
2587 bool comparePixelToColorClearValue (const ConstPixelBufferAccess&       access,
2588                                                                         int                                                             x,
2589                                                                         int                                                             y,
2590                                                                         const VkClearColorValue&                ref)
2591 {
2592         const tcu::TextureFormat                format                  = access.getFormat();
2593         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(format.type);
2594         const BVec4                                             channelMask             = tcu::getTextureFormatChannelMask(format);
2595
2596         switch (channelClass)
2597         {
2598                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2599                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2600                 {
2601                         const IVec4     bitDepth        (tcu::getTextureFormatBitDepth(format));
2602                         const Vec4      resColor        (access.getPixel(x, y));
2603                         const Vec4      refColor        (ref.float32[0],
2604                                                                          ref.float32[1],
2605                                                                          ref.float32[2],
2606                                                                          ref.float32[3]);
2607                         const Vec4      threshold       (bitDepth[0] > 0 ? 20.0f / (float)((1 << bitDepth[0]) - 1) : 1.0f,
2608                                                                          bitDepth[1] > 0 ? 20.0f / (float)((1 << bitDepth[1]) - 1) : 1.0f,
2609                                                                          bitDepth[2] > 0 ? 20.0f / (float)((1 << bitDepth[2]) - 1) : 1.0f,
2610                                                                          bitDepth[3] > 0 ? 20.0f / (float)((1 << bitDepth[3]) - 1) : 1.0f);
2611
2612                         if (tcu::isSRGB(access.getFormat()))
2613                                 return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, tcu::linearToSRGB(refColor)), threshold), channelMask), channelMask));
2614                         else
2615                                 return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2616                 }
2617
2618                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2619                 {
2620                         const UVec4     resColor        (access.getPixelUint(x, y));
2621                         const UVec4     refColor        (ref.uint32[0],
2622                                                                          ref.uint32[1],
2623                                                                          ref.uint32[2],
2624                                                                          ref.uint32[3]);
2625                         const UVec4     threshold       (1);
2626
2627                         return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2628                 }
2629
2630                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2631                 {
2632                         const IVec4     resColor        (access.getPixelInt(x, y));
2633                         const IVec4     refColor        (ref.int32[0],
2634                                                                          ref.int32[1],
2635                                                                          ref.int32[2],
2636                                                                          ref.int32[3]);
2637                         const IVec4     threshold       (1);
2638
2639                         return !(tcu::anyNotEqual(tcu::logicalAnd(lessThanEqual(tcu::absDiff(resColor, refColor), threshold), channelMask), channelMask));
2640                 }
2641
2642                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2643                 {
2644                         const Vec4      resColor                (access.getPixel(x, y));
2645                         const Vec4      refColor                (ref.float32[0],
2646                                                                                  ref.float32[1],
2647                                                                                  ref.float32[2],
2648                                                                                  ref.float32[3]);
2649                         const IVec4     mantissaBits    (tcu::getTextureFormatMantissaBitDepth(format));
2650                         const IVec4     threshold               (10 * IVec4(1) << (23 - mantissaBits));
2651
2652                         DE_ASSERT(tcu::allEqual(greaterThanEqual(threshold, IVec4(0)), BVec4(true)));
2653
2654                         for (int ndx = 0; ndx < 4; ndx++)
2655                         {
2656                                 if (calcFloatDiff(resColor[ndx], refColor[ndx]) > threshold[ndx] && channelMask[ndx])
2657                                         return false;
2658                         }
2659
2660                         return true;
2661                 }
2662
2663                 default:
2664                         DE_FATAL("Invalid channel class");
2665                         return false;
2666         }
2667 }
2668
2669 class PixelStatus
2670 {
2671 public:
2672         enum Status
2673         {
2674                 STATUS_UNDEFINED        = 0,
2675                 STATUS_OK                       = 1,
2676                 STATUS_FAIL                     = 2,
2677
2678                 STATUS_LAST
2679         };
2680
2681                         PixelStatus                     (Status color, Status depth, Status stencil)
2682                 : m_status      ((deUint8)(color << COLOR_OFFSET)
2683                                         | (deUint8)((deUint8)depth << DEPTH_OFFSET)
2684                                         | (deUint8)((deUint8)stencil << STENCIL_OFFSET))
2685         {
2686         }
2687
2688         Status  getColorStatus          (void) const { return (Status)((m_status & COLOR_MASK) >> COLOR_OFFSET); }
2689         Status  getDepthStatus          (void) const { return (Status)((m_status & DEPTH_MASK) >> DEPTH_OFFSET); }
2690         Status  getStencilStatus        (void) const { return (Status)((m_status & STENCIL_MASK) >> STENCIL_OFFSET); }
2691
2692         void    setColorStatus          (Status status)
2693         {
2694                 DE_ASSERT(getColorStatus() == STATUS_UNDEFINED);
2695                 m_status |= (deUint8)(status << COLOR_OFFSET);
2696         }
2697
2698         void    setDepthStatus          (Status status)
2699         {
2700                 DE_ASSERT(getDepthStatus() == STATUS_UNDEFINED);
2701                 m_status |= (deUint8)(status << DEPTH_OFFSET);
2702         }
2703
2704         void    setStencilStatus        (Status status)
2705         {
2706                 DE_ASSERT(getStencilStatus() == STATUS_UNDEFINED);
2707                 m_status |= (deUint8)(status << STENCIL_OFFSET);
2708         }
2709
2710 private:
2711         enum
2712         {
2713                 COLOR_OFFSET    = 0,
2714                 DEPTH_OFFSET    = 2,
2715                 STENCIL_OFFSET  = 4,
2716
2717                 COLOR_MASK              = (3<<COLOR_OFFSET),
2718                 DEPTH_MASK              = (3<<DEPTH_OFFSET),
2719                 STENCIL_MASK    = (3<<STENCIL_OFFSET),
2720         };
2721         deUint8 m_status;
2722 };
2723
2724 void checkDepthRenderQuad (const ConstPixelBufferAccess&        result,
2725                                                    const IVec2&                                         posA,
2726                                                    const IVec2&                                         posB,
2727                                                    vector<PixelStatus>&                         status)
2728 {
2729         for (int y = posA.y(); y <= posB.y(); y++)
2730         for (int x = posA.x(); x <= posB.x(); x++)
2731         {
2732                 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2733
2734                 if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED)
2735                 {
2736                         const Vec4      minUvs          = computeUvs(posA, posB, IVec2(x-1, y-1));
2737                         const Vec4      maxUvs          = computeUvs(posA, posB, IVec2(x+1, y+1));
2738                         const bool      softCheck       = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2739                                                                         || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2740                         const float     resDepth        = result.getPixDepth(x, y);
2741
2742                         if (resDepth >= minUvs.x() && resDepth <= maxUvs.x())
2743                                 pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
2744                         else if (!softCheck)
2745                                 pixelStatus.setDepthStatus(PixelStatus::STATUS_FAIL);
2746                 }
2747         }
2748 }
2749
2750 void checkStencilRenderQuad (const ConstPixelBufferAccess&              result,
2751                                                          const IVec2&                                           posA,
2752                                                          const IVec2&                                           posB,
2753                                                          vector<PixelStatus>&                           status)
2754 {
2755         for (int y = posA.y(); y <= posB.y(); y++)
2756         for (int x = posA.x(); x <= posB.x(); x++)
2757         {
2758                 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2759
2760                 if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED)
2761                 {
2762                         const bool      softCheck       = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2763                                                                         || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2764
2765                         if (result.getPixStencil(x, y) == STENCIL_VALUE)
2766                                 pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
2767                         else if (!softCheck)
2768                                 pixelStatus.setStencilStatus(PixelStatus::STATUS_FAIL);
2769                 }
2770         }
2771 }
2772
2773 void checkColorRenderQuad (const ConstPixelBufferAccess&        result,
2774                                                    const IVec2&                                         posA,
2775                                                    const IVec2&                                         posB,
2776                                                    vector<PixelStatus>&                         status)
2777 {
2778         const tcu::TextureFormat&               format                          = result.getFormat();
2779         const bool                                              srgb                            = tcu::isSRGB(format);
2780         const tcu::TextureChannelClass  channelClass            = tcu::getTextureChannelClass(format.type);
2781         const tcu::TextureFormatInfo    textureInfo                     = tcu::getTextureFormatInfo(format);
2782         const float                                             clampMin                        = (float)(-MAX_INTEGER_VALUE);
2783         const float                                             clampMax                        = (float)(MAX_INTEGER_VALUE);
2784         const Vec4                                              valueMax                        (de::clamp(textureInfo.valueMax[0], clampMin, clampMax),
2785                                                                                                                  de::clamp(textureInfo.valueMax[1], clampMin, clampMax),
2786                                                                                                                  de::clamp(textureInfo.valueMax[2], clampMin, clampMax),
2787                                                                                                                  de::clamp(textureInfo.valueMax[3], clampMin, clampMax));
2788
2789         const Vec4                                              valueMin                        (de::clamp(textureInfo.valueMin[0], clampMin, clampMax),
2790                                                                                                                  de::clamp(textureInfo.valueMin[1], clampMin, clampMax),
2791                                                                                                                  de::clamp(textureInfo.valueMin[2], clampMin, clampMax),
2792                                                                                                                  de::clamp(textureInfo.valueMin[3], clampMin, clampMax));
2793         const BVec4                                             channelMask                     = tcu::getTextureFormatChannelMask(format);
2794
2795         IVec4                                           formatBitDepths = tcu::getTextureFormatBitDepth(format);
2796         Vec4                                            threshold = Vec4(1.0f) / Vec4((float)(1 << formatBitDepths.x()),
2797                                                                                                                                 (float)(1 << formatBitDepths.y()),
2798                                                                                                                                 (float)(1 << formatBitDepths.z()),
2799                                                                                                                                 (float)(1 << formatBitDepths.w()));
2800
2801         switch (channelClass)
2802         {
2803                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2804                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2805                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2806                 {
2807                         for (int y = posA.y(); y <= posB.y(); y++)
2808                         for (int x = posA.x(); x <= posB.x(); x++)
2809                         {
2810                                 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2811
2812                                 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2813                                 {
2814                                         const Vec4      minUvs          = computeUvs(posA, posB, IVec2(x-1, y-1));
2815                                         const Vec4      maxUvs          = computeUvs(posA, posB, IVec2(x+1, y+1));
2816                                         const bool      softCheck       = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2817                                                                                         || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2818
2819                                         const Vec4      resColor        (result.getPixel(x, y));
2820
2821                                         const Vec4      minRefColor     = srgb ? tcu::linearToSRGB(valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs))
2822                                                                                                          : valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs) - threshold;
2823                                         const Vec4      maxRefColor     = srgb ? tcu::linearToSRGB(valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs))
2824                                                                                                          : valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs) + threshold;
2825
2826                                         DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2827                                         DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2828                                         DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2829                                         DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2830
2831                                         if (tcu::anyNotEqual(tcu::logicalAnd(
2832                                                                                         tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2833                                                                                                                         lessThanEqual(resColor, maxRefColor)),
2834                                                                                         channelMask), channelMask))
2835                                         {
2836                                                 if (!softCheck)
2837                                                         pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2838                                         }
2839                                         else
2840                                                 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2841                                 }
2842                         }
2843
2844                         break;
2845                 }
2846
2847                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2848                 {
2849                         for (int y = posA.y(); y <= posB.y(); y++)
2850                         for (int x = posA.x(); x <= posB.x(); x++)
2851                         {
2852                                 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2853
2854                                 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2855                                 {
2856                                         const Vec4      minUvs                  = computeUvs(posA, posB, IVec2(x-1, y-1));
2857                                         const Vec4      maxUvs                  = computeUvs(posA, posB, IVec2(x+1, y+1));
2858                                         const bool      softCheck               = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2859                                                                                                 || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2860
2861                                         const UVec4     resColor                (result.getPixelUint(x, y));
2862
2863                                         const Vec4      minRefColorF    = valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
2864                                         const Vec4      maxRefColorF    = valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
2865
2866                                         const UVec4     minRefColor             (minRefColorF.asUint());
2867                                         const UVec4     maxRefColor             (maxRefColorF.asUint());
2868
2869                                         DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2870                                         DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2871                                         DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2872                                         DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2873
2874                                         if (tcu::anyNotEqual(tcu::logicalAnd(
2875                                                                                         tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2876                                                                                                                         lessThanEqual(resColor, maxRefColor)),
2877                                                                                         channelMask), channelMask))
2878                                         {
2879                                                 if (!softCheck)
2880                                                         pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2881                                         }
2882                                         else
2883                                                 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2884                                 }
2885                         }
2886
2887                         break;
2888                 }
2889
2890                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2891                 {
2892                         for (int y = posA.y(); y <= posB.y(); y++)
2893                         for (int x = posA.x(); x <= posB.x(); x++)
2894                         {
2895                                 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2896
2897                                 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2898                                 {
2899                                         const Vec4      minUvs                  = computeUvs(posA, posB, IVec2(x-1, y-1));
2900                                         const Vec4      maxUvs                  = computeUvs(posA, posB, IVec2(x+1, y+1));
2901                                         const bool      softCheck               = std::abs(x - posA.x()) <= 1 || std::abs(x - posB.x()) <= 1
2902                                                                                                 || std::abs(y - posA.y()) <= 1 || std::abs(y - posB.y()) <= 1;
2903
2904                                         const IVec4     resColor                (result.getPixelInt(x, y));
2905
2906                                         const Vec4      minRefColorF    = valueMax * minUvs + valueMin * (Vec4(1.0f) - minUvs);
2907                                         const Vec4      maxRefColorF    = valueMax * maxUvs + valueMin * (Vec4(1.0f) - maxUvs);
2908
2909                                         const IVec4     minRefColor             (minRefColorF.asInt());
2910                                         const IVec4     maxRefColor             (maxRefColorF.asInt());
2911
2912                                         DE_ASSERT(minRefColor[0] <= maxRefColor[0]);
2913                                         DE_ASSERT(minRefColor[1] <= maxRefColor[1]);
2914                                         DE_ASSERT(minRefColor[2] <= maxRefColor[2]);
2915                                         DE_ASSERT(minRefColor[3] <= maxRefColor[3]);
2916
2917                                         if (tcu::anyNotEqual(tcu::logicalAnd(
2918                                                                                         tcu::logicalAnd(greaterThanEqual(resColor, minRefColor),
2919                                                                                                                         lessThanEqual(resColor, maxRefColor)),
2920                                                                                         channelMask), channelMask))
2921                                         {
2922                                                 if (!softCheck)
2923                                                         pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2924                                         }
2925                                         else
2926                                                 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2927                                 }
2928                         }
2929
2930                         break;
2931                 }
2932
2933                 default:
2934                         DE_FATAL("Invalid channel class");
2935         }
2936 }
2937
2938 void checkColorClear (const ConstPixelBufferAccess&     result,
2939                                           const UVec2&                                  offset,
2940                                           const UVec2&                                  size,
2941                                           vector<PixelStatus>&                  status,
2942                                           const VkClearColorValue&              color)
2943 {
2944         DE_ASSERT(offset.x() + size.x() <= (deUint32)result.getWidth());
2945         DE_ASSERT(offset.y() + size.y() <= (deUint32)result.getHeight());
2946
2947         DE_ASSERT(result.getWidth() * result.getHeight() == (int)status.size());
2948
2949         for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2950         for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2951         {
2952                 PixelStatus& pixelStatus = status[x + y * result.getWidth()];
2953
2954                 DE_ASSERT(x + y * result.getWidth() < (int)status.size());
2955
2956                 if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
2957                 {
2958                         if (comparePixelToColorClearValue(result, x, y, color))
2959                                 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
2960                         else
2961                                 pixelStatus.setColorStatus(PixelStatus::STATUS_FAIL);
2962                 }
2963         }
2964 }
2965
2966 void checkDepthClear (const ConstPixelBufferAccess&     result,
2967                                           const UVec2&                                  offset,
2968                                           const UVec2&                                  size,
2969                                           vector<PixelStatus>&                  status,
2970                                           float                                                 depth)
2971 {
2972         for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2973         for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2974         {
2975                 PixelStatus&    pixelStatus     = status[x + y * result.getWidth()];
2976
2977                 if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED)
2978                 {
2979                         if (comparePixelToDepthClearValue(result, x, y, depth))
2980                                 pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
2981                         else
2982                                 pixelStatus.setDepthStatus(PixelStatus::STATUS_FAIL);
2983                 }
2984         }
2985 }
2986
2987 void checkStencilClear (const ConstPixelBufferAccess&   result,
2988                                                 const UVec2&                                    offset,
2989                                                 const UVec2&                                    size,
2990                                                 vector<PixelStatus>&                    status,
2991                                                 deUint32                                                stencil)
2992 {
2993         for (int y = offset.y(); y < (int)(offset.y() + size.y()); y++)
2994         for (int x = offset.x(); x < (int)(offset.x() + size.x()); x++)
2995         {
2996                 PixelStatus&    pixelStatus     = status[x + y * result.getWidth()];
2997
2998                 if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED)
2999                 {
3000                         if (comparePixelToStencilClearValue(result, x, y, stencil))
3001                                 pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3002                         else
3003                                 pixelStatus.setStencilStatus(PixelStatus::STATUS_FAIL);
3004                 }
3005         }
3006 }
3007
3008 bool verifyAttachment (const ConstPixelBufferAccess&            result,
3009                                            const Maybe<ConstPixelBufferAccess>& secondaryResult,
3010                                            const RenderPass&                                    renderPassInfo,
3011                                            const Maybe<VkClearValue>&                   renderPassClearValue,
3012                                            const Maybe<VkClearValue>&                   imageClearValue,
3013                                            const vector<Subpass>&                               subpasses,
3014                                            const vector<SubpassRenderInfo>&             subpassRenderInfo,
3015                                            const PixelBufferAccess&                             errorImage,
3016                                            deUint32                                                             attachmentIndex,
3017                                            const UVec2&                                                 renderPos,
3018                                            const UVec2&                                                 renderSize)
3019 {
3020         const tcu::TextureFormat&               format                          = result.getFormat();
3021         const bool                                              hasDepth                        = tcu::hasDepthComponent(format.order);
3022         const bool                                              hasStencil                      = tcu::hasStencilComponent(format.order);
3023         const bool                                              isColorFormat           = !hasDepth && !hasStencil;
3024         const PixelStatus                               initialStatus           (isColorFormat ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK,
3025                                                                                                                  hasDepth ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK,
3026                                                                                                                  hasStencil ? PixelStatus::STATUS_UNDEFINED : PixelStatus::STATUS_OK);
3027
3028         bool                                                    attachmentIsUsed        = false;
3029         vector<PixelStatus>                             status                          (result.getWidth() * result.getHeight(), initialStatus);
3030         tcu::clear(errorImage, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
3031
3032         // Check if attachment is used
3033         for (int subpassNdx = 0; subpassNdx < (int)subpasses.size(); subpassNdx++)
3034         {
3035                 const Subpass&                  subpass                 = subpasses[subpassNdx];
3036                 const Maybe<deUint32>   attachmentNdx   = findColorAttachment(subpass, attachmentIndex);
3037
3038                 if (attachmentNdx || subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex)
3039                         attachmentIsUsed = true;
3040         }
3041
3042         // Set all pixels that have undefined values to OK
3043         if (attachmentIsUsed && (((isColorFormat || hasDepth) && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3044                                                         || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)))
3045         {
3046                 for(int y = renderPos.y(); y < (int)(renderPos.y() + renderSize.y()); y++)
3047                 for(int x = renderPos.x(); x < (int)(renderPos.x() + renderSize.x()); x++)
3048                 {
3049                         PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3050
3051                         if (isColorFormat && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3052                                 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
3053                         else
3054                         {
3055                                 if (hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3056                                         pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
3057
3058                                 if (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_DONT_CARE)
3059                                         pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3060                         }
3061                 }
3062         }
3063
3064         // Check renderpass rendering results
3065         if (renderPassInfo.getAttachments()[attachmentIndex].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE
3066                 || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE))
3067         {
3068                 // Check subpass rendering results
3069                 for (int subpassNdx = (int)subpasses.size() - 1; subpassNdx >= 0; subpassNdx--)
3070                 {
3071                         const Subpass&                          subpass                 = subpasses[subpassNdx];
3072                         const SubpassRenderInfo&        renderInfo              = subpassRenderInfo[subpassNdx];
3073                         const Maybe<deUint32>           attachmentNdx   = findColorAttachment(subpass, attachmentIndex);
3074
3075                         // Check rendered quad
3076                         if (renderInfo.getRenderQuad() && (attachmentNdx || subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex))
3077                         {
3078                                 const RenderQuad&       renderQuad      = *renderInfo.getRenderQuad();
3079                                 const Vec4                      posA            = renderQuad.getCornerA();
3080                                 const Vec4                      posB            = renderQuad.getCornerB();
3081                                 const Vec2                      origin          = Vec2((float)renderInfo.getViewportOffset().x(), (float)renderInfo.getViewportOffset().y()) + Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
3082                                 const Vec2                      p                       = Vec2((float)renderInfo.getViewportSize().x(), (float)renderInfo.getViewportSize().y()) / Vec2(2.0f);
3083                                 const IVec2                     posAI           ((deInt32)(origin.x() + (p.x() * posA.x())),
3084                                                                                                  (deInt32)(origin.y() + (p.y() * posA.y())));
3085                                 const IVec2                     posBI           ((deInt32)(origin.x() + (p.x() * posB.x())),
3086                                                                                                  (deInt32)(origin.y() + (p.y() * posB.y())));
3087
3088                                 if (isColorFormat)
3089                                         checkColorRenderQuad(result, posAI, posBI, status);
3090                                 else
3091                                 {
3092                                         if (hasDepth)
3093                                                 checkDepthRenderQuad(result, posAI, posBI, status);
3094
3095                                         if (hasDepth && hasStencil)
3096                                                 checkStencilRenderQuad(*secondaryResult, posAI, posBI, status);
3097                                         else if (hasStencil)
3098                                                 checkStencilRenderQuad(result, posAI, posBI, status);
3099                                 }
3100                         }
3101
3102                         // Check color attachment clears
3103                         if (attachmentNdx && !renderInfo.getColorClears().empty())
3104                         {
3105                                 const ColorClear& clear = renderInfo.getColorClears()[*attachmentNdx];
3106
3107                                 checkColorClear(result, clear.getOffset(), clear.getSize(), status, clear.getColor());
3108                         }
3109
3110                         // Check depth/stencil attachment clears
3111                         if (subpass.getDepthStencilAttachment().getAttachment() == attachmentIndex && renderInfo.getDepthStencilClear())
3112                         {
3113                                 const DepthStencilClear clear = *renderInfo.getDepthStencilClear();
3114
3115                                 if (hasDepth)
3116                                         checkDepthClear(result, clear.getOffset(), clear.getSize(), status, clear.getDepth());
3117
3118                                 if (hasDepth && hasStencil)
3119                                         checkStencilClear(*secondaryResult, clear.getOffset(), clear.getSize(), status, clear.getStencil());
3120                                 else if (hasStencil)
3121                                         checkStencilClear(result, clear.getOffset(), clear.getSize(), status, clear.getStencil());
3122                         }
3123                 }
3124
3125                 // Check renderpas clear results
3126                 if (attachmentIsUsed && renderPassClearValue)
3127                 {
3128                         if (isColorFormat)
3129                         {
3130                                 if (renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3131                                         checkColorClear(result, renderPos, renderSize, status, renderPassClearValue->color);
3132                         }
3133                         else
3134                         {
3135                                 if (hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3136                                         checkDepthClear(result, renderPos, renderSize, status, renderPassClearValue->depthStencil.depth);
3137
3138                                 if (hasDepth && hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3139                                         checkStencilClear(*secondaryResult, renderPos, renderSize, status, renderPassClearValue->depthStencil.stencil);
3140                                 else if (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3141                                         checkStencilClear(result, renderPos, renderSize, status, renderPassClearValue->depthStencil.stencil);
3142                         }
3143                 }
3144         }
3145
3146         // Set all pixels that have undefined values fater renderpass to OK
3147         if (attachmentIsUsed && (((isColorFormat || hasDepth) && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3148                                                         || (hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)))
3149         {
3150                 for(int y = renderPos.y(); y < (int)(renderPos.y() + renderSize.y()); y++)
3151                 for(int x = renderPos.x(); x < (int)(renderPos.x() + renderSize.x()); x++)
3152                 {
3153                         PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3154
3155                         if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED
3156                                 && isColorFormat && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3157                                 pixelStatus.setColorStatus(PixelStatus::STATUS_OK);
3158                         else
3159                         {
3160                                 if (pixelStatus.getDepthStatus() == PixelStatus::STATUS_UNDEFINED
3161                                         && hasDepth && renderPassInfo.getAttachments()[attachmentIndex].getLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3162                                         pixelStatus.setDepthStatus(PixelStatus::STATUS_OK);
3163
3164                                 if (pixelStatus.getStencilStatus() == PixelStatus::STATUS_UNDEFINED
3165                                         && hasStencil && renderPassInfo.getAttachments()[attachmentIndex].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_DONT_CARE)
3166                                         pixelStatus.setStencilStatus(PixelStatus::STATUS_OK);
3167                         }
3168                 }
3169         }
3170
3171         if (imageClearValue)
3172         {
3173                 if (isColorFormat)
3174                         checkColorClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->color);
3175                 else
3176                 {
3177                         if (hasDepth)
3178                                 checkDepthClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->depthStencil.depth);
3179
3180                         if (hasDepth && hasStencil)
3181                                 checkStencilClear(*secondaryResult, UVec2(0, 0), UVec2(secondaryResult->getWidth(), result.getHeight()), status, imageClearValue->depthStencil.stencil);
3182                         else if (hasStencil)
3183                                 checkStencilClear(result, UVec2(0, 0), UVec2(result.getWidth(), result.getHeight()), status, imageClearValue->depthStencil.stencil);
3184                 }
3185         }
3186
3187         {
3188                 bool isOk = true;
3189
3190                 for(int y = 0; y < result.getHeight(); y++)
3191                 for(int x = 0; x < result.getWidth(); x++)
3192                 {
3193                         const PixelStatus& pixelStatus = status[x + y * result.getWidth()];
3194
3195                         if (isColorFormat)
3196                         {
3197                                 if (pixelStatus.getColorStatus() != PixelStatus::STATUS_OK)
3198                                 {
3199                                         if (pixelStatus.getColorStatus() == PixelStatus::STATUS_UNDEFINED)
3200                                                 errorImage.setPixel(Vec4(1.0f, 1.0f, 0.0f, 1.0f), x, y);
3201                                         else if (pixelStatus.getColorStatus() == PixelStatus::STATUS_FAIL)
3202                                                 errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3203
3204                                         isOk = false;
3205                                 }
3206                         }
3207                         else
3208                         {
3209                                 if (hasDepth && pixelStatus.getDepthStatus() != PixelStatus::STATUS_OK)
3210                                 {
3211                                         errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3212                                         isOk = false;
3213                                 }
3214
3215                                 if (hasStencil && pixelStatus.getStencilStatus() != PixelStatus::STATUS_OK)
3216                                 {
3217                                         errorImage.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y);
3218                                         isOk = false;
3219                                 }
3220                         }
3221                 }
3222
3223                 return isOk;
3224         }
3225 }
3226
3227 bool logAndVerifyImages (TestLog&                                                                                       log,
3228                                                  const DeviceInterface&                                                         vk,
3229                                                  VkDevice                                                                                       device,
3230                                                  const vector<de::SharedPtr<AttachmentResources> >&     attachmentResources,
3231                                                  const vector<bool>&                                                            attachmentIsLazy,
3232                                                  const RenderPass&                                                                      renderPassInfo,
3233                                                  const vector<Maybe<VkClearValue> >&                            renderPassClearValues,
3234                                                  const vector<Maybe<VkClearValue> >&                            imageClearValues,
3235                                                  const vector<SubpassRenderInfo>&                                       subpassRenderInfo,
3236                                                  const UVec2&                                                                           targetSize,
3237                                                  const TestConfig&                                                                      config)
3238 {
3239         vector<tcu::TextureLevel>       referenceAttachments;
3240         bool                                            isOk                                    = true;
3241
3242         log << TestLog::Message << "Reference images fill undefined pixels with grid pattern." << TestLog::EndMessage;
3243
3244         renderReferenceImages(referenceAttachments, renderPassInfo, targetSize, imageClearValues, renderPassClearValues, subpassRenderInfo, config.renderPos, config.renderSize);
3245
3246         for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3247         {
3248                 if (!attachmentIsLazy[attachmentNdx])
3249                 {
3250                         const Attachment                        attachment              = renderPassInfo.getAttachments()[attachmentNdx];
3251                         const tcu::TextureFormat        format                  = mapVkFormat(attachment.getFormat());
3252
3253                         if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
3254                         {
3255                                 const tcu::TextureFormat        depthFormat             = getDepthCopyFormat(attachment.getFormat());
3256                                 const VkDeviceSize                      depthBufferSize = targetSize.x() * targetSize.y() * depthFormat.getPixelSize();
3257                                 void* const                                     depthPtr                = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
3258
3259                                 const tcu::TextureFormat        stencilFormat           = getStencilCopyFormat(attachment.getFormat());
3260                                 const VkDeviceSize                      stencilBufferSize       = targetSize.x() * targetSize.y() * stencilFormat.getPixelSize();
3261                                 void* const                                     stencilPtr                      = attachmentResources[attachmentNdx]->getSecondaryResultMemory().getHostPtr();
3262
3263                                 const VkMappedMemoryRange       ranges[] =
3264                                 {
3265                                         {
3266                                                 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,                                                          // sType;
3267                                                 DE_NULL,                                                                                                                        // pNext;
3268                                                 attachmentResources[attachmentNdx]->getResultMemory().getMemory(),      // mem;
3269                                                 attachmentResources[attachmentNdx]->getResultMemory().getOffset(),      // offset;
3270                                                 depthBufferSize                                                                                                         // size;
3271                                         },
3272                                         {
3273                                                 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,                                                                          // sType;
3274                                                 DE_NULL,                                                                                                                                        // pNext;
3275                                                 attachmentResources[attachmentNdx]->getSecondaryResultMemory().getMemory(),     // mem;
3276                                                 attachmentResources[attachmentNdx]->getSecondaryResultMemory().getOffset(),     // offset;
3277                                                 stencilBufferSize                                                                                                                       // size;
3278                                         }
3279                                 };
3280                                 VK_CHECK(vk.invalidateMappedMemoryRanges(device, 2u, ranges));
3281
3282                                 {
3283                                         const ConstPixelBufferAccess    depthAccess             (depthFormat, targetSize.x(), targetSize.y(), 1, depthPtr);
3284                                         const ConstPixelBufferAccess    stencilAccess   (stencilFormat, targetSize.x(), targetSize.y(), 1, stencilPtr);
3285                                         tcu::TextureLevel                               errorImage              (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y());
3286
3287                                         log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Depth", "Attachment " + de::toString(attachmentNdx) + " Depth", depthAccess);
3288                                         log << TestLog::Image("Attachment" + de::toString(attachmentNdx) + "Stencil", "Attachment " + de::toString(attachmentNdx) + " Stencil", stencilAccess);
3289
3290                                         log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess());
3291
3292                                         if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE)
3293                                                 && !verifyAttachment(depthAccess, tcu::just(stencilAccess), renderPassInfo, renderPassClearValues[attachmentNdx], imageClearValues[attachmentNdx], renderPassInfo.getSubpasses(), subpassRenderInfo, errorImage.getAccess(), (deUint32)attachmentNdx, config.renderPos, config.renderSize))
3294                                         {
3295                                                 log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
3296                                                 isOk = false;
3297                                         }
3298                                 }
3299                         }
3300                         else
3301                         {
3302                                 const VkDeviceSize                      bufferSize      = targetSize.x() * targetSize.y() * format.getPixelSize();
3303                                 void* const                                     ptr                     = attachmentResources[attachmentNdx]->getResultMemory().getHostPtr();
3304
3305                                 const VkMappedMemoryRange       range   =
3306                                 {
3307                                         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,                                                          // sType;
3308                                         DE_NULL,                                                                                                                        // pNext;
3309                                         attachmentResources[attachmentNdx]->getResultMemory().getMemory(),      // mem;
3310                                         attachmentResources[attachmentNdx]->getResultMemory().getOffset(),      // offset;
3311                                         bufferSize                                                                                                                      // size;
3312                                 };
3313                                 VK_CHECK(vk.invalidateMappedMemoryRanges(device, 1u, &range));
3314
3315                                 {
3316                                         const ConstPixelBufferAccess    access          (format, targetSize.x(), targetSize.y(), 1, ptr);
3317                                         tcu::TextureLevel                               errorImage      (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), targetSize.x(), targetSize.y());
3318
3319                                         log << TestLog::Image("Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx), access);
3320                                         log << TestLog::Image("AttachmentReference" + de::toString(attachmentNdx), "Attachment reference " + de::toString(attachmentNdx), referenceAttachments[attachmentNdx].getAccess());
3321
3322                                         if ((renderPassInfo.getAttachments()[attachmentNdx].getStoreOp() == VK_ATTACHMENT_STORE_OP_STORE || renderPassInfo.getAttachments()[attachmentNdx].getStencilStoreOp() == VK_ATTACHMENT_STORE_OP_STORE)
3323                                                 && !verifyAttachment(access, tcu::nothing<ConstPixelBufferAccess>(), renderPassInfo, renderPassClearValues[attachmentNdx], imageClearValues[attachmentNdx], renderPassInfo.getSubpasses(), subpassRenderInfo, errorImage.getAccess(), (deUint32)attachmentNdx, config.renderPos, config.renderSize))
3324                                         {
3325                                                 log << TestLog::Image("AttachmentError" + de::toString(attachmentNdx), "Attachment Error " + de::toString(attachmentNdx), errorImage.getAccess());
3326                                                 isOk = false;
3327                                         }
3328                                 }
3329                         }
3330                 }
3331         }
3332
3333         return isOk;
3334 }
3335
3336 std::string getAttachmentType (VkFormat vkFormat)
3337 {
3338         const tcu::TextureFormat                format                  = mapVkFormat(vkFormat);
3339         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(format.type);
3340
3341         switch (channelClass)
3342         {
3343                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
3344                         return "ivec4";
3345
3346                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
3347                         return "uvec4";
3348
3349                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
3350                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
3351                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
3352                         return "vec4";
3353
3354                 default:
3355                         DE_FATAL("Unknown channel class");
3356                         return "";
3357         }
3358 }
3359
3360 void createTestShaders (SourceCollections& dst, TestConfig config)
3361 {
3362         if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
3363         {
3364                 const vector<Subpass>&  subpasses       = config.renderPass.getSubpasses();
3365
3366                 for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
3367                 {
3368                         const Subpass&          subpass         = subpasses[subpassNdx];
3369                         std::ostringstream      vertexShader;
3370                         std::ostringstream      fragmentShader;
3371
3372                         vertexShader << "#version 310 es\n"
3373                                                  << "layout(location = 0) in highp vec4 a_position;\n"
3374                                                  << "layout(location = 0) out highp vec2 v_color;\n"
3375                                                  << "void main (void) {\n"
3376                                                  << "\thighp float a = 0.5 + a_position.x;\n"
3377                                                  << "\thighp float b = 0.5 + a_position.y;\n"
3378                                                  << "\tv_color = vec2(a, b);\n"
3379                                                  << "\tgl_Position = a_position;\n"
3380                                                  << "}\n";
3381
3382                         fragmentShader << "#version 310 es\n"
3383                                                    << "layout(location = 0) in highp vec2 v_color;\n";
3384
3385                         for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
3386                         {
3387                                 const std::string attachmentType = getAttachmentType(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3388                                 fragmentShader << "layout(location = " << attachmentNdx << ") out highp " << attachmentType << " o_color" << attachmentNdx << ";\n";
3389                         }
3390
3391                         fragmentShader  << "void main (void) {\n"
3392                                                         << "\thighp vec4 scale = vec4(v_color.x, v_color.y, v_color.x * v_color.y, (v_color.x + v_color.y) / 2.0);\n";
3393
3394                         for (size_t attachmentNdx = 0; attachmentNdx < subpass.getColorAttachments().size(); attachmentNdx++)
3395                         {
3396                                 const tcu::TextureFormat                format                  = mapVkFormat(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3397                                 const tcu::TextureFormatInfo    formatInfo              = tcu::getTextureFormatInfo(format);
3398                                 const float                                             clampMin                = (float)(-MAX_INTEGER_VALUE);
3399                                 const float                                             clampMax                = (float)(MAX_INTEGER_VALUE);
3400                                 const Vec4                                              valueMax                (de::clamp(formatInfo.valueMax[0], clampMin, clampMax),
3401                                                                                                                                  de::clamp(formatInfo.valueMax[1], clampMin, clampMax),
3402                                                                                                                                  de::clamp(formatInfo.valueMax[2], clampMin, clampMax),
3403                                                                                                                                  de::clamp(formatInfo.valueMax[3], clampMin, clampMax));
3404
3405                                 const Vec4                                              valueMin                (de::clamp(formatInfo.valueMin[0], clampMin, clampMax),
3406                                                                                                                                  de::clamp(formatInfo.valueMin[1], clampMin, clampMax),
3407                                                                                                                                  de::clamp(formatInfo.valueMin[2], clampMin, clampMax),
3408                                                                                                                                  de::clamp(formatInfo.valueMin[3], clampMin, clampMax));
3409                                 const std::string                               attachmentType  = getAttachmentType(config.renderPass.getAttachments()[subpass.getColorAttachments()[attachmentNdx].getAttachment()].getFormat());
3410
3411                                 fragmentShader << "\to_color" << attachmentNdx << " = " << attachmentType << "(vec4" << valueMin << " + vec4" << (valueMax - valueMin)  << " * scale);\n";
3412                         }
3413
3414                         fragmentShader << "}\n";
3415
3416                         dst.glslSources.add(de::toString(subpassNdx) + "-vert") << glu::VertexSource(vertexShader.str());
3417                         dst.glslSources.add(de::toString(subpassNdx) + "-frag") << glu::FragmentSource(fragmentShader.str());
3418                 }
3419         }
3420 }
3421
3422 void initializeAttachmentIsLazy (vector<bool>& attachmentIsLazy, const vector<Attachment>& attachments, TestConfig::ImageMemory imageMemory)
3423 {
3424         bool lastAttachmentWasLazy = false;
3425
3426         for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3427         {
3428                 if (attachments[attachmentNdx].getLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD
3429                         && attachments[attachmentNdx].getStoreOp() != VK_ATTACHMENT_STORE_OP_STORE
3430                         && attachments[attachmentNdx].getStencilLoadOp() != VK_ATTACHMENT_LOAD_OP_LOAD
3431                         && attachments[attachmentNdx].getStencilStoreOp() != VK_ATTACHMENT_STORE_OP_STORE)
3432                 {
3433                         if (imageMemory == TestConfig::IMAGEMEMORY_LAZY || (imageMemory & TestConfig::IMAGEMEMORY_LAZY && !lastAttachmentWasLazy))
3434                         {
3435                                 attachmentIsLazy.push_back(true);
3436                                 lastAttachmentWasLazy = true;
3437                         }
3438                         else if (imageMemory & TestConfig::IMAGEMEMORY_STRICT)
3439                         {
3440                                 attachmentIsLazy.push_back(false);
3441                                 lastAttachmentWasLazy = false;
3442                         }
3443                         else
3444                                 DE_FATAL("Unknown imageMemory");
3445                 }
3446                 else
3447                         attachmentIsLazy.push_back(false);
3448         }
3449 }
3450
3451 void initializeSubpassIsSecondary (vector<bool>& subpassIsSecondary, const vector<Subpass>& subpasses, TestConfig::CommandBufferTypes commandBuffer)
3452 {
3453         bool lastSubpassWasSecondary = false;
3454
3455         for (size_t subpassNdx = 0; subpassNdx < subpasses.size(); subpassNdx++)
3456         {
3457                 if (commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary))
3458                 {
3459                         subpassIsSecondary.push_back(true);
3460                         lastSubpassWasSecondary = true;
3461                 }
3462                 else if (commandBuffer & TestConfig::COMMANDBUFFERTYPES_INLINE)
3463                 {
3464                         subpassIsSecondary.push_back(false);
3465                         lastSubpassWasSecondary = false;
3466                 }
3467                 else
3468                         DE_FATAL("Unknown commandBuffer");
3469         }
3470 }
3471
3472 void initializeImageClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments, const vector<bool>& isLazy)
3473 {
3474         for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3475         {
3476                 if (!isLazy[attachmentNdx])
3477                         clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng)));
3478                 else
3479                         clearValues.push_back(nothing<VkClearValue>());
3480         }
3481 }
3482
3483 void initializeRenderPassClearValues (de::Random& rng, vector<Maybe<VkClearValue> >& clearValues, const vector<Attachment>& attachments)
3484 {
3485         for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3486         {
3487                 if (attachments[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR
3488                         || attachments[attachmentNdx].getStencilLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR)
3489                 {
3490                         clearValues.push_back(just(randomClearValue(attachments[attachmentNdx], rng)));
3491                 }
3492                 else
3493                         clearValues.push_back(nothing<VkClearValue>());
3494         }
3495 }
3496
3497 void initializeSubpassClearValues (de::Random& rng, vector<vector<VkClearColorValue> >& clearValues, const RenderPass& renderPass)
3498 {
3499         clearValues.resize(renderPass.getSubpasses().size());
3500
3501         for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
3502         {
3503                 const Subpass&                                          subpass                         = renderPass.getSubpasses()[subpassNdx];
3504                 const vector<AttachmentReference>&      colorAttachments        = subpass.getColorAttachments();
3505
3506                 clearValues[subpassNdx].resize(colorAttachments.size());
3507
3508                 for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
3509                 {
3510                         const AttachmentReference&      attachmentRef   = colorAttachments[attachmentRefNdx];
3511                         const Attachment&                       attachment              = renderPass.getAttachments()[attachmentRef.getAttachment()];
3512
3513                         clearValues[subpassNdx][attachmentRefNdx] = randomColorClearValue(attachment, rng);
3514                 }
3515         }
3516 }
3517
3518 void logSubpassRenderInfo (TestLog&                                     log,
3519                                                    const SubpassRenderInfo&     info)
3520 {
3521         log << TestLog::Message << "Viewport, offset: " << info.getViewportOffset() << ", size: " << info.getViewportSize() << TestLog::EndMessage;
3522
3523         if (info.isSecondary())
3524                 log << TestLog::Message << "Subpass uses secondary command buffers" << TestLog::EndMessage;
3525         else
3526                 log << TestLog::Message << "Subpass uses inlined commands" << TestLog::EndMessage;
3527
3528         for (deUint32 attachmentNdx = 0; attachmentNdx < info.getColorClears().size(); attachmentNdx++)
3529         {
3530                 const ColorClear&       colorClear      = info.getColorClears()[attachmentNdx];
3531
3532                 log << TestLog::Message << "Clearing color attachment " << attachmentNdx
3533                         << ". Offset: " << colorClear.getOffset()
3534                         << ", Size: " << colorClear.getSize()
3535                         << ", Color: " << clearColorToString(info.getColorAttachment(attachmentNdx).getFormat(), colorClear.getColor()) << TestLog::EndMessage;
3536         }
3537
3538         if (info.getDepthStencilClear())
3539         {
3540                 const DepthStencilClear&        depthStencilClear       = *info.getDepthStencilClear();
3541
3542                 log << TestLog::Message << "Clearing depth stencil attachment"
3543                         << ". Offset: " << depthStencilClear.getOffset()
3544                         << ", Size: " << depthStencilClear.getSize()
3545                         << ", Depth: " << depthStencilClear.getDepth()
3546                         << ", Stencil: " << depthStencilClear.getStencil() << TestLog::EndMessage;
3547         }
3548
3549         if (info.getRenderQuad())
3550         {
3551                 const RenderQuad&       renderQuad      = *info.getRenderQuad();
3552
3553                 log << TestLog::Message << "Rendering gradient quad to " << renderQuad.getCornerA() << " -> " << renderQuad.getCornerB() << TestLog::EndMessage;
3554         }
3555 }
3556
3557 void logTestCaseInfo (TestLog&                                                                  log,
3558                                           const TestConfig&                                                     config,
3559                                           const vector<bool>&                                           attachmentIsLazy,
3560                                           const vector<Maybe<VkClearValue> >&           imageClearValues,
3561                                           const vector<Maybe<VkClearValue> >&           renderPassClearValues,
3562                                           const vector<SubpassRenderInfo>&                      subpassRenderInfo)
3563 {
3564         const RenderPass&       renderPass      = config.renderPass;
3565
3566         logRenderPassInfo(log, renderPass);
3567
3568         DE_ASSERT(attachmentIsLazy.size() == renderPass.getAttachments().size());
3569         DE_ASSERT(imageClearValues.size() == renderPass.getAttachments().size());
3570         DE_ASSERT(renderPassClearValues.size() == renderPass.getAttachments().size());
3571
3572         log << TestLog::Message << "TargetSize: " << config.targetSize << TestLog::EndMessage;
3573         log << TestLog::Message << "Render area, Offset: " << config.renderPos << ", Size: " << config.renderSize << TestLog::EndMessage;
3574
3575         for (size_t attachmentNdx = 0; attachmentNdx < attachmentIsLazy.size(); attachmentNdx++)
3576         {
3577                 const tcu::ScopedLogSection     section (log, "Attachment" + de::toString(attachmentNdx), "Attachment " + de::toString(attachmentNdx));
3578
3579                 if (attachmentIsLazy[attachmentNdx])
3580                         log << TestLog::Message << "Is lazy." << TestLog::EndMessage;
3581
3582                 if (imageClearValues[attachmentNdx])
3583                         log << TestLog::Message << "Image is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), *imageClearValues[attachmentNdx]) << " before rendering." << TestLog::EndMessage;
3584
3585                 if (renderPass.getAttachments()[attachmentNdx].getLoadOp() == VK_ATTACHMENT_LOAD_OP_CLEAR && renderPassClearValues[attachmentNdx])
3586                         log << TestLog::Message << "Attachment is cleared to " << clearValueToString(renderPass.getAttachments()[attachmentNdx].getFormat(), *renderPassClearValues[attachmentNdx]) << " in the beginning of the render pass." << TestLog::EndMessage;
3587         }
3588
3589         for (size_t subpassNdx = 0; subpassNdx < renderPass.getSubpasses().size(); subpassNdx++)
3590         {
3591                 const tcu::ScopedLogSection section (log, "Subpass" + de::toString(subpassNdx), "Subpass " + de::toString(subpassNdx));
3592
3593                 logSubpassRenderInfo(log, subpassRenderInfo[subpassNdx]);
3594         }
3595 }
3596
3597 void initializeSubpassRenderInfo (vector<SubpassRenderInfo>& renderInfos, de::Random& rng, const RenderPass& renderPass, const TestConfig& config)
3598 {
3599         const TestConfig::CommandBufferTypes    commandBuffer                   = config.commandBufferTypes;
3600         const vector<Subpass>&                                  subpasses                               = renderPass.getSubpasses();
3601         bool                                                                    lastSubpassWasSecondary = false;
3602
3603         for (deUint32 subpassNdx = 0; subpassNdx < (deUint32)subpasses.size(); subpassNdx++)
3604         {
3605                 const Subpass&                          subpass                         = subpasses[subpassNdx];
3606                 const bool                                      subpassIsSecondary      = commandBuffer == TestConfig::COMMANDBUFFERTYPES_SECONDARY
3607                                                                                                                 || (commandBuffer & TestConfig::COMMANDBUFFERTYPES_SECONDARY && !lastSubpassWasSecondary) ? true : false;
3608                 const UVec2                                     viewportSize            ((config.renderSize * UVec2(2)) / UVec2(3));
3609                 const UVec2                                     viewportOffset          (config.renderPos.x() + (subpassNdx % 2) * (config.renderSize.x() / 3),
3610                                                                                                                  config.renderPos.y() + ((subpassNdx / 2) % 2) * (config.renderSize.y() / 3));
3611
3612                 vector<ColorClear>                      colorClears;
3613                 Maybe<DepthStencilClear>        depthStencilClear;
3614                 Maybe<RenderQuad>                       renderQuad;
3615
3616                 lastSubpassWasSecondary         = subpassIsSecondary;
3617
3618                 if (config.renderTypes & TestConfig::RENDERTYPES_CLEAR)
3619                 {
3620                         const vector<AttachmentReference>&      colorAttachments        = subpass.getColorAttachments();
3621
3622                         for (size_t attachmentRefNdx = 0; attachmentRefNdx < colorAttachments.size(); attachmentRefNdx++)
3623                         {
3624                                 const AttachmentReference&      attachmentRef   = colorAttachments[attachmentRefNdx];
3625                                 const Attachment&                       attachment              = renderPass.getAttachments()[attachmentRef.getAttachment()];
3626                                 const UVec2                                     size                    ((viewportSize * UVec2(2)) / UVec2(3));
3627                                 const UVec2                                     offset                  (viewportOffset.x() + ((deUint32)attachmentRefNdx % 2u) * (viewportSize.x() / 3u),
3628                                                                                                                          viewportOffset.y() + (((deUint32)attachmentRefNdx / 2u) % 2u) * (viewportSize.y() / 3u));
3629                                 const VkClearColorValue         color                   = randomColorClearValue(attachment, rng);
3630
3631                                 colorClears.push_back(ColorClear(offset, size, color));
3632                         }
3633
3634                         if (subpass.getDepthStencilAttachment().getAttachment() != VK_ATTACHMENT_UNUSED)
3635                         {
3636                                 const Attachment&       attachment              = renderPass.getAttachments()[subpass.getDepthStencilAttachment().getAttachment()];
3637                                 const UVec2                     size                    ((viewportSize * UVec2(2)) / UVec2(3));
3638                                 const UVec2                     offset                  (viewportOffset.x() + ((deUint32)colorAttachments.size() % 2u) * (viewportSize.x() / 3u),
3639                                                                                                          viewportOffset.y() + (((deUint32)colorAttachments.size() / 2u) % 2u) * (viewportSize.y() / 3u));
3640                                 const VkClearValue      value                   = randomClearValue(attachment, rng);
3641
3642                                 depthStencilClear = tcu::just(DepthStencilClear(offset, size, value.depthStencil.depth, value.depthStencil.stencil));
3643                         }
3644                 }
3645
3646                 if (config.renderTypes & TestConfig::RENDERTYPES_DRAW)
3647                         renderQuad = tcu::just(RenderQuad(tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f), tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f)));
3648
3649                 renderInfos.push_back(SubpassRenderInfo(renderPass, subpassNdx, subpassIsSecondary, viewportOffset, viewportSize, renderQuad, colorClears, depthStencilClear));
3650         }
3651 }
3652
3653 void checkTextureFormatSupport (TestLog&                                        log,
3654                                                                 const InstanceInterface&        vk,
3655                                                                 VkPhysicalDevice                        device,
3656                                                                 const vector<Attachment>&       attachments)
3657 {
3658         bool supported = true;
3659
3660         for (size_t attachmentNdx = 0; attachmentNdx < attachments.size(); attachmentNdx++)
3661         {
3662                 const Attachment&                       attachment                                      = attachments[attachmentNdx];
3663                 const tcu::TextureFormat        format                                          = mapVkFormat(attachment.getFormat());
3664                 const bool                                      isDepthOrStencilAttachment      = hasDepthComponent(format.order) || hasStencilComponent(format.order);
3665                 const VkFormatFeatureFlags      flags                                           = isDepthOrStencilAttachment? VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
3666                 VkFormatProperties                      properties;
3667
3668                 vk.getPhysicalDeviceFormatProperties(device, attachment.getFormat(), &properties);
3669
3670                 if ((properties.optimalTilingFeatures & flags) != flags)
3671                 {
3672                         supported = false;
3673                         log << TestLog::Message << "Format: " << attachment.getFormat() << " not supported as " << (isDepthOrStencilAttachment ? "depth stencil attachment" : "color attachment") << TestLog::EndMessage;
3674                 }
3675         }
3676
3677         if (!supported)
3678                 TCU_THROW(NotSupportedError, "Format not supported");
3679 }
3680
3681 tcu::TestStatus renderPassTest (Context& context, TestConfig config)
3682 {
3683         const UVec2                                                     targetSize                      = config.targetSize;
3684         const UVec2                                                     renderPos                       = config.renderPos;
3685         const UVec2                                                     renderSize                      = config.renderSize;
3686         const RenderPass&                                       renderPassInfo          = config.renderPass;
3687
3688         TestLog&                                                        log                                     = context.getTestContext().getLog();
3689         de::Random                                                      rng                                     (config.seed);
3690
3691         vector<bool>                                            attachmentIsLazy;
3692         vector<Maybe<VkClearValue> >            imageClearValues;
3693         vector<Maybe<VkClearValue> >            renderPassClearValues;
3694
3695         vector<bool>                                            subpassIsSecondary;
3696         vector<SubpassRenderInfo>                       subpassRenderInfo;
3697         vector<vector<VkClearColorValue> >      subpassColorClearValues;
3698
3699         initializeAttachmentIsLazy(attachmentIsLazy, renderPassInfo.getAttachments(), config.imageMemory);
3700         initializeImageClearValues(rng, imageClearValues, renderPassInfo.getAttachments(), attachmentIsLazy);
3701         initializeRenderPassClearValues(rng, renderPassClearValues, renderPassInfo.getAttachments());
3702
3703         initializeSubpassIsSecondary(subpassIsSecondary, renderPassInfo.getSubpasses(), config.commandBufferTypes);
3704         initializeSubpassClearValues(rng, subpassColorClearValues, renderPassInfo);
3705         initializeSubpassRenderInfo(subpassRenderInfo, rng, renderPassInfo, config);
3706
3707         logTestCaseInfo(log, config, attachmentIsLazy, imageClearValues, renderPassClearValues, subpassRenderInfo);
3708
3709         checkTextureFormatSupport(log, context.getInstanceInterface(), context.getPhysicalDevice(), config.renderPass.getAttachments());
3710
3711         {
3712                 const VkDevice                                                          device                                                          = context.getDevice();
3713                 const DeviceInterface&                                          vk                                                                      = context.getDeviceInterface();
3714                 const VkQueue                                                           queue                                                           = context.getUniversalQueue();
3715                 const deUint32                                                          queueIndex                                                      = context.getUniversalQueueFamilyIndex();
3716                 Allocator&                                                                      allocator                                                       = context.getDefaultAllocator();
3717
3718                 const Unique<VkRenderPass>                                      renderPass                                                      (createRenderPass(vk, device, renderPassInfo));
3719                 const Unique<VkCommandPool>                                     commandBufferPool                                       (createCommandPool(vk, device, queueIndex, 0));
3720                 const Unique<VkCommandBuffer>                           initializeImagesCommandBuffer           (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3721                 const Unique<VkCommandBuffer>                           renderCommandBuffer                                     (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3722                 const Unique<VkCommandBuffer>                           readImagesToBuffersCommandBuffer        (allocateCommandBuffer(vk, device, *commandBufferPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3723
3724                 vector<de::SharedPtr<AttachmentResources> >     attachmentResources;
3725                 vector<de::SharedPtr<SubpassRenderer> >         subpassRenderers;
3726                 vector<VkImageView>                                                     attachmentViews;
3727
3728                 for (size_t attachmentNdx = 0; attachmentNdx < renderPassInfo.getAttachments().size(); attachmentNdx++)
3729                 {
3730                         const Attachment&       attachmentInfo  = renderPassInfo.getAttachments()[attachmentNdx];
3731
3732                         attachmentResources.push_back(de::SharedPtr<AttachmentResources>(new AttachmentResources(vk, device, allocator, queueIndex, targetSize, attachmentInfo, attachmentIsLazy[attachmentNdx])));
3733                         attachmentViews.push_back(attachmentResources[attachmentNdx]->getAttachmentView());
3734                 }
3735
3736                 beginCommandBuffer(vk, *initializeImagesCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3737                 pushImageInitializationCommands(vk, *initializeImagesCommandBuffer, renderPassInfo.getAttachments(), attachmentResources, queueIndex, imageClearValues);
3738                 endCommandBuffer(vk, *initializeImagesCommandBuffer);
3739
3740                 {
3741                         const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, device, *renderPass, targetSize, attachmentViews));
3742
3743                         for (size_t subpassNdx = 0; subpassNdx < renderPassInfo.getSubpasses().size(); subpassNdx++)
3744                                 subpassRenderers.push_back(de::SharedPtr<SubpassRenderer>(new SubpassRenderer(context, vk, device, allocator, *renderPass, *framebuffer, *commandBufferPool, queueIndex, subpassRenderInfo[subpassNdx])));
3745
3746                         beginCommandBuffer(vk, *renderCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3747                         pushRenderPassCommands(vk, *renderCommandBuffer, *renderPass, *framebuffer, subpassRenderers, renderPos, renderSize, renderPassClearValues, config.renderTypes);
3748                         endCommandBuffer(vk, *renderCommandBuffer);
3749
3750                         beginCommandBuffer(vk, *readImagesToBuffersCommandBuffer, (VkCommandBufferUsageFlags)0, DE_NULL, 0, DE_NULL, VK_FALSE, (VkQueryControlFlags)0, (VkQueryPipelineStatisticFlags)0);
3751                         pushReadImagesToBuffers(vk, *readImagesToBuffersCommandBuffer, queueIndex, attachmentResources, renderPassInfo.getAttachments(), attachmentIsLazy, targetSize);
3752                         endCommandBuffer(vk, *readImagesToBuffersCommandBuffer);
3753                         {
3754                                 const VkCommandBuffer commandBuffers[] =
3755                                 {
3756                                         *initializeImagesCommandBuffer,
3757                                         *renderCommandBuffer,
3758                                         *readImagesToBuffersCommandBuffer
3759                                 };
3760                                 const Unique<VkFence>   fence           (createFence(vk, device, 0u));
3761
3762                                 queueSubmit(vk, queue, DE_LENGTH_OF_ARRAY(commandBuffers), commandBuffers, *fence);
3763                                 waitForFences(vk, device, 1, &fence.get(), VK_TRUE, ~0ull);
3764                         }
3765                 }
3766
3767                 if (logAndVerifyImages(log, vk, device, attachmentResources, attachmentIsLazy, renderPassInfo, renderPassClearValues, imageClearValues, subpassRenderInfo, targetSize, config))
3768                         return tcu::TestStatus::pass("Pass");
3769                 else
3770                         return tcu::TestStatus::fail("Result verification failed");
3771         }
3772 }
3773
3774 static const VkFormat s_coreColorFormats[] =
3775 {
3776         VK_FORMAT_R5G6B5_UNORM_PACK16,
3777         VK_FORMAT_R8_UNORM,
3778         VK_FORMAT_R8_SNORM,
3779         VK_FORMAT_R8_UINT,
3780         VK_FORMAT_R8_SINT,
3781         VK_FORMAT_R8G8_UNORM,
3782         VK_FORMAT_R8G8_SNORM,
3783         VK_FORMAT_R8G8_UINT,
3784         VK_FORMAT_R8G8_SINT,
3785         VK_FORMAT_R8G8B8A8_UNORM,
3786         VK_FORMAT_R8G8B8A8_SNORM,
3787         VK_FORMAT_R8G8B8A8_UINT,
3788         VK_FORMAT_R8G8B8A8_SINT,
3789         VK_FORMAT_R8G8B8A8_SRGB,
3790         VK_FORMAT_A8B8G8R8_UNORM_PACK32,
3791         VK_FORMAT_A8B8G8R8_SNORM_PACK32,
3792         VK_FORMAT_A8B8G8R8_UINT_PACK32,
3793         VK_FORMAT_A8B8G8R8_SINT_PACK32,
3794         VK_FORMAT_A8B8G8R8_SRGB_PACK32,
3795         VK_FORMAT_B8G8R8A8_UNORM,
3796         VK_FORMAT_B8G8R8A8_SRGB,
3797         VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3798         VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3799         VK_FORMAT_A2B10G10R10_UINT_PACK32,
3800         VK_FORMAT_R16_UNORM,
3801         VK_FORMAT_R16_SNORM,
3802         VK_FORMAT_R16_UINT,
3803         VK_FORMAT_R16_SINT,
3804         VK_FORMAT_R16_SFLOAT,
3805         VK_FORMAT_R16G16_UNORM,
3806         VK_FORMAT_R16G16_SNORM,
3807         VK_FORMAT_R16G16_UINT,
3808         VK_FORMAT_R16G16_SINT,
3809         VK_FORMAT_R16G16_SFLOAT,
3810         VK_FORMAT_R16G16B16A16_UNORM,
3811         VK_FORMAT_R16G16B16A16_SNORM,
3812         VK_FORMAT_R16G16B16A16_UINT,
3813         VK_FORMAT_R16G16B16A16_SINT,
3814         VK_FORMAT_R16G16B16A16_SFLOAT,
3815         VK_FORMAT_R32_UINT,
3816         VK_FORMAT_R32_SINT,
3817         VK_FORMAT_R32_SFLOAT,
3818         VK_FORMAT_R32G32_UINT,
3819         VK_FORMAT_R32G32_SINT,
3820         VK_FORMAT_R32G32_SFLOAT,
3821         VK_FORMAT_R32G32B32A32_UINT,
3822         VK_FORMAT_R32G32B32A32_SINT,
3823         VK_FORMAT_R32G32B32A32_SFLOAT
3824 };
3825
3826 static const VkFormat s_coreDepthStencilFormats[] =
3827 {
3828         VK_FORMAT_D16_UNORM,
3829
3830         VK_FORMAT_X8_D24_UNORM_PACK32,
3831         VK_FORMAT_D32_SFLOAT,
3832
3833         VK_FORMAT_D24_UNORM_S8_UINT,
3834         VK_FORMAT_D32_SFLOAT_S8_UINT
3835 };
3836
3837 de::MovePtr<tcu::TestCaseGroup> createAttachmentTestCaseGroup (tcu::TestContext& testCtx)
3838 {
3839         const deUint32 attachmentCounts[] = { 1, 3, 8 };
3840         const VkAttachmentLoadOp loadOps[] =
3841         {
3842                 VK_ATTACHMENT_LOAD_OP_LOAD,
3843                 VK_ATTACHMENT_LOAD_OP_CLEAR,
3844                 VK_ATTACHMENT_LOAD_OP_DONT_CARE
3845         };
3846
3847         const VkAttachmentStoreOp storeOps[] =
3848         {
3849                 VK_ATTACHMENT_STORE_OP_STORE,
3850                 VK_ATTACHMENT_STORE_OP_DONT_CARE
3851         };
3852
3853         const VkImageLayout initialAndFinalColorLayouts[] =
3854         {
3855                 VK_IMAGE_LAYOUT_GENERAL,
3856                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3857                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
3858                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3859                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
3860         };
3861
3862         const VkImageLayout initialAndFinalDepthStencilLayouts[] =
3863         {
3864                 VK_IMAGE_LAYOUT_GENERAL,
3865                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
3866                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
3867                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
3868                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3869                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
3870         };
3871
3872         const VkImageLayout subpassLayouts[] =
3873         {
3874                 VK_IMAGE_LAYOUT_GENERAL,
3875                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
3876         };
3877
3878         const VkImageLayout depthStencilLayouts[] =
3879         {
3880                 VK_IMAGE_LAYOUT_GENERAL,
3881                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
3882         };
3883
3884         const TestConfig::RenderTypes renderCommands[] =
3885         {
3886                 TestConfig::RENDERTYPES_NONE,
3887                 TestConfig::RENDERTYPES_CLEAR,
3888                 TestConfig::RENDERTYPES_DRAW,
3889                 TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW,
3890         };
3891
3892         const TestConfig::CommandBufferTypes commandBuffers[] =
3893         {
3894                 TestConfig::COMMANDBUFFERTYPES_INLINE,
3895                 TestConfig::COMMANDBUFFERTYPES_SECONDARY,
3896                 TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY
3897         };
3898
3899         const TestConfig::ImageMemory imageMemories[] =
3900         {
3901                 TestConfig::IMAGEMEMORY_STRICT,
3902                 TestConfig::IMAGEMEMORY_LAZY,
3903                 TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY
3904         };
3905
3906         const UVec2 targetSizes[] =
3907         {
3908                 UVec2(64, 64),
3909                 UVec2(63, 65)
3910         };
3911
3912         const UVec2 renderPositions[] =
3913         {
3914                 UVec2(0, 0),
3915                 UVec2(3, 17)
3916         };
3917
3918         const UVec2 renderSizes[] =
3919         {
3920                 UVec2(32, 32),
3921                 UVec2(60, 47)
3922         };
3923
3924         de::Random rng (1433774382u);
3925         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "attachment", "Attachment format and count tests with load and store ops and image layouts"));
3926
3927         for (size_t attachmentCountNdx = 0; attachmentCountNdx < DE_LENGTH_OF_ARRAY(attachmentCounts); attachmentCountNdx++)
3928         {
3929                 const deUint32                                  attachmentCount                 = attachmentCounts[attachmentCountNdx];
3930                 const deUint32                                  testCaseCount                   = (attachmentCount == 1 ? 100 : 200);
3931                 de::MovePtr<tcu::TestCaseGroup> attachmentCountGroup    (new tcu::TestCaseGroup(testCtx, de::toString(attachmentCount).c_str(), de::toString(attachmentCount).c_str()));
3932
3933                 for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
3934                 {
3935                         const bool                                      useDepthStencil         = rng.getBool();
3936                         VkImageLayout                           depthStencilLayout      = VK_IMAGE_LAYOUT_GENERAL;
3937                         vector<Attachment>                      attachments;
3938                         vector<AttachmentReference>     colorAttachmentReferences;
3939
3940                         for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
3941                         {
3942                                 const VkSampleCountFlagBits     sampleCount             = VK_SAMPLE_COUNT_1_BIT;
3943                                 const VkFormat                          format                  = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
3944                                 const VkAttachmentLoadOp        loadOp                  = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
3945                                 const VkAttachmentStoreOp       storeOp                 = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
3946
3947                                 const VkImageLayout                     initialLayout   = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
3948                                 const VkImageLayout                     finalizeLayout  = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalColorLayouts), DE_ARRAY_END(initialAndFinalColorLayouts));
3949                                 const VkImageLayout                     subpassLayout   = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
3950
3951                                 const VkAttachmentLoadOp        stencilLoadOp   = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
3952                                 const VkAttachmentStoreOp       stencilStoreOp  = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
3953
3954                                 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
3955                                 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
3956                         }
3957
3958                         if (useDepthStencil)
3959                         {
3960                                 const VkSampleCountFlagBits     sampleCount                     = VK_SAMPLE_COUNT_1_BIT;
3961                                 const VkFormat                          format                          = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreDepthStencilFormats), DE_ARRAY_END(s_coreDepthStencilFormats));
3962                                 const VkAttachmentLoadOp        loadOp                          = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
3963                                 const VkAttachmentStoreOp       storeOp                         = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
3964
3965                                 const VkImageLayout                     initialLayout           = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts));
3966                                 const VkImageLayout                     finalizeLayout          = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalDepthStencilLayouts), DE_ARRAY_END(initialAndFinalDepthStencilLayouts));
3967
3968                                 const VkAttachmentLoadOp        stencilLoadOp           = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
3969                                 const VkAttachmentStoreOp       stencilStoreOp          = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
3970
3971                                 depthStencilLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(depthStencilLayouts), DE_ARRAY_END(depthStencilLayouts));
3972                                 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
3973                         }
3974
3975                         {
3976                                 const TestConfig::RenderTypes                   render                  = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
3977                                 const TestConfig::CommandBufferTypes    commandBuffer   = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
3978                                 const TestConfig::ImageMemory                   imageMemory             = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
3979                                 const vector<Subpass>                                   subpasses               (1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference((useDepthStencil ? (deUint32)(attachments.size() - 1) : VK_ATTACHMENT_UNUSED), depthStencilLayout), vector<AttachmentReference>()));
3980                                 const vector<SubpassDependency>                 deps;
3981
3982                                 const string                                                    testCaseName    = de::toString(attachmentCountNdx * testCaseCount + testCaseNdx);
3983                                 const RenderPass                                                renderPass              (attachments, subpasses, deps);
3984                                 const UVec2                                                             targetSize              = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
3985                                 const UVec2                                                             renderPos               = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
3986                                 const UVec2                                                             renderSize              = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
3987
3988                                 addFunctionCaseWithPrograms<TestConfig>(attachmentCountGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, TestConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos, renderSize, 1293809));
3989                         }
3990                 }
3991
3992                 group->addChild(attachmentCountGroup.release());
3993         }
3994
3995         return group;
3996 }
3997
3998 de::MovePtr<tcu::TestCaseGroup> createAttachmentAllocationTestGroup (tcu::TestContext& testCtx)
3999 {
4000         const deUint32 attachmentCounts[] = { 4, 8 };
4001         const VkAttachmentLoadOp loadOps[] =
4002         {
4003                 VK_ATTACHMENT_LOAD_OP_LOAD,
4004                 VK_ATTACHMENT_LOAD_OP_CLEAR,
4005                 VK_ATTACHMENT_LOAD_OP_DONT_CARE
4006         };
4007
4008         const VkAttachmentStoreOp storeOps[] =
4009         {
4010                 VK_ATTACHMENT_STORE_OP_STORE,
4011                 VK_ATTACHMENT_STORE_OP_DONT_CARE
4012         };
4013
4014         const VkImageLayout initialAndFinalLayouts[] =
4015         {
4016                 VK_IMAGE_LAYOUT_GENERAL,
4017                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4018                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4019                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
4020                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
4021                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4022                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
4023         };
4024
4025         const VkImageLayout subpassLayouts[] =
4026         {
4027                 VK_IMAGE_LAYOUT_GENERAL,
4028                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4029         };
4030
4031         enum AllocationType
4032         {
4033                 // Each pass uses one more attachmen than previous one
4034                 ALLOCATIONTYPE_GROW,
4035                 // Each pass uses one less attachment than previous one
4036                 ALLOCATIONTYPE_SHRINK,
4037                 // Each pass drops one attachment and picks up new one
4038                 ALLOCATIONTYPE_ROLL,
4039                 // Start by growing and end by shrinking
4040                 ALLOCATIONTYPE_GROW_SHRINK
4041         };
4042
4043         const AllocationType allocationTypes[] =
4044         {
4045                 ALLOCATIONTYPE_GROW,
4046                 ALLOCATIONTYPE_SHRINK,
4047                 ALLOCATIONTYPE_ROLL,
4048                 ALLOCATIONTYPE_GROW_SHRINK
4049         };
4050
4051         const char* const allocationTypeStr[] =
4052         {
4053                 "grow",
4054                 "shrink",
4055                 "roll",
4056                 "grow_shrink"
4057         };
4058
4059         const TestConfig::RenderTypes renderCommands[] =
4060         {
4061                 TestConfig::RENDERTYPES_NONE,
4062                 TestConfig::RENDERTYPES_CLEAR,
4063                 TestConfig::RENDERTYPES_DRAW,
4064                 TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW,
4065         };
4066
4067         const TestConfig::CommandBufferTypes commandBuffers[] =
4068         {
4069                 TestConfig::COMMANDBUFFERTYPES_INLINE,
4070                 TestConfig::COMMANDBUFFERTYPES_SECONDARY,
4071                 TestConfig::COMMANDBUFFERTYPES_INLINE|TestConfig::COMMANDBUFFERTYPES_SECONDARY
4072         };
4073
4074         const TestConfig::ImageMemory imageMemories[] =
4075         {
4076                 TestConfig::IMAGEMEMORY_STRICT,
4077                 TestConfig::IMAGEMEMORY_LAZY,
4078                 TestConfig::IMAGEMEMORY_STRICT|TestConfig::IMAGEMEMORY_LAZY
4079         };
4080
4081         const UVec2 targetSizes[] =
4082         {
4083                 UVec2(64, 64),
4084                 UVec2(63, 65)
4085         };
4086
4087         const UVec2 renderPositions[] =
4088         {
4089                 UVec2(0, 0),
4090                 UVec2(3, 17)
4091         };
4092
4093         const UVec2 renderSizes[] =
4094         {
4095                 UVec2(32, 32),
4096                 UVec2(60, 47)
4097         };
4098
4099         de::MovePtr<tcu::TestCaseGroup> group   (new tcu::TestCaseGroup(testCtx, "attachment_allocation", "Attachment allocation tests"));
4100         de::Random                                              rng             (3700649827u);
4101
4102         for (size_t allocationTypeNdx = 0; allocationTypeNdx < DE_LENGTH_OF_ARRAY(allocationTypes); allocationTypeNdx++)
4103         {
4104                 const AllocationType                    allocationType          = allocationTypes[allocationTypeNdx];
4105                 const size_t                                    testCaseCount           = 100;
4106                 de::MovePtr<tcu::TestCaseGroup> allocationTypeGroup     (new tcu::TestCaseGroup(testCtx, allocationTypeStr[allocationTypeNdx], allocationTypeStr[allocationTypeNdx]));
4107
4108                 for (size_t testCaseNdx = 0; testCaseNdx < testCaseCount; testCaseNdx++)
4109                 {
4110                         const deUint32          attachmentCount = rng.choose<deUint32>(DE_ARRAY_BEGIN(attachmentCounts), DE_ARRAY_END(attachmentCounts));
4111                         vector<Attachment>      attachments;
4112                         vector<Subpass>         subpasses;
4113
4114                         for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount; attachmentNdx++)
4115                         {
4116                                 const VkSampleCountFlagBits     sampleCount             = VK_SAMPLE_COUNT_1_BIT;
4117                                 const VkFormat                          format                  = rng.choose<VkFormat>(DE_ARRAY_BEGIN(s_coreColorFormats), DE_ARRAY_END(s_coreColorFormats));
4118                                 const VkAttachmentLoadOp        loadOp                  = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4119                                 const VkAttachmentStoreOp       storeOp                 = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4120
4121                                 const VkImageLayout                     initialLayout   = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalLayouts), DE_ARRAY_END(initialAndFinalLayouts));
4122                                 const VkImageLayout                     finalizeLayout  = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(initialAndFinalLayouts), DE_ARRAY_END(initialAndFinalLayouts));
4123
4124                                 const VkAttachmentLoadOp        stencilLoadOp   = rng.choose<VkAttachmentLoadOp>(DE_ARRAY_BEGIN(loadOps), DE_ARRAY_END(loadOps));
4125                                 const VkAttachmentStoreOp       stencilStoreOp  = rng.choose<VkAttachmentStoreOp>(DE_ARRAY_BEGIN(storeOps), DE_ARRAY_END(storeOps));
4126
4127                                 attachments.push_back(Attachment(format, sampleCount, loadOp, storeOp, stencilLoadOp, stencilStoreOp, initialLayout, finalizeLayout));
4128                         }
4129
4130                         if (allocationType == ALLOCATIONTYPE_GROW)
4131                         {
4132                                 for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4133                                 {
4134                                         vector<AttachmentReference>     colorAttachmentReferences;
4135
4136                                         for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
4137                                         {
4138                                                 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4139
4140                                                 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4141                                         }
4142
4143                                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4144                                 }
4145                         }
4146                         else if (allocationType == ALLOCATIONTYPE_SHRINK)
4147                         {
4148                                 for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4149                                 {
4150                                         vector<AttachmentReference>     colorAttachmentReferences;
4151
4152                                         for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
4153                                         {
4154                                                 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4155
4156                                                 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4157                                         }
4158
4159                                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4160                                 }
4161                         }
4162                         else if (allocationType == ALLOCATIONTYPE_ROLL)
4163                         {
4164                                 for (size_t subpassNdx = 0; subpassNdx < attachmentCount / 2; subpassNdx++)
4165                                 {
4166                                         vector<AttachmentReference>     colorAttachmentReferences;
4167
4168                                         for (size_t attachmentNdx = 0; attachmentNdx < attachmentCount / 2; attachmentNdx++)
4169                                         {
4170                                                 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4171
4172                                                 colorAttachmentReferences.push_back(AttachmentReference((deUint32)(subpassNdx + attachmentNdx), subpassLayout));
4173                                         }
4174
4175                                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4176                                 }
4177                         }
4178                         else if (allocationType == ALLOCATIONTYPE_GROW_SHRINK)
4179                         {
4180                                 for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4181                                 {
4182                                         vector<AttachmentReference>     colorAttachmentReferences;
4183
4184                                         for (size_t attachmentNdx = 0; attachmentNdx < subpassNdx + 1; attachmentNdx++)
4185                                         {
4186                                                 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4187
4188                                                 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4189                                         }
4190
4191                                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4192                                 }
4193
4194                                 for (size_t subpassNdx = 0; subpassNdx < attachmentCount; subpassNdx++)
4195                                 {
4196                                         vector<AttachmentReference>     colorAttachmentReferences;
4197
4198                                         for (size_t attachmentNdx = 0; attachmentNdx < (attachmentCount - subpassNdx); attachmentNdx++)
4199                                         {
4200                                                 const VkImageLayout subpassLayout = rng.choose<VkImageLayout>(DE_ARRAY_BEGIN(subpassLayouts), DE_ARRAY_END(subpassLayouts));
4201
4202                                                 colorAttachmentReferences.push_back(AttachmentReference((deUint32)attachmentNdx, subpassLayout));
4203                                         }
4204
4205                                         subpasses.push_back(Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, 0u, vector<AttachmentReference>(), colorAttachmentReferences, vector<AttachmentReference>(), AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL), vector<AttachmentReference>()));
4206                                 }
4207                         }
4208                         else
4209                                 DE_FATAL("Unknown allocation type");
4210
4211                         {
4212                                 const TestConfig::RenderTypes                   render                  = rng.choose<TestConfig::RenderTypes>(DE_ARRAY_BEGIN(renderCommands), DE_ARRAY_END(renderCommands));
4213                                 const TestConfig::CommandBufferTypes    commandBuffer   = rng.choose<TestConfig::CommandBufferTypes>(DE_ARRAY_BEGIN(commandBuffers), DE_ARRAY_END(commandBuffers));
4214                                 const TestConfig::ImageMemory                   imageMemory             = rng.choose<TestConfig::ImageMemory>(DE_ARRAY_BEGIN(imageMemories), DE_ARRAY_END(imageMemories));
4215
4216                                 const string                                                    testCaseName    = de::toString(testCaseNdx);
4217                                 const UVec2                                                             targetSize              = rng.choose<UVec2>(DE_ARRAY_BEGIN(targetSizes), DE_ARRAY_END(targetSizes));
4218                                 const UVec2                                                             renderPos               = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderPositions), DE_ARRAY_END(renderPositions));
4219                                 const UVec2                                                             renderSize              = rng.choose<UVec2>(DE_ARRAY_BEGIN(renderSizes), DE_ARRAY_END(renderSizes));
4220
4221                                 vector<SubpassDependency>                               deps;
4222
4223                                 for (size_t subpassNdx = 0; subpassNdx < subpasses.size() - 1; subpassNdx++)
4224                                 {
4225                                         const bool byRegion                             = rng.getBool();
4226                                         deps.push_back(SubpassDependency((deUint32)subpassNdx, (deUint32)subpassNdx + 1,
4227                                                                                                          VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
4228                                                                                                                 | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
4229                                                                                                                 | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
4230                                                                                                                 | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
4231
4232                                                                                                          VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
4233                                                                                                                 | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
4234                                                                                                                 | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
4235                                                                                                                 | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
4236
4237                                                                                                          VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
4238                                                                                                          VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // \todo [pyry] Correct?
4239
4240                                                                                                          byRegion ? (VkBool32)VK_TRUE : (VkBool32)VK_FALSE));
4241                                 }
4242
4243                                 const RenderPass                                        renderPass              (attachments, subpasses, deps);
4244
4245                                 addFunctionCaseWithPrograms<TestConfig>(allocationTypeGroup.get(), testCaseName.c_str(), testCaseName.c_str(), createTestShaders, renderPassTest, TestConfig(renderPass, render, commandBuffer, imageMemory, targetSize, renderPos, renderSize, 80329));
4246                         }
4247                 }
4248
4249                 group->addChild(allocationTypeGroup.release());
4250         }
4251
4252         return group;
4253 }
4254
4255 de::MovePtr<tcu::TestCaseGroup> createSimpleTestGroup (tcu::TestContext& testCtx)
4256 {
4257         const UVec2                                             targetSize      (64, 64);
4258         const UVec2                                             renderPos       (0, 0);
4259         const UVec2                                             renderSize      (64, 64);
4260         de::MovePtr<tcu::TestCaseGroup> group           (new tcu::TestCaseGroup(testCtx, "simple", "Simple basic render pass tests"));
4261
4262         // color
4263         {
4264                 const RenderPass        renderPass      (vector<Attachment>(1, Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4265                                                                                                                                                   VK_SAMPLE_COUNT_1_BIT,
4266                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_CLEAR,
4267                                                                                                                                                   VK_ATTACHMENT_STORE_OP_STORE,
4268                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4269                                                                                                                                                   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4270                                                                                                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4271                                                                                                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4272                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4273                                                                                                                                         0u,
4274                                                                                                                                         vector<AttachmentReference>(),
4275                                                                                                                                         vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4276                                                                                                                                         vector<AttachmentReference>(),
4277                                                                                                                                         AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
4278                                                                                                                                         vector<AttachmentReference>())),
4279                                                                                  vector<SubpassDependency>());
4280
4281                 addFunctionCaseWithPrograms<TestConfig>(group.get(), "color", "Single color attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4282         }
4283
4284         // depth
4285         {
4286                 const RenderPass        renderPass      (vector<Attachment>(1, Attachment(VK_FORMAT_X8_D24_UNORM_PACK32,
4287                                                                                                                                                   VK_SAMPLE_COUNT_1_BIT,
4288                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_CLEAR,
4289                                                                                                                                                   VK_ATTACHMENT_STORE_OP_STORE,
4290                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4291                                                                                                                                                   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4292                                                                                                                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4293                                                                                                                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4294                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4295                                                                                                                                         0u,
4296                                                                                                                                         vector<AttachmentReference>(),
4297                                                                                                                                         vector<AttachmentReference>(),
4298                                                                                                                                         vector<AttachmentReference>(),
4299                                                                                                                                         AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4300                                                                                                                                         vector<AttachmentReference>())),
4301                                                                                  vector<SubpassDependency>());
4302
4303                 addFunctionCaseWithPrograms<TestConfig>(group.get(), "depth", "Single depth attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4304         }
4305
4306         // stencil
4307         {
4308                 const RenderPass        renderPass      (vector<Attachment>(1, Attachment(VK_FORMAT_S8_UINT,
4309                                                                                                                                                   VK_SAMPLE_COUNT_1_BIT,
4310                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4311                                                                                                                                                   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4312                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_CLEAR,
4313                                                                                                                                                   VK_ATTACHMENT_STORE_OP_STORE,
4314                                                                                                                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4315                                                                                                                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4316                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4317                                                                                                                                         0u,
4318                                                                                                                                         vector<AttachmentReference>(),
4319                                                                                                                                         vector<AttachmentReference>(),
4320                                                                                                                                         vector<AttachmentReference>(),
4321                                                                                                                                         AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4322                                                                                                                                         vector<AttachmentReference>())),
4323                                                                                  vector<SubpassDependency>());
4324
4325                 addFunctionCaseWithPrograms<TestConfig>(group.get(), "stencil", "Single stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4326         }
4327
4328         // depth_stencil
4329         {
4330                 const RenderPass        renderPass      (vector<Attachment>(1, Attachment(VK_FORMAT_D24_UNORM_S8_UINT,
4331                                                                                                                                                   VK_SAMPLE_COUNT_1_BIT,
4332                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_CLEAR,
4333                                                                                                                                                   VK_ATTACHMENT_STORE_OP_STORE,
4334                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_CLEAR,
4335                                                                                                                                                   VK_ATTACHMENT_STORE_OP_STORE,
4336                                                                                                                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4337                                                                                                                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4338                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4339                                                                                                                                         0u,
4340                                                                                                                                         vector<AttachmentReference>(),
4341                                                                                                                                         vector<AttachmentReference>(),
4342                                                                                                                                         vector<AttachmentReference>(),
4343                                                                                                                                         AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4344                                                                                                                                         vector<AttachmentReference>())),
4345                                                                                  vector<SubpassDependency>());
4346
4347                 addFunctionCaseWithPrograms<TestConfig>(group.get(), "depth_stencil", "Single depth stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4348         }
4349
4350         // color_depth
4351         {
4352                 const Attachment        attachments[] =
4353                 {
4354                         Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4355                                            VK_SAMPLE_COUNT_1_BIT,
4356                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
4357                                            VK_ATTACHMENT_STORE_OP_STORE,
4358                                            VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4359                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
4360                                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4361                                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4362                         Attachment(VK_FORMAT_X8_D24_UNORM_PACK32,
4363                                            VK_SAMPLE_COUNT_1_BIT,
4364                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
4365                                            VK_ATTACHMENT_STORE_OP_STORE,
4366                                            VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4367                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
4368                                            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4369                                            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4370                 };
4371
4372                 const RenderPass        renderPass      (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4373                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4374                                                                                                                                         0u,
4375                                                                                                                                         vector<AttachmentReference>(),
4376                                                                                                                                         vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4377                                                                                                                                         vector<AttachmentReference>(),
4378                                                                                                                                         AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4379                                                                                                                                         vector<AttachmentReference>())),
4380                                                                                  vector<SubpassDependency>());
4381
4382                 addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_depth", "Color and depth attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4383         }
4384
4385         // color_stencil
4386         {
4387                 const Attachment        attachments[] =
4388                 {
4389                         Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4390                                            VK_SAMPLE_COUNT_1_BIT,
4391                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
4392                                            VK_ATTACHMENT_STORE_OP_STORE,
4393                                            VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4394                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
4395                                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4396                                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4397                         Attachment(VK_FORMAT_S8_UINT,
4398                                            VK_SAMPLE_COUNT_1_BIT,
4399                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
4400                                            VK_ATTACHMENT_STORE_OP_STORE,
4401                                            VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4402                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
4403                                            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4404                                            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4405                 };
4406
4407                 const RenderPass        renderPass      (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4408                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4409                                                                                                                                         0u,
4410                                                                                                                                         vector<AttachmentReference>(),
4411                                                                                                                                         vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4412                                                                                                                                         vector<AttachmentReference>(),
4413                                                                                                                                         AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4414                                                                                                                                         vector<AttachmentReference>())),
4415                                                                                  vector<SubpassDependency>());
4416
4417
4418                 addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_stencil", "Color and stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4419         }
4420
4421         // color_depth_stencil
4422         {
4423                 const Attachment        attachments[] =
4424                 {
4425                         Attachment(VK_FORMAT_R8G8B8A8_UNORM,
4426                                            VK_SAMPLE_COUNT_1_BIT,
4427                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
4428                                            VK_ATTACHMENT_STORE_OP_STORE,
4429                                            VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4430                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
4431                                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4432                                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
4433                         Attachment(VK_FORMAT_D24_UNORM_S8_UINT,
4434                                            VK_SAMPLE_COUNT_1_BIT,
4435                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
4436                                            VK_ATTACHMENT_STORE_OP_STORE,
4437                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
4438                                            VK_ATTACHMENT_STORE_OP_STORE,
4439                                            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4440                                            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4441                 };
4442
4443                 const RenderPass        renderPass      (vector<Attachment>(DE_ARRAY_BEGIN(attachments), DE_ARRAY_END(attachments)),
4444                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4445                                                                                                                                         0u,
4446                                                                                                                                         vector<AttachmentReference>(),
4447                                                                                                                                         vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4448                                                                                                                                         vector<AttachmentReference>(),
4449                                                                                                                                         AttachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4450                                                                                                                                         vector<AttachmentReference>())),
4451                                                                                  vector<SubpassDependency>());
4452
4453                 addFunctionCaseWithPrograms<TestConfig>(group.get(), "color_depth_stencil", "Color, depth and stencil attachment case.", createTestShaders, renderPassTest, TestConfig(renderPass, TestConfig::RENDERTYPES_DRAW, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4454         }
4455
4456         return group;
4457 }
4458
4459 std::string formatToName (VkFormat format)
4460 {
4461         const std::string       formatStr       = de::toString(format);
4462         const std::string       prefix          = "VK_FORMAT_";
4463
4464         DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
4465
4466         return de::toLower(formatStr.substr(prefix.length()));
4467 }
4468
4469 de::MovePtr<tcu::TestCaseGroup> createFormatTestGroup(tcu::TestContext& testCtx)
4470 {
4471         de::MovePtr<tcu::TestCaseGroup> group   (new tcu::TestCaseGroup(testCtx, "formats", "Tests for different image formats."));
4472
4473         const UVec2 targetSize  (64, 64);
4474         const UVec2 renderPos   (0, 0);
4475         const UVec2 renderSize  (64, 64);
4476
4477         const struct
4478         {
4479                 const char* const                       str;
4480                 const VkAttachmentLoadOp        op;
4481         } loadOps[] =
4482         {
4483                 { "clear",              VK_ATTACHMENT_LOAD_OP_CLEAR             },
4484                 { "load",               VK_ATTACHMENT_LOAD_OP_LOAD              },
4485                 { "dont_care",  VK_ATTACHMENT_LOAD_OP_DONT_CARE }
4486         };
4487
4488         const struct
4489         {
4490                  const char* const                              str;
4491                  const TestConfig::RenderTypes  types;
4492         } renderTypes[] =
4493         {
4494                 { "clear",              TestConfig::RENDERTYPES_CLEAR                                                           },
4495                 { "draw",               TestConfig::RENDERTYPES_DRAW                                                            },
4496                 { "clear_draw", TestConfig::RENDERTYPES_CLEAR|TestConfig::RENDERTYPES_DRAW      }
4497         };
4498
4499         // Color formats
4500         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreColorFormats); formatNdx++)
4501         {
4502                 const VkFormat                                  format          = s_coreColorFormats[formatNdx];
4503                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, formatToName(format).c_str(), de::toString(format).c_str()));
4504
4505                 for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
4506                 {
4507                         const VkAttachmentLoadOp                loadOp  = loadOps[loadOpNdx].op;
4508                         de::MovePtr<tcu::TestCaseGroup> loadOpGroup     (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str));
4509
4510                         for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
4511                         {
4512                                 const RenderPass        renderPass      (vector<Attachment>(1, Attachment(format,
4513                                                                                                                                                                   VK_SAMPLE_COUNT_1_BIT,
4514                                                                                                                                                                   loadOp,
4515                                                                                                                                                                   VK_ATTACHMENT_STORE_OP_STORE,
4516                                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4517                                                                                                                                                                   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4518                                                                                                                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4519                                                                                                                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4520                                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4521                                                                                                                                                         0u,
4522                                                                                                                                                         vector<AttachmentReference>(),
4523                                                                                                                                                         vector<AttachmentReference>(1, AttachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)),
4524                                                                                                                                                         vector<AttachmentReference>(),
4525                                                                                                                                                         AttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_GENERAL),
4526                                                                                                                                                         vector<AttachmentReference>())),
4527                                                                                                  vector<SubpassDependency>());
4528
4529                                 addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, TestConfig(renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4530                         }
4531
4532                         formatGroup->addChild(loadOpGroup.release());
4533                 }
4534
4535                 group->addChild(formatGroup.release());
4536         }
4537
4538         // Depth stencil formats
4539         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_coreDepthStencilFormats); formatNdx++)
4540         {
4541                 const VkFormat                                  format          = s_coreDepthStencilFormats[formatNdx];
4542                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, formatToName(format).c_str(), de::toString(format).c_str()));
4543
4544                 for (size_t loadOpNdx = 0; loadOpNdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpNdx++)
4545                 {
4546                         const VkAttachmentLoadOp                loadOp  = loadOps[loadOpNdx].op;
4547                         de::MovePtr<tcu::TestCaseGroup> loadOpGroup     (new tcu::TestCaseGroup(testCtx, loadOps[loadOpNdx].str, loadOps[loadOpNdx].str));
4548
4549                         for (size_t renderTypeNdx = 0; renderTypeNdx < DE_LENGTH_OF_ARRAY(renderTypes); renderTypeNdx++)
4550                         {
4551                                 const RenderPass        renderPass      (vector<Attachment>(1, Attachment(format,
4552                                                                                                                                                                   VK_SAMPLE_COUNT_1_BIT,
4553                                                                                                                                                                   VK_ATTACHMENT_LOAD_OP_DONT_CARE,
4554                                                                                                                                                                   VK_ATTACHMENT_STORE_OP_DONT_CARE,
4555                                                                                                                                                                   loadOp,
4556                                                                                                                                                                   VK_ATTACHMENT_STORE_OP_STORE,
4557                                                                                                                                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4558                                                                                                                                                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)),
4559                                                                                                  vector<Subpass>(1, Subpass(VK_PIPELINE_BIND_POINT_GRAPHICS,
4560                                                                                                                                                         0u,
4561                                                                                                                                                         vector<AttachmentReference>(),
4562                                                                                                                                                         vector<AttachmentReference>(),
4563                                                                                                                                                         vector<AttachmentReference>(),
4564                                                                                                                                                         AttachmentReference(0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL),
4565                                                                                                                                                         vector<AttachmentReference>())),
4566                                                                                                  vector<SubpassDependency>());
4567
4568                                 addFunctionCaseWithPrograms<TestConfig>(loadOpGroup.get(), renderTypes[renderTypeNdx].str, renderTypes[renderTypeNdx].str, createTestShaders, renderPassTest, TestConfig(renderPass, renderTypes[renderTypeNdx].types, TestConfig::COMMANDBUFFERTYPES_INLINE, TestConfig::IMAGEMEMORY_STRICT, targetSize, renderPos, renderSize, 90239));
4569                         }
4570
4571                         formatGroup->addChild(loadOpGroup.release());
4572                 }
4573
4574                 group->addChild(formatGroup.release());
4575         }
4576
4577         return group;
4578 }
4579
4580 } // anonymous
4581
4582 tcu::TestCaseGroup* createRenderPassTests (tcu::TestContext& testCtx)
4583 {
4584         de::MovePtr<tcu::TestCaseGroup> renderpassTests (new tcu::TestCaseGroup(testCtx, "renderpass", "RenderPass Tests"));
4585
4586         renderpassTests->addChild(createSimpleTestGroup(testCtx).release());
4587         renderpassTests->addChild(createFormatTestGroup(testCtx).release());
4588         renderpassTests->addChild(createAttachmentTestCaseGroup(testCtx).release());
4589         renderpassTests->addChild(createAttachmentAllocationTestGroup(testCtx).release());
4590
4591         return renderpassTests.release();
4592 }
4593
4594 } // vkt