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