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