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