Added tests for rasterizer discard
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / rasterization / vktRasterizationTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Functional rasterization tests.
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktRasterizationTests.hpp"
27 #include "tcuRasterizationVerifier.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "tcuStringTemplate.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuResultCollector.hpp"
34 #include "vkImageUtil.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
37 #include "vktTestCase.hpp"
38 #include "vktTestCaseUtil.hpp"
39 #include "vktTestGroupUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkMemUtil.hpp"
42 #include "vkRefUtil.hpp"
43 #include "vkQueryUtil.hpp"
44 #include "vkBuilderUtil.hpp"
45 #include "vkTypeUtil.hpp"
46 #include "vkCmdUtil.hpp"
47 #include "vkObjUtil.hpp"
48
49 #include <vector>
50
51 using namespace vk;
52
53 namespace vkt
54 {
55 namespace rasterization
56 {
57 namespace
58 {
59
60 using tcu::RasterizationArguments;
61 using tcu::TriangleSceneSpec;
62 using tcu::PointSceneSpec;
63 using tcu::LineSceneSpec;
64 using tcu::LineInterpolationMethod;
65
66 static const char* const s_shaderVertexTemplate =       "#version 310 es\n"
67                                                                                                         "layout(location = 0) in highp vec4 a_position;\n"
68                                                                                                         "layout(location = 1) in highp vec4 a_color;\n"
69                                                                                                         "layout(location = 0) ${INTERPOLATION}out highp vec4 v_color;\n"
70                                                                                                         "layout (set=0, binding=0) uniform PointSize {\n"
71                                                                                                         "       highp float u_pointSize;\n"
72                                                                                                         "};\n"
73                                                                                                         "void main ()\n"
74                                                                                                         "{\n"
75                                                                                                         "       gl_Position = a_position;\n"
76                                                                                                         "       gl_PointSize = u_pointSize;\n"
77                                                                                                         "       v_color = a_color;\n"
78                                                                                                         "}\n";
79
80 static const char* const s_shaderFragmentTemplate =     "#version 310 es\n"
81                                                                                                         "layout(location = 0) out highp vec4 fragColor;\n"
82                                                                                                         "layout(location = 0) ${INTERPOLATION}in highp vec4 v_color;\n"
83                                                                                                         "void main ()\n"
84                                                                                                         "{\n"
85                                                                                                         "       fragColor = v_color;\n"
86                                                                                                         "}\n";
87 enum InterpolationCaseFlags
88 {
89         INTERPOLATIONFLAGS_NONE = 0,
90         INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
91         INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
92 };
93
94 enum PrimitiveWideness
95 {
96         PRIMITIVEWIDENESS_NARROW = 0,
97         PRIMITIVEWIDENESS_WIDE,
98
99         PRIMITIVEWIDENESS_LAST
100 };
101
102 class BaseRenderingTestCase : public TestCase
103 {
104 public:
105                                                                 BaseRenderingTestCase   (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deBool flatshade = DE_FALSE);
106         virtual                                         ~BaseRenderingTestCase  (void);
107
108         virtual void                            initPrograms                    (vk::SourceCollections& programCollection) const;
109
110 protected:
111         const VkSampleCountFlagBits     m_sampleCount;
112         const deBool                            m_flatshade;
113 };
114
115 BaseRenderingTestCase::BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount, deBool flatshade)
116         : TestCase(context, name, description)
117         , m_sampleCount (sampleCount)
118         , m_flatshade   (flatshade)
119 {
120 }
121
122 void BaseRenderingTestCase::initPrograms (vk::SourceCollections& programCollection) const
123 {
124         tcu::StringTemplate                                     vertexSource    (s_shaderVertexTemplate);
125         tcu::StringTemplate                                     fragmentSource  (s_shaderFragmentTemplate);
126         std::map<std::string, std::string>      params;
127
128         params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
129
130         programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vertexSource.specialize(params));
131         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fragmentSource.specialize(params));
132 }
133
134 BaseRenderingTestCase::~BaseRenderingTestCase (void)
135 {
136 }
137
138 class BaseRenderingTestInstance : public TestInstance
139 {
140 public:
141         enum {
142                 DEFAULT_RENDER_SIZE = 256
143         };
144
145                                                                                                         BaseRenderingTestInstance               (Context& context, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deUint32 renderSize = DEFAULT_RENDER_SIZE);
146                                                                                                         ~BaseRenderingTestInstance              (void);
147
148 protected:
149         void                                                                                    addImageTransitionBarrier               (VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
150         void                                                                                    drawPrimitives                                  (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology);
151         void                                                                                    drawPrimitives                                  (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, VkPrimitiveTopology primitiveTopology);
152         virtual float                                                                   getLineWidth                                    (void) const;
153         virtual float                                                                   getPointSize                                    (void) const;
154
155         virtual
156         const VkPipelineRasterizationStateCreateInfo*   getRasterizationStateCreateInfo (void) const;
157
158         virtual
159         const VkPipelineColorBlendStateCreateInfo*              getColorBlendStateCreateInfo    (void) const;
160
161         const tcu::TextureFormat&                                               getTextureFormat                                (void) const;
162
163         const deUint32                                                                  m_renderSize;
164         const VkSampleCountFlagBits                                             m_sampleCount;
165         const deUint32                                                                  m_subpixelBits;
166         const deBool                                                                    m_multisampling;
167
168         const VkFormat                                                                  m_imageFormat;
169         const tcu::TextureFormat                                                m_textureFormat;
170         Move<VkCommandPool>                                                             m_commandPool;
171
172         Move<VkImage>                                                                   m_image;
173         de::MovePtr<Allocation>                                                 m_imageMemory;
174         Move<VkImageView>                                                               m_imageView;
175
176         Move<VkImage>                                                                   m_resolvedImage;
177         de::MovePtr<Allocation>                                                 m_resolvedImageMemory;
178         Move<VkImageView>                                                               m_resolvedImageView;
179
180         Move<VkRenderPass>                                                              m_renderPass;
181         Move<VkFramebuffer>                                                             m_frameBuffer;
182
183         Move<VkDescriptorPool>                                                  m_descriptorPool;
184         Move<VkDescriptorSet>                                                   m_descriptorSet;
185         Move<VkDescriptorSetLayout>                                             m_descriptorSetLayout;
186
187         Move<VkBuffer>                                                                  m_uniformBuffer;
188         de::MovePtr<Allocation>                                                 m_uniformBufferMemory;
189         const VkDeviceSize                                                              m_uniformBufferSize;
190
191         Move<VkPipelineLayout>                                                  m_pipelineLayout;
192
193         Move<VkShaderModule>                                                    m_vertexShaderModule;
194         Move<VkShaderModule>                                                    m_fragmentShaderModule;
195
196         Move<VkBuffer>                                                                  m_resultBuffer;
197         de::MovePtr<Allocation>                                                 m_resultBufferMemory;
198         const VkDeviceSize                                                              m_resultBufferSize;
199 };
200
201 BaseRenderingTestInstance::BaseRenderingTestInstance (Context& context, VkSampleCountFlagBits sampleCount, deUint32 renderSize)
202         : TestInstance                  (context)
203         , m_renderSize                  (renderSize)
204         , m_sampleCount                 (sampleCount)
205         , m_subpixelBits                (context.getDeviceProperties().limits.subPixelPrecisionBits)
206         , m_multisampling               (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
207         , m_imageFormat                 (VK_FORMAT_R8G8B8A8_UNORM)
208         , m_textureFormat               (vk::mapVkFormat(m_imageFormat))
209         , m_uniformBufferSize   (sizeof(float))
210         , m_resultBufferSize    (renderSize * renderSize * m_textureFormat.getPixelSize())
211 {
212         const DeviceInterface&                                          vkd                                             = m_context.getDeviceInterface();
213         const VkDevice                                                          vkDevice                                = m_context.getDevice();
214         const deUint32                                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
215         Allocator&                                                                      allocator                               = m_context.getDefaultAllocator();
216         DescriptorPoolBuilder                                           descriptorPoolBuilder;
217         DescriptorSetLayoutBuilder                                      descriptorSetLayoutBuilder;
218
219         // Command Pool
220         m_commandPool = createCommandPool(vkd, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
221
222         // Image
223         {
224                 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
225                 VkImageFormatProperties properties;
226
227                 if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
228                                                                                                                                                                          m_imageFormat,
229                                                                                                                                                                          VK_IMAGE_TYPE_2D,
230                                                                                                                                                                          VK_IMAGE_TILING_OPTIMAL,
231                                                                                                                                                                          imageUsage,
232                                                                                                                                                                          0,
233                                                                                                                                                                          &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
234                 {
235                         TCU_THROW(NotSupportedError, "Format not supported");
236                 }
237
238                 if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
239                 {
240                         TCU_THROW(NotSupportedError, "Format not supported");
241                 }
242
243                 const VkImageCreateInfo                                 imageCreateInfo                 =
244                 {
245                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
246                         DE_NULL,                                                                        // const void*                          pNext;
247                         0u,                                                                                     // VkImageCreateFlags           flags;
248                         VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
249                         m_imageFormat,                                                          // VkFormat                                     format;
250                         { m_renderSize, m_renderSize, 1u },                     // VkExtent3D                           extent;
251                         1u,                                                                                     // deUint32                                     mipLevels;
252                         1u,                                                                                     // deUint32                                     arrayLayers;
253                         m_sampleCount,                                                          // VkSampleCountFlagBits        samples;
254                         VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
255                         imageUsage,                                                                     // VkImageUsageFlags            usage;
256                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
257                         1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
258                         &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices;
259                         VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
260                 };
261
262                 m_image = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
263
264                 m_imageMemory   = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_image), MemoryRequirement::Any);
265                 VK_CHECK(vkd.bindImageMemory(vkDevice, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
266         }
267
268         // Image View
269         {
270                 const VkImageViewCreateInfo                             imageViewCreateInfo             =
271                 {
272                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                              sType;
273                         DE_NULL,                                                                        // const void*                                  pNext;
274                         0u,                                                                                     // VkImageViewCreateFlags               flags;
275                         *m_image,                                                                       // VkImage                                              image;
276                         VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                              viewType;
277                         m_imageFormat,                                                          // VkFormat                                             format;
278                         makeComponentMappingRGBA(),                                     // VkComponentMapping                   components;
279                         {
280                                 VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags                   aspectMask;
281                                 0u,                                                                                     // deUint32                                             baseMipLevel;
282                                 1u,                                                                                     // deUint32                                             mipLevels;
283                                 0u,                                                                                     // deUint32                                             baseArrayLayer;
284                                 1u,                                                                                     // deUint32                                             arraySize;
285                         },                                                                                      // VkImageSubresourceRange              subresourceRange;
286                 };
287
288                 m_imageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
289         }
290
291         if (m_multisampling)
292         {
293                 {
294                         // Resolved Image
295                         const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
296                         VkImageFormatProperties properties;
297
298                         if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
299                                                                                                                                                                                  m_imageFormat,
300                                                                                                                                                                                  VK_IMAGE_TYPE_2D,
301                                                                                                                                                                                  VK_IMAGE_TILING_OPTIMAL,
302                                                                                                                                                                                  imageUsage,
303                                                                                                                                                                                  0,
304                                                                                                                                                                                  &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
305                         {
306                                 TCU_THROW(NotSupportedError, "Format not supported");
307                         }
308
309                         const VkImageCreateInfo                                 imageCreateInfo                 =
310                         {
311                                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
312                                 DE_NULL,                                                                        // const void*                          pNext;
313                                 0u,                                                                                     // VkImageCreateFlags           flags;
314                                 VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
315                                 m_imageFormat,                                                          // VkFormat                                     format;
316                                 { m_renderSize, m_renderSize, 1u },                     // VkExtent3D                           extent;
317                                 1u,                                                                                     // deUint32                                     mipLevels;
318                                 1u,                                                                                     // deUint32                                     arrayLayers;
319                                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples;
320                                 VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
321                                 imageUsage,                                                                     // VkImageUsageFlags            usage;
322                                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
323                                 1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
324                                 &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices;
325                                 VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
326                         };
327
328                         m_resolvedImage                 = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
329                         m_resolvedImageMemory   = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_resolvedImage), MemoryRequirement::Any);
330                         VK_CHECK(vkd.bindImageMemory(vkDevice, *m_resolvedImage, m_resolvedImageMemory->getMemory(), m_resolvedImageMemory->getOffset()));
331                 }
332
333                 // Resolved Image View
334                 {
335                         const VkImageViewCreateInfo                             imageViewCreateInfo             =
336                         {
337                                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                              sType;
338                                 DE_NULL,                                                                        // const void*                                  pNext;
339                                 0u,                                                                                     // VkImageViewCreateFlags               flags;
340                                 *m_resolvedImage,                                                       // VkImage                                              image;
341                                 VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                              viewType;
342                                 m_imageFormat,                                                          // VkFormat                                             format;
343                                 makeComponentMappingRGBA(),                                     // VkComponentMapping                   components;
344                                 {
345                                         VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags                   aspectMask;
346                                         0u,                                                                                     // deUint32                                             baseMipLevel;
347                                         1u,                                                                                     // deUint32                                             mipLevels;
348                                         0u,                                                                                     // deUint32                                             baseArrayLayer;
349                                         1u,                                                                                     // deUint32                                             arraySize;
350                                 },                                                                                      // VkImageSubresourceRange              subresourceRange;
351                         };
352
353                         m_resolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
354                 }
355
356         }
357
358         // Render Pass
359         {
360                 const VkImageLayout                                             imageLayout                             = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
361                 const VkAttachmentDescription                   attachmentDesc[]                =
362                 {
363                         {
364                                 0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
365                                 m_imageFormat,                                                                          // VkFormat                                                     format;
366                                 m_sampleCount,                                                                          // VkSampleCountFlagBits                        samples;
367                                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
368                                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
369                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
370                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
371                                 imageLayout,                                                                            // VkImageLayout                                        initialLayout;
372                                 imageLayout,                                                                            // VkImageLayout                                        finalLayout;
373                         },
374                         {
375                                 0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
376                                 m_imageFormat,                                                                          // VkFormat                                                     format;
377                                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
378                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           loadOp;
379                                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
380                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
381                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
382                                 imageLayout,                                                                            // VkImageLayout                                        initialLayout;
383                                 imageLayout,                                                                            // VkImageLayout                                        finalLayout;
384                         }
385                 };
386
387                 const VkAttachmentReference                             attachmentRef                   =
388                 {
389                         0u,                                                                                                     // deUint32                                                     attachment;
390                         imageLayout,                                                                            // VkImageLayout                                        layout;
391                 };
392
393                 const VkAttachmentReference                             resolveAttachmentRef    =
394                 {
395                         1u,                                                                                                     // deUint32                                                     attachment;
396                         imageLayout,                                                                            // VkImageLayout                                        layout;
397                 };
398
399                 const VkSubpassDescription                              subpassDesc                             =
400                 {
401                         0u,                                                                                                     // VkSubpassDescriptionFlags            flags;
402                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
403                         0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
404                         DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
405                         1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
406                         &attachmentRef,                                                                         // const VkAttachmentReference*         pColorAttachments;
407                         m_multisampling ? &resolveAttachmentRef : DE_NULL,      // const VkAttachmentReference*         pResolveAttachments;
408                         DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
409                         0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
410                         DE_NULL,                                                                                        // const VkAttachmentReference*         pPreserveAttachments;
411                 };
412
413                 const VkRenderPassCreateInfo                    renderPassCreateInfo    =
414                 {
415                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
416                         DE_NULL,                                                                                        // const void*                                          pNext;
417                         0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
418                         m_multisampling ? 2u : 1u,                                                      // deUint32                                                     attachmentCount;
419                         attachmentDesc,                                                                         // const VkAttachmentDescription*       pAttachments;
420                         1u,                                                                                                     // deUint32                                                     subpassCount;
421                         &subpassDesc,                                                                           // const VkSubpassDescription*          pSubpasses;
422                         0u,                                                                                                     // deUint32                                                     dependencyCount;
423                         DE_NULL,                                                                                        // const VkSubpassDependency*           pDependencies;
424                 };
425
426                 m_renderPass =  createRenderPass(vkd, vkDevice, &renderPassCreateInfo, DE_NULL);
427         }
428
429         // FrameBuffer
430         {
431                 const VkImageView                                               attachments[]                   =
432                 {
433                         *m_imageView,
434                         *m_resolvedImageView
435                 };
436
437                 const VkFramebufferCreateInfo                   framebufferCreateInfo   =
438                 {
439                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                      sType;
440                         DE_NULL,                                                                        // const void*                          pNext;
441                         0u,                                                                                     // VkFramebufferCreateFlags     flags;
442                         *m_renderPass,                                                          // VkRenderPass                         renderPass;
443                         m_multisampling ? 2u : 1u,                                      // deUint32                                     attachmentCount;
444                         attachments,                                                            // const VkImageView*           pAttachments;
445                         m_renderSize,                                                           // deUint32                                     width;
446                         m_renderSize,                                                           // deUint32                                     height;
447                         1u,                                                                                     // deUint32                                     layers;
448                 };
449
450                 m_frameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
451         }
452
453         // Uniform Buffer
454         {
455                 const VkBufferCreateInfo                                bufferCreateInfo                =
456                 {
457                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
458                         DE_NULL,                                                                        // const void*                  pNext;
459                         0u,                                                                                     // VkBufferCreateFlags  flags;
460                         m_uniformBufferSize,                                            // VkDeviceSize                 size;
461                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,                     // VkBufferUsageFlags   usage;
462                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
463                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
464                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
465                 };
466
467                 m_uniformBuffer                 = createBuffer(vkd, vkDevice, &bufferCreateInfo);
468                 m_uniformBufferMemory   = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
469
470                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset()));
471         }
472
473         // Descriptors
474         {
475                 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
476                 m_descriptorPool = descriptorPoolBuilder.build(vkd, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
477
478                 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
479                 m_descriptorSetLayout = descriptorSetLayoutBuilder.build(vkd, vkDevice);
480
481                 const VkDescriptorSetAllocateInfo               descriptorSetParams             =
482                 {
483                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
484                         DE_NULL,
485                         *m_descriptorPool,
486                         1u,
487                         &m_descriptorSetLayout.get(),
488                 };
489
490                 m_descriptorSet = allocateDescriptorSet(vkd, vkDevice, &descriptorSetParams);
491
492                 const VkDescriptorBufferInfo                    descriptorBufferInfo    =
493                 {
494                         *m_uniformBuffer,                                                       // VkBuffer             buffer;
495                         0u,                                                                                     // VkDeviceSize offset;
496                         VK_WHOLE_SIZE                                                           // VkDeviceSize range;
497                 };
498
499                 const VkWriteDescriptorSet                              writeDescritporSet              =
500                 {
501                         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,         // VkStructureType                                      sType;
502                         DE_NULL,                                                                        // const void*                                          pNext;
503                         *m_descriptorSet,                                                       // VkDescriptorSet                                      destSet;
504                         0,                                                                                      // deUint32                                                     destBinding;
505                         0,                                                                                      // deUint32                                                     destArrayElement;
506                         1u,                                                                                     // deUint32                                                     count;
507                         VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,                      // VkDescriptorType                                     descriptorType;
508                         DE_NULL,                                                                        // const VkDescriptorImageInfo*         pImageInfo;
509                         &descriptorBufferInfo,                                          // const VkDescriptorBufferInfo*        pBufferInfo;
510                         DE_NULL                                                                         // const VkBufferView*                          pTexelBufferView;
511                 };
512
513                 vkd.updateDescriptorSets(vkDevice, 1u, &writeDescritporSet, 0u, DE_NULL);
514         }
515
516         // Pipeline Layout
517         {
518                 const VkPipelineLayoutCreateInfo                pipelineLayoutCreateInfo        =
519                 {
520                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
521                         DE_NULL,                                                                                        // const void*                                  pNext;
522                         0u,                                                                                                     // VkPipelineLayoutCreateFlags  flags;
523                         1u,                                                                                                     // deUint32                                             descriptorSetCount;
524                         &m_descriptorSetLayout.get(),                                           // const VkDescriptorSetLayout* pSetLayouts;
525                         0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
526                         DE_NULL                                                                                         // const VkPushConstantRange*   pPushConstantRanges;
527                 };
528
529                 m_pipelineLayout = createPipelineLayout(vkd, vkDevice, &pipelineLayoutCreateInfo);
530         }
531
532         // Shaders
533         {
534                 m_vertexShaderModule    = createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("vertext_shader"), 0);
535                 m_fragmentShaderModule  = createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("fragment_shader"), 0);
536         }
537
538         // Result Buffer
539         {
540                 const VkBufferCreateInfo                                bufferCreateInfo                =
541                 {
542                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
543                         DE_NULL,                                                                        // const void*                  pNext;
544                         0u,                                                                                     // VkBufferCreateFlags  flags;
545                         m_resultBufferSize,                                                     // VkDeviceSize                 size;
546                         VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
547                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
548                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
549                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
550                 };
551
552                 m_resultBuffer                  = createBuffer(vkd, vkDevice, &bufferCreateInfo);
553                 m_resultBufferMemory    = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
554
555                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
556         }
557
558         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Sample count = " << getSampleCountFlagsStr(m_sampleCount) << tcu::TestLog::EndMessage;
559         m_context.getTestContext().getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
560 }
561
562 BaseRenderingTestInstance::~BaseRenderingTestInstance (void)
563 {
564 }
565
566
567 void BaseRenderingTestInstance::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
568 {
569
570         const DeviceInterface&                  vkd                                     = m_context.getDeviceInterface();
571
572         const VkImageSubresourceRange   subResourcerange        =
573         {
574                 VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
575                 0,                                                              // deUint32                             baseMipLevel;
576                 1,                                                              // deUint32                             levelCount;
577                 0,                                                              // deUint32                             baseArrayLayer;
578                 1                                                               // deUint32                             layerCount;
579         };
580
581         const VkImageMemoryBarrier              imageBarrier            =
582         {
583                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
584                 DE_NULL,                                                                        // const void*                          pNext;
585                 srcAccessMask,                                                          // VkAccessFlags                        srcAccessMask;
586                 dstAccessMask,                                                          // VkAccessFlags                        dstAccessMask;
587                 oldLayout,                                                                      // VkImageLayout                        oldLayout;
588                 newLayout,                                                                      // VkImageLayout                        newLayout;
589                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
590                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
591                 image,                                                                          // VkImage                                      image;
592                 subResourcerange                                                        // VkImageSubresourceRange      subresourceRange;
593         };
594
595         vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
596 }
597
598 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
599 {
600         // default to color white
601         const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
602
603         drawPrimitives(result, vertexData, colorData, primitiveTopology);
604 }
605
606 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology)
607 {
608         const DeviceInterface&                                          vkd                                             = m_context.getDeviceInterface();
609         const VkDevice                                                          vkDevice                                = m_context.getDevice();
610         const VkQueue                                                           queue                                   = m_context.getUniversalQueue();
611         const deUint32                                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
612         Allocator&                                                                      allocator                               = m_context.getDefaultAllocator();
613         const size_t                                                            attributeBatchSize              = positionData.size() * sizeof(tcu::Vec4);
614
615         Move<VkCommandBuffer>                                           commandBuffer;
616         Move<VkPipeline>                                                        graphicsPipeline;
617         Move<VkBuffer>                                                          vertexBuffer;
618         de::MovePtr<Allocation>                                         vertexBufferMemory;
619         const VkPhysicalDeviceProperties                        properties                              = m_context.getDeviceProperties();
620
621         if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
622         {
623                 std::stringstream message;
624                 message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
625                 TCU_THROW(NotSupportedError, message.str().c_str());
626         }
627
628         // Create Graphics Pipeline
629         {
630                 const VkVertexInputBindingDescription   vertexInputBindingDescription =
631                 {
632                         0u,                                                             // deUint32                                     binding;
633                         sizeof(tcu::Vec4),                              // deUint32                                     strideInBytes;
634                         VK_VERTEX_INPUT_RATE_VERTEX             // VkVertexInputStepRate        stepRate;
635                 };
636
637                 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
638                 {
639                         {
640                                 0u,                                                                     // deUint32     location;
641                                 0u,                                                                     // deUint32     binding;
642                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
643                                 0u                                                                      // deUint32     offsetInBytes;
644                         },
645                         {
646                                 1u,                                                                     // deUint32     location;
647                                 0u,                                                                     // deUint32     binding;
648                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
649                                 (deUint32)attributeBatchSize            // deUint32     offsetInBytes;
650                         }
651                 };
652
653                 const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams =
654                 {
655                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
656                         DE_NULL,                                                                                                                // const void*                                                          pNext;
657                         0,                                                                                                                              // VkPipelineVertexInputStateCreateFlags        flags;
658                         1u,                                                                                                                             // deUint32                                                                     bindingCount;
659                         &vertexInputBindingDescription,                                                                 // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
660                         2u,                                                                                                                             // deUint32                                                                     attributeCount;
661                         vertexInputAttributeDescriptions                                                                // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
662                 };
663
664                 const std::vector<VkViewport>   viewports       (1, makeViewport(tcu::UVec2(m_renderSize)));
665                 const std::vector<VkRect2D>             scissors        (1, makeRect2D(tcu::UVec2(m_renderSize)));
666
667                 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
668                 {
669                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
670                         DE_NULL,                                                                                                                // const void*                                                          pNext;
671                         0u,                                                                                                                             // VkPipelineMultisampleStateCreateFlags        flags;
672                         m_sampleCount,                                                                                                  // VkSampleCountFlagBits                                        rasterizationSamples;
673                         VK_FALSE,                                                                                                               // VkBool32                                                                     sampleShadingEnable;
674                         0.0f,                                                                                                                   // float                                                                        minSampleShading;
675                         DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
676                         VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
677                         VK_FALSE                                                                                                                // VkBool32                                                                     alphaToOneEnable;
678                 };
679
680                 graphicsPipeline = makeGraphicsPipeline(vkd,                                                            // const DeviceInterface&                        vk
681                                                                                                 vkDevice,                                                       // const VkDevice                                device
682                                                                                                 *m_pipelineLayout,                                      // const VkPipelineLayout                        pipelineLayout
683                                                                                                 *m_vertexShaderModule,                          // const VkShaderModule                          vertexShaderModule
684                                                                                                 DE_NULL,                                                        // const VkShaderModule                          tessellationControlShaderModule
685                                                                                                 DE_NULL,                                                        // const VkShaderModule                          tessellationEvalShaderModule
686                                                                                                 DE_NULL,                                                        // const VkShaderModule                          geometryShaderModule
687                                                                                                 *m_fragmentShaderModule,                        // const VkShaderModule                          fragmentShaderModule
688                                                                                                 *m_renderPass,                                          // const VkRenderPass                            renderPass
689                                                                                                 viewports,                                                      // const std::vector<VkViewport>&                viewports
690                                                                                                 scissors,                                                       // const std::vector<VkRect2D>&                  scissors
691                                                                                                 primitiveTopology,                                      // const VkPrimitiveTopology                     topology
692                                                                                                 0u,                                                                     // const deUint32                                subpass
693                                                                                                 0u,                                                                     // const deUint32                                patchControlPoints
694                                                                                                 &vertexInputStateParams,                        // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
695                                                                                                 getRasterizationStateCreateInfo(),      // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
696                                                                                                 &multisampleStateParams,                        // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
697                                                                                                 DE_NULL,                                                        // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo,
698                                                                                                 getColorBlendStateCreateInfo());        // const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
699         }
700
701         // Create Vertex Buffer
702         {
703                 const VkBufferCreateInfo                        vertexBufferParams              =
704                 {
705                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
706                         DE_NULL,                                                                        // const void*                  pNext;
707                         0u,                                                                                     // VkBufferCreateFlags  flags;
708                         attributeBatchSize * 2,                                         // VkDeviceSize                 size;
709                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
710                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
711                         1u,                                                                                     // deUint32                             queueFamilyCount;
712                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
713                 };
714
715                 vertexBuffer            = createBuffer(vkd, vkDevice, &vertexBufferParams);
716                 vertexBufferMemory      = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
717
718                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
719
720                 // Load vertices into vertex buffer
721                 deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
722                 deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) +  attributeBatchSize, colorData.data(), attributeBatchSize);
723                 flushMappedMemoryRange(vkd, vkDevice, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset(), vertexBufferParams.size);
724         }
725
726         // Create Command Buffer
727         commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
728
729         // Begin Command Buffer
730         beginCommandBuffer(vkd, *commandBuffer);
731
732         addImageTransitionBarrier(*commandBuffer, *m_image,
733                                                           VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                            // VkPipelineStageFlags         srcStageMask
734                                                           VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                           // VkPipelineStageFlags         dstStageMask
735                                                           0,                                                                                            // VkAccessFlags                        srcAccessMask
736                                                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        dstAccessMask
737                                                           VK_IMAGE_LAYOUT_UNDEFINED,                                            // VkImageLayout                        oldLayout;
738                                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);            // VkImageLayout                        newLayout;
739
740         if (m_multisampling) {
741                 addImageTransitionBarrier(*commandBuffer, *m_resolvedImage,
742                                                                   VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                            // VkPipelineStageFlags         srcStageMask
743                                                                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                           // VkPipelineStageFlags         dstStageMask
744                                                                   0,                                                                                            // VkAccessFlags                        srcAccessMask
745                                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        dstAccessMask
746                                                                   VK_IMAGE_LAYOUT_UNDEFINED,                                            // VkImageLayout                        oldLayout;
747                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);            // VkImageLayout                        newLayout;
748         }
749
750         // Begin Render Pass
751         beginRenderPass(vkd, *commandBuffer, *m_renderPass, *m_frameBuffer, vk::makeRect2D(0, 0, m_renderSize, m_renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
752
753         const VkDeviceSize                                              vertexBufferOffset              = 0;
754
755         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
756         vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
757         vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
758         vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
759         endRenderPass(vkd, *commandBuffer);
760
761         // Copy Image
762         {
763
764                 const VkBufferMemoryBarrier                     bufferBarrier                   =
765                 {
766                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType              sType;
767                         DE_NULL,                                                                        // const void*                  pNext;
768                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkMemoryOutputFlags  outputMask;
769                         VK_ACCESS_HOST_READ_BIT,                                        // VkMemoryInputFlags   inputMask;
770                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             srcQueueFamilyIndex;
771                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             destQueueFamilyIndex;
772                         *m_resultBuffer,                                                        // VkBuffer                             buffer;
773                         0u,                                                                                     // VkDeviceSize                 offset;
774                         m_resultBufferSize                                                      // VkDeviceSize                 size;
775                 };
776
777                 const VkBufferImageCopy                         copyRegion                              =
778                 {
779                         0u,                                                                                     // VkDeviceSize                         bufferOffset;
780                         m_renderSize,                                                           // deUint32                                     bufferRowLength;
781                         m_renderSize,                                                           // deUint32                                     bufferImageHeight;
782                         { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u },      // VkImageSubresourceCopy       imageSubresource;
783                         { 0, 0, 0 },                                                            // VkOffset3D                           imageOffset;
784                         { m_renderSize, m_renderSize, 1u }                      // VkExtent3D                           imageExtent;
785                 };
786
787                 addImageTransitionBarrier(*commandBuffer,
788                                                                   m_multisampling ? *m_resolvedImage : *m_image,
789                                                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,                // VkPipelineStageFlags         srcStageMask
790                                                                   VK_PIPELINE_STAGE_TRANSFER_BIT,                                               // VkPipelineStageFlags         dstStageMask
791                                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                                 // VkAccessFlags                        srcAccessMask
792                                                                   VK_ACCESS_TRANSFER_READ_BIT,                                                  // VkAccessFlags                        dstAccessMask
793                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                             // VkImageLayout                        oldLayout;
794                                                                   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);                                // VkImageLayout                        newLayout;)
795
796                 if (m_multisampling)
797                         vkd.cmdCopyImageToBuffer(*commandBuffer, *m_resolvedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
798                 else
799                         vkd.cmdCopyImageToBuffer(*commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
800
801                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
802         }
803
804         endCommandBuffer(vkd, *commandBuffer);
805
806         // Set Point Size
807         {
808                 float   pointSize       = getPointSize();
809                 deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
810                 flushMappedMemoryRange(vkd, vkDevice, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset(), m_uniformBufferSize);
811         }
812
813         // Submit
814         submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
815
816         invalidateMappedMemoryRange(vkd, vkDevice, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset(), m_resultBufferSize);
817         tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
818 }
819
820 float BaseRenderingTestInstance::getLineWidth (void) const
821 {
822         return 1.0f;
823 }
824
825 float BaseRenderingTestInstance::getPointSize (void) const
826 {
827         return 1.0f;
828 }
829
830 const VkPipelineRasterizationStateCreateInfo* BaseRenderingTestInstance::getRasterizationStateCreateInfo (void) const
831 {
832         static VkPipelineRasterizationStateCreateInfo   rasterizationStateCreateInfo    =
833         {
834                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
835                 DE_NULL,                                                                                                                // const void*                                                          pNext;
836                 0,                                                                                                                              // VkPipelineRasterizationStateCreateFlags      flags;
837                 false,                                                                                                                  // VkBool32                                                                     depthClipEnable;
838                 false,                                                                                                                  // VkBool32                                                                     rasterizerDiscardEnable;
839                 VK_POLYGON_MODE_FILL,                                                                                   // VkFillMode                                                           fillMode;
840                 VK_CULL_MODE_NONE,                                                                                              // VkCullMode                                                           cullMode;
841                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
842                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
843                 0.0f,                                                                                                                   // float                                                                        depthBias;
844                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
845                 0.0f,                                                                                                                   // float                                                                        slopeScaledDepthBias;
846                 getLineWidth(),                                                                                                 // float                                                                        lineWidth;
847         };
848
849         rasterizationStateCreateInfo.lineWidth = getLineWidth();
850         return &rasterizationStateCreateInfo;
851 }
852
853 const VkPipelineColorBlendStateCreateInfo* BaseRenderingTestInstance::getColorBlendStateCreateInfo (void) const
854 {
855         static const VkPipelineColorBlendAttachmentState        colorBlendAttachmentState       =
856         {
857                 false,                                                                                                          // VkBool32                     blendEnable;
858                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendColor;
859                 VK_BLEND_FACTOR_ZERO,                                                                           // VkBlend                      destBlendColor;
860                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpColor;
861                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendAlpha;
862                 VK_BLEND_FACTOR_ZERO,                                                                           // VkBlend                      destBlendAlpha;
863                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpAlpha;
864                 (VK_COLOR_COMPONENT_R_BIT |
865                  VK_COLOR_COMPONENT_G_BIT |
866                  VK_COLOR_COMPONENT_B_BIT |
867                  VK_COLOR_COMPONENT_A_BIT)                                                                      // VkChannelFlags       channelWriteMask;
868         };
869
870         static const VkPipelineColorBlendStateCreateInfo        colorBlendStateParams           =
871         {
872                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
873                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
874                 0,                                                                                                                      // VkPipelineColorBlendStateCreateFlags                 flags;
875                 false,                                                                                                          // VkBool32                                                                             logicOpEnable;
876                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
877                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
878                 &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
879                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConst[4];
880         };
881
882         return &colorBlendStateParams;
883 }
884
885 const tcu::TextureFormat& BaseRenderingTestInstance::getTextureFormat (void) const
886 {
887         return m_textureFormat;
888 }
889
890 class BaseTriangleTestInstance : public BaseRenderingTestInstance
891 {
892 public:
893                                                         BaseTriangleTestInstance        (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount);
894         virtual tcu::TestStatus iterate                                         (void);
895
896 private:
897         virtual void                    generateTriangles                       (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
898
899         int                                             m_iteration;
900         const int                               m_iterationCount;
901         VkPrimitiveTopology             m_primitiveTopology;
902         bool                                    m_allIterationsPassed;
903 };
904
905 BaseTriangleTestInstance::BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount)
906         : BaseRenderingTestInstance             (context, sampleCount)
907         , m_iteration                                   (0)
908         , m_iterationCount                              (3)
909         , m_primitiveTopology                   (primitiveTopology)
910         , m_allIterationsPassed                 (true)
911 {
912 }
913
914 tcu::TestStatus BaseTriangleTestInstance::iterate (void)
915 {
916         const std::string                                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
917         const tcu::ScopedLogSection                                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
918         tcu::Surface                                                                    resultImage                             (m_renderSize, m_renderSize);
919         std::vector<tcu::Vec4>                                                  drawBuffer;
920         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
921
922         generateTriangles(m_iteration, drawBuffer, triangles);
923
924         // draw image
925         drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
926
927         // compare
928         {
929                 bool                                    compareOk;
930                 RasterizationArguments  args;
931                 TriangleSceneSpec               scene;
932
933                 tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
934
935                 args.numSamples         = m_multisampling ? 1 : 0;
936                 args.subpixelBits       = m_subpixelBits;
937                 args.redBits            = colorBits[0];
938                 args.greenBits          = colorBits[1];
939                 args.blueBits           = colorBits[2];
940
941                 scene.triangles.swap(triangles);
942
943                 compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
944
945                 if (!compareOk)
946                         m_allIterationsPassed = false;
947         }
948
949         // result
950         if (++m_iteration == m_iterationCount)
951         {
952                 if (m_allIterationsPassed)
953                         return tcu::TestStatus::pass("Pass");
954                 else
955                         return tcu::TestStatus::fail("Incorrect rasterization");
956         }
957         else
958                 return tcu::TestStatus::incomplete();
959 }
960
961 class BaseLineTestInstance : public BaseRenderingTestInstance
962 {
963 public:
964                                                         BaseLineTestInstance    (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
965         virtual tcu::TestStatus iterate                                 (void);
966         virtual float                   getLineWidth                    (void) const;
967
968 private:
969         virtual void                    generateLines                   (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
970
971         int                                             m_iteration;
972         const int                               m_iterationCount;
973         VkPrimitiveTopology             m_primitiveTopology;
974         const PrimitiveWideness m_primitiveWideness;
975         bool                                    m_allIterationsPassed;
976         float                                   m_maxLineWidth;
977         std::vector<float>              m_lineWidths;
978 };
979
980 BaseLineTestInstance::BaseLineTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
981         : BaseRenderingTestInstance                     (context, sampleCount)
982         , m_iteration                                           (0)
983         , m_iterationCount                                      (3)
984         , m_primitiveTopology                           (primitiveTopology)
985         , m_primitiveWideness                           (wideness)
986         , m_allIterationsPassed                         (true)
987         , m_maxLineWidth                                        (1.0f)
988 {
989         DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
990
991         if (!context.getDeviceProperties().limits.strictLines)
992                 TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
993
994         // create line widths
995         if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
996         {
997                 m_lineWidths.resize(m_iterationCount, 1.0f);
998         }
999         else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1000         {
1001                 if (!m_context.getDeviceFeatures().wideLines)
1002                         TCU_THROW(NotSupportedError , "wide line support required");
1003
1004                 const float*    range = context.getDeviceProperties().limits.lineWidthRange;
1005
1006                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1007
1008                 // no wide line support
1009                 if (range[1] <= 1.0f)
1010                         TCU_THROW(NotSupportedError, "wide line support required");
1011
1012                 // set hand picked sizes
1013                 m_lineWidths.push_back(5.0f);
1014                 m_lineWidths.push_back(10.0f);
1015                 m_lineWidths.push_back(range[1]);
1016                 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
1017
1018                 m_maxLineWidth = range[1];
1019         }
1020         else
1021                 DE_ASSERT(false);
1022 }
1023
1024 tcu::TestStatus BaseLineTestInstance::iterate (void)
1025 {
1026         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1027         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1028         const float                                                             lineWidth                               = getLineWidth();
1029         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
1030         std::vector<tcu::Vec4>                                  drawBuffer;
1031         std::vector<LineSceneSpec::SceneLine>   lines;
1032
1033         // supported?
1034         if (lineWidth <= m_maxLineWidth)
1035         {
1036                 // gen data
1037                 generateLines(m_iteration, drawBuffer, lines);
1038
1039                 // draw image
1040                 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1041
1042                 // compare
1043                 {
1044                         RasterizationArguments  args;
1045                         LineSceneSpec                   scene;
1046
1047
1048                         tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1049
1050                         args.numSamples         = m_multisampling ? 1 : 0;
1051                         args.subpixelBits       = m_subpixelBits;
1052                         args.redBits            = colorBits[0];
1053                         args.greenBits          = colorBits[1];
1054                         args.blueBits           = colorBits[2];
1055
1056                         scene.lines.swap(lines);
1057                         scene.lineWidth = lineWidth;
1058
1059                         if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()))
1060                                 m_allIterationsPassed = false;
1061                 }
1062         }
1063         else
1064                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1065
1066         // result
1067         if (++m_iteration == m_iterationCount)
1068         {
1069                 if (m_allIterationsPassed)
1070                         return tcu::TestStatus::pass("Pass");
1071                 else
1072                         return tcu::TestStatus::fail("Incorrect rasterization");
1073         }
1074         else
1075                 return tcu::TestStatus::incomplete();
1076 }
1077
1078
1079 float BaseLineTestInstance::getLineWidth (void) const
1080 {
1081         return m_lineWidths[m_iteration];
1082 }
1083
1084
1085 class PointTestInstance : public BaseRenderingTestInstance
1086 {
1087 public:
1088                                                         PointTestInstance               (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
1089         virtual tcu::TestStatus iterate                                 (void);
1090         virtual float                   getPointSize                    (void) const;
1091
1092 private:
1093         virtual void                    generatePoints                  (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
1094
1095         int                                             m_iteration;
1096         const int                               m_iterationCount;
1097         const PrimitiveWideness m_primitiveWideness;
1098         bool                                    m_allIterationsPassed;
1099         float                                   m_maxPointSize;
1100         std::vector<float>              m_pointSizes;
1101 };
1102
1103 PointTestInstance::PointTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1104         : BaseRenderingTestInstance     (context, sampleCount)
1105         , m_iteration                           (0)
1106         , m_iterationCount                      (3)
1107         , m_primitiveWideness           (wideness)
1108         , m_allIterationsPassed         (true)
1109         , m_maxPointSize                        (1.0f)
1110 {
1111         // create point sizes
1112         if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1113         {
1114                 m_pointSizes.resize(m_iterationCount, 1.0f);
1115         }
1116         else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1117         {
1118                 if (!m_context.getDeviceFeatures().largePoints)
1119                         TCU_THROW(NotSupportedError , "large point support required");
1120
1121                 const float*    range = context.getDeviceProperties().limits.pointSizeRange;
1122
1123                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1124
1125                 // no wide line support
1126                 if (range[1] <= 1.0f)
1127                         TCU_THROW(NotSupportedError , "wide point support required");
1128
1129                 // set hand picked sizes
1130                 m_pointSizes.push_back(10.0f);
1131                 m_pointSizes.push_back(25.0f);
1132                 m_pointSizes.push_back(range[1]);
1133                 DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
1134
1135                 m_maxPointSize = range[1];
1136         }
1137         else
1138                 DE_ASSERT(false);
1139 }
1140
1141 tcu::TestStatus PointTestInstance::iterate (void)
1142 {
1143         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1144         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1145         const float                                                             pointSize                               = getPointSize();
1146         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
1147         std::vector<tcu::Vec4>                                  drawBuffer;
1148         std::vector<PointSceneSpec::ScenePoint> points;
1149
1150         // supported?
1151         if (pointSize <= m_maxPointSize)
1152         {
1153                 // gen data
1154                 generatePoints(m_iteration, drawBuffer, points);
1155
1156                 // draw image
1157                 drawPrimitives(resultImage, drawBuffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
1158
1159                 // compare
1160                 {
1161                         bool                                    compareOk;
1162                         RasterizationArguments  args;
1163                         PointSceneSpec                  scene;
1164
1165                         tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1166
1167                         args.numSamples         = m_multisampling ? 1 : 0;
1168                         args.subpixelBits       = m_subpixelBits;
1169                         args.redBits            = colorBits[0];
1170                         args.greenBits          = colorBits[1];
1171                         args.blueBits           = colorBits[2];
1172
1173                         scene.points.swap(points);
1174
1175                         compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1176
1177                         if (!compareOk)
1178                                 m_allIterationsPassed = false;
1179                 }
1180         }
1181         else
1182                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1183
1184         // result
1185         if (++m_iteration == m_iterationCount)
1186         {
1187                 if (m_allIterationsPassed)
1188                         return tcu::TestStatus::pass("Pass");
1189                 else
1190                         return tcu::TestStatus::fail("Incorrect rasterization");
1191         }
1192         else
1193                 return tcu::TestStatus::incomplete();
1194 }
1195
1196 float PointTestInstance::getPointSize (void) const
1197 {
1198         return m_pointSizes[m_iteration];
1199 }
1200
1201 void PointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
1202 {
1203         outData.resize(6);
1204
1205         switch (iteration)
1206         {
1207                 case 0:
1208                         // \note: these values are chosen arbitrarily
1209                         outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
1210                         outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
1211                         outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
1212                         outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
1213                         outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
1214                         outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
1215                         break;
1216
1217                 case 1:
1218                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1219                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1220                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1221                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1222                         outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1223                         outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
1224                         break;
1225
1226                 case 2:
1227                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1228                         outData[1] = tcu::Vec4(  0.3f, -0.9f, 0.0f, 1.0f);
1229                         outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
1230                         outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
1231                         outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1232                         outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
1233                         break;
1234         }
1235
1236         outPoints.resize(outData.size());
1237         for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1238         {
1239                 outPoints[pointNdx].position = outData[pointNdx];
1240                 outPoints[pointNdx].pointSize = getPointSize();
1241         }
1242
1243         // log
1244         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
1245         for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1246                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
1247 }
1248
1249 template <typename ConcreteTestInstance>
1250 class BaseTestCase : public BaseRenderingTestCase
1251 {
1252 public:
1253                                                         BaseTestCase    (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1254                                                                 : BaseRenderingTestCase(context, name, description, sampleCount)
1255                                                         {}
1256
1257         virtual TestInstance*   createInstance  (Context& context) const
1258                                                         {
1259                                                                 return new ConcreteTestInstance(context, m_sampleCount);
1260                                                         }
1261 };
1262
1263 class TrianglesTestInstance : public BaseTriangleTestInstance
1264 {
1265 public:
1266                                                         TrianglesTestInstance   (Context& context, VkSampleCountFlagBits sampleCount)
1267                                                                 : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, sampleCount)
1268                                                         {}
1269
1270         void                                    generateTriangles               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1271 };
1272
1273 void TrianglesTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1274 {
1275         outData.resize(6);
1276
1277         switch (iteration)
1278         {
1279                 case 0:
1280                         // \note: these values are chosen arbitrarily
1281                         outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
1282                         outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
1283                         outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
1284                         outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
1285                         outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
1286                         outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
1287                         break;
1288
1289                 case 1:
1290                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1291                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1292                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1293                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1294                         outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1295                         outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
1296                         break;
1297
1298                 case 2:
1299                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1300                         outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1301                         outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
1302                         outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
1303                         outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1304                         outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
1305                         break;
1306         }
1307
1308         outTriangles.resize(2);
1309         outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
1310         outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = false;
1311         outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = false;
1312
1313         outTriangles[1].positions[0] = outData[3];      outTriangles[1].sharedEdge[0] = false;
1314         outTriangles[1].positions[1] = outData[4];      outTriangles[1].sharedEdge[1] = false;
1315         outTriangles[1].positions[2] = outData[5];      outTriangles[1].sharedEdge[2] = false;
1316
1317         // log
1318         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
1319         for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
1320         {
1321                 m_context.getTestContext().getLog()
1322                         << tcu::TestLog::Message
1323                         << "Triangle " << (triangleNdx+1) << ":"
1324                         << "\n\t" << outTriangles[triangleNdx].positions[0]
1325                         << "\n\t" << outTriangles[triangleNdx].positions[1]
1326                         << "\n\t" << outTriangles[triangleNdx].positions[2]
1327                         << tcu::TestLog::EndMessage;
1328         }
1329 }
1330
1331 class TriangleStripTestInstance : public BaseTriangleTestInstance
1332 {
1333 public:
1334                                 TriangleStripTestInstance               (Context& context, VkSampleCountFlagBits sampleCount)
1335                                         : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, sampleCount)
1336                                 {}
1337
1338         void            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1339 };
1340
1341 void TriangleStripTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1342 {
1343         outData.resize(5);
1344
1345         switch (iteration)
1346         {
1347                 case 0:
1348                         // \note: these values are chosen arbitrarily
1349                         outData[0] = tcu::Vec4(-0.504f,  0.8f,   0.0f, 1.0f);
1350                         outData[1] = tcu::Vec4(-0.2f,   -0.2f,   0.0f, 1.0f);
1351                         outData[2] = tcu::Vec4(-0.2f,    0.199f, 0.0f, 1.0f);
1352                         outData[3] = tcu::Vec4( 0.5f,    0.201f, 0.0f, 1.0f);
1353                         outData[4] = tcu::Vec4( 1.5f,    0.4f,   0.0f, 1.0f);
1354                         break;
1355
1356                 case 1:
1357                         outData[0] = tcu::Vec4(-0.499f, 0.129f,  0.0f, 1.0f);
1358                         outData[1] = tcu::Vec4(-0.501f,  -0.3f,  0.0f, 1.0f);
1359                         outData[2] = tcu::Vec4(  0.11f,  -0.2f,  0.0f, 1.0f);
1360                         outData[3] = tcu::Vec4(  0.11f,  -0.31f, 0.0f, 1.0f);
1361                         outData[4] = tcu::Vec4(  0.88f,   0.9f,  0.0f, 1.0f);
1362                         break;
1363
1364                 case 2:
1365                         outData[0] = tcu::Vec4( -0.9f, -0.3f,  0.0f, 1.0f);
1366                         outData[1] = tcu::Vec4(  1.1f, -0.9f,  0.0f, 1.0f);
1367                         outData[2] = tcu::Vec4(-0.87f, -0.1f,  0.0f, 1.0f);
1368                         outData[3] = tcu::Vec4(-0.11f,  0.19f, 0.0f, 1.0f);
1369                         outData[4] = tcu::Vec4( 0.88f,  0.7f,  0.0f, 1.0f);
1370                         break;
1371         }
1372
1373         outTriangles.resize(3);
1374         outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
1375         outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = true;
1376         outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = false;
1377
1378         outTriangles[1].positions[0] = outData[2];      outTriangles[1].sharedEdge[0] = true;
1379         outTriangles[1].positions[1] = outData[1];      outTriangles[1].sharedEdge[1] = false;
1380         outTriangles[1].positions[2] = outData[3];      outTriangles[1].sharedEdge[2] = true;
1381
1382         outTriangles[2].positions[0] = outData[2];      outTriangles[2].sharedEdge[0] = true;
1383         outTriangles[2].positions[1] = outData[3];      outTriangles[2].sharedEdge[1] = false;
1384         outTriangles[2].positions[2] = outData[4];      outTriangles[2].sharedEdge[2] = false;
1385
1386         // log
1387         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1388         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1389         {
1390                 m_context.getTestContext().getLog()
1391                         << tcu::TestLog::Message
1392                         << "\t" << outData[vtxNdx]
1393                         << tcu::TestLog::EndMessage;
1394         }
1395 }
1396
1397 class TriangleFanTestInstance : public BaseTriangleTestInstance
1398 {
1399 public:
1400                                 TriangleFanTestInstance                 (Context& context, VkSampleCountFlagBits sampleCount)
1401                                         : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, sampleCount)
1402                                 {}
1403
1404         void            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1405 };
1406
1407 void TriangleFanTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1408 {
1409         outData.resize(5);
1410
1411         switch (iteration)
1412         {
1413                 case 0:
1414                         // \note: these values are chosen arbitrarily
1415                         outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1416                         outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1417                         outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1418                         outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
1419                         outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
1420                         break;
1421
1422                 case 1:
1423                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1424                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1425                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1426                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1427                         outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1428                         break;
1429
1430                 case 2:
1431                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1432                         outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1433                         outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1434                         outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1435                         outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1436                         break;
1437         }
1438
1439         outTriangles.resize(3);
1440         outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
1441         outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = false;
1442         outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = true;
1443
1444         outTriangles[1].positions[0] = outData[0];      outTriangles[1].sharedEdge[0] = true;
1445         outTriangles[1].positions[1] = outData[2];      outTriangles[1].sharedEdge[1] = false;
1446         outTriangles[1].positions[2] = outData[3];      outTriangles[1].sharedEdge[2] = true;
1447
1448         outTriangles[2].positions[0] = outData[0];      outTriangles[2].sharedEdge[0] = true;
1449         outTriangles[2].positions[1] = outData[3];      outTriangles[2].sharedEdge[1] = false;
1450         outTriangles[2].positions[2] = outData[4];      outTriangles[2].sharedEdge[2] = false;
1451
1452         // log
1453         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1454         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1455         {
1456                 m_context.getTestContext().getLog()
1457                         << tcu::TestLog::Message
1458                         << "\t" << outData[vtxNdx]
1459                         << tcu::TestLog::EndMessage;
1460         }
1461 }
1462
1463 template <typename ConcreteTestInstance>
1464 class WidenessTestCase : public BaseRenderingTestCase
1465 {
1466 public:
1467                                                                 WidenessTestCase        (tcu::TestContext& context, const std::string& name, const std::string& description, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1468                                                                         : BaseRenderingTestCase(context, name, description, sampleCount)
1469                                                                         , m_wideness(wideness)
1470                                                                 {}
1471
1472         virtual TestInstance*           createInstance          (Context& context) const
1473                                                                 {
1474                                                                         return new ConcreteTestInstance(context, m_wideness, m_sampleCount);
1475                                                                 }
1476 protected:
1477         const PrimitiveWideness         m_wideness;
1478 };
1479
1480 class LinesTestInstance : public BaseLineTestInstance
1481 {
1482 public:
1483                                                                 LinesTestInstance       (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1484                                                                         : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, sampleCount)
1485                                                                 {}
1486
1487         virtual void                            generateLines           (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1488 };
1489
1490 void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1491 {
1492         outData.resize(6);
1493
1494         switch (iteration)
1495         {
1496                 case 0:
1497                         // \note: these values are chosen arbitrarily
1498                         outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1499                         outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1500                         outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1501                         outData[3] = tcu::Vec4(-0.3f,   0.2f, 0.0f, 1.0f);
1502                         outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
1503                         outData[5] = tcu::Vec4( 0.1f,   0.5f, 0.0f, 1.0f);
1504                         break;
1505
1506                 case 1:
1507                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1508                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1509                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1510                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1511                         outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1512                         outData[5] = tcu::Vec4(  0.18f,  -0.2f, 0.0f, 1.0f);
1513                         break;
1514
1515                 case 2:
1516                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1517                         outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1518                         outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1519                         outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1520                         outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1521                         outData[5] = tcu::Vec4(  0.8f, -0.7f, 0.0f, 1.0f);
1522                         break;
1523         }
1524
1525         outLines.resize(3);
1526         outLines[0].positions[0] = outData[0];
1527         outLines[0].positions[1] = outData[1];
1528         outLines[1].positions[0] = outData[2];
1529         outLines[1].positions[1] = outData[3];
1530         outLines[2].positions[0] = outData[4];
1531         outLines[2].positions[1] = outData[5];
1532
1533         // log
1534         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
1535         for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
1536         {
1537                 m_context.getTestContext().getLog()
1538                         << tcu::TestLog::Message
1539                         << "Line " << (lineNdx+1) << ":"
1540                         << "\n\t" << outLines[lineNdx].positions[0]
1541                         << "\n\t" << outLines[lineNdx].positions[1]
1542                         << tcu::TestLog::EndMessage;
1543         }
1544 }
1545
1546 class LineStripTestInstance : public BaseLineTestInstance
1547 {
1548 public:
1549                                         LineStripTestInstance   (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1550                                                 : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, sampleCount)
1551                                         {}
1552
1553         virtual void    generateLines                   (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1554 };
1555
1556 void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1557 {
1558         outData.resize(4);
1559
1560         switch (iteration)
1561         {
1562                 case 0:
1563                         // \note: these values are chosen arbitrarily
1564                         outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1565                         outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1566                         outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1567                         outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
1568                         break;
1569
1570                 case 1:
1571                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1572                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1573                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1574                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1575                         break;
1576
1577                 case 2:
1578                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1579                         outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1580                         outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1581                         outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1582                         break;
1583         }
1584
1585         outLines.resize(3);
1586         outLines[0].positions[0] = outData[0];
1587         outLines[0].positions[1] = outData[1];
1588         outLines[1].positions[0] = outData[1];
1589         outLines[1].positions[1] = outData[2];
1590         outLines[2].positions[0] = outData[2];
1591         outLines[2].positions[1] = outData[3];
1592
1593         // log
1594         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1595         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1596         {
1597                 m_context.getTestContext().getLog()
1598                         << tcu::TestLog::Message
1599                         << "\t" << outData[vtxNdx]
1600                         << tcu::TestLog::EndMessage;
1601         }
1602 }
1603
1604 class FillRuleTestInstance : public BaseRenderingTestInstance
1605 {
1606 public:
1607         enum FillRuleCaseType
1608         {
1609                 FILLRULECASE_BASIC = 0,
1610                 FILLRULECASE_REVERSED,
1611                 FILLRULECASE_CLIPPED_FULL,
1612                 FILLRULECASE_CLIPPED_PARTIAL,
1613                 FILLRULECASE_PROJECTED,
1614
1615                 FILLRULECASE_LAST
1616         };
1617                                                                                                                 FillRuleTestInstance                    (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount);
1618         virtual tcu::TestStatus                                                         iterate                                                 (void);
1619
1620 private:
1621
1622         virtual const VkPipelineColorBlendStateCreateInfo*      getColorBlendStateCreateInfo    (void) const;
1623         int                                                                                                     getRenderSize                                   (FillRuleCaseType type) const;
1624         int                                                                                                     getNumIterations                                (FillRuleCaseType type) const;
1625         void                                                                                            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData) const;
1626
1627         const FillRuleCaseType                                                          m_caseType;
1628         int                                                                                                     m_iteration;
1629         const int                                                                                       m_iterationCount;
1630         bool                                                                                            m_allIterationsPassed;
1631
1632 };
1633
1634 FillRuleTestInstance::FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount)
1635         : BaseRenderingTestInstance             (context, sampleCount, getRenderSize(type))
1636         , m_caseType                                    (type)
1637         , m_iteration                                   (0)
1638         , m_iterationCount                              (getNumIterations(type))
1639         , m_allIterationsPassed                 (true)
1640 {
1641         DE_ASSERT(type < FILLRULECASE_LAST);
1642 }
1643
1644 tcu::TestStatus FillRuleTestInstance::iterate (void)
1645 {
1646         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1647         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1648         tcu::IVec4                                                              colorBits                               = tcu::getTextureFormatBitDepth(getTextureFormat());
1649         const int                                                               thresholdRed                    = 1 << (8 - colorBits[0]);
1650         const int                                                               thresholdGreen                  = 1 << (8 - colorBits[1]);
1651         const int                                                               thresholdBlue                   = 1 << (8 - colorBits[2]);
1652         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
1653         std::vector<tcu::Vec4>                                  drawBuffer;
1654
1655         generateTriangles(m_iteration, drawBuffer);
1656
1657         // draw image
1658         {
1659                 const std::vector<tcu::Vec4>    colorBuffer             (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
1660
1661                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
1662
1663                 drawPrimitives(resultImage, drawBuffer, colorBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1664         }
1665
1666         // verify no overdraw
1667         {
1668                 const tcu::RGBA triangleColor   = tcu::RGBA(127, 127, 127, 255);
1669                 bool                    overdraw                = false;
1670
1671                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
1672
1673                 for (int y = 0; y < resultImage.getHeight(); ++y)
1674                 for (int x = 0; x < resultImage.getWidth();  ++x)
1675                 {
1676                         const tcu::RGBA color = resultImage.getPixel(x, y);
1677
1678                         // color values are greater than triangle color? Allow lower values for multisampled edges and background.
1679                         if ((color.getRed()   - triangleColor.getRed())   > thresholdRed   ||
1680                                 (color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
1681                                 (color.getBlue()  - triangleColor.getBlue())  > thresholdBlue)
1682                                 overdraw = true;
1683                 }
1684
1685                 // results
1686                 if (!overdraw)
1687                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
1688                 else
1689                 {
1690                         m_context.getTestContext().getLog()     << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1691                         m_allIterationsPassed = false;
1692                 }
1693         }
1694
1695         // verify no missing fragments in the full viewport case
1696         if (m_caseType == FILLRULECASE_CLIPPED_FULL)
1697         {
1698                 bool missingFragments = false;
1699
1700                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
1701
1702                 for (int y = 0; y < resultImage.getHeight(); ++y)
1703                 for (int x = 0; x < resultImage.getWidth();  ++x)
1704                 {
1705                         const tcu::RGBA color = resultImage.getPixel(x, y);
1706
1707                         // black? (background)
1708                         if (color.getRed()   <= thresholdRed   ||
1709                                 color.getGreen() <= thresholdGreen ||
1710                                 color.getBlue()  <= thresholdBlue)
1711                                 missingFragments = true;
1712                 }
1713
1714                 // results
1715                 if (!missingFragments)
1716                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
1717                 else
1718                 {
1719                         m_context.getTestContext().getLog()     << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1720
1721                         m_allIterationsPassed = false;
1722                 }
1723         }
1724
1725         m_context.getTestContext().getLog()     << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1726                                                                                 << tcu::TestLog::Image("Result", "Result", resultImage)
1727                                                                                 << tcu::TestLog::EndImageSet;
1728
1729         // result
1730         if (++m_iteration == m_iterationCount)
1731         {
1732                 if (m_allIterationsPassed)
1733                         return tcu::TestStatus::pass("Pass");
1734                 else
1735                         return tcu::TestStatus::fail("Found invalid pixels");
1736         }
1737         else
1738                 return tcu::TestStatus::incomplete();
1739 }
1740
1741 int FillRuleTestInstance::getRenderSize (FillRuleCaseType type) const
1742 {
1743         if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1744                 return DEFAULT_RENDER_SIZE / 4;
1745         else
1746                 return DEFAULT_RENDER_SIZE;
1747 }
1748
1749 int FillRuleTestInstance::getNumIterations (FillRuleCaseType type) const
1750 {
1751         if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1752                 return 15;
1753         else
1754                 return 2;
1755 }
1756
1757 void FillRuleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
1758 {
1759         switch (m_caseType)
1760         {
1761                 case FILLRULECASE_BASIC:
1762                 case FILLRULECASE_REVERSED:
1763                 case FILLRULECASE_PROJECTED:
1764                 {
1765                         const int       numRows         = 4;
1766                         const int       numColumns      = 4;
1767                         const float     quadSide        = 0.15f;
1768                         de::Random      rnd                     (0xabcd);
1769
1770                         outData.resize(6 * numRows * numColumns);
1771
1772                         for (int col = 0; col < numColumns; ++col)
1773                         for (int row = 0; row < numRows;    ++row)
1774                         {
1775                                 const tcu::Vec2 center          = tcu::Vec2(((float)row + 0.5f) / (float)numRows * 2.0f - 1.0f, ((float)col + 0.5f) / (float)numColumns * 2.0f - 1.0f);
1776                                 const float             rotation        = (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
1777                                 const tcu::Vec2 sideH           = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1778                                 const tcu::Vec2 sideV           = tcu::Vec2(sideH.y(), -sideH.x());
1779                                 const tcu::Vec2 quad[4]         =
1780                                 {
1781                                         center + sideH + sideV,
1782                                         center + sideH - sideV,
1783                                         center - sideH - sideV,
1784                                         center - sideH + sideV,
1785                                 };
1786
1787                                 if (m_caseType == FILLRULECASE_BASIC)
1788                                 {
1789                                         outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1790                                         outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1791                                         outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1792                                         outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1793                                         outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1794                                         outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1795                                 }
1796                                 else if (m_caseType == FILLRULECASE_REVERSED)
1797                                 {
1798                                         outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1799                                         outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1800                                         outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1801                                         outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1802                                         outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1803                                         outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1804                                 }
1805                                 else if (m_caseType == FILLRULECASE_PROJECTED)
1806                                 {
1807                                         const float w0 = rnd.getFloat(0.1f, 4.0f);
1808                                         const float w1 = rnd.getFloat(0.1f, 4.0f);
1809                                         const float w2 = rnd.getFloat(0.1f, 4.0f);
1810                                         const float w3 = rnd.getFloat(0.1f, 4.0f);
1811
1812                                         outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1813                                         outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
1814                                         outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1815                                         outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1816                                         outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1817                                         outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
1818                                 }
1819                                 else
1820                                         DE_ASSERT(DE_FALSE);
1821                         }
1822
1823                         break;
1824                 }
1825
1826                 case FILLRULECASE_CLIPPED_PARTIAL:
1827                 case FILLRULECASE_CLIPPED_FULL:
1828                 {
1829                         const float             quadSide        = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
1830                         const tcu::Vec2 center          = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
1831                         const float             rotation        = (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
1832                         const tcu::Vec2 sideH           = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1833                         const tcu::Vec2 sideV           = tcu::Vec2(sideH.y(), -sideH.x());
1834                         const tcu::Vec2 quad[4]         =
1835                         {
1836                                 center + sideH + sideV,
1837                                 center + sideH - sideV,
1838                                 center - sideH - sideV,
1839                                 center - sideH + sideV,
1840                         };
1841
1842                         outData.resize(6);
1843                         outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1844                         outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1845                         outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1846                         outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1847                         outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1848                         outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1849                         break;
1850                 }
1851
1852                 default:
1853                         DE_ASSERT(DE_FALSE);
1854         }
1855 }
1856
1857 const VkPipelineColorBlendStateCreateInfo* FillRuleTestInstance::getColorBlendStateCreateInfo (void) const
1858 {
1859         static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1860         {
1861                 true,                                                                                                           // VkBool32                     blendEnable;
1862                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendColor;
1863                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      destBlendColor;
1864                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpColor;
1865                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendAlpha;
1866                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      destBlendAlpha;
1867                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpAlpha;
1868                 (VK_COLOR_COMPONENT_R_BIT |
1869                  VK_COLOR_COMPONENT_G_BIT |
1870                  VK_COLOR_COMPONENT_B_BIT |
1871                  VK_COLOR_COMPONENT_A_BIT)                                                                      // VkChannelFlags       channelWriteMask;
1872         };
1873
1874         static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1875         {
1876                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
1877                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
1878                 0,                                                                                                                      // VkPipelineColorBlendStateCreateFlags                 flags;
1879                 false,                                                                                                          // VkBool32                                                                             logicOpEnable;
1880                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
1881                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
1882                 &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
1883                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConst[4];
1884         };
1885
1886         return &colorBlendStateParams;
1887 }
1888
1889
1890 class FillRuleTestCase : public BaseRenderingTestCase
1891 {
1892 public:
1893                                                                 FillRuleTestCase        (tcu::TestContext& context, const std::string& name, const std::string& description, FillRuleTestInstance::FillRuleCaseType type, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1894                                                                         : BaseRenderingTestCase (context, name, description, sampleCount)
1895                                                                         , m_type                                (type)
1896                                                                 {}
1897
1898         virtual TestInstance*           createInstance          (Context& context) const
1899                                                                 {
1900                                                                         return new FillRuleTestInstance(context, m_type, m_sampleCount);
1901                                                                 }
1902 protected:
1903         const FillRuleTestInstance::FillRuleCaseType m_type;
1904 };
1905
1906 class CullingTestInstance : public BaseRenderingTestInstance
1907 {
1908 public:
1909                                                                                                         CullingTestInstance                             (Context& context, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode)
1910                                                                                                                 : BaseRenderingTestInstance             (context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
1911                                                                                                                 , m_cullMode                                    (cullMode)
1912                                                                                                                 , m_primitiveTopology                   (primitiveTopology)
1913                                                                                                                 , m_frontFace                                   (frontFace)
1914                                                                                                                 , m_polygonMode                                 (polygonMode)
1915                                                                                                                 , m_multisampling                               (true)
1916                                                                                                         {}
1917         virtual
1918         const VkPipelineRasterizationStateCreateInfo*   getRasterizationStateCreateInfo (void) const;
1919
1920         tcu::TestStatus                                                                 iterate                                                 (void);
1921
1922 private:
1923         void                                                                                    generateVertices                                (std::vector<tcu::Vec4>& outData) const;
1924         void                                                                                    extractTriangles                                (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
1925         void                                                                                    extractLines                                    (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<LineSceneSpec::SceneLine>& outLines) const;
1926         void                                                                                    extractPoints                                   (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<PointSceneSpec::ScenePoint>& outPoints) const;
1927         bool                                                                                    triangleOrder                                   (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
1928
1929         const VkCullModeFlags                                                   m_cullMode;
1930         const VkPrimitiveTopology                                               m_primitiveTopology;
1931         const VkFrontFace                                                               m_frontFace;
1932         const VkPolygonMode                                                             m_polygonMode;
1933         const bool                                                                              m_multisampling;
1934 };
1935
1936
1937 tcu::TestStatus CullingTestInstance::iterate (void)
1938 {
1939         DE_ASSERT(m_polygonMode <= VK_POLYGON_MODE_POINT);
1940
1941         tcu::Surface                                                                    resultImage                                             (m_renderSize, m_renderSize);
1942         std::vector<tcu::Vec4>                                                  drawBuffer;
1943         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
1944         std::vector<PointSceneSpec::ScenePoint>                 points;
1945         std::vector<LineSceneSpec::SceneLine>                   lines;
1946
1947         const InstanceInterface&                                                vk                              = m_context.getInstanceInterface();
1948         const VkPhysicalDevice                                                  physicalDevice  = m_context.getPhysicalDevice();
1949         const VkPhysicalDeviceFeatures                                  deviceFeatures  = getPhysicalDeviceFeatures(vk, physicalDevice);
1950
1951         if (!(deviceFeatures.fillModeNonSolid) && (m_polygonMode == VK_POLYGON_MODE_LINE || m_polygonMode == VK_POLYGON_MODE_POINT))
1952                 TCU_THROW(NotSupportedError, "Wireframe fill modes are not supported");
1953
1954         // generate scene
1955         generateVertices(drawBuffer);
1956         extractTriangles(triangles, drawBuffer);
1957
1958         if (m_polygonMode == VK_POLYGON_MODE_LINE)
1959                 extractLines(triangles ,lines);
1960         else if (m_polygonMode == VK_POLYGON_MODE_POINT)
1961                 extractPoints(triangles, points);
1962
1963         // draw image
1964         {
1965                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting front face to " << m_frontFace << tcu::TestLog::EndMessage;
1966                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting cull face to " << m_cullMode << tcu::TestLog::EndMessage;
1967                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing test pattern (" << m_primitiveTopology << ")" << tcu::TestLog::EndMessage;
1968
1969                 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1970         }
1971
1972         // compare
1973         {
1974                 RasterizationArguments  args;
1975                 tcu::IVec4                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
1976                 bool                                    isCompareOk     = false;
1977
1978                 args.numSamples         = m_multisampling ? 1 : 0;
1979                 args.subpixelBits       = m_subpixelBits;
1980                 args.redBits            = colorBits[0];
1981                 args.greenBits          = colorBits[1];
1982                 args.blueBits           = colorBits[2];
1983
1984                 switch (m_polygonMode)
1985                 {
1986                         case VK_POLYGON_MODE_LINE:
1987                         {
1988                                 LineSceneSpec scene;
1989                                 scene.lineWidth = 0;
1990                                 scene.lines.swap(lines);
1991                                 isCompareOk = verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1992                                 break;
1993                         }
1994                         case VK_POLYGON_MODE_POINT:
1995                         {
1996                                 PointSceneSpec scene;
1997                                 scene.points.swap(points);
1998                                 isCompareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1999                                 break;
2000                         }
2001                         default:
2002                         {
2003                                 TriangleSceneSpec scene;
2004                                 scene.triangles.swap(triangles);
2005                                 isCompareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), tcu::VERIFICATIONMODE_WEAK);
2006                                 break;
2007                         }
2008                 }
2009
2010                 if (isCompareOk)
2011                         return tcu::TestStatus::pass("Pass");
2012                 else
2013                         return tcu::TestStatus::fail("Incorrect rendering");
2014         }
2015 }
2016
2017 void CullingTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
2018 {
2019         de::Random rnd(543210);
2020
2021         outData.resize(6);
2022         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
2023         {
2024                 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2025                 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2026                 outData[vtxNdx].z() = 0.0f;
2027                 outData[vtxNdx].w() = 1.0f;
2028         }
2029 }
2030
2031 void CullingTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
2032 {
2033         const bool cullDirection = (m_cullMode == VK_CULL_MODE_FRONT_BIT) ^ (m_frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
2034
2035         // No triangles
2036         if (m_cullMode == VK_CULL_MODE_FRONT_AND_BACK)
2037                 return;
2038
2039         switch (m_primitiveTopology)
2040         {
2041                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2042                 {
2043                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2044                         {
2045                                 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
2046                                 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
2047                                 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
2048
2049                                 if (triangleOrder(v0, v1, v2) != cullDirection)
2050                                 {
2051                                         TriangleSceneSpec::SceneTriangle tri;
2052                                         tri.positions[0] = v0;  tri.sharedEdge[0] = false;
2053                                         tri.positions[1] = v1;  tri.sharedEdge[1] = false;
2054                                         tri.positions[2] = v2;  tri.sharedEdge[2] = false;
2055
2056                                         outTriangles.push_back(tri);
2057                                 }
2058                         }
2059                         break;
2060                 }
2061
2062                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2063                 {
2064                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2065                         {
2066                                 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
2067                                 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
2068                                 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
2069
2070                                 if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
2071                                 {
2072                                         TriangleSceneSpec::SceneTriangle tri;
2073                                         tri.positions[0] = v0;  tri.sharedEdge[0] = false;
2074                                         tri.positions[1] = v1;  tri.sharedEdge[1] = false;
2075                                         tri.positions[2] = v2;  tri.sharedEdge[2] = false;
2076
2077                                         outTriangles.push_back(tri);
2078                                 }
2079                         }
2080                         break;
2081                 }
2082
2083                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2084                 {
2085                         for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2086                         {
2087                                 const tcu::Vec4& v0 = vertices[0];
2088                                 const tcu::Vec4& v1 = vertices[vtxNdx + 0];
2089                                 const tcu::Vec4& v2 = vertices[vtxNdx + 1];
2090
2091                                 if (triangleOrder(v0, v1, v2) != cullDirection)
2092                                 {
2093                                         TriangleSceneSpec::SceneTriangle tri;
2094                                         tri.positions[0] = v0;  tri.sharedEdge[0] = false;
2095                                         tri.positions[1] = v1;  tri.sharedEdge[1] = false;
2096                                         tri.positions[2] = v2;  tri.sharedEdge[2] = false;
2097
2098                                         outTriangles.push_back(tri);
2099                                 }
2100                         }
2101                         break;
2102                 }
2103
2104                 default:
2105                         DE_ASSERT(false);
2106         }
2107 }
2108
2109 void CullingTestInstance::extractLines (std::vector<TriangleSceneSpec::SceneTriangle>&  outTriangles,
2110                                                                                 std::vector<LineSceneSpec::SceneLine>&                  outLines) const
2111 {
2112         for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
2113         {
2114                 for (int vrtxNdx = 0; vrtxNdx < 2; ++vrtxNdx)
2115                 {
2116                         LineSceneSpec::SceneLine line;
2117                         line.positions[0] = outTriangles.at(triNdx).positions[vrtxNdx];
2118                         line.positions[1] = outTriangles.at(triNdx).positions[vrtxNdx + 1];
2119
2120                         outLines.push_back(line);
2121                 }
2122                 LineSceneSpec::SceneLine line;
2123                 line.positions[0] = outTriangles.at(triNdx).positions[2];
2124                 line.positions[1] = outTriangles.at(triNdx).positions[0];
2125                 outLines.push_back(line);
2126         }
2127 }
2128
2129 void CullingTestInstance::extractPoints (std::vector<TriangleSceneSpec::SceneTriangle>  &outTriangles,
2130                                                                                 std::vector<PointSceneSpec::ScenePoint>                 &outPoints) const
2131 {
2132         for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
2133         {
2134                 for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
2135                 {
2136                         PointSceneSpec::ScenePoint point;
2137                         point.position = outTriangles.at(triNdx).positions[vrtxNdx];
2138                         point.pointSize = 1.0f;
2139
2140                         outPoints.push_back(point);
2141                 }
2142         }
2143 }
2144
2145 bool CullingTestInstance::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
2146 {
2147         const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
2148         const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
2149         const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
2150
2151         // cross
2152         return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) > 0;
2153 }
2154
2155
2156 const VkPipelineRasterizationStateCreateInfo* CullingTestInstance::getRasterizationStateCreateInfo (void) const
2157 {
2158         static VkPipelineRasterizationStateCreateInfo   rasterizationStateCreateInfo    =
2159         {
2160                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
2161                 DE_NULL,                                                                                                                // const void*                                                          pNext;
2162                 0,                                                                                                                              // VkPipelineRasterizationStateCreateFlags      flags;
2163                 false,                                                                                                                  // VkBool32                                                                     depthClipEnable;
2164                 false,                                                                                                                  // VkBool32                                                                     rasterizerDiscardEnable;
2165                 VK_POLYGON_MODE_FILL,                                                                                   // VkFillMode                                                           fillMode;
2166                 VK_CULL_MODE_NONE,                                                                                              // VkCullMode                                                           cullMode;
2167                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
2168                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
2169                 0.0f,                                                                                                                   // float                                                                        depthBias;
2170                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
2171                 0.0f,                                                                                                                   // float                                                                        slopeScaledDepthBias;
2172                 getLineWidth(),                                                                                                 // float                                                                        lineWidth;
2173         };
2174
2175         rasterizationStateCreateInfo.lineWidth          = getLineWidth();
2176         rasterizationStateCreateInfo.cullMode           = m_cullMode;
2177         rasterizationStateCreateInfo.frontFace          = m_frontFace;
2178         rasterizationStateCreateInfo.polygonMode        = m_polygonMode;
2179
2180         return &rasterizationStateCreateInfo;
2181 }
2182
2183 class CullingTestCase : public BaseRenderingTestCase
2184 {
2185 public:
2186                                                                 CullingTestCase         (tcu::TestContext& context, const std::string& name, const std::string& description, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2187                                                                         : BaseRenderingTestCase (context, name, description, sampleCount)
2188                                                                         , m_cullMode                    (cullMode)
2189                                                                         , m_primitiveTopology   (primitiveTopology)
2190                                                                         , m_frontFace                   (frontFace)
2191                                                                         , m_polygonMode                 (polygonMode)
2192                                                                 {}
2193
2194         virtual TestInstance*           createInstance          (Context& context) const
2195                                                                 {
2196                                                                         return new CullingTestInstance(context, m_cullMode, m_primitiveTopology, m_frontFace, m_polygonMode);
2197                                                                 }
2198 protected:
2199         const VkCullModeFlags           m_cullMode;
2200         const VkPrimitiveTopology       m_primitiveTopology;
2201         const VkFrontFace                       m_frontFace;
2202         const VkPolygonMode                     m_polygonMode;
2203 };
2204
2205 class DiscardTestInstance : public BaseRenderingTestInstance
2206 {
2207 public:
2208                                                                                                                         DiscardTestInstance                                     (Context& context, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations)
2209                                                                                                                                 : BaseRenderingTestInstance                     (context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
2210                                                                                                                                 , m_primitiveTopology                           (primitiveTopology)
2211                                                                                                                                 , m_queryFragmentShaderInvocations      (queryFragmentShaderInvocations)
2212                                                                                                                         {}
2213
2214         virtual const VkPipelineRasterizationStateCreateInfo*   getRasterizationStateCreateInfo         (void) const;
2215         tcu::TestStatus                                                                                 iterate                                                         (void);
2216
2217 private:
2218         void                                                                                                    generateVertices                                        (std::vector<tcu::Vec4>& outData) const;
2219         void                                                                                                    extractTriangles                                        (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
2220         void                                                                                                    extractLines                                            (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const;
2221         void                                                                                                    extractPoints                                           (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const;
2222         void                                                                                                    drawPrimitives                                          (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool);
2223
2224         const VkPrimitiveTopology                                                               m_primitiveTopology;
2225         const deBool                                                                                    m_queryFragmentShaderInvocations;
2226 };
2227
2228 tcu::TestStatus DiscardTestInstance::iterate (void)
2229 {
2230         const DeviceInterface&                                                  vkd                     = m_context.getDeviceInterface();
2231         const VkDevice                                                                  vkDevice        = m_context.getDevice();
2232         deUint64                                                                                queryResult     = 0u;
2233         tcu::Surface                                                                    resultImage     (m_renderSize, m_renderSize);
2234         std::vector<tcu::Vec4>                                                  drawBuffer;
2235         std::vector<PointSceneSpec::ScenePoint>                 points;
2236         std::vector<LineSceneSpec::SceneLine>                   lines;
2237         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
2238
2239         generateVertices(drawBuffer);
2240
2241         switch (m_primitiveTopology)
2242         {
2243                 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2244                         extractPoints(points, drawBuffer);
2245                         break;
2246
2247                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2248                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2249                         extractLines(lines, drawBuffer);
2250                         break;
2251
2252                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2253                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2254                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2255                         extractTriangles(triangles, drawBuffer);
2256                         break;
2257
2258                 default:
2259                         DE_ASSERT(false);
2260         }
2261
2262         const VkQueryPoolCreateInfo queryPoolCreateInfo =
2263         {
2264                 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,                                               // VkStructureType                                      sType
2265                 DE_NULL,                                                                                                                // const void*                                          pNext
2266                 (VkQueryPoolCreateFlags)0,                                                                              // VkQueryPoolCreateFlags                       flags
2267                 VK_QUERY_TYPE_PIPELINE_STATISTICS ,                                                             // VkQueryType                                          queryType
2268                 1u,                                                                                                                             // deUint32                                                     entryCount
2269                 VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT,    // VkQueryPipelineStatisticFlags        pipelineStatistics
2270         };
2271
2272         if (m_queryFragmentShaderInvocations)
2273         {
2274                 Move<VkQueryPool> queryPool     = createQueryPool(vkd, vkDevice, &queryPoolCreateInfo);
2275
2276                 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology, queryPool);
2277                 vkd.getQueryPoolResults(vkDevice, *queryPool, 0u, 1u, sizeof(deUint64), &queryResult, 0u, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
2278         }
2279         else
2280                 BaseRenderingTestInstance::drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
2281
2282         // compare
2283         {
2284                 tcu::IVec4                                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
2285
2286                 const RasterizationArguments    args            =
2287                 {
2288                         0,                                                      // int  numSamples;
2289                         (int)m_subpixelBits,            // int  subpixelBits;
2290                         colorBits[0],                           // int  redBits;
2291                         colorBits[1],                           // int  greenBits;
2292                         colorBits[2]                            // int  blueBits;
2293                 };
2294
2295                 // Empty scene to compare to, primitives should be discarded before rasterization
2296                 TriangleSceneSpec                               scene;
2297
2298                 const bool                                              isCompareOk     = verifyTriangleGroupRasterization(resultImage,
2299                                                                                                                                                                            scene,
2300                                                                                                                                                                            args,
2301                                                                                                                                                                            m_context.getTestContext().getLog(),
2302                                                                                                                                                                            tcu::VERIFICATIONMODE_STRICT);
2303
2304                 if (isCompareOk)
2305                 {
2306                         if (m_queryFragmentShaderInvocations && queryResult > 0u)
2307                                 return tcu::TestStatus::fail("Fragment shader invocations occured");
2308                         else
2309                                 return tcu::TestStatus::pass("Pass");
2310                 }
2311                 else
2312                         return tcu::TestStatus::fail("Incorrect rendering");
2313         }
2314 }
2315
2316 void DiscardTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
2317 {
2318         de::Random rnd(12345);
2319
2320         outData.resize(6);
2321
2322         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
2323         {
2324                 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2325                 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2326                 outData[vtxNdx].z() = 0.0f;
2327                 outData[vtxNdx].w() = 1.0f;
2328         }
2329 }
2330
2331 void DiscardTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
2332 {
2333         switch (m_primitiveTopology)
2334         {
2335                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2336                 {
2337                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2338                         {
2339                                 TriangleSceneSpec::SceneTriangle        tri;
2340                                 const tcu::Vec4&                                        v0      = vertices[vtxNdx + 0];
2341                                 const tcu::Vec4&                                        v1      = vertices[vtxNdx + 1];
2342                                 const tcu::Vec4&                                        v2      = vertices[vtxNdx + 2];
2343
2344                                 tri.positions[0] = v0;
2345                                 tri.positions[1] = v1;
2346                                 tri.positions[2] = v2;
2347
2348                                 outTriangles.push_back(tri);
2349                         }
2350
2351                         break;
2352                 }
2353
2354                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2355                 {
2356                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2357                         {
2358                                 TriangleSceneSpec::SceneTriangle        tri;
2359                                 const tcu::Vec4&                                        v0      = vertices[vtxNdx + 0];
2360                                 const tcu::Vec4&                                        v1      = vertices[vtxNdx + 1];
2361                                 const tcu::Vec4&                                        v2      = vertices[vtxNdx + 2];
2362
2363                                 tri.positions[0] = v0;
2364                                 tri.positions[1] = v1;
2365                                 tri.positions[2] = v2;
2366
2367                                 outTriangles.push_back(tri);
2368                         }
2369
2370                         break;
2371                 }
2372
2373                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2374                 {
2375                         for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2376                         {
2377                                 TriangleSceneSpec::SceneTriangle        tri;
2378                                 const tcu::Vec4&                                        v0      = vertices[0];
2379                                 const tcu::Vec4&                                        v1      = vertices[vtxNdx + 0];
2380                                 const tcu::Vec4&                                        v2      = vertices[vtxNdx + 1];
2381
2382                                 tri.positions[0] = v0;
2383                                 tri.positions[1] = v1;
2384                                 tri.positions[2] = v2;
2385
2386                                 outTriangles.push_back(tri);
2387                         }
2388
2389                         break;
2390                 }
2391
2392                 default:
2393                         DE_ASSERT(false);
2394         }
2395 }
2396
2397 void DiscardTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const
2398 {
2399         switch (m_primitiveTopology)
2400         {
2401                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2402                 {
2403                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
2404                         {
2405                                 LineSceneSpec::SceneLine line;
2406
2407                                 line.positions[0] = vertices[vtxNdx + 0];
2408                                 line.positions[1] = vertices[vtxNdx + 1];
2409
2410                                 outLines.push_back(line);
2411                         }
2412
2413                         break;
2414                 }
2415
2416                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2417                 {
2418                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2419                         {
2420                                 LineSceneSpec::SceneLine line;
2421
2422                                 line.positions[0] = vertices[vtxNdx + 0];
2423                                 line.positions[1] = vertices[vtxNdx + 1];
2424
2425                                 outLines.push_back(line);
2426                         }
2427
2428                         break;
2429                 }
2430
2431                 default:
2432                         DE_ASSERT(false);
2433                 }
2434 }
2435
2436 void DiscardTestInstance::extractPoints (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const
2437 {
2438         for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
2439         {
2440                 for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
2441                 {
2442                         PointSceneSpec::ScenePoint point;
2443
2444                         point.position  = vertices[vrtxNdx];
2445                         point.pointSize = 1.0f;
2446
2447                         outPoints.push_back(point);
2448                 }
2449         }
2450 }
2451
2452 const VkPipelineRasterizationStateCreateInfo* DiscardTestInstance::getRasterizationStateCreateInfo (void) const
2453 {
2454         static const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
2455         {
2456                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
2457                 NULL,                                                                                                           // const void*                                                          pNext;
2458                 0,                                                                                                                      // VkPipelineRasterizationStateCreateFlags      flags;
2459                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthClipEnable;
2460                 VK_TRUE,                                                                                                        // VkBool32                                                                     rasterizerDiscardEnable;
2461                 VK_POLYGON_MODE_FILL,                                                                           // VkFillMode                                                           fillMode;
2462                 VK_CULL_MODE_NONE,                                                                                      // VkCullMode                                                           cullMode;
2463                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
2464                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable;
2465                 0.0f,                                                                                                           // float                                                                        depthBias;
2466                 0.0f,                                                                                                           // float                                                                        depthBiasClamp;
2467                 0.0f,                                                                                                           // float                                                                        slopeScaledDepthBias;
2468                 getLineWidth(),                                                                                         // float                                                                        lineWidth;
2469         };
2470
2471         return &rasterizationStateCreateInfo;
2472 }
2473
2474 void DiscardTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool)
2475 {
2476         const DeviceInterface&                          vkd                                     = m_context.getDeviceInterface();
2477         const VkDevice                                          vkDevice                        = m_context.getDevice();
2478         const VkPhysicalDeviceProperties        properties                      = m_context.getDeviceProperties();
2479         const VkQueue                                           queue                           = m_context.getUniversalQueue();
2480         const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
2481         Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
2482
2483         const size_t                                            attributeBatchSize      = positionData.size() * sizeof(tcu::Vec4);
2484         const VkDeviceSize                                      vertexBufferOffset      = 0;
2485         de::MovePtr<Allocation>                         vertexBufferMemory;
2486         Move<VkBuffer>                                          vertexBuffer;
2487         Move<VkCommandBuffer>                           commandBuffer;
2488         Move<VkPipeline>                                        graphicsPipeline;
2489
2490         if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
2491         {
2492                 std::stringstream message;
2493                 message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
2494                 TCU_THROW(NotSupportedError, message.str().c_str());
2495         }
2496
2497         // Create Graphics Pipeline
2498         {
2499                 const VkVertexInputBindingDescription           vertexInputBindingDescription           =
2500                 {
2501                         0u,                                                                             // deUint32                                     binding;
2502                         sizeof(tcu::Vec4),                                              // deUint32                                     strideInBytes;
2503                         VK_VERTEX_INPUT_RATE_VERTEX                             // VkVertexInputStepRate        stepRate;
2504                 };
2505
2506                 const VkVertexInputAttributeDescription         vertexInputAttributeDescriptions[2]     =
2507                 {
2508                         {
2509                                 0u,                                                                     // deUint32     location;
2510                                 0u,                                                                     // deUint32     binding;
2511                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
2512                                 0u                                                                      // deUint32     offsetInBytes;
2513                         },
2514                         {
2515                                 1u,                                                                     // deUint32     location;
2516                                 0u,                                                                     // deUint32     binding;
2517                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
2518                                 (deUint32)attributeBatchSize            // deUint32     offsetInBytes;
2519                         }
2520                 };
2521
2522                 const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams                          =
2523                 {
2524                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
2525                         DE_NULL,                                                                                                        // const void*                                                          pNext;
2526                         0,                                                                                                                      // VkPipelineVertexInputStateCreateFlags        flags;
2527                         1u,                                                                                                                     // deUint32                                                                     bindingCount;
2528                         &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
2529                         2u,                                                                                                                     // deUint32                                                                     attributeCount;
2530                         vertexInputAttributeDescriptions                                                        // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
2531                 };
2532
2533                 const std::vector<VkViewport>                           viewports                                                       (1, makeViewport(tcu::UVec2(m_renderSize)));
2534                 const std::vector<VkRect2D>                                     scissors                                                        (1, makeRect2D(tcu::UVec2(m_renderSize)));
2535
2536                 const VkPipelineMultisampleStateCreateInfo      multisampleStateParams                          =
2537                 {
2538                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
2539                         DE_NULL,                                                                                                        // const void*                                                          pNext;
2540                         0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
2541                         m_sampleCount,                                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
2542                         VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
2543                         0.0f,                                                                                                           // float                                                                        minSampleShading;
2544                         DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
2545                         VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
2546                         VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
2547                 };
2548
2549                 graphicsPipeline = makeGraphicsPipeline(vkd,                                                            // const DeviceInterface&                                                       vk
2550                                                                                                 vkDevice,                                                       // const VkDevice                                                                       device
2551                                                                                                 *m_pipelineLayout,                                      // const VkPipelineLayout                                                       pipelineLayout
2552                                                                                                 *m_vertexShaderModule,                          // const VkShaderModule                                                         vertexShaderModule
2553                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                         tessellationControlShaderModule
2554                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                         tessellationEvalShaderModule
2555                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                         geometryShaderModule
2556                                                                                                 *m_fragmentShaderModule,                        // const VkShaderModule                                                         fragmentShaderModule
2557                                                                                                 *m_renderPass,                                          // const VkRenderPass                                                           renderPass
2558                                                                                                 viewports,                                                      // const std::vector<VkViewport>&                                       viewports
2559                                                                                                 scissors,                                                       // const std::vector<VkRect2D>&                                         scissors
2560                                                                                                 primitiveTopology,                                      // const VkPrimitiveTopology                                            topology
2561                                                                                                 0u,                                                                     // const deUint32                                                                       subpass
2562                                                                                                 0u,                                                                     // const deUint32                                                                       patchControlPoints
2563                                                                                                 &vertexInputStateParams,                        // const VkPipelineVertexInputStateCreateInfo*          vertexInputStateCreateInfo
2564                                                                                                 getRasterizationStateCreateInfo(),      // const VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
2565                                                                                                 &multisampleStateParams,                        // const VkPipelineMultisampleStateCreateInfo*          multisampleStateCreateInfo
2566                                                                                                 DE_NULL,                                                        // const VkPipelineDepthStencilStateCreateInfo*         depthStencilStateCreateInfo,
2567                                                                                                 getColorBlendStateCreateInfo());        // const VkPipelineColorBlendStateCreateInfo*           colorBlendStateCreateInfo
2568         }
2569
2570         // Create Vertex Buffer
2571         {
2572                 const VkBufferCreateInfo                                        vertexBufferParams              =
2573                 {
2574                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
2575                         DE_NULL,                                                                // const void*                  pNext;
2576                         0u,                                                                             // VkBufferCreateFlags  flags;
2577                         attributeBatchSize * 2,                                 // VkDeviceSize                 size;
2578                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,              // VkBufferUsageFlags   usage;
2579                         VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
2580                         1u,                                                                             // deUint32                             queueFamilyCount;
2581                         &queueFamilyIndex                                               // const deUint32*              pQueueFamilyIndices;
2582                 };
2583
2584                 const std::vector<tcu::Vec4>                            colorData                               (positionData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
2585
2586                 vertexBuffer            = createBuffer(vkd, vkDevice, &vertexBufferParams);
2587                 vertexBufferMemory      = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
2588
2589                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
2590
2591                 // Load vertices into vertex buffer
2592                 deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
2593                 deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize);
2594                 flushMappedMemoryRange(vkd, vkDevice, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset(), vertexBufferParams.size);
2595         }
2596
2597         // Create Command Buffer
2598         commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2599
2600         // Begin Command Buffer
2601         beginCommandBuffer(vkd, *commandBuffer);
2602
2603         addImageTransitionBarrier(*commandBuffer,                                                                       // VkCommandBuffer                      commandBuffer
2604                                                           *m_image,                                                                                     // VkImage                                      image
2605                                                           VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                            // VkPipelineStageFlags         srcStageMask
2606                                                           VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                           // VkPipelineStageFlags         dstStageMask
2607                                                           0,                                                                                            // VkAccessFlags                        srcAccessMask
2608                                                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        dstAccessMask
2609                                                           VK_IMAGE_LAYOUT_UNDEFINED,                                            // VkImageLayout                        oldLayout;
2610                                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);            // VkImageLayout                        newLayout;
2611
2612         if (m_multisampling)
2613         {
2614                 addImageTransitionBarrier(*commandBuffer,                                                               // VkCommandBuffer                      commandBuffer
2615                                                                   *m_resolvedImage,                                                             // VkImage                                      image
2616                                                                   VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                    // VkPipelineStageFlags         srcStageMask
2617                                                                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                   // VkPipelineStageFlags         dstStageMask
2618                                                                   0,                                                                                    // VkAccessFlags                        srcAccessMask
2619                                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                 // VkAccessFlags                        dstAccessMask
2620                                                                   VK_IMAGE_LAYOUT_UNDEFINED,                                    // VkImageLayout                        oldLayout;
2621                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);    // VkImageLayout                        newLayout;
2622         }
2623
2624         // Reset query pool
2625         vkd.cmdResetQueryPool(*commandBuffer, *queryPool, 0u, 1u);
2626
2627         // Begin render pass and start query
2628         beginRenderPass(vkd, *commandBuffer, *m_renderPass, *m_frameBuffer, vk::makeRect2D(0, 0, m_renderSize, m_renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
2629         vkd.cmdBeginQuery(*commandBuffer, *queryPool, 0u, (VkQueryControlFlags)0u);
2630         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
2631         vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
2632         vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
2633         vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
2634         endRenderPass(vkd, *commandBuffer);
2635         vkd.cmdEndQuery(*commandBuffer, *queryPool, 0u);
2636
2637         // Copy Image
2638         {
2639                 const VkBufferMemoryBarrier     bufferBarrier   =
2640                 {
2641                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType              sType;
2642                         DE_NULL,                                                                        // const void*                  pNext;
2643                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkMemoryOutputFlags  outputMask;
2644                         VK_ACCESS_HOST_READ_BIT,                                        // VkMemoryInputFlags   inputMask;
2645                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             srcQueueFamilyIndex;
2646                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             destQueueFamilyIndex;
2647                         *m_resultBuffer,                                                        // VkBuffer                             buffer;
2648                         0u,                                                                                     // VkDeviceSize                 offset;
2649                         m_resultBufferSize                                                      // VkDeviceSize                 size;
2650                 };
2651
2652                 const VkBufferImageCopy         copyRegion              =
2653                 {
2654                         0u,                                                                                     // VkDeviceSize                         bufferOffset;
2655                         m_renderSize,                                                           // deUint32                                     bufferRowLength;
2656                         m_renderSize,                                                           // deUint32                                     bufferImageHeight;
2657                         { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u },      // VkImageSubresourceCopy       imageSubresource;
2658                         { 0, 0, 0 },                                                            // VkOffset3D                           imageOffset;
2659                         { m_renderSize, m_renderSize, 1u }                      // VkExtent3D                           imageExtent;
2660                 };
2661
2662                 addImageTransitionBarrier(*commandBuffer,                                                                       // VkCommandBuffer                      commandBuffer
2663                                                                   m_multisampling ? *m_resolvedImage : *m_image,        // VkImage                                      image
2664                                                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,        // VkPipelineStageFlags         srcStageMask
2665                                                                   VK_PIPELINE_STAGE_TRANSFER_BIT,                                       // VkPipelineStageFlags         dstStageMask
2666                                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        srcAccessMask
2667                                                                   VK_ACCESS_TRANSFER_READ_BIT,                                          // VkAccessFlags                        dstAccessMask
2668                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                     // VkImageLayout                        oldLayout;
2669                                                                   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);                        // VkImageLayout                        newLayout;)
2670
2671                 if (m_multisampling)
2672                         vkd.cmdCopyImageToBuffer(*commandBuffer, *m_resolvedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
2673                 else
2674                         vkd.cmdCopyImageToBuffer(*commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
2675
2676                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
2677         }
2678
2679         endCommandBuffer(vkd, *commandBuffer);
2680
2681         // Set Point Size
2682         {
2683                 float pointSize = getPointSize();
2684
2685                 deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
2686                 flushMappedMemoryRange(vkd, vkDevice, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset(), m_uniformBufferSize);
2687         }
2688
2689         // Submit
2690         submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
2691
2692         invalidateMappedMemoryRange(vkd, vkDevice, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset(), m_resultBufferSize);
2693         tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
2694 }
2695
2696 class DiscardTestCase : public BaseRenderingTestCase
2697 {
2698 public:
2699                                                                 DiscardTestCase                                 (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2700                                                                         : BaseRenderingTestCase                         (context, name, description, sampleCount)
2701                                                                         , m_primitiveTopology                           (primitiveTopology)
2702                                                                         , m_queryFragmentShaderInvocations      (queryFragmentShaderInvocations)
2703                                                                 {}
2704
2705         virtual TestInstance*           createInstance          (Context& context) const
2706                                                                 {
2707                                                                         if (m_queryFragmentShaderInvocations && !context.getDeviceFeatures().pipelineStatisticsQuery)
2708                                                                                 throw tcu::NotSupportedError("Pipeline statistics queries are not supported");
2709
2710                                                                         return new DiscardTestInstance (context, m_primitiveTopology, m_queryFragmentShaderInvocations);
2711                                                                 }
2712
2713 protected:
2714         const VkPrimitiveTopology       m_primitiveTopology;
2715         const deBool                            m_queryFragmentShaderInvocations;
2716 };
2717
2718 class TriangleInterpolationTestInstance : public BaseRenderingTestInstance
2719 {
2720 public:
2721
2722                                                                 TriangleInterpolationTestInstance       (Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount)
2723                                                                         : BaseRenderingTestInstance     (context, sampleCount, DEFAULT_RENDER_SIZE)
2724                                                                         , m_primitiveTopology           (primitiveTopology)
2725                                                                         , m_projective                          ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
2726                                                                         , m_iterationCount                      (3)
2727                                                                         , m_iteration                           (0)
2728                                                                         , m_allIterationsPassed         (true)
2729                                                                         , m_flatshade                           ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2730                                                                 {}
2731
2732         tcu::TestStatus                         iterate                                                         (void);
2733
2734
2735 private:
2736         void                                            generateVertices                                        (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
2737         void                                            extractTriangles                                        (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
2738
2739
2740         VkPrimitiveTopology                     m_primitiveTopology;
2741         const bool                                      m_projective;
2742         const int                                       m_iterationCount;
2743         int                                                     m_iteration;
2744         bool                                            m_allIterationsPassed;
2745         const deBool                            m_flatshade;
2746 };
2747
2748 tcu::TestStatus TriangleInterpolationTestInstance::iterate (void)
2749 {
2750         const std::string                                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
2751         const tcu::ScopedLogSection                                             section                                 (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
2752         tcu::Surface                                                                    resultImage                             (m_renderSize, m_renderSize);
2753         std::vector<tcu::Vec4>                                                  drawBuffer;
2754         std::vector<tcu::Vec4>                                                  colorBuffer;
2755         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
2756
2757         // generate scene
2758         generateVertices(m_iteration, drawBuffer, colorBuffer);
2759         extractTriangles(triangles, drawBuffer, colorBuffer);
2760
2761         // log
2762         {
2763                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
2764                 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2765                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2766         }
2767
2768         // draw image
2769         drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
2770
2771         // compare
2772         {
2773                 RasterizationArguments  args;
2774                 TriangleSceneSpec               scene;
2775                 tcu::IVec4                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
2776
2777                 args.numSamples         = m_multisampling ? 1 : 0;
2778                 args.subpixelBits       = m_subpixelBits;
2779                 args.redBits            = colorBits[0];
2780                 args.greenBits          = colorBits[1];
2781                 args.blueBits           = colorBits[2];
2782
2783                 scene.triangles.swap(triangles);
2784
2785                 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
2786                         m_allIterationsPassed = false;
2787         }
2788
2789         // result
2790         if (++m_iteration == m_iterationCount)
2791         {
2792                 if (m_allIterationsPassed)
2793                         return tcu::TestStatus::pass("Pass");
2794                 else
2795                         return tcu::TestStatus::fail("Found invalid pixel values");
2796         }
2797         else
2798                 return tcu::TestStatus::incomplete();
2799 }
2800
2801 void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
2802 {
2803         // use only red, green and blue
2804         const tcu::Vec4 colors[] =
2805         {
2806                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2807                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2808                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
2809         };
2810
2811         de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
2812
2813         outVertices.resize(6);
2814         outColors.resize(6);
2815
2816         for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
2817         {
2818                 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2819                 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2820                 outVertices[vtxNdx].z() = 0.0f;
2821
2822                 if (!m_projective)
2823                         outVertices[vtxNdx].w() = 1.0f;
2824                 else
2825                 {
2826                         const float w = rnd.getFloat(0.2f, 4.0f);
2827
2828                         outVertices[vtxNdx].x() *= w;
2829                         outVertices[vtxNdx].y() *= w;
2830                         outVertices[vtxNdx].z() *= w;
2831                         outVertices[vtxNdx].w() = w;
2832                 }
2833
2834                 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
2835         }
2836 }
2837
2838 void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
2839 {
2840         switch (m_primitiveTopology)
2841         {
2842                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2843                 {
2844                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2845                         {
2846                                 TriangleSceneSpec::SceneTriangle tri;
2847                                 tri.positions[0]        = vertices[vtxNdx + 0];
2848                                 tri.positions[1]        = vertices[vtxNdx + 1];
2849                                 tri.positions[2]        = vertices[vtxNdx + 2];
2850                                 tri.sharedEdge[0]       = false;
2851                                 tri.sharedEdge[1]       = false;
2852                                 tri.sharedEdge[2]       = false;
2853
2854                                 if (m_flatshade)
2855                                 {
2856                                         tri.colors[0] = colors[vtxNdx];
2857                                         tri.colors[1] = colors[vtxNdx];
2858                                         tri.colors[2] = colors[vtxNdx];
2859                                 }
2860                                 else
2861                                 {
2862                                         tri.colors[0] = colors[vtxNdx + 0];
2863                                         tri.colors[1] = colors[vtxNdx + 1];
2864                                         tri.colors[2] = colors[vtxNdx + 2];
2865                                 }
2866
2867                                 outTriangles.push_back(tri);
2868                         }
2869                         break;
2870                 }
2871
2872                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2873                 {
2874                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2875                         {
2876                                 TriangleSceneSpec::SceneTriangle tri;
2877                                 tri.positions[0]        = vertices[vtxNdx + 0];
2878                                 tri.positions[1]        = vertices[vtxNdx + 1];
2879                                 tri.positions[2]        = vertices[vtxNdx + 2];
2880                                 tri.sharedEdge[0]       = false;
2881                                 tri.sharedEdge[1]       = false;
2882                                 tri.sharedEdge[2]       = false;
2883
2884                                 if (m_flatshade)
2885                                 {
2886                                         tri.colors[0] = colors[vtxNdx];
2887                                         tri.colors[1] = colors[vtxNdx];
2888                                         tri.colors[2] = colors[vtxNdx];
2889                                 }
2890                                 else
2891                                 {
2892                                         tri.colors[0] = colors[vtxNdx + 0];
2893                                         tri.colors[1] = colors[vtxNdx + 1];
2894                                         tri.colors[2] = colors[vtxNdx + 2];
2895                                 }
2896
2897                                 outTriangles.push_back(tri);
2898                         }
2899                         break;
2900                 }
2901
2902                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2903                 {
2904                         for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2905                         {
2906                                 TriangleSceneSpec::SceneTriangle tri;
2907                                 tri.positions[0]        = vertices[0];
2908                                 tri.positions[1]        = vertices[vtxNdx + 0];
2909                                 tri.positions[2]        = vertices[vtxNdx + 1];
2910                                 tri.sharedEdge[0]       = false;
2911                                 tri.sharedEdge[1]       = false;
2912                                 tri.sharedEdge[2]       = false;
2913
2914                                 if (m_flatshade)
2915                                 {
2916                                         tri.colors[0] = colors[vtxNdx];
2917                                         tri.colors[1] = colors[vtxNdx];
2918                                         tri.colors[2] = colors[vtxNdx];
2919                                 }
2920                                 else
2921                                 {
2922                                         tri.colors[0] = colors[0];
2923                                         tri.colors[1] = colors[vtxNdx + 0];
2924                                         tri.colors[2] = colors[vtxNdx + 1];
2925                                 }
2926
2927                                 outTriangles.push_back(tri);
2928                         }
2929                         break;
2930                 }
2931
2932                 default:
2933                         DE_ASSERT(false);
2934         }
2935 }
2936
2937 class TriangleInterpolationTestCase : public BaseRenderingTestCase
2938 {
2939 public:
2940                                                                 TriangleInterpolationTestCase   (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2941                                                                         : BaseRenderingTestCase         (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2942                                                                         , m_primitiveTopology           (primitiveTopology)
2943                                                                         , m_flags                                       (flags)
2944                                                                 {}
2945
2946         virtual TestInstance*           createInstance                                  (Context& context) const
2947                                                                 {
2948                                                                         return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount);
2949                                                                 }
2950 protected:
2951         const VkPrimitiveTopology       m_primitiveTopology;
2952         const int                                       m_flags;
2953 };
2954
2955 class LineInterpolationTestInstance : public BaseRenderingTestInstance
2956 {
2957 public:
2958                                                         LineInterpolationTestInstance   (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
2959
2960         virtual tcu::TestStatus iterate                                                 (void);
2961
2962 private:
2963         void                                    generateVertices                                (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
2964         void                                    extractLines                                    (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
2965         virtual float                   getLineWidth                                    (void) const;
2966
2967         VkPrimitiveTopology             m_primitiveTopology;
2968         const bool                              m_projective;
2969         const int                               m_iterationCount;
2970         const PrimitiveWideness m_primitiveWideness;
2971
2972         int                                             m_iteration;
2973         bool                                    m_allIterationsPassed;
2974         float                                   m_maxLineWidth;
2975         std::vector<float>              m_lineWidths;
2976         bool                                    m_flatshade;
2977 };
2978
2979 LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
2980         : BaseRenderingTestInstance                     (context, sampleCount)
2981         , m_primitiveTopology                           (primitiveTopology)
2982         , m_projective                                          ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
2983         , m_iterationCount                                      (3)
2984         , m_primitiveWideness                           (wideness)
2985         , m_iteration                                           (0)
2986         , m_allIterationsPassed                         (true)
2987         , m_maxLineWidth                                        (1.0f)
2988         , m_flatshade                                           ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2989 {
2990         DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
2991
2992         if (!context.getDeviceProperties().limits.strictLines)
2993                 TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
2994
2995         // create line widths
2996         if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
2997         {
2998                 m_lineWidths.resize(m_iterationCount, 1.0f);
2999         }
3000         else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
3001         {
3002                 if (!m_context.getDeviceFeatures().wideLines)
3003                         TCU_THROW(NotSupportedError , "wide line support required");
3004
3005                 const float*    range = context.getDeviceProperties().limits.lineWidthRange;
3006
3007                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
3008
3009                 // no wide line support
3010                 if (range[1] <= 1.0f)
3011                         throw tcu::NotSupportedError("wide line support required");
3012
3013                 // set hand picked sizes
3014                 m_lineWidths.push_back(5.0f);
3015                 m_lineWidths.push_back(10.0f);
3016                 m_lineWidths.push_back(range[1]);
3017                 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
3018
3019                 m_maxLineWidth = range[1];
3020         }
3021         else
3022                 DE_ASSERT(false);
3023 }
3024
3025 tcu::TestStatus LineInterpolationTestInstance::iterate (void)
3026 {
3027         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
3028         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
3029         const float                                                             lineWidth                               = getLineWidth();
3030         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
3031         std::vector<tcu::Vec4>                                  drawBuffer;
3032         std::vector<tcu::Vec4>                                  colorBuffer;
3033         std::vector<LineSceneSpec::SceneLine>   lines;
3034
3035         // supported?
3036         if (lineWidth <= m_maxLineWidth)
3037         {
3038                 // generate scene
3039                 generateVertices(m_iteration, drawBuffer, colorBuffer);
3040                 extractLines(lines, drawBuffer, colorBuffer);
3041
3042                 // log
3043                 {
3044                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
3045                         for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
3046                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
3047                 }
3048
3049                 // draw image
3050                 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
3051
3052                 // compare
3053                 {
3054                         RasterizationArguments  args;
3055                         LineSceneSpec                   scene;
3056
3057                         tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
3058
3059                         args.numSamples         = m_multisampling ? 1 : 0;
3060                         args.subpixelBits       = m_subpixelBits;
3061                         args.redBits            = colorBits[0];
3062                         args.greenBits          = colorBits[1];
3063                         args.blueBits           = colorBits[2];
3064
3065                         scene.lines.swap(lines);
3066                         scene.lineWidth = getLineWidth();
3067
3068                         if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
3069                                 m_allIterationsPassed = false;
3070                 }
3071         }
3072         else
3073                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
3074
3075         // result
3076         if (++m_iteration == m_iterationCount)
3077         {
3078                 if (m_allIterationsPassed)
3079                         return tcu::TestStatus::pass("Pass");
3080                 else
3081                         return tcu::TestStatus::fail("Incorrect rasterization");
3082         }
3083         else
3084                 return tcu::TestStatus::incomplete();
3085 }
3086
3087 void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
3088 {
3089         // use only red, green and blue
3090         const tcu::Vec4 colors[] =
3091         {
3092                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
3093                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
3094                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
3095         };
3096
3097         de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
3098
3099         outVertices.resize(6);
3100         outColors.resize(6);
3101
3102         for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
3103         {
3104                 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
3105                 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
3106                 outVertices[vtxNdx].z() = 0.0f;
3107
3108                 if (!m_projective)
3109                         outVertices[vtxNdx].w() = 1.0f;
3110                 else
3111                 {
3112                         const float w = rnd.getFloat(0.2f, 4.0f);
3113
3114                         outVertices[vtxNdx].x() *= w;
3115                         outVertices[vtxNdx].y() *= w;
3116                         outVertices[vtxNdx].z() *= w;
3117                         outVertices[vtxNdx].w() = w;
3118                 }
3119
3120                 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
3121         }
3122 }
3123
3124 void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
3125 {
3126         switch (m_primitiveTopology)
3127         {
3128                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
3129                 {
3130                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
3131                         {
3132                                 LineSceneSpec::SceneLine line;
3133                                 line.positions[0] = vertices[vtxNdx + 0];
3134                                 line.positions[1] = vertices[vtxNdx + 1];
3135
3136                                 if (m_flatshade)
3137                                 {
3138                                         line.colors[0] = colors[vtxNdx];
3139                                         line.colors[1] = colors[vtxNdx];
3140                                 }
3141                                 else
3142                                 {
3143                                         line.colors[0] = colors[vtxNdx + 0];
3144                                         line.colors[1] = colors[vtxNdx + 1];
3145                                 }
3146
3147                                 outLines.push_back(line);
3148                         }
3149                         break;
3150                 }
3151
3152                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
3153                 {
3154                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
3155                         {
3156                                 LineSceneSpec::SceneLine line;
3157                                 line.positions[0] = vertices[vtxNdx + 0];
3158                                 line.positions[1] = vertices[vtxNdx + 1];
3159
3160                                 if (m_flatshade)
3161                                 {
3162                                         line.colors[0] = colors[vtxNdx];
3163                                         line.colors[1] = colors[vtxNdx];
3164                                 }
3165                                 else
3166                                 {
3167                                         line.colors[0] = colors[vtxNdx + 0];
3168                                         line.colors[1] = colors[vtxNdx + 1];
3169                                 }
3170
3171                                 outLines.push_back(line);
3172                         }
3173                         break;
3174                 }
3175
3176                 default:
3177                         DE_ASSERT(false);
3178         }
3179 }
3180
3181 float LineInterpolationTestInstance::getLineWidth (void) const
3182 {
3183         return m_lineWidths[m_iteration];
3184 }
3185
3186 class LineInterpolationTestCase : public BaseRenderingTestCase
3187 {
3188 public:
3189                                                                 LineInterpolationTestCase               (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
3190                                                                         : BaseRenderingTestCase         (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
3191                                                                         , m_primitiveTopology           (primitiveTopology)
3192                                                                         , m_flags                                       (flags)
3193                                                                         , m_wideness                            (wideness)
3194                                                                 {}
3195
3196         virtual TestInstance*           createInstance                                  (Context& context) const
3197                                                                 {
3198                                                                         return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_sampleCount);
3199                                                                 }
3200 protected:
3201         const VkPrimitiveTopology       m_primitiveTopology;
3202         const int                                       m_flags;
3203         const PrimitiveWideness         m_wideness;
3204 };
3205
3206 void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
3207 {
3208         tcu::TestContext&       testCtx         =       rasterizationTests->getTestContext();
3209
3210         // .primitives
3211         {
3212                 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives", "Primitive rasterization");
3213
3214                 rasterizationTests->addChild(primitives);
3215
3216                 primitives->addChild(new BaseTestCase<TrianglesTestInstance>            (testCtx, "triangles",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result"));
3217                 primitives->addChild(new BaseTestCase<TriangleStripTestInstance>        (testCtx, "triangle_strip",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result"));
3218                 primitives->addChild(new BaseTestCase<TriangleFanTestInstance>          (testCtx, "triangle_fan",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result"));
3219                 primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines",                              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW));
3220                 primitives->addChild(new WidenessTestCase<LineStripTestInstance>        (testCtx, "line_strip",                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW));
3221                 primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines_wide",                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE));
3222                 primitives->addChild(new WidenessTestCase<LineStripTestInstance>        (testCtx, "line_strip_wide",    "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE));
3223                 primitives->addChild(new WidenessTestCase<PointTestInstance>            (testCtx, "points",                             "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",                                           PRIMITIVEWIDENESS_WIDE));
3224         }
3225
3226         // .fill_rules
3227         {
3228                 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules", "Primitive fill rules");
3229
3230                 rasterizationTests->addChild(fillRules);
3231
3232                 fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad",                   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_BASIC));
3233                 fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad_reverse",   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_REVERSED));
3234                 fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_full",                 "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL));
3235                 fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_partly",               "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL));
3236                 fillRules->addChild(new FillRuleTestCase(testCtx,       "projected",                    "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_PROJECTED));
3237         }
3238
3239         // .culling
3240         {
3241                 static const struct CullMode
3242                 {
3243                         VkCullModeFlags mode;
3244                         const char*             prefix;
3245                 } cullModes[] =
3246                 {
3247                         { VK_CULL_MODE_FRONT_BIT,                               "front_"        },
3248                         { VK_CULL_MODE_BACK_BIT,                                "back_"         },
3249                         { VK_CULL_MODE_FRONT_AND_BACK,                  "both_"         },
3250                 };
3251                 static const struct PrimitiveType
3252                 {
3253                         VkPrimitiveTopology     type;
3254                         const char*                     name;
3255                 } primitiveTypes[] =
3256                 {
3257                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                  "triangles"                     },
3258                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                 "triangle_strip"        },
3259                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,                   "triangle_fan"          },
3260                 };
3261                 static const struct FrontFaceOrder
3262                 {
3263                         VkFrontFace     mode;
3264                         const char*     postfix;
3265                 } frontOrders[] =
3266                 {
3267                         { VK_FRONT_FACE_COUNTER_CLOCKWISE,      ""                      },
3268                         { VK_FRONT_FACE_CLOCKWISE,                      "_reverse"      },
3269                 };
3270
3271                 static const struct PolygonMode
3272                 {
3273                         VkPolygonMode   mode;
3274                         const char*             name;
3275                 } polygonModes[] =
3276                 {
3277                         { VK_POLYGON_MODE_FILL,         ""              },
3278                         { VK_POLYGON_MODE_LINE,         "_line"         },
3279                         { VK_POLYGON_MODE_POINT,        "_point"        }
3280                 };
3281
3282                 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling", "Culling");
3283
3284                 rasterizationTests->addChild(culling);
3285
3286                 for (int cullModeNdx    = 0; cullModeNdx        < DE_LENGTH_OF_ARRAY(cullModes);                ++cullModeNdx)
3287                 for (int primitiveNdx   = 0; primitiveNdx       < DE_LENGTH_OF_ARRAY(primitiveTypes);   ++primitiveNdx)
3288                 for (int frontOrderNdx  = 0; frontOrderNdx      < DE_LENGTH_OF_ARRAY(frontOrders);              ++frontOrderNdx)
3289                 for (int polygonModeNdx = 0; polygonModeNdx     < DE_LENGTH_OF_ARRAY(polygonModes);             ++polygonModeNdx)
3290                 {
3291                         if (!(cullModes[cullModeNdx].mode == VK_CULL_MODE_FRONT_AND_BACK && polygonModes[polygonModeNdx].mode != VK_POLYGON_MODE_FILL))
3292                         {
3293                                 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix + polygonModes[polygonModeNdx].name;
3294                                 culling->addChild(new CullingTestCase(testCtx, name, "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode, polygonModes[polygonModeNdx].mode));
3295                         }
3296                 }
3297         }
3298
3299         // .discard
3300         {
3301                 static const struct PrimitiveType
3302                 {
3303                         VkPrimitiveTopology     type;
3304                         const char*                     name;
3305                 } primitiveTypes[] =
3306                 {
3307                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,  "triangle_list"         },
3308                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip"        },
3309                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,   "triangle_fan"          },
3310                         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,              "line_list"                     },
3311                         { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,             "line_strip"            },
3312                         { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,             "point_list"            }
3313                 };
3314
3315                 static const struct queryPipeline
3316                 {
3317                         deBool                  useQuery;
3318                         const char*             name;
3319                 } queryPipeline[] =
3320                 {
3321                         { DE_FALSE,     "query_pipeline_false"  },
3322                         { DE_TRUE,      "query_pipeline_true"   },
3323                 };
3324
3325                 tcu::TestCaseGroup* const discard = new tcu::TestCaseGroup(testCtx, "discard", "Rasterizer discard");
3326
3327                 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
3328                 {
3329                         tcu::TestCaseGroup* const primitive = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveNdx].name, "Rasterizer discard");
3330
3331                         for (int useQueryNdx = 0; useQueryNdx < DE_LENGTH_OF_ARRAY(queryPipeline); useQueryNdx++)
3332                         {
3333                                 const std::string name = std::string(queryPipeline[useQueryNdx].name);
3334
3335                                 primitive->addChild(new DiscardTestCase(testCtx, name, "Test primitive discarding.", primitiveTypes[primitiveNdx].type, queryPipeline[useQueryNdx].useQuery));
3336                         }
3337
3338                         discard->addChild(primitive);
3339                 }
3340
3341                 rasterizationTests->addChild(discard);
3342         }
3343
3344         // .interpolation
3345         {
3346                 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
3347
3348                 rasterizationTests->addChild(interpolation);
3349
3350                 // .basic
3351                 {
3352                         tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation");
3353
3354                         interpolation->addChild(basic);
3355
3356                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_NONE));
3357                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangle_strip",     "Verify triangle strip interpolation",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_NONE));
3358                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangle_fan",       "Verify triangle fan interpolation",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_NONE));
3359                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW));
3360                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "line_strip",         "Verify line strip interpolation",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW));
3361                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE));
3362                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "line_strip_wide","Verify wide line strip interpolation",     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE));
3363                 }
3364
3365                 // .projected
3366                 {
3367                         tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation");
3368
3369                         interpolation->addChild(projected);
3370
3371                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_PROJECTED));
3372                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangle_strip",     "Verify triangle strip interpolation",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_PROJECTED));
3373                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangle_fan",       "Verify triangle fan interpolation",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_PROJECTED));
3374                         projected->addChild(new LineInterpolationTestCase               (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW));
3375                         projected->addChild(new LineInterpolationTestCase               (testCtx, "line_strip",         "Verify line strip interpolation",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW));
3376                         projected->addChild(new LineInterpolationTestCase               (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE));
3377                         projected->addChild(new LineInterpolationTestCase               (testCtx, "line_strip_wide","Verify wide line strip interpolation",     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE));
3378                 }
3379         }
3380
3381         // .flatshading
3382         {
3383                 tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading");
3384
3385                 rasterizationTests->addChild(flatshading);
3386
3387                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangles",          "Verify triangle flatshading",                  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_FLATSHADE));
3388                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangle_strip",     "Verify triangle strip flatshading",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_FLATSHADE));
3389                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangle_fan",       "Verify triangle fan flatshading",              VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_FLATSHADE));
3390                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "lines",                      "Verify line flatshading",                              VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW));
3391                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "line_strip",         "Verify line strip flatshading",                VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW));
3392                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "lines_wide",         "Verify wide line flatshading",                 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE));
3393                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "line_strip_wide","Verify wide line strip flatshading",       VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE));
3394         }
3395
3396         const VkSampleCountFlagBits samples[] =
3397         {
3398                 VK_SAMPLE_COUNT_2_BIT,
3399                 VK_SAMPLE_COUNT_4_BIT,
3400                 VK_SAMPLE_COUNT_8_BIT,
3401                 VK_SAMPLE_COUNT_16_BIT,
3402                 VK_SAMPLE_COUNT_32_BIT,
3403                 VK_SAMPLE_COUNT_64_BIT
3404         };
3405
3406         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
3407         {
3408                 std::ostringstream caseName;
3409
3410                 caseName << "_multisample_" << (2 << samplesNdx) << "_bit";
3411
3412                 // .primitives
3413                 {
3414                         tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization");
3415
3416                         rasterizationTests->addChild(primitives);
3417
3418                         primitives->addChild(new BaseTestCase<TrianglesTestInstance>            (testCtx, "triangles",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result",                                        samples[samplesNdx]));
3419                         primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines",                              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       samples[samplesNdx]));
3420                         primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines_wide",                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         samples[samplesNdx]));
3421                         primitives->addChild(new WidenessTestCase<PointTestInstance>            (testCtx, "points",                             "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",                                           PRIMITIVEWIDENESS_WIDE,         samples[samplesNdx]));
3422                 }
3423
3424                 // .fill_rules
3425                 {
3426                         tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules");
3427
3428                         rasterizationTests->addChild(fillRules);
3429
3430                         fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad",                   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_BASIC,                       samples[samplesNdx]));
3431                         fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad_reverse",   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_REVERSED,            samples[samplesNdx]));
3432                         fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_full",                 "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL,        samples[samplesNdx]));
3433                         fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_partly",               "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL,     samples[samplesNdx]));
3434                         fillRules->addChild(new FillRuleTestCase(testCtx,       "projected",                    "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_PROJECTED,           samples[samplesNdx]));
3435                 }
3436
3437                 // .interpolation
3438                 {
3439                         tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation");
3440
3441                         rasterizationTests->addChild(interpolation);
3442
3443                         interpolation->addChild(new TriangleInterpolationTestCase               (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_NONE,                                                                samples[samplesNdx]));
3444                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       samples[samplesNdx]));
3445                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         samples[samplesNdx]));
3446                 }
3447         }
3448 }
3449
3450 } // anonymous
3451
3452 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
3453 {
3454         return createTestGroup(testCtx, "rasterization", "Rasterization Tests", createRasterizationTests);
3455 }
3456
3457 } // rasterization
3458 } // vkt