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