84ebb4b36dd0277b4348ea1ae80ee93c6ceef7fe
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / tessellation / vktTessellationUtil.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2014 The Android Open Source Project
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tessellation Utilities
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktTessellationUtil.hpp"
26 #include "vkTypeUtil.hpp"
27 #include "deMath.h"
28
29 namespace vkt
30 {
31 namespace tessellation
32 {
33
34 using namespace vk;
35
36 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize                     bufferSize,
37                                                                                  const VkBufferUsageFlags       usage)
38 {
39         const VkBufferCreateInfo bufferCreateInfo =
40         {
41                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
42                 DE_NULL,                                                                // const void*                  pNext;
43                 (VkBufferCreateFlags)0,                                 // VkBufferCreateFlags  flags;
44                 bufferSize,                                                             // VkDeviceSize                 size;
45                 usage,                                                                  // VkBufferUsageFlags   usage;
46                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
47                 0u,                                                                             // deUint32                             queueFamilyIndexCount;
48                 DE_NULL,                                                                // const deUint32*              pQueueFamilyIndices;
49         };
50         return bufferCreateInfo;
51 }
52
53 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags      srcAccessMask,
54                                                                                            const VkAccessFlags  dstAccessMask,
55                                                                                            const VkBuffer               buffer,
56                                                                                            const VkDeviceSize   offset,
57                                                                                            const VkDeviceSize   bufferSizeBytes)
58 {
59         const VkBufferMemoryBarrier barrier =
60         {
61                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType;
62                 DE_NULL,                                                                        // const void*          pNext;
63                 srcAccessMask,                                                          // VkAccessFlags        srcAccessMask;
64                 dstAccessMask,                                                          // VkAccessFlags        dstAccessMask;
65                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex;
66                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     destQueueFamilyIndex;
67                 buffer,                                                                         // VkBuffer                     buffer;
68                 offset,                                                                         // VkDeviceSize         offset;
69                 bufferSizeBytes,                                                        // VkDeviceSize         size;
70         };
71         return barrier;
72 }
73
74 VkImageMemoryBarrier makeImageMemoryBarrier     (const VkAccessFlags                    srcAccessMask,
75                                                                                          const VkAccessFlags                    dstAccessMask,
76                                                                                          const VkImageLayout                    oldLayout,
77                                                                                          const VkImageLayout                    newLayout,
78                                                                                          const VkImage                                  image,
79                                                                                          const VkImageSubresourceRange  subresourceRange)
80 {
81         const VkImageMemoryBarrier barrier =
82         {
83                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
84                 DE_NULL,                                                                                // const void*                          pNext;
85                 srcAccessMask,                                                                  // VkAccessFlags                        outputMask;
86                 dstAccessMask,                                                                  // VkAccessFlags                        inputMask;
87                 oldLayout,                                                                              // VkImageLayout                        oldLayout;
88                 newLayout,                                                                              // VkImageLayout                        newLayout;
89                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
90                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
91                 image,                                                                                  // VkImage                                      image;
92                 subresourceRange,                                                               // VkImageSubresourceRange      subresourceRange;
93         };
94         return barrier;
95 }
96
97 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
98 {
99         const VkCommandPoolCreateInfo info =
100         {
101                 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,                     // VkStructureType                      sType;
102                 DE_NULL,                                                                                        // const void*                          pNext;
103                 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,        // VkCommandPoolCreateFlags     flags;
104                 queueFamilyIndex,                                                                       // deUint32                                     queueFamilyIndex;
105         };
106         return createCommandPool(vk, device, &info);
107 }
108
109
110 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&                 vk,
111                                                                                  const VkDevice                                 device,
112                                                                                  const VkDescriptorPool                 descriptorPool,
113                                                                                  const VkDescriptorSetLayout    setLayout)
114 {
115         const VkDescriptorSetAllocateInfo info =
116         {
117                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType;
118                 DE_NULL,                                                                                        // const void*                                  pNext;
119                 descriptorPool,                                                                         // VkDescriptorPool                             descriptorPool;
120                 1u,                                                                                                     // deUint32                                             descriptorSetCount;
121                 &setLayout,                                                                                     // const VkDescriptorSetLayout* pSetLayouts;
122         };
123         return allocateDescriptorSet(vk, device, &info);
124 }
125
126 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&               vk,
127                                                                                    const VkDevice                               device,
128                                                                                    const VkDescriptorSetLayout  descriptorSetLayout)
129 {
130         const VkPipelineLayoutCreateInfo info =
131         {
132                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
133                 DE_NULL,                                                                                        // const void*                                  pNext;
134                 (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags  flags;
135                 1u,                                                                                                     // deUint32                                             setLayoutCount;
136                 &descriptorSetLayout,                                                           // const VkDescriptorSetLayout* pSetLayouts;
137                 0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
138                 DE_NULL,                                                                                        // const VkPushConstantRange*   pPushConstantRanges;
139         };
140         return createPipelineLayout(vk, device, &info);
141 }
142
143 Move<VkPipelineLayout> makePipelineLayoutWithoutDescriptors (const DeviceInterface&             vk,
144                                                                                                                          const VkDevice                         device)
145 {
146         const VkPipelineLayoutCreateInfo info =
147         {
148                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
149                 DE_NULL,                                                                                        // const void*                                  pNext;
150                 (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags  flags;
151                 0u,                                                                                                     // deUint32                                             setLayoutCount;
152                 DE_NULL,                                                                                        // const VkDescriptorSetLayout* pSetLayouts;
153                 0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
154                 DE_NULL,                                                                                        // const VkPushConstantRange*   pPushConstantRanges;
155         };
156         return createPipelineLayout(vk, device, &info);
157 }
158
159 Move<VkPipeline> makeComputePipeline (const DeviceInterface&            vk,
160                                                                           const VkDevice                                device,
161                                                                           const VkPipelineLayout                pipelineLayout,
162                                                                           const VkShaderModule                  shaderModule,
163                                                                           const VkSpecializationInfo*   specInfo)
164 {
165         const VkPipelineShaderStageCreateInfo shaderStageInfo =
166         {
167                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                      sType;
168                 DE_NULL,                                                                                                // const void*                                          pNext;
169                 (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags     flags;
170                 VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits                        stage;
171                 shaderModule,                                                                                   // VkShaderModule                                       module;
172                 "main",                                                                                                 // const char*                                          pName;
173                 specInfo,                                                                                               // const VkSpecializationInfo*          pSpecializationInfo;
174         };
175         const VkComputePipelineCreateInfo pipelineInfo =
176         {
177                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,         // VkStructureType                                      sType;
178                 DE_NULL,                                                                                        // const void*                                          pNext;
179                 (VkPipelineCreateFlags)0,                                                       // VkPipelineCreateFlags                        flags;
180                 shaderStageInfo,                                                                        // VkPipelineShaderStageCreateInfo      stage;
181                 pipelineLayout,                                                                         // VkPipelineLayout                                     layout;
182                 DE_NULL,                                                                                        // VkPipeline                                           basePipelineHandle;
183                 0,                                                                                                      // deInt32                                                      basePipelineIndex;
184         };
185         return createComputePipeline(vk, device, DE_NULL , &pipelineInfo);
186 }
187
188 VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage, const deUint32 numArrayLayers)
189 {
190         const VkImageCreateInfo imageInfo =
191         {
192                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType          sType;
193                 DE_NULL,                                                                        // const void*              pNext;
194                 (VkImageCreateFlags)0,                                          // VkImageCreateFlags       flags;
195                 VK_IMAGE_TYPE_2D,                                                       // VkImageType              imageType;
196                 format,                                                                         // VkFormat                 format;
197                 makeExtent3D(size.x(), size.y(), 1),            // VkExtent3D               extent;
198                 1u,                                                                                     // uint32_t                 mipLevels;
199                 numArrayLayers,                                                         // uint32_t                 arrayLayers;
200                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits    samples;
201                 VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling            tiling;
202                 usage,                                                                          // VkImageUsageFlags        usage;
203                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode            sharingMode;
204                 0u,                                                                                     // uint32_t                 queueFamilyIndexCount;
205                 DE_NULL,                                                                        // const uint32_t*          pQueueFamilyIndices;
206                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout            initialLayout;
207         };
208         return imageInfo;
209 }
210
211 Move<VkImageView> makeImageView (const DeviceInterface&                 vk,
212                                                                  const VkDevice                                 vkDevice,
213                                                                  const VkImage                                  image,
214                                                                  const VkImageViewType                  viewType,
215                                                                  const VkFormat                                 format,
216                                                                  const VkImageSubresourceRange  subresourceRange)
217 {
218         const VkImageViewCreateInfo imageViewParams =
219         {
220                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType                      sType;
221                 DE_NULL,                                                                                // const void*                          pNext;
222                 (VkImageViewCreateFlags)0,                                              // VkImageViewCreateFlags       flags;
223                 image,                                                                                  // VkImage                                      image;
224                 viewType,                                                                               // VkImageViewType                      viewType;
225                 format,                                                                                 // VkFormat                                     format;
226                 makeComponentMappingRGBA(),                                             // VkComponentMapping           components;
227                 subresourceRange,                                                               // VkImageSubresourceRange      subresourceRange;
228         };
229         return createImageView(vk, vkDevice, &imageViewParams);
230 }
231
232 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D                                 extent,
233                                                                            const VkImageSubresourceLayers       subresourceLayers)
234 {
235         const VkBufferImageCopy copyParams =
236         {
237                 0ull,                                                                           //      VkDeviceSize                            bufferOffset;
238                 0u,                                                                                     //      deUint32                                        bufferRowLength;
239                 0u,                                                                                     //      deUint32                                        bufferImageHeight;
240                 subresourceLayers,                                                      //      VkImageSubresourceLayers        imageSubresource;
241                 makeOffset3D(0, 0, 0),                                          //      VkOffset3D                                      imageOffset;
242                 extent,                                                                         //      VkExtent3D                                      imageExtent;
243         };
244         return copyParams;
245 }
246
247 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
248 {
249         const VkCommandBufferBeginInfo info =
250         {
251                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                          sType;
252                 DE_NULL,                                                                                // const void*                              pNext;
253                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,    // VkCommandBufferUsageFlags                flags;
254                 DE_NULL,                                                                                // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
255         };
256         VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
257 }
258
259 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
260 {
261         VK_CHECK(vk.endCommandBuffer(commandBuffer));
262 }
263
264 void submitCommandsAndWait (const DeviceInterface&      vk,
265                                                         const VkDevice                  device,
266                                                         const VkQueue                   queue,
267                                                         const VkCommandBuffer   commandBuffer)
268 {
269         const Unique<VkFence> fence(createFence(vk, device));
270
271         const VkSubmitInfo submitInfo =
272         {
273                 VK_STRUCTURE_TYPE_SUBMIT_INFO,          // VkStructureType                sType;
274                 DE_NULL,                                                        // const void*                    pNext;
275                 0u,                                                                     // uint32_t                       waitSemaphoreCount;
276                 DE_NULL,                                                        // const VkSemaphore*             pWaitSemaphores;
277                 DE_NULL,                                                        // const VkPipelineStageFlags*    pWaitDstStageMask;
278                 1u,                                                                     // uint32_t                       commandBufferCount;
279                 &commandBuffer,                                         // const VkCommandBuffer*         pCommandBuffers;
280                 0u,                                                                     // uint32_t                       signalSemaphoreCount;
281                 DE_NULL,                                                        // const VkSemaphore*             pSignalSemaphores;
282         };
283         VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
284         VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
285 }
286
287 void beginRenderPass (const DeviceInterface&    vk,
288                                           const VkCommandBuffer         commandBuffer,
289                                           const VkRenderPass            renderPass,
290                                           const VkFramebuffer           framebuffer,
291                                           const VkRect2D&                       renderArea,
292                                           const tcu::Vec4&                      clearColor)
293 {
294         const VkClearValue clearValue = makeClearValueColor(clearColor);
295
296         const VkRenderPassBeginInfo renderPassBeginInfo = {
297                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
298                 DE_NULL,                                                                                // const void*             pNext;
299                 renderPass,                                                                             // VkRenderPass            renderPass;
300                 framebuffer,                                                                    // VkFramebuffer           framebuffer;
301                 renderArea,                                                                             // VkRect2D                renderArea;
302                 1u,                                                                                             // uint32_t                clearValueCount;
303                 &clearValue,                                                                    // const VkClearValue*     pClearValues;
304         };
305
306         vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
307 }
308
309 void beginRenderPassWithRasterizationDisabled (const DeviceInterface&   vk,
310                                                                                            const VkCommandBuffer        commandBuffer,
311                                                                                            const VkRenderPass           renderPass,
312                                                                                            const VkFramebuffer          framebuffer)
313 {
314         const VkRect2D renderArea = {{ 0, 0 }, { 0, 0 }};
315
316         const VkRenderPassBeginInfo renderPassBeginInfo = {
317                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
318                 DE_NULL,                                                                                // const void*             pNext;
319                 renderPass,                                                                             // VkRenderPass            renderPass;
320                 framebuffer,                                                                    // VkFramebuffer           framebuffer;
321                 renderArea,                                                                             // VkRect2D                renderArea;
322                 0u,                                                                                             // uint32_t                clearValueCount;
323                 DE_NULL,                                                                                // const VkClearValue*     pClearValues;
324         };
325
326         vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
327 }
328
329 void endRenderPass (const DeviceInterface&      vk,
330                                         const VkCommandBuffer   commandBuffer)
331 {
332         vk.cmdEndRenderPass(commandBuffer);
333 }
334
335 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
336                                                                    const VkDevice                       device,
337                                                                    const VkFormat                       colorFormat)
338 {
339         const VkAttachmentDescription colorAttachmentDescription =
340         {
341                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
342                 colorFormat,                                                                            // VkFormat                                                     format;
343                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
344                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
345                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
346                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
347                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
348                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
349                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
350         };
351
352         const VkAttachmentReference colorAttachmentReference =
353         {
354                 0u,                                                                                                     // deUint32                     attachment;
355                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
356         };
357
358         const VkAttachmentReference depthAttachmentReference =
359         {
360                 VK_ATTACHMENT_UNUSED,                                                           // deUint32                     attachment;
361                 VK_IMAGE_LAYOUT_UNDEFINED                                                       // VkImageLayout        layout;
362         };
363
364         const VkSubpassDescription subpassDescription =
365         {
366                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags            flags;
367                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
368                 0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
369                 DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
370                 1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
371                 &colorAttachmentReference,                                                      // const VkAttachmentReference*         pColorAttachments;
372                 DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
373                 &depthAttachmentReference,                                                      // const VkAttachmentReference*         pDepthStencilAttachment;
374                 0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
375                 DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
376         };
377
378         const VkRenderPassCreateInfo renderPassInfo =
379         {
380                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
381                 DE_NULL,                                                                                        // const void*                                          pNext;
382                 (VkRenderPassCreateFlags)0,                                                     // VkRenderPassCreateFlags                      flags;
383                 1u,                                                                                                     // deUint32                                                     attachmentCount;
384                 &colorAttachmentDescription,                                            // const VkAttachmentDescription*       pAttachments;
385                 1u,                                                                                                     // deUint32                                                     subpassCount;
386                 &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
387                 0u,                                                                                                     // deUint32                                                     dependencyCount;
388                 DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
389         };
390
391         return createRenderPass(vk, device, &renderPassInfo);
392 }
393
394 Move<VkRenderPass> makeRenderPassWithoutAttachments (const DeviceInterface&     vk,
395                                                                                                          const VkDevice                 device)
396 {
397         const VkAttachmentReference unusedAttachment =
398         {
399                 VK_ATTACHMENT_UNUSED,                                                           // deUint32                     attachment;
400                 VK_IMAGE_LAYOUT_UNDEFINED                                                       // VkImageLayout        layout;
401         };
402
403         const VkSubpassDescription subpassDescription =
404         {
405                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags            flags;
406                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
407                 0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
408                 DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
409                 0u,                                                                                                     // deUint32                                                     colorAttachmentCount;
410                 DE_NULL,                                                                                        // const VkAttachmentReference*         pColorAttachments;
411                 DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
412                 &unusedAttachment,                                                                      // const VkAttachmentReference*         pDepthStencilAttachment;
413                 0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
414                 DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
415         };
416
417         const VkRenderPassCreateInfo renderPassInfo =
418         {
419                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
420                 DE_NULL,                                                                                        // const void*                                          pNext;
421                 (VkRenderPassCreateFlags)0,                                                     // VkRenderPassCreateFlags                      flags;
422                 0u,                                                                                                     // deUint32                                                     attachmentCount;
423                 DE_NULL,                                                                                        // const VkAttachmentDescription*       pAttachments;
424                 1u,                                                                                                     // deUint32                                                     subpassCount;
425                 &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
426                 0u,                                                                                                     // deUint32                                                     dependencyCount;
427                 DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
428         };
429
430         return createRenderPass(vk, device, &renderPassInfo);
431 }
432
433 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&             vk,
434                                                                          const VkDevice                         device,
435                                                                          const VkRenderPass                     renderPass,
436                                                                          const VkImageView                      colorAttachment,
437                                                                          const deUint32                         width,
438                                                                          const deUint32                         height,
439                                                                          const deUint32                         layers)
440 {
441         const VkFramebufferCreateInfo framebufferInfo = {
442                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                             sType;
443                 DE_NULL,                                                                                // const void*                                 pNext;
444                 (VkFramebufferCreateFlags)0,                                    // VkFramebufferCreateFlags                    flags;
445                 renderPass,                                                                             // VkRenderPass                                renderPass;
446                 1u,                                                                                             // uint32_t                                    attachmentCount;
447                 &colorAttachment,                                                               // const VkImageView*                          pAttachments;
448                 width,                                                                                  // uint32_t                                    width;
449                 height,                                                                                 // uint32_t                                    height;
450                 layers,                                                                                 // uint32_t                                    layers;
451         };
452
453         return createFramebuffer(vk, device, &framebufferInfo);
454 }
455
456 Move<VkFramebuffer> makeFramebufferWithoutAttachments (const DeviceInterface&           vk,
457                                                                                                            const VkDevice                               device,
458                                                                                                            const VkRenderPass                   renderPass)
459 {
460         const VkFramebufferCreateInfo framebufferInfo = {
461                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                             sType;
462                 DE_NULL,                                                                                // const void*                                 pNext;
463                 (VkFramebufferCreateFlags)0,                                    // VkFramebufferCreateFlags                    flags;
464                 renderPass,                                                                             // VkRenderPass                                renderPass;
465                 0u,                                                                                             // uint32_t                                    attachmentCount;
466                 DE_NULL,                                                                                // const VkImageView*                          pAttachments;
467                 1u,                                                                                             // uint32_t                                    width;
468                 1u,                                                                                             // uint32_t                                    height;
469                 1u,                                                                                             // uint32_t                                    layers;
470         };
471
472         return createFramebuffer(vk, device, &framebufferInfo);
473 }
474
475 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&                     vk,
476                                                                                                                          const VkDevice                                 device,
477                                                                                                                          const VkShaderStageFlagBits    stage,
478                                                                                                                          const ProgramBinary&                   binary,
479                                                                                                                          const VkSpecializationInfo*    specInfo)
480 {
481         VkShaderModule module;
482         switch (stage)
483         {
484                 case (VK_SHADER_STAGE_VERTEX_BIT):
485                         DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
486                         m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
487                         module = *m_vertexShaderModule;
488                         break;
489
490                 case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
491                         DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
492                         m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
493                         module = *m_tessControlShaderModule;
494                         break;
495
496                 case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
497                         DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
498                         m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
499                         module = *m_tessEvaluationShaderModule;
500                         break;
501
502                 case (VK_SHADER_STAGE_GEOMETRY_BIT):
503                         DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
504                         m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
505                         module = *m_geometryShaderModule;
506                         break;
507
508                 case (VK_SHADER_STAGE_FRAGMENT_BIT):
509                         DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
510                         m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
511                         module = *m_fragmentShaderModule;
512                         break;
513
514                 default:
515                         DE_FATAL("Invalid shader stage");
516                         return *this;
517         }
518
519         const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
520         {
521                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
522                 DE_NULL,                                                                                                // const void*                                                  pNext;
523                 (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
524                 stage,                                                                                                  // VkShaderStageFlagBits                                stage;
525                 module,                                                                                                 // VkShaderModule                                               module;
526                 "main",                                                                                                 // const char*                                                  pName;
527                 specInfo,                                                                                               // const VkSpecializationInfo*                  pSpecializationInfo;
528         };
529
530         m_shaderStageFlags |= stage;
531         m_shaderStages.push_back(pipelineShaderStageInfo);
532
533         return *this;
534 }
535
536 GraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
537 {
538         const VkVertexInputBindingDescription bindingDesc =
539         {
540                 0u,                                                                     // uint32_t                             binding;
541                 stride,                                                         // uint32_t                             stride;
542                 VK_VERTEX_INPUT_RATE_VERTEX,            // VkVertexInputRate    inputRate;
543         };
544         const VkVertexInputAttributeDescription attributeDesc =
545         {
546                 0u,                                                                     // uint32_t                     location;
547                 0u,                                                                     // uint32_t                     binding;
548                 vertexFormat,                                           // VkFormat                     format;
549                 0u,                                                                     // uint32_t                     offset;
550         };
551
552         m_vertexInputBindings.clear();
553         m_vertexInputBindings.push_back(bindingDesc);
554
555         m_vertexInputAttributes.clear();
556         m_vertexInputAttributes.push_back(attributeDesc);
557
558         return *this;
559 }
560
561 template<typename T>
562 inline const T* dataPointer (const std::vector<T>& vec)
563 {
564         return (vec.size() != 0 ? &vec[0] : DE_NULL);
565 }
566
567 Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface& vk,
568                                                                                                  const VkDevice                 device,
569                                                                                                  const VkPipelineLayout pipelineLayout,
570                                                                                                  const VkRenderPass             renderPass)
571 {
572         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
573         {
574                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                             sType;
575                 DE_NULL,                                                                                                                // const void*                                 pNext;
576                 (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags       flags;
577                 static_cast<deUint32>(m_vertexInputBindings.size()),                    // uint32_t                                    vertexBindingDescriptionCount;
578                 dataPointer(m_vertexInputBindings),                                                             // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
579                 static_cast<deUint32>(m_vertexInputAttributes.size()),                  // uint32_t                                    vertexAttributeDescriptionCount;
580                 dataPointer(m_vertexInputAttributes),                                                   // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
581         };
582
583         const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
584                                                                                                                                                                                                                  : m_primitiveTopology;
585         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
586         {
587                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
588                 DE_NULL,                                                                                                                // const void*                                 pNext;
589                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags     flags;
590                 topology,                                                                                                               // VkPrimitiveTopology                         topology;
591                 VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
592         };
593
594         const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
595         {
596                 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,              // VkStructureType                             sType;
597                 DE_NULL,                                                                                                                // const void*                                 pNext;
598                 (VkPipelineTessellationStateCreateFlags)0,                                              // VkPipelineTessellationStateCreateFlags      flags;
599                 m_patchControlPoints,                                                                                   // uint32_t                                    patchControlPoints;
600         };
601
602         const VkViewport viewport = makeViewport(
603                 0.0f, 0.0f,
604                 static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()),
605                 0.0f, 1.0f);
606
607         const VkRect2D scissor = {
608                 makeOffset2D(0, 0),
609                 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
610         };
611
612         const bool haveRenderSize = m_renderSize.x() > 0 && m_renderSize.y() > 0;
613
614         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
615         {
616                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                             sType;
617                 DE_NULL,                                                                                                // const void*                                 pNext;
618                 (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags          flags;
619                 1u,                                                                                                             // uint32_t                                    viewportCount;
620                 haveRenderSize ? &viewport : DE_NULL,                                   // const VkViewport*                           pViewports;
621                 1u,                                                                                                             // uint32_t                                    scissorCount;
622                 haveRenderSize ? &scissor : DE_NULL,                                    // const VkRect2D*                             pScissors;
623         };
624
625         const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
626         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
627         {
628                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
629                 DE_NULL,                                                                                                                // const void*                              pNext;
630                 (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags  flags;
631                 VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
632                 isRasterizationDisabled,                                                                                // VkBool32                                 rasterizerDiscardEnable;
633                 VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
634                 m_cullModeFlags,                                                                                                // VkCullModeFlags                                                      cullMode;
635                 m_frontFace,                                                                                                    // VkFrontFace                                                          frontFace;
636                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
637                 0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
638                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
639                 0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
640                 1.0f,                                                                                                                   // float                                                                        lineWidth;
641         };
642
643         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
644         {
645                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
646                 DE_NULL,                                                                                                        // const void*                                                          pNext;
647                 (VkPipelineMultisampleStateCreateFlags)0,                                       // VkPipelineMultisampleStateCreateFlags        flags;
648                 VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
649                 VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
650                 0.0f,                                                                                                           // float                                                                        minSampleShading;
651                 DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
652                 VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
653                 VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
654         };
655
656         const VkStencilOpState stencilOpState = makeStencilOpState(
657                 VK_STENCIL_OP_KEEP,             // stencil fail
658                 VK_STENCIL_OP_KEEP,             // depth & stencil pass
659                 VK_STENCIL_OP_KEEP,             // depth only fail
660                 VK_COMPARE_OP_NEVER,    // compare op
661                 0u,                                             // compare mask
662                 0u,                                             // write mask
663                 0u);                                    // reference
664
665         const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
666         {
667                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
668                 DE_NULL,                                                                                                        // const void*                                                          pNext;
669                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
670                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthTestEnable;
671                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthWriteEnable;
672                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
673                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
674                 VK_FALSE,                                                                                                       // VkBool32                                                                     stencilTestEnable;
675                 stencilOpState,                                                                                         // VkStencilOpState                                                     front;
676                 stencilOpState,                                                                                         // VkStencilOpState                                                     back;
677                 0.0f,                                                                                                           // float                                                                        minDepthBounds;
678                 1.0f,                                                                                                           // float                                                                        maxDepthBounds;
679         };
680
681         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
682         const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
683         {
684                 m_blendEnable,                                          // VkBool32                                     blendEnable;
685                 VK_BLEND_FACTOR_SRC_ALPHA,                      // VkBlendFactor                        srcColorBlendFactor;
686                 VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        dstColorBlendFactor;
687                 VK_BLEND_OP_ADD,                                        // VkBlendOp                            colorBlendOp;
688                 VK_BLEND_FACTOR_SRC_ALPHA,                      // VkBlendFactor                        srcAlphaBlendFactor;
689                 VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        dstAlphaBlendFactor;
690                 VK_BLEND_OP_ADD,                                        // VkBlendOp                            alphaBlendOp;
691                 colorComponentsAll,                                     // VkColorComponentFlags        colorWriteMask;
692         };
693
694         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
695         {
696                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
697                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
698                 (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
699                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
700                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
701                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
702                 &pipelineColorBlendAttachmentState,                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
703                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
704         };
705
706         std::vector<VkDynamicState> dynamicStates;
707         if (!haveRenderSize)
708         {
709                 dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
710                 dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
711         }
712
713         const VkPipelineDynamicStateCreateInfo pipelineDynamicStateInfo =
714         {
715                 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,   // VkStructureType                                              sType;
716                 DE_NULL,                                                                                                // const void*                                                  pNext;
717                 0,                                                                                                              // VkPipelineDynamicStateCreateFlags    flags;
718                 static_cast<deUint32>(dynamicStates.size()),                    // uint32_t                                                             dynamicStateCount;
719                 (dynamicStates.empty() ? DE_NULL : &dynamicStates[0]),  // const VkDynamicState*                                pDynamicStates;
720         };
721
722         const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
723         {
724                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                                // VkStructureType                                                                      sType;
725                 DE_NULL,                                                                                                                                // const void*                                                                          pNext;
726                 (VkPipelineCreateFlags)0,                                                                                               // VkPipelineCreateFlags                                                        flags;
727                 static_cast<deUint32>(m_shaderStages.size()),                                                   // deUint32                                                                                     stageCount;
728                 &m_shaderStages[0],                                                                                                             // const VkPipelineShaderStageCreateInfo*                       pStages;
729                 &vertexInputStateInfo,                                                                                                  // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
730                 &pipelineInputAssemblyStateInfo,                                                                                // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
731                 (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*             pTessellationState;
732                 (isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo),               // const VkPipelineViewportStateCreateInfo*                     pViewportState;
733                 &pipelineRasterizationStateInfo,                                                                                // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
734                 (isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo),    // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
735                 (isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo),   // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
736                 (isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo),             // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
737                 &pipelineDynamicStateInfo,                                                                                              // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
738                 pipelineLayout,                                                                                                                 // VkPipelineLayout                                                                     layout;
739                 renderPass,                                                                                                                             // VkRenderPass                                                                         renderPass;
740                 0u,                                                                                                                                             // deUint32                                                                                     subpass;
741                 DE_NULL,                                                                                                                                // VkPipeline                                                                           basePipelineHandle;
742                 0,                                                                                                                                              // deInt32                                                                                      basePipelineIndex;
743         };
744
745         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
746 }
747
748 float getClampedTessLevel (const SpacingMode mode, const float tessLevel)
749 {
750         switch (mode)
751         {
752                 case SPACINGMODE_EQUAL:                         return de::max(1.0f, tessLevel);
753                 case SPACINGMODE_FRACTIONAL_ODD:        return de::max(1.0f, tessLevel);
754                 case SPACINGMODE_FRACTIONAL_EVEN:       return de::max(2.0f, tessLevel);
755                 default:
756                         DE_ASSERT(false);
757                         return 0.0f;
758         }
759 }
760
761 int getRoundedTessLevel (const SpacingMode mode, const float clampedTessLevel)
762 {
763         static const int minimumMaxTessGenLevel = 64;   //!< Minimum maxTessellationGenerationLevel defined by the spec.
764
765         int result = (int)deFloatCeil(clampedTessLevel);
766
767         switch (mode)
768         {
769                 case SPACINGMODE_EQUAL:                                                                                 break;
770                 case SPACINGMODE_FRACTIONAL_ODD:        result += 1 - result % 2;       break;
771                 case SPACINGMODE_FRACTIONAL_EVEN:       result += result % 2;           break;
772                 default:
773                         DE_ASSERT(false);
774         }
775         DE_ASSERT(de::inRange<int>(result, 1, minimumMaxTessGenLevel));
776         DE_UNREF(minimumMaxTessGenLevel);
777
778         return result;
779 }
780
781 int getClampedRoundedTessLevel (const SpacingMode mode, const float tessLevel)
782 {
783         return getRoundedTessLevel(mode, getClampedTessLevel(mode, tessLevel));
784 }
785
786 void getClampedRoundedTriangleTessLevels (const SpacingMode     spacingMode,
787                                                                                   const float*          innerSrc,
788                                                                                   const float*          outerSrc,
789                                                                                   int*                          innerDst,
790                                                                                   int*                          outerDst)
791 {
792         innerDst[0] = getClampedRoundedTessLevel(spacingMode, innerSrc[0]);
793         for (int i = 0; i < 3; i++)
794                 outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
795 }
796
797 void getClampedRoundedQuadTessLevels (const SpacingMode spacingMode,
798                                                                           const float*          innerSrc,
799                                                                           const float*          outerSrc,
800                                                                           int*                          innerDst,
801                                                                           int*                          outerDst)
802 {
803         for (int i = 0; i < 2; i++)
804                 innerDst[i] = getClampedRoundedTessLevel(spacingMode, innerSrc[i]);
805         for (int i = 0; i < 4; i++)
806                 outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
807 }
808
809 void getClampedRoundedIsolineTessLevels (const SpacingMode      spacingMode,
810                                                                                  const float*           outerSrc,
811                                                                                  int*                           outerDst)
812 {
813         outerDst[0] = getClampedRoundedTessLevel(SPACINGMODE_EQUAL,     outerSrc[0]);
814         outerDst[1] = getClampedRoundedTessLevel(spacingMode,           outerSrc[1]);
815 }
816
817 int numOuterTessellationLevels (const TessPrimitiveType primType)
818 {
819         switch (primType)
820         {
821                 case TESSPRIMITIVETYPE_TRIANGLES:       return 3;
822                 case TESSPRIMITIVETYPE_QUADS:           return 4;
823                 case TESSPRIMITIVETYPE_ISOLINES:        return 2;
824                 default:
825                         DE_ASSERT(false);
826                         return 0;
827         }
828 }
829
830 bool isPatchDiscarded (const TessPrimitiveType primitiveType, const float* outerLevels)
831 {
832         const int numOuterLevels = numOuterTessellationLevels(primitiveType);
833         for (int i = 0; i < numOuterLevels; i++)
834                 if (outerLevels[i] <= 0.0f)
835                         return true;
836         return false;
837 }
838
839 std::string getTessellationLevelsString (const TessLevels& tessLevels, const TessPrimitiveType primitiveType)
840 {
841         std::ostringstream str;
842         switch (primitiveType)
843         {
844                 case TESSPRIMITIVETYPE_ISOLINES:
845                         str << "inner: { }, "
846                                 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << " }";
847                         break;
848
849                 case TESSPRIMITIVETYPE_TRIANGLES:
850                         str << "inner: { " << tessLevels.inner[0] << " }, "
851                                 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << " }";
852                         break;
853
854                 case TESSPRIMITIVETYPE_QUADS:
855                         str << "inner: { " << tessLevels.inner[0] << ", " << tessLevels.inner[1] << " }, "
856                                 << "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << ", " << tessLevels.outer[3] << " }";
857                         break;
858
859                 default:
860                         DE_ASSERT(false);
861         }
862
863         return str.str();
864 }
865
866 //! Assumes array sizes inner[2] and outer[4].
867 std::string getTessellationLevelsString (const float* inner, const float* outer)
868 {
869         const TessLevels tessLevels =
870         {
871                 { inner[0], inner[1] },
872                 { outer[0], outer[1], outer[2], outer[3] }
873         };
874         return getTessellationLevelsString(tessLevels, TESSPRIMITIVETYPE_QUADS);
875 }
876
877 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
878 // (e.g. it may not exactly hold that u+v+w == 1.0f, or [uvw] + (1.0f-[uvw]) == 1.0f).
879 std::vector<tcu::Vec3> generateReferenceTriangleTessCoords (const SpacingMode   spacingMode,
880                                                                                                                         const int                       inner,
881                                                                                                                         const int                       outer0,
882                                                                                                                         const int                       outer1,
883                                                                                                                         const int                       outer2)
884 {
885         std::vector<tcu::Vec3> tessCoords;
886
887         if (inner == 1)
888         {
889                 if (outer0 == 1 && outer1 == 1 && outer2 == 1)
890                 {
891                         tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f));
892                         tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f));
893                         tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 1.0f));
894                         return tessCoords;
895                 }
896                 else
897                         return generateReferenceTriangleTessCoords(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
898                                                                                                            outer0, outer1, outer2);
899         }
900         else
901         {
902                 for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3(    0.0f,        v, 1.0f - v)); }
903                 for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v,     0.0f,        v)); }
904                 for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3(       v, 1.0f - v,     0.0f)); }
905
906                 const int numInnerTriangles = inner/2;
907                 for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
908                 {
909                         const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
910
911                         if (curInnerTriangleLevel == 0)
912                                 tessCoords.push_back(tcu::Vec3(1.0f/3.0f));
913                         else
914                         {
915                                 const float             minUVW          = (float)(2 * (innerTriangleNdx + 1)) / (float)(3 * inner);
916                                 const float             maxUVW          = 1.0f - 2.0f*minUVW;
917                                 const tcu::Vec3 corners[3]      =
918                                 {
919                                         tcu::Vec3(maxUVW, minUVW, minUVW),
920                                         tcu::Vec3(minUVW, maxUVW, minUVW),
921                                         tcu::Vec3(minUVW, minUVW, maxUVW)
922                                 };
923
924                                 for (int i = 0; i < curInnerTriangleLevel; i++)
925                                 {
926                                         const float f = (float)i / (float)curInnerTriangleLevel;
927                                         for (int j = 0; j < 3; j++)
928                                                 tessCoords.push_back((1.0f - f)*corners[j] + f*corners[(j+1)%3]);
929                                 }
930                         }
931                 }
932
933                 return tessCoords;
934         }
935 }
936
937 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
938 // (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
939 std::vector<tcu::Vec3> generateReferenceQuadTessCoords (const SpacingMode       spacingMode,
940                                                                                                                 const int                       inner0,
941                                                                                                                 const int                       inner1,
942                                                                                                                 const int                       outer0,
943                                                                                                                 const int                       outer1,
944                                                                                                                 const int                       outer2,
945                                                                                                                 const int                       outer3)
946 {
947         std::vector<tcu::Vec3> tessCoords;
948
949         if (inner0 == 1 || inner1 == 1)
950         {
951                 if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
952                 {
953                         tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 0.0f));
954                         tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f));
955                         tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f));
956                         tessCoords.push_back(tcu::Vec3(1.0f, 1.0f, 0.0f));
957                         return tessCoords;
958                 }
959                 else
960                         return generateReferenceQuadTessCoords(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
961                                                                                                                                 inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
962                                                                                                                                 outer0, outer1, outer2, outer3);
963         }
964         else
965         {
966                 for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3(    0.0f,        v, 0.0f)); }
967                 for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v,     0.0f, 0.0f)); }
968                 for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3(    1.0f, 1.0f - v, 0.0f)); }
969                 for (int i = 0; i < outer3; i++) { const float v = (float)i / (float)outer3; tessCoords.push_back(tcu::Vec3(       v,     1.0f, 0.0f)); }
970
971                 for (int innerVtxY = 0; innerVtxY < inner1-1; innerVtxY++)
972                 for (int innerVtxX = 0; innerVtxX < inner0-1; innerVtxX++)
973                         tessCoords.push_back(tcu::Vec3((float)(innerVtxX + 1) / (float)inner0,
974                                                                                    (float)(innerVtxY + 1) / (float)inner1,
975                                                                                    0.0f));
976
977                 return tessCoords;
978         }
979 }
980
981 // \note The tessellation coordinates generated by this function could break some of the rules given in the spec
982 // (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
983 std::vector<tcu::Vec3> generateReferenceIsolineTessCoords (const int outer0, const int outer1)
984 {
985         std::vector<tcu::Vec3> tessCoords;
986
987         for (int y = 0; y < outer0;   y++)
988         for (int x = 0; x < outer1+1; x++)
989                 tessCoords.push_back(tcu::Vec3((float)x / (float)outer1,
990                                                                            (float)y / (float)outer0,
991                                                                            0.0f));
992
993         return tessCoords;
994 }
995
996 static int referencePointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
997 {
998         if (isPatchDiscarded(primitiveType, outerLevels))
999                 return 0;
1000
1001         switch (primitiveType)
1002         {
1003                 case TESSPRIMITIVETYPE_TRIANGLES:
1004                 {
1005                         int inner;
1006                         int outer[3];
1007                         getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
1008                         return static_cast<int>(generateReferenceTriangleTessCoords(spacingMode, inner, outer[0], outer[1], outer[2]).size());
1009                 }
1010
1011                 case TESSPRIMITIVETYPE_QUADS:
1012                 {
1013                         int inner[2];
1014                         int outer[4];
1015                         getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
1016                         return static_cast<int>(generateReferenceQuadTessCoords(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]).size());
1017                 }
1018
1019                 case TESSPRIMITIVETYPE_ISOLINES:
1020                 {
1021                         int outer[2];
1022                         getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
1023                         return static_cast<int>(generateReferenceIsolineTessCoords(outer[0], outer[1]).size());
1024                 }
1025
1026                 default:
1027                         DE_ASSERT(false);
1028                         return 0;
1029         }
1030 }
1031
1032 static int referenceTriangleNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner, const int outer0, const int outer1, const int outer2)
1033 {
1034         if (inner == 1)
1035         {
1036                 if (outer0 == 1 && outer1 == 1 && outer2 == 1)
1037                         return 1;
1038                 else
1039                         return referenceTriangleNonPointModePrimitiveCount(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
1040                                                                                                                                                         outer0, outer1, outer2);
1041         }
1042         else
1043         {
1044                 int result = outer0 + outer1 + outer2;
1045
1046                 const int numInnerTriangles = inner/2;
1047                 for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
1048                 {
1049                         const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
1050
1051                         if (curInnerTriangleLevel == 1)
1052                                 result += 4;
1053                         else
1054                                 result += 2*3*curInnerTriangleLevel;
1055                 }
1056
1057                 return result;
1058         }
1059 }
1060
1061 static int referenceQuadNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner0, const int inner1, const int outer0, const int outer1, const int outer2, const int outer3)
1062 {
1063         if (inner0 == 1 || inner1 == 1)
1064         {
1065                 if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
1066                         return 2;
1067                 else
1068                         return referenceQuadNonPointModePrimitiveCount(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
1069                                                                                                                                                 inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
1070                                                                                                                                                 outer0, outer1, outer2, outer3);
1071         }
1072         else
1073                 return 2*(inner0-2)*(inner1-2) + 2*(inner0-2) + 2*(inner1-2) + outer0+outer1+outer2+outer3;
1074 }
1075
1076 static inline int referenceIsolineNonPointModePrimitiveCount (const int outer0, const int outer1)
1077 {
1078         return outer0*outer1;
1079 }
1080
1081 static int referenceNonPointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
1082 {
1083         if (isPatchDiscarded(primitiveType, outerLevels))
1084                 return 0;
1085
1086         switch (primitiveType)
1087         {
1088                 case TESSPRIMITIVETYPE_TRIANGLES:
1089                 {
1090                         int inner;
1091                         int outer[3];
1092                         getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
1093                         return referenceTriangleNonPointModePrimitiveCount(spacingMode, inner, outer[0], outer[1], outer[2]);
1094                 }
1095
1096                 case TESSPRIMITIVETYPE_QUADS:
1097                 {
1098                         int inner[2];
1099                         int outer[4];
1100                         getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
1101                         return referenceQuadNonPointModePrimitiveCount(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]);
1102                 }
1103
1104                 case TESSPRIMITIVETYPE_ISOLINES:
1105                 {
1106                         int outer[2];
1107                         getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
1108                         return referenceIsolineNonPointModePrimitiveCount(outer[0], outer[1]);
1109                 }
1110
1111                 default:
1112                         DE_ASSERT(false);
1113                         return 0;
1114         }
1115 }
1116
1117 int numVerticesPerPrimitive (const TessPrimitiveType primitiveType, const bool usePointMode)
1118 {
1119         if (usePointMode)
1120                 return 1;
1121
1122         switch (primitiveType)
1123         {
1124                 case TESSPRIMITIVETYPE_TRIANGLES:       return 3;
1125                 case TESSPRIMITIVETYPE_QUADS:           return 3;  // quads are composed of two triangles
1126                 case TESSPRIMITIVETYPE_ISOLINES:        return 2;
1127                 default:
1128                         DE_ASSERT(false);
1129                         return 0;
1130         }
1131 }
1132
1133 int referencePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels)
1134 {
1135         return usePointMode ? referencePointModePrimitiveCount          (primitiveType, spacingMode, innerLevels, outerLevels)
1136                                                 : referenceNonPointModePrimitiveCount   (primitiveType, spacingMode, innerLevels, outerLevels);
1137 }
1138
1139 //! In point mode this should return the number of unique vertices, while in non-point mode the maximum theoretical number of verticies.
1140 //! Actual implementation will likely return a much smaller number because the shader isn't required to be run for duplicate coordinates.
1141 int referenceVertexCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels)
1142 {
1143         return referencePrimitiveCount(primitiveType, spacingMode, usePointMode, innerLevels, outerLevels)
1144                    * numVerticesPerPrimitive(primitiveType, usePointMode);
1145 }
1146
1147 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
1148 {
1149         const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
1150
1151         if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
1152                 throw tcu::NotSupportedError("Tessellation shader not supported");
1153
1154         if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
1155                 throw tcu::NotSupportedError("Geometry shader not supported");
1156
1157         if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
1158                 throw tcu::NotSupportedError("Double-precision floats not supported");
1159
1160         if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
1161                 throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
1162
1163         if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
1164                 throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
1165
1166         if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
1167                 throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
1168 }
1169
1170 } // tessellation
1171 } // vkt