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