Test behaviour of color write enable with colorWriteMask
[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 "vktTestGroupUtil.hpp"
27 #include "vktAmberTestCase.hpp"
28 #include "vktRasterizationTests.hpp"
29 #include "vktRasterizationFragShaderSideEffectsTests.hpp"
30 #include "vktRasterizationProvokingVertexTests.hpp"
31 #include "tcuRasterizationVerifier.hpp"
32 #include "tcuSurface.hpp"
33 #include "tcuRenderTarget.hpp"
34 #include "tcuVectorUtil.hpp"
35 #include "tcuStringTemplate.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuResultCollector.hpp"
38 #include "tcuFloatFormat.hpp"
39 #include "vkImageUtil.hpp"
40 #include "deStringUtil.hpp"
41 #include "deRandom.hpp"
42 #include "vktTestCase.hpp"
43 #include "vktTestCaseUtil.hpp"
44 #include "vkPrograms.hpp"
45 #include "vkMemUtil.hpp"
46 #include "vkRefUtil.hpp"
47 #include "vkQueryUtil.hpp"
48 #include "vkBuilderUtil.hpp"
49 #include "vkTypeUtil.hpp"
50 #include "vkCmdUtil.hpp"
51 #include "vkObjUtil.hpp"
52 #include "vkBufferWithMemory.hpp"
53 #include "vkImageWithMemory.hpp"
54 #include "vkBarrierUtil.hpp"
55
56 #include <vector>
57 #include <sstream>
58
59 using namespace vk;
60
61 namespace vkt
62 {
63 namespace rasterization
64 {
65 namespace
66 {
67
68 using tcu::RasterizationArguments;
69 using tcu::TriangleSceneSpec;
70 using tcu::PointSceneSpec;
71 using tcu::LineSceneSpec;
72 using tcu::LineInterpolationMethod;
73
74 static const char* const s_shaderVertexTemplate =       "#version 310 es\n"
75                                                                                                         "layout(location = 0) in highp vec4 a_position;\n"
76                                                                                                         "layout(location = 1) in highp vec4 a_color;\n"
77                                                                                                         "layout(location = 0) ${INTERPOLATION}out highp vec4 v_color;\n"
78                                                                                                         "layout (set=0, binding=0) uniform PointSize {\n"
79                                                                                                         "       highp float u_pointSize;\n"
80                                                                                                         "};\n"
81                                                                                                         "void main ()\n"
82                                                                                                         "{\n"
83                                                                                                         "       gl_Position = a_position;\n"
84                                                                                                         "       gl_PointSize = u_pointSize;\n"
85                                                                                                         "       v_color = a_color;\n"
86                                                                                                         "}\n";
87
88 static const char* const s_shaderFragmentTemplate =     "#version 310 es\n"
89                                                                                                         "layout(location = 0) out highp vec4 fragColor;\n"
90                                                                                                         "layout(location = 0) ${INTERPOLATION}in highp vec4 v_color;\n"
91                                                                                                         "void main ()\n"
92                                                                                                         "{\n"
93                                                                                                         "       fragColor = v_color;\n"
94                                                                                                         "}\n";
95
96 enum InterpolationCaseFlags
97 {
98         INTERPOLATIONFLAGS_NONE = 0,
99         INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
100         INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
101 };
102
103 enum ResolutionValues
104 {
105         RESOLUTION_POT = 256,
106         RESOLUTION_NPOT = 258
107 };
108
109 enum PrimitiveWideness
110 {
111         PRIMITIVEWIDENESS_NARROW = 0,
112         PRIMITIVEWIDENESS_WIDE,
113
114         PRIMITIVEWIDENESS_LAST
115 };
116
117 enum LineStipple
118 {
119         LINESTIPPLE_DISABLED = 0,
120         LINESTIPPLE_STATIC,
121         LINESTIPPLE_DYNAMIC,
122
123         LINESTIPPLE_LAST
124 };
125
126 static const deUint32 lineStippleFactor = 2;
127 static const deUint32 lineStipplePattern = 0x0F0F;
128
129 enum PrimitiveStrictness
130 {
131         PRIMITIVESTRICTNESS_STRICT = 0,
132         PRIMITIVESTRICTNESS_NONSTRICT,
133         PRIMITIVESTRICTNESS_IGNORE,
134
135         PRIMITIVESTRICTNESS_LAST
136 };
137
138
139 class BaseRenderingTestCase : public TestCase
140 {
141 public:
142                                                                 BaseRenderingTestCase   (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deBool flatshade = DE_FALSE);
143         virtual                                         ~BaseRenderingTestCase  (void);
144
145         virtual void                            initPrograms                    (vk::SourceCollections& programCollection) const;
146
147 protected:
148         const VkSampleCountFlagBits     m_sampleCount;
149         const deBool                            m_flatshade;
150 };
151
152 BaseRenderingTestCase::BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount, deBool flatshade)
153         : TestCase(context, name, description)
154         , m_sampleCount (sampleCount)
155         , m_flatshade   (flatshade)
156 {
157 }
158
159 void BaseRenderingTestCase::initPrograms (vk::SourceCollections& programCollection) const
160 {
161         tcu::StringTemplate                                     vertexSource    (s_shaderVertexTemplate);
162         tcu::StringTemplate                                     fragmentSource  (s_shaderFragmentTemplate);
163         std::map<std::string, std::string>      params;
164
165         params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
166
167         programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vertexSource.specialize(params));
168         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fragmentSource.specialize(params));
169 }
170
171 BaseRenderingTestCase::~BaseRenderingTestCase (void)
172 {
173 }
174
175 class BaseRenderingTestInstance : public TestInstance
176 {
177 public:
178                                                                                                         BaseRenderingTestInstance               (Context& context, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deUint32 renderSize = RESOLUTION_POT, VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM, deUint32 additionalRenderSize = 0);
179                                                                                                         ~BaseRenderingTestInstance              (void);
180
181 protected:
182         void                                                                                    addImageTransitionBarrier               (VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
183         virtual void                                                                    drawPrimitives                                  (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology);
184         void                                                                                    drawPrimitives                                  (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, VkPrimitiveTopology primitiveTopology);
185         void                                                                                    drawPrimitives                                  (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology,
186                                                                                                                                                                                 VkImage image, VkImage resolvedImage, VkFramebuffer frameBuffer, const deUint32 renderSize, VkBuffer resultBuffer, const Allocation& resultBufferMemory);
187         virtual float                                                                   getLineWidth                                    (void) const;
188         virtual float                                                                   getPointSize                                    (void) const;
189         virtual bool                                                                    getLineStippleDynamic                   (void) const { return false; };
190
191         virtual
192         const VkPipelineRasterizationStateCreateInfo*   getRasterizationStateCreateInfo (void) const;
193
194         virtual
195         VkPipelineRasterizationLineStateCreateInfoEXT   initLineRasterizationStateCreateInfo    (void) const;
196
197         virtual
198         const VkPipelineRasterizationLineStateCreateInfoEXT*    getLineRasterizationStateCreateInfo     (void);
199
200         virtual
201         const VkPipelineColorBlendStateCreateInfo*              getColorBlendStateCreateInfo    (void) const;
202
203         const tcu::TextureFormat&                                               getTextureFormat                                (void) const;
204
205         const deUint32                                                                  m_renderSize;
206         const VkSampleCountFlagBits                                             m_sampleCount;
207         deUint32                                                                                m_subpixelBits;
208         const deBool                                                                    m_multisampling;
209
210         const VkFormat                                                                  m_imageFormat;
211         const tcu::TextureFormat                                                m_textureFormat;
212         Move<VkCommandPool>                                                             m_commandPool;
213
214         Move<VkImage>                                                                   m_image;
215         de::MovePtr<Allocation>                                                 m_imageMemory;
216         Move<VkImageView>                                                               m_imageView;
217
218         Move<VkImage>                                                                   m_resolvedImage;
219         de::MovePtr<Allocation>                                                 m_resolvedImageMemory;
220         Move<VkImageView>                                                               m_resolvedImageView;
221
222         Move<VkRenderPass>                                                              m_renderPass;
223         Move<VkFramebuffer>                                                             m_frameBuffer;
224
225         Move<VkDescriptorPool>                                                  m_descriptorPool;
226         Move<VkDescriptorSet>                                                   m_descriptorSet;
227         Move<VkDescriptorSetLayout>                                             m_descriptorSetLayout;
228
229         Move<VkBuffer>                                                                  m_uniformBuffer;
230         de::MovePtr<Allocation>                                                 m_uniformBufferMemory;
231         const VkDeviceSize                                                              m_uniformBufferSize;
232
233         Move<VkPipelineLayout>                                                  m_pipelineLayout;
234
235         Move<VkShaderModule>                                                    m_vertexShaderModule;
236         Move<VkShaderModule>                                                    m_fragmentShaderModule;
237
238         Move<VkBuffer>                                                                  m_resultBuffer;
239         de::MovePtr<Allocation>                                                 m_resultBufferMemory;
240         const VkDeviceSize                                                              m_resultBufferSize;
241
242         const deUint32                                                                  m_additionalRenderSize;
243         const VkDeviceSize                                                              m_additionalResultBufferSize;
244
245         VkPipelineRasterizationLineStateCreateInfoEXT   m_lineRasterizationStateInfo;
246
247 private:
248         virtual int                                                                             getIteration                                    (void) const { TCU_THROW(InternalError, "Iteration undefined in the base class"); }
249 };
250
251 BaseRenderingTestInstance::BaseRenderingTestInstance (Context& context, VkSampleCountFlagBits sampleCount, deUint32 renderSize, VkFormat imageFormat, deUint32 additionalRenderSize)
252         : TestInstance                  (context)
253         , m_renderSize                  (renderSize)
254         , m_sampleCount                 (sampleCount)
255         , m_subpixelBits                (context.getDeviceProperties().limits.subPixelPrecisionBits)
256         , m_multisampling               (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
257         , m_imageFormat                 (imageFormat)
258         , m_textureFormat               (vk::mapVkFormat(m_imageFormat))
259         , m_uniformBufferSize   (sizeof(float))
260         , m_resultBufferSize    (renderSize * renderSize * m_textureFormat.getPixelSize())
261         , m_additionalRenderSize(additionalRenderSize)
262         , m_additionalResultBufferSize(additionalRenderSize * additionalRenderSize * m_textureFormat.getPixelSize())
263         , m_lineRasterizationStateInfo  ()
264 {
265         const DeviceInterface&                                          vkd                                             = m_context.getDeviceInterface();
266         const VkDevice                                                          vkDevice                                = m_context.getDevice();
267         const deUint32                                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
268         Allocator&                                                                      allocator                               = m_context.getDefaultAllocator();
269         DescriptorPoolBuilder                                           descriptorPoolBuilder;
270         DescriptorSetLayoutBuilder                                      descriptorSetLayoutBuilder;
271
272         // Command Pool
273         m_commandPool = createCommandPool(vkd, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
274
275         // Image
276         {
277                 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
278                 VkImageFormatProperties properties;
279
280                 if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
281                                                                                                                                                                          m_imageFormat,
282                                                                                                                                                                          VK_IMAGE_TYPE_2D,
283                                                                                                                                                                          VK_IMAGE_TILING_OPTIMAL,
284                                                                                                                                                                          imageUsage,
285                                                                                                                                                                          0,
286                                                                                                                                                                          &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
287                 {
288                         TCU_THROW(NotSupportedError, "Format not supported");
289                 }
290
291                 if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
292                 {
293                         TCU_THROW(NotSupportedError, "Format not supported");
294                 }
295
296                 const VkImageCreateInfo                                 imageCreateInfo                 =
297                 {
298                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
299                         DE_NULL,                                                                        // const void*                          pNext;
300                         0u,                                                                                     // VkImageCreateFlags           flags;
301                         VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
302                         m_imageFormat,                                                          // VkFormat                                     format;
303                         { m_renderSize, m_renderSize, 1u },                     // VkExtent3D                           extent;
304                         1u,                                                                                     // deUint32                                     mipLevels;
305                         1u,                                                                                     // deUint32                                     arrayLayers;
306                         m_sampleCount,                                                          // VkSampleCountFlagBits        samples;
307                         VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
308                         imageUsage,                                                                     // VkImageUsageFlags            usage;
309                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
310                         1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
311                         &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices;
312                         VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
313                 };
314
315                 m_image = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
316
317                 m_imageMemory   = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_image), MemoryRequirement::Any);
318                 VK_CHECK(vkd.bindImageMemory(vkDevice, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
319         }
320
321         // Image View
322         {
323                 const VkImageViewCreateInfo                             imageViewCreateInfo             =
324                 {
325                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                              sType;
326                         DE_NULL,                                                                        // const void*                                  pNext;
327                         0u,                                                                                     // VkImageViewCreateFlags               flags;
328                         *m_image,                                                                       // VkImage                                              image;
329                         VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                              viewType;
330                         m_imageFormat,                                                          // VkFormat                                             format;
331                         makeComponentMappingRGBA(),                                     // VkComponentMapping                   components;
332                         {
333                                 VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags                   aspectMask;
334                                 0u,                                                                                     // deUint32                                             baseMipLevel;
335                                 1u,                                                                                     // deUint32                                             mipLevels;
336                                 0u,                                                                                     // deUint32                                             baseArrayLayer;
337                                 1u,                                                                                     // deUint32                                             arraySize;
338                         },                                                                                      // VkImageSubresourceRange              subresourceRange;
339                 };
340
341                 m_imageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
342         }
343
344         if (m_multisampling)
345         {
346                 {
347                         // Resolved Image
348                         const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
349                         VkImageFormatProperties properties;
350
351                         if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
352                                                                                                                                                                                  m_imageFormat,
353                                                                                                                                                                                  VK_IMAGE_TYPE_2D,
354                                                                                                                                                                                  VK_IMAGE_TILING_OPTIMAL,
355                                                                                                                                                                                  imageUsage,
356                                                                                                                                                                                  0,
357                                                                                                                                                                                  &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
358                         {
359                                 TCU_THROW(NotSupportedError, "Format not supported");
360                         }
361
362                         const VkImageCreateInfo                                 imageCreateInfo                 =
363                         {
364                                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
365                                 DE_NULL,                                                                        // const void*                          pNext;
366                                 0u,                                                                                     // VkImageCreateFlags           flags;
367                                 VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
368                                 m_imageFormat,                                                          // VkFormat                                     format;
369                                 { m_renderSize, m_renderSize, 1u },                     // VkExtent3D                           extent;
370                                 1u,                                                                                     // deUint32                                     mipLevels;
371                                 1u,                                                                                     // deUint32                                     arrayLayers;
372                                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples;
373                                 VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
374                                 imageUsage,                                                                     // VkImageUsageFlags            usage;
375                                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
376                                 1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
377                                 &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices;
378                                 VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
379                         };
380
381                         m_resolvedImage                 = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
382                         m_resolvedImageMemory   = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_resolvedImage), MemoryRequirement::Any);
383                         VK_CHECK(vkd.bindImageMemory(vkDevice, *m_resolvedImage, m_resolvedImageMemory->getMemory(), m_resolvedImageMemory->getOffset()));
384                 }
385
386                 // Resolved Image View
387                 {
388                         const VkImageViewCreateInfo                             imageViewCreateInfo             =
389                         {
390                                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                              sType;
391                                 DE_NULL,                                                                        // const void*                                  pNext;
392                                 0u,                                                                                     // VkImageViewCreateFlags               flags;
393                                 *m_resolvedImage,                                                       // VkImage                                              image;
394                                 VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                              viewType;
395                                 m_imageFormat,                                                          // VkFormat                                             format;
396                                 makeComponentMappingRGBA(),                                     // VkComponentMapping                   components;
397                                 {
398                                         VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags                   aspectMask;
399                                         0u,                                                                                     // deUint32                                             baseMipLevel;
400                                         1u,                                                                                     // deUint32                                             mipLevels;
401                                         0u,                                                                                     // deUint32                                             baseArrayLayer;
402                                         1u,                                                                                     // deUint32                                             arraySize;
403                                 },                                                                                      // VkImageSubresourceRange              subresourceRange;
404                         };
405
406                         m_resolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
407                 }
408
409         }
410
411         // Render Pass
412         {
413                 const VkImageLayout                                             imageLayout                             = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
414                 const VkAttachmentDescription                   attachmentDesc[]                =
415                 {
416                         {
417                                 0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
418                                 m_imageFormat,                                                                          // VkFormat                                                     format;
419                                 m_sampleCount,                                                                          // VkSampleCountFlagBits                        samples;
420                                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
421                                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
422                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
423                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
424                                 imageLayout,                                                                            // VkImageLayout                                        initialLayout;
425                                 imageLayout,                                                                            // VkImageLayout                                        finalLayout;
426                         },
427                         {
428                                 0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
429                                 m_imageFormat,                                                                          // VkFormat                                                     format;
430                                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
431                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           loadOp;
432                                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
433                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
434                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
435                                 imageLayout,                                                                            // VkImageLayout                                        initialLayout;
436                                 imageLayout,                                                                            // VkImageLayout                                        finalLayout;
437                         }
438                 };
439
440                 const VkAttachmentReference                             attachmentRef                   =
441                 {
442                         0u,                                                                                                     // deUint32                                                     attachment;
443                         imageLayout,                                                                            // VkImageLayout                                        layout;
444                 };
445
446                 const VkAttachmentReference                             resolveAttachmentRef    =
447                 {
448                         1u,                                                                                                     // deUint32                                                     attachment;
449                         imageLayout,                                                                            // VkImageLayout                                        layout;
450                 };
451
452                 const VkSubpassDescription                              subpassDesc                             =
453                 {
454                         0u,                                                                                                     // VkSubpassDescriptionFlags            flags;
455                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
456                         0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
457                         DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
458                         1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
459                         &attachmentRef,                                                                         // const VkAttachmentReference*         pColorAttachments;
460                         m_multisampling ? &resolveAttachmentRef : DE_NULL,      // const VkAttachmentReference*         pResolveAttachments;
461                         DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
462                         0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
463                         DE_NULL,                                                                                        // const VkAttachmentReference*         pPreserveAttachments;
464                 };
465
466                 const VkRenderPassCreateInfo                    renderPassCreateInfo    =
467                 {
468                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
469                         DE_NULL,                                                                                        // const void*                                          pNext;
470                         0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
471                         m_multisampling ? 2u : 1u,                                                      // deUint32                                                     attachmentCount;
472                         attachmentDesc,                                                                         // const VkAttachmentDescription*       pAttachments;
473                         1u,                                                                                                     // deUint32                                                     subpassCount;
474                         &subpassDesc,                                                                           // const VkSubpassDescription*          pSubpasses;
475                         0u,                                                                                                     // deUint32                                                     dependencyCount;
476                         DE_NULL,                                                                                        // const VkSubpassDependency*           pDependencies;
477                 };
478
479                 m_renderPass =  createRenderPass(vkd, vkDevice, &renderPassCreateInfo, DE_NULL);
480         }
481
482         // FrameBuffer
483         {
484                 const VkImageView                                               attachments[]                   =
485                 {
486                         *m_imageView,
487                         *m_resolvedImageView
488                 };
489
490                 const VkFramebufferCreateInfo                   framebufferCreateInfo   =
491                 {
492                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                      sType;
493                         DE_NULL,                                                                        // const void*                          pNext;
494                         0u,                                                                                     // VkFramebufferCreateFlags     flags;
495                         *m_renderPass,                                                          // VkRenderPass                         renderPass;
496                         m_multisampling ? 2u : 1u,                                      // deUint32                                     attachmentCount;
497                         attachments,                                                            // const VkImageView*           pAttachments;
498                         m_renderSize,                                                           // deUint32                                     width;
499                         m_renderSize,                                                           // deUint32                                     height;
500                         1u,                                                                                     // deUint32                                     layers;
501                 };
502
503                 m_frameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
504         }
505
506         // Uniform Buffer
507         {
508                 const VkBufferCreateInfo                                bufferCreateInfo                =
509                 {
510                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
511                         DE_NULL,                                                                        // const void*                  pNext;
512                         0u,                                                                                     // VkBufferCreateFlags  flags;
513                         m_uniformBufferSize,                                            // VkDeviceSize                 size;
514                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,                     // VkBufferUsageFlags   usage;
515                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
516                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
517                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
518                 };
519
520                 m_uniformBuffer                 = createBuffer(vkd, vkDevice, &bufferCreateInfo);
521                 m_uniformBufferMemory   = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
522
523                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset()));
524         }
525
526         // Descriptors
527         {
528                 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
529                 m_descriptorPool = descriptorPoolBuilder.build(vkd, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
530
531                 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
532                 m_descriptorSetLayout = descriptorSetLayoutBuilder.build(vkd, vkDevice);
533
534                 const VkDescriptorSetAllocateInfo               descriptorSetParams             =
535                 {
536                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
537                         DE_NULL,
538                         *m_descriptorPool,
539                         1u,
540                         &m_descriptorSetLayout.get(),
541                 };
542
543                 m_descriptorSet = allocateDescriptorSet(vkd, vkDevice, &descriptorSetParams);
544
545                 const VkDescriptorBufferInfo                    descriptorBufferInfo    =
546                 {
547                         *m_uniformBuffer,                                                       // VkBuffer             buffer;
548                         0u,                                                                                     // VkDeviceSize offset;
549                         VK_WHOLE_SIZE                                                           // VkDeviceSize range;
550                 };
551
552                 const VkWriteDescriptorSet                              writeDescritporSet              =
553                 {
554                         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,         // VkStructureType                                      sType;
555                         DE_NULL,                                                                        // const void*                                          pNext;
556                         *m_descriptorSet,                                                       // VkDescriptorSet                                      destSet;
557                         0,                                                                                      // deUint32                                                     destBinding;
558                         0,                                                                                      // deUint32                                                     destArrayElement;
559                         1u,                                                                                     // deUint32                                                     count;
560                         VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,                      // VkDescriptorType                                     descriptorType;
561                         DE_NULL,                                                                        // const VkDescriptorImageInfo*         pImageInfo;
562                         &descriptorBufferInfo,                                          // const VkDescriptorBufferInfo*        pBufferInfo;
563                         DE_NULL                                                                         // const VkBufferView*                          pTexelBufferView;
564                 };
565
566                 vkd.updateDescriptorSets(vkDevice, 1u, &writeDescritporSet, 0u, DE_NULL);
567         }
568
569         // Pipeline Layout
570         {
571                 const VkPipelineLayoutCreateInfo                pipelineLayoutCreateInfo        =
572                 {
573                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
574                         DE_NULL,                                                                                        // const void*                                  pNext;
575                         0u,                                                                                                     // VkPipelineLayoutCreateFlags  flags;
576                         1u,                                                                                                     // deUint32                                             descriptorSetCount;
577                         &m_descriptorSetLayout.get(),                                           // const VkDescriptorSetLayout* pSetLayouts;
578                         0u,                                                                                                     // deUint32                                             pushConstantRangeCount;
579                         DE_NULL                                                                                         // const VkPushConstantRange*   pPushConstantRanges;
580                 };
581
582                 m_pipelineLayout = createPipelineLayout(vkd, vkDevice, &pipelineLayoutCreateInfo);
583         }
584
585         // Shaders
586         {
587                 m_vertexShaderModule    = createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("vertext_shader"), 0);
588                 m_fragmentShaderModule  = createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("fragment_shader"), 0);
589         }
590
591         // Result Buffer
592         {
593                 const VkBufferCreateInfo                                bufferCreateInfo                =
594                 {
595                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
596                         DE_NULL,                                                                        // const void*                  pNext;
597                         0u,                                                                                     // VkBufferCreateFlags  flags;
598                         m_resultBufferSize,                                                     // VkDeviceSize                 size;
599                         VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
600                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
601                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
602                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
603                 };
604
605                 m_resultBuffer                  = createBuffer(vkd, vkDevice, &bufferCreateInfo);
606                 m_resultBufferMemory    = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
607
608                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
609         }
610
611         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Sample count = " << getSampleCountFlagsStr(m_sampleCount) << tcu::TestLog::EndMessage;
612         m_context.getTestContext().getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
613 }
614
615 BaseRenderingTestInstance::~BaseRenderingTestInstance (void)
616 {
617 }
618
619
620 void BaseRenderingTestInstance::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
621 {
622
623         const DeviceInterface&                  vkd                                     = m_context.getDeviceInterface();
624
625         const VkImageSubresourceRange   subResourcerange        =
626         {
627                 VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
628                 0,                                                              // deUint32                             baseMipLevel;
629                 1,                                                              // deUint32                             levelCount;
630                 0,                                                              // deUint32                             baseArrayLayer;
631                 1                                                               // deUint32                             layerCount;
632         };
633
634         const VkImageMemoryBarrier              imageBarrier            =
635         {
636                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
637                 DE_NULL,                                                                        // const void*                          pNext;
638                 srcAccessMask,                                                          // VkAccessFlags                        srcAccessMask;
639                 dstAccessMask,                                                          // VkAccessFlags                        dstAccessMask;
640                 oldLayout,                                                                      // VkImageLayout                        oldLayout;
641                 newLayout,                                                                      // VkImageLayout                        newLayout;
642                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
643                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
644                 image,                                                                          // VkImage                                      image;
645                 subResourcerange                                                        // VkImageSubresourceRange      subresourceRange;
646         };
647
648         vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
649 }
650
651 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
652 {
653         // default to color white
654         const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
655
656         drawPrimitives(result, vertexData, colorData, primitiveTopology);
657 }
658
659 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology)
660 {
661         drawPrimitives(result, positionData, colorData, primitiveTopology, *m_image, *m_resolvedImage, *m_frameBuffer, m_renderSize, *m_resultBuffer, *m_resultBufferMemory);
662 }
663 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology,
664                                         VkImage image, VkImage resolvedImage, VkFramebuffer frameBuffer, const deUint32 renderSize, VkBuffer resultBuffer, const Allocation& resultBufferMemory)
665 {
666         const DeviceInterface&                                          vkd                                             = m_context.getDeviceInterface();
667         const VkDevice                                                          vkDevice                                = m_context.getDevice();
668         const VkQueue                                                           queue                                   = m_context.getUniversalQueue();
669         const deUint32                                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
670         Allocator&                                                                      allocator                               = m_context.getDefaultAllocator();
671         const size_t                                                            attributeBatchSize              = positionData.size() * sizeof(tcu::Vec4);
672
673         Move<VkCommandBuffer>                                           commandBuffer;
674         Move<VkPipeline>                                                        graphicsPipeline;
675         Move<VkBuffer>                                                          vertexBuffer;
676         de::MovePtr<Allocation>                                         vertexBufferMemory;
677         const VkPhysicalDeviceProperties                        properties                              = m_context.getDeviceProperties();
678
679         if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
680         {
681                 std::stringstream message;
682                 message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
683                 TCU_THROW(NotSupportedError, message.str().c_str());
684         }
685
686         // Create Graphics Pipeline
687         {
688                 const VkVertexInputBindingDescription   vertexInputBindingDescription =
689                 {
690                         0u,                                                             // deUint32                                     binding;
691                         sizeof(tcu::Vec4),                              // deUint32                                     strideInBytes;
692                         VK_VERTEX_INPUT_RATE_VERTEX             // VkVertexInputStepRate        stepRate;
693                 };
694
695                 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
696                 {
697                         {
698                                 0u,                                                                     // deUint32     location;
699                                 0u,                                                                     // deUint32     binding;
700                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
701                                 0u                                                                      // deUint32     offsetInBytes;
702                         },
703                         {
704                                 1u,                                                                     // deUint32     location;
705                                 0u,                                                                     // deUint32     binding;
706                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
707                                 (deUint32)attributeBatchSize            // deUint32     offsetInBytes;
708                         }
709                 };
710
711                 const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams =
712                 {
713                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
714                         DE_NULL,                                                                                                                // const void*                                                          pNext;
715                         0,                                                                                                                              // VkPipelineVertexInputStateCreateFlags        flags;
716                         1u,                                                                                                                             // deUint32                                                                     bindingCount;
717                         &vertexInputBindingDescription,                                                                 // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
718                         2u,                                                                                                                             // deUint32                                                                     attributeCount;
719                         vertexInputAttributeDescriptions                                                                // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
720                 };
721
722                 const std::vector<VkViewport>   viewports       (1, makeViewport(tcu::UVec2(renderSize)));
723                 const std::vector<VkRect2D>             scissors        (1, makeRect2D(tcu::UVec2(renderSize)));
724
725                 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
726                 {
727                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
728                         DE_NULL,                                                                                                                // const void*                                                          pNext;
729                         0u,                                                                                                                             // VkPipelineMultisampleStateCreateFlags        flags;
730                         m_sampleCount,                                                                                                  // VkSampleCountFlagBits                                        rasterizationSamples;
731                         VK_FALSE,                                                                                                               // VkBool32                                                                     sampleShadingEnable;
732                         0.0f,                                                                                                                   // float                                                                        minSampleShading;
733                         DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
734                         VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
735                         VK_FALSE                                                                                                                // VkBool32                                                                     alphaToOneEnable;
736                 };
737
738
739                 VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = *getRasterizationStateCreateInfo();
740
741                 const VkPipelineRasterizationLineStateCreateInfoEXT* lineRasterizationStateInfo = getLineRasterizationStateCreateInfo();
742
743                 if (lineRasterizationStateInfo != DE_NULL)
744                         appendStructurePtrToVulkanChain(&rasterizationStateInfo.pNext, lineRasterizationStateInfo);
745
746                 VkPipelineDynamicStateCreateInfo                        dynamicStateCreateInfo =
747                 {
748                         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,   // VkStructureType                      sType
749                         DE_NULL,                                                                                                // const void*                          pNext
750                         0u,                                                                                                             // VkPipelineDynamicStateCreateFlags    flags
751                         0u,                                                                                                             // deUint32                             dynamicStateCount
752                         DE_NULL                                                                                                 // const VkDynamicState*                pDynamicStates
753                 };
754
755                 VkDynamicState dynamicState = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
756                 if (getLineStippleDynamic())
757                 {
758                         dynamicStateCreateInfo.dynamicStateCount = 1;
759                         dynamicStateCreateInfo.pDynamicStates = &dynamicState;
760                 }
761
762                 graphicsPipeline = makeGraphicsPipeline(vkd,                                                            // const DeviceInterface&                        vk
763                                                                                                 vkDevice,                                                       // const VkDevice                                device
764                                                                                                 *m_pipelineLayout,                                      // const VkPipelineLayout                        pipelineLayout
765                                                                                                 *m_vertexShaderModule,                          // const VkShaderModule                          vertexShaderModule
766                                                                                                 DE_NULL,                                                        // const VkShaderModule                          tessellationControlShaderModule
767                                                                                                 DE_NULL,                                                        // const VkShaderModule                          tessellationEvalShaderModule
768                                                                                                 DE_NULL,                                                        // const VkShaderModule                          geometryShaderModule
769                                                                                                 *m_fragmentShaderModule,                        // const VkShaderModule                          fragmentShaderModule
770                                                                                                 *m_renderPass,                                          // const VkRenderPass                            renderPass
771                                                                                                 viewports,                                                      // const std::vector<VkViewport>&                viewports
772                                                                                                 scissors,                                                       // const std::vector<VkRect2D>&                  scissors
773                                                                                                 primitiveTopology,                                      // const VkPrimitiveTopology                     topology
774                                                                                                 0u,                                                                     // const deUint32                                subpass
775                                                                                                 0u,                                                                     // const deUint32                                patchControlPoints
776                                                                                                 &vertexInputStateParams,                        // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
777                                                                                                 &rasterizationStateInfo,                        // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
778                                                                                                 &multisampleStateParams,                        // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
779                                                                                                 DE_NULL,                                                        // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo,
780                                                                                                 getColorBlendStateCreateInfo(),         // const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo,
781                                                                                                 &dynamicStateCreateInfo);                       // const VkPipelineDynamicStateCreateInfo*       dynamicStateCreateInfo
782         }
783
784         // Create Vertex Buffer
785         {
786                 const VkBufferCreateInfo                        vertexBufferParams              =
787                 {
788                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
789                         DE_NULL,                                                                        // const void*                  pNext;
790                         0u,                                                                                     // VkBufferCreateFlags  flags;
791                         attributeBatchSize * 2,                                         // VkDeviceSize                 size;
792                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
793                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
794                         1u,                                                                                     // deUint32                             queueFamilyCount;
795                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
796                 };
797
798                 vertexBuffer            = createBuffer(vkd, vkDevice, &vertexBufferParams);
799                 vertexBufferMemory      = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
800
801                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
802
803                 // Load vertices into vertex buffer
804                 deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
805                 deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) +  attributeBatchSize, colorData.data(), attributeBatchSize);
806                 flushAlloc(vkd, vkDevice, *vertexBufferMemory);
807         }
808
809         // Create Command Buffer
810         commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
811
812         // Begin Command Buffer
813         beginCommandBuffer(vkd, *commandBuffer);
814
815         addImageTransitionBarrier(*commandBuffer, image,
816                                                           VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                            // VkPipelineStageFlags         srcStageMask
817                                                           VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                           // VkPipelineStageFlags         dstStageMask
818                                                           0,                                                                                            // VkAccessFlags                        srcAccessMask
819                                                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        dstAccessMask
820                                                           VK_IMAGE_LAYOUT_UNDEFINED,                                            // VkImageLayout                        oldLayout;
821                                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);            // VkImageLayout                        newLayout;
822
823         if (m_multisampling) {
824                 addImageTransitionBarrier(*commandBuffer, resolvedImage,
825                                                                   VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                            // VkPipelineStageFlags         srcStageMask
826                                                                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                           // VkPipelineStageFlags         dstStageMask
827                                                                   0,                                                                                            // VkAccessFlags                        srcAccessMask
828                                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        dstAccessMask
829                                                                   VK_IMAGE_LAYOUT_UNDEFINED,                                            // VkImageLayout                        oldLayout;
830                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);            // VkImageLayout                        newLayout;
831         }
832
833         // Begin Render Pass
834         beginRenderPass(vkd, *commandBuffer, *m_renderPass, frameBuffer, vk::makeRect2D(0, 0, renderSize, renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
835
836         const VkDeviceSize                                              vertexBufferOffset              = 0;
837
838         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
839         vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
840         vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
841         if (getLineStippleDynamic())
842                 vkd.cmdSetLineStippleEXT(*commandBuffer, lineStippleFactor, lineStipplePattern);
843         vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
844         endRenderPass(vkd, *commandBuffer);
845
846         // Copy Image
847         copyImageToBuffer(vkd, *commandBuffer, m_multisampling ? resolvedImage : image, resultBuffer, tcu::IVec2(renderSize, renderSize));
848
849         endCommandBuffer(vkd, *commandBuffer);
850
851         // Set Point Size
852         {
853                 float   pointSize       = getPointSize();
854                 deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
855                 flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
856         }
857
858         // Submit
859         submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
860
861         invalidateAlloc(vkd, vkDevice, resultBufferMemory);
862         tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(renderSize, renderSize, 1), resultBufferMemory.getHostPtr()));
863 }
864
865 float BaseRenderingTestInstance::getLineWidth (void) const
866 {
867         return 1.0f;
868 }
869
870 float BaseRenderingTestInstance::getPointSize (void) const
871 {
872         return 1.0f;
873 }
874
875 const VkPipelineRasterizationStateCreateInfo* BaseRenderingTestInstance::getRasterizationStateCreateInfo (void) const
876 {
877         static VkPipelineRasterizationStateCreateInfo   rasterizationStateCreateInfo    =
878         {
879                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
880                 DE_NULL,                                                                                                                // const void*                                                          pNext;
881                 0,                                                                                                                              // VkPipelineRasterizationStateCreateFlags      flags;
882                 false,                                                                                                                  // VkBool32                                                                     depthClipEnable;
883                 false,                                                                                                                  // VkBool32                                                                     rasterizerDiscardEnable;
884                 VK_POLYGON_MODE_FILL,                                                                                   // VkFillMode                                                           fillMode;
885                 VK_CULL_MODE_NONE,                                                                                              // VkCullMode                                                           cullMode;
886                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
887                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
888                 0.0f,                                                                                                                   // float                                                                        depthBias;
889                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
890                 0.0f,                                                                                                                   // float                                                                        slopeScaledDepthBias;
891                 getLineWidth(),                                                                                                 // float                                                                        lineWidth;
892         };
893
894         rasterizationStateCreateInfo.lineWidth = getLineWidth();
895         return &rasterizationStateCreateInfo;
896 }
897
898 VkPipelineRasterizationLineStateCreateInfoEXT BaseRenderingTestInstance::initLineRasterizationStateCreateInfo (void) const
899 {
900         VkPipelineRasterizationLineStateCreateInfoEXT lineRasterizationStateInfo =
901         {
902                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT,    // VkStructureType                              sType;
903                 DE_NULL,                                                                                                                                // const void*                                  pNext;
904                 VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,                                                                 // VkLineRasterizationModeEXT   lineRasterizationMode;
905                 VK_FALSE,                                                                                                                               // VkBool32                                             stippledLineEnable;
906                 1,                                                                                                                                              // uint32_t                                             lineStippleFactor;
907                 0xFFFF,                                                                                                                                 // uint16_t                                             lineStipplePattern;
908         };
909
910         return lineRasterizationStateInfo;
911 }
912
913 const VkPipelineRasterizationLineStateCreateInfoEXT* BaseRenderingTestInstance::getLineRasterizationStateCreateInfo (void)
914 {
915         if (m_lineRasterizationStateInfo.sType != VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT)
916                 m_lineRasterizationStateInfo = initLineRasterizationStateCreateInfo();
917
918         return &m_lineRasterizationStateInfo;
919 }
920
921 const VkPipelineColorBlendStateCreateInfo* BaseRenderingTestInstance::getColorBlendStateCreateInfo (void) const
922 {
923         static const VkPipelineColorBlendAttachmentState        colorBlendAttachmentState       =
924         {
925                 false,                                                                                                          // VkBool32                     blendEnable;
926                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendColor;
927                 VK_BLEND_FACTOR_ZERO,                                                                           // VkBlend                      destBlendColor;
928                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpColor;
929                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendAlpha;
930                 VK_BLEND_FACTOR_ZERO,                                                                           // VkBlend                      destBlendAlpha;
931                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpAlpha;
932                 (VK_COLOR_COMPONENT_R_BIT |
933                  VK_COLOR_COMPONENT_G_BIT |
934                  VK_COLOR_COMPONENT_B_BIT |
935                  VK_COLOR_COMPONENT_A_BIT)                                                                      // VkChannelFlags       channelWriteMask;
936         };
937
938         static const VkPipelineColorBlendStateCreateInfo        colorBlendStateParams           =
939         {
940                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
941                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
942                 0,                                                                                                                      // VkPipelineColorBlendStateCreateFlags                 flags;
943                 false,                                                                                                          // VkBool32                                                                             logicOpEnable;
944                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
945                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
946                 &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
947                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConst[4];
948         };
949
950         return &colorBlendStateParams;
951 }
952
953 const tcu::TextureFormat& BaseRenderingTestInstance::getTextureFormat (void) const
954 {
955         return m_textureFormat;
956 }
957
958 class BaseTriangleTestInstance : public BaseRenderingTestInstance
959 {
960 public:
961                                                         BaseTriangleTestInstance        (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount, deUint32 renderSize = RESOLUTION_POT);
962         virtual tcu::TestStatus iterate                                         (void);
963
964 protected:
965         int                                             getIteration                            (void) const    { return m_iteration;           }
966         int                                             getIterationCount                       (void) const    { return m_iterationCount;      }
967
968 private:
969         virtual void                    generateTriangles                       (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
970         virtual bool                    compareAndVerify                        (std::vector<TriangleSceneSpec::SceneTriangle>& triangles,
971                                                                                                                  tcu::Surface&                                                                  resultImage,
972                                                                                                                  std::vector<tcu::Vec4>&                                                drawBuffer);
973
974         int                                             m_iteration;
975         const int                               m_iterationCount;
976         VkPrimitiveTopology             m_primitiveTopology;
977         bool                                    m_allIterationsPassed;
978 };
979
980 BaseTriangleTestInstance::BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount, deUint32 renderSize)
981         : BaseRenderingTestInstance             (context, sampleCount, renderSize)
982         , m_iteration                                   (0)
983         , m_iterationCount                              (3)
984         , m_primitiveTopology                   (primitiveTopology)
985         , m_allIterationsPassed                 (true)
986 {
987 }
988
989 tcu::TestStatus BaseTriangleTestInstance::iterate (void)
990 {
991         const std::string                                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
992         const tcu::ScopedLogSection                                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
993         tcu::Surface                                                                    resultImage                             (m_renderSize, m_renderSize);
994         std::vector<tcu::Vec4>                                                  drawBuffer;
995         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
996
997         generateTriangles(m_iteration, drawBuffer, triangles);
998
999         // draw image
1000         drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1001
1002         // compare
1003         {
1004                 const bool compareOk = compareAndVerify(triangles, resultImage, drawBuffer);
1005
1006                 if (!compareOk)
1007                         m_allIterationsPassed = false;
1008         }
1009
1010         // result
1011         if (++m_iteration == m_iterationCount)
1012         {
1013                 if (m_allIterationsPassed)
1014                         return tcu::TestStatus::pass("Pass");
1015                 else
1016                         return tcu::TestStatus::fail("Incorrect rasterization");
1017         }
1018         else
1019                 return tcu::TestStatus::incomplete();
1020 }
1021
1022 bool BaseTriangleTestInstance::compareAndVerify (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage, std::vector<tcu::Vec4>&)
1023 {
1024         RasterizationArguments  args;
1025         TriangleSceneSpec               scene;
1026
1027         tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1028
1029         args.numSamples         = m_multisampling ? 1 : 0;
1030         args.subpixelBits       = m_subpixelBits;
1031         args.redBits            = colorBits[0];
1032         args.greenBits          = colorBits[1];
1033         args.blueBits           = colorBits[2];
1034
1035         scene.triangles.swap(triangles);
1036
1037         return verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1038 }
1039
1040 class BaseLineTestInstance : public BaseRenderingTestInstance
1041 {
1042 public:
1043                                                                 BaseLineTestInstance    (Context&                                       context,
1044                                                                                                                  VkPrimitiveTopology            primitiveTopology,
1045                                                                                                                  PrimitiveWideness                      wideness,
1046                                                                                                                  PrimitiveStrictness            strictness,
1047                                                                                                                  VkSampleCountFlagBits          sampleCount,
1048                                                                                                                  LineStipple                            stipple,
1049                                                                                                                  VkLineRasterizationModeEXT     lineRasterizationMode,
1050                                                                                                                  const deUint32                         additionalRenderSize = 0,
1051                                                                                                                  const deUint32                         renderSize = RESOLUTION_POT,
1052                                                                                                                  const float                            narrowLineWidth = 1.0f);
1053         virtual tcu::TestStatus         iterate                                 (void);
1054         virtual float                           getLineWidth                    (void) const;
1055         bool                                            getLineStippleEnable    (void) const { return m_stipple != LINESTIPPLE_DISABLED; }
1056         virtual bool                            getLineStippleDynamic   (void) const { return m_stipple == LINESTIPPLE_DYNAMIC; };
1057
1058         virtual
1059         VkPipelineRasterizationLineStateCreateInfoEXT   initLineRasterizationStateCreateInfo    (void) const;
1060
1061         virtual
1062         const VkPipelineRasterizationLineStateCreateInfoEXT*    getLineRasterizationStateCreateInfo     (void);
1063
1064 protected:
1065         int                                                     getIteration                    (void) const    { return m_iteration;           }
1066         int                                                     getIterationCount               (void) const    { return m_iterationCount;      }
1067
1068 private:
1069         virtual void                            generateLines                   (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
1070         virtual bool                            compareAndVerify                (std::vector<LineSceneSpec::SceneLine>& lines,
1071                                                                                                                  tcu::Surface&                                                  resultImage,
1072                                                                                                                  std::vector<tcu::Vec4>&                                drawBuffer);
1073
1074         bool                                            resultHasAlpha                  (tcu::Surface& result);
1075
1076         int                                                     m_iteration;
1077         const int                                       m_iterationCount;
1078         VkPrimitiveTopology                     m_primitiveTopology;
1079         const PrimitiveWideness         m_primitiveWideness;
1080         const PrimitiveStrictness       m_primitiveStrictness;
1081         bool                                            m_allIterationsPassed;
1082         bool                                            m_qualityWarning;
1083         float                                           m_maxLineWidth;
1084         std::vector<float>                      m_lineWidths;
1085         LineStipple                                     m_stipple;
1086         VkLineRasterizationModeEXT      m_lineRasterizationMode;
1087         Move<VkImage>                           m_additionalImage;
1088         de::MovePtr<Allocation>         m_additionalImageMemory;
1089         Move<VkImageView>                       m_additionalImageView;
1090         Move<VkImage>                           m_additionalResolvedImage;
1091         de::MovePtr<Allocation>         m_additionalResolvedImageMemory;
1092         Move<VkImageView>                       m_additionalResolvedImageView;
1093         Move<VkFramebuffer>                     m_additionalFrameBuffer;
1094         Move<VkBuffer>                          m_additionalResultBuffer;
1095         de::MovePtr<Allocation>         m_additionalResultBufferMemory;
1096 };
1097
1098 BaseLineTestInstance::BaseLineTestInstance (Context&                                    context,
1099                                                                                         VkPrimitiveTopology                     primitiveTopology,
1100                                                                                         PrimitiveWideness                       wideness,
1101                                                                                         PrimitiveStrictness                     strictness,
1102                                                                                         VkSampleCountFlagBits           sampleCount,
1103                                                                                         LineStipple                                     stipple,
1104                                                                                         VkLineRasterizationModeEXT      lineRasterizationMode,
1105                                                                                         const deUint32                          additionalRenderSize,
1106                                                                                         const deUint32                          renderSize,
1107                                                                                         const float                                     narrowLineWidth)
1108         : BaseRenderingTestInstance     (context, sampleCount, renderSize, VK_FORMAT_R8G8B8A8_UNORM, additionalRenderSize)
1109         , m_iteration                           (0)
1110         , m_iterationCount                      (3)
1111         , m_primitiveTopology           (primitiveTopology)
1112         , m_primitiveWideness           (wideness)
1113         , m_primitiveStrictness         (strictness)
1114         , m_allIterationsPassed         (true)
1115         , m_qualityWarning                      (false)
1116         , m_maxLineWidth                        (1.0f)
1117         , m_stipple                                     (stipple)
1118         , m_lineRasterizationMode       (lineRasterizationMode)
1119 {
1120         DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
1121
1122         if (m_lineRasterizationMode != VK_LINE_RASTERIZATION_MODE_EXT_LAST)
1123         {
1124                 if (context.isDeviceFunctionalitySupported("VK_EXT_line_rasterization"))
1125                 {
1126                         VkPhysicalDeviceLineRasterizationPropertiesEXT lineRasterizationProperties =
1127                         {
1128                                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT,    // VkStructureType      sType;
1129                                 DE_NULL,                                                                                                                                // void*                        pNext;
1130                                 0u,                                                                                                                                             // deUint32                     lineSubPixelPrecisionBits;
1131                         };
1132
1133                         VkPhysicalDeviceProperties2 deviceProperties2;
1134                         deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1135                         deviceProperties2.pNext = &lineRasterizationProperties;
1136
1137                         context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &deviceProperties2);
1138
1139                         m_subpixelBits = lineRasterizationProperties.lineSubPixelPrecisionBits;
1140                 }
1141         }
1142
1143         // create line widths
1144         if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1145         {
1146                 m_lineWidths.resize(m_iterationCount, narrowLineWidth);
1147
1148                 // Bump up m_maxLineWidth for conservative rasterization
1149                 if (narrowLineWidth > m_maxLineWidth)
1150                         m_maxLineWidth = narrowLineWidth;
1151         }
1152         else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1153         {
1154                 const float*    range = context.getDeviceProperties().limits.lineWidthRange;
1155
1156                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1157
1158                 DE_ASSERT(range[1] > 1.0f);
1159
1160                 // set hand picked sizes
1161                 m_lineWidths.push_back(5.0f);
1162                 m_lineWidths.push_back(10.0f);
1163
1164                 // Do not pick line width with 0.5 fractional value as rounding direction is not defined.
1165                 if (deFloatFrac(range[1]) == 0.5f)
1166                 {
1167                         m_lineWidths.push_back(range[1] - context.getDeviceProperties().limits.lineWidthGranularity);
1168                 }
1169                 else
1170                 {
1171                         m_lineWidths.push_back(range[1]);
1172                 }
1173
1174                 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
1175
1176                 m_maxLineWidth = range[1];
1177         }
1178         else
1179                 DE_ASSERT(false);
1180
1181         // Create image, image view and frame buffer for testing at an additional resolution if required.
1182         if (m_additionalRenderSize != 0)
1183         {
1184                 const DeviceInterface&                                          vkd                                             = m_context.getDeviceInterface();
1185                 const VkDevice                                                          vkDevice                                = m_context.getDevice();
1186                 const deUint32                                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
1187                 Allocator&                                                                      allocator                               = m_context.getDefaultAllocator();
1188                 DescriptorPoolBuilder                                           descriptorPoolBuilder;
1189                 DescriptorSetLayoutBuilder                                      descriptorSetLayoutBuilder;
1190                 {
1191                         const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1192                         const VkImageCreateInfo                                 imageCreateInfo                 =
1193                         {
1194                                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
1195                                 DE_NULL,                                                                        // const void*                          pNext;
1196                                 0u,                                                                                     // VkImageCreateFlags           flags;
1197                                 VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
1198                                 m_imageFormat,                                                          // VkFormat                                     format;
1199                                 { m_additionalRenderSize, m_additionalRenderSize, 1u },                 // VkExtent3D                           extent;
1200                                 1u,                                                                                     // deUint32                                     mipLevels;
1201                                 1u,                                                                                     // deUint32                                     arrayLayers;
1202                                 m_sampleCount,                                                          // VkSampleCountFlagBits        samples;
1203                                 VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
1204                                 imageUsage,                                                                     // VkImageUsageFlags            usage;
1205                                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
1206                                 1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
1207                                 &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices;
1208                                 VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
1209                         };
1210
1211                         m_additionalImage = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
1212
1213                         m_additionalImageMemory = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_additionalImage), MemoryRequirement::Any);
1214                         VK_CHECK(vkd.bindImageMemory(vkDevice, *m_additionalImage, m_additionalImageMemory->getMemory(), m_additionalImageMemory->getOffset()));
1215                 }
1216
1217                 // Image View
1218                 {
1219                         const VkImageViewCreateInfo                             imageViewCreateInfo             =
1220                         {
1221                                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                              sType;
1222                                 DE_NULL,                                                                        // const void*                                  pNext;
1223                                 0u,                                                                                     // VkImageViewCreateFlags               flags;
1224                                 *m_additionalImage,                                                     // VkImage                                              image;
1225                                 VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                              viewType;
1226                                 m_imageFormat,                                                          // VkFormat                                             format;
1227                                 makeComponentMappingRGBA(),                                     // VkComponentMapping                   components;
1228                                 {
1229                                         VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags                   aspectMask;
1230                                         0u,                                                                                     // deUint32                                             baseMipLevel;
1231                                         1u,                                                                                     // deUint32                                             mipLevels;
1232                                         0u,                                                                                     // deUint32                                             baseArrayLayer;
1233                                         1u,                                                                                     // deUint32                                             arraySize;
1234                                 },                                                                                      // VkImageSubresourceRange              subresourceRange;
1235                         };
1236
1237                         m_additionalImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
1238                 }
1239
1240                 if (m_multisampling)
1241                 {
1242                         {
1243                                 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1244                                 const VkImageCreateInfo                                 imageCreateInfo                 =
1245                                 {
1246                                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
1247                                         DE_NULL,                                                                        // const void*                          pNext;
1248                                         0u,                                                                                     // VkImageCreateFlags           flags;
1249                                         VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
1250                                         m_imageFormat,                                                          // VkFormat                                     format;
1251                                         { m_additionalRenderSize,       m_additionalRenderSize, 1u },                   // VkExtent3D                           extent;
1252                                         1u,                                                                                     // deUint32                                     mipLevels;
1253                                         1u,                                                                                     // deUint32                                     arrayLayers;
1254                                         VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples;
1255                                         VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling                        tiling;
1256                                         imageUsage,                                                                     // VkImageUsageFlags            usage;
1257                                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                        sharingMode;
1258                                         1u,                                                                                     // deUint32                                     queueFamilyIndexCount;
1259                                         &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices;
1260                                         VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
1261                                 };
1262
1263                                 m_additionalResolvedImage                       = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
1264                                 m_additionalResolvedImageMemory = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_additionalResolvedImage), MemoryRequirement::Any);
1265                                 VK_CHECK(vkd.bindImageMemory(vkDevice, *m_additionalResolvedImage, m_additionalResolvedImageMemory->getMemory(), m_additionalResolvedImageMemory->getOffset()));
1266                         }
1267
1268                         // Image view
1269                         {
1270                                 const VkImageViewCreateInfo                             imageViewCreateInfo             =
1271                                 {
1272                                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                              sType;
1273                                         DE_NULL,                                                                        // const void*                                  pNext;
1274                                         0u,                                                                                     // VkImageViewCreateFlags               flags;
1275                                         *m_additionalResolvedImage,                                     // VkImage                                              image;
1276                                         VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                              viewType;
1277                                         m_imageFormat,                                                          // VkFormat                                             format;
1278                                         makeComponentMappingRGBA(),                                     // VkComponentMapping                   components;
1279                                         {
1280                                                 VK_IMAGE_ASPECT_COLOR_BIT,                                      // VkImageAspectFlags                   aspectMask;
1281                                                 0u,                                                                                     // deUint32                                             baseMipLevel;
1282                                                 1u,                                                                                     // deUint32                                             mipLevels;
1283                                                 0u,                                                                                     // deUint32                                             baseArrayLayer;
1284                                                 1u,                                                                                     // deUint32                                             arraySize;
1285                                         },                                                                                      // VkImageSubresourceRange              subresourceRange;
1286                                 };
1287                                 m_additionalResolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
1288                         }
1289                 }
1290
1291                 {
1292                         const VkImageView                                               attachments[]                   =
1293                         {
1294                                 *m_additionalImageView,
1295                                 *m_additionalResolvedImageView
1296                         };
1297
1298                         const VkFramebufferCreateInfo                   framebufferCreateInfo   =
1299                         {
1300                                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                      sType;
1301                                 DE_NULL,                                                                        // const void*                          pNext;
1302                                 0u,                                                                                     // VkFramebufferCreateFlags     flags;
1303                                 *m_renderPass,                                                          // VkRenderPass                         renderPass;
1304                                 m_multisampling ? 2u : 1u,                                      // deUint32                                     attachmentCount;
1305                                 attachments,                                                            // const VkImageView*           pAttachments;
1306                                 m_additionalRenderSize,                                         // deUint32                                     width;
1307                                 m_additionalRenderSize,                                         // deUint32                                     height;
1308                                 1u,                                                                                     // deUint32                                     layers;
1309                         };
1310                         m_additionalFrameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
1311                 }
1312
1313                 // Framebuffer
1314                 {
1315                         const VkBufferCreateInfo                                bufferCreateInfo                =
1316                         {
1317                                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
1318                                 DE_NULL,                                                                        // const void*                  pNext;
1319                                 0u,                                                                                     // VkBufferCreateFlags  flags;
1320                                 m_additionalResultBufferSize,                                                   // VkDeviceSize                 size;
1321                                 VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
1322                                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
1323                                 1u,                                                                                     // deUint32                             queueFamilyIndexCount;
1324                                 &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
1325                         };
1326
1327                         m_additionalResultBuffer                        = createBuffer(vkd, vkDevice, &bufferCreateInfo);
1328                         m_additionalResultBufferMemory  = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_additionalResultBuffer), MemoryRequirement::HostVisible);
1329
1330                         VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_additionalResultBuffer, m_additionalResultBufferMemory->getMemory(), m_additionalResultBufferMemory->getOffset()));
1331                 }
1332         }
1333 }
1334
1335 bool BaseLineTestInstance::resultHasAlpha(tcu::Surface& resultImage)
1336 {
1337         bool hasAlpha = false;
1338         for (int y = 0; y < resultImage.getHeight() && !hasAlpha; ++y)
1339         for (int x = 0; x < resultImage.getWidth(); ++x)
1340         {
1341                 const tcu::RGBA         color                           = resultImage.getPixel(x, y);
1342                 if (color.getAlpha() > 0 && color.getAlpha() < 0xFF)
1343                 {
1344                         hasAlpha = true;
1345                         break;
1346                 }
1347         }
1348         return hasAlpha;
1349 }
1350
1351 tcu::TestStatus BaseLineTestInstance::iterate (void)
1352 {
1353         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1354         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1355         const float                                                             lineWidth                               = getLineWidth();
1356         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
1357         std::vector<tcu::Vec4>                                  drawBuffer;
1358         std::vector<LineSceneSpec::SceneLine>   lines;
1359
1360         // supported?
1361         if (lineWidth <= m_maxLineWidth)
1362         {
1363                 // gen data
1364                 generateLines(m_iteration, drawBuffer, lines);
1365
1366                 // draw image
1367                 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1368
1369                 // compare
1370                 {
1371                         const bool compareOk = compareAndVerify(lines, resultImage, drawBuffer);
1372
1373                         if (!compareOk)
1374                                 m_allIterationsPassed = false;
1375                 }
1376         }
1377         else
1378                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1379
1380         // result
1381         if (++m_iteration == m_iterationCount)
1382         {
1383                 if (!m_allIterationsPassed)
1384                         return tcu::TestStatus::fail("Incorrect rasterization");
1385                 else if (m_qualityWarning)
1386                         return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality line rasterization");
1387                 else
1388                         return tcu::TestStatus::pass("Pass");
1389         }
1390         else
1391                 return tcu::TestStatus::incomplete();
1392 }
1393
1394 bool BaseLineTestInstance::compareAndVerify (std::vector<LineSceneSpec::SceneLine>&     lines, tcu::Surface& resultImage, std::vector<tcu::Vec4>& drawBuffer)
1395 {
1396         const float                             lineWidth                               = getLineWidth();
1397         bool                                    result                                  = true;
1398         tcu::Surface                    additionalResultImage   (m_additionalRenderSize, m_additionalRenderSize);
1399         RasterizationArguments  args;
1400         LineSceneSpec                   scene;
1401         tcu::IVec4                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
1402         bool                                    strict          = m_primitiveStrictness == PRIMITIVESTRICTNESS_STRICT;
1403
1404         args.numSamples         = m_multisampling ? 1 : 0;
1405         args.subpixelBits       = m_subpixelBits;
1406         args.redBits            = colorBits[0];
1407         args.greenBits          = colorBits[1];
1408         args.blueBits           = colorBits[2];
1409
1410         scene.lines.swap(lines);
1411         scene.lineWidth = lineWidth;
1412         scene.stippleEnable = getLineStippleEnable();
1413         scene.stippleFactor = getLineStippleEnable() ? lineStippleFactor : 1;
1414         scene.stipplePattern = getLineStippleEnable() ? lineStipplePattern : 0xFFFF;
1415         scene.isStrip = m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
1416         scene.isSmooth = m_lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
1417
1418         // Choose verification mode. Smooth lines assume mostly over-rasterization (bloated lines with a falloff).
1419         // Stippled lines lose some precision across segments in a strip, so need a weaker threshold than normal
1420         // lines. For simple cases, check for an exact match (STRICT).
1421         if (scene.isSmooth)
1422                 scene.verificationMode = tcu::VERIFICATIONMODE_SMOOTH;
1423         else if (scene.stippleEnable)
1424                 scene.verificationMode = tcu::VERIFICATIONMODE_WEAKER;
1425         else
1426                 scene.verificationMode = tcu::VERIFICATIONMODE_STRICT;
1427
1428         if (m_lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT)
1429         {
1430                 // bresenham is "no AA" in GL, so set numSamples to zero.
1431                 args.numSamples = 0;
1432                 if (!verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()))
1433                         result = false;
1434         }
1435         else
1436         {
1437                 if (scene.isSmooth)
1438                 {
1439                         // Smooth lines get the fractional coverage multiplied into the alpha component,
1440                         // so do a sanity check to validate that there is at least one pixel in the image
1441                         // with a fractional opacity.
1442                         bool hasAlpha = resultHasAlpha(resultImage);
1443                         if (!hasAlpha)
1444                         {
1445                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Missing alpha transparency (failed)." << tcu::TestLog::EndMessage;
1446                                 result = false;
1447                         }
1448                 }
1449
1450                 if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), (0 == m_multisampling), strict))
1451                 {
1452                         // Retry with weaker verification. If it passes, consider it a quality warning.
1453                         scene.verificationMode = tcu::VERIFICATIONMODE_WEAKER;
1454                         if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), false, strict))
1455                                 result = false;
1456                         else
1457                                 m_qualityWarning = true;
1458                 }
1459
1460                 if (m_additionalRenderSize != 0)
1461                 {
1462                         const std::vector<tcu::Vec4> colorData(drawBuffer.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1463
1464                         if (scene.isSmooth)
1465                                 scene.verificationMode = tcu::VERIFICATIONMODE_SMOOTH;
1466                         else if (scene.stippleEnable)
1467                                 scene.verificationMode = tcu::VERIFICATIONMODE_WEAKER;
1468                         else
1469                                 scene.verificationMode = tcu::VERIFICATIONMODE_STRICT;
1470
1471                         drawPrimitives(additionalResultImage, drawBuffer, colorData, m_primitiveTopology, *m_additionalImage, *m_additionalResolvedImage, *m_additionalFrameBuffer, m_additionalRenderSize, *m_additionalResultBuffer, *m_additionalResultBufferMemory);
1472
1473                         // Compare
1474                         if (!verifyRelaxedLineGroupRasterization(additionalResultImage, scene, args, m_context.getTestContext().getLog(), (0 == m_multisampling), strict))
1475                         {
1476                                 if (strict)
1477                                 {
1478                                         result = false;
1479                                 }
1480                                 else
1481                                 {
1482                                         // Retry with weaker verification. If it passes, consider it a quality warning.
1483                                         scene.verificationMode = tcu::VERIFICATIONMODE_WEAKER;
1484                                         if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), (0 == m_multisampling), strict))
1485                                                 result = false;
1486                                         else
1487                                                 m_qualityWarning = true;
1488                                 }
1489                         }
1490                 }
1491         }
1492
1493         return result;
1494 }
1495
1496 float BaseLineTestInstance::getLineWidth (void) const
1497 {
1498         return m_lineWidths[m_iteration];
1499 }
1500
1501 VkPipelineRasterizationLineStateCreateInfoEXT BaseLineTestInstance::initLineRasterizationStateCreateInfo (void) const
1502 {
1503         VkPipelineRasterizationLineStateCreateInfoEXT lineRasterizationStateInfo        =
1504         {
1505                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT,    // VkStructureType                              sType;
1506                 DE_NULL,                                                                                                                                // const void*                                  pNext;
1507                 m_lineRasterizationMode,                                                                                                // VkLineRasterizationModeEXT   lineRasterizationMode;
1508                 getLineStippleEnable() ? VK_TRUE : VK_FALSE,                                                    // VkBool32                                             stippledLineEnable;
1509                 1,                                                                                                                                              // uint32_t                                             lineStippleFactor;
1510                 0xFFFF,                                                                                                                                 // uint16_t                                             lineStipplePattern;
1511         };
1512
1513         if (m_stipple == LINESTIPPLE_STATIC)
1514         {
1515                 lineRasterizationStateInfo.lineStippleFactor = lineStippleFactor;
1516                 lineRasterizationStateInfo.lineStipplePattern = lineStipplePattern;
1517         }
1518
1519         return lineRasterizationStateInfo;
1520 }
1521
1522 const VkPipelineRasterizationLineStateCreateInfoEXT* BaseLineTestInstance::getLineRasterizationStateCreateInfo (void)
1523 {
1524         if (m_lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_EXT_LAST)
1525                 return DE_NULL;
1526
1527         if (m_lineRasterizationStateInfo.sType != VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT)
1528                 m_lineRasterizationStateInfo = initLineRasterizationStateCreateInfo();
1529
1530         return &m_lineRasterizationStateInfo;
1531 }
1532
1533 class PointTestInstance : public BaseRenderingTestInstance
1534 {
1535 public:
1536                                                         PointTestInstance               (Context&                                       context,
1537                                                                                                          PrimitiveWideness                      wideness,
1538                                                                                                          PrimitiveStrictness            strictness,                             // ignored
1539                                                                                                          VkSampleCountFlagBits          sampleCount,
1540                                                                                                          LineStipple                            stipple,                                // ignored
1541                                                                                                          VkLineRasterizationModeEXT     lineRasterizationMode,  // ignored
1542                                                                                                          deUint32                                       additionalRenderSize,   // ignored
1543                                                                                                          deUint32                                       renderSize                              = RESOLUTION_POT,
1544                                                                                                          float                                          pointSizeNarrow                 = 1.0f);
1545         virtual tcu::TestStatus iterate                                 (void);
1546         virtual float                   getPointSize                    (void) const;
1547
1548 protected:
1549         int                                             getIteration                            (void) const    { return m_iteration;           }
1550         int                                             getIterationCount                       (void) const    { return m_iterationCount;      }
1551
1552 private:
1553         virtual void                    generatePoints                  (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
1554         virtual bool                    compareAndVerify                (std::vector<PointSceneSpec::ScenePoint>&       points,
1555                                                                                                          tcu::Surface&                                                          resultImage,
1556                                                                                                          std::vector<tcu::Vec4>&                                        drawBuffer);
1557
1558         int                                             m_iteration;
1559         const int                               m_iterationCount;
1560         const PrimitiveWideness m_primitiveWideness;
1561         bool                                    m_allIterationsPassed;
1562         float                                   m_maxPointSize;
1563         std::vector<float>              m_pointSizes;
1564 };
1565
1566 PointTestInstance::PointTestInstance (Context&                                          context,
1567                                                                           PrimitiveWideness                             wideness,
1568                                                                           PrimitiveStrictness                   strictness,
1569                                                                           VkSampleCountFlagBits                 sampleCount,
1570                                                                           LineStipple                                   stipple,
1571                                                                           VkLineRasterizationModeEXT    lineRasterizationMode,
1572                                                                           deUint32                                              additionalRenderSize,
1573                                                                           deUint32                                              renderSize,
1574                                                                           float                                                 pointSizeNarrow)
1575         : BaseRenderingTestInstance     (context, sampleCount, renderSize)
1576         , m_iteration                           (0)
1577         , m_iterationCount                      (3)
1578         , m_primitiveWideness           (wideness)
1579         , m_allIterationsPassed         (true)
1580         , m_maxPointSize                        (pointSizeNarrow)
1581 {
1582         DE_UNREF(strictness);
1583         DE_UNREF(stipple);
1584         DE_UNREF(lineRasterizationMode);
1585         DE_UNREF(additionalRenderSize);
1586
1587         // create point sizes
1588         if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1589         {
1590                 m_pointSizes.resize(m_iterationCount, pointSizeNarrow);
1591         }
1592         else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1593         {
1594                 const float*    range = context.getDeviceProperties().limits.pointSizeRange;
1595
1596                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1597
1598                 DE_ASSERT(range[1] > 1.0f);
1599
1600                 // set hand picked sizes
1601                 m_pointSizes.push_back(10.0f);
1602                 m_pointSizes.push_back(25.0f);
1603                 m_pointSizes.push_back(range[1]);
1604                 DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
1605
1606                 m_maxPointSize = range[1];
1607         }
1608         else
1609                 DE_ASSERT(false);
1610 }
1611
1612 tcu::TestStatus PointTestInstance::iterate (void)
1613 {
1614         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1615         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1616         const float                                                             pointSize                               = getPointSize();
1617         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
1618         std::vector<tcu::Vec4>                                  drawBuffer;
1619         std::vector<PointSceneSpec::ScenePoint> points;
1620
1621         // supported?
1622         if (pointSize <= m_maxPointSize)
1623         {
1624                 // gen data
1625                 generatePoints(m_iteration, drawBuffer, points);
1626
1627                 // draw image
1628                 drawPrimitives(resultImage, drawBuffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
1629
1630                 // compare
1631                 {
1632                         const bool compareOk = compareAndVerify(points, resultImage, drawBuffer);
1633
1634                         if (!compareOk)
1635                                 m_allIterationsPassed = false;
1636                 }
1637         }
1638         else
1639                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1640
1641         // result
1642         if (++m_iteration == m_iterationCount)
1643         {
1644                 if (m_allIterationsPassed)
1645                         return tcu::TestStatus::pass("Pass");
1646                 else
1647                         return tcu::TestStatus::fail("Incorrect rasterization");
1648         }
1649         else
1650                 return tcu::TestStatus::incomplete();
1651 }
1652
1653 bool PointTestInstance::compareAndVerify (std::vector<PointSceneSpec::ScenePoint>&      points,
1654                                                                                   tcu::Surface&                                                         resultImage,
1655                                                                                   std::vector<tcu::Vec4>&                                       drawBuffer)
1656 {
1657         RasterizationArguments  args;
1658         PointSceneSpec                  scene;
1659
1660         tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1661
1662         args.numSamples         = m_multisampling ? 1 : 0;
1663         args.subpixelBits       = m_subpixelBits;
1664         args.redBits            = colorBits[0];
1665         args.greenBits          = colorBits[1];
1666         args.blueBits           = colorBits[2];
1667
1668         scene.points.swap(points);
1669
1670         DE_UNREF(drawBuffer);
1671
1672         return verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1673 }
1674
1675 float PointTestInstance::getPointSize (void) const
1676 {
1677         return m_pointSizes[m_iteration];
1678 }
1679
1680 void PointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
1681 {
1682         outData.resize(6);
1683
1684         switch (iteration)
1685         {
1686                 case 0:
1687                         // \note: these values are chosen arbitrarily
1688                         outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
1689                         outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
1690                         outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
1691                         outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
1692                         outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
1693                         outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
1694                         break;
1695
1696                 case 1:
1697                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1698                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1699                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1700                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1701                         outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1702                         outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
1703                         break;
1704
1705                 case 2:
1706                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1707                         outData[1] = tcu::Vec4(  0.3f, -0.9f, 0.0f, 1.0f);
1708                         outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
1709                         outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
1710                         outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1711                         outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
1712                         break;
1713         }
1714
1715         outPoints.resize(outData.size());
1716         for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1717         {
1718                 outPoints[pointNdx].position = outData[pointNdx];
1719                 outPoints[pointNdx].pointSize = getPointSize();
1720         }
1721
1722         // log
1723         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
1724         for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1725                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
1726 }
1727
1728 template <typename ConcreteTestInstance>
1729 class PointSizeTestCase : public BaseRenderingTestCase
1730 {
1731 public:
1732                                                         PointSizeTestCase       (tcu::TestContext&              context,
1733                                                                                                  std::string&                   name,
1734                                                                                                  std::string&                   description,
1735                                                                                                  deUint32                               renderSize,
1736                                                                                                  float                                  pointSize,
1737                                                                                                  VkSampleCountFlagBits  sampleCount = VK_SAMPLE_COUNT_1_BIT)
1738                                                                 : BaseRenderingTestCase (context, name, description, sampleCount)
1739                                                                 , m_pointSize   (pointSize)
1740                                                                 , m_renderSize  (renderSize)
1741                                                         {}
1742
1743         virtual TestInstance*   createInstance          (Context& context) const
1744                                                         {
1745                                                                 VkPhysicalDeviceProperties      properties      (context.getDeviceProperties());
1746
1747                                                                 if (m_renderSize > properties.limits.maxViewportDimensions[0] || m_renderSize > properties.limits.maxViewportDimensions[1])
1748                                                                         TCU_THROW(NotSupportedError , "Viewport dimensions not supported");
1749
1750                                                                 if (m_renderSize > properties.limits.maxFramebufferWidth || m_renderSize > properties.limits.maxFramebufferHeight)
1751                                                                         TCU_THROW(NotSupportedError , "Framebuffer width/height not supported");
1752
1753                                                                 return new ConcreteTestInstance(context, m_renderSize, m_pointSize);
1754                                                         }
1755
1756         virtual void                    checkSupport            (Context& context) const
1757                                                         {
1758                                                                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
1759                                                         }
1760 protected:
1761         const float                             m_pointSize;
1762         const deUint32                  m_renderSize;
1763 };
1764
1765 class PointSizeTestInstance : public BaseRenderingTestInstance
1766 {
1767 public:
1768                                                         PointSizeTestInstance   (Context& context, deUint32 renderSize, float pointSize);
1769         virtual tcu::TestStatus iterate                                 (void);
1770         virtual float                   getPointSize                    (void) const;
1771
1772 private:
1773         void                                    generatePointData               (PointSceneSpec::ScenePoint& outPoint);
1774         void                                    drawPoint                               (tcu::PixelBufferAccess& result, tcu::PointSceneSpec::ScenePoint& point);
1775         bool                                    verifyPoint                             (tcu::TestLog& log, tcu::PixelBufferAccess& access, float pointSize);
1776         bool                                    isPointSizeClamped              (float pointSize, float maxPointSizeLimit);
1777
1778         const float                             m_pointSize;
1779         const float                             m_maxPointSize;
1780         const deUint32                  m_renderSize;
1781         const VkFormat                  m_format;
1782 };
1783
1784 PointSizeTestInstance::PointSizeTestInstance (Context& context, deUint32 renderSize, float pointSize)
1785         : BaseRenderingTestInstance     (context, vk::VK_SAMPLE_COUNT_1_BIT, renderSize, VK_FORMAT_R8_UNORM)
1786         , m_pointSize                           (pointSize)
1787         , m_maxPointSize                        (context.getDeviceProperties().limits.pointSizeRange[1])
1788         , m_renderSize                          (renderSize)
1789         , m_format                                      (VK_FORMAT_R8_UNORM) // Use single-channel format to minimize memory allocation when using large render targets
1790 {
1791 }
1792
1793 tcu::TestStatus PointSizeTestInstance::iterate (void)
1794 {
1795         tcu::TextureLevel                       resultBuffer    (mapVkFormat(m_format), m_renderSize, m_renderSize);
1796         tcu::PixelBufferAccess          access                  (resultBuffer.getAccess());
1797         PointSceneSpec::ScenePoint      point;
1798
1799         // Generate data
1800         generatePointData(point);
1801
1802         // Draw
1803         drawPoint(access, point);
1804
1805         // Compare
1806         {
1807                 // pointSize must either be specified pointSize or clamped to device limit pointSizeRange[1]
1808                 const float     pointSize       (deFloatMin(m_pointSize, m_maxPointSize));
1809                 const bool      compareOk       (verifyPoint(m_context.getTestContext().getLog(), access, pointSize));
1810
1811                 // Result
1812                 if (compareOk)
1813                         return isPointSizeClamped(pointSize, m_maxPointSize) ? tcu::TestStatus::pass("Pass, pointSize clamped to pointSizeRange[1]") : tcu::TestStatus::pass("Pass");
1814                 else
1815                         return tcu::TestStatus::fail("Incorrect rasterization");
1816         }
1817 }
1818
1819 float PointSizeTestInstance::getPointSize (void) const
1820 {
1821         return m_pointSize;
1822 }
1823
1824 void PointSizeTestInstance::generatePointData (PointSceneSpec::ScenePoint& outPoint)
1825 {
1826         const tcu::PointSceneSpec::ScenePoint point =
1827         {
1828                 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),      // position
1829                 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),      // color
1830                 m_pointSize                                                     // pointSize
1831         };
1832
1833         outPoint = point;
1834
1835         // log
1836         {
1837                 tcu::TestLog& log = m_context.getTestContext().getLog();
1838
1839                 log << tcu::TestLog::Message << "Point position: "      << de::toString(point.position)         << tcu::TestLog::EndMessage;
1840                 log << tcu::TestLog::Message << "Point color: "         << de::toString(point.color)            << tcu::TestLog::EndMessage;
1841                 log << tcu::TestLog::Message << "Point size: "          << de::toString(point.pointSize)        << tcu::TestLog::EndMessage;
1842                 log << tcu::TestLog::Message << "Render size: "         << de::toString(m_renderSize)           << tcu::TestLog::EndMessage;
1843                 log << tcu::TestLog::Message << "Format: "                      << de::toString(m_format)                       << tcu::TestLog::EndMessage;
1844         }
1845 }
1846
1847 void PointSizeTestInstance::drawPoint (tcu::PixelBufferAccess& result, PointSceneSpec::ScenePoint& point)
1848 {
1849         const tcu::Vec4                 positionData            (point.position);
1850         const tcu::Vec4                 colorData                       (point.color);
1851
1852         const DeviceInterface&  vkd                                     (m_context.getDeviceInterface());
1853         const VkDevice                  vkDevice                        (m_context.getDevice());
1854         const VkQueue                   queue                           (m_context.getUniversalQueue());
1855         const deUint32                  queueFamilyIndex        (m_context.getUniversalQueueFamilyIndex());
1856         const size_t                    attributeBatchSize      (sizeof(tcu::Vec4));
1857         Allocator&                              allocator                       (m_context.getDefaultAllocator());
1858
1859         Move<VkCommandBuffer>   commandBuffer;
1860         Move<VkPipeline>                graphicsPipeline;
1861         Move<VkBuffer>                  vertexBuffer;
1862         de::MovePtr<Allocation> vertexBufferMemory;
1863
1864         // Create Graphics Pipeline
1865         {
1866                 const std::vector<VkViewport>                           viewports                                                       (1, makeViewport(tcu::UVec2(m_renderSize)));
1867                 const std::vector<VkRect2D>                                     scissors                                                        (1, makeRect2D(tcu::UVec2(m_renderSize)));
1868
1869                 const VkVertexInputBindingDescription           vertexInputBindingDescription           =
1870                 {
1871                         0u,                                                                     // deUint32                                     binding;
1872                         (deUint32)(2 * sizeof(tcu::Vec4)),      // deUint32                                     strideInBytes;
1873                         VK_VERTEX_INPUT_RATE_VERTEX                     // VkVertexInputStepRate        stepRate;
1874                 };
1875
1876                 const VkVertexInputAttributeDescription         vertexInputAttributeDescriptions[2]     =
1877                 {
1878                         {
1879                                 0u,                                                             // deUint32     location;
1880                                 0u,                                                             // deUint32     binding;
1881                                 VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat     format;
1882                                 0u                                                              // deUint32     offsetInBytes;
1883                         },
1884                         {
1885                                 1u,                                                             // deUint32     location;
1886                                 0u,                                                             // deUint32     binding;
1887                                 VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat     format;
1888                                 (deUint32)sizeof(tcu::Vec4)             // deUint32     offsetInBytes;
1889                         }
1890                 };
1891
1892                 const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams                          =
1893                 {
1894                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
1895                         DE_NULL,                                                                                                        // const void*                                                          pNext;
1896                         0,                                                                                                                      // VkPipelineVertexInputStateCreateFlags        flags;
1897                         1u,                                                                                                                     // deUint32                                                                     bindingCount;
1898                         &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
1899                         2u,                                                                                                                     // deUint32                                                                     attributeCount;
1900                         vertexInputAttributeDescriptions                                                        // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
1901                 };
1902
1903                 graphicsPipeline = makeGraphicsPipeline(vkd,                                                            // const DeviceInterface&                                                        vk
1904                                                                                                 vkDevice,                                                       // const VkDevice                                                                        device
1905                                                                                                 *m_pipelineLayout,                                      // const VkPipelineLayout                                                        pipelineLayout
1906                                                                                                 *m_vertexShaderModule,                          // const VkShaderModule                                                          vertexShaderModule
1907                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                          tessellationControlShaderModule
1908                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                          tessellationEvalShaderModule
1909                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                          geometryShaderModule
1910                                                                                                 *m_fragmentShaderModule,                        // const VkShaderModule                                                          fragmentShaderModule
1911                                                                                                 *m_renderPass,                                          // const VkRenderPass                                                            renderPass
1912                                                                                                 viewports,                                                      // const std::vector<VkViewport>&                                        viewports
1913                                                                                                 scissors,                                                       // const std::vector<VkRect2D>&                                          scissors
1914                                                                                                 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,       // const VkPrimitiveTopology                                             topology
1915                                                                                                 0u,                                                                     // const deUint32                                                                        subpass
1916                                                                                                 0u,                                                                     // const deUint32                                                                        patchControlPoints
1917                                                                                                 &vertexInputStateParams,                        // const VkPipelineVertexInputStateCreateInfo*           vertexInputStateCreateInfo
1918                                                                                                 getRasterizationStateCreateInfo(),      // const VkPipelineRasterizationStateCreateInfo*         rasterizationStateCreateInfo
1919                                                                                                 DE_NULL,                                                        // const VkPipelineMultisampleStateCreateInfo*           multisampleStateCreateInfo
1920                                                                                                 DE_NULL,                                                        // const VkPipelineDepthStencilStateCreateInfo*          depthStencilStateCreateInfo,
1921                                                                                                 getColorBlendStateCreateInfo());        // const VkPipelineColorBlendStateCreateInfo*            colorBlendStateCreateInfo
1922         }
1923
1924         // Create Vertex Buffer
1925         {
1926                 const VkBufferCreateInfo        vertexBufferParams =
1927                 {
1928                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
1929                         DE_NULL,                                                                // const void*                  pNext;
1930                         0u,                                                                             // VkBufferCreateFlags  flags;
1931                         attributeBatchSize * 2,                                 // VkDeviceSize                 size;
1932                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,              // VkBufferUsageFlags   usage;
1933                         VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
1934                         1u,                                                                             // deUint32                             queueFamilyCount;
1935                         &queueFamilyIndex                                               // const deUint32*              pQueueFamilyIndices;
1936                 };
1937
1938                 vertexBuffer            = createBuffer(vkd, vkDevice, &vertexBufferParams);
1939                 vertexBufferMemory      = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
1940
1941                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
1942
1943                 // Load vertices into vertex buffer
1944                 deMemcpy(vertexBufferMemory->getHostPtr(), &positionData, attributeBatchSize);
1945                 deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) +  attributeBatchSize, &colorData, attributeBatchSize);
1946                 flushAlloc(vkd, vkDevice, *vertexBufferMemory);
1947         }
1948
1949         // Create Command Buffer
1950         commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1951
1952         // Begin Command Buffer
1953         beginCommandBuffer(vkd, *commandBuffer);
1954
1955         addImageTransitionBarrier(*commandBuffer, *m_image,
1956                                                           VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                    // VkPipelineStageFlags         srcStageMask
1957                                                           VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                   // VkPipelineStageFlags         dstStageMask
1958                                                           0,                                                                                    // VkAccessFlags                        srcAccessMask
1959                                                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                 // VkAccessFlags                        dstAccessMask
1960                                                           VK_IMAGE_LAYOUT_UNDEFINED,                                    // VkImageLayout                        oldLayout;
1961                                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);    // VkImageLayout                        newLayout;
1962
1963         // Begin Render Pass
1964         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));
1965
1966         const VkDeviceSize vertexBufferOffset = 0;
1967
1968         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1969         vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
1970         vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
1971         vkd.cmdDraw(*commandBuffer, 1, 1, 0, 0);
1972         endRenderPass(vkd, *commandBuffer);
1973
1974         // Copy Image
1975         copyImageToBuffer(vkd, *commandBuffer, *m_image, *m_resultBuffer, tcu::IVec2(m_renderSize, m_renderSize));
1976
1977         endCommandBuffer(vkd, *commandBuffer);
1978
1979         // Set Point Size
1980         {
1981                 float pointSize = getPointSize();
1982
1983                 deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
1984                 flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
1985         }
1986
1987         // Submit
1988         submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
1989
1990         invalidateAlloc(vkd, vkDevice, *m_resultBufferMemory);
1991         tcu::copy(result, tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
1992 }
1993
1994 bool PointSizeTestInstance::verifyPoint (tcu::TestLog& log, tcu::PixelBufferAccess& image, float pointSize)
1995 {
1996         const float     expectedPointColor                              (1.0f);
1997         const float     expectedBackgroundColor                 (0.0f);
1998         deUint32        pointWidth                                              (0u);
1999         deUint32        pointHeight                                             (0u);
2000         bool            incorrectlyColoredPixelsFound   (false);
2001         bool            isOk                                                    (true);
2002
2003         // Verify rasterized point width and color
2004         for (size_t x = 0; x < (deUint32)image.getWidth(); x++)
2005         {
2006                 float pixelColor = image.getPixel((deUint32)x, image.getHeight() / 2).x();
2007
2008                 if (pixelColor == expectedPointColor)
2009                         pointWidth++;
2010
2011                 if ((pixelColor != expectedPointColor) && (pixelColor != expectedBackgroundColor))
2012                         incorrectlyColoredPixelsFound = true;
2013         }
2014
2015         // Verify rasterized point height and color
2016         for (size_t y = 0; y < (deUint32)image.getHeight(); y++)
2017         {
2018                 float pixelColor = image.getPixel((deUint32)y, image.getWidth() / 2).x();
2019
2020                 if (pixelColor == expectedPointColor)
2021                         pointHeight++;
2022
2023                 if ((pixelColor != expectedPointColor) && (pixelColor != expectedBackgroundColor))
2024                         incorrectlyColoredPixelsFound = true;
2025         }
2026
2027         // Compare amount of rasterized point pixels to expected pointSize.
2028         if ((pointWidth != (deUint32)deRoundFloatToInt32(pointSize)) || (pointHeight != (deUint32)deRoundFloatToInt32(pointSize)))
2029         {
2030                 log << tcu::TestLog::Message << "Incorrect point size. Expected pointSize: " << de::toString(pointSize)
2031                         << ". Rasterized point width: " << pointWidth << " pixels, height: "
2032                         << pointHeight << " pixels." << tcu::TestLog::EndMessage;
2033
2034                 isOk = false;
2035         }
2036
2037         // Check incorrectly colored pixels
2038         if (incorrectlyColoredPixelsFound)
2039         {
2040                 log << tcu::TestLog::Message << "Incorrectly colored pixels found." << tcu::TestLog::EndMessage;
2041                 isOk = false;
2042         }
2043
2044         return isOk;
2045 }
2046
2047 bool PointSizeTestInstance::isPointSizeClamped (float pointSize, float maxPointSizeLimit)
2048 {
2049         return (pointSize == maxPointSizeLimit);
2050 }
2051
2052 template <typename ConcreteTestInstance>
2053 class BaseTestCase : public BaseRenderingTestCase
2054 {
2055 public:
2056                                                         BaseTestCase    (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2057                                                                 : BaseRenderingTestCase(context, name, description, sampleCount)
2058                                                         {}
2059
2060         virtual TestInstance*   createInstance  (Context& context) const
2061                                                         {
2062                                                                 return new ConcreteTestInstance(context, m_sampleCount);
2063                                                         }
2064 };
2065
2066 class TrianglesTestInstance : public BaseTriangleTestInstance
2067 {
2068 public:
2069                                                         TrianglesTestInstance   (Context& context, VkSampleCountFlagBits sampleCount)
2070                                                                 : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, sampleCount)
2071                                                         {}
2072
2073         void                                    generateTriangles               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2074 };
2075
2076 void TrianglesTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2077 {
2078         outData.resize(6);
2079
2080         switch (iteration)
2081         {
2082                 case 0:
2083                         // \note: these values are chosen arbitrarily
2084                         outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
2085                         outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
2086                         outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
2087                         outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
2088                         outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
2089                         outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
2090                         break;
2091
2092                 case 1:
2093                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
2094                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
2095                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
2096                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
2097                         outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
2098                         outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
2099                         break;
2100
2101                 case 2:
2102                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
2103                         outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
2104                         outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
2105                         outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
2106                         outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
2107                         outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
2108                         break;
2109         }
2110
2111         outTriangles.resize(2);
2112         outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
2113         outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = false;
2114         outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = false;
2115
2116         outTriangles[1].positions[0] = outData[3];      outTriangles[1].sharedEdge[0] = false;
2117         outTriangles[1].positions[1] = outData[4];      outTriangles[1].sharedEdge[1] = false;
2118         outTriangles[1].positions[2] = outData[5];      outTriangles[1].sharedEdge[2] = false;
2119
2120         // log
2121         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
2122         for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
2123         {
2124                 m_context.getTestContext().getLog()
2125                         << tcu::TestLog::Message
2126                         << "Triangle " << (triangleNdx+1) << ":"
2127                         << "\n\t" << outTriangles[triangleNdx].positions[0]
2128                         << "\n\t" << outTriangles[triangleNdx].positions[1]
2129                         << "\n\t" << outTriangles[triangleNdx].positions[2]
2130                         << tcu::TestLog::EndMessage;
2131         }
2132 }
2133
2134 class TriangleStripTestInstance : public BaseTriangleTestInstance
2135 {
2136 public:
2137                                 TriangleStripTestInstance               (Context& context, VkSampleCountFlagBits sampleCount)
2138                                         : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, sampleCount)
2139                                 {}
2140
2141         void            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2142 };
2143
2144 void TriangleStripTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2145 {
2146         outData.resize(5);
2147
2148         switch (iteration)
2149         {
2150                 case 0:
2151                         // \note: these values are chosen arbitrarily
2152                         outData[0] = tcu::Vec4(-0.504f,  0.8f,   0.0f, 1.0f);
2153                         outData[1] = tcu::Vec4(-0.2f,   -0.2f,   0.0f, 1.0f);
2154                         outData[2] = tcu::Vec4(-0.2f,    0.199f, 0.0f, 1.0f);
2155                         outData[3] = tcu::Vec4( 0.5f,    0.201f, 0.0f, 1.0f);
2156                         outData[4] = tcu::Vec4( 1.5f,    0.4f,   0.0f, 1.0f);
2157                         break;
2158
2159                 case 1:
2160                         outData[0] = tcu::Vec4(-0.499f, 0.129f,  0.0f, 1.0f);
2161                         outData[1] = tcu::Vec4(-0.501f,  -0.3f,  0.0f, 1.0f);
2162                         outData[2] = tcu::Vec4(  0.11f,  -0.2f,  0.0f, 1.0f);
2163                         outData[3] = tcu::Vec4(  0.11f,  -0.31f, 0.0f, 1.0f);
2164                         outData[4] = tcu::Vec4(  0.88f,   0.9f,  0.0f, 1.0f);
2165                         break;
2166
2167                 case 2:
2168                         outData[0] = tcu::Vec4( -0.9f, -0.3f,  0.0f, 1.0f);
2169                         outData[1] = tcu::Vec4(  1.1f, -0.9f,  0.0f, 1.0f);
2170                         outData[2] = tcu::Vec4(-0.87f, -0.1f,  0.0f, 1.0f);
2171                         outData[3] = tcu::Vec4(-0.11f,  0.19f, 0.0f, 1.0f);
2172                         outData[4] = tcu::Vec4( 0.88f,  0.7f,  0.0f, 1.0f);
2173                         break;
2174         }
2175
2176         outTriangles.resize(3);
2177         outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
2178         outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = true;
2179         outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = false;
2180
2181         outTriangles[1].positions[0] = outData[2];      outTriangles[1].sharedEdge[0] = true;
2182         outTriangles[1].positions[1] = outData[1];      outTriangles[1].sharedEdge[1] = false;
2183         outTriangles[1].positions[2] = outData[3];      outTriangles[1].sharedEdge[2] = true;
2184
2185         outTriangles[2].positions[0] = outData[2];      outTriangles[2].sharedEdge[0] = true;
2186         outTriangles[2].positions[1] = outData[3];      outTriangles[2].sharedEdge[1] = false;
2187         outTriangles[2].positions[2] = outData[4];      outTriangles[2].sharedEdge[2] = false;
2188
2189         // log
2190         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
2191         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
2192         {
2193                 m_context.getTestContext().getLog()
2194                         << tcu::TestLog::Message
2195                         << "\t" << outData[vtxNdx]
2196                         << tcu::TestLog::EndMessage;
2197         }
2198 }
2199
2200 class TriangleFanTestInstance : public BaseTriangleTestInstance
2201 {
2202 public:
2203                                 TriangleFanTestInstance                 (Context& context, VkSampleCountFlagBits sampleCount);
2204
2205
2206         void            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2207 };
2208
2209 TriangleFanTestInstance::TriangleFanTestInstance (Context& context, VkSampleCountFlagBits sampleCount)
2210         : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, sampleCount)
2211 {
2212         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
2213                 !context.getPortabilitySubsetFeatures().triangleFans)
2214         {
2215                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
2216         }
2217 }
2218
2219 void TriangleFanTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2220 {
2221         outData.resize(5);
2222
2223         switch (iteration)
2224         {
2225                 case 0:
2226                         // \note: these values are chosen arbitrarily
2227                         outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
2228                         outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
2229                         outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
2230                         outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
2231                         outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
2232                         break;
2233
2234                 case 1:
2235                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
2236                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
2237                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
2238                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
2239                         outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
2240                         break;
2241
2242                 case 2:
2243                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
2244                         outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
2245                         outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
2246                         outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
2247                         outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
2248                         break;
2249         }
2250
2251         outTriangles.resize(3);
2252         outTriangles[0].positions[0] = outData[0];      outTriangles[0].sharedEdge[0] = false;
2253         outTriangles[0].positions[1] = outData[1];      outTriangles[0].sharedEdge[1] = false;
2254         outTriangles[0].positions[2] = outData[2];      outTriangles[0].sharedEdge[2] = true;
2255
2256         outTriangles[1].positions[0] = outData[0];      outTriangles[1].sharedEdge[0] = true;
2257         outTriangles[1].positions[1] = outData[2];      outTriangles[1].sharedEdge[1] = false;
2258         outTriangles[1].positions[2] = outData[3];      outTriangles[1].sharedEdge[2] = true;
2259
2260         outTriangles[2].positions[0] = outData[0];      outTriangles[2].sharedEdge[0] = true;
2261         outTriangles[2].positions[1] = outData[3];      outTriangles[2].sharedEdge[1] = false;
2262         outTriangles[2].positions[2] = outData[4];      outTriangles[2].sharedEdge[2] = false;
2263
2264         // log
2265         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
2266         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
2267         {
2268                 m_context.getTestContext().getLog()
2269                         << tcu::TestLog::Message
2270                         << "\t" << outData[vtxNdx]
2271                         << tcu::TestLog::EndMessage;
2272         }
2273 }
2274
2275 struct ConservativeTestConfig
2276 {
2277         VkConservativeRasterizationModeEXT      conservativeRasterizationMode;
2278         float                                                           extraOverestimationSize;
2279         VkPrimitiveTopology                                     primitiveTopology;
2280         bool                                                            degeneratePrimitives;
2281         float                                                           lineWidth;
2282         deUint32                                                        resolution;
2283 };
2284
2285 float getExtraOverestimationSize (const float overestimationSizeDesired, const VkPhysicalDeviceConservativeRasterizationPropertiesEXT& conservativeRasterizationProperties)
2286 {
2287         const float extraOverestimationSize     = overestimationSizeDesired == TCU_INFINITY ? conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize
2288                                                                                 : overestimationSizeDesired == -TCU_INFINITY ? conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity
2289                                                                                 : overestimationSizeDesired;
2290
2291         return extraOverestimationSize;
2292 }
2293
2294 template <typename ConcreteTestInstance>
2295 class ConservativeTestCase : public BaseRenderingTestCase
2296 {
2297 public:
2298                                                                         ConservativeTestCase            (tcu::TestContext&                                      context,
2299                                                                                                                                  const std::string&                                     name,
2300                                                                                                                                  const std::string&                                     description,
2301                                                                                                                                  const ConservativeTestConfig&          conservativeTestConfig,
2302                                                                                                                                  VkSampleCountFlagBits                          sampleCount = VK_SAMPLE_COUNT_1_BIT)
2303                                                                                 : BaseRenderingTestCase         (context, name, description, sampleCount)
2304                                                                                 , m_conservativeTestConfig      (conservativeTestConfig)
2305                                                                         {}
2306
2307         virtual void                                    checkSupport                            (Context& context) const;
2308
2309         virtual TestInstance*                   createInstance                          (Context& context) const
2310                                                                         {
2311                                                                                 return new ConcreteTestInstance(context, m_conservativeTestConfig, m_sampleCount);
2312                                                                         }
2313
2314 protected:
2315         bool                                                    isUseLineSubPixel                       (Context& context) const;
2316         deUint32                                                getSubPixelResolution           (Context& context) const;
2317
2318         const ConservativeTestConfig    m_conservativeTestConfig;
2319 };
2320
2321 template <typename ConcreteTestInstance>
2322 bool ConservativeTestCase<ConcreteTestInstance>::isUseLineSubPixel (Context& context) const
2323 {
2324         return (isPrimitiveTopologyLine(m_conservativeTestConfig.primitiveTopology) && context.isDeviceFunctionalitySupported("VK_EXT_line_rasterization"));
2325 }
2326
2327 template <typename ConcreteTestInstance>
2328 deUint32 ConservativeTestCase<ConcreteTestInstance>::getSubPixelResolution (Context& context) const
2329 {
2330         if (isUseLineSubPixel(context))
2331         {
2332                 const VkPhysicalDeviceLineRasterizationPropertiesEXT    lineRasterizationPropertiesEXT  = context.getLineRasterizationPropertiesEXT();
2333
2334                 return lineRasterizationPropertiesEXT.lineSubPixelPrecisionBits;
2335         }
2336         else
2337         {
2338                 return context.getDeviceProperties().limits.subPixelPrecisionBits;
2339         }
2340 }
2341
2342 template <typename ConcreteTestInstance>
2343 void ConservativeTestCase<ConcreteTestInstance>::checkSupport (Context& context) const
2344 {
2345         context.requireDeviceFunctionality("VK_EXT_conservative_rasterization");
2346
2347         const VkPhysicalDeviceConservativeRasterizationPropertiesEXT    conservativeRasterizationProperties     = context.getConservativeRasterizationPropertiesEXT();
2348         const deUint32                                                                                                  subPixelPrecisionBits                           = getSubPixelResolution(context);
2349         const deUint32                                                                                                  subPixelPrecision                                       = 1<<subPixelPrecisionBits;
2350         const bool                                                                                                              linesPrecision                                          = isUseLineSubPixel(context);
2351         const float                                                                                                             primitiveOverestimationSizeMult         = float(subPixelPrecision) * conservativeRasterizationProperties.primitiveOverestimationSize;
2352         const bool                                                                                                              topologyLineOrPoint                                     = isPrimitiveTopologyLine(m_conservativeTestConfig.primitiveTopology) || isPrimitiveTopologyPoint(m_conservativeTestConfig.primitiveTopology);
2353
2354         DE_ASSERT(subPixelPrecisionBits < sizeof(deUint32) * 8);
2355
2356         context.getTestContext().getLog()
2357                 << tcu::TestLog::Message
2358                 << "maxExtraPrimitiveOverestimationSize="                       << conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize << '\n'
2359                 << "extraPrimitiveOverestimationSizeGranularity="       << conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity << '\n'
2360                 << "degenerateLinesRasterized="                                         << conservativeRasterizationProperties.degenerateLinesRasterized << '\n'
2361                 << "degenerateTrianglesRasterized="                                     << conservativeRasterizationProperties.degenerateTrianglesRasterized << '\n'
2362                 << "primitiveOverestimationSize="                                       << conservativeRasterizationProperties.primitiveOverestimationSize << " (==" << primitiveOverestimationSizeMult << '/' << subPixelPrecision << ")\n"
2363                 << "subPixelPrecisionBits="                                                     << subPixelPrecisionBits << (linesPrecision ? " (using VK_EXT_line_rasterization)" : " (using limits)") << '\n'
2364                 << tcu::TestLog::EndMessage;
2365
2366         if (conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity > conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize)
2367                 TCU_FAIL("Granularity cannot be greater than maximum extra size");
2368
2369         if (topologyLineOrPoint)
2370         {
2371                 if (!conservativeRasterizationProperties.conservativePointAndLineRasterization)
2372                         TCU_THROW(NotSupportedError, "Conservative line and point rasterization is not supported");
2373         }
2374
2375         if (m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT)
2376         {
2377                 if (conservativeRasterizationProperties.primitiveUnderestimation == DE_FALSE)
2378                         TCU_THROW(NotSupportedError, "Underestimation is not supported");
2379
2380                 if (isPrimitiveTopologyLine(m_conservativeTestConfig.primitiveTopology))
2381                 {
2382                         const float     testLineWidth   = m_conservativeTestConfig.lineWidth;
2383
2384                         if (testLineWidth != 1.0f)
2385                         {
2386                                 const VkPhysicalDeviceLimits&   limits                                  = context.getDeviceProperties().limits;
2387                                 const float                                             lineWidthRange[2]               = { limits.lineWidthRange[0], limits.lineWidthRange[1] };
2388                                 const float                                             lineWidthGranularity    = limits.lineWidthGranularity;
2389
2390                                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
2391
2392                                 if (lineWidthGranularity == 0.0f)
2393                                         TCU_THROW(NotSupportedError, "Wide lines required for test, but are not supported");
2394
2395                                 DE_ASSERT(lineWidthGranularity > 0.0f && lineWidthRange[0] > 0.0f && lineWidthRange[1] >= lineWidthRange[0]);
2396
2397                                 if (!de::inBounds(testLineWidth, lineWidthRange[0], lineWidthRange[1]))
2398                                         TCU_THROW(NotSupportedError, "Tested line width is not supported");
2399
2400                                 const float     n       = (testLineWidth - lineWidthRange[0]) / lineWidthGranularity;
2401
2402                                 if (deFloatFrac(n) != 0.0f || n * lineWidthGranularity + lineWidthRange[0] != testLineWidth)
2403                                         TCU_THROW(NotSupportedError, "Exact match of line width is required for the test");
2404                         }
2405                 }
2406                 else if (isPrimitiveTopologyPoint(m_conservativeTestConfig.primitiveTopology))
2407                 {
2408                         const float     testPointSize   = m_conservativeTestConfig.lineWidth;
2409
2410                         if (testPointSize != 1.0f)
2411                         {
2412                                 const VkPhysicalDeviceLimits&   limits                                  = context.getDeviceProperties().limits;
2413                                 const float                                             pointSizeRange[2]               = { limits.pointSizeRange[0], limits.pointSizeRange[1] };
2414                                 const float                                             pointSizeGranularity    = limits.pointSizeGranularity;
2415
2416                                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
2417
2418                                 if (pointSizeGranularity == 0.0f)
2419                                         TCU_THROW(NotSupportedError, "Large points required for test, but are not supported");
2420
2421                                 DE_ASSERT(pointSizeGranularity > 0.0f && pointSizeRange[0] > 0.0f && pointSizeRange[1] >= pointSizeRange[0]);
2422
2423                                 if (!de::inBounds(testPointSize, pointSizeRange[0], pointSizeRange[1]))
2424                                         TCU_THROW(NotSupportedError, "Tested point size is not supported");
2425
2426                                 const float     n       = (testPointSize - pointSizeRange[0]) / pointSizeGranularity;
2427
2428                                 if (deFloatFrac(n) != 0.0f || n * pointSizeGranularity + pointSizeRange[0] != testPointSize)
2429                                         TCU_THROW(NotSupportedError, "Exact match of point size is required for the test");
2430                         }
2431                 }
2432         }
2433         else if (m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT)
2434         {
2435                 const float extraOverestimationSize     = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, conservativeRasterizationProperties);
2436
2437                 if (extraOverestimationSize > conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize)
2438                         TCU_THROW(NotSupportedError, "Specified overestimation size is not supported");
2439
2440                 if (topologyLineOrPoint)
2441                 {
2442                         if (!conservativeRasterizationProperties.conservativePointAndLineRasterization)
2443                                 TCU_THROW(NotSupportedError, "Conservative line and point rasterization is not supported");
2444                 }
2445
2446                 if (isPrimitiveTopologyTriangle(m_conservativeTestConfig.primitiveTopology))
2447                 {
2448                         if (m_conservativeTestConfig.degeneratePrimitives)
2449                         {
2450                                 // Enforce specification minimum required limit to avoid division by zero
2451                                 DE_ASSERT(subPixelPrecisionBits >= 4);
2452
2453                                 // Make sure float precision of 22 bits is enough, i.e. resoultion in subpixel quarters less than float precision
2454                                 if (m_conservativeTestConfig.resolution * (1<<(subPixelPrecisionBits + 2)) > (1<<21))
2455                                         TCU_THROW(NotSupportedError, "Subpixel resolution is too high to generate degenerate primitives");
2456                         }
2457                 }
2458         }
2459         else
2460                 TCU_THROW(InternalError, "Non-conservative mode tests are not supported by this class");
2461 }
2462
2463 class ConservativeTraingleTestInstance : public BaseTriangleTestInstance
2464 {
2465 public:
2466                                                                                                                                                                 ConservativeTraingleTestInstance                                (Context&                               context,
2467                                                                                                                                                                                                                                                                  ConservativeTestConfig conservativeTestConfig,
2468                                                                                                                                                                                                                                                                  VkSampleCountFlagBits  sampleCount)
2469                                                                                                                                                                         : BaseTriangleTestInstance                                              (context,
2470                                                                                                                                                                                                                                                                          conservativeTestConfig.primitiveTopology,
2471                                                                                                                                                                                                                                                                          sampleCount,
2472                                                                                                                                                                                                                                                                          conservativeTestConfig.resolution)
2473                                                                                                                                                                         , m_conservativeTestConfig                                              (conservativeTestConfig)
2474                                                                                                                                                                         , m_conservativeRasterizationProperties                 (context.getConservativeRasterizationPropertiesEXT())
2475                                                                                                                                                                         , m_rasterizationConservativeStateCreateInfo    (initRasterizationConservativeStateCreateInfo())
2476                                                                                                                                                                         , m_rasterizationStateCreateInfo                                (initRasterizationStateCreateInfo())
2477                                                                                                                                                                 {}
2478
2479         void                                                                                                                                            generateTriangles                                                               (int                                                                                    iteration,
2480                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                                outData,
2481                                                                                                                                                                                                                                                                  std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2482         const VkPipelineRasterizationStateCreateInfo*                                                           getRasterizationStateCreateInfo                                 (void) const;
2483
2484 protected:
2485         virtual const VkPipelineRasterizationLineStateCreateInfoEXT*                            getLineRasterizationStateCreateInfo                             (void);
2486
2487         virtual bool                                                                                                                            compareAndVerify                                                                (std::vector<TriangleSceneSpec::SceneTriangle>& triangles,
2488                                                                                                                                                                                                                                                                  tcu::Surface&                                                                  resultImage,
2489                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                                drawBuffer);
2490         virtual bool                                                                                                                            compareAndVerifyOverestimatedNormal                             (std::vector<TriangleSceneSpec::SceneTriangle>& triangles,
2491                                                                                                                                                                                                                                                                  tcu::Surface&                                                                  resultImage);
2492         virtual bool                                                                                                                            compareAndVerifyOverestimatedDegenerate                 (std::vector<TriangleSceneSpec::SceneTriangle>& triangles,
2493                                                                                                                                                                                                                                                                  tcu::Surface&                                                                  resultImage);
2494         virtual bool                                                                                                                            compareAndVerifyUnderestimatedNormal                    (std::vector<TriangleSceneSpec::SceneTriangle>& triangles,
2495                                                                                                                                                                                                                                                                  tcu::Surface&                                                                  resultImage);
2496         virtual bool                                                                                                                            compareAndVerifyUnderestimatedDegenerate                (std::vector<TriangleSceneSpec::SceneTriangle>& triangles,
2497                                                                                                                                                                                                                                                                  tcu::Surface&                                                                  resultImage);
2498         void                                                                                                                                            generateNormalTriangles                                                 (int                                                                                    iteration,
2499                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                                outData,
2500                                                                                                                                                                                                                                                                  std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2501         void                                                                                                                                            generateDegenerateTriangles                                     (int                                                                                    iteration,
2502                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                                outData,
2503                                                                                                                                                                                                                                                                  std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2504         void                                                                                                                                            drawPrimitives                                                                  (tcu::Surface&                                                                  result,
2505                                                                                                                                                                                                                                                                  const std::vector<tcu::Vec4>&                                  vertexData,
2506                                                                                                                                                                                                                                                                  VkPrimitiveTopology                                                    primitiveTopology);
2507
2508 private:
2509         const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>        initRasterizationConservativeStateCreateInfo    (void);
2510         const std::vector<VkPipelineRasterizationStateCreateInfo>                                       initRasterizationStateCreateInfo                                (void);
2511
2512         const ConservativeTestConfig                                                                                            m_conservativeTestConfig;
2513         const VkPhysicalDeviceConservativeRasterizationPropertiesEXT                            m_conservativeRasterizationProperties;
2514         const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>        m_rasterizationConservativeStateCreateInfo;
2515         const std::vector<VkPipelineRasterizationStateCreateInfo>                                       m_rasterizationStateCreateInfo;
2516 };
2517
2518 void ConservativeTraingleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2519 {
2520         if (m_conservativeTestConfig.degeneratePrimitives)
2521                 generateDegenerateTriangles(iteration, outData, outTriangles);
2522         else
2523                 generateNormalTriangles(iteration, outData, outTriangles);
2524 }
2525
2526 void ConservativeTraingleTestInstance::generateNormalTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2527 {
2528         const float     halfPixel                                               = 1.0f / float(m_renderSize);
2529         const float extraOverestimationSize                     = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
2530         const float     overestimate                                    = 2.0f * halfPixel * (m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize);
2531         const float     overestimateMargin                              = overestimate;
2532         const float     underestimateMargin                             = 0.0f;
2533         const bool      isOverestimate                                  = m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
2534         const float     margin                                                  = isOverestimate ? overestimateMargin : underestimateMargin;
2535         const char*     overestimateIterationComments[] = { "Corner touch", "Any portion pixel coverage", "Edge touch" };
2536
2537         outData.resize(6);
2538
2539         switch (iteration)
2540         {
2541                 case 0:
2542                 {
2543                         // Corner touch
2544                         const float edge        = 2 * halfPixel + margin;
2545                         const float left        = -1.0f + edge;
2546                         const float right       = +1.0f - edge;
2547                         const float up          = -1.0f + edge;
2548                         const float down        = +1.0f - edge;
2549
2550                         outData[0] = tcu::Vec4( left, down, 0.0f, 1.0f);
2551                         outData[1] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2552                         outData[2] = tcu::Vec4(right, down, 0.0f, 1.0f);
2553
2554                         outData[3] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2555                         outData[4] = tcu::Vec4(right, down, 0.0f, 1.0f);
2556                         outData[5] = tcu::Vec4(right,   up, 0.0f, 1.0f);
2557
2558                         break;
2559                 }
2560
2561                 case 1:
2562                 {
2563                         // Partial coverage
2564                         const float eps         = halfPixel / 32.0f;
2565                         const float edge        = 4.0f * halfPixel  + margin - eps;
2566                         const float left        = -1.0f + edge;
2567                         const float right       = +1.0f - edge;
2568                         const float up          = -1.0f + edge;
2569                         const float down        = +1.0f - edge;
2570
2571                         outData[0] = tcu::Vec4( left, down, 0.0f, 1.0f);
2572                         outData[1] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2573                         outData[2] = tcu::Vec4(right, down, 0.0f, 1.0f);
2574
2575                         outData[3] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2576                         outData[4] = tcu::Vec4(right, down, 0.0f, 1.0f);
2577                         outData[5] = tcu::Vec4(right,   up, 0.0f, 1.0f);
2578
2579                         break;
2580                 }
2581
2582                 case 2:
2583                 {
2584                         // Edge touch
2585                         const float edge        = 6.0f * halfPixel + margin;
2586                         const float left        = -1.0f + edge;
2587                         const float right       = +1.0f - edge;
2588                         const float up          = -1.0f + edge;
2589                         const float down        = +1.0f - edge;
2590
2591                         outData[0] = tcu::Vec4( left, down, 0.0f, 1.0f);
2592                         outData[1] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2593                         outData[2] = tcu::Vec4(right, down, 0.0f, 1.0f);
2594
2595                         outData[3] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2596                         outData[4] = tcu::Vec4(right, down, 0.0f, 1.0f);
2597                         outData[5] = tcu::Vec4(right,   up, 0.0f, 1.0f);
2598
2599                         break;
2600                 }
2601
2602                 default:
2603                         TCU_THROW(InternalError, "Unexpected iteration");
2604         }
2605
2606         outTriangles.resize(outData.size() / 3);
2607
2608         for (size_t ndx = 0; ndx < outTriangles.size(); ++ndx)
2609         {
2610                 outTriangles[ndx].positions[0] = outData[3 * ndx + 0];  outTriangles[ndx].sharedEdge[0] = false;
2611                 outTriangles[ndx].positions[1] = outData[3 * ndx + 1];  outTriangles[ndx].sharedEdge[1] = false;
2612                 outTriangles[ndx].positions[2] = outData[3 * ndx + 2];  outTriangles[ndx].sharedEdge[2] = false;
2613         }
2614
2615         // log
2616         if (isOverestimate)
2617         {
2618                 m_context.getTestContext().getLog()
2619                         << tcu::TestLog::Message
2620                         << "Testing " << overestimateIterationComments[iteration] << " "
2621                         << "with rendering " << outTriangles.size() << " triangle(s):"
2622                         << tcu::TestLog::EndMessage;
2623         }
2624         else
2625         {
2626                 m_context.getTestContext().getLog()
2627                         << tcu::TestLog::Message
2628                         << "Rendering " << outTriangles.size() << " triangle(s):"
2629                         << tcu::TestLog::EndMessage;
2630         }
2631
2632         for (size_t ndx = 0; ndx < outTriangles.size(); ++ndx)
2633         {
2634                 const deUint32   multiplier     = m_renderSize / 2;
2635
2636                 m_context.getTestContext().getLog()
2637                         << tcu::TestLog::Message
2638                         << "Triangle " << (ndx + 1) << ":"
2639                         << "\n\t" << outTriangles[ndx].positions[0] << " == " << (float(multiplier) * outTriangles[ndx].positions[0]) << "/" << multiplier
2640                         << "\n\t" << outTriangles[ndx].positions[1] << " == " << (float(multiplier) * outTriangles[ndx].positions[1]) << "/" << multiplier
2641                         << "\n\t" << outTriangles[ndx].positions[2] << " == " << (float(multiplier) * outTriangles[ndx].positions[2]) << "/" << multiplier
2642                         << tcu::TestLog::EndMessage;
2643         }
2644 }
2645
2646 void ConservativeTraingleTestInstance::generateDegenerateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2647 {
2648         tcu::TestLog&   log                                                             = m_context.getTestContext().getLog();
2649         const float             pixelSize                                               = 2.0f / float(m_renderSize);
2650         const deUint32  subPixels                                               = 1u << m_context.getDeviceProperties().limits.subPixelPrecisionBits;
2651         const float             subPixelSize                                    = pixelSize / float(subPixels);
2652         const float             extraOverestimationSize                 = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
2653         const float             totalOverestimate                               = m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize;
2654         const float             totalOverestimateInSubPixels    = deFloatCeil(totalOverestimate * float(subPixels));
2655         const float             overestimate                                    = subPixelSize * totalOverestimateInSubPixels;
2656         const float             overestimateSafetyMargin                = subPixelSize * 0.125f;
2657         const float             overestimateMargin                              = overestimate + overestimateSafetyMargin;
2658         const float             underestimateMargin                             = 0.0f;
2659         const bool              isOverestimate                                  = m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
2660         const float             margin                                                  = isOverestimate ? overestimateMargin : underestimateMargin;
2661         const char*             overestimateIterationComments[] = { "Backfacing", "Generate pixels", "Use provoking vertex" };
2662
2663         if (pixelSize < 2 * overestimateMargin)
2664                 TCU_THROW(NotSupportedError, "Could not generate degenerate triangle for such overestimate parameters");
2665
2666         outData.clear();
2667
2668         switch (iteration)
2669         {
2670                 case 0:
2671                 case 1:
2672                 case 2:
2673                 {
2674                         for (int rowNdx = 0; rowNdx < 3; ++rowNdx)
2675                         for (int colNdx = 0; colNdx < 4; ++colNdx)
2676                         {
2677                                 const float     offsetX         = -1.0f + float(4 * (colNdx + 1)) * pixelSize;
2678                                 const float     offsetY         = -1.0f + float(4 * (rowNdx + 1)) * pixelSize;
2679                                 const float     left            = offsetX + margin;
2680                                 const float     right           = offsetX + margin + 0.25f * subPixelSize;
2681                                 const float     up                      = offsetY + margin;
2682                                 const float     down            = offsetY + margin + 0.25f * subPixelSize;
2683                                 const bool      luPresent       = (rowNdx & 1) == 0;
2684                                 const bool      rdPresent       = (rowNdx & 2) == 0;
2685                                 const bool      luCW            = (colNdx & 1) == 0;
2686                                 const bool      rdCW            = (colNdx & 2) == 0;
2687
2688                                 DE_ASSERT(left < right);
2689                                 DE_ASSERT(up < down);
2690
2691                                 if (luPresent)
2692                                 {
2693                                         if (luCW)
2694                                         {
2695                                                 // CW triangle left up
2696                                                 outData.push_back(tcu::Vec4( left, down, 0.0f, 1.0f));
2697                                                 outData.push_back(tcu::Vec4( left,   up, 0.0f, 1.0f));
2698                                                 outData.push_back(tcu::Vec4(right,   up, 0.0f, 1.0f));
2699                                         }
2700                                         else
2701                                         {
2702                                                 // CCW triangle left up
2703                                                 outData.push_back(tcu::Vec4(right,   up, 0.0f, 1.0f));
2704                                                 outData.push_back(tcu::Vec4( left,   up, 0.0f, 1.0f));
2705                                                 outData.push_back(tcu::Vec4( left, down, 0.0f, 1.0f));
2706                                         }
2707                                 }
2708
2709                                 if (rdPresent)
2710                                 {
2711                                         if (rdCW)
2712                                         {
2713                                                 // CW triangle right down
2714                                                 outData.push_back(tcu::Vec4(right,   up, 0.0f, 1.0f));
2715                                                 outData.push_back(tcu::Vec4(right, down, 0.0f, 1.0f));
2716                                                 outData.push_back(tcu::Vec4( left, down, 0.0f, 1.0f));
2717                                         }
2718                                         else
2719                                         {
2720                                                 // CCW triangle right down
2721                                                 outData.push_back(tcu::Vec4( left, down, 0.0f, 1.0f));
2722                                                 outData.push_back(tcu::Vec4(right, down, 0.0f, 1.0f));
2723                                                 outData.push_back(tcu::Vec4(right,   up, 0.0f, 1.0f));
2724                                         }
2725                                 }
2726                         }
2727
2728                         break;
2729                 }
2730
2731                 default:
2732                         TCU_THROW(InternalError, "Unexpected iteration");
2733         }
2734
2735         outTriangles.resize(outData.size() / 3);
2736
2737         for (size_t ndx = 0; ndx < outTriangles.size(); ++ndx)
2738         {
2739                 outTriangles[ndx].positions[0] = outData[3 * ndx + 0];  outTriangles[ndx].sharedEdge[0] = false;
2740                 outTriangles[ndx].positions[1] = outData[3 * ndx + 1];  outTriangles[ndx].sharedEdge[1] = false;
2741                 outTriangles[ndx].positions[2] = outData[3 * ndx + 2];  outTriangles[ndx].sharedEdge[2] = false;
2742         }
2743
2744         // log
2745         if (isOverestimate)
2746         {
2747                 m_context.getTestContext().getLog()
2748                         << tcu::TestLog::Message
2749                         << "Testing " << overestimateIterationComments[iteration] << " "
2750                         << "with rendering " << outTriangles.size() << " triangle(s):"
2751                         << tcu::TestLog::EndMessage;
2752         }
2753         else
2754         {
2755                 m_context.getTestContext().getLog()
2756                         << tcu::TestLog::Message
2757                         << "Rendering " << outTriangles.size() << " triangle(s):"
2758                         << tcu::TestLog::EndMessage;
2759         }
2760
2761         for (int ndx = 0; ndx < (int)outTriangles.size(); ++ndx)
2762         {
2763                 const deUint32  multiplierInt   = m_renderSize / 2;
2764                 const deUint32  multiplierFrac  = subPixels;
2765                 std::string             coordsString;
2766
2767                 for (size_t vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
2768                 {
2769                         const tcu::Vec4&        pos                             = outTriangles[ndx].positions[vertexNdx];
2770                         std::ostringstream      coordsFloat;
2771                         std::ostringstream      coordsNatural;
2772
2773                         for (int coordNdx = 0; coordNdx < 2; ++coordNdx)
2774                         {
2775                                 const char*     sep             = (coordNdx < 1) ? "," : "";
2776                                 const float     coord   = pos[coordNdx];
2777                                 const char      sign    = deSign(coord) < 0 ? '-' : '+';
2778                                 const float     m               = deFloatFloor(float(multiplierInt) * deFloatAbs(coord));
2779                                 const float     r               = deFloatFrac(float(multiplierInt) * deFloatAbs(coord)) * float(multiplierFrac);
2780
2781                                 coordsFloat << std::fixed << std::setw(13) << std::setprecision(10) << coord << sep;
2782                                 coordsNatural << sign << '(' << m << '+' << r << '/' << multiplierFrac << ')' << sep;
2783                         }
2784
2785                         coordsString += "\n\t[" + coordsFloat.str() + "] == [" + coordsNatural.str() + "] / " + de::toString(multiplierInt);
2786                 }
2787
2788                 log << tcu::TestLog::Message
2789                         << "Triangle " << (ndx + 1) << ':'
2790                         << coordsString
2791                         << tcu::TestLog::EndMessage;
2792         }
2793 }
2794
2795 void ConservativeTraingleTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
2796 {
2797         if (m_conservativeTestConfig.degeneratePrimitives && getIteration() == 2)
2798         {
2799                 // Set provoking vertex color to white
2800                 tcu::Vec4                               colorProvoking  (1.0f, 1.0f, 1.0f, 1.0f);
2801                 tcu::Vec4                               colorOther              (0.0f, 1.0f, 1.0f, 1.0f);
2802                 std::vector<tcu::Vec4>  colorData;
2803
2804                 colorData.reserve(vertexData.size());
2805
2806                 for (size_t vertexNdx = 0; vertexNdx < vertexData.size(); ++vertexNdx)
2807                         if (vertexNdx % 3 == 0)
2808                                 colorData.push_back(colorProvoking);
2809                         else
2810                                 colorData.push_back(colorOther);
2811
2812                 BaseRenderingTestInstance::drawPrimitives(result, vertexData, colorData, primitiveTopology);
2813         }
2814         else
2815                 BaseRenderingTestInstance::drawPrimitives(result, vertexData, primitiveTopology);
2816 }
2817
2818 bool ConservativeTraingleTestInstance::compareAndVerify (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage, std::vector<tcu::Vec4>& drawBuffer)
2819 {
2820         DE_UNREF(drawBuffer);
2821
2822         switch (m_conservativeTestConfig.conservativeRasterizationMode)
2823         {
2824                 case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT:
2825                 {
2826                         if (m_conservativeTestConfig.degeneratePrimitives)
2827                                 return compareAndVerifyOverestimatedDegenerate(triangles, resultImage);
2828                         else
2829                                 return compareAndVerifyOverestimatedNormal(triangles, resultImage);
2830
2831                         break;
2832                 }
2833
2834                 case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT:
2835                 {
2836                         if (m_conservativeTestConfig.degeneratePrimitives)
2837                                 return compareAndVerifyUnderestimatedDegenerate(triangles, resultImage);
2838                         else
2839                                 return compareAndVerifyUnderestimatedNormal(triangles, resultImage);
2840
2841                         break;
2842                 }
2843
2844                 default:
2845                         TCU_THROW(InternalError, "Unknown conservative rasterization mode");
2846         }
2847 }
2848
2849 bool ConservativeTraingleTestInstance::compareAndVerifyOverestimatedNormal (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage)
2850 {
2851         DE_UNREF(triangles);
2852
2853         const int                       start                                   = getIteration() + 1;
2854         const int                       end                                             = resultImage.getHeight() - start;
2855         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
2856         const tcu::RGBA         foregroundColor                 = tcu::RGBA(255, 255, 255, 255);
2857         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
2858         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
2859         int                                     errX                                    = 0;
2860         int                                     errY                                    = 0;
2861         deUint32                        errValue                                = 0;
2862         bool                            result                                  = true;
2863
2864         DE_ASSERT(resultImage.getHeight() == resultImage.getWidth());
2865
2866         for (int y = start; result && y < end; ++y)
2867         for (int x = start; result && x < end; ++x)
2868         {
2869                 if (resultImage.getPixel(x,y).getPacked() != foregroundColor.getPacked())
2870                 {
2871                         result          = false;
2872                         errX            = x;
2873                         errY            = y;
2874                         errValue        = resultImage.getPixel(x,y).getPacked();
2875
2876                         break;
2877                 }
2878         }
2879
2880         if (!result)
2881         {
2882                 tcu::Surface    errorMask               (resultImage.getWidth(), resultImage.getHeight());
2883                 tcu::Surface    expectedImage   (resultImage.getWidth(), resultImage.getHeight());
2884
2885                 for (int y = 0; y < errorMask.getHeight(); ++y)
2886                 for (int x = 0; x < errorMask.getWidth(); ++x)
2887                 {
2888                         errorMask.setPixel(x, y, backgroundColor);
2889                         expectedImage.setPixel(x, y, backgroundColor);
2890                 }
2891
2892                 for (int y = start; y < end; ++y)
2893                 for (int x = start; x < end; ++x)
2894                 {
2895                         expectedImage.setPixel(x, y, foregroundColor);
2896
2897                         if (resultImage.getPixel(x, y).getPacked() != foregroundColor.getPacked())
2898                                 errorMask.setPixel(x, y, unexpectedPixelColor);
2899                 }
2900
2901                 log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
2902                         << tcu::TestLog::EndMessage;
2903                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
2904                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
2905                         << tcu::TestLog::Image("Expected",      "Expected",             expectedImage)
2906                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
2907                         << tcu::TestLog::EndImageSet;
2908         }
2909         else
2910         {
2911                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
2912                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
2913                         << tcu::TestLog::Image("Result", "Result", resultImage)
2914                         << tcu::TestLog::EndImageSet;
2915         }
2916
2917         return result;
2918 }
2919
2920 bool ConservativeTraingleTestInstance::compareAndVerifyOverestimatedDegenerate (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage)
2921 {
2922         DE_UNREF(triangles);
2923
2924         const char*                     iterationComments[]             = { "Cull back face triangles", "Cull front face triangles", "Cull none" };
2925         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
2926         const tcu::RGBA         foregroundColor                 = tcu::RGBA(255, 255, 255, 255);
2927         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
2928         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
2929         bool                            result                                  = true;
2930         tcu::Surface            referenceImage                  (resultImage.getWidth(), resultImage.getHeight());
2931
2932         for (int y = 0; y < resultImage.getHeight(); ++y)
2933         for (int x = 0; x < resultImage.getWidth(); ++x)
2934                 referenceImage.setPixel(x, y, backgroundColor);
2935
2936         if (m_conservativeRasterizationProperties.degenerateTrianglesRasterized)
2937         {
2938                 if (getIteration() != 0)
2939                 {
2940                         log << tcu::TestLog::Message << "Triangles expected to be rasterized with at least one pixel of white color each" << tcu::TestLog::EndMessage;
2941
2942                         for (int rowNdx = 0; rowNdx < 3; ++rowNdx)
2943                         for (int colNdx = 0; colNdx < 4; ++colNdx)
2944                         {
2945                                 referenceImage.setPixel(4 * (colNdx + 1), 4 * (rowNdx + 1), foregroundColor);
2946
2947                                 // Allow implementations that need to be extra conservative with degenerate triangles,
2948                                 // which may cause extra coverage.
2949                                 if (resultImage.getPixel(4 * (colNdx + 1) - 1, 4 * (rowNdx + 1) - 1) == foregroundColor)
2950                                         referenceImage.setPixel(4 * (colNdx + 1) - 1, 4 * (rowNdx + 1) - 1, foregroundColor);
2951                                 if (resultImage.getPixel(4 * (colNdx + 1) - 1, 4 * (rowNdx + 1)) == foregroundColor)
2952                                         referenceImage.setPixel(4 * (colNdx + 1) - 1, 4 * (rowNdx + 1), foregroundColor);
2953                                 if (resultImage.getPixel(4 * (colNdx + 1), 4 * (rowNdx + 1) - 1) == foregroundColor)
2954                                         referenceImage.setPixel(4 * (colNdx + 1), 4 * (rowNdx + 1) - 1, foregroundColor);
2955                         }
2956                 }
2957                 else
2958                         log << tcu::TestLog::Message << "Triangles expected to be culled due to backfacing culling and all degenerate triangles assumed to be backfacing" << tcu::TestLog::EndMessage;
2959         }
2960         else
2961                 log << tcu::TestLog::Message << "Triangles expected to be culled due to degenerateTrianglesRasterized=false" << tcu::TestLog::EndMessage;
2962
2963         for (int y = 0; result && y < resultImage.getHeight(); ++y)
2964         for (int x = 0; result && x < resultImage.getWidth(); ++x)
2965         {
2966                 if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
2967                 {
2968                         result = false;
2969
2970                         break;
2971                 }
2972         }
2973
2974         if (!result)
2975         {
2976                 tcu::Surface    errorMask       (resultImage.getWidth(), resultImage.getHeight());
2977
2978                 for (int y = 0; y < errorMask.getHeight(); ++y)
2979                 for (int x = 0; x < errorMask.getWidth(); ++x)
2980                 {
2981                         if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
2982                                 errorMask.setPixel(x, y, unexpectedPixelColor);
2983                         else
2984                                 errorMask.setPixel(x, y, backgroundColor);
2985                 }
2986
2987                 log << tcu::TestLog::Message << "Invalid pixels found for mode '" << iterationComments[getIteration()] << "'"
2988                         << tcu::TestLog::EndMessage;
2989                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
2990                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
2991                         << tcu::TestLog::Image("Reference",     "Reference",    referenceImage)
2992                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
2993                         << tcu::TestLog::EndImageSet;
2994         }
2995         else
2996         {
2997                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
2998                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
2999                         << tcu::TestLog::Image("Result", "Result", resultImage)
3000                         << tcu::TestLog::EndImageSet;
3001         }
3002
3003         return result;
3004 }
3005
3006 bool ConservativeTraingleTestInstance::compareAndVerifyUnderestimatedNormal (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage)
3007 {
3008         DE_UNREF(triangles);
3009
3010         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
3011         const tcu::RGBA         foregroundColor                 = tcu::RGBA(255, 255, 255, 255);
3012         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
3013         const tcu::IVec2        viewportSize                    = tcu::IVec2(resultImage.getWidth(), resultImage.getHeight());
3014         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
3015         int                                     errX                                    = -1;
3016         int                                     errY                                    = -1;
3017         deUint32                        errValue                                = 0;
3018         tcu::Surface            referenceImage                  (resultImage.getWidth(), resultImage.getHeight());
3019         bool                            result                                  = true;
3020
3021         DE_ASSERT(resultImage.getHeight() == resultImage.getWidth());
3022
3023         for (int y = 0; y < resultImage.getHeight(); ++y)
3024         for (int x = 0; x < resultImage.getWidth(); ++x)
3025                 referenceImage.setPixel(x, y, backgroundColor);
3026
3027         for (size_t triangleNdx = 0; triangleNdx < triangles.size(); ++triangleNdx)
3028         {
3029                 const tcu::Vec4&        p0      = triangles[triangleNdx].positions[0];
3030                 const tcu::Vec4&        p1      = triangles[triangleNdx].positions[1];
3031                 const tcu::Vec4&        p2      = triangles[triangleNdx].positions[2];
3032
3033                 for (int y = 0; y < resultImage.getHeight(); ++y)
3034                 for (int x = 0; x < resultImage.getWidth(); ++x)
3035                 {
3036                         if (calculateUnderestimateTriangleCoverage(p0, p1, p2, tcu::IVec2(x,y), m_subpixelBits, viewportSize) == tcu::COVERAGE_FULL)
3037                                 referenceImage.setPixel(x, y, foregroundColor);
3038                 }
3039         }
3040
3041         for (int y = 0; result && y < resultImage.getHeight(); ++y)
3042         for (int x = 0; result && x < resultImage.getWidth(); ++x)
3043                 if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
3044                 {
3045                         result          = false;
3046                         errX            = x;
3047                         errY            = y;
3048                         errValue        = resultImage.getPixel(x,y).getPacked();
3049                 }
3050
3051         if (!result)
3052         {
3053                 tcu::Surface    errorMask       (resultImage.getWidth(), resultImage.getHeight());
3054
3055                 for (int y = 0; y < errorMask.getHeight(); ++y)
3056                 for (int x = 0; x < errorMask.getWidth(); ++x)
3057                 {
3058                         if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
3059                                 errorMask.setPixel(x, y, unexpectedPixelColor);
3060                         else
3061                                 errorMask.setPixel(x, y, backgroundColor);
3062                 }
3063
3064                 log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
3065                         << tcu::TestLog::EndMessage;
3066                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3067                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
3068                         << tcu::TestLog::Image("Refernce",      "Refernce",             referenceImage)
3069                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
3070                         << tcu::TestLog::EndImageSet;
3071         }
3072         else
3073         {
3074                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3075                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3076                         << tcu::TestLog::Image("Result", "Result", resultImage)
3077                         << tcu::TestLog::EndImageSet;
3078         }
3079
3080         return result;
3081 }
3082
3083 bool ConservativeTraingleTestInstance::compareAndVerifyUnderestimatedDegenerate (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage)
3084 {
3085         DE_UNREF(triangles);
3086
3087         const char*                     iterationComments[]             = { "Cull back face triangles", "Cull front face triangles", "Cull none" };
3088         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
3089         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
3090         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
3091         int                                     errX                                    = 0;
3092         int                                     errY                                    = 0;
3093         deUint32                        errValue                                = 0;
3094         bool                            result                                  = true;
3095
3096         if (m_conservativeRasterizationProperties.degenerateTrianglesRasterized)
3097         {
3098                 if (getIteration() != 0)
3099                         log << tcu::TestLog::Message << "Triangles expected to be not rendered due to no one triangle can fully cover fragment" << tcu::TestLog::EndMessage;
3100                 else
3101                         log << tcu::TestLog::Message << "Triangles expected to be culled due to backfacing culling and all degenerate triangles assumed to be backfacing" << tcu::TestLog::EndMessage;
3102         }
3103         else
3104                 log << tcu::TestLog::Message << "Triangles expected to be culled due to degenerateTrianglesRasterized=false" << tcu::TestLog::EndMessage;
3105
3106         for (int y = 0; result && y < resultImage.getHeight(); ++y)
3107         for (int x = 0; result && x < resultImage.getWidth(); ++x)
3108         {
3109                 if (resultImage.getPixel(x, y).getPacked() != backgroundColor.getPacked())
3110                 {
3111                         result          = false;
3112                         errX            = x;
3113                         errY            = y;
3114                         errValue        = resultImage.getPixel(x,y).getPacked();
3115
3116                         break;
3117                 }
3118         }
3119
3120         if (!result)
3121         {
3122                 tcu::Surface    referenceImage  (resultImage.getWidth(), resultImage.getHeight());
3123                 tcu::Surface    errorMask               (resultImage.getWidth(), resultImage.getHeight());
3124
3125                 for (int y = 0; y < resultImage.getHeight(); ++y)
3126                 for (int x = 0; x < resultImage.getWidth(); ++x)
3127                         referenceImage.setPixel(x, y, backgroundColor);
3128
3129                 for (int y = 0; y < errorMask.getHeight(); ++y)
3130                 for (int x = 0; x < errorMask.getWidth(); ++x)
3131                 {
3132                         if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
3133                                 errorMask.setPixel(x, y, unexpectedPixelColor);
3134                         else
3135                                 errorMask.setPixel(x, y, backgroundColor);
3136                 }
3137
3138                 log << tcu::TestLog::Message << "Invalid pixels found for mode '" << iterationComments[getIteration()] << "' starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
3139                         << tcu::TestLog::EndMessage;
3140
3141                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3142                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
3143                         << tcu::TestLog::Image("Reference",     "Reference",    referenceImage)
3144                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
3145                         << tcu::TestLog::EndImageSet;
3146         }
3147         else
3148         {
3149                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3150                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3151                         << tcu::TestLog::Image("Result", "Result", resultImage)
3152                         << tcu::TestLog::EndImageSet;
3153         }
3154
3155         return result;
3156 }
3157
3158 const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT> ConservativeTraingleTestInstance::initRasterizationConservativeStateCreateInfo (void)
3159 {
3160         const float                                                                                                                     extraOverestimationSize = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3161         std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>      result;
3162
3163         result.reserve(getIterationCount());
3164
3165         for (int iteration = 0; iteration < getIterationCount(); ++iteration)
3166         {
3167                 const VkPipelineRasterizationConservativeStateCreateInfoEXT     rasterizationConservativeStateCreateInfo        =
3168                 {
3169                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,    //  VkStructureType                                                                                     sType;
3170                         DE_NULL,                                                                                                                                                //  const void*                                                                                         pNext;
3171                         (VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,                                              //  VkPipelineRasterizationConservativeStateCreateFlagsEXT      flags;
3172                         m_conservativeTestConfig.conservativeRasterizationMode,                                                 //  VkConservativeRasterizationModeEXT                                          conservativeRasterizationMode;
3173                         extraOverestimationSize                                                                                                                 //  float                                                                                                       extraPrimitiveOverestimationSize;
3174                 };
3175
3176                 result.push_back(rasterizationConservativeStateCreateInfo);
3177         }
3178
3179         return result;
3180 }
3181
3182 const std::vector<VkPipelineRasterizationStateCreateInfo> ConservativeTraingleTestInstance::initRasterizationStateCreateInfo (void)
3183 {
3184         std::vector<VkPipelineRasterizationStateCreateInfo>     result;
3185
3186         result.reserve(getIterationCount());
3187
3188         for (int iteration = 0; iteration < getIterationCount(); ++iteration)
3189         {
3190                 const VkCullModeFlags                                                   cullModeFlags                                   = (!m_conservativeTestConfig.degeneratePrimitives) ? VK_CULL_MODE_NONE
3191                                                                                                                                                                                 : (iteration == 0) ? VK_CULL_MODE_BACK_BIT
3192                                                                                                                                                                                 : (iteration == 1) ? VK_CULL_MODE_FRONT_BIT
3193                                                                                                                                                                                 : VK_CULL_MODE_NONE;
3194
3195                 const VkPipelineRasterizationStateCreateInfo    rasterizationStateCreateInfo    =
3196                 {
3197                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             //  VkStructureType                                                     sType;
3198                         &m_rasterizationConservativeStateCreateInfo[iteration],                 //  const void*                                                         pNext;
3199                         0,                                                                                                                              //  VkPipelineRasterizationStateCreateFlags     flags;
3200                         false,                                                                                                                  //  VkBool32                                                            depthClampEnable;
3201                         false,                                                                                                                  //  VkBool32                                                            rasterizerDiscardEnable;
3202                         VK_POLYGON_MODE_FILL,                                                                                   //  VkPolygonMode                                                       polygonMode;
3203                         cullModeFlags,                                                                                                  //  VkCullModeFlags                                                     cullMode;
3204                         VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                //  VkFrontFace                                                         frontFace;
3205                         VK_FALSE,                                                                                                               //  VkBool32                                                            depthBiasEnable;
3206                         0.0f,                                                                                                                   //  float                                                                       depthBiasConstantFactor;
3207                         0.0f,                                                                                                                   //  float                                                                       depthBiasClamp;
3208                         0.0f,                                                                                                                   //  float                                                                       depthBiasSlopeFactor;
3209                         getLineWidth(),                                                                                                 //  float                                                                       lineWidth;
3210                 };
3211
3212                 result.push_back(rasterizationStateCreateInfo);
3213         }
3214
3215         return result;
3216 }
3217
3218 const VkPipelineRasterizationStateCreateInfo* ConservativeTraingleTestInstance::getRasterizationStateCreateInfo (void) const
3219 {
3220         return &m_rasterizationStateCreateInfo[getIteration()];
3221 }
3222
3223 const VkPipelineRasterizationLineStateCreateInfoEXT* ConservativeTraingleTestInstance::getLineRasterizationStateCreateInfo      (void)
3224 {
3225         return DE_NULL;
3226 }
3227
3228
3229 class ConservativeLineTestInstance : public BaseLineTestInstance
3230 {
3231 public:
3232                                                                                                                                                                 ConservativeLineTestInstance                                    (Context&                                                               context,
3233                                                                                                                                                                                                                                                                  ConservativeTestConfig                                 conservativeTestConfig,
3234                                                                                                                                                                                                                                                                  VkSampleCountFlagBits                                  sampleCount);
3235
3236         void                                                                                                                                            generateLines                                                                   (int                                                                    iteration,
3237                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                outData,
3238                                                                                                                                                                                                                                                                  std::vector<LineSceneSpec::SceneLine>& outLines);
3239         const VkPipelineRasterizationStateCreateInfo*                                                           getRasterizationStateCreateInfo                                 (void) const;
3240
3241 protected:
3242         virtual const VkPipelineRasterizationLineStateCreateInfoEXT*                            getLineRasterizationStateCreateInfo                             (void);
3243
3244         virtual bool                                                                                                                            compareAndVerify                                                                (std::vector<LineSceneSpec::SceneLine>& lines,
3245                                                                                                                                                                                                                                                                  tcu::Surface&                                                  resultImage,
3246                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                drawBuffer);
3247         virtual bool                                                                                                                            compareAndVerifyOverestimatedNormal                             (std::vector<LineSceneSpec::SceneLine>& lines,
3248                                                                                                                                                                                                                                                                  tcu::Surface&                                                  resultImage);
3249         virtual bool                                                                                                                            compareAndVerifyOverestimatedDegenerate                 (std::vector<LineSceneSpec::SceneLine>& lines,
3250                                                                                                                                                                                                                                                                  tcu::Surface&                                                  resultImage);
3251         virtual bool                                                                                                                            compareAndVerifyUnderestimatedNormal                    (std::vector<LineSceneSpec::SceneLine>& lines,
3252                                                                                                                                                                                                                                                                  tcu::Surface&                                                  resultImage);
3253         virtual bool                                                                                                                            compareAndVerifyUnderestimatedDegenerate                (std::vector<LineSceneSpec::SceneLine>& lines,
3254                                                                                                                                                                                                                                                                  tcu::Surface&                                                  resultImage);
3255         void                                                                                                                                            generateNormalLines                                                             (int                                                                    iteration,
3256                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                outData,
3257                                                                                                                                                                                                                                                                  std::vector<LineSceneSpec::SceneLine>& outLines);
3258         void                                                                                                                                            generateDegenerateLines                                                 (int                                                                    iteration,
3259                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                outData,
3260                                                                                                                                                                                                                                                                  std::vector<LineSceneSpec::SceneLine>& outLines);
3261         void                                                                                                                                            drawPrimitives                                                                  (tcu::Surface&                                                  result,
3262                                                                                                                                                                                                                                                                  const std::vector<tcu::Vec4>&                  vertexData,
3263                                                                                                                                                                                                                                                                  VkPrimitiveTopology                                    primitiveTopology);
3264
3265 private:
3266         const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>        initRasterizationConservativeStateCreateInfo    (void);
3267         const std::vector<VkPipelineRasterizationStateCreateInfo>                                       initRasterizationStateCreateInfo                                (void);
3268
3269         const ConservativeTestConfig                                                                                            m_conservativeTestConfig;
3270         const VkPhysicalDeviceConservativeRasterizationPropertiesEXT                            m_conservativeRasterizationProperties;
3271         const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>        m_rasterizationConservativeStateCreateInfo;
3272         const std::vector<VkPipelineRasterizationStateCreateInfo>                                       m_rasterizationStateCreateInfo;
3273 };
3274
3275 ConservativeLineTestInstance::ConservativeLineTestInstance (Context&                            context,
3276                                                                                                                         ConservativeTestConfig  conservativeTestConfig,
3277                                                                                                                         VkSampleCountFlagBits   sampleCount)
3278         : BaseLineTestInstance                                                  (
3279                                                                                                                 context,
3280                                                                                                                 conservativeTestConfig.primitiveTopology,
3281                                                                                                                 PRIMITIVEWIDENESS_NARROW,
3282                                                                                                                 PRIMITIVESTRICTNESS_IGNORE,
3283                                                                                                                 sampleCount,
3284                                                                                                                 LINESTIPPLE_DISABLED,
3285                                                                                                                 VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,
3286                                                                                                                 0,
3287                                                                                                                 conservativeTestConfig.resolution,
3288                                                                                                                 conservativeTestConfig.lineWidth
3289                                                                                                         )
3290         , m_conservativeTestConfig                                              (conservativeTestConfig)
3291         , m_conservativeRasterizationProperties                 (context.getConservativeRasterizationPropertiesEXT())
3292         , m_rasterizationConservativeStateCreateInfo    (initRasterizationConservativeStateCreateInfo())
3293         , m_rasterizationStateCreateInfo                                (initRasterizationStateCreateInfo())
3294 {
3295 }
3296
3297 void ConservativeLineTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
3298 {
3299         if (m_conservativeTestConfig.degeneratePrimitives)
3300                 generateDegenerateLines(iteration, outData, outLines);
3301         else
3302                 generateNormalLines(iteration, outData, outLines);
3303 }
3304
3305 void ConservativeLineTestInstance::generateNormalLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
3306 {
3307         const char*             iterationComment                = "";
3308         const float             halfPixel                               = 1.0f / float(m_renderSize);
3309         const float             extraOverestimationSize = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3310         const float             overestimate                    = 2.0f * halfPixel * (m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize);
3311         const float             overestimateMargin              = overestimate;
3312         const float             underestimateMargin             = 0.0f;
3313         const bool              isOverestimate                  = m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3314         const float             margin                                  = isOverestimate ? overestimateMargin : underestimateMargin;
3315         const float             edge                                    = 4 * halfPixel + margin;
3316         const float             left                                    = -1.0f + edge;
3317         const float             right                                   = +1.0f - edge;
3318         const float             up                                              = -1.0f + edge;
3319         const float             down                                    = +1.0f - edge;
3320
3321         outData.reserve(2);
3322
3323         if (isOverestimate)
3324         {
3325                 const char*             iterationComments[]             = { "Horizontal up line", "Vertical line", "Horizontal down line" };
3326
3327                 iterationComment = iterationComments[iteration];
3328
3329                 switch (iteration)
3330                 {
3331                         case 0:
3332                         {
3333                                 outData.push_back(tcu::Vec4(              left,   up + halfPixel, 0.0f, 1.0f));
3334                                 outData.push_back(tcu::Vec4(             right,   up + halfPixel, 0.0f, 1.0f));
3335
3336                                 break;
3337                         }
3338
3339                         case 1:
3340                         {
3341                                 outData.push_back(tcu::Vec4(  left + halfPixel,               up, 0.0f, 1.0f));
3342                                 outData.push_back(tcu::Vec4(  left + halfPixel,             down, 0.0f, 1.0f));
3343
3344                                 break;
3345                         }
3346
3347                         case 2:
3348                         {
3349                                 outData.push_back(tcu::Vec4(              left, down - halfPixel, 0.0f, 1.0f));
3350                                 outData.push_back(tcu::Vec4(             right, down - halfPixel, 0.0f, 1.0f));
3351
3352                                 break;
3353                         }
3354
3355                         default:
3356                                 TCU_THROW(InternalError, "Unexpected iteration");
3357                 }
3358         }
3359         else
3360         {
3361                 const char*             iterationComments[]     = { "Horizontal lines", "Vertical lines", "Diagonal lines" };
3362                 const deUint32  subPixels                       = 1u << m_subpixelBits;
3363                 const float             subPixelSize            = 2.0f * halfPixel / float(subPixels);
3364                 const float             blockStep                       = 16.0f * 2.0f * halfPixel;
3365                 const float             lineWidth                       = 2.0f * halfPixel * getLineWidth();
3366                 const float             offsets[]                       =
3367                 {
3368                         float(1) * blockStep,
3369                         float(2) * blockStep + halfPixel,
3370                         float(3) * blockStep + 0.5f * lineWidth + 2.0f * subPixelSize,
3371                         float(4) * blockStep + 0.5f * lineWidth - 2.0f * subPixelSize,
3372                 };
3373
3374                 iterationComment = iterationComments[iteration];
3375
3376                 outData.reserve(DE_LENGTH_OF_ARRAY(offsets));
3377
3378                 switch (iteration)
3379                 {
3380                         case 0:
3381                         {
3382                                 for (size_t lineNdx = 0; lineNdx < DE_LENGTH_OF_ARRAY(offsets); ++lineNdx)
3383                                 {
3384                                         outData.push_back(tcu::Vec4( left + halfPixel, up + offsets[lineNdx], 0.0f, 1.0f));
3385                                         outData.push_back(tcu::Vec4(right - halfPixel, up + offsets[lineNdx], 0.0f, 1.0f));
3386                                 }
3387
3388                                 break;
3389                         }
3390
3391                         case 1:
3392                         {
3393                                 for (size_t lineNdx = 0; lineNdx < DE_LENGTH_OF_ARRAY(offsets); ++lineNdx)
3394                                 {
3395                                         outData.push_back(tcu::Vec4(left + offsets[lineNdx],   up + halfPixel, 0.0f, 1.0f));
3396                                         outData.push_back(tcu::Vec4(left + offsets[lineNdx], down - halfPixel, 0.0f, 1.0f));
3397                                 }
3398
3399                                 break;
3400                         }
3401
3402                         case 2:
3403                         {
3404                                 for (size_t lineNdx = 0; lineNdx < DE_LENGTH_OF_ARRAY(offsets); ++lineNdx)
3405                                 {
3406                                         outData.push_back(tcu::Vec4(left + offsets[lineNdx],          up + halfPixel, 0.0f, 1.0f));
3407                                         outData.push_back(tcu::Vec4(      right - halfPixel, down - offsets[lineNdx], 0.0f, 1.0f));
3408                                 }
3409
3410                                 break;
3411                         }
3412
3413                         default:
3414                                 TCU_THROW(InternalError, "Unexpected iteration");
3415                 }
3416         }
3417
3418         DE_ASSERT(outData.size() % 2 == 0);
3419         outLines.resize(outData.size() / 2);
3420         for(size_t lineNdx = 0; lineNdx < outLines.size(); ++lineNdx)
3421         {
3422                 outLines[lineNdx].positions[0] = outData[2 * lineNdx + 0];
3423                 outLines[lineNdx].positions[1] = outData[2 * lineNdx + 1];
3424         }
3425
3426         // log
3427         m_context.getTestContext().getLog()
3428                 << tcu::TestLog::Message
3429                 << "Testing " << iterationComment << " "
3430                 << "with rendering " << outLines.size() << " line(s):"
3431                 << tcu::TestLog::EndMessage;
3432
3433         for (int ndx = 0; ndx < (int)outLines.size(); ++ndx)
3434         {
3435                 const deUint32   multiplier     = m_renderSize / 2;
3436
3437                 m_context.getTestContext().getLog()
3438                         << tcu::TestLog::Message
3439                         << "Line " << (ndx+1) << ":"
3440                         << "\n\t" << outLines[ndx].positions[0] << " == " << (float(multiplier) * outLines[ndx].positions[0]) << "/" << multiplier
3441                         << "\n\t" << outLines[ndx].positions[1] << " == " << (float(multiplier) * outLines[ndx].positions[1]) << "/" << multiplier
3442                         << tcu::TestLog::EndMessage;
3443         }
3444 }
3445
3446 void ConservativeLineTestInstance::generateDegenerateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
3447 {
3448         const bool              isOverestimate          = m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3449         const float             pixelSize                       = 2.0f / float(m_renderSize);
3450         const deUint32  subPixels                       = 1u << m_context.getDeviceProperties().limits.subPixelPrecisionBits;
3451         const float             subPixelSize            = pixelSize / float(subPixels);
3452         const char*             iterationComments[]     = { "Horizontal line", "Vertical line", "Diagonal line" };
3453
3454         outData.clear();
3455
3456         if (isOverestimate)
3457         {
3458                 const float             extraOverestimationSize                 = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3459                 const float             totalOverestimate                               = m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize;
3460                 const float             totalOverestimateInSubPixels    = deFloatCeil(totalOverestimate * float(subPixels));
3461                 const float             overestimate                                    = subPixelSize * totalOverestimateInSubPixels;
3462                 const float             overestimateSafetyMargin                = subPixelSize * 0.125f;
3463                 const float             margin                                                  = overestimate + overestimateSafetyMargin;
3464                 const float             originOffset                                    = -1.0f + 1 * pixelSize;
3465                 const float             originLeft                                              = originOffset + margin;
3466                 const float             originRight                                             = originOffset + margin + 0.25f * subPixelSize;
3467                 const float             originUp                                                = originOffset + margin;
3468                 const float             originDown                                              = originOffset + margin + 0.25f * subPixelSize;
3469
3470                 switch (iteration)
3471                 {
3472                         case 0:
3473                         {
3474                                 outData.push_back(tcu::Vec4( originLeft,   originUp, 0.0f, 1.0f));
3475                                 outData.push_back(tcu::Vec4(originRight,   originUp, 0.0f, 1.0f));
3476
3477                                 break;
3478                         }
3479
3480                         case 1:
3481                         {
3482                                 outData.push_back(tcu::Vec4( originLeft,   originUp, 0.0f, 1.0f));
3483                                 outData.push_back(tcu::Vec4( originLeft, originDown, 0.0f, 1.0f));
3484
3485                                 break;
3486                         }
3487
3488                         case 2:
3489                         {
3490                                 outData.push_back(tcu::Vec4( originLeft,   originUp, 0.0f, 1.0f));
3491                                 outData.push_back(tcu::Vec4(originRight, originDown, 0.0f, 1.0f));
3492
3493                                 break;
3494                         }
3495
3496                         default:
3497                                 TCU_THROW(InternalError, "Unexpected iteration");
3498                 }
3499         }
3500         else
3501         {
3502                 size_t rowStart = 3 * getIteration();
3503                 size_t rowEnd   = 3 * (getIteration() + 1);
3504
3505                 for (size_t rowNdx = rowStart; rowNdx < rowEnd; ++rowNdx)
3506                 for (size_t colNdx = 0; colNdx < 3 * 3; ++colNdx)
3507                 {
3508                         const float             originOffsetY   = -1.0f + float(4 * (1 + rowNdx)) * pixelSize;
3509                         const float             originOffsetX   = -1.0f + float(4 * (1 + colNdx)) * pixelSize;
3510                         const float             x0                              = float(rowNdx % 3);
3511                         const float             y0                              = float(rowNdx / 3);
3512                         const float             x1                              = float(colNdx % 3);
3513                         const float             y1                              = float(colNdx / 3);
3514                         const tcu::Vec4 p0                              = tcu::Vec4(originOffsetX + x0 * pixelSize / 2.0f, originOffsetY + y0 * pixelSize / 2.0f, 0.0f, 1.0f);
3515                         const tcu::Vec4 p1                              = tcu::Vec4(originOffsetX + x1 * pixelSize / 2.0f, originOffsetY + y1 * pixelSize / 2.0f, 0.0f, 1.0f);
3516
3517                         if (x0 == x1 && y0 == y1)
3518                                 continue;
3519
3520                         outData.push_back(p0);
3521                         outData.push_back(p1);
3522                 }
3523         }
3524
3525         outLines.resize(outData.size() / 2);
3526
3527         for (size_t ndx = 0; ndx < outLines.size(); ++ndx)
3528         {
3529                 outLines[ndx].positions[0] = outData[2 * ndx + 0];
3530                 outLines[ndx].positions[1] = outData[2 * ndx + 1];
3531         }
3532
3533         // log
3534         m_context.getTestContext().getLog()
3535                 << tcu::TestLog::Message
3536                 << "Testing " << iterationComments[iteration] << " "
3537                 << "with rendering " << outLines.size() << " line(s):"
3538                 << tcu::TestLog::EndMessage;
3539
3540         for (int ndx = 0; ndx < (int)outLines.size(); ++ndx)
3541         {
3542                 const deUint32  multiplierInt   = m_renderSize / 2;
3543                 const deUint32  multiplierFrac  = subPixels;
3544                 std::string             coordsString;
3545
3546                 for (size_t vertexNdx = 0; vertexNdx < 2; ++vertexNdx)
3547                 {
3548                         const tcu::Vec4&        pos                             = outLines[ndx].positions[vertexNdx];
3549                         std::ostringstream      coordsFloat;
3550                         std::ostringstream      coordsNatural;
3551
3552                         for (int coordNdx = 0; coordNdx < 2; ++coordNdx)
3553                         {
3554                                 const char*     sep             = (coordNdx < 1) ? "," : "";
3555                                 const float     coord   = pos[coordNdx];
3556                                 const char      sign    = deSign(coord) < 0 ? '-' : '+';
3557                                 const float     m               = deFloatFloor(float(multiplierInt) * deFloatAbs(coord));
3558                                 const float     r               = deFloatFrac(float(multiplierInt) * deFloatAbs(coord)) * float(multiplierFrac);
3559
3560                                 coordsFloat << std::fixed << std::setw(13) << std::setprecision(10) << coord << sep;
3561                                 coordsNatural << sign << '(' << m << '+' << r << '/' << multiplierFrac << ')' << sep;
3562                         }
3563
3564                         coordsString += "\n\t[" + coordsFloat.str() + "] == [" + coordsNatural.str() + "] / " + de::toString(multiplierInt);
3565                 }
3566
3567                 m_context.getTestContext().getLog()
3568                         << tcu::TestLog::Message
3569                         << "Line " << (ndx + 1) << ':'
3570                         << coordsString
3571                         << tcu::TestLog::EndMessage;
3572         }
3573 }
3574
3575 void ConservativeLineTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
3576 {
3577         if (m_conservativeTestConfig.degeneratePrimitives)
3578         {
3579                 // Set provoking vertex color to white
3580                 tcu::Vec4                               colorProvoking  (1.0f, 1.0f, 1.0f, 1.0f);
3581                 tcu::Vec4                               colorOther              (0.0f, 1.0f, 1.0f, 1.0f);
3582                 std::vector<tcu::Vec4>  colorData;
3583
3584                 colorData.reserve(vertexData.size());
3585
3586                 for (size_t vertexNdx = 0; vertexNdx < vertexData.size(); ++vertexNdx)
3587                         if (vertexNdx % 2 == 0)
3588                                 colorData.push_back(colorProvoking);
3589                         else
3590                                 colorData.push_back(colorOther);
3591
3592                 BaseRenderingTestInstance::drawPrimitives(result, vertexData, colorData, primitiveTopology);
3593         }
3594         else
3595                 BaseRenderingTestInstance::drawPrimitives(result, vertexData, primitiveTopology);
3596 }
3597
3598 bool ConservativeLineTestInstance::compareAndVerify (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage, std::vector<tcu::Vec4>& drawBuffer)
3599 {
3600         DE_UNREF(drawBuffer);
3601
3602         switch (m_conservativeTestConfig.conservativeRasterizationMode)
3603         {
3604                 case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT:
3605                 {
3606                         if (m_conservativeTestConfig.degeneratePrimitives)
3607                                 return compareAndVerifyOverestimatedDegenerate(lines, resultImage);
3608                         else
3609                                 return compareAndVerifyOverestimatedNormal(lines, resultImage);
3610
3611                         break;
3612                 }
3613                 case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT:
3614                 {
3615                         if (m_conservativeTestConfig.degeneratePrimitives)
3616                                 return compareAndVerifyUnderestimatedDegenerate(lines, resultImage);
3617                         else
3618                                 return compareAndVerifyUnderestimatedNormal(lines, resultImage);
3619
3620                         break;
3621                 }
3622
3623                 default:
3624                         TCU_THROW(InternalError, "Unknown conservative rasterization mode");
3625         }
3626 }
3627
3628 bool ConservativeLineTestInstance::compareAndVerifyOverestimatedNormal (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage)
3629 {
3630         DE_UNREF(lines);
3631
3632         const int                       b                                               = 3; // bar width
3633         const int                       w                                               = resultImage.getWidth() - 1;
3634         const int                       h                                               = resultImage.getHeight() - 1;
3635         const int                       xStarts[]                               = {     1,     1,     1 };
3636         const int                       xEnds[]                                 = { w - 1,     b, w - 1 };
3637         const int                       yStarts[]                               = {     1,     1, h - b };
3638         const int                       yEnds[]                                 = {     b, h - 1, h - 1 };
3639         const int                       xStart                                  = xStarts[getIteration()];
3640         const int                       xEnd                                    = xEnds[getIteration()];
3641         const int                       yStart                                  = yStarts[getIteration()];
3642         const int                       yEnd                                    = yEnds[getIteration()];
3643         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
3644         const tcu::RGBA         foregroundColor                 = tcu::RGBA(255, 255, 255, 255);
3645         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
3646         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
3647         int                                     errX                                    = 0;
3648         int                                     errY                                    = 0;
3649         deUint32                        errValue                                = 0;
3650         bool                            result                                  = true;
3651
3652         DE_ASSERT(resultImage.getHeight() == resultImage.getWidth());
3653
3654         for (int y = yStart; result && y < yEnd; ++y)
3655         for (int x = xStart; result && x < xEnd; ++x)
3656         {
3657                 if (resultImage.getPixel(x,y).getPacked() != foregroundColor.getPacked())
3658                 {
3659                         result          = false;
3660                         errX            = x;
3661                         errY            = y;
3662                         errValue        = resultImage.getPixel(x,y).getPacked();
3663
3664                         break;
3665                 }
3666         }
3667
3668         if (!result)
3669         {
3670                 tcu::Surface    errorMask       (resultImage.getWidth(), resultImage.getHeight());
3671
3672                 for (int y = 0; y < errorMask.getHeight(); ++y)
3673                 for (int x = 0; x < errorMask.getWidth(); ++x)
3674                         errorMask.setPixel(x, y, backgroundColor);
3675
3676                 for (int y = yStart; y < yEnd; ++y)
3677                 for (int x = xStart; x < xEnd; ++x)
3678                 {
3679                         if (resultImage.getPixel(x,y).getPacked() != foregroundColor.getPacked())
3680                                 errorMask.setPixel(x,y, unexpectedPixelColor);
3681                 }
3682
3683                 log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
3684                         << tcu::TestLog::EndMessage;
3685                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3686                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
3687                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
3688                         << tcu::TestLog::EndImageSet;
3689         }
3690         else
3691         {
3692                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3693                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3694                         << tcu::TestLog::Image("Result", "Result", resultImage)
3695                         << tcu::TestLog::EndImageSet;
3696         }
3697
3698         return result;
3699 }
3700
3701 bool ConservativeLineTestInstance::compareAndVerifyOverestimatedDegenerate (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage)
3702 {
3703         DE_UNREF(lines);
3704
3705         const char*                     iterationComments[]             = { "Horizontal line", "Vertical line", "Diagonal line" };
3706         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
3707         const tcu::RGBA         foregroundColor                 = tcu::RGBA(255, 255, 255, 255);
3708         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
3709         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
3710         bool                            result                                  = true;
3711         tcu::Surface            referenceImage                  (resultImage.getWidth(), resultImage.getHeight());
3712
3713         for (int y = 0; y < resultImage.getHeight(); ++y)
3714         for (int x = 0; x < resultImage.getWidth(); ++x)
3715                 referenceImage.setPixel(x, y, backgroundColor);
3716
3717         if (m_conservativeRasterizationProperties.degenerateLinesRasterized)
3718         {
3719                 log << tcu::TestLog::Message << "Lines expected to be rasterized with white color" << tcu::TestLog::EndMessage;
3720
3721                 // This pixel will alway be covered due to the placement of the line.
3722                 referenceImage.setPixel(1, 1, foregroundColor);
3723
3724                 // Additional pixels will be covered based on the extra bloat added to the primitive.
3725                 const float extraOverestimation = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3726                 const int xExtent = 1 + int((extraOverestimation * 2.0f) + 0.5f);
3727                 const int yExtent = xExtent;
3728
3729                 for (int y = 0; y <= yExtent; ++y)
3730                 for (int x = 0; x <= xExtent; ++x)
3731                         referenceImage.setPixel(x, y, foregroundColor);
3732         }
3733         else
3734                 log << tcu::TestLog::Message << "Lines expected to be culled" << tcu::TestLog::EndMessage;
3735
3736         for (int y = 0; result && y < resultImage.getHeight(); ++y)
3737         for (int x = 0; result && x < resultImage.getWidth(); ++x)
3738         {
3739                 if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
3740                 {
3741                         result = false;
3742
3743                         break;
3744                 }
3745         }
3746
3747         if (!result)
3748         {
3749                 tcu::Surface    errorMask       (resultImage.getWidth(), resultImage.getHeight());
3750
3751                 for (int y = 0; y < errorMask.getHeight(); ++y)
3752                 for (int x = 0; x < errorMask.getWidth(); ++x)
3753                 {
3754                         if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
3755                                 errorMask.setPixel(x, y, unexpectedPixelColor);
3756                         else
3757                                 errorMask.setPixel(x, y, backgroundColor);
3758                 }
3759
3760                 log << tcu::TestLog::Message << "Invalid pixels found for mode " << iterationComments[getIteration()]
3761                         << tcu::TestLog::EndMessage;
3762                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3763                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
3764                         << tcu::TestLog::Image("Reference",     "Reference",    referenceImage)
3765                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
3766                         << tcu::TestLog::EndImageSet;
3767         }
3768         else
3769         {
3770                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3771                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3772                         << tcu::TestLog::Image("Result", "Result", resultImage)
3773                         << tcu::TestLog::EndImageSet;
3774         }
3775
3776         return result;
3777 }
3778
3779 bool ConservativeLineTestInstance::compareAndVerifyUnderestimatedNormal (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage)
3780 {
3781         DE_UNREF(lines);
3782
3783         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
3784         const tcu::RGBA         foregroundColor                 = tcu::RGBA(255, 255, 255, 255);
3785         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
3786         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
3787         int                                     errX                                    = -1;
3788         int                                     errY                                    = -1;
3789         tcu::RGBA                       errValue;
3790         bool                            result                                  = true;
3791         tcu::Surface            referenceImage                  (resultImage.getWidth(), resultImage.getHeight());
3792
3793         DE_ASSERT(resultImage.getHeight() == resultImage.getWidth());
3794
3795         for (int y = 0; y < referenceImage.getHeight(); ++y)
3796         for (int x = 0; x < referenceImage.getWidth(); ++x)
3797                 referenceImage.setPixel(x, y, backgroundColor);
3798
3799         if (getLineWidth() > 1.0f)
3800         {
3801                 const tcu::IVec2        viewportSize(resultImage.getWidth(), resultImage.getHeight());
3802
3803                 for (size_t lineNdx = 0; lineNdx < lines.size(); ++lineNdx)
3804                 for (int y = 0; y < resultImage.getHeight(); ++y)
3805                 for (int x = 0; x < resultImage.getWidth(); ++x)
3806                 {
3807                         if (calculateUnderestimateLineCoverage(lines[lineNdx].positions[0], lines[lineNdx].positions[1], getLineWidth(), tcu::IVec2(x,y), viewportSize) == tcu::COVERAGE_FULL)
3808                                 referenceImage.setPixel(x, y, foregroundColor);
3809                 }
3810         }
3811
3812         for (int y = 0; result && y < resultImage.getHeight(); ++y)
3813         for (int x = 0; result && x < resultImage.getWidth(); ++x)
3814         {
3815                 if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
3816                 {
3817                         result          = false;
3818                         errX            = x;
3819                         errY            = y;
3820                         errValue        = resultImage.getPixel(x,y);
3821
3822                         break;
3823                 }
3824         }
3825
3826         if (!result)
3827         {
3828                 tcu::Surface    errorMask       (resultImage.getWidth(), resultImage.getHeight());
3829
3830                 for (int y = 0; y < errorMask.getHeight(); ++y)
3831                 for (int x = 0; x < errorMask.getWidth(); ++x)
3832                         errorMask.setPixel(x, y, backgroundColor);
3833
3834                 for (int y = 0; y < errorMask.getHeight(); ++y)
3835                 for (int x = 0; x < errorMask.getWidth();  ++x)
3836                 {
3837                         if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
3838                                 errorMask.setPixel(x, y, unexpectedPixelColor);
3839                 }
3840
3841                 log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " errValue=" << errValue
3842                         << tcu::TestLog::EndMessage;
3843                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3844                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
3845                         << tcu::TestLog::Image("Reference",     "Reference",    referenceImage)
3846                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
3847                         << tcu::TestLog::EndImageSet;
3848         }
3849         else
3850         {
3851                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3852                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3853                         << tcu::TestLog::Image("Result", "Result", resultImage)
3854                         << tcu::TestLog::EndImageSet;
3855         }
3856
3857         return result;
3858 }
3859
3860 bool ConservativeLineTestInstance::compareAndVerifyUnderestimatedDegenerate (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage)
3861 {
3862         DE_UNREF(lines);
3863
3864         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
3865         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
3866         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
3867         bool                            result                                  = true;
3868         tcu::Surface            referenceImage                  (resultImage.getWidth(), resultImage.getHeight());
3869
3870         for (int y = 0; y < resultImage.getHeight(); ++y)
3871         for (int x = 0; x < resultImage.getWidth(); ++x)
3872                 referenceImage.setPixel(x, y, backgroundColor);
3873
3874         log << tcu::TestLog::Message << "No lines expected to be rasterized" << tcu::TestLog::EndMessage;
3875
3876         for (int y = 0; result && y < resultImage.getHeight(); ++y)
3877         for (int x = 0; result && x < resultImage.getWidth(); ++x)
3878         {
3879                 if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
3880                 {
3881                         result = false;
3882
3883                         break;
3884                 }
3885         }
3886
3887         if (!result)
3888         {
3889                 tcu::Surface    errorMask       (resultImage.getWidth(), resultImage.getHeight());
3890
3891                 for (int y = 0; y < errorMask.getHeight(); ++y)
3892                 for (int x = 0; x < errorMask.getWidth(); ++x)
3893                 {
3894                         if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
3895                                 errorMask.setPixel(x, y, unexpectedPixelColor);
3896                         else
3897                                 errorMask.setPixel(x, y, backgroundColor);
3898                 }
3899
3900                 log << tcu::TestLog::Message << "Invalid pixels found" << tcu::TestLog::EndMessage;
3901                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3902                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
3903                         << tcu::TestLog::Image("Reference",     "Reference",    referenceImage)
3904                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
3905                         << tcu::TestLog::EndImageSet;
3906         }
3907         else
3908         {
3909                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3910                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3911                         << tcu::TestLog::Image("Result", "Result", resultImage)
3912                         << tcu::TestLog::EndImageSet;
3913         }
3914
3915         return result;
3916 }
3917
3918 const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT> ConservativeLineTestInstance::initRasterizationConservativeStateCreateInfo (void)
3919 {
3920         const float                                                                                                                     extraOverestimationSize = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3921         std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>      result;
3922
3923         result.reserve(getIterationCount());
3924
3925         for (int iteration = 0; iteration < getIterationCount(); ++iteration)
3926         {
3927                 const VkPipelineRasterizationConservativeStateCreateInfoEXT     rasterizationConservativeStateCreateInfo        =
3928                 {
3929                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,    //  VkStructureType                                                                                     sType;
3930                         DE_NULL,                                                                                                                                                //  const void*                                                                                         pNext;
3931                         (VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,                                              //  VkPipelineRasterizationConservativeStateCreateFlagsEXT      flags;
3932                         m_conservativeTestConfig.conservativeRasterizationMode,                                                 //  VkConservativeRasterizationModeEXT                                          conservativeRasterizationMode;
3933                         extraOverestimationSize                                                                                                                 //  float                                                                                                       extraPrimitiveOverestimationSize;
3934                 };
3935
3936                 result.push_back(rasterizationConservativeStateCreateInfo);
3937         }
3938
3939         return result;
3940 }
3941
3942 const std::vector<VkPipelineRasterizationStateCreateInfo> ConservativeLineTestInstance::initRasterizationStateCreateInfo (void)
3943 {
3944         std::vector<VkPipelineRasterizationStateCreateInfo>     result;
3945
3946         result.reserve(getIterationCount());
3947
3948         for (int iteration = 0; iteration < getIterationCount(); ++iteration)
3949         {
3950                 const VkPipelineRasterizationStateCreateInfo    rasterizationStateCreateInfo    =
3951                 {
3952                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             //  VkStructureType                                                     sType;
3953                         &m_rasterizationConservativeStateCreateInfo[iteration],                 //  const void*                                                         pNext;
3954                         0,                                                                                                                              //  VkPipelineRasterizationStateCreateFlags     flags;
3955                         false,                                                                                                                  //  VkBool32                                                            depthClampEnable;
3956                         false,                                                                                                                  //  VkBool32                                                            rasterizerDiscardEnable;
3957                         VK_POLYGON_MODE_FILL,                                                                                   //  VkPolygonMode                                                       polygonMode;
3958                         VK_CULL_MODE_NONE,                                                                                              //  VkCullModeFlags                                                     cullMode;
3959                         VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                //  VkFrontFace                                                         frontFace;
3960                         VK_FALSE,                                                                                                               //  VkBool32                                                            depthBiasEnable;
3961                         0.0f,                                                                                                                   //  float                                                                       depthBiasConstantFactor;
3962                         0.0f,                                                                                                                   //  float                                                                       depthBiasClamp;
3963                         0.0f,                                                                                                                   //  float                                                                       depthBiasSlopeFactor;
3964                         getLineWidth(),                                                                                                 //  float                                                                       lineWidth;
3965                 };
3966
3967                 result.push_back(rasterizationStateCreateInfo);
3968         }
3969
3970         return result;
3971 }
3972
3973 const VkPipelineRasterizationStateCreateInfo* ConservativeLineTestInstance::getRasterizationStateCreateInfo     (void) const
3974 {
3975         return &m_rasterizationStateCreateInfo[getIteration()];
3976 }
3977
3978 const VkPipelineRasterizationLineStateCreateInfoEXT* ConservativeLineTestInstance::getLineRasterizationStateCreateInfo  (void)
3979 {
3980         return DE_NULL;
3981 }
3982
3983
3984 class ConservativePointTestInstance : public PointTestInstance
3985 {
3986 public:
3987                                                                                                                                                                 ConservativePointTestInstance                                   (Context&                               context,
3988                                                                                                                                                                                                                                                                  ConservativeTestConfig conservativeTestConfig,
3989                                                                                                                                                                                                                                                                  VkSampleCountFlagBits  sampleCount)
3990                                                                                                                                                                         : PointTestInstance                                                             (
3991                                                                                                                                                                                                                                                                                 context,
3992                                                                                                                                                                                                                                                                                 PRIMITIVEWIDENESS_NARROW,
3993                                                                                                                                                                                                                                                                                 PRIMITIVESTRICTNESS_IGNORE,
3994                                                                                                                                                                                                                                                                                 sampleCount,
3995                                                                                                                                                                                                                                                                                 LINESTIPPLE_DISABLED,
3996                                                                                                                                                                                                                                                                                 VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,
3997                                                                                                                                                                                                                                                                                 0,
3998                                                                                                                                                                                                                                                                                 conservativeTestConfig.resolution,
3999                                                                                                                                                                                                                                                                                 conservativeTestConfig.lineWidth
4000                                                                                                                                                                                                                                                                         )
4001                                                                                                                                                                         , m_conservativeTestConfig                                              (conservativeTestConfig)
4002                                                                                                                                                                         , m_conservativeRasterizationProperties                 (context.getConservativeRasterizationPropertiesEXT())
4003                                                                                                                                                                         , m_rasterizationConservativeStateCreateInfo    (initRasterizationConservativeStateCreateInfo())
4004                                                                                                                                                                         , m_rasterizationStateCreateInfo                                (initRasterizationStateCreateInfo())
4005                                                                                                                                                                         , m_renderStart                                                                 ()
4006                                                                                                                                                                         , m_renderEnd                                                                   ()
4007                                                                                                                                                                 {}
4008
4009         void                                                                                                                                            generatePoints                                                                  (int                                                                            iteration,
4010                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                        outData,
4011                                                                                                                                                                                                                                                                  std::vector<PointSceneSpec::ScenePoint>&       outPoints);
4012         const VkPipelineRasterizationStateCreateInfo*                                                           getRasterizationStateCreateInfo                                 (void) const;
4013
4014 protected:
4015         virtual const VkPipelineRasterizationLineStateCreateInfoEXT*                            getLineRasterizationStateCreateInfo                             (void);
4016
4017         virtual bool                                                                                                                            compareAndVerify                                                                (std::vector<PointSceneSpec::ScenePoint>&       points,
4018                                                                                                                                                                                                                                                                  tcu::Surface&                                                          resultImage,
4019                                                                                                                                                                                                                                                                  std::vector<tcu::Vec4>&                                        drawBuffer);
4020         virtual bool                                                                                                                            compareAndVerifyOverestimated                                   (std::vector<PointSceneSpec::ScenePoint>&       points,
4021                                                                                                                                                                                                                                                                  tcu::Surface&                                                          resultImage);
4022         virtual bool                                                                                                                            compareAndVerifyUnderestimated                                  (std::vector<PointSceneSpec::ScenePoint>&       points,
4023                                                                                                                                                                                                                                                                  tcu::Surface&                                                          resultImage);
4024
4025 private:
4026         const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>        initRasterizationConservativeStateCreateInfo    (void);
4027         const std::vector<VkPipelineRasterizationStateCreateInfo>                                       initRasterizationStateCreateInfo                                (void);
4028
4029         const ConservativeTestConfig                                                                                            m_conservativeTestConfig;
4030         const VkPhysicalDeviceConservativeRasterizationPropertiesEXT                            m_conservativeRasterizationProperties;
4031         const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>        m_rasterizationConservativeStateCreateInfo;
4032         const std::vector<VkPipelineRasterizationStateCreateInfo>                                       m_rasterizationStateCreateInfo;
4033         std::vector<int>                                                                                                                        m_renderStart;
4034         std::vector<int>                                                                                                                        m_renderEnd;
4035 };
4036
4037 void ConservativePointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
4038 {
4039         const float     pixelSize               = 2.0f / float(m_renderSize);
4040         const bool      isOverestimate  = m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
4041
4042         m_renderStart.clear();
4043         m_renderEnd.clear();
4044
4045         if (isOverestimate)
4046         {
4047                 const float     extraOverestimationSize = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
4048                 const float     overestimate                    = m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize;
4049                 const float     halfRenderAreaSize              = overestimate + 0.5f;
4050                 const float     pointCenterOffset               = 2.0f + 0.5f * float(iteration) + halfRenderAreaSize;
4051                 const float     pointEdgeStart                  = pointCenterOffset - halfRenderAreaSize;
4052                 const float     pointEdgeEnd                    = pointEdgeStart + 2 * halfRenderAreaSize;
4053                 const int       renderStart                             = int(deFloatFloor(pointEdgeStart)) + int((deFloatFrac(pointEdgeStart) > 0.0f) ? 0 : -1);
4054                 const int       renderEnd                               = int(deFloatCeil(pointEdgeEnd)) + int((deFloatFrac(pointEdgeEnd) > 0.0f) ? 0 : 1);
4055
4056                 outData.push_back(tcu::Vec4(-1.0f + pixelSize * pointCenterOffset, -1.0f + pixelSize * pointCenterOffset, 0.0f, 1.0f));
4057
4058                 m_renderStart.push_back(renderStart);
4059                 m_renderEnd.push_back(renderEnd);
4060         }
4061         else
4062         {
4063                 const float     pointSize                       = m_conservativeTestConfig.lineWidth;
4064                 const float     halfRenderAreaSize      = pointSize / 2.0f;
4065
4066                 switch (iteration)
4067                 {
4068                         case 0:
4069                         {
4070                                 const float     pointCenterOffset       = (pointSize + 1.0f + deFloatFrac(pointSize)) / 2.0f;
4071                                 const float     pointEdgeStart          = pointCenterOffset - halfRenderAreaSize;
4072                                 const float     pointEdgeEnd            = pointEdgeStart + 2.0f * halfRenderAreaSize;
4073                                 const int       renderStart                     = (m_renderSize / 2) + int(deFloatCeil(pointEdgeStart));
4074                                 const int       renderEnd                       = (m_renderSize / 2) + int(deFloatFloor(pointEdgeEnd));
4075
4076                                 outData.push_back(tcu::Vec4(pixelSize * pointCenterOffset, pixelSize * pointCenterOffset, 0.0f, 1.0f));
4077
4078                                 m_renderStart.push_back(renderStart);
4079                                 m_renderEnd.push_back(renderEnd);
4080
4081                                 break;
4082                         }
4083
4084                         case 1:
4085                         {
4086                                 const float subPixelSize                = 1.0f / float(1u<<(m_subpixelBits - 1));
4087                                 const float     pointBottomLeft         = 1.0f - subPixelSize;
4088                                 const float     pointCenterOffset       = pointBottomLeft + pointSize / 2.0f;
4089                                 const float     pointEdgeStart          = pointCenterOffset - halfRenderAreaSize;
4090                                 const float     pointEdgeEnd            = pointEdgeStart + 2.0f * halfRenderAreaSize;
4091                                 const int       renderStart                     = (m_renderSize / 2) + int(deFloatCeil(pointEdgeStart));
4092                                 const int       renderEnd                       = (m_renderSize / 2) + int(deFloatFloor(pointEdgeEnd));
4093
4094                                 outData.push_back(tcu::Vec4(pixelSize * pointCenterOffset, pixelSize * pointCenterOffset, 0.0f, 1.0f));
4095
4096                                 m_renderStart.push_back(renderStart);
4097                                 m_renderEnd.push_back(renderEnd);
4098
4099                                 break;
4100                         }
4101
4102                         case 2:
4103                         {
4104                                 // Edges of a point are considered not covered. Top-left coverage rule is not applicable for underestimate rasterization.
4105                                 const float     pointCenterOffset       = (pointSize + deFloatFrac(pointSize)) / 2.0f;
4106                                 const float     pointEdgeStart          = pointCenterOffset - halfRenderAreaSize;
4107                                 const float     pointEdgeEnd            = pointEdgeStart + 2.0f * halfRenderAreaSize;
4108                                 const int       renderStart                     = (m_renderSize / 2) + int(deFloatCeil(pointEdgeStart)) + 1;
4109                                 const int       renderEnd                       = (m_renderSize / 2) + int(deFloatFloor(pointEdgeEnd)) - 1;
4110
4111                                 outData.push_back(tcu::Vec4(pixelSize * pointCenterOffset, pixelSize * pointCenterOffset, 0.0f, 1.0f));
4112
4113                                 m_renderStart.push_back(renderStart);
4114                                 m_renderEnd.push_back(renderEnd);
4115
4116                                 break;
4117                         }
4118
4119                         default:
4120                                 TCU_THROW(InternalError, "Unexpected iteration");
4121                 }
4122         }
4123
4124         outPoints.resize(outData.size());
4125         for (size_t ndx = 0; ndx < outPoints.size(); ++ndx)
4126         {
4127                 outPoints[ndx].position = outData[ndx];
4128                 outPoints[ndx].pointSize = getPointSize();
4129         }
4130
4131         // log
4132         m_context.getTestContext().getLog()
4133                 << tcu::TestLog::Message
4134                 << "Testing conservative point rendering "
4135                 << "with rendering " << outPoints.size() << " points(s):"
4136                 << tcu::TestLog::EndMessage;
4137         for (int ndx = 0; ndx < (int)outPoints.size(); ++ndx)
4138         {
4139                 const deUint32   multiplier     = m_renderSize / 2;
4140
4141                 m_context.getTestContext().getLog()
4142                         << tcu::TestLog::Message
4143                         << "Point " << (ndx+1) << ":"
4144                         << "\n\t" << outPoints[ndx].position << " == " << (float(multiplier) * outPoints[ndx].position) << "/" << multiplier
4145                         << tcu::TestLog::EndMessage;
4146         }
4147 }
4148
4149 bool ConservativePointTestInstance::compareAndVerify (std::vector<PointSceneSpec::ScenePoint>& points, tcu::Surface& resultImage, std::vector<tcu::Vec4>& drawBuffer)
4150 {
4151         DE_UNREF(drawBuffer);
4152
4153         switch (m_conservativeTestConfig.conservativeRasterizationMode)
4154         {
4155                 case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT:
4156                 {
4157                         return compareAndVerifyOverestimated(points, resultImage);
4158                 }
4159                 case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT:
4160                 {
4161                         return compareAndVerifyUnderestimated(points, resultImage);
4162                 }
4163
4164                 default:
4165                         TCU_THROW(InternalError, "Unknown conservative rasterization mode");
4166         }
4167 }
4168
4169 bool ConservativePointTestInstance::compareAndVerifyOverestimated (std::vector<PointSceneSpec::ScenePoint>& points, tcu::Surface& resultImage)
4170 {
4171         DE_UNREF(points);
4172
4173         const char*                     iterationComments[]             = { "Edges and corners", "Partial coverage", "Edges and corners" };
4174         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
4175         const tcu::RGBA         foregroundColor                 = tcu::RGBA(255, 255, 255, 255);
4176         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
4177         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
4178         int                                     errX                                    = 0;
4179         int                                     errY                                    = 0;
4180         deUint32                        errValue                                = 0;
4181         bool                            result                                  = true;
4182
4183         log << tcu::TestLog::Message << "Points expected to be rasterized with white color" << tcu::TestLog::EndMessage;
4184         log << tcu::TestLog::Message << "Testing " << iterationComments[getIteration()] << tcu::TestLog::EndMessage;
4185
4186         for (size_t renderAreaNdx = 0; result && renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4187         {
4188                 const int renderStart   = m_renderStart[renderAreaNdx];
4189                 const int renderEnd             = m_renderEnd[renderAreaNdx];
4190
4191                 for (int y = renderStart; result && y < renderEnd; ++y)
4192                 for (int x = renderStart; result && x < renderEnd; ++x)
4193                 {
4194                         if (resultImage.getPixel(x,y).getPacked() != foregroundColor.getPacked())
4195                         {
4196                                 result          = false;
4197                                 errX            = x;
4198                                 errY            = y;
4199                                 errValue        = resultImage.getPixel(x, y).getPacked();
4200
4201                                 break;
4202                         }
4203                 }
4204         }
4205
4206         if (!result)
4207         {
4208                 tcu::Surface            referenceImage  (resultImage.getWidth(), resultImage.getHeight());
4209                 tcu::Surface            errorMask               (resultImage.getWidth(), resultImage.getHeight());
4210                 std::ostringstream      css;
4211
4212                 for (int y = 0; y < resultImage.getHeight(); ++y)
4213                 for (int x = 0; x < resultImage.getWidth(); ++x)
4214                         referenceImage.setPixel(x, y, backgroundColor);
4215
4216                 for (size_t renderAreaNdx = 0; renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4217                 {
4218                         const int renderStart   = m_renderStart[renderAreaNdx];
4219                         const int renderEnd             = m_renderEnd[renderAreaNdx];
4220
4221                         for (int y = renderStart; y < renderEnd; ++y)
4222                         for (int x = renderStart; x < renderEnd; ++x)
4223                                 referenceImage.setPixel(x, y, foregroundColor);
4224                 }
4225
4226                 for (int y = 0; y < errorMask.getHeight(); ++y)
4227                 for (int x = 0; x < errorMask.getWidth(); ++x)
4228                 {
4229                         if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4230                                 errorMask.setPixel(x, y, unexpectedPixelColor);
4231                         else
4232                                 errorMask.setPixel(x, y, backgroundColor);
4233                 }
4234
4235                 css << std::endl;
4236                 for (size_t renderAreaNdx = 0; renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4237                 {
4238                         const int renderStart   = m_renderStart[renderAreaNdx];
4239                         const int renderEnd             = m_renderEnd[renderAreaNdx];
4240
4241                         css << "[" << renderStart << "," << renderEnd << ") x [" << renderStart << "," << renderEnd << ")" << std::endl;
4242                 }
4243
4244                 log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
4245                         << tcu::TestLog::EndMessage;
4246                 log << tcu::TestLog::Message << "Expected area(s) to be filled:" << css.str()
4247                         << tcu::TestLog::EndMessage;
4248                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4249                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
4250                         << tcu::TestLog::Image("Reference",     "Reference",    referenceImage)
4251                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
4252                         << tcu::TestLog::EndImageSet;
4253         }
4254         else
4255         {
4256                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
4257                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4258                         << tcu::TestLog::Image("Result", "Result", resultImage)
4259                         << tcu::TestLog::EndImageSet;
4260         }
4261
4262         return result;
4263 }
4264
4265 bool ConservativePointTestInstance::compareAndVerifyUnderestimated (std::vector<PointSceneSpec::ScenePoint>& points, tcu::Surface& resultImage)
4266 {
4267         DE_UNREF(points);
4268
4269         const char*                     iterationComments[]             = { "Full coverage", "Full coverage with subpixel", "Exact coverage" };
4270         const tcu::RGBA         backgroundColor                 = tcu::RGBA(0, 0, 0, 255);
4271         const tcu::RGBA         foregroundColor                 = tcu::RGBA(255, 255, 255, 255);
4272         const tcu::RGBA         unexpectedPixelColor    = tcu::RGBA(255, 0, 0, 255);
4273         tcu::TestLog&           log                                             = m_context.getTestContext().getLog();
4274         int                                     errX                                    = 0;
4275         int                                     errY                                    = 0;
4276         deUint32                        errValue                                = 0;
4277         bool                            result                                  = true;
4278         tcu::Surface            referenceImage                  (resultImage.getWidth(), resultImage.getHeight());
4279
4280         log << tcu::TestLog::Message << "Points expected to be rasterized with white color" << tcu::TestLog::EndMessage;
4281         log << tcu::TestLog::Message << "Testing " << iterationComments[getIteration()] << tcu::TestLog::EndMessage;
4282
4283         for (int y = 0; y < resultImage.getHeight(); ++y)
4284         for (int x = 0; x < resultImage.getWidth(); ++x)
4285                 referenceImage.setPixel(x, y, backgroundColor);
4286
4287         for (size_t renderAreaNdx = 0; result && renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4288         {
4289                 const int renderStart   = m_renderStart[renderAreaNdx];
4290                 const int renderEnd             = m_renderEnd[renderAreaNdx];
4291
4292                 for (int y = renderStart; y < renderEnd; ++y)
4293                 for (int x = renderStart; x < renderEnd; ++x)
4294                         referenceImage.setPixel(x, y, foregroundColor);
4295         }
4296
4297         for (int y = 0; result && y < resultImage.getHeight(); ++y)
4298         for (int x = 0; result && x < resultImage.getWidth(); ++x)
4299         {
4300                 if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4301                 {
4302                         result          = false;
4303                         errX            = x;
4304                         errY            = y;
4305                         errValue        = resultImage.getPixel(x, y).getPacked();
4306
4307                         break;
4308                 }
4309         }
4310
4311         if (!result)
4312         {
4313                 tcu::Surface            errorMask       (resultImage.getWidth(), resultImage.getHeight());
4314                 std::ostringstream      css;
4315
4316                 for (int y = 0; y < errorMask.getHeight(); ++y)
4317                 for (int x = 0; x < errorMask.getWidth(); ++x)
4318                 {
4319                         if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4320                                 errorMask.setPixel(x, y, unexpectedPixelColor);
4321                         else
4322                                 errorMask.setPixel(x, y, backgroundColor);
4323                 }
4324
4325                 css << std::endl;
4326                 for (size_t renderAreaNdx = 0; renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4327                 {
4328                         const int renderStart   = m_renderStart[renderAreaNdx];
4329                         const int renderEnd             = m_renderEnd[renderAreaNdx];
4330
4331                         css << "[" << renderStart << "," << renderEnd << ") x [" << renderStart << "," << renderEnd << ")" << std::endl;
4332                 }
4333
4334                 log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
4335                         << tcu::TestLog::EndMessage;
4336                 log << tcu::TestLog::Message << "Expected area(s) to be filled:" << css.str()
4337                         << tcu::TestLog::EndMessage;
4338                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4339                         << tcu::TestLog::Image("Result",        "Result",               resultImage)
4340                         << tcu::TestLog::Image("Reference",     "Reference",    referenceImage)
4341                         << tcu::TestLog::Image("ErrorMask", "ErrorMask",        errorMask)
4342                         << tcu::TestLog::EndImageSet;
4343         }
4344         else
4345         {
4346                 log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
4347                 log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4348                         << tcu::TestLog::Image("Result", "Result", resultImage)
4349                         << tcu::TestLog::EndImageSet;
4350         }
4351
4352         return result;
4353 }
4354
4355 const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT> ConservativePointTestInstance::initRasterizationConservativeStateCreateInfo (void)
4356 {
4357         const float                                                                                                                     extraOverestimationSize = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
4358         std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>      result;
4359
4360         result.reserve(getIterationCount());
4361
4362         for (int iteration = 0; iteration < getIterationCount(); ++iteration)
4363         {
4364                 const VkPipelineRasterizationConservativeStateCreateInfoEXT     rasterizationConservativeStateCreateInfo        =
4365                 {
4366                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,    //  VkStructureType                                                                                     sType;
4367                         DE_NULL,                                                                                                                                                //  const void*                                                                                         pNext;
4368                         (VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,                                              //  VkPipelineRasterizationConservativeStateCreateFlagsEXT      flags;
4369                         m_conservativeTestConfig.conservativeRasterizationMode,                                                 //  VkConservativeRasterizationModeEXT                                          conservativeRasterizationMode;
4370                         extraOverestimationSize                                                                                                                 //  float                                                                                                       extraPrimitiveOverestimationSize;
4371                 };
4372
4373                 result.push_back(rasterizationConservativeStateCreateInfo);
4374         }
4375
4376         return result;
4377 }
4378
4379 const std::vector<VkPipelineRasterizationStateCreateInfo> ConservativePointTestInstance::initRasterizationStateCreateInfo (void)
4380 {
4381         std::vector<VkPipelineRasterizationStateCreateInfo>     result;
4382
4383         result.reserve(getIterationCount());
4384
4385         for (int iteration = 0; iteration < getIterationCount(); ++iteration)
4386         {
4387                 const VkPipelineRasterizationStateCreateInfo    rasterizationStateCreateInfo    =
4388                 {
4389                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             //  VkStructureType                                                     sType;
4390                         &m_rasterizationConservativeStateCreateInfo[iteration],                 //  const void*                                                         pNext;
4391                         0,                                                                                                                              //  VkPipelineRasterizationStateCreateFlags     flags;
4392                         false,                                                                                                                  //  VkBool32                                                            depthClampEnable;
4393                         false,                                                                                                                  //  VkBool32                                                            rasterizerDiscardEnable;
4394                         VK_POLYGON_MODE_FILL,                                                                                   //  VkPolygonMode                                                       polygonMode;
4395                         VK_CULL_MODE_NONE,                                                                                              //  VkCullModeFlags                                                     cullMode;
4396                         VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                //  VkFrontFace                                                         frontFace;
4397                         VK_FALSE,                                                                                                               //  VkBool32                                                            depthBiasEnable;
4398                         0.0f,                                                                                                                   //  float                                                                       depthBiasConstantFactor;
4399                         0.0f,                                                                                                                   //  float                                                                       depthBiasClamp;
4400                         0.0f,                                                                                                                   //  float                                                                       depthBiasSlopeFactor;
4401                         0.0f,                                                                                                                   //  float                                                                       lineWidth;
4402                 };
4403
4404                 result.push_back(rasterizationStateCreateInfo);
4405         }
4406
4407         return result;
4408 }
4409
4410 const VkPipelineRasterizationStateCreateInfo* ConservativePointTestInstance::getRasterizationStateCreateInfo    (void) const
4411 {
4412         return &m_rasterizationStateCreateInfo[getIteration()];
4413 }
4414
4415 const VkPipelineRasterizationLineStateCreateInfoEXT* ConservativePointTestInstance::getLineRasterizationStateCreateInfo (void)
4416 {
4417         return DE_NULL;
4418 }
4419
4420
4421 template <typename ConcreteTestInstance>
4422 class WidenessTestCase : public BaseRenderingTestCase
4423 {
4424 public:
4425                                                                 WidenessTestCase        (tcu::TestContext&                      context,
4426                                                                                                          const std::string&                     name,
4427                                                                                                          const std::string&                     description,
4428                                                                                                          PrimitiveWideness                      wideness,
4429                                                                                                          PrimitiveStrictness            strictness,
4430                                                                                                          bool                                           isLineTest,
4431                                                                                                          VkSampleCountFlagBits          sampleCount,
4432                                                                                                          LineStipple                            stipple,
4433                                                                                                          VkLineRasterizationModeEXT     lineRasterizationMode,
4434                                                                                                          deUint32                                       additionalRenderSize    = 0)
4435                                                                         : BaseRenderingTestCase         (context, name, description, sampleCount)
4436                                                                         , m_wideness(wideness)
4437                                                                         , m_strictness                          (strictness)
4438                                                                         , m_isLineTest                          (isLineTest)
4439                                                                         , m_stipple                                     (stipple)
4440                                                                         , m_lineRasterizationMode       (lineRasterizationMode)
4441                                                                         , m_additionalRenderSize        (additionalRenderSize)
4442                                                                 {}
4443
4444         virtual TestInstance*           createInstance          (Context& context) const
4445                                                                 {
4446                                                                         return new ConcreteTestInstance(context, m_wideness, m_strictness, m_sampleCount, m_stipple, m_lineRasterizationMode, m_additionalRenderSize);
4447                                                                 }
4448
4449         virtual void                            checkSupport            (Context& context) const
4450                                                                 {
4451                                                                         if (m_isLineTest)
4452                                                                         {
4453                                                                                 if (m_wideness == PRIMITIVEWIDENESS_WIDE)
4454                                                                                         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
4455
4456                                                                                 switch (m_lineRasterizationMode)
4457                                                                                 {
4458                                                                                         default:
4459                                                                                                 TCU_THROW(InternalError, "Unknown line rasterization mode");
4460
4461                                                                                         case VK_LINE_RASTERIZATION_MODE_EXT_LAST:
4462                                                                                         {
4463                                                                                                 if (m_strictness == PRIMITIVESTRICTNESS_STRICT)
4464                                                                                                         if (!context.getDeviceProperties().limits.strictLines)
4465                                                                                                                 TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
4466
4467                                                                                                 if (m_strictness == PRIMITIVESTRICTNESS_NONSTRICT)
4468                                                                                                         if (context.getDeviceProperties().limits.strictLines)
4469                                                                                                                 TCU_THROW(NotSupportedError, "Nonstrict rasterization is not supported");
4470
4471                                                                                                 break;
4472                                                                                         }
4473
4474                                                                                         case VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT:
4475                                                                                         {
4476                                                                                                 if (!context.getDeviceProperties().limits.strictLines)
4477                                                                                                         TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
4478
4479                                                                                                 if (getLineStippleEnable() &&
4480                                                                                                         !context.getLineRasterizationFeaturesEXT().stippledRectangularLines)
4481                                                                                                         TCU_THROW(NotSupportedError, "Stippled rectangular lines not supported");
4482                                                                                                 break;
4483                                                                                         }
4484
4485                                                                                         case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT:
4486                                                                                         {
4487                                                                                                 if (!context.getLineRasterizationFeaturesEXT().rectangularLines)
4488                                                                                                         TCU_THROW(NotSupportedError, "Rectangular lines not supported");
4489
4490                                                                                                 if (getLineStippleEnable() &&
4491                                                                                                         !context.getLineRasterizationFeaturesEXT().stippledRectangularLines)
4492                                                                                                         TCU_THROW(NotSupportedError, "Stippled rectangular lines not supported");
4493                                                                                                 break;
4494                                                                                         }
4495
4496                                                                                         case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT:
4497                                                                                         {
4498                                                                                                 if (!context.getLineRasterizationFeaturesEXT().bresenhamLines)
4499                                                                                                         TCU_THROW(NotSupportedError, "Bresenham lines not supported");
4500
4501                                                                                                 if (getLineStippleEnable() &&
4502                                                                                                         !context.getLineRasterizationFeaturesEXT().stippledBresenhamLines)
4503                                                                                                         TCU_THROW(NotSupportedError, "Stippled Bresenham lines not supported");
4504                                                                                                 break;
4505                                                                                         }
4506
4507                                                                                         case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT:
4508                                                                                         {
4509                                                                                                 if (!context.getLineRasterizationFeaturesEXT().smoothLines)
4510                                                                                                         TCU_THROW(NotSupportedError, "Smooth lines not supported");
4511
4512                                                                                                 if (getLineStippleEnable() &&
4513                                                                                                         !context.getLineRasterizationFeaturesEXT().stippledSmoothLines)
4514                                                                                                         TCU_THROW(NotSupportedError, "Stippled smooth lines not supported");
4515                                                                                                 break;
4516                                                                                         }
4517                                                                                 }
4518                                                                         }
4519                                                                         else
4520                                                                         {
4521                                                                                 if (m_wideness == PRIMITIVEWIDENESS_WIDE)
4522                                                                                         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
4523                                                                         }
4524                                                                 }
4525
4526         bool                                    getLineStippleEnable    (void) const { return m_stipple != LINESTIPPLE_DISABLED; }
4527         virtual bool                    getLineStippleDynamic   (void) const { return m_stipple == LINESTIPPLE_DYNAMIC; };
4528
4529 protected:
4530         const PrimitiveWideness                         m_wideness;
4531         const PrimitiveStrictness                       m_strictness;
4532         const bool                                                      m_isLineTest;
4533         const LineStipple                                       m_stipple;
4534         const VkLineRasterizationModeEXT        m_lineRasterizationMode;
4535         const deUint32                                          m_additionalRenderSize;
4536 };
4537
4538 class LinesTestInstance : public BaseLineTestInstance
4539 {
4540 public:
4541                                                                 LinesTestInstance       (Context& context, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount, LineStipple stipple, VkLineRasterizationModeEXT lineRasterizationMode, deUint32 additionalRenderSize = 0)
4542                                                                         : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, strictness, sampleCount, stipple, lineRasterizationMode, additionalRenderSize)
4543                                                                 {}
4544
4545         virtual void                            generateLines           (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
4546 };
4547
4548 void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
4549 {
4550         outData.resize(8);
4551
4552         switch (iteration)
4553         {
4554                 case 0:
4555                         // \note: these values are chosen arbitrarily
4556                         outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
4557                         outData[1] = tcu::Vec4(  0.5f,  0.2f, 0.0f, 1.0f);
4558                         outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
4559                         outData[3] = tcu::Vec4( -0.3f,  0.2f, 0.0f, 1.0f);
4560                         outData[4] = tcu::Vec4( -1.5f, -0.4f, 0.0f, 1.0f);
4561                         outData[5] = tcu::Vec4(  0.1f,  0.5f, 0.0f, 1.0f);
4562                         outData[6] = tcu::Vec4( 0.75f, -0.4f, 0.0f, 1.0f);
4563                         outData[7] = tcu::Vec4(  0.3f,  0.8f, 0.0f, 1.0f);
4564                         break;
4565
4566                 case 1:
4567                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
4568                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
4569                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
4570                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
4571                         outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
4572                         outData[5] = tcu::Vec4(  0.18f,  -0.2f, 0.0f, 1.0f);
4573                         outData[6] = tcu::Vec4(   0.0f,   1.0f, 0.0f, 1.0f);
4574                         outData[7] = tcu::Vec4(   0.0f,  -1.0f, 0.0f, 1.0f);
4575                         break;
4576
4577                 case 2:
4578                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
4579                         outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
4580                         outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
4581                         outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
4582                         outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
4583                         outData[5] = tcu::Vec4(  0.8f, -0.7f, 0.0f, 1.0f);
4584                         outData[6] = tcu::Vec4(  0.9f,  0.7f, 0.0f, 1.0f);
4585                         outData[7] = tcu::Vec4( -0.9f,  0.7f, 0.0f, 1.0f);
4586                         break;
4587         }
4588
4589         outLines.resize(4);
4590         outLines[0].positions[0] = outData[0];
4591         outLines[0].positions[1] = outData[1];
4592         outLines[1].positions[0] = outData[2];
4593         outLines[1].positions[1] = outData[3];
4594         outLines[2].positions[0] = outData[4];
4595         outLines[2].positions[1] = outData[5];
4596         outLines[3].positions[0] = outData[6];
4597         outLines[3].positions[1] = outData[7];
4598
4599         // log
4600         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
4601         for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
4602         {
4603                 m_context.getTestContext().getLog()
4604                         << tcu::TestLog::Message
4605                         << "Line " << (lineNdx+1) << ":"
4606                         << "\n\t" << outLines[lineNdx].positions[0]
4607                         << "\n\t" << outLines[lineNdx].positions[1]
4608                         << tcu::TestLog::EndMessage;
4609         }
4610 }
4611
4612 class LineStripTestInstance : public BaseLineTestInstance
4613 {
4614 public:
4615                                         LineStripTestInstance   (Context& context, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount, LineStipple stipple, VkLineRasterizationModeEXT lineRasterizationMode, deUint32)
4616                                                 : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, strictness, sampleCount, stipple, lineRasterizationMode)
4617                                         {}
4618
4619         virtual void    generateLines                   (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
4620 };
4621
4622 void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
4623 {
4624         outData.resize(4);
4625
4626         switch (iteration)
4627         {
4628                 case 0:
4629                         // \note: these values are chosen arbitrarily
4630                         outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
4631                         outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
4632                         outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
4633                         outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
4634                         break;
4635
4636                 case 1:
4637                         outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
4638                         outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
4639                         outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
4640                         outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
4641                         break;
4642
4643                 case 2:
4644                         outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
4645                         outData[1] = tcu::Vec4(  0.9f, -0.9f, 0.0f, 1.0f);
4646                         outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
4647                         outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
4648                         break;
4649         }
4650
4651         outLines.resize(3);
4652         outLines[0].positions[0] = outData[0];
4653         outLines[0].positions[1] = outData[1];
4654         outLines[1].positions[0] = outData[1];
4655         outLines[1].positions[1] = outData[2];
4656         outLines[2].positions[0] = outData[2];
4657         outLines[2].positions[1] = outData[3];
4658
4659         // log
4660         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
4661         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
4662         {
4663                 m_context.getTestContext().getLog()
4664                         << tcu::TestLog::Message
4665                         << "\t" << outData[vtxNdx]
4666                         << tcu::TestLog::EndMessage;
4667         }
4668 }
4669
4670 class FillRuleTestInstance : public BaseRenderingTestInstance
4671 {
4672 public:
4673         enum FillRuleCaseType
4674         {
4675                 FILLRULECASE_BASIC = 0,
4676                 FILLRULECASE_REVERSED,
4677                 FILLRULECASE_CLIPPED_FULL,
4678                 FILLRULECASE_CLIPPED_PARTIAL,
4679                 FILLRULECASE_PROJECTED,
4680
4681                 FILLRULECASE_LAST
4682         };
4683                                                                                                                 FillRuleTestInstance                    (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount);
4684         virtual tcu::TestStatus                                                         iterate                                                 (void);
4685
4686 private:
4687
4688         virtual const VkPipelineColorBlendStateCreateInfo*      getColorBlendStateCreateInfo    (void) const;
4689         int                                                                                                     getRenderSize                                   (FillRuleCaseType type) const;
4690         int                                                                                                     getNumIterations                                (FillRuleCaseType type) const;
4691         void                                                                                            generateTriangles                               (int iteration, std::vector<tcu::Vec4>& outData) const;
4692
4693         const FillRuleCaseType                                                          m_caseType;
4694         int                                                                                                     m_iteration;
4695         const int                                                                                       m_iterationCount;
4696         bool                                                                                            m_allIterationsPassed;
4697
4698 };
4699
4700 FillRuleTestInstance::FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount)
4701         : BaseRenderingTestInstance             (context, sampleCount, getRenderSize(type))
4702         , m_caseType                                    (type)
4703         , m_iteration                                   (0)
4704         , m_iterationCount                              (getNumIterations(type))
4705         , m_allIterationsPassed                 (true)
4706 {
4707         DE_ASSERT(type < FILLRULECASE_LAST);
4708 }
4709
4710 tcu::TestStatus FillRuleTestInstance::iterate (void)
4711 {
4712         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
4713         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
4714         tcu::IVec4                                                              colorBits                               = tcu::getTextureFormatBitDepth(getTextureFormat());
4715         const int                                                               thresholdRed                    = 1 << (8 - colorBits[0]);
4716         const int                                                               thresholdGreen                  = 1 << (8 - colorBits[1]);
4717         const int                                                               thresholdBlue                   = 1 << (8 - colorBits[2]);
4718         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
4719         std::vector<tcu::Vec4>                                  drawBuffer;
4720
4721         generateTriangles(m_iteration, drawBuffer);
4722
4723         // draw image
4724         {
4725                 const std::vector<tcu::Vec4>    colorBuffer             (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
4726
4727                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
4728
4729                 drawPrimitives(resultImage, drawBuffer, colorBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
4730         }
4731
4732         // verify no overdraw
4733         {
4734                 const tcu::RGBA triangleColor   = tcu::RGBA(127, 127, 127, 255);
4735                 bool                    overdraw                = false;
4736
4737                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
4738
4739                 for (int y = 0; y < resultImage.getHeight(); ++y)
4740                 for (int x = 0; x < resultImage.getWidth();  ++x)
4741                 {
4742                         const tcu::RGBA color = resultImage.getPixel(x, y);
4743
4744                         // color values are greater than triangle color? Allow lower values for multisampled edges and background.
4745                         if ((color.getRed()   - triangleColor.getRed())   > thresholdRed   ||
4746                                 (color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
4747                                 (color.getBlue()  - triangleColor.getBlue())  > thresholdBlue)
4748                                 overdraw = true;
4749                 }
4750
4751                 // results
4752                 if (!overdraw)
4753                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
4754                 else
4755                 {
4756                         m_context.getTestContext().getLog()     << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
4757                         m_allIterationsPassed = false;
4758                 }
4759         }
4760
4761         // verify no missing fragments in the full viewport case
4762         if (m_caseType == FILLRULECASE_CLIPPED_FULL)
4763         {
4764                 bool missingFragments = false;
4765
4766                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
4767
4768                 for (int y = 0; y < resultImage.getHeight(); ++y)
4769                 for (int x = 0; x < resultImage.getWidth();  ++x)
4770                 {
4771                         const tcu::RGBA color = resultImage.getPixel(x, y);
4772
4773                         // black? (background)
4774                         if (color.getRed()   <= thresholdRed   ||
4775                                 color.getGreen() <= thresholdGreen ||
4776                                 color.getBlue()  <= thresholdBlue)
4777                                 missingFragments = true;
4778                 }
4779
4780                 // results
4781                 if (!missingFragments)
4782                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
4783                 else
4784                 {
4785                         m_context.getTestContext().getLog()     << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
4786
4787                         m_allIterationsPassed = false;
4788                 }
4789         }
4790
4791         m_context.getTestContext().getLog()     << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
4792                                                                                 << tcu::TestLog::Image("Result", "Result", resultImage)
4793                                                                                 << tcu::TestLog::EndImageSet;
4794
4795         // result
4796         if (++m_iteration == m_iterationCount)
4797         {
4798                 if (m_allIterationsPassed)
4799                         return tcu::TestStatus::pass("Pass");
4800                 else
4801                         return tcu::TestStatus::fail("Found invalid pixels");
4802         }
4803         else
4804                 return tcu::TestStatus::incomplete();
4805 }
4806
4807 int FillRuleTestInstance::getRenderSize (FillRuleCaseType type) const
4808 {
4809         if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
4810                 return RESOLUTION_POT / 4;
4811         else
4812                 return RESOLUTION_POT;
4813 }
4814
4815 int FillRuleTestInstance::getNumIterations (FillRuleCaseType type) const
4816 {
4817         if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
4818                 return 15;
4819         else
4820                 return 2;
4821 }
4822
4823 void FillRuleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
4824 {
4825         switch (m_caseType)
4826         {
4827                 case FILLRULECASE_BASIC:
4828                 case FILLRULECASE_REVERSED:
4829                 case FILLRULECASE_PROJECTED:
4830                 {
4831                         const int       numRows         = 4;
4832                         const int       numColumns      = 4;
4833                         const float     quadSide        = 0.15f;
4834                         de::Random      rnd                     (0xabcd);
4835
4836                         outData.resize(6 * numRows * numColumns);
4837
4838                         for (int col = 0; col < numColumns; ++col)
4839                         for (int row = 0; row < numRows;    ++row)
4840                         {
4841                                 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);
4842                                 const float             rotation        = (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
4843                                 const tcu::Vec2 sideH           = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
4844                                 const tcu::Vec2 sideV           = tcu::Vec2(sideH.y(), -sideH.x());
4845                                 const tcu::Vec2 quad[4]         =
4846                                 {
4847                                         center + sideH + sideV,
4848                                         center + sideH - sideV,
4849                                         center - sideH - sideV,
4850                                         center - sideH + sideV,
4851                                 };
4852
4853                                 if (m_caseType == FILLRULECASE_BASIC)
4854                                 {
4855                                         outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
4856                                         outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
4857                                         outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
4858                                         outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
4859                                         outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
4860                                         outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
4861                                 }
4862                                 else if (m_caseType == FILLRULECASE_REVERSED)
4863                                 {
4864                                         outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
4865                                         outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
4866                                         outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
4867                                         outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
4868                                         outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
4869                                         outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
4870                                 }
4871                                 else if (m_caseType == FILLRULECASE_PROJECTED)
4872                                 {
4873                                         const float w0 = rnd.getFloat(0.1f, 4.0f);
4874                                         const float w1 = rnd.getFloat(0.1f, 4.0f);
4875                                         const float w2 = rnd.getFloat(0.1f, 4.0f);
4876                                         const float w3 = rnd.getFloat(0.1f, 4.0f);
4877
4878                                         outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
4879                                         outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
4880                                         outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
4881                                         outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
4882                                         outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
4883                                         outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
4884                                 }
4885                                 else
4886                                         DE_ASSERT(DE_FALSE);
4887                         }
4888
4889                         break;
4890                 }
4891
4892                 case FILLRULECASE_CLIPPED_PARTIAL:
4893                 case FILLRULECASE_CLIPPED_FULL:
4894                 {
4895                         const float             quadSide        = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
4896                         const tcu::Vec2 center          = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
4897                         const float             rotation        = (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
4898                         const tcu::Vec2 sideH           = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
4899                         const tcu::Vec2 sideV           = tcu::Vec2(sideH.y(), -sideH.x());
4900                         const tcu::Vec2 quad[4]         =
4901                         {
4902                                 center + sideH + sideV,
4903                                 center + sideH - sideV,
4904                                 center - sideH - sideV,
4905                                 center - sideH + sideV,
4906                         };
4907
4908                         outData.resize(6);
4909                         outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
4910                         outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
4911                         outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
4912                         outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
4913                         outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
4914                         outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
4915                         break;
4916                 }
4917
4918                 default:
4919                         DE_ASSERT(DE_FALSE);
4920         }
4921 }
4922
4923 const VkPipelineColorBlendStateCreateInfo* FillRuleTestInstance::getColorBlendStateCreateInfo (void) const
4924 {
4925         static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
4926         {
4927                 true,                                                                                                           // VkBool32                     blendEnable;
4928                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendColor;
4929                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      destBlendColor;
4930                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpColor;
4931                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      srcBlendAlpha;
4932                 VK_BLEND_FACTOR_ONE,                                                                            // VkBlend                      destBlendAlpha;
4933                 VK_BLEND_OP_ADD,                                                                                        // VkBlendOp            blendOpAlpha;
4934                 (VK_COLOR_COMPONENT_R_BIT |
4935                  VK_COLOR_COMPONENT_G_BIT |
4936                  VK_COLOR_COMPONENT_B_BIT |
4937                  VK_COLOR_COMPONENT_A_BIT)                                                                      // VkChannelFlags       channelWriteMask;
4938         };
4939
4940         static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
4941         {
4942                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
4943                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
4944                 0,                                                                                                                      // VkPipelineColorBlendStateCreateFlags                 flags;
4945                 false,                                                                                                          // VkBool32                                                                             logicOpEnable;
4946                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
4947                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
4948                 &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
4949                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConst[4];
4950         };
4951
4952         return &colorBlendStateParams;
4953 }
4954
4955
4956 class FillRuleTestCase : public BaseRenderingTestCase
4957 {
4958 public:
4959                                                                 FillRuleTestCase        (tcu::TestContext& context, const std::string& name, const std::string& description, FillRuleTestInstance::FillRuleCaseType type, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
4960                                                                         : BaseRenderingTestCase (context, name, description, sampleCount)
4961                                                                         , m_type                                (type)
4962                                                                 {}
4963
4964         virtual TestInstance*           createInstance          (Context& context) const
4965                                                                 {
4966                                                                         return new FillRuleTestInstance(context, m_type, m_sampleCount);
4967                                                                 }
4968 protected:
4969         const FillRuleTestInstance::FillRuleCaseType m_type;
4970 };
4971
4972 class CullingTestInstance : public BaseRenderingTestInstance
4973 {
4974 public:
4975                                                                                                         CullingTestInstance                             (Context& context, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode)
4976                                                                                                                 : BaseRenderingTestInstance             (context, VK_SAMPLE_COUNT_1_BIT, RESOLUTION_POT)
4977                                                                                                                 , m_cullMode                                    (cullMode)
4978                                                                                                                 , m_primitiveTopology                   (primitiveTopology)
4979                                                                                                                 , m_frontFace                                   (frontFace)
4980                                                                                                                 , m_polygonMode                                 (polygonMode)
4981                                                                                                                 , m_multisampling                               (true)
4982                                                                                                         {}
4983         virtual
4984         const VkPipelineRasterizationStateCreateInfo*   getRasterizationStateCreateInfo (void) const;
4985
4986         tcu::TestStatus                                                                 iterate                                                 (void);
4987
4988 private:
4989         void                                                                                    generateVertices                                (std::vector<tcu::Vec4>& outData) const;
4990         void                                                                                    extractTriangles                                (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
4991         void                                                                                    extractLines                                    (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<LineSceneSpec::SceneLine>& outLines) const;
4992         void                                                                                    extractPoints                                   (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<PointSceneSpec::ScenePoint>& outPoints) const;
4993         bool                                                                                    triangleOrder                                   (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
4994
4995         const VkCullModeFlags                                                   m_cullMode;
4996         const VkPrimitiveTopology                                               m_primitiveTopology;
4997         const VkFrontFace                                                               m_frontFace;
4998         const VkPolygonMode                                                             m_polygonMode;
4999         const bool                                                                              m_multisampling;
5000 };
5001
5002
5003 tcu::TestStatus CullingTestInstance::iterate (void)
5004 {
5005         DE_ASSERT(m_polygonMode <= VK_POLYGON_MODE_POINT);
5006
5007         tcu::Surface                                                                    resultImage                                             (m_renderSize, m_renderSize);
5008         std::vector<tcu::Vec4>                                                  drawBuffer;
5009         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
5010         std::vector<PointSceneSpec::ScenePoint>                 points;
5011         std::vector<LineSceneSpec::SceneLine>                   lines;
5012
5013         const InstanceInterface&                                                vk                              = m_context.getInstanceInterface();
5014         const VkPhysicalDevice                                                  physicalDevice  = m_context.getPhysicalDevice();
5015         const VkPhysicalDeviceFeatures                                  deviceFeatures  = getPhysicalDeviceFeatures(vk, physicalDevice);
5016
5017         if (!(deviceFeatures.fillModeNonSolid) && (m_polygonMode == VK_POLYGON_MODE_LINE || m_polygonMode == VK_POLYGON_MODE_POINT))
5018                 TCU_THROW(NotSupportedError, "Wireframe fill modes are not supported");
5019
5020         // generate scene
5021         generateVertices(drawBuffer);
5022         extractTriangles(triangles, drawBuffer);
5023
5024         if (m_polygonMode == VK_POLYGON_MODE_LINE)
5025                 extractLines(triangles ,lines);
5026         else if (m_polygonMode == VK_POLYGON_MODE_POINT)
5027                 extractPoints(triangles, points);
5028
5029         // draw image
5030         {
5031                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting front face to " << m_frontFace << tcu::TestLog::EndMessage;
5032                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting cull face to " << m_cullMode << tcu::TestLog::EndMessage;
5033                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing test pattern (" << m_primitiveTopology << ")" << tcu::TestLog::EndMessage;
5034
5035                 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
5036         }
5037
5038         // compare
5039         {
5040                 RasterizationArguments  args;
5041                 tcu::IVec4                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
5042                 bool                                    isCompareOk     = false;
5043
5044                 args.numSamples         = m_multisampling ? 1 : 0;
5045                 args.subpixelBits       = m_subpixelBits;
5046                 args.redBits            = colorBits[0];
5047                 args.greenBits          = colorBits[1];
5048                 args.blueBits           = colorBits[2];
5049
5050                 switch (m_polygonMode)
5051                 {
5052                         case VK_POLYGON_MODE_LINE:
5053                         {
5054                                 LineSceneSpec scene;
5055                                 scene.lineWidth = 0;
5056                                 scene.lines.swap(lines);
5057                                 isCompareOk = verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
5058                                 break;
5059                         }
5060                         case VK_POLYGON_MODE_POINT:
5061                         {
5062                                 PointSceneSpec scene;
5063                                 scene.points.swap(points);
5064                                 isCompareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
5065                                 break;
5066                         }
5067                         default:
5068                         {
5069                                 TriangleSceneSpec scene;
5070                                 scene.triangles.swap(triangles);
5071                                 isCompareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), tcu::VERIFICATIONMODE_WEAK);
5072                                 break;
5073                         }
5074                 }
5075
5076                 if (isCompareOk)
5077                         return tcu::TestStatus::pass("Pass");
5078                 else
5079                         return tcu::TestStatus::fail("Incorrect rendering");
5080         }
5081 }
5082
5083 void CullingTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
5084 {
5085         de::Random rnd(543210);
5086
5087         outData.resize(6);
5088         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
5089         {
5090                 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
5091                 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
5092                 outData[vtxNdx].z() = 0.0f;
5093                 outData[vtxNdx].w() = 1.0f;
5094         }
5095 }
5096
5097 void CullingTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
5098 {
5099         const bool cullDirection = (m_cullMode == VK_CULL_MODE_FRONT_BIT) ^ (m_frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
5100
5101         // No triangles
5102         if (m_cullMode == VK_CULL_MODE_FRONT_AND_BACK)
5103                 return;
5104
5105         switch (m_primitiveTopology)
5106         {
5107                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
5108                 {
5109                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
5110                         {
5111                                 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
5112                                 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
5113                                 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
5114
5115                                 if (triangleOrder(v0, v1, v2) != cullDirection)
5116                                 {
5117                                         TriangleSceneSpec::SceneTriangle tri;
5118                                         tri.positions[0] = v0;  tri.sharedEdge[0] = false;
5119                                         tri.positions[1] = v1;  tri.sharedEdge[1] = false;
5120                                         tri.positions[2] = v2;  tri.sharedEdge[2] = false;
5121
5122                                         outTriangles.push_back(tri);
5123                                 }
5124                         }
5125                         break;
5126                 }
5127
5128                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
5129                 {
5130                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
5131                         {
5132                                 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
5133                                 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
5134                                 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
5135
5136                                 if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
5137                                 {
5138                                         TriangleSceneSpec::SceneTriangle tri;
5139                                         tri.positions[0] = v0;  tri.sharedEdge[0] = false;
5140                                         tri.positions[1] = v1;  tri.sharedEdge[1] = false;
5141                                         tri.positions[2] = v2;  tri.sharedEdge[2] = false;
5142
5143                                         outTriangles.push_back(tri);
5144                                 }
5145                         }
5146                         break;
5147                 }
5148
5149                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
5150                 {
5151                         for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
5152                         {
5153                                 const tcu::Vec4& v0 = vertices[0];
5154                                 const tcu::Vec4& v1 = vertices[vtxNdx + 0];
5155                                 const tcu::Vec4& v2 = vertices[vtxNdx + 1];
5156
5157                                 if (triangleOrder(v0, v1, v2) != cullDirection)
5158                                 {
5159                                         TriangleSceneSpec::SceneTriangle tri;
5160                                         tri.positions[0] = v0;  tri.sharedEdge[0] = false;
5161                                         tri.positions[1] = v1;  tri.sharedEdge[1] = false;
5162                                         tri.positions[2] = v2;  tri.sharedEdge[2] = false;
5163
5164                                         outTriangles.push_back(tri);
5165                                 }
5166                         }
5167                         break;
5168                 }
5169
5170                 default:
5171                         DE_ASSERT(false);
5172         }
5173 }
5174
5175 void CullingTestInstance::extractLines (std::vector<TriangleSceneSpec::SceneTriangle>&  outTriangles,
5176                                                                                 std::vector<LineSceneSpec::SceneLine>&                  outLines) const
5177 {
5178         for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
5179         {
5180                 for (int vrtxNdx = 0; vrtxNdx < 2; ++vrtxNdx)
5181                 {
5182                         LineSceneSpec::SceneLine line;
5183                         line.positions[0] = outTriangles.at(triNdx).positions[vrtxNdx];
5184                         line.positions[1] = outTriangles.at(triNdx).positions[vrtxNdx + 1];
5185
5186                         outLines.push_back(line);
5187                 }
5188                 LineSceneSpec::SceneLine line;
5189                 line.positions[0] = outTriangles.at(triNdx).positions[2];
5190                 line.positions[1] = outTriangles.at(triNdx).positions[0];
5191                 outLines.push_back(line);
5192         }
5193 }
5194
5195 void CullingTestInstance::extractPoints (std::vector<TriangleSceneSpec::SceneTriangle>  &outTriangles,
5196                                                                                 std::vector<PointSceneSpec::ScenePoint>                 &outPoints) const
5197 {
5198         for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
5199         {
5200                 for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
5201                 {
5202                         PointSceneSpec::ScenePoint point;
5203                         point.position = outTriangles.at(triNdx).positions[vrtxNdx];
5204                         point.pointSize = 1.0f;
5205
5206                         outPoints.push_back(point);
5207                 }
5208         }
5209 }
5210
5211 bool CullingTestInstance::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
5212 {
5213         const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
5214         const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
5215         const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
5216
5217         // cross
5218         return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) > 0;
5219 }
5220
5221
5222 const VkPipelineRasterizationStateCreateInfo* CullingTestInstance::getRasterizationStateCreateInfo (void) const
5223 {
5224         static VkPipelineRasterizationStateCreateInfo   rasterizationStateCreateInfo    =
5225         {
5226                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
5227                 DE_NULL,                                                                                                                // const void*                                                          pNext;
5228                 0,                                                                                                                              // VkPipelineRasterizationStateCreateFlags      flags;
5229                 false,                                                                                                                  // VkBool32                                                                     depthClipEnable;
5230                 false,                                                                                                                  // VkBool32                                                                     rasterizerDiscardEnable;
5231                 VK_POLYGON_MODE_FILL,                                                                                   // VkFillMode                                                           fillMode;
5232                 VK_CULL_MODE_NONE,                                                                                              // VkCullMode                                                           cullMode;
5233                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
5234                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
5235                 0.0f,                                                                                                                   // float                                                                        depthBias;
5236                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
5237                 0.0f,                                                                                                                   // float                                                                        slopeScaledDepthBias;
5238                 getLineWidth(),                                                                                                 // float                                                                        lineWidth;
5239         };
5240
5241         rasterizationStateCreateInfo.lineWidth          = getLineWidth();
5242         rasterizationStateCreateInfo.cullMode           = m_cullMode;
5243         rasterizationStateCreateInfo.frontFace          = m_frontFace;
5244         rasterizationStateCreateInfo.polygonMode        = m_polygonMode;
5245
5246         return &rasterizationStateCreateInfo;
5247 }
5248
5249 class CullingTestCase : public BaseRenderingTestCase
5250 {
5251 public:
5252                                                                 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)
5253                                                                         : BaseRenderingTestCase (context, name, description, sampleCount)
5254                                                                         , m_cullMode                    (cullMode)
5255                                                                         , m_primitiveTopology   (primitiveTopology)
5256                                                                         , m_frontFace                   (frontFace)
5257                                                                         , m_polygonMode                 (polygonMode)
5258                                                                 {}
5259
5260         virtual TestInstance*           createInstance          (Context& context) const
5261                                                                 {
5262                                                                         return new CullingTestInstance(context, m_cullMode, m_primitiveTopology, m_frontFace, m_polygonMode);
5263                                                                 }
5264         void                                            checkSupport            (Context& context) const;
5265 protected:
5266         const VkCullModeFlags           m_cullMode;
5267         const VkPrimitiveTopology       m_primitiveTopology;
5268         const VkFrontFace                       m_frontFace;
5269         const VkPolygonMode                     m_polygonMode;
5270 };
5271
5272 void CullingTestCase::checkSupport (Context& context) const
5273 {
5274         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset"))
5275         {
5276                 const VkPhysicalDevicePortabilitySubsetFeaturesKHR& subsetFeatures = context.getPortabilitySubsetFeatures();
5277                 if (m_polygonMode == VK_POLYGON_MODE_POINT && !subsetFeatures.pointPolygons)
5278                         TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Point polygons are not supported by this implementation");
5279                 if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN && !subsetFeatures.triangleFans)
5280                         TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
5281         }
5282 }
5283
5284 class DiscardTestInstance : public BaseRenderingTestInstance
5285 {
5286 public:
5287                                                                                                                         DiscardTestInstance                                     (Context& context, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations)
5288                                                                                                                                 : BaseRenderingTestInstance                     (context, VK_SAMPLE_COUNT_1_BIT, RESOLUTION_POT)
5289                                                                                                                                 , m_primitiveTopology                           (primitiveTopology)
5290                                                                                                                                 , m_queryFragmentShaderInvocations      (queryFragmentShaderInvocations)
5291                                                                                                                         {}
5292
5293         virtual const VkPipelineRasterizationStateCreateInfo*   getRasterizationStateCreateInfo         (void) const;
5294         tcu::TestStatus                                                                                 iterate                                                         (void);
5295
5296 private:
5297         void                                                                                                    generateVertices                                        (std::vector<tcu::Vec4>& outData) const;
5298         void                                                                                                    extractTriangles                                        (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
5299         void                                                                                                    extractLines                                            (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const;
5300         void                                                                                                    extractPoints                                           (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const;
5301         void                                                                                                    drawPrimitivesDiscard                           (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool);
5302
5303         const VkPrimitiveTopology                                                               m_primitiveTopology;
5304         const deBool                                                                                    m_queryFragmentShaderInvocations;
5305 };
5306
5307 tcu::TestStatus DiscardTestInstance::iterate (void)
5308 {
5309         const DeviceInterface&                                                  vkd                     = m_context.getDeviceInterface();
5310         const VkDevice                                                                  vkDevice        = m_context.getDevice();
5311         deUint64                                                                                queryResult     = 0u;
5312         tcu::Surface                                                                    resultImage     (m_renderSize, m_renderSize);
5313         std::vector<tcu::Vec4>                                                  drawBuffer;
5314         std::vector<PointSceneSpec::ScenePoint>                 points;
5315         std::vector<LineSceneSpec::SceneLine>                   lines;
5316         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
5317
5318         generateVertices(drawBuffer);
5319
5320         switch (m_primitiveTopology)
5321         {
5322                 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
5323                         extractPoints(points, drawBuffer);
5324                         break;
5325
5326                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
5327                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
5328                         extractLines(lines, drawBuffer);
5329                         break;
5330
5331                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
5332                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
5333                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
5334                         extractTriangles(triangles, drawBuffer);
5335                         break;
5336
5337                 default:
5338                         DE_ASSERT(false);
5339         }
5340
5341         const VkQueryPoolCreateInfo queryPoolCreateInfo =
5342         {
5343                 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,                                               // VkStructureType                                      sType
5344                 DE_NULL,                                                                                                                // const void*                                          pNext
5345                 (VkQueryPoolCreateFlags)0,                                                                              // VkQueryPoolCreateFlags                       flags
5346                 VK_QUERY_TYPE_PIPELINE_STATISTICS ,                                                             // VkQueryType                                          queryType
5347                 1u,                                                                                                                             // deUint32                                                     entryCount
5348                 VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT,    // VkQueryPipelineStatisticFlags        pipelineStatistics
5349         };
5350
5351         if (m_queryFragmentShaderInvocations)
5352         {
5353                 Move<VkQueryPool> queryPool     = createQueryPool(vkd, vkDevice, &queryPoolCreateInfo);
5354
5355                 drawPrimitivesDiscard(resultImage, drawBuffer, m_primitiveTopology, queryPool);
5356                 vkd.getQueryPoolResults(vkDevice, *queryPool, 0u, 1u, sizeof(deUint64), &queryResult, 0u, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
5357         }
5358         else
5359                 BaseRenderingTestInstance::drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
5360
5361         // compare
5362         {
5363                 tcu::IVec4                                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
5364
5365                 const RasterizationArguments    args            =
5366                 {
5367                         0,                                                      // int  numSamples;
5368                         (int)m_subpixelBits,            // int  subpixelBits;
5369                         colorBits[0],                           // int  redBits;
5370                         colorBits[1],                           // int  greenBits;
5371                         colorBits[2]                            // int  blueBits;
5372                 };
5373
5374                 // Empty scene to compare to, primitives should be discarded before rasterization
5375                 TriangleSceneSpec                               scene;
5376
5377                 const bool                                              isCompareOk     = verifyTriangleGroupRasterization(resultImage,
5378                                                                                                                                                                            scene,
5379                                                                                                                                                                            args,
5380                                                                                                                                                                            m_context.getTestContext().getLog(),
5381                                                                                                                                                                            tcu::VERIFICATIONMODE_STRICT);
5382
5383                 if (isCompareOk)
5384                 {
5385                         if (m_queryFragmentShaderInvocations && queryResult > 0u)
5386                                 return tcu::TestStatus::fail("Fragment shader invocations occured");
5387                         else
5388                                 return tcu::TestStatus::pass("Pass");
5389                 }
5390                 else
5391                         return tcu::TestStatus::fail("Incorrect rendering");
5392         }
5393 }
5394
5395 void DiscardTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
5396 {
5397         de::Random rnd(12345);
5398
5399         outData.resize(6);
5400
5401         for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
5402         {
5403                 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
5404                 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
5405                 outData[vtxNdx].z() = 0.0f;
5406                 outData[vtxNdx].w() = 1.0f;
5407         }
5408 }
5409
5410 void DiscardTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
5411 {
5412         switch (m_primitiveTopology)
5413         {
5414                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
5415                 {
5416                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
5417                         {
5418                                 TriangleSceneSpec::SceneTriangle        tri;
5419                                 const tcu::Vec4&                                        v0      = vertices[vtxNdx + 0];
5420                                 const tcu::Vec4&                                        v1      = vertices[vtxNdx + 1];
5421                                 const tcu::Vec4&                                        v2      = vertices[vtxNdx + 2];
5422
5423                                 tri.positions[0] = v0;
5424                                 tri.positions[1] = v1;
5425                                 tri.positions[2] = v2;
5426
5427                                 outTriangles.push_back(tri);
5428                         }
5429
5430                         break;
5431                 }
5432
5433                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
5434                 {
5435                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
5436                         {
5437                                 TriangleSceneSpec::SceneTriangle        tri;
5438                                 const tcu::Vec4&                                        v0      = vertices[vtxNdx + 0];
5439                                 const tcu::Vec4&                                        v1      = vertices[vtxNdx + 1];
5440                                 const tcu::Vec4&                                        v2      = vertices[vtxNdx + 2];
5441
5442                                 tri.positions[0] = v0;
5443                                 tri.positions[1] = v1;
5444                                 tri.positions[2] = v2;
5445
5446                                 outTriangles.push_back(tri);
5447                         }
5448
5449                         break;
5450                 }
5451
5452                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
5453                 {
5454                         for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
5455                         {
5456                                 TriangleSceneSpec::SceneTriangle        tri;
5457                                 const tcu::Vec4&                                        v0      = vertices[0];
5458                                 const tcu::Vec4&                                        v1      = vertices[vtxNdx + 0];
5459                                 const tcu::Vec4&                                        v2      = vertices[vtxNdx + 1];
5460
5461                                 tri.positions[0] = v0;
5462                                 tri.positions[1] = v1;
5463                                 tri.positions[2] = v2;
5464
5465                                 outTriangles.push_back(tri);
5466                         }
5467
5468                         break;
5469                 }
5470
5471                 default:
5472                         DE_ASSERT(false);
5473         }
5474 }
5475
5476 void DiscardTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const
5477 {
5478         switch (m_primitiveTopology)
5479         {
5480                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
5481                 {
5482                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
5483                         {
5484                                 LineSceneSpec::SceneLine line;
5485
5486                                 line.positions[0] = vertices[vtxNdx + 0];
5487                                 line.positions[1] = vertices[vtxNdx + 1];
5488
5489                                 outLines.push_back(line);
5490                         }
5491
5492                         break;
5493                 }
5494
5495                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
5496                 {
5497                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
5498                         {
5499                                 LineSceneSpec::SceneLine line;
5500
5501                                 line.positions[0] = vertices[vtxNdx + 0];
5502                                 line.positions[1] = vertices[vtxNdx + 1];
5503
5504                                 outLines.push_back(line);
5505                         }
5506
5507                         break;
5508                 }
5509
5510                 default:
5511                         DE_ASSERT(false);
5512                 }
5513 }
5514
5515 void DiscardTestInstance::extractPoints (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const
5516 {
5517         for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
5518         {
5519                 for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
5520                 {
5521                         PointSceneSpec::ScenePoint point;
5522
5523                         point.position  = vertices[vrtxNdx];
5524                         point.pointSize = 1.0f;
5525
5526                         outPoints.push_back(point);
5527                 }
5528         }
5529 }
5530
5531 const VkPipelineRasterizationStateCreateInfo* DiscardTestInstance::getRasterizationStateCreateInfo (void) const
5532 {
5533         static const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
5534         {
5535                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
5536                 NULL,                                                                                                           // const void*                                                          pNext;
5537                 0,                                                                                                                      // VkPipelineRasterizationStateCreateFlags      flags;
5538                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthClipEnable;
5539                 VK_TRUE,                                                                                                        // VkBool32                                                                     rasterizerDiscardEnable;
5540                 VK_POLYGON_MODE_FILL,                                                                           // VkFillMode                                                           fillMode;
5541                 VK_CULL_MODE_NONE,                                                                                      // VkCullMode                                                           cullMode;
5542                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
5543                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable;
5544                 0.0f,                                                                                                           // float                                                                        depthBias;
5545                 0.0f,                                                                                                           // float                                                                        depthBiasClamp;
5546                 0.0f,                                                                                                           // float                                                                        slopeScaledDepthBias;
5547                 getLineWidth(),                                                                                         // float                                                                        lineWidth;
5548         };
5549
5550         return &rasterizationStateCreateInfo;
5551 }
5552
5553 void DiscardTestInstance::drawPrimitivesDiscard (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool)
5554 {
5555         const DeviceInterface&                          vkd                                     = m_context.getDeviceInterface();
5556         const VkDevice                                          vkDevice                        = m_context.getDevice();
5557         const VkPhysicalDeviceProperties        properties                      = m_context.getDeviceProperties();
5558         const VkQueue                                           queue                           = m_context.getUniversalQueue();
5559         const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
5560         Allocator&                                                      allocator                       = m_context.getDefaultAllocator();
5561
5562         const size_t                                            attributeBatchSize      = positionData.size() * sizeof(tcu::Vec4);
5563         const VkDeviceSize                                      vertexBufferOffset      = 0;
5564         de::MovePtr<Allocation>                         vertexBufferMemory;
5565         Move<VkBuffer>                                          vertexBuffer;
5566         Move<VkCommandBuffer>                           commandBuffer;
5567         Move<VkPipeline>                                        graphicsPipeline;
5568
5569         if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
5570         {
5571                 std::stringstream message;
5572                 message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
5573                 TCU_THROW(NotSupportedError, message.str().c_str());
5574         }
5575
5576         // Create Graphics Pipeline
5577         {
5578                 const VkVertexInputBindingDescription           vertexInputBindingDescription           =
5579                 {
5580                         0u,                                                                             // deUint32                                     binding;
5581                         sizeof(tcu::Vec4),                                              // deUint32                                     strideInBytes;
5582                         VK_VERTEX_INPUT_RATE_VERTEX                             // VkVertexInputStepRate        stepRate;
5583                 };
5584
5585                 const VkVertexInputAttributeDescription         vertexInputAttributeDescriptions[2]     =
5586                 {
5587                         {
5588                                 0u,                                                                     // deUint32     location;
5589                                 0u,                                                                     // deUint32     binding;
5590                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
5591                                 0u                                                                      // deUint32     offsetInBytes;
5592                         },
5593                         {
5594                                 1u,                                                                     // deUint32     location;
5595                                 0u,                                                                     // deUint32     binding;
5596                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
5597                                 (deUint32)attributeBatchSize            // deUint32     offsetInBytes;
5598                         }
5599                 };
5600
5601                 const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams                          =
5602                 {
5603                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
5604                         DE_NULL,                                                                                                        // const void*                                                          pNext;
5605                         0,                                                                                                                      // VkPipelineVertexInputStateCreateFlags        flags;
5606                         1u,                                                                                                                     // deUint32                                                                     bindingCount;
5607                         &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
5608                         2u,                                                                                                                     // deUint32                                                                     attributeCount;
5609                         vertexInputAttributeDescriptions                                                        // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
5610                 };
5611
5612                 const std::vector<VkViewport>                           viewports                                                       (1, makeViewport(tcu::UVec2(m_renderSize)));
5613                 const std::vector<VkRect2D>                                     scissors                                                        (1, makeRect2D(tcu::UVec2(m_renderSize)));
5614
5615                 const VkPipelineMultisampleStateCreateInfo      multisampleStateParams                          =
5616                 {
5617                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
5618                         DE_NULL,                                                                                                        // const void*                                                          pNext;
5619                         0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
5620                         m_sampleCount,                                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
5621                         VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
5622                         0.0f,                                                                                                           // float                                                                        minSampleShading;
5623                         DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
5624                         VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
5625                         VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
5626                 };
5627
5628                 graphicsPipeline = makeGraphicsPipeline(vkd,                                                            // const DeviceInterface&                                                       vk
5629                                                                                                 vkDevice,                                                       // const VkDevice                                                                       device
5630                                                                                                 *m_pipelineLayout,                                      // const VkPipelineLayout                                                       pipelineLayout
5631                                                                                                 *m_vertexShaderModule,                          // const VkShaderModule                                                         vertexShaderModule
5632                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                         tessellationControlShaderModule
5633                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                         tessellationEvalShaderModule
5634                                                                                                 DE_NULL,                                                        // const VkShaderModule                                                         geometryShaderModule
5635                                                                                                 *m_fragmentShaderModule,                        // const VkShaderModule                                                         fragmentShaderModule
5636                                                                                                 *m_renderPass,                                          // const VkRenderPass                                                           renderPass
5637                                                                                                 viewports,                                                      // const std::vector<VkViewport>&                                       viewports
5638                                                                                                 scissors,                                                       // const std::vector<VkRect2D>&                                         scissors
5639                                                                                                 primitiveTopology,                                      // const VkPrimitiveTopology                                            topology
5640                                                                                                 0u,                                                                     // const deUint32                                                                       subpass
5641                                                                                                 0u,                                                                     // const deUint32                                                                       patchControlPoints
5642                                                                                                 &vertexInputStateParams,                        // const VkPipelineVertexInputStateCreateInfo*          vertexInputStateCreateInfo
5643                                                                                                 getRasterizationStateCreateInfo(),      // const VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
5644                                                                                                 &multisampleStateParams,                        // const VkPipelineMultisampleStateCreateInfo*          multisampleStateCreateInfo
5645                                                                                                 DE_NULL,                                                        // const VkPipelineDepthStencilStateCreateInfo*         depthStencilStateCreateInfo,
5646                                                                                                 getColorBlendStateCreateInfo());        // const VkPipelineColorBlendStateCreateInfo*           colorBlendStateCreateInfo
5647         }
5648
5649         // Create Vertex Buffer
5650         {
5651                 const VkBufferCreateInfo                                        vertexBufferParams              =
5652                 {
5653                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
5654                         DE_NULL,                                                                // const void*                  pNext;
5655                         0u,                                                                             // VkBufferCreateFlags  flags;
5656                         attributeBatchSize * 2,                                 // VkDeviceSize                 size;
5657                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,              // VkBufferUsageFlags   usage;
5658                         VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
5659                         1u,                                                                             // deUint32                             queueFamilyCount;
5660                         &queueFamilyIndex                                               // const deUint32*              pQueueFamilyIndices;
5661                 };
5662
5663                 const std::vector<tcu::Vec4>                            colorData                               (positionData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
5664
5665                 vertexBuffer            = createBuffer(vkd, vkDevice, &vertexBufferParams);
5666                 vertexBufferMemory      = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
5667
5668                 VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
5669
5670                 // Load vertices into vertex buffer
5671                 deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
5672                 deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize);
5673                 flushAlloc(vkd, vkDevice, *vertexBufferMemory);
5674         }
5675
5676         // Create Command Buffer
5677         commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
5678
5679         // Begin Command Buffer
5680         beginCommandBuffer(vkd, *commandBuffer);
5681
5682         addImageTransitionBarrier(*commandBuffer,                                                                       // VkCommandBuffer                      commandBuffer
5683                                                           *m_image,                                                                                     // VkImage                                      image
5684                                                           VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                            // VkPipelineStageFlags         srcStageMask
5685                                                           VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                           // VkPipelineStageFlags         dstStageMask
5686                                                           0,                                                                                            // VkAccessFlags                        srcAccessMask
5687                                                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                         // VkAccessFlags                        dstAccessMask
5688                                                           VK_IMAGE_LAYOUT_UNDEFINED,                                            // VkImageLayout                        oldLayout;
5689                                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);            // VkImageLayout                        newLayout;
5690
5691         if (m_multisampling)
5692         {
5693                 addImageTransitionBarrier(*commandBuffer,                                                               // VkCommandBuffer                      commandBuffer
5694                                                                   *m_resolvedImage,                                                             // VkImage                                      image
5695                                                                   VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                    // VkPipelineStageFlags         srcStageMask
5696                                                                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,                   // VkPipelineStageFlags         dstStageMask
5697                                                                   0,                                                                                    // VkAccessFlags                        srcAccessMask
5698                                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                 // VkAccessFlags                        dstAccessMask
5699                                                                   VK_IMAGE_LAYOUT_UNDEFINED,                                    // VkImageLayout                        oldLayout;
5700                                                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);    // VkImageLayout                        newLayout;
5701         }
5702
5703         // Reset query pool
5704         vkd.cmdResetQueryPool(*commandBuffer, *queryPool, 0u, 1u);
5705
5706         // Begin render pass and start query
5707         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));
5708         vkd.cmdBeginQuery(*commandBuffer, *queryPool, 0u, (VkQueryControlFlags)0u);
5709         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
5710         vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
5711         vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
5712         vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
5713         endRenderPass(vkd, *commandBuffer);
5714         vkd.cmdEndQuery(*commandBuffer, *queryPool, 0u);
5715
5716         // Copy Image
5717         copyImageToBuffer(vkd, *commandBuffer, m_multisampling ? *m_resolvedImage : *m_image, *m_resultBuffer, tcu::IVec2(m_renderSize, m_renderSize));
5718
5719         endCommandBuffer(vkd, *commandBuffer);
5720
5721         // Set Point Size
5722         {
5723                 float pointSize = getPointSize();
5724
5725                 deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
5726                 flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
5727         }
5728
5729         // Submit
5730         submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
5731
5732         invalidateAlloc(vkd, vkDevice, *m_resultBufferMemory);
5733         tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
5734 }
5735
5736 class DiscardTestCase : public BaseRenderingTestCase
5737 {
5738 public:
5739                                                                 DiscardTestCase                                 (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
5740                                                                         : BaseRenderingTestCase                         (context, name, description, sampleCount)
5741                                                                         , m_primitiveTopology                           (primitiveTopology)
5742                                                                         , m_queryFragmentShaderInvocations      (queryFragmentShaderInvocations)
5743                                                                 {}
5744
5745         virtual TestInstance*           createInstance          (Context& context) const
5746                                                                 {
5747                                                                         return new DiscardTestInstance (context, m_primitiveTopology, m_queryFragmentShaderInvocations);
5748                                                                 }
5749
5750         virtual void                            checkSupport            (Context& context) const
5751                                                                 {
5752                                                                         if (m_queryFragmentShaderInvocations)
5753                                                                                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_PIPELINE_STATISTICS_QUERY);
5754
5755                                                                         if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
5756                                                                                         context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
5757                                                                                         !context.getPortabilitySubsetFeatures().triangleFans)
5758                                                                                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
5759                                                                 }
5760
5761 protected:
5762         const VkPrimitiveTopology       m_primitiveTopology;
5763         const deBool                            m_queryFragmentShaderInvocations;
5764 };
5765
5766 class TriangleInterpolationTestInstance : public BaseRenderingTestInstance
5767 {
5768 public:
5769
5770                                                                 TriangleInterpolationTestInstance       (Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount)
5771                                                                         : BaseRenderingTestInstance     (context, sampleCount, RESOLUTION_POT)
5772                                                                         , m_primitiveTopology           (primitiveTopology)
5773                                                                         , m_projective                          ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
5774                                                                         , m_iterationCount                      (3)
5775                                                                         , m_iteration                           (0)
5776                                                                         , m_allIterationsPassed         (true)
5777                                                                         , m_flatshade                           ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
5778                                                                 {}
5779
5780         tcu::TestStatus                         iterate                                                         (void);
5781
5782
5783 private:
5784         void                                            generateVertices                                        (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
5785         void                                            extractTriangles                                        (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
5786
5787
5788         VkPrimitiveTopology                     m_primitiveTopology;
5789         const bool                                      m_projective;
5790         const int                                       m_iterationCount;
5791         int                                                     m_iteration;
5792         bool                                            m_allIterationsPassed;
5793         const deBool                            m_flatshade;
5794 };
5795
5796 tcu::TestStatus TriangleInterpolationTestInstance::iterate (void)
5797 {
5798         const std::string                                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
5799         const tcu::ScopedLogSection                                             section                                 (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
5800         tcu::Surface                                                                    resultImage                             (m_renderSize, m_renderSize);
5801         std::vector<tcu::Vec4>                                                  drawBuffer;
5802         std::vector<tcu::Vec4>                                                  colorBuffer;
5803         std::vector<TriangleSceneSpec::SceneTriangle>   triangles;
5804
5805         // generate scene
5806         generateVertices(m_iteration, drawBuffer, colorBuffer);
5807         extractTriangles(triangles, drawBuffer, colorBuffer);
5808
5809         // log
5810         {
5811                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
5812                 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
5813                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
5814         }
5815
5816         // draw image
5817         drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
5818
5819         // compare
5820         {
5821                 RasterizationArguments  args;
5822                 TriangleSceneSpec               scene;
5823                 tcu::IVec4                              colorBits       = tcu::getTextureFormatBitDepth(getTextureFormat());
5824
5825                 args.numSamples         = m_multisampling ? 1 : 0;
5826                 args.subpixelBits       = m_subpixelBits;
5827                 args.redBits            = colorBits[0];
5828                 args.greenBits          = colorBits[1];
5829                 args.blueBits           = colorBits[2];
5830
5831                 scene.triangles.swap(triangles);
5832
5833                 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
5834                         m_allIterationsPassed = false;
5835         }
5836
5837         // result
5838         if (++m_iteration == m_iterationCount)
5839         {
5840                 if (m_allIterationsPassed)
5841                         return tcu::TestStatus::pass("Pass");
5842                 else
5843                         return tcu::TestStatus::fail("Found invalid pixel values");
5844         }
5845         else
5846                 return tcu::TestStatus::incomplete();
5847 }
5848
5849 void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
5850 {
5851         // use only red, green and blue
5852         const tcu::Vec4 colors[] =
5853         {
5854                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
5855                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
5856                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
5857         };
5858
5859         de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
5860
5861         outVertices.resize(6);
5862         outColors.resize(6);
5863
5864         for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
5865         {
5866                 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
5867                 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
5868                 outVertices[vtxNdx].z() = 0.0f;
5869
5870                 if (!m_projective)
5871                         outVertices[vtxNdx].w() = 1.0f;
5872                 else
5873                 {
5874                         const float w = rnd.getFloat(0.2f, 4.0f);
5875
5876                         outVertices[vtxNdx].x() *= w;
5877                         outVertices[vtxNdx].y() *= w;
5878                         outVertices[vtxNdx].z() *= w;
5879                         outVertices[vtxNdx].w() = w;
5880                 }
5881
5882                 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
5883         }
5884 }
5885
5886 void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
5887 {
5888         switch (m_primitiveTopology)
5889         {
5890                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
5891                 {
5892                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
5893                         {
5894                                 TriangleSceneSpec::SceneTriangle tri;
5895                                 tri.positions[0]        = vertices[vtxNdx + 0];
5896                                 tri.positions[1]        = vertices[vtxNdx + 1];
5897                                 tri.positions[2]        = vertices[vtxNdx + 2];
5898                                 tri.sharedEdge[0]       = false;
5899                                 tri.sharedEdge[1]       = false;
5900                                 tri.sharedEdge[2]       = false;
5901
5902                                 if (m_flatshade)
5903                                 {
5904                                         tri.colors[0] = colors[vtxNdx];
5905                                         tri.colors[1] = colors[vtxNdx];
5906                                         tri.colors[2] = colors[vtxNdx];
5907                                 }
5908                                 else
5909                                 {
5910                                         tri.colors[0] = colors[vtxNdx + 0];
5911                                         tri.colors[1] = colors[vtxNdx + 1];
5912                                         tri.colors[2] = colors[vtxNdx + 2];
5913                                 }
5914
5915                                 outTriangles.push_back(tri);
5916                         }
5917                         break;
5918                 }
5919
5920                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
5921                 {
5922                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
5923                         {
5924                                 TriangleSceneSpec::SceneTriangle tri;
5925                                 tri.positions[0]        = vertices[vtxNdx + 0];
5926                                 tri.positions[1]        = vertices[vtxNdx + 1];
5927                                 tri.positions[2]        = vertices[vtxNdx + 2];
5928                                 tri.sharedEdge[0]       = false;
5929                                 tri.sharedEdge[1]       = false;
5930                                 tri.sharedEdge[2]       = false;
5931
5932                                 if (m_flatshade)
5933                                 {
5934                                         tri.colors[0] = colors[vtxNdx];
5935                                         tri.colors[1] = colors[vtxNdx];
5936                                         tri.colors[2] = colors[vtxNdx];
5937                                 }
5938                                 else
5939                                 {
5940                                         tri.colors[0] = colors[vtxNdx + 0];
5941                                         tri.colors[1] = colors[vtxNdx + 1];
5942                                         tri.colors[2] = colors[vtxNdx + 2];
5943                                 }
5944
5945                                 outTriangles.push_back(tri);
5946                         }
5947                         break;
5948                 }
5949
5950                 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
5951                 {
5952                         for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
5953                         {
5954                                 TriangleSceneSpec::SceneTriangle tri;
5955                                 tri.positions[0]        = vertices[0];
5956                                 tri.positions[1]        = vertices[vtxNdx + 0];
5957                                 tri.positions[2]        = vertices[vtxNdx + 1];
5958                                 tri.sharedEdge[0]       = false;
5959                                 tri.sharedEdge[1]       = false;
5960                                 tri.sharedEdge[2]       = false;
5961
5962                                 if (m_flatshade)
5963                                 {
5964                                         tri.colors[0] = colors[vtxNdx];
5965                                         tri.colors[1] = colors[vtxNdx];
5966                                         tri.colors[2] = colors[vtxNdx];
5967                                 }
5968                                 else
5969                                 {
5970                                         tri.colors[0] = colors[0];
5971                                         tri.colors[1] = colors[vtxNdx + 0];
5972                                         tri.colors[2] = colors[vtxNdx + 1];
5973                                 }
5974
5975                                 outTriangles.push_back(tri);
5976                         }
5977                         break;
5978                 }
5979
5980                 default:
5981                         DE_ASSERT(false);
5982         }
5983 }
5984
5985 class TriangleInterpolationTestCase : public BaseRenderingTestCase
5986 {
5987 public:
5988                                                                 TriangleInterpolationTestCase   (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
5989                                                                         : BaseRenderingTestCase         (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
5990                                                                         , m_primitiveTopology           (primitiveTopology)
5991                                                                         , m_flags                                       (flags)
5992                                                                 {}
5993
5994         virtual TestInstance*           createInstance                                  (Context& context) const
5995                                                                 {
5996                                                                         return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount);
5997                                                                 }
5998
5999         virtual void                            checkSupport            (Context& context) const
6000                                                                 {
6001                                                                         if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
6002                                                                                 context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
6003                                                                                 !context.getPortabilitySubsetFeatures().triangleFans)
6004                                                                         {
6005                                                                                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
6006                                                                         }
6007                                                                 }
6008 protected:
6009         const VkPrimitiveTopology       m_primitiveTopology;
6010         const int                                       m_flags;
6011 };
6012
6013 class LineInterpolationTestInstance : public BaseRenderingTestInstance
6014 {
6015 public:
6016                                                         LineInterpolationTestInstance   (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount);
6017
6018         virtual tcu::TestStatus iterate                                                 (void);
6019
6020 private:
6021         void                                    generateVertices                                (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
6022         void                                    extractLines                                    (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
6023         virtual float                   getLineWidth                                    (void) const;
6024
6025         VkPrimitiveTopology             m_primitiveTopology;
6026         const bool                              m_projective;
6027         const int                               m_iterationCount;
6028         const PrimitiveWideness m_primitiveWideness;
6029
6030         int                                             m_iteration;
6031         bool                                    m_allIterationsPassed;
6032         float                                   m_maxLineWidth;
6033         std::vector<float>              m_lineWidths;
6034         bool                                    m_flatshade;
6035         PrimitiveStrictness             m_strictness;
6036 };
6037
6038 LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount)
6039         : BaseRenderingTestInstance                     (context, sampleCount)
6040         , m_primitiveTopology                           (primitiveTopology)
6041         , m_projective                                          ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
6042         , m_iterationCount                                      (3)
6043         , m_primitiveWideness                           (wideness)
6044         , m_iteration                                           (0)
6045         , m_allIterationsPassed                         (true)
6046         , m_maxLineWidth                                        (1.0f)
6047         , m_flatshade                                           ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
6048         , m_strictness                                          (strictness)
6049 {
6050         DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
6051
6052         // create line widths
6053         if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
6054         {
6055                 m_lineWidths.resize(m_iterationCount, 1.0f);
6056         }
6057         else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
6058         {
6059                 const float*    range = context.getDeviceProperties().limits.lineWidthRange;
6060
6061                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
6062
6063                 DE_ASSERT(range[1] > 1.0f);
6064
6065                 // set hand picked sizes
6066                 m_lineWidths.push_back(5.0f);
6067                 m_lineWidths.push_back(10.0f);
6068                 m_lineWidths.push_back(range[1]);
6069                 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
6070
6071                 m_maxLineWidth = range[1];
6072         }
6073         else
6074                 DE_ASSERT(false);
6075 }
6076
6077 tcu::TestStatus LineInterpolationTestInstance::iterate (void)
6078 {
6079         const std::string                                               iterationDescription    = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
6080         const tcu::ScopedLogSection                             section                                 (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
6081         const float                                                             lineWidth                               = getLineWidth();
6082         tcu::Surface                                                    resultImage                             (m_renderSize, m_renderSize);
6083         std::vector<tcu::Vec4>                                  drawBuffer;
6084         std::vector<tcu::Vec4>                                  colorBuffer;
6085         std::vector<LineSceneSpec::SceneLine>   lines;
6086
6087         // supported?
6088         if (lineWidth <= m_maxLineWidth)
6089         {
6090                 // generate scene
6091                 generateVertices(m_iteration, drawBuffer, colorBuffer);
6092                 extractLines(lines, drawBuffer, colorBuffer);
6093
6094                 // log
6095                 {
6096                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
6097                         for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
6098                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
6099                 }
6100
6101                 // draw image
6102                 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
6103
6104                 // compare
6105                 {
6106                         RasterizationArguments  args;
6107                         LineSceneSpec                   scene;
6108
6109                         tcu::IVec4                              colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
6110
6111                         args.numSamples         = m_multisampling ? 1 : 0;
6112                         args.subpixelBits       = m_subpixelBits;
6113                         args.redBits            = colorBits[0];
6114                         args.greenBits          = colorBits[1];
6115                         args.blueBits           = colorBits[2];
6116
6117                         scene.lines.swap(lines);
6118                         scene.lineWidth = getLineWidth();
6119
6120                         switch (m_strictness)
6121                         {
6122                                 case PRIMITIVESTRICTNESS_STRICT:
6123                                 {
6124                                         if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog(), true))
6125                                                 m_allIterationsPassed = false;
6126
6127                                         break;
6128                                 }
6129
6130                                 case PRIMITIVESTRICTNESS_NONSTRICT:
6131                                 case PRIMITIVESTRICTNESS_IGNORE:
6132                                 {
6133                                         if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog(), false, true))
6134                                                 m_allIterationsPassed = false;
6135
6136                                         break;
6137                                 }
6138
6139                                 default:
6140                                         TCU_THROW(InternalError, "Not implemented");
6141                         }
6142                 }
6143         }
6144         else
6145                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
6146
6147         // result
6148         if (++m_iteration == m_iterationCount)
6149         {
6150                 if (m_allIterationsPassed)
6151                         return tcu::TestStatus::pass("Pass");
6152                 else
6153                         return tcu::TestStatus::fail("Incorrect rasterization");
6154         }
6155         else
6156                 return tcu::TestStatus::incomplete();
6157 }
6158
6159 void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
6160 {
6161         // use only red, green and blue
6162         const tcu::Vec4 colors[] =
6163         {
6164                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
6165                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
6166                 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
6167         };
6168
6169         de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
6170
6171         outVertices.resize(6);
6172         outColors.resize(6);
6173
6174         for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
6175         {
6176                 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
6177                 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
6178                 outVertices[vtxNdx].z() = 0.0f;
6179
6180                 if (!m_projective)
6181                         outVertices[vtxNdx].w() = 1.0f;
6182                 else
6183                 {
6184                         const float w = rnd.getFloat(0.2f, 4.0f);
6185
6186                         outVertices[vtxNdx].x() *= w;
6187                         outVertices[vtxNdx].y() *= w;
6188                         outVertices[vtxNdx].z() *= w;
6189                         outVertices[vtxNdx].w() = w;
6190                 }
6191
6192                 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
6193         }
6194 }
6195
6196 void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
6197 {
6198         switch (m_primitiveTopology)
6199         {
6200                 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
6201                 {
6202                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
6203                         {
6204                                 LineSceneSpec::SceneLine line;
6205                                 line.positions[0] = vertices[vtxNdx + 0];
6206                                 line.positions[1] = vertices[vtxNdx + 1];
6207
6208                                 if (m_flatshade)
6209                                 {
6210                                         line.colors[0] = colors[vtxNdx];
6211                                         line.colors[1] = colors[vtxNdx];
6212                                 }
6213                                 else
6214                                 {
6215                                         line.colors[0] = colors[vtxNdx + 0];
6216                                         line.colors[1] = colors[vtxNdx + 1];
6217                                 }
6218
6219                                 outLines.push_back(line);
6220                         }
6221                         break;
6222                 }
6223
6224                 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
6225                 {
6226                         for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
6227                         {
6228                                 LineSceneSpec::SceneLine line;
6229                                 line.positions[0] = vertices[vtxNdx + 0];
6230                                 line.positions[1] = vertices[vtxNdx + 1];
6231
6232                                 if (m_flatshade)
6233                                 {
6234                                         line.colors[0] = colors[vtxNdx];
6235                                         line.colors[1] = colors[vtxNdx];
6236                                 }
6237                                 else
6238                                 {
6239                                         line.colors[0] = colors[vtxNdx + 0];
6240                                         line.colors[1] = colors[vtxNdx + 1];
6241                                 }
6242
6243                                 outLines.push_back(line);
6244                         }
6245                         break;
6246                 }
6247
6248                 default:
6249                         DE_ASSERT(false);
6250         }
6251 }
6252
6253 float LineInterpolationTestInstance::getLineWidth (void) const
6254 {
6255         return m_lineWidths[m_iteration];
6256 }
6257
6258 class LineInterpolationTestCase : public BaseRenderingTestCase
6259 {
6260 public:
6261                                                                 LineInterpolationTestCase               (tcu::TestContext&              context,
6262                                                                                                                                  const std::string&             name,
6263                                                                                                                                  const std::string&             description,
6264                                                                                                                                  VkPrimitiveTopology    primitiveTopology,
6265                                                                                                                                  int                                    flags,
6266                                                                                                                                  PrimitiveWideness              wideness,
6267                                                                                                                                  PrimitiveStrictness    strictness,
6268                                                                                                                                  VkSampleCountFlagBits  sampleCount = VK_SAMPLE_COUNT_1_BIT)
6269                                                                         : BaseRenderingTestCase         (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
6270                                                                         , m_primitiveTopology           (primitiveTopology)
6271                                                                         , m_flags                                       (flags)
6272                                                                         , m_wideness                            (wideness)
6273                                                                         , m_strictness                          (strictness)
6274                                                                 {}
6275
6276         virtual TestInstance*           createInstance                                  (Context& context) const
6277                                                                 {
6278                                                                         return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_strictness, m_sampleCount);
6279                                                                 }
6280
6281         virtual void                            checkSupport            (Context& context) const
6282                                                                 {
6283                                                                         if (m_strictness == PRIMITIVESTRICTNESS_STRICT &&
6284                                                                                 !context.getDeviceProperties().limits.strictLines)
6285                                                                                 TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
6286
6287                                                                         if (m_wideness == PRIMITIVEWIDENESS_WIDE)
6288                                                                                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
6289                                                                 }
6290 protected:
6291         const VkPrimitiveTopology       m_primitiveTopology;
6292         const int                                       m_flags;
6293         const PrimitiveWideness         m_wideness;
6294         const PrimitiveStrictness       m_strictness;
6295 };
6296
6297 class StrideZeroCase : public vkt::TestCase
6298 {
6299 public:
6300         struct Params
6301         {
6302                 std::vector<tcu::Vec2>  bufferData;
6303                 deUint32                                drawVertexCount;
6304         };
6305
6306                                                         StrideZeroCase          (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const Params& params)
6307                                                                 : vkt::TestCase (testCtx, name, description)
6308                                                                 , m_params              (params)
6309                                                                 {}
6310
6311         virtual                                 ~StrideZeroCase         (void) {}
6312
6313         virtual void                    initPrograms            (vk::SourceCollections& programCollection) const;
6314         virtual TestInstance*   createInstance          (Context& context) const;
6315         virtual void                    checkSupport            (Context& context) const;
6316
6317         static constexpr vk::VkFormat                           kColorFormat    = vk::VK_FORMAT_R8G8B8A8_UNORM;
6318         static constexpr vk::VkFormatFeatureFlags       kColorFeatures  = (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
6319         static constexpr vk::VkImageUsageFlags          kColorUsage             = (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
6320
6321         //      (-1,-1)
6322         //              +-----+-----+
6323         //              |     |     |
6324         //              |  a  |  b  |   a = (-0.5, -0.5)
6325         //              |     |     |   b = ( 0.5, -0.5)
6326         //              +-----------+   c = (-0.5,  0.5)
6327         //              |     |     |   d = ( 0.5,  0.5)
6328         //              |  c  |  d  |
6329         //              |     |     |
6330         //              +-----+-----+
6331         //                                      (1,1)
6332         static constexpr deUint32                                       kImageDim               = 2u;
6333         static const float                                                      kCornerDelta;   // 0.5f;
6334
6335         static const tcu::Vec4                                          kClearColor;
6336         static const tcu::Vec4                                          kDrawColor;
6337
6338 private:
6339         Params m_params;
6340 };
6341
6342 const float             StrideZeroCase::kCornerDelta    = 0.5f;
6343 const tcu::Vec4 StrideZeroCase::kClearColor             (0.0f, 0.0f, 0.0f, 1.0f);
6344 const tcu::Vec4 StrideZeroCase::kDrawColor              (1.0f, 1.0f, 1.0f, 1.0f);
6345
6346 class StrideZeroInstance : public vkt::TestInstance
6347 {
6348 public:
6349                                                                 StrideZeroInstance      (Context& context, const StrideZeroCase::Params& params)
6350                                                                         : vkt::TestInstance     (context)
6351                                                                         , m_params                      (params)
6352                                                                         {}
6353
6354         virtual                                         ~StrideZeroInstance     (void) {}
6355
6356         virtual tcu::TestStatus         iterate                         (void);
6357
6358 private:
6359         StrideZeroCase::Params m_params;
6360 };
6361
6362 void StrideZeroCase::initPrograms (vk::SourceCollections& programCollection) const
6363 {
6364         std::ostringstream vert;
6365         std::ostringstream frag;
6366
6367         std::ostringstream drawColor;
6368         drawColor
6369                 << std::setprecision(2) << std::fixed
6370                 << "vec4(" << kDrawColor.x() << ", " << kDrawColor.y() << ", " << kDrawColor.z() << ", " << kDrawColor.w() << ")";
6371
6372         vert
6373                 << "#version 450\n"
6374                 << "layout (location=0) in vec2 inPos;\n"
6375                 << "void main() {\n"
6376                 << "    gl_Position = vec4(inPos, 0.0, 1.0);\n"
6377                 << "    gl_PointSize = 1.0;\n"
6378                 << "}\n"
6379                 ;
6380
6381         frag
6382                 << "#version 450\n"
6383                 << "layout (location=0) out vec4 outColor;\n"
6384                 << "void main() {\n"
6385                 << "    outColor = " << drawColor.str() << ";\n"
6386                 << "}\n"
6387                 ;
6388
6389         programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
6390         programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
6391 }
6392
6393 TestInstance* StrideZeroCase::createInstance (Context& context) const
6394 {
6395         return new StrideZeroInstance(context, m_params);
6396 }
6397
6398 void StrideZeroCase::checkSupport (Context& context) const
6399 {
6400         const auto properties = vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), kColorFormat);
6401         if ((properties.optimalTilingFeatures & kColorFeatures) != kColorFeatures)
6402                 TCU_THROW(NotSupportedError, "Required image format not supported");
6403 }
6404
6405 // Creates a vertex buffer with the given data but uses zero as the binding stride.
6406 // Then, tries to draw the requested number of points. Only the first point should ever be used.
6407 tcu::TestStatus StrideZeroInstance::iterate (void)
6408 {
6409         const auto&             vkd                     = m_context.getDeviceInterface();
6410         const auto              device          = m_context.getDevice();
6411         auto&                   alloc           = m_context.getDefaultAllocator();
6412         const auto              queue           = m_context.getUniversalQueue();
6413         const auto              queueIndex      = m_context.getUniversalQueueFamilyIndex();
6414         constexpr auto  kImageDim       = StrideZeroCase::kImageDim;
6415         const auto              colorExtent     = vk::makeExtent3D(kImageDim, kImageDim, 1u);
6416
6417         // Prepare vertex buffer.
6418         const auto                                      vertexBufferSize        = static_cast<vk::VkDeviceSize>(m_params.bufferData.size() * sizeof(decltype(m_params.bufferData)::value_type));
6419         const auto                                      vertexBufferInfo        = vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
6420         const vk::BufferWithMemory      vertexBuffer(           vkd, device, alloc, vertexBufferInfo, vk::MemoryRequirement::HostVisible);
6421         auto&                                           vertexBufferAlloc       = vertexBuffer.getAllocation();
6422         const vk::VkDeviceSize          vertexBufferOffset      = 0ull;
6423         deMemcpy(vertexBufferAlloc.getHostPtr(), m_params.bufferData.data(), static_cast<size_t>(vertexBufferSize));
6424         flushAlloc(vkd, device, vertexBufferAlloc);
6425
6426         // Prepare render image.
6427         const vk::VkImageCreateInfo colorAttachmentInfo =
6428         {
6429                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,        //      VkStructureType                 sType;
6430                 nullptr,                                                                        //      const void*                             pNext;
6431                 0u,                                                                                     //      VkImageCreateFlags              flags;
6432                 vk::VK_IMAGE_TYPE_2D,                                           //      VkImageType                             imageType;
6433                 StrideZeroCase::kColorFormat,                           //      VkFormat                                format;
6434                 colorExtent,                                                            //      VkExtent3D                              extent;
6435                 1u,                                                                                     //      deUint32                                mipLevels;
6436                 1u,                                                                                     //      deUint32                                arrayLayers;
6437                 vk::VK_SAMPLE_COUNT_1_BIT,                                      //      VkSampleCountFlagBits   samples;
6438                 vk::VK_IMAGE_TILING_OPTIMAL,                            //      VkImageTiling                   tiling;
6439                 StrideZeroCase::kColorUsage,                            //      VkImageUsageFlags               usage;
6440                 vk::VK_SHARING_MODE_EXCLUSIVE,                          //      VkSharingMode                   sharingMode;
6441                 1u,                                                                                     //      deUint32                                queueFamilyIndexCount;
6442                 &queueIndex,                                                            //      const deUint32*                 pQueueFamilyIndices;
6443                 vk::VK_IMAGE_LAYOUT_UNDEFINED,                          //      VkImageLayout                   initialLayout;
6444         };
6445         const vk::ImageWithMemory colorAttachment(vkd, device, alloc, colorAttachmentInfo, vk::MemoryRequirement::Any);
6446
6447         const auto colorSubresourceRange        = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
6448         const auto colorAttachmentView          = vk::makeImageView(vkd, device, colorAttachment.get(), vk::VK_IMAGE_VIEW_TYPE_2D, StrideZeroCase::kColorFormat, colorSubresourceRange);
6449
6450         const vk::VkVertexInputBindingDescription vertexBinding =
6451         {
6452                 0u,                                                                     //      deUint32                        binding;
6453                 0u,                                                                     //      deUint32                        stride;         [IMPORTANT]
6454                 vk::VK_VERTEX_INPUT_RATE_VERTEX,        //      VkVertexInputRate       inputRate;
6455         };
6456
6457         const vk::VkVertexInputAttributeDescription vertexAttribute =
6458         {
6459                 0u,                                                             //      deUint32        location;
6460                 0u,                                                             //      deUint32        binding;
6461                 vk::VK_FORMAT_R32G32_SFLOAT,    //      VkFormat        format;
6462                 0u,                                                             //      deUint32        offset;
6463         };
6464
6465         const vk::VkPipelineVertexInputStateCreateInfo vertexInput =
6466         {
6467                 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,  //      VkStructureType                                                         sType;
6468                 nullptr,                                                                                                                //      const void*                                                                     pNext;
6469                 0u,                                                                                                                             //      VkPipelineVertexInputStateCreateFlags           flags;
6470                 1u,                                                                                                                             //      deUint32                                                                        vertexBindingDescriptionCount;
6471                 &vertexBinding,                                                                                                 //      const VkVertexInputBindingDescription*          pVertexBindingDescriptions;
6472                 1u,                                                                                                                             //      deUint32                                                                        vertexAttributeDescriptionCount;
6473                 &vertexAttribute,                                                                                               //      const VkVertexInputAttributeDescription*        pVertexAttributeDescriptions;
6474         };
6475
6476         const auto renderArea           = vk::makeRect2D(kImageDim, kImageDim);
6477         const auto viewports            = std::vector<vk::VkViewport>(1, vk::makeViewport(kImageDim, kImageDim));
6478         const auto scissors                     = std::vector<vk::VkRect2D>(1, renderArea);
6479         const auto pipelineLayout       = vk::makePipelineLayout(vkd, device);
6480         const auto vertexShader         = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
6481         const auto fragmentShader       = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
6482         const auto renderPass           = vk::makeRenderPass(vkd, device, StrideZeroCase::kColorFormat);
6483         const auto graphicsPipeline     = vk::makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
6484                 vertexShader.get(), DE_NULL, DE_NULL, DE_NULL, fragmentShader.get(),                                    // Shaders.
6485                 renderPass.get(), viewports, scissors, vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, 0u,    // Render pass, viewports, scissors, topology.
6486                 &vertexInput);                                                                                                                                                  // Vertex input state.
6487         const auto framebuffer          = vk::makeFramebuffer(vkd, device, renderPass.get(), colorAttachmentView.get(), kImageDim, kImageDim);
6488
6489         const auto cmdPool              = vk::makeCommandPool(vkd, device, queueIndex);
6490         const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
6491         const auto cmdBuffer    = cmdBufferPtr.get();
6492
6493         // Buffer used to verify results.
6494         const auto                                      tcuFormat                       = vk::mapVkFormat(StrideZeroCase::kColorFormat);
6495         const auto                                      colorBufferSize         = static_cast<vk::VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * kImageDim * kImageDim;
6496         const auto                                      colorBufferInfo         = vk::makeBufferCreateInfo(colorBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
6497         const vk::BufferWithMemory      colorBuffer                     (vkd, device, alloc, colorBufferInfo, vk::MemoryRequirement::HostVisible);
6498         auto&                                           colorBufferAlloc        = colorBuffer.getAllocation();
6499         void*                                           colorBufferPtr          = colorBufferAlloc.getHostPtr();
6500         const auto                                      colorLayers                     = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
6501         const auto                                      copyRegion                      = vk::makeBufferImageCopy(colorExtent, colorLayers);
6502
6503         // Barriers from attachment to buffer and buffer to host.
6504         const auto colorAttachmentBarrier       = vk::makeImageMemoryBarrier    (vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorAttachment.get(), colorSubresourceRange);
6505         const auto colorBufferBarrier           = vk::makeBufferMemoryBarrier   (vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, colorBuffer.get(), 0ull, colorBufferSize);
6506
6507         vk::beginCommandBuffer(vkd, cmdBuffer);
6508         vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea, StrideZeroCase::kClearColor);
6509         vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
6510         vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
6511         vkd.cmdDraw(cmdBuffer, m_params.drawVertexCount, 1u, 0u, 0u);
6512         vk::endRenderPass(vkd, cmdBuffer);
6513         vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorAttachmentBarrier);
6514         vkd.cmdCopyImageToBuffer(cmdBuffer, colorAttachment.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), 1u, &copyRegion);
6515         vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &colorBufferBarrier, 0u, nullptr);
6516         vk::endCommandBuffer(vkd, cmdBuffer);
6517
6518         vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
6519
6520         // Invalidate color buffer alloc.
6521         vk::invalidateAlloc(vkd, device, colorBufferAlloc);
6522
6523         // Check buffer.
6524         const int                                                       imageDimI       = static_cast<int>(kImageDim);
6525         const tcu::ConstPixelBufferAccess       colorPixels     (tcuFormat, imageDimI, imageDimI, 1, colorBufferPtr);
6526         tcu::TestStatus                                         testStatus      = tcu::TestStatus::pass("Pass");
6527         auto&                                                           log                     = m_context.getTestContext().getLog();
6528
6529         for (int x = 0; x < imageDimI; ++x)
6530         for (int y = 0; y < imageDimI; ++y)
6531         {
6532                 // Only the top-left corner should have draw data.
6533                 const auto expectedColor        = ((x == 0 && y == 0) ? StrideZeroCase::kDrawColor : StrideZeroCase::kClearColor);
6534                 const auto imageColor           = colorPixels.getPixel(x, y);
6535
6536                 if (expectedColor != imageColor)
6537                 {
6538                         log
6539                                 << tcu::TestLog::Message
6540                                 << "Unexpected color found in pixel (" << x << ", " << y << "): "
6541                                 << "expected (" << expectedColor.x() << ", " << expectedColor.y() << ", " << expectedColor.z() << ", " << expectedColor.w() << ") "
6542                                 << "and found (" << imageColor.x() << ", " << imageColor.y() << ", " << imageColor.z() << ", " << imageColor.w() << ")"
6543                                 << tcu::TestLog::EndMessage;
6544
6545                         testStatus = tcu::TestStatus::fail("Failed; Check log for details");
6546                 }
6547         }
6548
6549         return testStatus;
6550 }
6551
6552 void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
6553 {
6554         tcu::TestContext&       testCtx         =       rasterizationTests->getTestContext();
6555
6556         // .primitives
6557         {
6558                 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives", "Primitive rasterization");
6559
6560                 rasterizationTests->addChild(primitives);
6561
6562                 tcu::TestCaseGroup* const nostippleTests = new tcu::TestCaseGroup(testCtx, "no_stipple", "No stipple");
6563                 tcu::TestCaseGroup* const stippleStaticTests = new tcu::TestCaseGroup(testCtx, "static_stipple", "Line stipple static");
6564                 tcu::TestCaseGroup* const stippleDynamicTests = new tcu::TestCaseGroup(testCtx, "dynamic_stipple", "Line stipple dynamic");
6565                 tcu::TestCaseGroup* const strideZeroTests = new tcu::TestCaseGroup(testCtx, "stride_zero", "Test input assembly with stride zero");
6566
6567                 primitives->addChild(nostippleTests);
6568                 primitives->addChild(stippleStaticTests);
6569                 primitives->addChild(stippleDynamicTests);
6570                 primitives->addChild(strideZeroTests);
6571
6572                 // .stride_zero
6573                 {
6574                         {
6575                                 StrideZeroCase::Params params;
6576                                 params.bufferData.emplace_back(-StrideZeroCase::kCornerDelta, -StrideZeroCase::kCornerDelta);
6577                                 params.drawVertexCount = 1u;
6578                                 strideZeroTests->addChild(new StrideZeroCase(testCtx, "single_point", "Attempt to draw 1 point with stride 0", params));
6579                         }
6580                         {
6581                                 StrideZeroCase::Params params;
6582                                 params.bufferData.emplace_back(-StrideZeroCase::kCornerDelta, -StrideZeroCase::kCornerDelta);
6583                                 params.bufferData.emplace_back( StrideZeroCase::kCornerDelta, -StrideZeroCase::kCornerDelta);
6584                                 params.bufferData.emplace_back(-StrideZeroCase::kCornerDelta,  StrideZeroCase::kCornerDelta);
6585                                 params.bufferData.emplace_back( StrideZeroCase::kCornerDelta,  StrideZeroCase::kCornerDelta);
6586                                 params.drawVertexCount = static_cast<deUint32>(params.bufferData.size());
6587                                 strideZeroTests->addChild(new StrideZeroCase(testCtx, "four_points", "Attempt to draw 4 points with stride 0 and 4 points in the buffer", params));
6588                         }
6589                         {
6590                                 StrideZeroCase::Params params;
6591                                 params.bufferData.emplace_back(-StrideZeroCase::kCornerDelta, -StrideZeroCase::kCornerDelta);
6592                                 params.drawVertexCount = 100000u;
6593                                 strideZeroTests->addChild(new StrideZeroCase(testCtx, "many_points", "Attempt to draw many points with stride 0 with one point in the buffer", params));
6594                         }
6595                 }
6596
6597                 nostippleTests->addChild(new BaseTestCase<TrianglesTestInstance>                (testCtx, "triangles",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result"));
6598                 nostippleTests->addChild(new BaseTestCase<TriangleStripTestInstance>    (testCtx, "triangle_strip",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result"));
6599                 nostippleTests->addChild(new BaseTestCase<TriangleFanTestInstance>              (testCtx, "triangle_fan",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result"));
6600                 nostippleTests->addChild(new WidenessTestCase<PointTestInstance>                (testCtx, "points",                             "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",                                   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, false, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
6601
6602                 nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>                (testCtx, "strict_lines",                       "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in strict mode, verify rasterization result",                                             PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
6603                 nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance>    (testCtx, "strict_line_strip",          "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in strict mode, verify rasterization result",                                    PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
6604                 nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>                (testCtx, "strict_lines_wide",          "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in strict mode with wide lines, verify rasterization result",             PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
6605                 nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance>    (testCtx, "strict_line_strip_wide",     "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in strict mode with wide lines, verify rasterization result",    PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
6606
6607                 nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>                (testCtx, "non_strict_lines",                   "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode, verify rasterization result",                                  PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
6608                 nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance>    (testCtx, "non_strict_line_strip",              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in nonstrict mode, verify rasterization result",                                 PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
6609                 nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>                (testCtx, "non_strict_lines_wide",              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode with wide lines, verify rasterization result",  PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
6610                 nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance>    (testCtx, "non_strict_line_strip_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in nonstrict mode with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
6611
6612                 for (int i = 0; i < 3; ++i) {
6613
6614                         tcu::TestCaseGroup *g = i == 2 ? stippleDynamicTests : i == 1 ? stippleStaticTests : nostippleTests;
6615
6616                         LineStipple stipple = (LineStipple)i;
6617
6618                         g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "lines",                                              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, i == 0 ? RESOLUTION_NPOT : 0));
6619                         g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "line_strip",                                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
6620                         g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "lines_wide",                                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
6621                         g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "line_strip_wide",                    "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
6622
6623                         g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "rectangular_lines",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
6624                         g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "rectangular_line_strip",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
6625                         g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "rectangular_lines_wide",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
6626                         g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "rectangular_line_strip_wide","Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
6627
6628                         g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "bresenham_lines",                    "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
6629                         g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "bresenham_line_strip",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
6630                         g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "bresenham_lines_wide",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
6631                         g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "bresenham_line_strip_wide",  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
6632
6633                         g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "smooth_lines",                               "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
6634                         g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "smooth_line_strip",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
6635                         g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "smooth_lines_wide",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
6636                         g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "smooth_line_strip_wide",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
6637                 }
6638         }
6639
6640         // .primitive_size
6641         {
6642                 tcu::TestCaseGroup* const primitiveSize = new tcu::TestCaseGroup(testCtx, "primitive_size", "Primitive size");
6643                 rasterizationTests->addChild(primitiveSize);
6644
6645                 // .points
6646                 {
6647                         tcu::TestCaseGroup* const points = new tcu::TestCaseGroup(testCtx, "points", "Point size");
6648
6649                         static const struct TestCombinations
6650                         {
6651                                 const deUint32  renderSize;
6652                                 const float             pointSize;
6653                         } testCombinations[] =
6654                         {
6655                                 { 1024,         128.0f          },
6656                                 { 1024,         256.0f          },
6657                                 { 1024,         512.0f          },
6658                                 { 2048,         1024.0f         },
6659                                 { 4096,         2048.0f         },
6660                                 { 8192,         4096.0f         },
6661                                 { 9216,         8192.0f         },
6662                                 { 10240,        10000.0f        }
6663                         };
6664
6665                         for (size_t testCombNdx = 0; testCombNdx < DE_LENGTH_OF_ARRAY(testCombinations); testCombNdx++)
6666                         {
6667                                 std::string     testCaseName    = "point_size_" + de::toString(testCombinations[testCombNdx].pointSize);
6668                                 deUint32        renderSize              = testCombinations[testCombNdx].renderSize;
6669                                 float           pointSize               = testCombinations[testCombNdx].pointSize;
6670
6671                                 points->addChild(new PointSizeTestCase<PointSizeTestInstance>   (testCtx, testCaseName, testCaseName, renderSize, pointSize));
6672                         }
6673
6674                         primitiveSize->addChild(points);
6675                 }
6676         }
6677
6678         // .fill_rules
6679         {
6680                 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules", "Primitive fill rules");
6681
6682                 rasterizationTests->addChild(fillRules);
6683
6684                 fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad",                   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_BASIC));
6685                 fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad_reverse",   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_REVERSED));
6686                 fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_full",                 "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL));
6687                 fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_partly",               "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL));
6688                 fillRules->addChild(new FillRuleTestCase(testCtx,       "projected",                    "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_PROJECTED));
6689         }
6690
6691         // .culling
6692         {
6693                 static const struct CullMode
6694                 {
6695                         VkCullModeFlags mode;
6696                         const char*             prefix;
6697                 } cullModes[] =
6698                 {
6699                         { VK_CULL_MODE_FRONT_BIT,                               "front_"        },
6700                         { VK_CULL_MODE_BACK_BIT,                                "back_"         },
6701                         { VK_CULL_MODE_FRONT_AND_BACK,                  "both_"         },
6702                 };
6703                 static const struct PrimitiveType
6704                 {
6705                         VkPrimitiveTopology     type;
6706                         const char*                     name;
6707                 } primitiveTypes[] =
6708                 {
6709                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                  "triangles"                     },
6710                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                 "triangle_strip"        },
6711                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,                   "triangle_fan"          },
6712                 };
6713                 static const struct FrontFaceOrder
6714                 {
6715                         VkFrontFace     mode;
6716                         const char*     postfix;
6717                 } frontOrders[] =
6718                 {
6719                         { VK_FRONT_FACE_COUNTER_CLOCKWISE,      ""                      },
6720                         { VK_FRONT_FACE_CLOCKWISE,                      "_reverse"      },
6721                 };
6722
6723                 static const struct PolygonMode
6724                 {
6725                         VkPolygonMode   mode;
6726                         const char*             name;
6727                 } polygonModes[] =
6728                 {
6729                         { VK_POLYGON_MODE_FILL,         ""              },
6730                         { VK_POLYGON_MODE_LINE,         "_line"         },
6731                         { VK_POLYGON_MODE_POINT,        "_point"        }
6732                 };
6733
6734                 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling", "Culling");
6735
6736                 rasterizationTests->addChild(culling);
6737
6738                 for (int cullModeNdx    = 0; cullModeNdx        < DE_LENGTH_OF_ARRAY(cullModes);                ++cullModeNdx)
6739                 for (int primitiveNdx   = 0; primitiveNdx       < DE_LENGTH_OF_ARRAY(primitiveTypes);   ++primitiveNdx)
6740                 for (int frontOrderNdx  = 0; frontOrderNdx      < DE_LENGTH_OF_ARRAY(frontOrders);              ++frontOrderNdx)
6741                 for (int polygonModeNdx = 0; polygonModeNdx     < DE_LENGTH_OF_ARRAY(polygonModes);             ++polygonModeNdx)
6742                 {
6743                         if (!(cullModes[cullModeNdx].mode == VK_CULL_MODE_FRONT_AND_BACK && polygonModes[polygonModeNdx].mode != VK_POLYGON_MODE_FILL))
6744                         {
6745                                 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix + polygonModes[polygonModeNdx].name;
6746                                 culling->addChild(new CullingTestCase(testCtx, name, "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode, polygonModes[polygonModeNdx].mode));
6747                         }
6748                 }
6749         }
6750
6751         // .discard
6752         {
6753                 static const struct PrimitiveType
6754                 {
6755                         VkPrimitiveTopology     type;
6756                         const char*                     name;
6757                 } primitiveTypes[] =
6758                 {
6759                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,  "triangle_list"         },
6760                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip"        },
6761                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,   "triangle_fan"          },
6762                         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,              "line_list"                     },
6763                         { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,             "line_strip"            },
6764                         { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,             "point_list"            }
6765                 };
6766
6767                 static const struct queryPipeline
6768                 {
6769                         deBool                  useQuery;
6770                         const char*             name;
6771                 } queryPipeline[] =
6772                 {
6773                         { DE_FALSE,     "query_pipeline_false"  },
6774                         { DE_TRUE,      "query_pipeline_true"   },
6775                 };
6776
6777                 tcu::TestCaseGroup* const discard = new tcu::TestCaseGroup(testCtx, "discard", "Rasterizer discard");
6778
6779                 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
6780                 {
6781                         tcu::TestCaseGroup* const primitive = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveNdx].name, "Rasterizer discard");
6782
6783                         for (int useQueryNdx = 0; useQueryNdx < DE_LENGTH_OF_ARRAY(queryPipeline); useQueryNdx++)
6784                         {
6785                                 const std::string name = std::string(queryPipeline[useQueryNdx].name);
6786
6787                                 primitive->addChild(new DiscardTestCase(testCtx, name, "Test primitive discarding.", primitiveTypes[primitiveNdx].type, queryPipeline[useQueryNdx].useQuery));
6788                         }
6789
6790                         discard->addChild(primitive);
6791                 }
6792
6793                 rasterizationTests->addChild(discard);
6794         }
6795
6796         // .conservative
6797         {
6798                 typedef struct
6799                 {
6800                         float                   size;
6801                         const char*             name;
6802                 } overestimateSizes;
6803
6804                 const overestimateSizes overestimateNormalSizes[]       =
6805                 {
6806                         { 0.00f,                        "0_00" },
6807                         { 0.25f,                        "0_25" },
6808                         { 0.50f,                        "0_50" },
6809                         { 0.75f,                        "0_75" },
6810                         { 1.00f,                        "1_00" },
6811                         { 2.00f,                        "2_00" },
6812                         { 4.00f,                        "4_00" },
6813                         { -TCU_INFINITY,        "min" },
6814                         { TCU_INFINITY,         "max" },
6815                 };
6816                 const overestimateSizes overestimateDegenerate[]        =
6817                 {
6818                         { 0.00f,                        "0_00" },
6819                         { 0.25f,                        "0_25" },
6820                         { -TCU_INFINITY,        "min" },
6821                         { TCU_INFINITY,         "max" },
6822                 };
6823                 const overestimateSizes underestimateLineWidths[]       =
6824                 {
6825                         { 0.50f,                        "0_50" },
6826                         { 1.00f,                        "1_00" },
6827                         { 1.50f,                        "1_50" },
6828                 };
6829                 const overestimateSizes underestimatePointSizes[]       =
6830                 {
6831                         { 1.00f,                        "1_00" },
6832                         { 1.50f,                        "1_50" },
6833                         { 2.00f,                        "2_00" },
6834                         { 3.00f,                        "3_00" },
6835                         { 4.00f,                        "4_00" },
6836                         { 8.00f,                        "8_00" },
6837                 };
6838                 const struct PrimitiveType
6839                 {
6840                         VkPrimitiveTopology     type;
6841                         const char*                     name;
6842                 }
6843                 primitiveTypes[] =
6844                 {
6845                         { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,  "triangles"             },
6846                         { VK_PRIMITIVE_TOPOLOGY_LINE_LIST,              "lines"                 },
6847                         { VK_PRIMITIVE_TOPOLOGY_POINT_LIST,             "points"                }
6848                 };
6849                 const VkSampleCountFlagBits samples[] =
6850                 {
6851                         VK_SAMPLE_COUNT_1_BIT,
6852                         VK_SAMPLE_COUNT_2_BIT,
6853                         VK_SAMPLE_COUNT_4_BIT,
6854                         VK_SAMPLE_COUNT_8_BIT,
6855                         VK_SAMPLE_COUNT_16_BIT,
6856                         VK_SAMPLE_COUNT_32_BIT,
6857                         VK_SAMPLE_COUNT_64_BIT
6858                 };
6859
6860                 tcu::TestCaseGroup* const conservative = new tcu::TestCaseGroup(testCtx, "conservative", "Conservative rasterization tests");
6861
6862                 rasterizationTests->addChild(conservative);
6863
6864                 {
6865                         tcu::TestCaseGroup* const overestimate = new tcu::TestCaseGroup(testCtx, "overestimate", "Overestimate tests");
6866
6867                         conservative->addChild(overestimate);
6868
6869                         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
6870                         {
6871                                 const std::string samplesGroupName = "samples_" + de::toString(samples[samplesNdx]);
6872
6873                                 tcu::TestCaseGroup* const samplesGroup = new tcu::TestCaseGroup(testCtx, samplesGroupName.c_str(), "Samples tests");
6874
6875                                 overestimate->addChild(samplesGroup);
6876
6877                                 for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx)
6878                                 {
6879                                         tcu::TestCaseGroup* const primitiveGroup = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveTypeNdx].name, "Primitive tests");
6880
6881                                         samplesGroup->addChild(primitiveGroup);
6882
6883                                         {
6884                                                 tcu::TestCaseGroup* const normal = new tcu::TestCaseGroup(testCtx, "normal", "Normal conservative rasterization tests");
6885
6886                                                 primitiveGroup->addChild(normal);
6887
6888                                                 for (int overestimateSizesNdx = 0; overestimateSizesNdx < DE_LENGTH_OF_ARRAY(overestimateNormalSizes); ++overestimateSizesNdx)
6889                                                 {
6890                                                         const ConservativeTestConfig    config  =
6891                                                         {
6892                                                                 VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT,    //  VkConservativeRasterizationModeEXT  conservativeRasterizationMode;
6893                                                                 overestimateNormalSizes[overestimateSizesNdx].size,             //  float                                                               extraOverestimationSize;
6894                                                                 primitiveTypes[primitiveTypeNdx].type,                                  //  VkPrimitiveTopology                                 primitiveTopology;
6895                                                                 false,                                                                                                  //  bool                                                                degeneratePrimitives;
6896                                                                 1.0f,                                                                                                   //  float                                                               lineWidth;
6897                                                                 RESOLUTION_POT,                                                                                 //  deUint32                                                    resolution;
6898                                                         };
6899
6900                                                         if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
6901                                                                 normal->addChild(new ConservativeTestCase<ConservativeTraingleTestInstance>     (testCtx,
6902                                                                                                                                                                                                                          overestimateNormalSizes[overestimateSizesNdx].name,
6903                                                                                                                                                                                                                          "Overestimate test, verify rasterization result",
6904                                                                                                                                                                                                                          config,
6905                                                                                                                                                                                                                          samples[samplesNdx]));
6906
6907                                                         if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_LINE_LIST)
6908                                                                 normal->addChild(new ConservativeTestCase<ConservativeLineTestInstance>         (testCtx,
6909                                                                                                                                                                                                                          overestimateNormalSizes[overestimateSizesNdx].name,
6910                                                                                                                                                                                                                          "Overestimate test, verify rasterization result",
6911                                                                                                                                                                                                                          config,
6912                                                                                                                                                                                                                          samples[samplesNdx]));
6913
6914                                                         if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
6915                                                                 normal->addChild(new ConservativeTestCase<ConservativePointTestInstance>        (testCtx,
6916                                                                                                                                                                                                                          overestimateNormalSizes[overestimateSizesNdx].name,
6917                                                                                                                                                                                                                          "Overestimate test, verify rasterization result",
6918                                                                                                                                                                                                                          config,
6919                                                                                                                                                                                                                          samples[samplesNdx]));
6920                                                 }
6921                                         }
6922
6923                                         {
6924                                                 tcu::TestCaseGroup* const degenerate = new tcu::TestCaseGroup(testCtx, "degenerate", "Degenerate primitives conservative rasterization tests");
6925
6926                                                 primitiveGroup->addChild(degenerate);
6927
6928                                                 for (int overestimateSizesNdx = 0; overestimateSizesNdx < DE_LENGTH_OF_ARRAY(overestimateDegenerate); ++overestimateSizesNdx)
6929                                                 {
6930                                                         const ConservativeTestConfig    config  =
6931                                                         {
6932                                                                 VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT,    //  VkConservativeRasterizationModeEXT  conservativeRasterizationMode;
6933                                                                 overestimateDegenerate[overestimateSizesNdx].size,              //  float                                                               extraOverestimationSize;
6934                                                                 primitiveTypes[primitiveTypeNdx].type,                                  //  VkPrimitiveTopology                                 primitiveTopology;
6935                                                                 true,                                                                                                   //  bool                                                                degeneratePrimitives;
6936                                                                 1.0f,                                                                                                   //  float                                                               lineWidth;
6937                                                                 64u,                                                                                                    //  deUint32                                                    resolution;
6938                                                         };
6939
6940                                                         if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
6941                                                                 degenerate->addChild(new ConservativeTestCase<ConservativeTraingleTestInstance> (testCtx,
6942                                                                                                                                                                                                                                  overestimateDegenerate[overestimateSizesNdx].name,
6943                                                                                                                                                                                                                                  "Overestimate triangle test, verify rasterization result",
6944                                                                                                                                                                                                                                  config,
6945                                                                                                                                                                                                                                  samples[samplesNdx]));
6946
6947                                                         if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_LINE_LIST)
6948                                                                 degenerate->addChild(new ConservativeTestCase<ConservativeLineTestInstance>             (testCtx,
6949                                                                                                                                                                                                                                  overestimateDegenerate[overestimateSizesNdx].name,
6950                                                                                                                                                                                                                                  "Overestimate line test, verify rasterization result",
6951                                                                                                                                                                                                                                  config,
6952                                                                                                                                                                                                                                  samples[samplesNdx]));
6953                                                 }
6954                                         }
6955                                 }
6956                         }
6957                 }
6958
6959                 {
6960                         tcu::TestCaseGroup* const underestimate = new tcu::TestCaseGroup(testCtx, "underestimate", "Underestimate tests");
6961
6962                         conservative->addChild(underestimate);
6963
6964                         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
6965                         {
6966                                 const std::string samplesGroupName = "samples_" + de::toString(samples[samplesNdx]);
6967
6968                                 tcu::TestCaseGroup* const samplesGroup = new tcu::TestCaseGroup(testCtx, samplesGroupName.c_str(), "Samples tests");
6969
6970                                 underestimate->addChild(samplesGroup);
6971
6972                                 for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx)
6973                                 {
6974                                         tcu::TestCaseGroup* const primitiveGroup = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveTypeNdx].name, "Primitive tests");
6975
6976                                         samplesGroup->addChild(primitiveGroup);
6977
6978                                         {
6979                                                 tcu::TestCaseGroup* const normal = new tcu::TestCaseGroup(testCtx, "normal", "Normal conservative rasterization tests");
6980
6981                                                 primitiveGroup->addChild(normal);
6982
6983                                                 ConservativeTestConfig  config  =
6984                                                 {
6985                                                         VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,   //  VkConservativeRasterizationModeEXT  conservativeRasterizationMode;
6986                                                         0.0f,                                                                                                   //  float                                                               extraOverestimationSize;
6987                                                         primitiveTypes[primitiveTypeNdx].type,                                  //  VkPrimitiveTopology                                 primitiveTopology;
6988                                                         false,                                                                                                  //  bool                                                                degeneratePrimitives;
6989                                                         1.0f,                                                                                                   //  float                                                               lineWidth;
6990                                                         64u,                                                                                                    //  deUint32                                                    resolution;
6991                                                 };
6992
6993                                                 if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
6994                                                         normal->addChild(new ConservativeTestCase<ConservativeTraingleTestInstance>     (testCtx,
6995                                                                                                                                                                                                                  "test",
6996                                                                                                                                                                                                                  "Underestimate test, verify rasterization result",
6997                                                                                                                                                                                                                  config,
6998                                                                                                                                                                                                                  samples[samplesNdx]));
6999
7000                                                 if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_LINE_LIST)
7001                                                 {
7002                                                         for (int underestimateWidthNdx = 0; underestimateWidthNdx < DE_LENGTH_OF_ARRAY(underestimateLineWidths); ++underestimateWidthNdx)
7003                                                         {
7004                                                                 config.lineWidth = underestimateLineWidths[underestimateWidthNdx].size;
7005                                                                 normal->addChild(new ConservativeTestCase<ConservativeLineTestInstance>         (testCtx,
7006                                                                                                                                                                                                                          underestimateLineWidths[underestimateWidthNdx].name,
7007                                                                                                                                                                                                                          "Underestimate test, verify rasterization result",
7008                                                                                                                                                                                                                          config,
7009                                                                                                                                                                                                                          samples[samplesNdx]));
7010                                                         }
7011                                                 }
7012
7013                                                 if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
7014                                                 {
7015                                                         for (int underestimatePointSizeNdx = 0; underestimatePointSizeNdx < DE_LENGTH_OF_ARRAY(underestimatePointSizes); ++underestimatePointSizeNdx)
7016                                                         {
7017                                                                 config.lineWidth = underestimatePointSizes[underestimatePointSizeNdx].size;
7018                                                                 normal->addChild(new ConservativeTestCase<ConservativePointTestInstance>        (testCtx,
7019                                                                                                                                                                                                                          underestimatePointSizes[underestimatePointSizeNdx].name,
7020                                                                                                                                                                                                                          "Underestimate test, verify rasterization result",
7021                                                                                                                                                                                                                          config,
7022                                                                                                                                                                                                                          samples[samplesNdx]));
7023                                                         }
7024                                                 }
7025                                         }
7026
7027                                         {
7028                                                 tcu::TestCaseGroup* const degenerate = new tcu::TestCaseGroup(testCtx, "degenerate", "Degenerate primitives conservative rasterization tests");
7029
7030                                                 primitiveGroup->addChild(degenerate);
7031
7032                                                 ConservativeTestConfig  config  =
7033                                                 {
7034                                                         VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,   //  VkConservativeRasterizationModeEXT  conservativeRasterizationMode;
7035                                                         0.0f,                                                                                                   //  float                                                               extraOverestimationSize;
7036                                                         primitiveTypes[primitiveTypeNdx].type,                                  //  VkPrimitiveTopology                                 primitiveTopology;
7037                                                         true,                                                                                                   //  bool                                                                degeneratePrimitives;
7038                                                         1.0f,                                                                                                   //  float                                                               lineWidth;
7039                                                         64u,                                                                                                    //  deUint32                                                    resolution;
7040                                                 };
7041
7042                                                 if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
7043                                                         degenerate->addChild(new ConservativeTestCase<ConservativeTraingleTestInstance> (testCtx,
7044                                                                                                                                                                                                                          "test",
7045                                                                                                                                                                                                                          "Underestimate triangle test, verify rasterization result",
7046                                                                                                                                                                                                                          config,
7047                                                                                                                                                                                                                          samples[samplesNdx]));
7048
7049                                                 if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_LINE_LIST)
7050                                                 {
7051                                                         for (int underestimateWidthNdx = 0; underestimateWidthNdx < DE_LENGTH_OF_ARRAY(underestimateLineWidths); ++underestimateWidthNdx)
7052                                                         {
7053                                                                 config.lineWidth = underestimateLineWidths[underestimateWidthNdx].size;
7054                                                                 degenerate->addChild(new ConservativeTestCase<ConservativeLineTestInstance>             (testCtx,
7055                                                                                                                                                                                                                                  underestimateLineWidths[underestimateWidthNdx].name,
7056                                                                                                                                                                                                                                  "Underestimate line test, verify rasterization result",
7057                                                                                                                                                                                                                                  config,
7058                                                                                                                                                                                                                                  samples[samplesNdx]));
7059                                                         }
7060                                                 }
7061                                         }
7062                                 }
7063                         }
7064                 }
7065         }
7066
7067         // .interpolation
7068         {
7069                 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
7070
7071                 rasterizationTests->addChild(interpolation);
7072
7073                 // .basic
7074                 {
7075                         tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation");
7076
7077                         interpolation->addChild(basic);
7078
7079                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_NONE));
7080                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangle_strip",     "Verify triangle strip interpolation",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_NONE));
7081                         basic->addChild(new TriangleInterpolationTestCase               (testCtx, "triangle_fan",       "Verify triangle fan interpolation",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_NONE));
7082                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE));
7083                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "line_strip",         "Verify line strip interpolation",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE));
7084                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE));
7085                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "line_strip_wide","Verify wide line strip interpolation",     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE));
7086
7087                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "strict_lines",                       "Verify strict line interpolation",                             VK_PRIMITIVE_TOPOLOGY_LINE_LIST,        INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT));
7088                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "strict_line_strip",          "Verify strict line strip interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,       INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT));
7089                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "strict_lines_wide",          "Verify strict wide line interpolation",                VK_PRIMITIVE_TOPOLOGY_LINE_LIST,        INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT));
7090                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "strict_line_strip_wide",     "Verify strict wide line strip interpolation",  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,       INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT));
7091
7092                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "non_strict_lines",                   "Verify non-strict line interpolation",                         VK_PRIMITIVE_TOPOLOGY_LINE_LIST,        INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT));
7093                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "non_strict_line_strip",              "Verify non-strict line strip interpolation",           VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,       INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT));
7094                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "non_strict_lines_wide",              "Verify non-strict wide line interpolation",            VK_PRIMITIVE_TOPOLOGY_LINE_LIST,        INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT));
7095                         basic->addChild(new LineInterpolationTestCase                   (testCtx, "non_strict_line_strip_wide", "Verify non-strict wide line strip interpolation",      VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,       INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT));
7096                 }
7097
7098                 // .projected
7099                 {
7100                         tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation");
7101
7102                         interpolation->addChild(projected);
7103
7104                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_PROJECTED));
7105                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangle_strip",     "Verify triangle strip interpolation",  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_PROJECTED));
7106                         projected->addChild(new TriangleInterpolationTestCase   (testCtx, "triangle_fan",       "Verify triangle fan interpolation",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_PROJECTED));
7107                         projected->addChild(new LineInterpolationTestCase               (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE));
7108                         projected->addChild(new LineInterpolationTestCase               (testCtx, "line_strip",         "Verify line strip interpolation",              VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE));
7109                         projected->addChild(new LineInterpolationTestCase               (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE));
7110                         projected->addChild(new LineInterpolationTestCase               (testCtx, "line_strip_wide","Verify wide line strip interpolation",     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE));
7111
7112                         projected->addChild(new LineInterpolationTestCase               (testCtx, "strict_lines",                       "Verify strict line interpolation",                             VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT));
7113                         projected->addChild(new LineInterpolationTestCase               (testCtx, "strict_line_strip",          "Verify strict line strip interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT));
7114                         projected->addChild(new LineInterpolationTestCase               (testCtx, "strict_lines_wide",          "Verify strict wide line interpolation",                VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT));
7115                         projected->addChild(new LineInterpolationTestCase               (testCtx, "strict_line_strip_wide",     "Verify strict wide line strip interpolation",  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT));
7116
7117                         projected->addChild(new LineInterpolationTestCase               (testCtx, "non_strict_lines",                   "Verify non-strict line interpolation",                         VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT));
7118                         projected->addChild(new LineInterpolationTestCase               (testCtx, "non_strict_line_strip",              "Verify non-strict line strip interpolation",           VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT));
7119                         projected->addChild(new LineInterpolationTestCase               (testCtx, "non_strict_lines_wide",              "Verify non-strict wide line interpolation",            VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT));
7120                         projected->addChild(new LineInterpolationTestCase               (testCtx, "non_strict_line_strip_wide", "Verify non-strict wide line strip interpolation",      VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_PROJECTED,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT));
7121                 }
7122         }
7123
7124         // .flatshading
7125         {
7126                 tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading");
7127
7128                 rasterizationTests->addChild(flatshading);
7129
7130                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangles",          "Verify triangle flatshading",                  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_FLATSHADE));
7131                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangle_strip",     "Verify triangle strip flatshading",    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,   INTERPOLATIONFLAGS_FLATSHADE));
7132                 flatshading->addChild(new TriangleInterpolationTestCase         (testCtx, "triangle_fan",       "Verify triangle fan flatshading",              VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,             INTERPOLATIONFLAGS_FLATSHADE));
7133                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "lines",                      "Verify line flatshading",                              VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE));
7134                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "line_strip",         "Verify line strip flatshading",                VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE));
7135                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "lines_wide",         "Verify wide line flatshading",                 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE));
7136                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "line_strip_wide","Verify wide line strip flatshading",       VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE));
7137
7138                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "strict_lines",                       "Verify strict line flatshading",                               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT));
7139                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "strict_line_strip",          "Verify strict line strip flatshading",                 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT));
7140                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "strict_lines_wide",          "Verify strict wide line flatshading",                  VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT));
7141                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "strict_line_strip_wide",     "Verify strict wide line strip flatshading",    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT));
7142
7143                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "non_strict_lines",                   "Verify non-strict line flatshading",                           VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT));
7144                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "non_strict_line_strip",              "Verify non-strict line strip flatshading",                     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT));
7145                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "non_strict_lines_wide",              "Verify non-strict wide line flatshading",                      VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT));
7146                 flatshading->addChild(new LineInterpolationTestCase                     (testCtx, "non_strict_line_strip_wide", "Verify non-strict wide line strip flatshading",        VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,               INTERPOLATIONFLAGS_FLATSHADE,   PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT));
7147         }
7148
7149         const VkSampleCountFlagBits samples[] =
7150         {
7151                 VK_SAMPLE_COUNT_2_BIT,
7152                 VK_SAMPLE_COUNT_4_BIT,
7153                 VK_SAMPLE_COUNT_8_BIT,
7154                 VK_SAMPLE_COUNT_16_BIT,
7155                 VK_SAMPLE_COUNT_32_BIT,
7156                 VK_SAMPLE_COUNT_64_BIT
7157         };
7158
7159         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
7160         {
7161                 std::ostringstream caseName;
7162
7163                 caseName << "_multisample_" << (2 << samplesNdx) << "_bit";
7164
7165                 // .primitives
7166                 {
7167                         tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization");
7168
7169                         rasterizationTests->addChild(primitives);
7170
7171                         tcu::TestCaseGroup* const nostippleTests = new tcu::TestCaseGroup(testCtx, "no_stipple", "No stipple");
7172                         tcu::TestCaseGroup* const stippleStaticTests = new tcu::TestCaseGroup(testCtx, "static_stipple", "Line stipple static");
7173                         tcu::TestCaseGroup* const stippleDynamicTests = new tcu::TestCaseGroup(testCtx, "dynamic_stipple", "Line stipple dynamic");
7174
7175                         primitives->addChild(nostippleTests);
7176                         primitives->addChild(stippleStaticTests);
7177                         primitives->addChild(stippleDynamicTests);
7178
7179                         nostippleTests->addChild(new BaseTestCase<TrianglesTestInstance>                (testCtx, "triangles",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result",                                        samples[samplesNdx]));
7180                         nostippleTests->addChild(new WidenessTestCase<PointTestInstance>                (testCtx, "points",                             "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result",                                           PRIMITIVEWIDENESS_WIDE, PRIMITIVESTRICTNESS_IGNORE,     false, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
7181
7182                         nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>                (testCtx, "strict_lines",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in strict mode, verify rasterization result",                                             PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT,     true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7183                         nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>                (testCtx, "strict_lines_wide",  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in strict mode with wide lines, verify rasterization result",             PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT,     true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7184
7185                         nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>                (testCtx, "non_strict_lines",           "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode, verify rasterization result",                                          PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT,  true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7186                         nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>                (testCtx, "non_strict_lines_wide",      "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode with wide lines, verify rasterization result",          PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT,  true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7187
7188                         for (int i = 0; i < 3; ++i) {
7189
7190                                 tcu::TestCaseGroup *g = i == 2 ? stippleDynamicTests : i == 1 ? stippleStaticTests : nostippleTests;
7191
7192                                 LineStipple stipple = (LineStipple)i;
7193
7194                                 g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "lines",                                              "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, i == 0 ? RESOLUTION_NPOT : 0));
7195                                 g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "line_strip",                                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
7196                                 g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "lines_wide",                                 "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
7197                                 g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "line_strip_wide",                    "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
7198
7199                                 g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "rectangular_lines",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
7200                                 g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "rectangular_line_strip",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
7201                                 g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "rectangular_lines_wide",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
7202                                 g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "rectangular_line_strip_wide","Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
7203
7204                                 g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "bresenham_lines",                    "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
7205                                 g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "bresenham_line_strip",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
7206                                 g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "bresenham_lines_wide",               "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
7207                                 g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "bresenham_line_strip_wide",  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
7208
7209                                 g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "smooth_lines",                               "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result",                                            PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
7210                                 g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "smooth_line_strip",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result",                                           PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
7211                                 g->addChild(new WidenessTestCase<LinesTestInstance>             (testCtx, "smooth_lines_wide",                  "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result",            PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
7212                                 g->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "smooth_line_strip_wide",             "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result",           PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
7213                         }
7214                 }
7215
7216                 // .fill_rules
7217                 {
7218                         tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules");
7219
7220                         rasterizationTests->addChild(fillRules);
7221
7222                         fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad",                   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_BASIC,                       samples[samplesNdx]));
7223                         fillRules->addChild(new FillRuleTestCase(testCtx,       "basic_quad_reverse",   "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_REVERSED,            samples[samplesNdx]));
7224                         fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_full",                 "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL,        samples[samplesNdx]));
7225                         fillRules->addChild(new FillRuleTestCase(testCtx,       "clipped_partly",               "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL,     samples[samplesNdx]));
7226                         fillRules->addChild(new FillRuleTestCase(testCtx,       "projected",                    "Verify fill rules",    FillRuleTestInstance::FILLRULECASE_PROJECTED,           samples[samplesNdx]));
7227                 }
7228
7229                 // .interpolation
7230                 {
7231                         tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation");
7232
7233                         rasterizationTests->addChild(interpolation);
7234
7235                         interpolation->addChild(new TriangleInterpolationTestCase               (testCtx, "triangles",          "Verify triangle interpolation",                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    INTERPOLATIONFLAGS_NONE,                                                                                                                        samples[samplesNdx]));
7236                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "lines",                      "Verify line interpolation",                    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_IGNORE,     samples[samplesNdx]));
7237                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "lines_wide",         "Verify wide line interpolation",               VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_IGNORE,     samples[samplesNdx]));
7238
7239                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "strict_lines",                       "Verify strict line interpolation",                     VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_STRICT,     samples[samplesNdx]));
7240                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "strict_lines_wide",          "Verify strict wide line interpolation",        VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_STRICT,     samples[samplesNdx]));
7241
7242                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "non_strict_lines",                   "Verify non-strict line interpolation",                 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_NARROW,       PRIMITIVESTRICTNESS_NONSTRICT,  samples[samplesNdx]));
7243                         interpolation->addChild(new LineInterpolationTestCase                   (testCtx, "non_strict_lines_wide",              "Verify non-strict wide line interpolation",    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,                INTERPOLATIONFLAGS_NONE,        PRIMITIVEWIDENESS_WIDE,         PRIMITIVESTRICTNESS_NONSTRICT,  samples[samplesNdx]));
7244                 }
7245         }
7246
7247         // .provoking_vertex
7248         {
7249                 rasterizationTests->addChild(createProvokingVertexTests(testCtx));
7250         }
7251
7252         // .line_continuity
7253         {
7254                 tcu::TestCaseGroup* const       lineContinuity  = new tcu::TestCaseGroup(testCtx, "line_continuity", "Test line continuity");
7255                 static const char                       dataDir[]               = "rasterization/line_continuity";
7256
7257                 struct Case
7258                 {
7259                         std::string     name;
7260                         std::string     desc;
7261                         bool            requireFillModeNonSolid;
7262                 };
7263
7264                 static const Case cases[] =
7265                 {
7266                         {       "line-strip",                   "Test line strip drawing produces continuous lines",    false   },
7267                         {       "polygon-mode-lines",   "Test triangles drawn with lines are continuous",               true    }
7268                 };
7269
7270                 rasterizationTests->addChild(lineContinuity);
7271
7272                 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
7273                 {
7274                         const std::string                       fileName        = cases[i].name + ".amber";
7275                         cts_amber::AmberTestCase*       testCase        = cts_amber::createAmberTestCase(testCtx, cases[i].name.c_str(), cases[i].desc.c_str(), dataDir, fileName);
7276
7277                         if (cases[i].requireFillModeNonSolid)
7278                         {
7279                                 testCase->addRequirement("Features.fillModeNonSolid");
7280                         }
7281
7282                         lineContinuity->addChild(testCase);
7283                 }
7284         }
7285
7286         // .depth bias
7287         {
7288                 tcu::TestCaseGroup* const       depthBias       = new tcu::TestCaseGroup(testCtx, "depth_bias", "Test depth bias");
7289                 static const char                       dataDir[]       = "rasterization/depth_bias";
7290
7291                 static const struct
7292                 {
7293                         std::string name;
7294                         vk::VkFormat format;
7295                         std::string description;
7296                 } cases [] =
7297                 {
7298                         {"d16_unorm",   vk::VK_FORMAT_D16_UNORM,                        "Test depth bias with format D16_UNORM"},
7299                         {"d32_sfloat",  vk::VK_FORMAT_D32_SFLOAT,                       "Test depth bias with format D32_SFLOAT"},
7300                         {"d24_unorm",   vk::VK_FORMAT_D24_UNORM_S8_UINT,        "Test depth bias with format D24_UNORM_S8_UINT"}
7301                 };
7302
7303                 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
7304                 {
7305                         const VkImageCreateInfo vkImageCreateInfo = {
7306                                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // sType
7307                                 nullptr,                                                                                // pNext
7308                                 0,                                                                                              // flags
7309                                 VK_IMAGE_TYPE_2D,                                                               // imageType
7310                                 cases[i].format,                                                                // format
7311                                 {250, 250, 1},                                                                  // extent
7312                                 1,                                                                                              // mipLevels
7313                                 1,                                                                                              // arrayLayers
7314                                 VK_SAMPLE_COUNT_1_BIT,                                                  // samples
7315                                 VK_IMAGE_TILING_OPTIMAL,                                                // tiling
7316                                 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,    // usage
7317                                 VK_SHARING_MODE_EXCLUSIVE,                                              // sharingMode
7318                                 0,                                                                                              // queueFamilyIndexCount
7319                                 nullptr,                                                                                // pQueueFamilyIndices
7320                                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // initialLayout
7321                         };
7322
7323                         std::vector<std::string>                requirements = std::vector<std::string>(0);
7324                         std::vector<VkImageCreateInfo>  imageRequirements;
7325                         imageRequirements.push_back(vkImageCreateInfo);
7326                         const std::string                       fileName        = cases[i].name + ".amber";
7327                         cts_amber::AmberTestCase*       testCase        = cts_amber::createAmberTestCase(testCtx, cases[i].name.c_str(), cases[i].description.c_str(), dataDir, fileName, requirements, imageRequirements);
7328
7329                         depthBias->addChild(testCase);
7330                 }
7331
7332                 rasterizationTests->addChild(depthBias);
7333         }
7334
7335         // Fragment shader side effects.
7336         {
7337                 rasterizationTests->addChild(createFragSideEffectsTests(testCtx));
7338         }
7339 }
7340
7341 } // anonymous
7342
7343 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
7344 {
7345         return createTestGroup(testCtx, "rasterization", "Rasterization Tests", createRasterizationTests);
7346 }
7347
7348 } // rasterization
7349 } // vkt