c9d6d8498eb621699622c0fb0ed23cebcc208454
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineRenderToImageTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group 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 vktPipelineRenderToImageTests.cpp
21  * \brief Render to image tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineRenderToImageTests.hpp"
25 #include "vktPipelineMakeUtil.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30
31 #include "vkMemUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkImageUtil.hpp"
38
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuTestLog.hpp"
42
43 #include "deUniquePtr.hpp"
44 #include "deSharedPtr.hpp"
45
46 #include <string>
47 #include <vector>
48 #include <set>
49
50 namespace vkt
51 {
52 namespace pipeline
53 {
54 namespace
55 {
56 using namespace vk;
57 using de::UniquePtr;
58 using de::MovePtr;
59 using de::SharedPtr;
60 using tcu::IVec3;
61 using tcu::Vec4;
62 using tcu::UVec4;
63 using tcu::IVec2;
64 using tcu::IVec4;
65 using tcu::BVec4;
66 using std::vector;
67
68 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView;
69 typedef SharedPtr<Unique<VkPipeline> >  SharedPtrVkPipeline;
70
71 enum Constants
72 {
73         NUM_CUBE_FACES                                  = 6,
74         REFERENCE_COLOR_VALUE                   = 125,
75         REFERENCE_STENCIL_VALUE                 = 42,
76         MAX_SIZE                                                = -1,   //!< Should be queried at runtime and replaced with max possible value
77         MAX_VERIFICATION_REGION_SIZE    = 32,   //!<  Limit the checked area to a small size, especially for huge images
78         MAX_VERIFICATION_REGION_DEPTH   = 8,
79
80         MASK_W                                  = (1 | 0 | 0 | 0),
81         MASK_W_LAYERS                   = (1 | 0 | 0 | 8),
82         MASK_WH                                 = (1 | 2 | 0 | 0),
83         MASK_WH_LAYERS                  = (1 | 2 | 0 | 8),
84         MASK_WHD                                = (1 | 2 | 4 | 0),
85 };
86
87 static const float      REFERENCE_DEPTH_VALUE   = 1.0f;
88 static const Vec4       COLOR_TABLE[]                   =
89 {
90         Vec4(0.9f, 0.0f, 0.0f, 1.0f),
91         Vec4(0.6f, 1.0f, 0.0f, 1.0f),
92         Vec4(0.3f, 0.0f, 1.0f, 1.0f),
93         Vec4(0.1f, 1.0f, 1.0f, 1.0f),
94         Vec4(0.8f, 1.0f, 0.0f, 1.0f),
95         Vec4(0.5f, 0.0f, 1.0f, 1.0f),
96         Vec4(0.2f, 0.0f, 0.0f, 1.0f),
97         Vec4(1.0f, 1.0f, 0.0f, 1.0f),
98 };
99
100 struct CaseDef
101 {
102         VkImageViewType viewType;
103         IVec4                   imageSizeHint;                  //!< (w, h, d, layers), a component may have a symbolic value MAX_SIZE
104         VkFormat                colorFormat;
105         VkFormat                depthStencilFormat;             //! A depth/stencil format, or UNDEFINED if not used
106 };
107
108 template<typename T>
109 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
110 {
111         return SharedPtr<Unique<T> >(new Unique<T>(move));
112 }
113
114 template<typename T>
115 inline VkDeviceSize sizeInBytes (const vector<T>& vec)
116 {
117         return vec.size() * sizeof(vec[0]);
118 }
119
120 inline bool isCube (const VkImageViewType viewType)
121 {
122         return (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
123 }
124
125 inline VkDeviceSize product (const IVec4& v)
126 {
127         return ((static_cast<VkDeviceSize>(v.x()) * v.y()) * v.z()) * v.w();
128 }
129
130 template<typename T>
131 inline T sum (const vector<T>& v)
132 {
133         T total = static_cast<T>(0);
134         for (typename vector<T>::const_iterator it = v.begin(); it != v.end(); ++it)
135                 total += *it;
136         return total;
137 }
138
139 template <typename T, int Size>
140 int findIndexOfMaxComponent (const tcu::Vector<T, Size>& vec)
141 {
142         int index       = 0;
143         T       value   = vec[0];
144
145         for (int i = 1; i < Size; ++i)
146         {
147                 if (vec[i] > value)
148                 {
149                         index   = i;
150                         value   = vec[i];
151                 }
152         }
153
154         return index;
155 }
156
157 inline int maxLayersOrDepth (const IVec4& size)
158 {
159         // This is safe because 3D images must have layers (w) = 1
160         return deMax32(size.z(), size.w());
161 }
162
163 // This is very test specific, so be careful if you want to reuse this code.
164 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
165                                                                            const VkDevice                               device,
166                                                                            const VkPipeline                             basePipeline,           // for derivatives
167                                                                            const VkPipelineLayout               pipelineLayout,
168                                                                            const VkRenderPass                   renderPass,
169                                                                            const VkShaderModule                 vertexModule,
170                                                                            const VkShaderModule                 fragmentModule,
171                                                                            const IVec2&                                 renderSize,
172                                                                            const VkPrimitiveTopology    topology,
173                                                                            const deUint32                               subpass,
174                                                                            const bool                                   useDepth,
175                                                                            const bool                                   useStencil)
176 {
177         const VkVertexInputBindingDescription vertexInputBindingDescription =
178         {
179                 0u,                                                             // uint32_t                             binding;
180                 sizeof(Vertex4RGBA),                    // uint32_t                             stride;
181                 VK_VERTEX_INPUT_RATE_VERTEX,    // VkVertexInputRate    inputRate;
182         };
183
184         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
185         {
186                 {
187                         0u,                                                             // uint32_t                     location;
188                         0u,                                                             // uint32_t                     binding;
189                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat                     format;
190                         0u,                                                             // uint32_t                     offset;
191                 },
192                 {
193                         1u,                                                             // uint32_t                     location;
194                         0u,                                                             // uint32_t                     binding;
195                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat                     format;
196                         sizeof(Vec4),                                   // uint32_t                     offset;
197                 }
198         };
199
200         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
201         {
202                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
203                 DE_NULL,                                                                                                        // const void*                                                          pNext;
204                 (VkPipelineVertexInputStateCreateFlags)0,                                       // VkPipelineVertexInputStateCreateFlags        flags;
205                 1u,                                                                                                                     // uint32_t                                                                     vertexBindingDescriptionCount;
206                 &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
207                 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),           // uint32_t                                                                     vertexAttributeDescriptionCount;
208                 vertexInputAttributeDescriptions,                                                       // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
209         };
210
211         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
212         {
213                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
214                 DE_NULL,                                                                                                                // const void*                                                          pNext;
215                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags      flags;
216                 topology,                                                                                                               // VkPrimitiveTopology                                          topology;
217                 VK_FALSE,                                                                                                               // VkBool32                                                                     primitiveRestartEnable;
218         };
219
220         const VkViewport viewport = makeViewport(
221                 0.0f, 0.0f,
222                 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
223                 0.0f, 1.0f);
224
225         const VkRect2D scissor =
226         {
227                 makeOffset2D(0, 0),
228                 makeExtent2D(renderSize.x(), renderSize.y()),
229         };
230
231         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
232         {
233                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                                              sType;
234                 DE_NULL,                                                                                                // const void*                                                  pNext;
235                 (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags   flags;
236                 1u,                                                                                                             // uint32_t                                                             viewportCount;
237                 &viewport,                                                                                              // const VkViewport*                                    pViewports;
238                 1u,                                                                                                             // uint32_t                                                             scissorCount;
239                 &scissor,                                                                                               // const VkRect2D*                                              pScissors;
240         };
241
242         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
243         {
244                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
245                 DE_NULL,                                                                                                        // const void*                                                          pNext;
246                 (VkPipelineRasterizationStateCreateFlags)0,                                     // VkPipelineRasterizationStateCreateFlags      flags;
247                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthClampEnable;
248                 VK_FALSE,                                                                                                       // VkBool32                                                                     rasterizerDiscardEnable;
249                 VK_POLYGON_MODE_FILL,                                                                           // VkPolygonMode                                                        polygonMode;
250                 VK_CULL_MODE_NONE,                                                                                      // VkCullModeFlags                                                      cullMode;
251                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
252                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable;
253                 0.0f,                                                                                                           // float                                                                        depthBiasConstantFactor;
254                 0.0f,                                                                                                           // float                                                                        depthBiasClamp;
255                 0.0f,                                                                                                           // float                                                                        depthBiasSlopeFactor;
256                 1.0f,                                                                                                           // float                                                                        lineWidth;
257         };
258
259         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
260         {
261                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
262                 DE_NULL,                                                                                                        // const void*                                                          pNext;
263                 (VkPipelineMultisampleStateCreateFlags)0,                                       // VkPipelineMultisampleStateCreateFlags        flags;
264                 VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
265                 VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
266                 0.0f,                                                                                                           // float                                                                        minSampleShading;
267                 DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
268                 VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
269                 VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
270         };
271
272         const VkStencilOpState stencilOpState = makeStencilOpState(
273                 VK_STENCIL_OP_KEEP,                                                                     // stencil fail
274                 VK_STENCIL_OP_ZERO,                                                                     // depth & stencil pass
275                 VK_STENCIL_OP_KEEP,                                                                     // depth only fail
276                 VK_COMPARE_OP_EQUAL,                                                            // compare op
277                 ~0u,                                                                                            // compare mask
278                 ~0u,                                                                                            // write mask
279                 static_cast<deUint32>(REFERENCE_STENCIL_VALUE));        // reference
280
281         VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
282         {
283                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
284                 DE_NULL,                                                                                                        // const void*                                                          pNext;
285                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
286                 useDepth,                                                                                                       // VkBool32                                                                     depthTestEnable;
287                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthWriteEnable;
288                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
289                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
290                 useStencil,                                                                                                     // VkBool32                                                                     stencilTestEnable;
291                 stencilOpState,                                                                                         // VkStencilOpState                                                     front;
292                 stencilOpState,                                                                                         // VkStencilOpState                                                     back;
293                 0.0f,                                                                                                           // float                                                                        minDepthBounds;
294                 1.0f,                                                                                                           // float                                                                        maxDepthBounds;
295         };
296
297         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
298         // Number of blend attachments must equal the number of color attachments during any subpass.
299         const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
300         {
301                 VK_FALSE,                               // VkBool32                                     blendEnable;
302                 VK_BLEND_FACTOR_ONE,    // VkBlendFactor                        srcColorBlendFactor;
303                 VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        dstColorBlendFactor;
304                 VK_BLEND_OP_ADD,                // VkBlendOp                            colorBlendOp;
305                 VK_BLEND_FACTOR_ONE,    // VkBlendFactor                        srcAlphaBlendFactor;
306                 VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        dstAlphaBlendFactor;
307                 VK_BLEND_OP_ADD,                // VkBlendOp                            alphaBlendOp;
308                 colorComponentsAll,             // VkColorComponentFlags        colorWriteMask;
309         };
310
311         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
312         {
313                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
314                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
315                 (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
316                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
317                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
318                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
319                 &pipelineColorBlendAttachmentState,                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
320                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
321         };
322
323         const VkPipelineShaderStageCreateInfo pShaderStages[] =
324         {
325                 {
326                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
327                         DE_NULL,                                                                                                // const void*                                                  pNext;
328                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
329                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // VkShaderStageFlagBits                                stage;
330                         vertexModule,                                                                                   // VkShaderModule                                               module;
331                         "main",                                                                                                 // const char*                                                  pName;
332                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
333                 },
334                 {
335                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
336                         DE_NULL,                                                                                                // const void*                                                  pNext;
337                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
338                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // VkShaderStageFlagBits                                stage;
339                         fragmentModule,                                                                                 // VkShaderModule                                               module;
340                         "main",                                                                                                 // const char*                                                  pName;
341                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
342                 }
343         };
344
345         const VkPipelineCreateFlags                     flags = (basePipeline == DE_NULL ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
346                                                                                                                                                  : VK_PIPELINE_CREATE_DERIVATIVE_BIT);
347
348         const VkGraphicsPipelineCreateInfo      graphicsPipelineInfo =
349         {
350                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
351                 DE_NULL,                                                                                        // const void*                                                                          pNext;
352                 flags,                                                                                          // VkPipelineCreateFlags                                                        flags;
353                 DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
354                 pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
355                 &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
356                 &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
357                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
358                 &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
359                 &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
360                 &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
361                 &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
362                 &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
363                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
364                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
365                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
366                 subpass,                                                                                        // deUint32                                                                                     subpass;
367                 basePipeline,                                                                           // VkPipeline                                                                           basePipelineHandle;
368                 -1,                                                                                                     // deInt32                                                                                      basePipelineIndex;
369         };
370
371         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
372 }
373
374 //! Make a render pass with one subpass per color attachment and depth/stencil attachment (if used).
375 Move<VkRenderPass> makeRenderPass (const DeviceInterface&               vk,
376                                                                    const VkDevice                               device,
377                                                                    const VkFormat                               colorFormat,
378                                                                    const VkFormat                               depthStencilFormat,
379                                                                    const deUint32                               numLayers,
380                                                                    const VkImageLayout                  initialColorImageLayout                 = VK_IMAGE_LAYOUT_UNDEFINED,
381                                                                    const VkImageLayout                  initialDepthStencilImageLayout  = VK_IMAGE_LAYOUT_UNDEFINED)
382 {
383         const VkAttachmentDescription colorAttachmentDescription =
384         {
385                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
386                 colorFormat,                                                                            // VkFormat                                                     format;
387                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
388                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
389                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
390                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
391                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
392                 initialColorImageLayout,                                                        // VkImageLayout                                        initialLayout;
393                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
394         };
395         vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
396
397         const VkAttachmentDescription depthStencilAttachmentDescription =
398         {
399                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
400                 depthStencilFormat,                                                                     // VkFormat                                                     format;
401                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
402                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
403                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          storeOp;
404                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           stencilLoadOp;
405                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
406                 initialDepthStencilImageLayout,                                         // VkImageLayout                                        initialLayout;
407                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        finalLayout;
408         };
409
410         if (depthStencilFormat != VK_FORMAT_UNDEFINED)
411                 attachmentDescriptions.insert(attachmentDescriptions.end(), numLayers, depthStencilAttachmentDescription);
412
413         // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
414         vector<VkAttachmentReference>   colorAttachmentReferences               (numLayers);
415         vector<VkAttachmentReference>   depthStencilAttachmentReferences(numLayers);
416         vector<VkSubpassDescription>    subpasses;
417
418         // Ordering here must match the framebuffer attachments
419         for (deUint32 i = 0; i < numLayers; ++i)
420         {
421                 const VkAttachmentReference attachmentRef =
422                 {
423                         i,                                                                                                      // deUint32                     attachment;
424                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
425                 };
426                 const VkAttachmentReference depthStencilAttachmentRef =
427                 {
428                         i + numLayers,                                                                          // deUint32                     attachment;
429                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
430                 };
431
432                 colorAttachmentReferences[i]            = attachmentRef;
433                 depthStencilAttachmentReferences[i]     = depthStencilAttachmentRef;
434
435                 const VkAttachmentReference*    pDepthStencilAttachment = (depthStencilFormat != VK_FORMAT_UNDEFINED ? &depthStencilAttachmentReferences[i] : DE_NULL);
436                 const VkSubpassDescription              subpassDescription              =
437                 {
438                         (VkSubpassDescriptionFlags)0,                                   // VkSubpassDescriptionFlags            flags;
439                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                // VkPipelineBindPoint                          pipelineBindPoint;
440                         0u,                                                                                             // deUint32                                                     inputAttachmentCount;
441                         DE_NULL,                                                                                // const VkAttachmentReference*         pInputAttachments;
442                         1u,                                                                                             // deUint32                                                     colorAttachmentCount;
443                         &colorAttachmentReferences[i],                                  // const VkAttachmentReference*         pColorAttachments;
444                         DE_NULL,                                                                                // const VkAttachmentReference*         pResolveAttachments;
445                         pDepthStencilAttachment,                                                // const VkAttachmentReference*         pDepthStencilAttachment;
446                         0u,                                                                                             // deUint32                                                     preserveAttachmentCount;
447                         DE_NULL                                                                                 // const deUint32*                                      pPreserveAttachments;
448                 };
449                 subpasses.push_back(subpassDescription);
450         }
451
452         const VkRenderPassCreateInfo renderPassInfo =
453         {
454                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                                      sType;
455                 DE_NULL,                                                                                                // const void*                                          pNext;
456                 (VkRenderPassCreateFlags)0,                                                             // VkRenderPassCreateFlags                      flags;
457                 static_cast<deUint32>(attachmentDescriptions.size()),   // deUint32                                                     attachmentCount;
458                 &attachmentDescriptions[0],                                                             // const VkAttachmentDescription*       pAttachments;
459                 static_cast<deUint32>(subpasses.size()),                                // deUint32                                                     subpassCount;
460                 &subpasses[0],                                                                                  // const VkSubpassDescription*          pSubpasses;
461                 0u,                                                                                                             // deUint32                                                     dependencyCount;
462                 DE_NULL                                                                                                 // const VkSubpassDependency*           pDependencies;
463         };
464
465         return createRenderPass(vk, device, &renderPassInfo);
466 }
467
468 Move<VkImage> makeImage (const DeviceInterface&         vk,
469                                                  const VkDevice                         device,
470                                                  VkImageCreateFlags                     flags,
471                                                  VkImageType                            imageType,
472                                                  const VkFormat                         format,
473                                                  const IVec3&                           size,
474                                                  const deUint32                         numMipLevels,
475                                                  const deUint32                         numLayers,
476                                                  const VkImageUsageFlags        usage)
477 {
478         const VkImageCreateInfo imageParams =
479         {
480                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    // VkStructureType                      sType;
481                 DE_NULL,                                                                // const void*                          pNext;
482                 flags,                                                                  // VkImageCreateFlags           flags;
483                 imageType,                                                              // VkImageType                          imageType;
484                 format,                                                                 // VkFormat                                     format;
485                 makeExtent3D(size),                                             // VkExtent3D                           extent;
486                 numMipLevels,                                                   // deUint32                                     mipLevels;
487                 numLayers,                                                              // deUint32                                     arrayLayers;
488                 VK_SAMPLE_COUNT_1_BIT,                                  // VkSampleCountFlagBits        samples;
489                 VK_IMAGE_TILING_OPTIMAL,                                // VkImageTiling                        tiling;
490                 usage,                                                                  // VkImageUsageFlags            usage;
491                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                        sharingMode;
492                 0u,                                                                             // deUint32                                     queueFamilyIndexCount;
493                 DE_NULL,                                                                // const deUint32*                      pQueueFamilyIndices;
494                 VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        initialLayout;
495         };
496         return createImage(vk, device, &imageParams);
497 }
498
499 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
500 {
501         const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
502         return createBuffer(vk, device, &bufferCreateInfo);
503 }
504
505 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
506 {
507         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
508 }
509
510 //! Get a reference clear value based on color format.
511 VkClearValue getClearValue (const VkFormat format)
512 {
513         if (isUintFormat(format) || isIntFormat(format))
514                 return makeClearValueColorU32(REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE);
515         else
516                 return makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
517 }
518
519 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
520 {
521         std::ostringstream str;
522         if (numComponents == 1)
523                 str << (isUint ? "uint" : isSint ? "int" : "float");
524         else
525                 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
526
527         return str.str();
528 }
529
530 //! A half-viewport quad. Use with TRIANGLE_STRIP topology.
531 vector<Vertex4RGBA> genFullQuadVertices (const int subpassCount)
532 {
533         vector<Vertex4RGBA>     vectorData;
534         for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
535         {
536                 Vertex4RGBA data =
537                 {
538                         Vec4(0.0f, -1.0f, 0.0f, 1.0f),
539                         COLOR_TABLE[subpassNdx % DE_LENGTH_OF_ARRAY(COLOR_TABLE)],
540                 };
541                 vectorData.push_back(data);
542                 data.position   = Vec4(0.0f,  1.0f, 0.0f, 1.0f);
543                 vectorData.push_back(data);
544                 data.position   = Vec4(1.0f, -1.0f, 0.0f, 1.0f);
545                 vectorData.push_back(data);
546                 data.position   = Vec4(1.0f,  1.0f, 0.0f, 1.0f);
547                 vectorData.push_back(data);
548         }
549         return vectorData;
550 }
551
552 VkImageType getImageType (const VkImageViewType viewType)
553 {
554         switch (viewType)
555         {
556                 case VK_IMAGE_VIEW_TYPE_1D:
557                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
558                         return VK_IMAGE_TYPE_1D;
559
560                 case VK_IMAGE_VIEW_TYPE_2D:
561                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
562                 case VK_IMAGE_VIEW_TYPE_CUBE:
563                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
564                         return VK_IMAGE_TYPE_2D;
565
566                 case VK_IMAGE_VIEW_TYPE_3D:
567                         return VK_IMAGE_TYPE_3D;
568
569                 default:
570                         DE_ASSERT(0);
571                         return VK_IMAGE_TYPE_LAST;
572         }
573 }
574
575 //! ImageViewType for accessing a single layer/slice of an image
576 VkImageViewType getImageViewSliceType (const VkImageViewType viewType)
577 {
578         switch (viewType)
579         {
580                 case VK_IMAGE_VIEW_TYPE_1D:
581                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
582                         return VK_IMAGE_VIEW_TYPE_1D;
583
584                 case VK_IMAGE_VIEW_TYPE_2D:
585                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
586                 case VK_IMAGE_VIEW_TYPE_CUBE:
587                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
588                 case VK_IMAGE_VIEW_TYPE_3D:
589                         return VK_IMAGE_VIEW_TYPE_2D;
590
591                 default:
592                         DE_ASSERT(0);
593                         return VK_IMAGE_VIEW_TYPE_LAST;
594         }
595 }
596
597 VkImageCreateFlags getImageCreateFlags (const VkImageViewType viewType)
598 {
599         VkImageCreateFlags      flags   = (VkImageCreateFlags)0;
600
601         if (viewType == VK_IMAGE_VIEW_TYPE_3D)  flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
602         if (isCube(viewType))                                   flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
603
604         return flags;
605 }
606
607 void generateExpectedImage (const tcu::PixelBufferAccess& outputImage, const IVec2& renderSize, const int colorDepthOffset)
608 {
609         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(outputImage.getFormat().type);
610         const bool                                              isInt                   = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
611         const VkClearValue                              clearValue              = getClearValue(mapTextureFormat(outputImage.getFormat()));
612
613         if (isInt)
614                 tcu::clear(outputImage, IVec4(clearValue.color.int32));
615         else
616                 tcu::clear(outputImage, Vec4(clearValue.color.float32));
617
618         for (int z = 0; z < outputImage.getDepth(); ++z)
619         {
620                 const Vec4& setColor    = COLOR_TABLE[(z + colorDepthOffset) % DE_LENGTH_OF_ARRAY(COLOR_TABLE)];
621                 const IVec4 setColorInt = (static_cast<float>(REFERENCE_COLOR_VALUE) * setColor).cast<deInt32>();
622
623                 for (int y = 0;                                 y < renderSize.y(); ++y)
624                 for (int x = renderSize.x()/2;  x < renderSize.x(); ++x)
625                 {
626                         if (isInt)
627                                 outputImage.setPixel(setColorInt, x, y, z);
628                         else
629                                 outputImage.setPixel(setColor, x, y, z);
630                 }
631         }
632 }
633
634 VkDeviceSize getMaxDeviceHeapSize (const InstanceInterface& vki, const VkPhysicalDevice physDevice)
635 {
636         const VkPhysicalDeviceMemoryProperties  memoryProperties        = getPhysicalDeviceMemoryProperties(vki, physDevice);
637         VkDeviceSize                                                    memorySize                      = 0;
638
639         for (deUint32 heapNdx = 0; heapNdx < memoryProperties.memoryHeapCount; ++heapNdx)
640         {
641                 if ((memoryProperties.memoryHeaps[heapNdx].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
642                         memorySize = std::max(memorySize, memoryProperties.memoryHeaps[heapNdx].size);
643         }
644
645         return memorySize;
646 }
647
648 //! Get a smaller image size. Returns a vector of zeroes, if it can't reduce more.
649 IVec4 getReducedImageSize (const CaseDef& caseDef, IVec4 size)
650 {
651         const int maxIndex              = findIndexOfMaxComponent(size);
652         const int reducedSize   = size[maxIndex] >> 1;
653
654         switch (caseDef.viewType)
655         {
656                 case VK_IMAGE_VIEW_TYPE_CUBE:
657                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
658                         if (maxIndex < 2)
659                                 size.x() = size.y() = reducedSize;
660                         else if (maxIndex == 3 && reducedSize >= NUM_CUBE_FACES)
661                                 size.w() = NUM_CUBE_FACES * (reducedSize / NUM_CUBE_FACES); // round down to a multiple of 6
662                         else
663                                 size = IVec4(0);
664                         break;
665
666                 default:
667                         size[maxIndex] = reducedSize;
668                         break;
669         }
670
671         if (reducedSize == 0)
672                 size = IVec4(0);
673
674         return size;
675 }
676
677 bool isDepthStencilFormatSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format)
678 {
679         const VkFormatProperties properties = getPhysicalDeviceFormatProperties(vki, physDevice, format);
680         return (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
681 }
682
683 IVec4 getMaxImageSize (const VkPhysicalDeviceLimits& limits, const VkImageViewType viewType, const IVec4& sizeHint, const bool useDepthStencil)
684 {
685         // If we use a layered D/S together with a 3D image, we have to use the smallest common limit
686         const int maxDepth = (useDepthStencil ? deMin32(static_cast<int>(limits.maxImageArrayLayers), static_cast<int>(limits.maxImageDimension3D))
687                                                                                   : static_cast<int>(limits.maxImageDimension3D));
688
689         // Images have to respect framebuffer limits and image limits (the framebuffer is not layered in this case)
690         IVec4 size = IVec4(
691                 sizeHint.x() != MAX_SIZE ? sizeHint.x() : static_cast<int>(limits.maxFramebufferWidth),
692                 sizeHint.y() != MAX_SIZE ? sizeHint.y() : static_cast<int>(limits.maxFramebufferHeight),
693                 sizeHint.z() != MAX_SIZE ? sizeHint.z() : maxDepth,
694                 sizeHint.w() != MAX_SIZE ? sizeHint.w() : static_cast<int>(limits.maxImageArrayLayers));
695
696         switch (viewType)
697         {
698                 case VK_IMAGE_VIEW_TYPE_1D:
699                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
700                         size.x() = deMin32(size.x(), limits.maxImageDimension1D);
701                         break;
702
703                 case VK_IMAGE_VIEW_TYPE_2D:
704                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
705                         size.x() = deMin32(size.x(), limits.maxImageDimension2D);
706                         size.y() = deMin32(size.y(), limits.maxImageDimension2D);
707                         break;
708
709                 case VK_IMAGE_VIEW_TYPE_3D:
710                         size.x() = deMin32(size.x(), limits.maxImageDimension3D);
711                         size.y() = deMin32(size.y(), limits.maxImageDimension3D);
712                         break;
713
714                 case VK_IMAGE_VIEW_TYPE_CUBE:
715                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
716                         size.x() = size.y() = deMin32(size.x(), limits.maxImageDimensionCube);
717                         size.w() = NUM_CUBE_FACES * (size.w() / NUM_CUBE_FACES);        // round down to 6 faces
718                         break;
719
720                 default:
721                         DE_ASSERT(0);
722                         return IVec4();
723         }
724
725         return size;
726 }
727
728 VkImageAspectFlags getFormatAspectFlags (const VkFormat format)
729 {
730         if (format == VK_FORMAT_UNDEFINED)
731                 return 0;
732
733         const tcu::TextureFormat::ChannelOrder  order   = mapVkFormat(format).order;
734
735         switch (order)
736         {
737                 case tcu::TextureFormat::DS:    return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
738                 case tcu::TextureFormat::D:             return VK_IMAGE_ASPECT_DEPTH_BIT;
739                 case tcu::TextureFormat::S:             return VK_IMAGE_ASPECT_STENCIL_BIT;
740                 default:                                                return VK_IMAGE_ASPECT_COLOR_BIT;
741         }
742 }
743
744 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
745 {
746         const int       numComponents   = getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
747         const bool      isUint                  = isUintFormat(caseDef.colorFormat);
748         const bool      isSint                  = isIntFormat(caseDef.colorFormat);
749
750         // Vertex shader
751         {
752                 std::ostringstream src;
753                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
754                         << "\n"
755                         << "layout(location = 0) in  vec4 in_position;\n"
756                         << "layout(location = 1) in  vec4 in_color;\n"
757                         << "layout(location = 0) out vec4 out_color;\n"
758                         << "\n"
759                         << "out gl_PerVertex {\n"
760                         << "    vec4 gl_Position;\n"
761                         << "};\n"
762                         << "\n"
763                         << "void main(void)\n"
764                         << "{\n"
765                         << "    gl_Position     = in_position;\n"
766                         << "    out_color       = in_color;\n"
767                         << "}\n";
768
769                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
770         }
771
772         // Fragment shader
773         {
774                 std::ostringstream colorValue;
775                 colorValue << REFERENCE_COLOR_VALUE;
776                 const std::string colorFormat   = getColorFormatStr(numComponents, isUint, isSint);
777                 const std::string colorInteger  = (isUint || isSint ? " * "+colorFormat+"("+colorValue.str()+")" :"");
778
779                 std::ostringstream src;
780                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
781                         << "\n"
782                         << "layout(location = 0) in  vec4 in_color;\n"
783                         << "layout(location = 0) out " << colorFormat << " o_color;\n"
784                         << "\n"
785                         << "void main(void)\n"
786                         << "{\n"
787                         << "    o_color = " << colorFormat << "("
788                         << (numComponents == 1 ? "in_color.r"   :
789                                 numComponents == 2 ? "in_color.rg"  :
790                                 numComponents == 3 ? "in_color.rgb" : "in_color")
791                         << colorInteger
792                         << ");\n"
793                         << "}\n";
794
795                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
796         }
797 }
798
799 //! See testAttachmentSize() description
800 tcu::TestStatus testWithSizeReduction (Context& context, const CaseDef& caseDef, const int sizeReductionIndex)
801 {
802         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
803         const InstanceInterface&                vki                                     = context.getInstanceInterface();
804         const VkDevice                                  device                          = context.getDevice();
805         const VkPhysicalDevice                  physDevice                      = context.getPhysicalDevice();
806         const VkQueue                                   queue                           = context.getUniversalQueue();
807         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
808         Allocator&                                              allocator                       = context.getDefaultAllocator();
809
810         // The memory might be too small to allocate a largest possible attachment, so try to account for that.
811         const bool                                              useDepthStencil         = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
812         const VkDeviceSize                              deviceMemoryBudget      = getMaxDeviceHeapSize(vki, physDevice) >> 2;
813         IVec4                                                   imageSize                       = getMaxImageSize(context.getDeviceProperties().limits, caseDef.viewType, caseDef.imageSizeHint, useDepthStencil);
814
815         // Keep reducing the size, if needed
816         for (int i = 0; i < sizeReductionIndex; ++i)
817         {
818                 imageSize = getReducedImageSize(caseDef, imageSize);
819
820                 if (imageSize == IVec4())
821                         return tcu::TestStatus::fail("Couldn't create an image with required size");
822         }
823
824         context.getTestContext().getLog()
825                 << tcu::TestLog::Message << "Using an image with size (width, height, depth, layers) = " << imageSize << tcu::TestLog::EndMessage;
826
827         // "Slices" is either the depth of a 3D image, or the number of layers of an arrayed image
828         const deInt32                                   numSlices                       = maxLayersOrDepth(imageSize);
829         const VkDeviceSize                              colorSize                       = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
830         const VkDeviceSize                              depthStencilSize        = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull);
831
832         if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat))
833                 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format");
834
835         if (colorSize + depthStencilSize > deviceMemoryBudget)
836                 throw OutOfMemoryError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Image size exceeds test's image memory budget");
837
838         // Determine the verification bounds. The checked region will be in the center of the rendered image
839         const IVec4     checkSize       = tcu::min(imageSize, IVec4(MAX_VERIFICATION_REGION_SIZE,
840                                                                                                                 MAX_VERIFICATION_REGION_SIZE,
841                                                                                                                 MAX_VERIFICATION_REGION_DEPTH,
842                                                                                                                 MAX_VERIFICATION_REGION_DEPTH));
843         const IVec4     checkOffset     = (imageSize - checkSize) / 2;
844
845         // Only make enough space for the check region
846         const VkDeviceSize                              colorBufferSize         = product(checkSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
847         const Unique<VkBuffer>                  colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
848         const UniquePtr<Allocation>             colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
849
850         {
851                 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
852                 flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
853         }
854
855         const Unique<VkShaderModule>    vertexModule    (createShaderModule                     (vk, device, context.getBinaryCollection().get("vert"), 0u));
856         const Unique<VkShaderModule>    fragmentModule  (createShaderModule                     (vk, device, context.getBinaryCollection().get("frag"), 0u));
857         const Unique<VkRenderPass>              renderPass              (makeRenderPass                         (vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices)));
858         const Unique<VkPipelineLayout>  pipelineLayout  (makePipelineLayout                     (vk, device));
859         vector<SharedPtrVkPipeline>             pipelines;
860
861         Move<VkImage>                                   colorImage;
862         MovePtr<Allocation>                             colorImageAlloc;
863         vector<SharedPtrVkImageView>    colorAttachments;
864         Move<VkImage>                                   depthStencilImage;
865         MovePtr<Allocation>                             depthStencilImageAlloc;
866         vector<SharedPtrVkImageView>    depthStencilAttachments;
867         vector<VkImageView>                             attachmentHandles;                      // all attachments (color and d/s)
868         Move<VkBuffer>                                  vertexBuffer;
869         MovePtr<Allocation>                             vertexBufferAlloc;
870         Move<VkFramebuffer>                             framebuffer;
871
872         // Create a color image
873         {
874                 const VkImageUsageFlags imageUsage      = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
875
876                 colorImage              = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
877                                                                         imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), imageUsage);
878                 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
879         }
880
881         // Create a depth/stencil image (always a 2D image, optionally layered)
882         if (useDepthStencil)
883         {
884                 const VkImageUsageFlags imageUsage      = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
885
886                 depthStencilImage               = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
887                                                                                         IVec3(imageSize.x(), imageSize.y(), 1), 1u, numSlices, imageUsage);
888                 depthStencilImageAlloc  = bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any);
889         }
890
891         // Create a vertex buffer
892         {
893                 const vector<Vertex4RGBA>       vertices                        = genFullQuadVertices(numSlices);
894                 const VkDeviceSize                      vertexBufferSize        = sizeInBytes(vertices);
895
896                 vertexBuffer            = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
897                 vertexBufferAlloc       = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
898                 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
899                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
900         }
901
902         // For each image layer or slice (3D), create an attachment and a pipeline
903         {
904                 const VkImageAspectFlags        depthStencilAspect              = getFormatAspectFlags(caseDef.depthStencilFormat);
905                 const bool                                      useDepth                                = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT)   != 0;
906                 const bool                                      useStencil                              = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
907                 VkPipeline                                      basePipeline                    = DE_NULL;
908
909                 // Color attachments are first in the framebuffer
910                 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
911                 {
912                         colorAttachments.push_back(makeSharedPtr(
913                                 makeImageView(vk, device, *colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat, makeColorSubresourceRange(subpassNdx, 1))));
914                         attachmentHandles.push_back(**colorAttachments.back());
915
916                         // We also have to create pipelines for each subpass
917                         pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(
918                                 vk, device, basePipeline, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, imageSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
919                                 static_cast<deUint32>(subpassNdx), useDepth, useStencil)));
920
921                         basePipeline = **pipelines.front();
922                 }
923
924                 // Then D/S attachments, if any
925                 if (useDepthStencil)
926                 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
927                 {
928                         depthStencilAttachments.push_back(makeSharedPtr(
929                                 makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat, makeImageSubresourceRange(depthStencilAspect, 0u, 1u, subpassNdx, 1u))));
930                         attachmentHandles.push_back(**depthStencilAttachments.back());
931                 }
932         }
933
934         framebuffer = makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0], static_cast<deUint32>(imageSize.x()), static_cast<deUint32>(imageSize.y()));
935
936         {
937                 const Unique<VkCommandPool>             cmdPool         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
938                 const Unique<VkCommandBuffer>   cmdBuffer       (makeCommandBuffer(vk, device, *cmdPool));
939
940                 beginCommandBuffer(vk, *cmdBuffer);
941                 {
942                         vector<VkClearValue>    clearValues     (numSlices, getClearValue(caseDef.colorFormat));
943
944                         if (useDepthStencil)
945                                 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE));
946
947                         const VkRect2D                  renderArea      =
948                         {
949                                 makeOffset2D(0, 0),
950                                 makeExtent2D(imageSize.x(), imageSize.y()),
951                         };
952                         const VkRenderPassBeginInfo     renderPassBeginInfo     =
953                         {
954                                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
955                                 DE_NULL,                                                                        // const void*             pNext;
956                                 *renderPass,                                                            // VkRenderPass            renderPass;
957                                 *framebuffer,                                                           // VkFramebuffer           framebuffer;
958                                 renderArea,                                                                     // VkRect2D                renderArea;
959                                 static_cast<deUint32>(clearValues.size()),      // uint32_t                clearValueCount;
960                                 &clearValues[0],                                                        // const VkClearValue*     pClearValues;
961                         };
962                         const VkDeviceSize              vertexBufferOffset      = 0ull;
963
964                         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
965                         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
966                 }
967
968                 // Draw
969                 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx)
970                 {
971                         if (subpassNdx != 0)
972                                 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
973
974                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
975                         vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u);
976                 }
977
978                 vk.cmdEndRenderPass(*cmdBuffer);
979
980                 // Copy colorImage -> host visible colorBuffer
981                 {
982                         const VkImageMemoryBarrier      imageBarriers[] =
983                         {
984                                 {
985                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
986                                         DE_NULL,                                                                                // const void*                          pNext;
987                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        outputMask;
988                                         VK_ACCESS_TRANSFER_READ_BIT,                                    // VkAccessFlags                        inputMask;
989                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                        oldLayout;
990                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                   // VkImageLayout                        newLayout;
991                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
992                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
993                                         *colorImage,                                                                    // VkImage                                      image;
994                                         makeColorSubresourceRange(0, imageSize.w())             // VkImageSubresourceRange      subresourceRange;
995                                 }
996                         };
997
998                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
999                                                                   0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1000
1001                         // Copy the checked region rather than the whole image
1002                         const VkImageSubresourceLayers  subresource     =
1003                         {
1004                                 VK_IMAGE_ASPECT_COLOR_BIT,                                                      // VkImageAspectFlags    aspectMask;
1005                                 0u,                                                                                                     // uint32_t              mipLevel;
1006                                 static_cast<deUint32>(checkOffset.w()),                         // uint32_t              baseArrayLayer;
1007                                 static_cast<deUint32>(checkSize.w()),                           // uint32_t              layerCount;
1008                         };
1009
1010                         const VkBufferImageCopy                 region          =
1011                         {
1012                                 0ull,                                                                                                                           // VkDeviceSize                bufferOffset;
1013                                 0u,                                                                                                                                     // uint32_t                    bufferRowLength;
1014                                 0u,                                                                                                                                     // uint32_t                    bufferImageHeight;
1015                                 subresource,                                                                                                            // VkImageSubresourceLayers    imageSubresource;
1016                                 makeOffset3D(checkOffset.x(), checkOffset.y(), checkOffset.z()),        // VkOffset3D                  imageOffset;
1017                                 makeExtent3D(checkSize.swizzle(0, 1, 2)),                                                       // VkExtent3D                  imageExtent;
1018                         };
1019
1020                         vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1021
1022                         const VkBufferMemoryBarrier     bufferBarriers[] =
1023                         {
1024                                 {
1025                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
1026                                         DE_NULL,                                                                        // const void*        pNext;
1027                                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
1028                                         VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
1029                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
1030                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
1031                                         *colorBuffer,                                                           // VkBuffer           buffer;
1032                                         0ull,                                                                           // VkDeviceSize       offset;
1033                                         VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
1034                                 },
1035                         };
1036
1037                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1038                                                                   0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1039                 }
1040
1041                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1042                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1043         }
1044
1045         // Verify results
1046         {
1047                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1048
1049                 const tcu::TextureFormat                        format                  = mapVkFormat(caseDef.colorFormat);
1050                 const int                                                       checkDepth              = maxLayersOrDepth(checkSize);
1051                 const int                                                       depthOffset             = maxLayersOrDepth(checkOffset);
1052                 const tcu::ConstPixelBufferAccess       resultImage             (format, checkSize.x(), checkSize.y(), checkDepth, colorBufferAlloc->getHostPtr());
1053                 tcu::TextureLevel                                       textureLevel    (format, checkSize.x(), checkSize.y(), checkDepth);
1054                 const tcu::PixelBufferAccess            expectedImage   = textureLevel.getAccess();
1055                 bool                                                            ok                              = false;
1056
1057                 generateExpectedImage(expectedImage, checkSize.swizzle(0, 1), depthOffset);
1058
1059                 if (isFloatFormat(caseDef.colorFormat))
1060                         ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1061                 else
1062                         ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT);
1063
1064                 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1065         }
1066 }
1067
1068 void checkImageViewTypeRequirements (Context& context, const VkImageViewType viewType)
1069 {
1070         if (viewType == VK_IMAGE_VIEW_TYPE_3D &&
1071                 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1"))
1072                 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1073
1074         if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !context.getDeviceFeatures().imageCubeArray)
1075                 TCU_THROW(NotSupportedError, "Missing feature: imageCubeArray");
1076 }
1077
1078 //! A test that can exercise very big color and depth/stencil attachment sizes.
1079 //! If the total memory consumed by images is too large, or if the implementation returns OUT_OF_MEMORY error somewhere,
1080 //! the test can be retried with a next increment of size reduction index, making the attachments smaller.
1081 tcu::TestStatus testAttachmentSize (Context& context, const CaseDef caseDef)
1082 {
1083         checkImageViewTypeRequirements(context, caseDef.viewType);
1084
1085         int sizeReductionIndex = 0;
1086
1087         for (;;)
1088         {
1089                 try
1090                 {
1091                         return testWithSizeReduction(context, caseDef, sizeReductionIndex);
1092                 }
1093                 catch (OutOfMemoryError& ex)
1094                 {
1095                         context.getTestContext().getLog()
1096                                 << tcu::TestLog::Message << "-- OutOfMemoryError: " << ex.getMessage() << tcu::TestLog::EndMessage;
1097
1098                         ++sizeReductionIndex;
1099                 }
1100         }
1101         // Never reached
1102 }
1103
1104 vector<IVec4> getMipLevelSizes (IVec4 baseSize)
1105 {
1106         vector<IVec4> levels;
1107         levels.push_back(baseSize);
1108
1109         while (baseSize.x() != 1 || baseSize.y() != 1 || baseSize.z() != 1)
1110         {
1111                 baseSize.x() = deMax32(baseSize.x() >> 1, 1);
1112                 baseSize.y() = deMax32(baseSize.y() >> 1, 1);
1113                 baseSize.z() = deMax32(baseSize.z() >> 1, 1);
1114                 levels.push_back(baseSize);
1115         }
1116
1117         return levels;
1118 }
1119
1120 //! Compute memory consumed by each mip level, including all layers. Sizes include a padding for alignment.
1121 vector<VkDeviceSize> getPerMipLevelStorageSize (const vector<IVec4>& mipLevelSizes, const VkDeviceSize pixelSize)
1122 {
1123         const deInt64                   levelAlignment  = 16;
1124         vector<VkDeviceSize>    storageSizes;
1125
1126         for (vector<IVec4>::const_iterator it = mipLevelSizes.begin(); it != mipLevelSizes.end(); ++it)
1127                 storageSizes.push_back(deAlign64(pixelSize * product(*it), levelAlignment));
1128
1129         return storageSizes;
1130 }
1131
1132 void drawToMipLevel (const Context&                             context,
1133                                          const CaseDef&                         caseDef,
1134                                          const int                                      mipLevel,
1135                                          const IVec4&                           mipSize,
1136                                          const int                                      numSlices,
1137                                          const VkImage                          colorImage,
1138                                          const VkImage                          depthStencilImage,
1139                                          const VkBuffer                         vertexBuffer,
1140                                          const VkPipelineLayout         pipelineLayout,
1141                                          const VkShaderModule           vertexModule,
1142                                          const VkShaderModule           fragmentModule)
1143 {
1144         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
1145         const VkDevice                                  device                          = context.getDevice();
1146         const VkQueue                                   queue                           = context.getUniversalQueue();
1147         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1148         const VkImageAspectFlags                depthStencilAspect      = getFormatAspectFlags(caseDef.depthStencilFormat);
1149         const bool                                              useDepth                        = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT)   != 0;
1150         const bool                                              useStencil                      = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
1151         const Unique<VkRenderPass>              renderPass                      (makeRenderPass(vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices),
1152                                                                                                                                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1153                                                                                                                                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
1154         vector<SharedPtrVkPipeline>             pipelines;
1155         vector<SharedPtrVkImageView>    colorAttachments;
1156         vector<SharedPtrVkImageView>    depthStencilAttachments;
1157         vector<VkImageView>                             attachmentHandles;                      // all attachments (color and d/s)
1158
1159         // For each image layer or slice (3D), create an attachment and a pipeline
1160         {
1161                 VkPipeline                                      basePipeline                    = DE_NULL;
1162
1163                 // Color attachments are first in the framebuffer
1164                 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1165                 {
1166                         colorAttachments.push_back(makeSharedPtr(makeImageView(
1167                                 vk, device, colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat,
1168                                 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, subpassNdx, 1u))));
1169                         attachmentHandles.push_back(**colorAttachments.back());
1170
1171                         // We also have to create pipelines for each subpass
1172                         pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(
1173                                 vk, device, basePipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, mipSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1174                                 static_cast<deUint32>(subpassNdx), useDepth, useStencil)));
1175
1176                         basePipeline = **pipelines.front();
1177                 }
1178
1179                 // Then D/S attachments, if any
1180                 if (useDepth || useStencil)
1181                 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1182                 {
1183                         depthStencilAttachments.push_back(makeSharedPtr(makeImageView(
1184                                 vk, device, depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat,
1185                                 makeImageSubresourceRange(depthStencilAspect, mipLevel, 1u, subpassNdx, 1u))));
1186                         attachmentHandles.push_back(**depthStencilAttachments.back());
1187                 }
1188         }
1189
1190         const Unique<VkFramebuffer>                     framebuffer (makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0],
1191                                                                                                                                          static_cast<deUint32>(mipSize.x()), static_cast<deUint32>(mipSize.y())));
1192
1193         {
1194                 const Unique<VkCommandPool>             cmdPool         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1195                 const Unique<VkCommandBuffer>   cmdBuffer       (makeCommandBuffer(vk, device, *cmdPool));
1196
1197                 beginCommandBuffer(vk, *cmdBuffer);
1198                 {
1199                         vector<VkClearValue>    clearValues     (numSlices, getClearValue(caseDef.colorFormat));
1200
1201                         if (useDepth || useStencil)
1202                                 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE));
1203
1204                         const VkRect2D                  renderArea      =
1205                         {
1206                                 makeOffset2D(0, 0),
1207                                 makeExtent2D(mipSize.x(), mipSize.y()),
1208                         };
1209                         const VkRenderPassBeginInfo     renderPassBeginInfo     =
1210                         {
1211                                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
1212                                 DE_NULL,                                                                        // const void*             pNext;
1213                                 *renderPass,                                                            // VkRenderPass            renderPass;
1214                                 *framebuffer,                                                           // VkFramebuffer           framebuffer;
1215                                 renderArea,                                                                     // VkRect2D                renderArea;
1216                                 static_cast<deUint32>(clearValues.size()),      // uint32_t                clearValueCount;
1217                                 &clearValues[0],                                                        // const VkClearValue*     pClearValues;
1218                         };
1219                         const VkDeviceSize              vertexBufferOffset      = 0ull;
1220
1221                         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1222                         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
1223                 }
1224
1225                 // Draw
1226                 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx)
1227                 {
1228                         if (subpassNdx != 0)
1229                                 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1230
1231                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
1232                         vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u);
1233                 }
1234
1235                 vk.cmdEndRenderPass(*cmdBuffer);
1236
1237                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1238                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1239         }
1240 }
1241
1242 //! Use image mip levels as attachments
1243 tcu::TestStatus testRenderToMipMaps (Context& context, const CaseDef caseDef)
1244 {
1245         checkImageViewTypeRequirements(context, caseDef.viewType);
1246
1247         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
1248         const InstanceInterface&                vki                                     = context.getInstanceInterface();
1249         const VkDevice                                  device                          = context.getDevice();
1250         const VkPhysicalDevice                  physDevice                      = context.getPhysicalDevice();
1251         const VkQueue                                   queue                           = context.getUniversalQueue();
1252         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1253         Allocator&                                              allocator                       = context.getDefaultAllocator();
1254
1255         const IVec4                                             imageSize                               = caseDef.imageSizeHint;        // MAX_SIZE is not used in this test
1256         const deInt32                                   numSlices                               = maxLayersOrDepth(imageSize);
1257         const vector<IVec4>                             mipLevelSizes                   = getMipLevelSizes(imageSize);
1258         const vector<VkDeviceSize>              mipLevelStorageSizes    = getPerMipLevelStorageSize(mipLevelSizes, tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)));
1259         const int                                               numMipLevels                    = static_cast<int>(mipLevelSizes.size());
1260         const bool                                              useDepthStencil                 = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
1261
1262         if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat))
1263                 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format");
1264
1265         // Create a color buffer big enough to hold all layers and mip levels
1266         const VkDeviceSize                              colorBufferSize         = sum(mipLevelStorageSizes);
1267         const Unique<VkBuffer>                  colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1268         const UniquePtr<Allocation>             colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1269
1270         {
1271                 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1272                 flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1273         }
1274
1275         const Unique<VkShaderModule>    vertexModule            (createShaderModule     (vk, device, context.getBinaryCollection().get("vert"), 0u));
1276         const Unique<VkShaderModule>    fragmentModule          (createShaderModule     (vk, device, context.getBinaryCollection().get("frag"), 0u));
1277         const Unique<VkPipelineLayout>  pipelineLayout          (makePipelineLayout     (vk, device));
1278
1279         Move<VkImage>                                   colorImage;
1280         MovePtr<Allocation>                             colorImageAlloc;
1281         Move<VkImage>                                   depthStencilImage;
1282         MovePtr<Allocation>                             depthStencilImageAlloc;
1283         Move<VkBuffer>                                  vertexBuffer;
1284         MovePtr<Allocation>                             vertexBufferAlloc;
1285
1286         // Create a color image
1287         {
1288                 const VkImageUsageFlags imageUsage      = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1289
1290                 colorImage              = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
1291                                                                         imageSize.swizzle(0, 1, 2), numMipLevels, imageSize.w(), imageUsage);
1292                 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1293         }
1294
1295         // Create a depth/stencil image (always a 2D image, optionally layered)
1296         if (useDepthStencil)
1297         {
1298                 const VkImageUsageFlags imageUsage      = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1299
1300                 depthStencilImage               = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
1301                                                                                         IVec3(imageSize.x(), imageSize.y(), 1), numMipLevels, numSlices, imageUsage);
1302                 depthStencilImageAlloc  = bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any);
1303         }
1304
1305         // Create a vertex buffer
1306         {
1307                 const vector<Vertex4RGBA>       vertices                        = genFullQuadVertices(numSlices);
1308                 const VkDeviceSize                      vertexBufferSize        = sizeInBytes(vertices);
1309
1310                 vertexBuffer            = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1311                 vertexBufferAlloc       = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1312                 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1313                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
1314         }
1315
1316         // Prepare images
1317         {
1318                 const Unique<VkCommandPool>             cmdPool         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1319                 const Unique<VkCommandBuffer>   cmdBuffer       (makeCommandBuffer(vk, device, *cmdPool));
1320
1321                 beginCommandBuffer(vk, *cmdBuffer);
1322
1323                 const VkImageMemoryBarrier      imageBarriers[] =
1324                 {
1325                         {
1326                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType            sType;
1327                                 DE_NULL,                                                                                        // const void*                pNext;
1328                                 (VkAccessFlags)0,                                                                       // VkAccessFlags              srcAccessMask;
1329                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                           // VkAccessFlags              dstAccessMask;
1330                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout              oldLayout;
1331                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout              newLayout;
1332                                 VK_QUEUE_FAMILY_IGNORED,                                                        // uint32_t                   srcQueueFamilyIndex;
1333                                 VK_QUEUE_FAMILY_IGNORED,                                                        // uint32_t                   dstQueueFamilyIndex;
1334                                 *colorImage,                                                                            // VkImage                    image;
1335                                 {                                                                                                       // VkImageSubresourceRange    subresourceRange;
1336                                         VK_IMAGE_ASPECT_COLOR_BIT,                                                      // VkImageAspectFlags    aspectMask;
1337                                         0u,                                                                                                     // uint32_t              baseMipLevel;
1338                                         static_cast<deUint32>(numMipLevels),                            // uint32_t              levelCount;
1339                                         0u,                                                                                                     // uint32_t              baseArrayLayer;
1340                                         static_cast<deUint32>(imageSize.w()),                           // uint32_t              layerCount;
1341                                 },
1342                         },
1343                         {
1344                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType            sType;
1345                                 DE_NULL,                                                                                        // const void*                pNext;
1346                                 (VkAccessFlags)0,                                                                       // VkAccessFlags              srcAccessMask;
1347                                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,           // VkAccessFlags              dstAccessMask;
1348                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout              oldLayout;
1349                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout              newLayout;
1350                                 VK_QUEUE_FAMILY_IGNORED,                                                        // uint32_t                   srcQueueFamilyIndex;
1351                                 VK_QUEUE_FAMILY_IGNORED,                                                        // uint32_t                   dstQueueFamilyIndex;
1352                                 *depthStencilImage,                                                                     // VkImage                    image;
1353                                 {                                                                                                       // VkImageSubresourceRange    subresourceRange;
1354                                         getFormatAspectFlags(caseDef.depthStencilFormat),       // VkImageAspectFlags    aspectMask;
1355                                         0u,                                                                                                     // uint32_t              baseMipLevel;
1356                                         static_cast<deUint32>(numMipLevels),                            // uint32_t              levelCount;
1357                                         0u,                                                                                                     // uint32_t              baseArrayLayer;
1358                                         static_cast<deUint32>(numSlices),                                       // uint32_t              layerCount;
1359                                 },
1360                         }
1361                 };
1362
1363                 const deUint32  numImageBarriers = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(imageBarriers) - (useDepthStencil ? 0 : 1));
1364
1365                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1366                                                                 0u, DE_NULL, 0u, DE_NULL, numImageBarriers, imageBarriers);
1367
1368                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1369                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1370         }
1371
1372         // Draw
1373         for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1374         {
1375                 const IVec4&    mipSize         = mipLevelSizes[mipLevel];
1376                 const int               levelSlices     = maxLayersOrDepth(mipSize);
1377
1378                 drawToMipLevel (context, caseDef, mipLevel, mipSize, levelSlices, *colorImage, *depthStencilImage, *vertexBuffer, *pipelineLayout,
1379                                                 *vertexModule, *fragmentModule);
1380         }
1381
1382         // Copy results: colorImage -> host visible colorBuffer
1383         {
1384                 const Unique<VkCommandPool>             cmdPool         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1385                 const Unique<VkCommandBuffer>   cmdBuffer       (makeCommandBuffer(vk, device, *cmdPool));
1386
1387                 beginCommandBuffer(vk, *cmdBuffer);
1388
1389                 {
1390                         const VkImageMemoryBarrier      imageBarriers[] =
1391                         {
1392                                 {
1393                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType            sType;
1394                                         DE_NULL,                                                                                // const void*                pNext;
1395                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags              srcAccessMask;
1396                                         VK_ACCESS_TRANSFER_READ_BIT,                                    // VkAccessFlags              dstAccessMask;
1397                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout              oldLayout;
1398                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                   // VkImageLayout              newLayout;
1399                                         VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t                   srcQueueFamilyIndex;
1400                                         VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t                   dstQueueFamilyIndex;
1401                                         *colorImage,                                                                    // VkImage                    image;
1402                                         {                                                                                               // VkImageSubresourceRange    subresourceRange;
1403                                                 VK_IMAGE_ASPECT_COLOR_BIT,                                                      // VkImageAspectFlags    aspectMask;
1404                                                 0u,                                                                                                     // uint32_t              baseMipLevel;
1405                                                 static_cast<deUint32>(numMipLevels),                            // uint32_t              levelCount;
1406                                                 0u,                                                                                                     // uint32_t              baseArrayLayer;
1407                                                 static_cast<deUint32>(imageSize.w()),                           // uint32_t              layerCount;
1408                                         },
1409                                 }
1410                         };
1411
1412                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1413                                                                         0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1414                 }
1415                 {
1416                         vector<VkBufferImageCopy>       regions;
1417                         VkDeviceSize                            levelOffset = 0ull;
1418                         VkBufferImageCopy                       workRegion      =
1419                         {
1420                                 0ull,                                                                                                                                                           // VkDeviceSize                bufferOffset;
1421                                 0u,                                                                                                                                                                     // uint32_t                    bufferRowLength;
1422                                 0u,                                                                                                                                                                     // uint32_t                    bufferImageHeight;
1423                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageSize.w()),           // VkImageSubresourceLayers    imageSubresource;
1424                                 makeOffset3D(0, 0, 0),                                                                                                                          // VkOffset3D                  imageOffset;
1425                                 makeExtent3D(0, 0, 0),                                                                                                                          // VkExtent3D                  imageExtent;
1426                         };
1427
1428                         for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1429                         {
1430                                 workRegion.bufferOffset                                 = levelOffset;
1431                                 workRegion.imageSubresource.mipLevel    = static_cast<deUint32>(mipLevel);
1432                                 workRegion.imageExtent                                  = makeExtent3D(mipLevelSizes[mipLevel].swizzle(0, 1, 2));
1433
1434                                 regions.push_back(workRegion);
1435
1436                                 levelOffset += mipLevelStorageSizes[mipLevel];
1437                         }
1438
1439                         vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, static_cast<deUint32>(regions.size()), &regions[0]);
1440                 }
1441                 {
1442                         const VkBufferMemoryBarrier     bufferBarriers[] =
1443                         {
1444                                 {
1445                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
1446                                         DE_NULL,                                                                        // const void*        pNext;
1447                                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
1448                                         VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
1449                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
1450                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
1451                                         *colorBuffer,                                                           // VkBuffer           buffer;
1452                                         0ull,                                                                           // VkDeviceSize       offset;
1453                                         VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
1454                                 },
1455                         };
1456
1457                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1458                                                                         0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1459                 }
1460
1461                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1462                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1463         }
1464
1465         // Verify results (per mip level)
1466         {
1467                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1468
1469                 const tcu::TextureFormat                        format                  = mapVkFormat(caseDef.colorFormat);
1470
1471                 VkDeviceSize                                            levelOffset             = 0ull;
1472                 bool                                                            allOk                   = true;
1473
1474                 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1475                 {
1476                         const IVec4&                                            mipSize                 = mipLevelSizes[mipLevel];
1477                         const void*     const                                   pLevelData              = static_cast<const deUint8*>(colorBufferAlloc->getHostPtr()) + levelOffset;
1478                         const int                                                       levelDepth              = maxLayersOrDepth(mipSize);
1479                         const tcu::ConstPixelBufferAccess       resultImage             (format, mipSize.x(), mipSize.y(), levelDepth, pLevelData);
1480                         tcu::TextureLevel                                       textureLevel    (format, mipSize.x(), mipSize.y(), levelDepth);
1481                         const tcu::PixelBufferAccess            expectedImage   = textureLevel.getAccess();
1482                         const std::string                                       comparisonName  = "Mip level " + de::toString(mipLevel);
1483                         bool                                                            ok                              = false;
1484
1485                         generateExpectedImage(expectedImage, mipSize.swizzle(0, 1), 0);
1486
1487                         if (isFloatFormat(caseDef.colorFormat))
1488                                 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1489                         else
1490                                 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT);
1491
1492                         allOk           =  allOk && ok; // keep testing all levels, even if we know it's a fail overall
1493                         levelOffset += mipLevelStorageSizes[mipLevel];
1494                 }
1495
1496                 return allOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1497         }
1498 }
1499
1500 std::string getSizeDescription (const IVec4& size)
1501 {
1502         std::ostringstream str;
1503
1504         const char* const description[4] =
1505         {
1506                 "width", "height", "depth", "layers"
1507         };
1508
1509         int numMaxComponents = 0;
1510
1511         for (int i = 0; i < 4; ++i)
1512         {
1513                 if (size[i] == MAX_SIZE)
1514                 {
1515                         if (numMaxComponents > 0)
1516                                 str << "_";
1517
1518                         str << description[i];
1519                         ++numMaxComponents;
1520                 }
1521         }
1522
1523         if (numMaxComponents == 0)
1524                 str << "small";
1525
1526         return str.str();
1527 }
1528
1529 inline std::string getFormatString (const VkFormat format)
1530 {
1531         std::string name(getFormatName(format));
1532         return de::toLower(name.substr(10));
1533 }
1534
1535 std::string getFormatString (const VkFormat colorFormat, const VkFormat depthStencilFormat)
1536 {
1537         std::ostringstream str;
1538         str << getFormatString(colorFormat);
1539         if (depthStencilFormat != VK_FORMAT_UNDEFINED)
1540                 str << "_" << getFormatString(depthStencilFormat);
1541         return str.str();
1542 }
1543
1544 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1545 {
1546         std::string s(getImageViewTypeName(imageViewType));
1547         return de::toLower(s.substr(19));
1548 }
1549
1550 inline BVec4 bvecFromMask (deUint32 mask)
1551 {
1552         return BVec4((mask >> 0) & 1,
1553                                  (mask >> 1) & 1,
1554                                  (mask >> 2) & 1,
1555                                  (mask >> 3) & 1);
1556 }
1557
1558 vector<IVec4> genSizeCombinations (const IVec4& baselineSize, const deUint32 sizeMask, const VkImageViewType imageViewType)
1559 {
1560         vector<IVec4>           sizes;
1561         std::set<deUint32>      masks;
1562
1563         for (deUint32 i = 0; i < (1u << 4); ++i)
1564         {
1565                 // Cube images have square faces
1566                 if (isCube(imageViewType) && ((i & MASK_WH) != 0))
1567                         i |= MASK_WH;
1568
1569                 masks.insert(i & sizeMask);
1570         }
1571
1572         for (std::set<deUint32>::const_iterator it = masks.begin(); it != masks.end(); ++it)
1573                 sizes.push_back(tcu::select(IVec4(MAX_SIZE), baselineSize, bvecFromMask(*it)));
1574
1575         return sizes;
1576 }
1577
1578 void addTestCasesWithFunctions (tcu::TestCaseGroup* group)
1579 {
1580         const struct
1581         {
1582                 VkImageViewType         viewType;
1583                 IVec4                           baselineSize;   //!< image size: (dimX, dimY, dimZ, arraySize)
1584                 deUint32                        sizeMask;               //!< if a dimension is masked, generate a huge size case for it
1585         } testCase[] =
1586         {
1587                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec4(54,  1, 1,   1),  MASK_W                  },
1588                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec4(54,  1, 1,   4),  MASK_W_LAYERS   },
1589                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec4(44, 23, 1,   1),  MASK_WH                 },
1590                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec4(44, 23, 1,   4),  MASK_WH_LAYERS  },
1591                 { VK_IMAGE_VIEW_TYPE_3D,                        IVec4(22, 31, 7,   1),  MASK_WHD                },
1592                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec4(35, 35, 1,   6),  MASK_WH                 },
1593                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec4(35, 35, 1, 2*6),  MASK_WH_LAYERS  },
1594         };
1595
1596         const VkFormat format[] =
1597         {
1598                 VK_FORMAT_R8G8B8A8_UNORM,
1599                 VK_FORMAT_R32_UINT,
1600                 VK_FORMAT_R16G16_SINT,
1601                 VK_FORMAT_R32G32B32A32_SFLOAT,
1602         };
1603
1604         const VkFormat depthStencilFormat[] =
1605         {
1606                 VK_FORMAT_UNDEFINED,                    // don't use a depth/stencil attachment
1607                 VK_FORMAT_D16_UNORM,
1608                 VK_FORMAT_S8_UINT,
1609                 VK_FORMAT_D24_UNORM_S8_UINT,    // one of the following mixed formats must be supported
1610                 VK_FORMAT_D32_SFLOAT_S8_UINT,
1611         };
1612
1613         for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCase); ++caseNdx)
1614         {
1615                 MovePtr<tcu::TestCaseGroup>     imageGroup(new tcu::TestCaseGroup(group->getTestContext(), getShortImageViewTypeName(testCase[caseNdx].viewType).c_str(), ""));
1616
1617                 // Generate attachment size cases
1618                 {
1619                         const vector<IVec4> sizes = genSizeCombinations(testCase[caseNdx].baselineSize, testCase[caseNdx].sizeMask, testCase[caseNdx].viewType);
1620
1621                         MovePtr<tcu::TestCaseGroup>     smallGroup(new tcu::TestCaseGroup(group->getTestContext(), "small", ""));
1622                         MovePtr<tcu::TestCaseGroup>     hugeGroup (new tcu::TestCaseGroup(group->getTestContext(), "huge",  ""));
1623
1624                         imageGroup->addChild(smallGroup.get());
1625                         imageGroup->addChild(hugeGroup.get());
1626
1627                         for (vector<IVec4>::const_iterator sizeIter = sizes.begin(); sizeIter != sizes.end(); ++sizeIter)
1628                         {
1629                                 // The first size is the baseline size, put it in a dedicated group
1630                                 if (sizeIter == sizes.begin())
1631                                 {
1632                                         for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1633                                         for (int formatNdx   = 0; formatNdx   < DE_LENGTH_OF_ARRAY(format);             ++formatNdx)
1634                                         {
1635                                                 const CaseDef caseDef =
1636                                                 {
1637                                                         testCase[caseNdx].viewType,                     // VkImageViewType      imageType;
1638                                                         *sizeIter,                                                      // IVec4                        imageSizeHint;
1639                                                         format[formatNdx],                                      // VkFormat                     colorFormat;
1640                                                         depthStencilFormat[dsFormatNdx],        // VkFormat                     depthStencilFormat;
1641                                                 };
1642                                                 addFunctionCaseWithPrograms(smallGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef);
1643                                         }
1644                                 }
1645                                 else // All huge cases go into a separate group
1646                                 {
1647                                         MovePtr<tcu::TestCaseGroup>     sizeGroup       (new tcu::TestCaseGroup(group->getTestContext(), getSizeDescription(*sizeIter).c_str(), ""));
1648                                         const VkFormat                          colorFormat     = VK_FORMAT_R8G8B8A8_UNORM;
1649
1650                                         // Use the same color format for all cases, to reduce the number of permutations
1651                                         for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1652                                         {
1653                                                 const CaseDef caseDef =
1654                                                 {
1655                                                         testCase[caseNdx].viewType,                     // VkImageViewType      viewType;
1656                                                         *sizeIter,                                                      // IVec4                        imageSizeHint;
1657                                                         colorFormat,                                            // VkFormat                     colorFormat;
1658                                                         depthStencilFormat[dsFormatNdx],        // VkFormat                     depthStencilFormat;
1659                                                 };
1660                                                 addFunctionCaseWithPrograms(sizeGroup.get(), getFormatString(colorFormat, depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef);
1661                                         }
1662                                         hugeGroup->addChild(sizeGroup.release());
1663                                 }
1664                         }
1665                         smallGroup.release();
1666                         hugeGroup.release();
1667                 }
1668
1669                 // Generate mip map cases
1670                 {
1671                         MovePtr<tcu::TestCaseGroup>     mipmapGroup(new tcu::TestCaseGroup(group->getTestContext(), "mipmap", ""));
1672
1673                         for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1674                         for (int formatNdx   = 0; formatNdx   < DE_LENGTH_OF_ARRAY(format);             ++formatNdx)
1675                         {
1676                                 const CaseDef caseDef =
1677                                 {
1678                                         testCase[caseNdx].viewType,                     // VkImageViewType      imageType;
1679                                         testCase[caseNdx].baselineSize,         // IVec4                        imageSizeHint;
1680                                         format[formatNdx],                                      // VkFormat                     colorFormat;
1681                                         depthStencilFormat[dsFormatNdx],        // VkFormat                     depthStencilFormat;
1682                                 };
1683                                 addFunctionCaseWithPrograms(mipmapGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testRenderToMipMaps, caseDef);
1684                         }
1685                         imageGroup->addChild(mipmapGroup.release());
1686                 }
1687
1688                 group->addChild(imageGroup.release());
1689         }
1690 }
1691
1692 } // anonymous ns
1693
1694 tcu::TestCaseGroup* createRenderToImageTests (tcu::TestContext& testCtx)
1695 {
1696         return createTestGroup(testCtx, "render_to_image", "Render to image tests", addTestCasesWithFunctions);
1697 }
1698
1699 } // pipeline
1700 } // vkt