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