5f389eb2e0c47064af5a70622a809a11707aa8c3
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineRenderToImageTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 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
42 #include "deUniquePtr.hpp"
43 #include "deSharedPtr.hpp"
44
45 #include <string>
46 #include <vector>
47
48 namespace vkt
49 {
50 namespace pipeline
51 {
52 namespace
53 {
54 using namespace vk;
55 using de::UniquePtr;
56 using de::MovePtr;
57 using de::SharedPtr;
58 using tcu::IVec3;
59 using tcu::Vec4;
60 using tcu::UVec4;
61 using tcu::IVec4;
62 using std::vector;
63
64 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView;
65 typedef SharedPtr<Unique<VkPipeline> >  SharedPtrVkPipeline;
66
67 enum Constants
68 {
69         REFERENCE_COLOR_VALUE = 125
70 };
71
72 struct CaseDef
73 {
74         VkImageViewType imageType;
75         IVec3                   renderSize;
76         int                             numLayers;
77         VkFormat                colorFormat;
78 };
79
80 template<typename T>
81 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
82 {
83         return SharedPtr<Unique<T> >(new Unique<T>(move));
84 }
85
86 template<typename T>
87 inline VkDeviceSize sizeInBytes (const vector<T>& vec)
88 {
89         return vec.size() * sizeof(vec[0]);
90 }
91
92 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
93                                                                            const VkDevice                               device,
94                                                                            const VkPipelineLayout               pipelineLayout,
95                                                                            const VkRenderPass                   renderPass,
96                                                                            const VkShaderModule                 vertexModule,
97                                                                            const VkShaderModule                 fragmentModule,
98                                                                            const IVec3                                  renderSize,
99                                                                            const VkPrimitiveTopology    topology,
100                                                                            const deUint32                               subpass)
101 {
102         const VkVertexInputBindingDescription vertexInputBindingDescription =
103         {
104                 0u,                                                             // uint32_t                             binding;
105                 sizeof(Vertex4RGBA),                    // uint32_t                             stride;
106                 VK_VERTEX_INPUT_RATE_VERTEX,    // VkVertexInputRate    inputRate;
107         };
108
109         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
110         {
111                 {
112                         0u,                                                             // uint32_t                     location;
113                         0u,                                                             // uint32_t                     binding;
114                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat                     format;
115                         0u,                                                             // uint32_t                     offset;
116                 },
117                 {
118                         1u,                                                             // uint32_t                     location;
119                         0u,                                                             // uint32_t                     binding;
120                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat                     format;
121                         sizeof(Vec4),                                   // uint32_t                     offset;
122                 }
123         };
124
125         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
126         {
127                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
128                 DE_NULL,                                                                                                        // const void*                                                          pNext;
129                 (VkPipelineVertexInputStateCreateFlags)0,                                       // VkPipelineVertexInputStateCreateFlags        flags;
130                 1u,                                                                                                                     // uint32_t                                                                     vertexBindingDescriptionCount;
131                 &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
132                 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),           // uint32_t                                                                     vertexAttributeDescriptionCount;
133                 vertexInputAttributeDescriptions,                                                       // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
134         };
135
136         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
137         {
138                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
139                 DE_NULL,                                                                                                                // const void*                                                          pNext;
140                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags      flags;
141                 topology,                                                                                                               // VkPrimitiveTopology                                          topology;
142                 VK_FALSE,                                                                                                               // VkBool32                                                                     primitiveRestartEnable;
143         };
144
145         const VkViewport viewport = makeViewport(
146                 0.0f, 0.0f,
147                 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
148                 0.0f, 1.0f);
149
150         const VkRect2D scissor =
151         {
152                 makeOffset2D(0, 0),
153                 makeExtent2D(renderSize.x(), renderSize.y()),
154         };
155
156         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
157         {
158                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                                              sType;
159                 DE_NULL,                                                                                                // const void*                                                  pNext;
160                 (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags   flags;
161                 1u,                                                                                                             // uint32_t                                                             viewportCount;
162                 &viewport,                                                                                              // const VkViewport*                                    pViewports;
163                 1u,                                                                                                             // uint32_t                                                             scissorCount;
164                 &scissor,                                                                                               // const VkRect2D*                                              pScissors;
165         };
166
167         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
168         {
169                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
170                 DE_NULL,                                                                                                        // const void*                                                          pNext;
171                 (VkPipelineRasterizationStateCreateFlags)0,                                     // VkPipelineRasterizationStateCreateFlags      flags;
172                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthClampEnable;
173                 VK_FALSE,                                                                                                       // VkBool32                                                                     rasterizerDiscardEnable;
174                 VK_POLYGON_MODE_FILL,                                                                           // VkPolygonMode                                                        polygonMode;
175                 VK_CULL_MODE_NONE,                                                                                      // VkCullModeFlags                                                      cullMode;
176                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
177                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable;
178                 0.0f,                                                                                                           // float                                                                        depthBiasConstantFactor;
179                 0.0f,                                                                                                           // float                                                                        depthBiasClamp;
180                 0.0f,                                                                                                           // float                                                                        depthBiasSlopeFactor;
181                 1.0f,                                                                                                           // float                                                                        lineWidth;
182         };
183
184         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
185         {
186                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
187                 DE_NULL,                                                                                                        // const void*                                                          pNext;
188                 (VkPipelineMultisampleStateCreateFlags)0,                                       // VkPipelineMultisampleStateCreateFlags        flags;
189                 VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
190                 VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
191                 0.0f,                                                                                                           // float                                                                        minSampleShading;
192                 DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
193                 VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
194                 VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
195         };
196
197         const VkStencilOpState stencilOpState = makeStencilOpState(
198                 VK_STENCIL_OP_KEEP,             // stencil fail
199                 VK_STENCIL_OP_KEEP,             // depth & stencil pass
200                 VK_STENCIL_OP_KEEP,             // depth only fail
201                 VK_COMPARE_OP_ALWAYS,   // compare op
202                 0u,                                             // compare mask
203                 0u,                                             // write mask
204                 0u);                                    // reference
205
206         VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
207         {
208                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
209                 DE_NULL,                                                                                                        // const void*                                                          pNext;
210                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
211                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthTestEnable;
212                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthWriteEnable;
213                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
214                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
215                 VK_FALSE,                                                                                                       // VkBool32                                                                     stencilTestEnable;
216                 stencilOpState,                                                                                         // VkStencilOpState                                                     front;
217                 stencilOpState,                                                                                         // VkStencilOpState                                                     back;
218                 0.0f,                                                                                                           // float                                                                        minDepthBounds;
219                 1.0f,                                                                                                           // float                                                                        maxDepthBounds;
220         };
221
222         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
223         // Number of blend attachments must equal the number of color attachments during any subpass.
224         const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
225         {
226                 VK_FALSE,                               // VkBool32                                     blendEnable;
227                 VK_BLEND_FACTOR_ONE,    // VkBlendFactor                        srcColorBlendFactor;
228                 VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        dstColorBlendFactor;
229                 VK_BLEND_OP_ADD,                // VkBlendOp                            colorBlendOp;
230                 VK_BLEND_FACTOR_ONE,    // VkBlendFactor                        srcAlphaBlendFactor;
231                 VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        dstAlphaBlendFactor;
232                 VK_BLEND_OP_ADD,                // VkBlendOp                            alphaBlendOp;
233                 colorComponentsAll,             // VkColorComponentFlags        colorWriteMask;
234         };
235
236         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
237         {
238                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
239                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
240                 (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
241                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
242                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
243                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
244                 &pipelineColorBlendAttachmentState,                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
245                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
246         };
247
248         const VkPipelineShaderStageCreateInfo pShaderStages[] =
249         {
250                 {
251                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
252                         DE_NULL,                                                                                                // const void*                                                  pNext;
253                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
254                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // VkShaderStageFlagBits                                stage;
255                         vertexModule,                                                                                   // VkShaderModule                                               module;
256                         "main",                                                                                                 // const char*                                                  pName;
257                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
258                 },
259                 {
260                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
261                         DE_NULL,                                                                                                // const void*                                                  pNext;
262                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
263                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // VkShaderStageFlagBits                                stage;
264                         fragmentModule,                                                                                 // VkShaderModule                                               module;
265                         "main",                                                                                                 // const char*                                                  pName;
266                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
267                 }
268         };
269
270         const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
271         {
272                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
273                 DE_NULL,                                                                                        // const void*                                                                          pNext;
274                 (VkPipelineCreateFlags)0,                                                       // VkPipelineCreateFlags                                                        flags;
275                 DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
276                 pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
277                 &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
278                 &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
279                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
280                 &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
281                 &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
282                 &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
283                 &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
284                 &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
285                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
286                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
287                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
288                 subpass,                                                                                        // deUint32                                                                                     subpass;
289                 DE_NULL,                                                                                        // VkPipeline                                                                           basePipelineHandle;
290                 0,                                                                                                      // deInt32                                                                                      basePipelineIndex;
291         };
292
293         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
294 }
295
296 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
297 Move<VkRenderPass> makeRenderPass (const DeviceInterface&               vk,
298                                                                    const VkDevice                               device,
299                                                                    const VkFormat                               colorFormat,
300                                                                    const deUint32                               numLayers)
301 {
302         const VkAttachmentDescription colorAttachmentDescription =
303         {
304                 (VkAttachmentDescriptionFlags)0,                        // VkAttachmentDescriptionFlags         flags;
305                 colorFormat,                                                            // VkFormat                                                     format;
306                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits                        samples;
307                 VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp                           loadOp;
308                 VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                          storeOp;
309                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                           stencilLoadOp;
310                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                          stencilStoreOp;
311                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                                        initialLayout;
312                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        finalLayout;
313         };
314         const vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
315
316         // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
317         vector<VkAttachmentReference>   colorAttachmentReferences(numLayers);
318         vector<VkSubpassDescription>    subpasses;
319
320         for (deUint32 i = 0; i < numLayers; ++i)
321         {
322                 const VkAttachmentReference attachmentRef =
323                 {
324                         i,                                                                                              // deUint32                     attachment;
325                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                // VkImageLayout        layout;
326                 };
327                 colorAttachmentReferences[i] = attachmentRef;
328
329                 const VkSubpassDescription subpassDescription =
330                 {
331                         (VkSubpassDescriptionFlags)0,           // VkSubpassDescriptionFlags            flags;
332                         VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint                          pipelineBindPoint;
333                         0u,                                                                     // deUint32                                                     inputAttachmentCount;
334                         DE_NULL,                                                        // const VkAttachmentReference*         pInputAttachments;
335                         1u,                                                                     // deUint32                                                     colorAttachmentCount;
336                         &colorAttachmentReferences[i],          // const VkAttachmentReference*         pColorAttachments;
337                         DE_NULL,                                                        // const VkAttachmentReference*         pResolveAttachments;
338                         DE_NULL,                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
339                         0u,                                                                     // deUint32                                                     preserveAttachmentCount;
340                         DE_NULL                                                         // const deUint32*                                      pPreserveAttachments;
341                 };
342                 subpasses.push_back(subpassDescription);
343         }
344
345         const VkRenderPassCreateInfo renderPassInfo =
346         {
347                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                                      sType;
348                 DE_NULL,                                                                                                // const void*                                          pNext;
349                 (VkRenderPassCreateFlags)0,                                                             // VkRenderPassCreateFlags                      flags;
350                 static_cast<deUint32>(attachmentDescriptions.size()),   // deUint32                                                     attachmentCount;
351                 &attachmentDescriptions[0],                                                             // const VkAttachmentDescription*       pAttachments;
352                 static_cast<deUint32>(subpasses.size()),                                // deUint32                                                     subpassCount;
353                 &subpasses[0],                                                                                  // const VkSubpassDescription*          pSubpasses;
354                 0u,                                                                                                             // deUint32                                                     dependencyCount;
355                 DE_NULL                                                                                                 // const VkSubpassDependency*           pDependencies;
356         };
357
358         return createRenderPass(vk, device, &renderPassInfo);
359 }
360
361 Move<VkImage> makeImage (const DeviceInterface&         vk,
362                                                  const VkDevice                         device,
363                                                  VkImageCreateFlags                     flags,
364                                                  VkImageType                            imageType,
365                                                  const VkFormat                         format,
366                                                  const IVec3&                           size,
367                                                  const deUint32                         numLayers,
368                                                  const VkImageUsageFlags        usage)
369 {
370         const VkImageCreateInfo imageParams =
371         {
372                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    // VkStructureType                      sType;
373                 DE_NULL,                                                                // const void*                          pNext;
374                 flags,                                                                  // VkImageCreateFlags           flags;
375                 imageType,                                                              // VkImageType                          imageType;
376                 format,                                                                 // VkFormat                                     format;
377                 makeExtent3D(size),                                             // VkExtent3D                           extent;
378                 1u,                                                                             // deUint32                                     mipLevels;
379                 numLayers,                                                              // deUint32                                     arrayLayers;
380                 VK_SAMPLE_COUNT_1_BIT,                                  // VkSampleCountFlagBits        samples;
381                 VK_IMAGE_TILING_OPTIMAL,                                // VkImageTiling                        tiling;
382                 usage,                                                                  // VkImageUsageFlags            usage;
383                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                        sharingMode;
384                 0u,                                                                             // deUint32                                     queueFamilyIndexCount;
385                 DE_NULL,                                                                // const deUint32*                      pQueueFamilyIndices;
386                 VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        initialLayout;
387         };
388         return createImage(vk, device, &imageParams);
389 }
390
391 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
392 {
393         const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
394         return createBuffer(vk, device, &bufferCreateInfo);
395 }
396
397 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
398 {
399         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
400 }
401
402 //! Get a reference clear value based on color format.
403 VkClearValue getClearValue (const VkFormat format)
404 {
405         if (isUintFormat(format) || isIntFormat(format))
406                 return makeClearValueColorU32(REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE);
407         else
408                 return makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
409 }
410
411 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
412 {
413         std::ostringstream str;
414         if (numComponents == 1)
415                 str << (isUint ? "uint" : isSint ? "int" : "float");
416         else
417                 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
418
419         return str.str();
420 }
421
422 //! A half-viewport quad. Use with TRIANGLE_STRIP topology.
423 vector<Vertex4RGBA> genFullQuadVertices (const int subpassCount, const vector<Vec4>& color)
424 {
425         vector<Vertex4RGBA>     vectorData;
426         for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
427         {
428                 Vertex4RGBA data =
429                 {
430                         Vec4(0.0f, -1.0f, 0.0f, 1.0f),
431                         color[subpassNdx % color.size()],
432                 };
433                 vectorData.push_back(data);
434                 data.position   = Vec4(0.0f,  1.0f, 0.0f, 1.0f);
435                 vectorData.push_back(data);
436                 data.position   = Vec4(1.0f, -1.0f, 0.0f, 1.0f);
437                 vectorData.push_back(data);
438                 data.position   = Vec4(1.0f,  1.0f, 0.0f, 1.0f);
439                 vectorData.push_back(data);
440         }
441         return vectorData;
442 }
443
444 VkImageType getImageType (const VkImageViewType viewType)
445 {
446         switch (viewType)
447         {
448         case VK_IMAGE_VIEW_TYPE_1D:
449         case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
450                 return VK_IMAGE_TYPE_1D;
451
452         case VK_IMAGE_VIEW_TYPE_2D:
453         case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
454         case VK_IMAGE_VIEW_TYPE_CUBE:
455         case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
456                 return VK_IMAGE_TYPE_2D;
457
458         case VK_IMAGE_VIEW_TYPE_3D:
459                 return VK_IMAGE_TYPE_3D;
460
461         default:
462                 DE_ASSERT(0);
463                 return VK_IMAGE_TYPE_LAST;
464         }
465 }
466
467 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
468 {
469         const int       numComponents   = getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
470         const bool      isUint                  = isUintFormat(caseDef.colorFormat);
471         const bool      isSint                  = isIntFormat(caseDef.colorFormat);
472
473         // Vertex shader
474         {
475                 std::ostringstream src;
476                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
477                         << "\n"
478                         << "layout(location = 0) in  vec4 in_position;\n"
479                         << "layout(location = 1) in  vec4 in_color;\n"
480                         << "layout(location = 0) out vec4 out_color;\n"
481                         << "\n"
482                         << "out gl_PerVertex {\n"
483                         << "    vec4 gl_Position;\n"
484                         << "};\n"
485                         << "\n"
486                         << "void main(void)\n"
487                         << "{\n"
488                         << "    gl_Position     = in_position;\n"
489                         << "    out_color       = in_color;\n"
490                         << "}\n";
491
492                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
493         }
494
495         // Fragment shader
496         {
497                 std::ostringstream colorValue;
498                 colorValue << REFERENCE_COLOR_VALUE;
499                 const std::string colorFormat   = getColorFormatStr(numComponents, isUint, isSint);
500                 const std::string colorInteger  = (isUint || isSint ? " * "+colorFormat+"("+colorValue.str()+")" :"");
501
502                 std::ostringstream src;
503                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
504                         << "\n"
505                         << "layout(location = 0) in  vec4 in_color;\n"
506                         << "layout(location = 0) out " << colorFormat << " o_color;\n"
507                         << "\n"
508                         << "void main(void)\n"
509                         << "{\n"
510                         << "    o_color = " << colorFormat << "("
511                         << (numComponents == 1 ? "in_color.r"   :
512                                 numComponents == 2 ? "in_color.rg"  :
513                                 numComponents == 3 ? "in_color.rgb" : "in_color")
514                         << colorInteger
515                         << ");\n"
516                         << "}\n";
517
518                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
519         }
520 }
521
522 tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef, const Vec4* color, const int sizeColor)
523 {
524         const bool                                              isInt                   = isUintFormat(caseDef.colorFormat) || isIntFormat(caseDef.colorFormat);
525         const tcu::PixelBufferAccess    expectedImage   (textureLevel);
526
527         if (isInt)
528                 tcu::clear(expectedImage, tcu::IVec4(REFERENCE_COLOR_VALUE));
529         else
530                 tcu::clear(expectedImage, tcu::Vec4(1.0));
531
532         for (int z = 0; z < expectedImage.getDepth(); ++z)
533         {
534                 const Vec4& setColor    = color[z % sizeColor];
535                 const IVec4 setColorInt = (static_cast<float>(REFERENCE_COLOR_VALUE) * setColor).cast<deInt32>();
536
537                 for (int y = 0;                                                 y < caseDef.renderSize.y(); ++y)
538                 for (int x = caseDef.renderSize.x()/2;  x < caseDef.renderSize.x(); ++x)
539                 {
540                         if (isInt)
541                                 expectedImage.setPixel(setColorInt, x, y, z);
542                         else
543                                 expectedImage.setPixel(setColor, x, y, z);
544                 }
545         }
546         return expectedImage;
547 }
548
549 tcu::TestStatus test (Context& context, const CaseDef caseDef)
550 {
551         if (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType &&
552                 (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1")))
553                 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
554
555         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
556         const VkDevice                                  device                          = context.getDevice();
557         const VkQueue                                   queue                           = context.getUniversalQueue();
558         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
559         Allocator&                                              allocator                       = context.getDefaultAllocator();
560         Move<VkImage>                                   colorImage;
561         MovePtr<Allocation>                             colorImageAlloc;
562         const Vec4                                              color[]                         =
563         {
564                 Vec4(0.9f, 0.0f, 0.0f, 1.0f),
565                 Vec4(0.6f, 1.0f, 0.0f, 1.0f),
566                 Vec4(0.3f, 0.0f, 1.0f, 1.0f),
567                 Vec4(0.1f, 0.0f, 1.0f, 1.0f)
568         };
569
570         const int                                               numLayers                       = (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? caseDef.renderSize.z() : caseDef.numLayers);
571         const VkDeviceSize                              colorBufferSize         = caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.renderSize.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
572         const Unique<VkBuffer>                  colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
573         const UniquePtr<Allocation>             colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
574
575         const Unique<VkShaderModule>    vertexModule            (createShaderModule                     (vk, device, context.getBinaryCollection().get("vert"), 0u));
576         const Unique<VkShaderModule>    fragmentModule          (createShaderModule                     (vk, device, context.getBinaryCollection().get("frag"), 0u));
577         const Unique<VkRenderPass>              renderPass                      (makeRenderPass                         (vk, device, caseDef.colorFormat, static_cast<deUint32>(numLayers)));
578         const Unique<VkPipelineLayout>  pipelineLayout          (makePipelineLayout                     (vk, device));
579         vector<SharedPtrVkPipeline>             pipeline;
580         const Unique<VkCommandPool>             cmdPool                         (makeCommandPool  (vk, device, queueFamilyIndex));
581         const Unique<VkCommandBuffer>   cmdBuffer                       (makeCommandBuffer(vk, device, *cmdPool));
582
583         vector<SharedPtrVkImageView>    colorAttachments;
584         vector<VkImageView>                             attachmentHandles;
585         Move<VkBuffer>                                  vertexBuffer;
586         MovePtr<Allocation>                             vertexBufferAlloc;
587         Move<VkFramebuffer>                             framebuffer;
588
589         //create colorImage
590         {
591                 const VkImageViewCreateFlags    flags                   = (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? (VkImageViewCreateFlags)VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageViewCreateFlags)0);
592                 const VkImageUsageFlags                 colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
593                 colorImage = makeImage(vk, device, flags, getImageType(caseDef.imageType), caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, colorImageUsage);
594                 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
595         }
596
597         //create vertexBuffer
598         {
599                 const vector<Vertex4RGBA>       vertices                        = genFullQuadVertices(numLayers, vector<Vec4>(color, color + DE_LENGTH_OF_ARRAY(color)));
600                 const VkDeviceSize                      vertexBufferSize        = sizeInBytes(vertices);
601
602                 vertexBuffer            = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
603                 vertexBufferAlloc       = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
604                 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
605                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
606         }
607
608         //create attachmentHandles and pipelines
609         for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
610         {
611                 const VkImageViewType   imageType = (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY :
612                                                                                         (VK_IMAGE_VIEW_TYPE_CUBE == caseDef.imageType || VK_IMAGE_VIEW_TYPE_CUBE_ARRAY == caseDef.imageType ? VK_IMAGE_VIEW_TYPE_2D :
613                                                                                         caseDef.imageType));
614
615                 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, *colorImage, imageType, caseDef.colorFormat, makeColorSubresourceRange(layerNdx, 1))));
616                 attachmentHandles.push_back(**colorAttachments.back());
617
618                 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
619                                                                                                                           caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, static_cast<deUint32>(layerNdx))));
620         }
621
622         framebuffer = makeFramebuffer(vk, device, *renderPass, numLayers, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
623
624         beginCommandBuffer(vk, *cmdBuffer);
625         {
626                 const vector<VkClearValue>      clearValues                     (numLayers, getClearValue(caseDef.colorFormat));
627                 const VkRect2D                          renderArea                      =
628                 {
629                         makeOffset2D(0, 0),
630                         makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
631                 };
632                 const VkRenderPassBeginInfo     renderPassBeginInfo     =
633                 {
634                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
635                         DE_NULL,                                                                        // const void*             pNext;
636                         *renderPass,                                                            // VkRenderPass            renderPass;
637                         *framebuffer,                                                           // VkFramebuffer           framebuffer;
638                         renderArea,                                                                     // VkRect2D                renderArea;
639                         static_cast<deUint32>(clearValues.size()),      // uint32_t                clearValueCount;
640                         &clearValues[0],                                                        // const VkClearValue*     pClearValues;
641                 };
642                 const VkDeviceSize                      vertexBufferOffset      = 0ull;
643
644                 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
645                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
646         }
647
648         //cmdDraw
649         for (deUint32 layerNdx = 0; layerNdx < static_cast<deUint32>(numLayers); ++layerNdx)
650         {
651                 if (layerNdx != 0)
652                         vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
653
654                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
655                 vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
656         }
657
658         vk.cmdEndRenderPass(*cmdBuffer);
659
660         // copy colorImage -> host visible colorBuffer
661         {
662                 const VkImageMemoryBarrier      imageBarriers[] =
663                 {
664                         {
665                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
666                                 DE_NULL,                                                                                // const void*                          pNext;
667                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        outputMask;
668                                 VK_ACCESS_TRANSFER_READ_BIT,                                    // VkAccessFlags                        inputMask;
669                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                        oldLayout;
670                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                   // VkImageLayout                        newLayout;
671                                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
672                                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
673                                 *colorImage,                                                                    // VkImage                                      image;
674                                 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange      subresourceRange;
675                         }
676                 };
677
678                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
679                                                           0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
680
681                 const VkBufferImageCopy         region                  =
682                 {
683                         0ull,                                                                                                                                                           // VkDeviceSize                bufferOffset;
684                         0u,                                                                                                                                                                     // uint32_t                    bufferRowLength;
685                         0u,                                                                                                                                                                     // uint32_t                    bufferImageHeight;
686                         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers),       // VkImageSubresourceLayers    imageSubresource;
687                         makeOffset3D(0, 0, 0),                                                                                                                          // VkOffset3D                  imageOffset;
688                         makeExtent3D(caseDef.renderSize),                                                                                                       // VkExtent3D                  imageExtent;
689                 };
690
691                 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
692
693                 const VkBufferMemoryBarrier     bufferBarriers[] =
694                 {
695                         {
696                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
697                                 DE_NULL,                                                                        // const void*        pNext;
698                                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
699                                 VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
700                                 VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
701                                 VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
702                                 *colorBuffer,                                                           // VkBuffer           buffer;
703                                 0ull,                                                                           // VkDeviceSize       offset;
704                                 VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
705                         },
706                 };
707
708                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
709                                                           0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
710         }
711
712         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
713         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
714
715         // Verify results
716         {
717                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
718
719                 const tcu::TextureFormat                        format                  = mapVkFormat(caseDef.colorFormat);
720                 const int                                                       depth                   = deMax32(caseDef.renderSize.z(), caseDef.numLayers);
721                 tcu::TextureLevel                                       textureLevel    (format, caseDef.renderSize.x(), caseDef.renderSize.y(), depth);
722                 const tcu::PixelBufferAccess            expectedImage   = getExpectedData (textureLevel, caseDef, color, DE_LENGTH_OF_ARRAY(color));
723                 const tcu::ConstPixelBufferAccess       resultImage             (format, caseDef.renderSize.x(), caseDef.renderSize.y(), depth, colorBufferAlloc->getHostPtr());
724
725                 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT))
726                         return tcu::TestStatus::fail("Fail");
727         }
728         return tcu::TestStatus::pass("Pass");
729 }
730
731 std::string getSizeString (const IVec3& size, const int numLayer)
732 {
733         std::ostringstream str;
734                                                         str <<            size.x();
735         if (size.y() > 1)               str << "x" << size.y();
736         if (size.z() > 1)               str << "x" << size.z();
737         if (numLayer > 1)               str << "_" << numLayer;
738
739         return str.str();
740 }
741
742 std::string getFormatString (const VkFormat format)
743 {
744         std::string name(getFormatName(format));
745         return de::toLower(name.substr(10));
746 }
747
748 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
749 {
750         std::string s(getImageViewTypeName(imageViewType));
751         return de::toLower(s.substr(19));
752 }
753
754 CaseDef caseDefWithFormat (CaseDef caseDef, const VkFormat format)
755 {
756         caseDef.colorFormat = format;
757         return caseDef;
758 }
759
760 void addTestCasesWithFunctions (tcu::TestCaseGroup* group)
761 {
762         const CaseDef caseDef[] =
763         {
764                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(54,  1, 1),       1,              VK_FORMAT_UNDEFINED},
765                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(54,  1, 1),       4,              VK_FORMAT_UNDEFINED},
766                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(22, 64, 1),       1,              VK_FORMAT_UNDEFINED},
767                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(22, 64, 1),       4,              VK_FORMAT_UNDEFINED},
768                 { VK_IMAGE_VIEW_TYPE_3D,                        IVec3(22, 64, 7),       1,              VK_FORMAT_UNDEFINED},
769                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(35, 35, 1),       6,              VK_FORMAT_UNDEFINED},
770                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(35, 35, 1),       2*6,    VK_FORMAT_UNDEFINED},
771         };
772
773         const VkFormat format[] =
774         {
775                 VK_FORMAT_R8G8B8A8_UNORM,
776                 VK_FORMAT_R32_UINT,
777                 VK_FORMAT_R16G16_SINT,
778                 VK_FORMAT_R32G32B32A32_SFLOAT,
779         };
780
781         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
782         {
783                 MovePtr<tcu::TestCaseGroup>     imageGroup(new tcu::TestCaseGroup(group->getTestContext(), getShortImageViewTypeName(caseDef[sizeNdx].imageType).c_str(), ""));
784                 {
785                         MovePtr<tcu::TestCaseGroup>     sizeGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeString(caseDef[sizeNdx].renderSize, caseDef[sizeNdx].numLayers).c_str(), ""));
786
787                         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
788                                 addFunctionCaseWithPrograms(sizeGroup.get(), getFormatString(format[formatNdx]).c_str(), "", initPrograms, test, caseDefWithFormat(caseDef[sizeNdx], format[formatNdx]));
789
790                         imageGroup->addChild(sizeGroup.release());
791                 }
792                 group->addChild(imageGroup.release());
793         }
794 }
795
796 } // anonymous ns
797
798 tcu::TestCaseGroup* createRenderToImageTests (tcu::TestContext& testCtx)
799 {
800         return createTestGroup(testCtx, "render_to_image", "Render to image tests", addTestCasesWithFunctions);
801 }
802
803 } // pipeline
804 } // vkt