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