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