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