992665042e8fed6866638932e4225675ff431f8c
[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 TriangleInterpolationTestInstance : public BaseRenderingTestInstance
2206 {
2207 public:
2208
2209                                                                 TriangleInterpolationTestInstance       (Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount)
2210                                                                         : BaseRenderingTestInstance     (context, sampleCount, DEFAULT_RENDER_SIZE)
2211                                                                         , m_primitiveTopology           (primitiveTopology)
2212                                                                         , m_projective                          ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
2213                                                                         , m_iterationCount                      (3)
2214                                                                         , m_iteration                           (0)
2215                                                                         , m_allIterationsPassed         (true)
2216                                                                         , m_flatshade                           ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2217                                                                 {}
2218
2219         tcu::TestStatus                         iterate                                                         (void);
2220
2221
2222 private:
2223         void                                            generateVertices                                        (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
2224         void                                            extractTriangles                                        (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
2225
2226
2227         VkPrimitiveTopology                     m_primitiveTopology;
2228         const bool                                      m_projective;
2229         const int                                       m_iterationCount;
2230         int                                                     m_iteration;
2231         bool                                            m_allIterationsPassed;
2232         const deBool                            m_flatshade;
2233 };
2234
2235 tcu::TestStatus TriangleInterpolationTestInstance::iterate (void)
2236 {
2237         const std::string                                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
2238         const tcu::ScopedLogSection                                             section                                 (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
2239         tcu::Surface                                                                    resultImage                             (m_renderSize, m_renderSize);
2240         std::vector<tcu::Vec4>                                                  drawBuffer;
2241         std::vector<tcu::Vec4>                                                  colorBuffer;
2242         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
2243
2244         // generate scene
2245         generateVertices(m_iteration, drawBuffer, colorBuffer);
2246         extractTriangles(triangles, drawBuffer, colorBuffer);
2247
2248         // log
2249         {
2250                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
2251                 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2252                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2253         }
2254
2255         // draw image
2256         drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
2257
2258         // compare
2259         {
2260                 RasterizationArguments  args;
2261                 TriangleSceneSpec               scene;
2262                 tcu::IVec4                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
2263
2264                 args.numSamples         = m_multisampling ? 1 : 0;
2265                 args.subpixelBits       = m_subpixelBits;
2266                 args.redBits            = colorBits[0];
2267                 args.greenBits          = colorBits[1];
2268                 args.blueBits           = colorBits[2];
2269
2270                 scene.triangles.swap(triangles);
2271
2272                 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
2273                         m_allIterationsPassed = false;
2274         }
2275
2276         // result
2277         if (++m_iteration == m_iterationCount)
2278         {
2279                 if (m_allIterationsPassed)
2280                         return tcu::TestStatus::pass("Pass");
2281                 else
2282                         return tcu::TestStatus::fail("Found invalid pixel values");
2283         }
2284         else
2285                 return tcu::TestStatus::incomplete();
2286 }
2287
2288 void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
2289 {
2290         // use only red, green and blue
2291         const tcu::Vec4 colors[] =
2292         {
2293                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2294                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2295                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
2296         };
2297
2298         de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
2299
2300         outVertices.resize(6);
2301         outColors.resize(6);
2302
2303         for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
2304         {
2305                 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2306                 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2307                 outVertices[vtxNdx].z() = 0.0f;
2308
2309                 if (!m_projective)
2310                         outVertices[vtxNdx].w() = 1.0f;
2311                 else
2312                 {
2313                         const float w = rnd.getFloat(0.2f, 4.0f);
2314
2315                         outVertices[vtxNdx].x() *= w;
2316                         outVertices[vtxNdx].y() *= w;
2317                         outVertices[vtxNdx].z() *= w;
2318                         outVertices[vtxNdx].w() = w;
2319                 }
2320
2321                 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
2322         }
2323 }
2324
2325 void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
2326 {
2327         switch (m_primitiveTopology)
2328         {
2329                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2330                 {
2331                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2332                         {
2333                                 TriangleSceneSpec::SceneTriangle tri;
2334                                 tri.positions[0]        = vertices[vtxNdx + 0];
2335                                 tri.positions[1]        = vertices[vtxNdx + 1];
2336                                 tri.positions[2]        = vertices[vtxNdx + 2];
2337                                 tri.sharedEdge[0]       = false;
2338                                 tri.sharedEdge[1]       = false;
2339                                 tri.sharedEdge[2]       = false;
2340
2341                                 if (m_flatshade)
2342                                 {
2343                                         tri.colors[0] = colors[vtxNdx];
2344                                         tri.colors[1] = colors[vtxNdx];
2345                                         tri.colors[2] = colors[vtxNdx];
2346                                 }
2347                                 else
2348                                 {
2349                                         tri.colors[0] = colors[vtxNdx + 0];
2350                                         tri.colors[1] = colors[vtxNdx + 1];
2351                                         tri.colors[2] = colors[vtxNdx + 2];
2352                                 }
2353
2354                                 outTriangles.push_back(tri);
2355                         }
2356                         break;
2357                 }
2358
2359                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2360                 {
2361                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2362                         {
2363                                 TriangleSceneSpec::SceneTriangle tri;
2364                                 tri.positions[0]        = vertices[vtxNdx + 0];
2365                                 tri.positions[1]        = vertices[vtxNdx + 1];
2366                                 tri.positions[2]        = vertices[vtxNdx + 2];
2367                                 tri.sharedEdge[0]       = false;
2368                                 tri.sharedEdge[1]       = false;
2369                                 tri.sharedEdge[2]       = false;
2370
2371                                 if (m_flatshade)
2372                                 {
2373                                         tri.colors[0] = colors[vtxNdx];
2374                                         tri.colors[1] = colors[vtxNdx];
2375                                         tri.colors[2] = colors[vtxNdx];
2376                                 }
2377                                 else
2378                                 {
2379                                         tri.colors[0] = colors[vtxNdx + 0];
2380                                         tri.colors[1] = colors[vtxNdx + 1];
2381                                         tri.colors[2] = colors[vtxNdx + 2];
2382                                 }
2383
2384                                 outTriangles.push_back(tri);
2385                         }
2386                         break;
2387                 }
2388
2389                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2390                 {
2391                         for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2392                         {
2393                                 TriangleSceneSpec::SceneTriangle tri;
2394                                 tri.positions[0]        = vertices[0];
2395                                 tri.positions[1]        = vertices[vtxNdx + 0];
2396                                 tri.positions[2]        = vertices[vtxNdx + 1];
2397                                 tri.sharedEdge[0]       = false;
2398                                 tri.sharedEdge[1]       = false;
2399                                 tri.sharedEdge[2]       = false;
2400
2401                                 if (m_flatshade)
2402                                 {
2403                                         tri.colors[0] = colors[vtxNdx];
2404                                         tri.colors[1] = colors[vtxNdx];
2405                                         tri.colors[2] = colors[vtxNdx];
2406                                 }
2407                                 else
2408                                 {
2409                                         tri.colors[0] = colors[0];
2410                                         tri.colors[1] = colors[vtxNdx + 0];
2411                                         tri.colors[2] = colors[vtxNdx + 1];
2412                                 }
2413
2414                                 outTriangles.push_back(tri);
2415                         }
2416                         break;
2417                 }
2418
2419                 default:
2420                         DE_ASSERT(false);
2421         }
2422 }
2423
2424 class TriangleInterpolationTestCase : public BaseRenderingTestCase
2425 {
2426 public:
2427                                                                 TriangleInterpolationTestCase   (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2428                                                                         : BaseRenderingTestCase         (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2429                                                                         , m_primitiveTopology           (primitiveTopology)
2430                                                                         , m_flags                                       (flags)
2431                                                                 {}
2432
2433         virtual TestInstance*           createInstance                                  (Context& context) const
2434                                                                 {
2435                                                                         return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount);
2436                                                                 }
2437 protected:
2438         const VkPrimitiveTopology       m_primitiveTopology;
2439         const int                                       m_flags;
2440 };
2441
2442 class LineInterpolationTestInstance : public BaseRenderingTestInstance
2443 {
2444 public:
2445                                                         LineInterpolationTestInstance   (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
2446
2447         virtual tcu::TestStatus iterate                                                 (void);
2448
2449 private:
2450         void                                    generateVertices                                (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
2451         void                                    extractLines                                    (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
2452         virtual float                   getLineWidth                                    (void) const;
2453
2454         VkPrimitiveTopology             m_primitiveTopology;
2455         const bool                              m_projective;
2456         const int                               m_iterationCount;
2457         const PrimitiveWideness m_primitiveWideness;
2458
2459         int                                             m_iteration;
2460         bool                                    m_allIterationsPassed;
2461         float                                   m_maxLineWidth;
2462         std::vector<float>              m_lineWidths;
2463         bool                                    m_flatshade;
2464 };
2465
2466 LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
2467         : BaseRenderingTestInstance                     (context, sampleCount)
2468         , m_primitiveTopology                           (primitiveTopology)
2469         , m_projective                                          ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
2470         , m_iterationCount                                      (3)
2471         , m_primitiveWideness                           (wideness)
2472         , m_iteration                                           (0)
2473         , m_allIterationsPassed                         (true)
2474         , m_maxLineWidth                                        (1.0f)
2475         , m_flatshade                                           ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2476 {
2477         DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
2478
2479         if (!context.getDeviceProperties().limits.strictLines)
2480                 TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
2481
2482         // create line widths
2483         if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
2484         {
2485                 m_lineWidths.resize(m_iterationCount, 1.0f);
2486         }
2487         else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
2488         {
2489                 if (!m_context.getDeviceFeatures().wideLines)
2490                         TCU_THROW(NotSupportedError , "wide line support required");
2491
2492                 const float*    range = context.getDeviceProperties().limits.lineWidthRange;
2493
2494                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
2495
2496                 // no wide line support
2497                 if (range[1] <= 1.0f)
2498                         throw tcu::NotSupportedError("wide line support required");
2499
2500                 // set hand picked sizes
2501                 m_lineWidths.push_back(5.0f);
2502                 m_lineWidths.push_back(10.0f);
2503                 m_lineWidths.push_back(range[1]);
2504                 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
2505
2506                 m_maxLineWidth = range[1];
2507         }
2508         else
2509                 DE_ASSERT(false);
2510 }
2511
2512 tcu::TestStatus LineInterpolationTestInstance::iterate (void)
2513 {
2514         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
2515         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
2516         const float                                                             lineWidth                               = getLineWidth();
2517         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
2518         std::vector<tcu::Vec4>                                  drawBuffer;
2519         std::vector<tcu::Vec4>                                  colorBuffer;
2520         std::vector<LineSceneSpec::SceneLine>   lines;
2521
2522         // supported?
2523         if (lineWidth <= m_maxLineWidth)
2524         {
2525                 // generate scene
2526                 generateVertices(m_iteration, drawBuffer, colorBuffer);
2527                 extractLines(lines, drawBuffer, colorBuffer);
2528
2529                 // log
2530                 {
2531                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
2532                         for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2533                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2534                 }
2535
2536                 // draw image
2537                 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
2538
2539                 // compare
2540                 {
2541                         RasterizationArguments  args;
2542                         LineSceneSpec                   scene;
2543
2544                         tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
2545
2546                         args.numSamples         = m_multisampling ? 1 : 0;
2547                         args.subpixelBits       = m_subpixelBits;
2548                         args.redBits            = colorBits[0];
2549                         args.greenBits          = colorBits[1];
2550                         args.blueBits           = colorBits[2];
2551
2552                         scene.lines.swap(lines);
2553                         scene.lineWidth = getLineWidth();
2554
2555                         if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
2556                                 m_allIterationsPassed = false;
2557                 }
2558         }
2559         else
2560                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
2561
2562         // result
2563         if (++m_iteration == m_iterationCount)
2564         {
2565                 if (m_allIterationsPassed)
2566                         return tcu::TestStatus::pass("Pass");
2567                 else
2568                         return tcu::TestStatus::fail("Incorrect rasterization");
2569         }
2570         else
2571                 return tcu::TestStatus::incomplete();
2572 }
2573
2574 void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
2575 {
2576         // use only red, green and blue
2577         const tcu::Vec4 colors[] =
2578         {
2579                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2580                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2581                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
2582         };
2583
2584         de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
2585
2586         outVertices.resize(6);
2587         outColors.resize(6);
2588
2589         for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
2590         {
2591                 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2592                 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2593                 outVertices[vtxNdx].z() = 0.0f;
2594
2595                 if (!m_projective)
2596                         outVertices[vtxNdx].w() = 1.0f;
2597                 else
2598                 {
2599                         const float w = rnd.getFloat(0.2f, 4.0f);
2600
2601                         outVertices[vtxNdx].x() *= w;
2602                         outVertices[vtxNdx].y() *= w;
2603                         outVertices[vtxNdx].z() *= w;
2604                         outVertices[vtxNdx].w() = w;
2605                 }
2606
2607                 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
2608         }
2609 }
2610
2611 void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
2612 {
2613         switch (m_primitiveTopology)
2614         {
2615                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2616                 {
2617                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
2618                         {
2619                                 LineSceneSpec::SceneLine line;
2620                                 line.positions[0] = vertices[vtxNdx + 0];
2621                                 line.positions[1] = vertices[vtxNdx + 1];
2622
2623                                 if (m_flatshade)
2624                                 {
2625                                         line.colors[0] = colors[vtxNdx];
2626                                         line.colors[1] = colors[vtxNdx];
2627                                 }
2628                                 else
2629                                 {
2630                                         line.colors[0] = colors[vtxNdx + 0];
2631                                         line.colors[1] = colors[vtxNdx + 1];
2632                                 }
2633
2634                                 outLines.push_back(line);
2635                         }
2636                         break;
2637                 }
2638
2639                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2640                 {
2641                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2642                         {
2643                                 LineSceneSpec::SceneLine line;
2644                                 line.positions[0] = vertices[vtxNdx + 0];
2645                                 line.positions[1] = vertices[vtxNdx + 1];
2646
2647                                 if (m_flatshade)
2648                                 {
2649                                         line.colors[0] = colors[vtxNdx];
2650                                         line.colors[1] = colors[vtxNdx];
2651                                 }
2652                                 else
2653                                 {
2654                                         line.colors[0] = colors[vtxNdx + 0];
2655                                         line.colors[1] = colors[vtxNdx + 1];
2656                                 }
2657
2658                                 outLines.push_back(line);
2659                         }
2660                         break;
2661                 }
2662
2663                 default:
2664                         DE_ASSERT(false);
2665         }
2666 }
2667
2668 float LineInterpolationTestInstance::getLineWidth (void) const
2669 {
2670         return m_lineWidths[m_iteration];
2671 }
2672
2673 class LineInterpolationTestCase : public BaseRenderingTestCase
2674 {
2675 public:
2676                                                                 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)
2677                                                                         : BaseRenderingTestCase         (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2678                                                                         , m_primitiveTopology           (primitiveTopology)
2679                                                                         , m_flags                                       (flags)
2680                                                                         , m_wideness                            (wideness)
2681                                                                 {}
2682
2683         virtual TestInstance*           createInstance                                  (Context& context) const
2684                                                                 {
2685                                                                         return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_sampleCount);
2686                                                                 }
2687 protected:
2688         const VkPrimitiveTopology       m_primitiveTopology;
2689         const int                                       m_flags;
2690         const PrimitiveWideness         m_wideness;
2691 };
2692
2693 void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
2694 {
2695         tcu::TestContext&       testCtx         =       rasterizationTests->getTestContext();
2696
2697         // .primitives
2698         {
2699                 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives", "Primitive rasterization");
2700
2701                 rasterizationTests->addChild(primitives);
2702
2703                 primitives->addChild(new BaseTestCase<TrianglesTestInstance>            (testCtx, "triangles",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result"));
2704                 primitives->addChild(new BaseTestCase<TriangleStripTestInstance>        (testCtx, "triangle_strip",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result"));
2705                 primitives->addChild(new BaseTestCase<TriangleFanTestInstance>          (testCtx, "triangle_fan",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result"));
2706                 primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines",                              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW));
2707                 primitives->addChild(new WidenessTestCase<LineStripTestInstance>        (testCtx, "line_strip",                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW));
2708                 primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines_wide",                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE));
2709                 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));
2710                 primitives->addChild(new WidenessTestCase<PointTestInstance>            (testCtx, "points",                             "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",                                           PRIMITIVEWIDENESS_WIDE));
2711         }
2712
2713         // .fill_rules
2714         {
2715                 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules", "Primitive fill rules");
2716
2717                 rasterizationTests->addChild(fillRules);
2718
2719                 fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad",                   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_BASIC));
2720                 fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad_reverse",   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_REVERSED));
2721                 fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_full",                 "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL));
2722                 fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_partly",               "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL));
2723                 fillRules->addChild(new FillRuleTestCase(testCtx,       "projected",                    "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_PROJECTED));
2724         }
2725
2726         // .culling
2727         {
2728                 static const struct CullMode
2729                 {
2730                         VkCullModeFlags mode;
2731                         const char*             prefix;
2732                 } cullModes[] =
2733                 {
2734                         { VK_CULL_MODE_FRONT_BIT,                               "front_"        },
2735                         { VK_CULL_MODE_BACK_BIT,                                "back_"         },
2736                         { VK_CULL_MODE_FRONT_AND_BACK,                  "both_"         },
2737                 };
2738                 static const struct PrimitiveType
2739                 {
2740                         VkPrimitiveTopology     type;
2741                         const char*                     name;
2742                 } primitiveTypes[] =
2743                 {
2744                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                  "triangles"                     },
2745                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                 "triangle_strip"        },
2746                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,                   "triangle_fan"          },
2747                 };
2748                 static const struct FrontFaceOrder
2749                 {
2750                         VkFrontFace     mode;
2751                         const char*     postfix;
2752                 } frontOrders[] =
2753                 {
2754                         { VK_FRONT_FACE_COUNTER_CLOCKWISE,      ""                      },
2755                         { VK_FRONT_FACE_CLOCKWISE,                      "_reverse"      },
2756                 };
2757
2758                 static const struct PolygonMode
2759                 {
2760                         VkPolygonMode   mode;
2761                         const char*             name;
2762                 } polygonModes[] =
2763                 {
2764                         { VK_POLYGON_MODE_FILL,         ""              },
2765                         { VK_POLYGON_MODE_LINE,         "_line"         },
2766                         { VK_POLYGON_MODE_POINT,        "_point"        }
2767                 };
2768
2769                 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling", "Culling");
2770
2771                 rasterizationTests->addChild(culling);
2772
2773                 for (int cullModeNdx    = 0; cullModeNdx        < DE_LENGTH_OF_ARRAY(cullModes);                ++cullModeNdx)
2774                 for (int primitiveNdx   = 0; primitiveNdx       < DE_LENGTH_OF_ARRAY(primitiveTypes);   ++primitiveNdx)
2775                 for (int frontOrderNdx  = 0; frontOrderNdx      < DE_LENGTH_OF_ARRAY(frontOrders);              ++frontOrderNdx)
2776                 for (int polygonModeNdx = 0; polygonModeNdx     < DE_LENGTH_OF_ARRAY(polygonModes);             ++polygonModeNdx)
2777                 {
2778                         if (!(cullModes[cullModeNdx].mode == VK_CULL_MODE_FRONT_AND_BACK && polygonModes[polygonModeNdx].mode != VK_POLYGON_MODE_FILL))
2779                         {
2780                                 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix + polygonModes[polygonModeNdx].name;
2781                                 culling->addChild(new CullingTestCase(testCtx, name, "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode, polygonModes[polygonModeNdx].mode));
2782                         }
2783                 }
2784         }
2785
2786         // .interpolation
2787         {
2788                 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
2789
2790                 rasterizationTests->addChild(interpolation);
2791
2792                 // .basic
2793                 {
2794                         tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation");
2795
2796                         interpolation->addChild(basic);
2797
2798                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_NONE));
2799                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangle_strip",     "Verify triangle strip interpolation",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_NONE));
2800                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangle_fan",       "Verify triangle fan interpolation",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_NONE));
2801                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW));
2802                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "line_strip",         "Verify line strip interpolation",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW));
2803                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE));
2804                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "line_strip_wide","Verify wide line strip interpolation",     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE));
2805                 }
2806
2807                 // .projected
2808                 {
2809                         tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation");
2810
2811                         interpolation->addChild(projected);
2812
2813                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_PROJECTED));
2814                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangle_strip",     "Verify triangle strip interpolation",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_PROJECTED));
2815                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangle_fan",       "Verify triangle fan interpolation",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_PROJECTED));
2816                         projected->addChild(new LineInterpolationTestCase               (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW));
2817                         projected->addChild(new LineInterpolationTestCase               (testCtx, "line_strip",         "Verify line strip interpolation",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW));
2818                         projected->addChild(new LineInterpolationTestCase               (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE));
2819                         projected->addChild(new LineInterpolationTestCase               (testCtx, "line_strip_wide","Verify wide line strip interpolation",     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE));
2820                 }
2821         }
2822
2823         // .flatshading
2824         {
2825                 tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading");
2826
2827                 rasterizationTests->addChild(flatshading);
2828
2829                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangles",          "Verify triangle flatshading",                  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_FLATSHADE));
2830                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangle_strip",     "Verify triangle strip flatshading",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_FLATSHADE));
2831                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangle_fan",       "Verify triangle fan flatshading",              VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_FLATSHADE));
2832                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "lines",                      "Verify line flatshading",                              VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW));
2833                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "line_strip",         "Verify line strip flatshading",                VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW));
2834                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "lines_wide",         "Verify wide line flatshading",                 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE));
2835                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "line_strip_wide","Verify wide line strip flatshading",       VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE));
2836         }
2837
2838         const VkSampleCountFlagBits samples[] =
2839         {
2840                 VK_SAMPLE_COUNT_2_BIT,
2841                 VK_SAMPLE_COUNT_4_BIT,
2842                 VK_SAMPLE_COUNT_8_BIT,
2843                 VK_SAMPLE_COUNT_16_BIT,
2844                 VK_SAMPLE_COUNT_32_BIT,
2845                 VK_SAMPLE_COUNT_64_BIT
2846         };
2847
2848         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
2849         {
2850                 std::ostringstream caseName;
2851
2852                 caseName << "_multisample_" << (2 << samplesNdx) << "_bit";
2853
2854                 // .primitives
2855                 {
2856                         tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization");
2857
2858                         rasterizationTests->addChild(primitives);
2859
2860                         primitives->addChild(new BaseTestCase<TrianglesTestInstance>            (testCtx, "triangles",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result",                                        samples[samplesNdx]));
2861                         primitives->addChild(new WidenessTestCase<LinesTestInstance>            (testCtx, "lines",                              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       samples[samplesNdx]));
2862                         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]));
2863                         primitives->addChild(new WidenessTestCase<PointTestInstance>            (testCtx, "points",                             "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",                                           PRIMITIVEWIDENESS_WIDE,         samples[samplesNdx]));
2864                 }
2865
2866                 // .fill_rules
2867                 {
2868                         tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules");
2869
2870                         rasterizationTests->addChild(fillRules);
2871
2872                         fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad",                   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_BASIC,                       samples[samplesNdx]));
2873                         fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad_reverse",   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_REVERSED,            samples[samplesNdx]));
2874                         fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_full",                 "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL,        samples[samplesNdx]));
2875                         fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_partly",               "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL,     samples[samplesNdx]));
2876                         fillRules->addChild(new FillRuleTestCase(testCtx,       "projected",                    "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_PROJECTED,           samples[samplesNdx]));
2877                 }
2878
2879                 // .interpolation
2880                 {
2881                         tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation");
2882
2883                         rasterizationTests->addChild(interpolation);
2884
2885                         interpolation->addChild(new TriangleInterpolationTestCase               (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_NONE,                                                                samples[samplesNdx]));
2886                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       samples[samplesNdx]));
2887                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         samples[samplesNdx]));
2888                 }
2889         }
2890 }
2891
2892 } // anonymous
2893
2894 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
2895 {
2896         return createTestGroup(testCtx, "rasterization", "Rasterization Tests", createRasterizationTests);
2897 }
2898
2899 } // rasterization
2900 } // vkt