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