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 "vktRasterizationTests.hpp"
27 #include "tcuRasterizationVerifier.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "tcuStringTemplate.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuResultCollector.hpp"
34 #include "vkImageUtil.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
37 #include "vktTestCase.hpp"
38 #include "vktTestCaseUtil.hpp"
39 #include "vktTestGroupUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkMemUtil.hpp"
42 #include "vkRefUtil.hpp"
43 #include "vkQueryUtil.hpp"
44 #include "vkBuilderUtil.hpp"
45 #include "vkTypeUtil.hpp"
46 #include "vkCmdUtil.hpp"
47 #include "vkObjUtil.hpp"
48
49 #include <vector>
50
51 using namespace vk;
52
53 namespace vkt
54 {
55 namespace rasterization
56 {
57 namespace
58 {
59
60 using tcu::RasterizationArguments;
61 using tcu::TriangleSceneSpec;
62 using tcu::PointSceneSpec;
63 using tcu::LineSceneSpec;
64 using tcu::LineInterpolationMethod;
65
66 static const char* const s_shaderVertexTemplate = "#version 310 es\n"
67 "layout(location = 0) in highp vec4 a_position;\n"
68 "layout(location = 1) in highp vec4 a_color;\n"
69 "layout(location = 0) ${INTERPOLATION}out highp vec4 v_color;\n"
70 "layout (set=0, binding=0) uniform PointSize {\n"
71 " highp float u_pointSize;\n"
72 "};\n"
73 "void main ()\n"
74 "{\n"
75 " gl_Position = a_position;\n"
76 " gl_PointSize = u_pointSize;\n"
77 " v_color = a_color;\n"
78 "}\n";
79
80 static const char* const s_shaderFragmentTemplate = "#version 310 es\n"
81 "layout(location = 0) out highp vec4 fragColor;\n"
82 "layout(location = 0) ${INTERPOLATION}in highp vec4 v_color;\n"
83 "void main ()\n"
84 "{\n"
85 " fragColor = v_color;\n"
86 "}\n";
87 enum InterpolationCaseFlags
88 {
89 INTERPOLATIONFLAGS_NONE = 0,
90 INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
91 INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
92 };
93
94 enum PrimitiveWideness
95 {
96 PRIMITIVEWIDENESS_NARROW = 0,
97 PRIMITIVEWIDENESS_WIDE,
98
99 PRIMITIVEWIDENESS_LAST
100 };
101
102 class BaseRenderingTestCase : public TestCase
103 {
104 public:
105 BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deBool flatshade = DE_FALSE);
106 virtual ~BaseRenderingTestCase (void);
107
108 virtual void initPrograms (vk::SourceCollections& programCollection) const;
109
110 protected:
111 const VkSampleCountFlagBits m_sampleCount;
112 const deBool m_flatshade;
113 };
114
BaseRenderingTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkSampleCountFlagBits sampleCount,deBool flatshade)115 BaseRenderingTestCase::BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount, deBool flatshade)
116 : TestCase(context, name, description)
117 , m_sampleCount (sampleCount)
118 , m_flatshade (flatshade)
119 {
120 }
121
initPrograms(vk::SourceCollections & programCollection) const122 void BaseRenderingTestCase::initPrograms (vk::SourceCollections& programCollection) const
123 {
124 tcu::StringTemplate vertexSource (s_shaderVertexTemplate);
125 tcu::StringTemplate fragmentSource (s_shaderFragmentTemplate);
126 std::map<std::string, std::string> params;
127
128 params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
129
130 programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vertexSource.specialize(params));
131 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fragmentSource.specialize(params));
132 }
133
~BaseRenderingTestCase(void)134 BaseRenderingTestCase::~BaseRenderingTestCase (void)
135 {
136 }
137
138 class BaseRenderingTestInstance : public TestInstance
139 {
140 public:
141 enum {
142 DEFAULT_RENDER_SIZE = 256
143 };
144
145 BaseRenderingTestInstance (Context& context, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deUint32 renderSize = DEFAULT_RENDER_SIZE);
146 ~BaseRenderingTestInstance (void);
147
148 protected:
149 void addImageTransitionBarrier (VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
150 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology);
151 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, VkPrimitiveTopology primitiveTopology);
152 virtual float getLineWidth (void) const;
153 virtual float getPointSize (void) const;
154
155 virtual
156 const VkPipelineRasterizationStateCreateInfo* getRasterizationStateCreateInfo (void) const;
157
158 virtual
159 const VkPipelineColorBlendStateCreateInfo* getColorBlendStateCreateInfo (void) const;
160
161 const tcu::TextureFormat& getTextureFormat (void) const;
162
163 const deUint32 m_renderSize;
164 const VkSampleCountFlagBits m_sampleCount;
165 const deUint32 m_subpixelBits;
166 const deBool m_multisampling;
167
168 const VkFormat m_imageFormat;
169 const tcu::TextureFormat m_textureFormat;
170 Move<VkCommandPool> m_commandPool;
171
172 Move<VkImage> m_image;
173 de::MovePtr<Allocation> m_imageMemory;
174 Move<VkImageView> m_imageView;
175
176 Move<VkImage> m_resolvedImage;
177 de::MovePtr<Allocation> m_resolvedImageMemory;
178 Move<VkImageView> m_resolvedImageView;
179
180 Move<VkRenderPass> m_renderPass;
181 Move<VkFramebuffer> m_frameBuffer;
182
183 Move<VkDescriptorPool> m_descriptorPool;
184 Move<VkDescriptorSet> m_descriptorSet;
185 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
186
187 Move<VkBuffer> m_uniformBuffer;
188 de::MovePtr<Allocation> m_uniformBufferMemory;
189 const VkDeviceSize m_uniformBufferSize;
190
191 Move<VkPipelineLayout> m_pipelineLayout;
192
193 Move<VkShaderModule> m_vertexShaderModule;
194 Move<VkShaderModule> m_fragmentShaderModule;
195
196 Move<VkBuffer> m_resultBuffer;
197 de::MovePtr<Allocation> m_resultBufferMemory;
198 const VkDeviceSize m_resultBufferSize;
199 };
200
BaseRenderingTestInstance(Context & context,VkSampleCountFlagBits sampleCount,deUint32 renderSize)201 BaseRenderingTestInstance::BaseRenderingTestInstance (Context& context, VkSampleCountFlagBits sampleCount, deUint32 renderSize)
202 : TestInstance (context)
203 , m_renderSize (renderSize)
204 , m_sampleCount (sampleCount)
205 , m_subpixelBits (context.getDeviceProperties().limits.subPixelPrecisionBits)
206 , m_multisampling (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
207 , m_imageFormat (VK_FORMAT_R8G8B8A8_UNORM)
208 , m_textureFormat (vk::mapVkFormat(m_imageFormat))
209 , m_uniformBufferSize (sizeof(float))
210 , m_resultBufferSize (renderSize * renderSize * m_textureFormat.getPixelSize())
211 {
212 const DeviceInterface& vkd = m_context.getDeviceInterface();
213 const VkDevice vkDevice = m_context.getDevice();
214 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
215 Allocator& allocator = m_context.getDefaultAllocator();
216 DescriptorPoolBuilder descriptorPoolBuilder;
217 DescriptorSetLayoutBuilder descriptorSetLayoutBuilder;
218
219 // Command Pool
220 m_commandPool = createCommandPool(vkd, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
221
222 // Image
223 {
224 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
225 VkImageFormatProperties properties;
226
227 if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
228 m_imageFormat,
229 VK_IMAGE_TYPE_2D,
230 VK_IMAGE_TILING_OPTIMAL,
231 imageUsage,
232 0,
233 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
234 {
235 TCU_THROW(NotSupportedError, "Format not supported");
236 }
237
238 if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
239 {
240 TCU_THROW(NotSupportedError, "Format not supported");
241 }
242
243 const VkImageCreateInfo imageCreateInfo =
244 {
245 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
246 DE_NULL, // const void* pNext;
247 0u, // VkImageCreateFlags flags;
248 VK_IMAGE_TYPE_2D, // VkImageType imageType;
249 m_imageFormat, // VkFormat format;
250 { m_renderSize, m_renderSize, 1u }, // VkExtent3D extent;
251 1u, // deUint32 mipLevels;
252 1u, // deUint32 arrayLayers;
253 m_sampleCount, // VkSampleCountFlagBits samples;
254 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
255 imageUsage, // VkImageUsageFlags usage;
256 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
257 1u, // deUint32 queueFamilyIndexCount;
258 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
259 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
260 };
261
262 m_image = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
263
264 m_imageMemory = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_image), MemoryRequirement::Any);
265 VK_CHECK(vkd.bindImageMemory(vkDevice, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
266 }
267
268 // Image View
269 {
270 const VkImageViewCreateInfo imageViewCreateInfo =
271 {
272 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
273 DE_NULL, // const void* pNext;
274 0u, // VkImageViewCreateFlags flags;
275 *m_image, // VkImage image;
276 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
277 m_imageFormat, // VkFormat format;
278 makeComponentMappingRGBA(), // VkComponentMapping components;
279 {
280 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
281 0u, // deUint32 baseMipLevel;
282 1u, // deUint32 mipLevels;
283 0u, // deUint32 baseArrayLayer;
284 1u, // deUint32 arraySize;
285 }, // VkImageSubresourceRange subresourceRange;
286 };
287
288 m_imageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
289 }
290
291 if (m_multisampling)
292 {
293 {
294 // Resolved Image
295 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
296 VkImageFormatProperties properties;
297
298 if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
299 m_imageFormat,
300 VK_IMAGE_TYPE_2D,
301 VK_IMAGE_TILING_OPTIMAL,
302 imageUsage,
303 0,
304 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
305 {
306 TCU_THROW(NotSupportedError, "Format not supported");
307 }
308
309 const VkImageCreateInfo imageCreateInfo =
310 {
311 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
312 DE_NULL, // const void* pNext;
313 0u, // VkImageCreateFlags flags;
314 VK_IMAGE_TYPE_2D, // VkImageType imageType;
315 m_imageFormat, // VkFormat format;
316 { m_renderSize, m_renderSize, 1u }, // VkExtent3D extent;
317 1u, // deUint32 mipLevels;
318 1u, // deUint32 arrayLayers;
319 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
320 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
321 imageUsage, // VkImageUsageFlags usage;
322 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
323 1u, // deUint32 queueFamilyIndexCount;
324 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
325 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
326 };
327
328 m_resolvedImage = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
329 m_resolvedImageMemory = allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_resolvedImage), MemoryRequirement::Any);
330 VK_CHECK(vkd.bindImageMemory(vkDevice, *m_resolvedImage, m_resolvedImageMemory->getMemory(), m_resolvedImageMemory->getOffset()));
331 }
332
333 // Resolved Image View
334 {
335 const VkImageViewCreateInfo imageViewCreateInfo =
336 {
337 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
338 DE_NULL, // const void* pNext;
339 0u, // VkImageViewCreateFlags flags;
340 *m_resolvedImage, // VkImage image;
341 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
342 m_imageFormat, // VkFormat format;
343 makeComponentMappingRGBA(), // VkComponentMapping components;
344 {
345 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
346 0u, // deUint32 baseMipLevel;
347 1u, // deUint32 mipLevels;
348 0u, // deUint32 baseArrayLayer;
349 1u, // deUint32 arraySize;
350 }, // VkImageSubresourceRange subresourceRange;
351 };
352
353 m_resolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
354 }
355
356 }
357
358 // Render Pass
359 {
360 const VkImageLayout imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
361 const VkAttachmentDescription attachmentDesc[] =
362 {
363 {
364 0u, // VkAttachmentDescriptionFlags flags;
365 m_imageFormat, // VkFormat format;
366 m_sampleCount, // VkSampleCountFlagBits samples;
367 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
368 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
369 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
370 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
371 imageLayout, // VkImageLayout initialLayout;
372 imageLayout, // VkImageLayout finalLayout;
373 },
374 {
375 0u, // VkAttachmentDescriptionFlags flags;
376 m_imageFormat, // VkFormat format;
377 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
378 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
379 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
380 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
381 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
382 imageLayout, // VkImageLayout initialLayout;
383 imageLayout, // VkImageLayout finalLayout;
384 }
385 };
386
387 const VkAttachmentReference attachmentRef =
388 {
389 0u, // deUint32 attachment;
390 imageLayout, // VkImageLayout layout;
391 };
392
393 const VkAttachmentReference resolveAttachmentRef =
394 {
395 1u, // deUint32 attachment;
396 imageLayout, // VkImageLayout layout;
397 };
398
399 const VkSubpassDescription subpassDesc =
400 {
401 0u, // VkSubpassDescriptionFlags flags;
402 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
403 0u, // deUint32 inputAttachmentCount;
404 DE_NULL, // const VkAttachmentReference* pInputAttachments;
405 1u, // deUint32 colorAttachmentCount;
406 &attachmentRef, // const VkAttachmentReference* pColorAttachments;
407 m_multisampling ? &resolveAttachmentRef : DE_NULL, // const VkAttachmentReference* pResolveAttachments;
408 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
409 0u, // deUint32 preserveAttachmentCount;
410 DE_NULL, // const VkAttachmentReference* pPreserveAttachments;
411 };
412
413 const VkRenderPassCreateInfo renderPassCreateInfo =
414 {
415 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
416 DE_NULL, // const void* pNext;
417 0u, // VkRenderPassCreateFlags flags;
418 m_multisampling ? 2u : 1u, // deUint32 attachmentCount;
419 attachmentDesc, // const VkAttachmentDescription* pAttachments;
420 1u, // deUint32 subpassCount;
421 &subpassDesc, // const VkSubpassDescription* pSubpasses;
422 0u, // deUint32 dependencyCount;
423 DE_NULL, // const VkSubpassDependency* pDependencies;
424 };
425
426 m_renderPass = createRenderPass(vkd, vkDevice, &renderPassCreateInfo, DE_NULL);
427 }
428
429 // FrameBuffer
430 {
431 const VkImageView attachments[] =
432 {
433 *m_imageView,
434 *m_resolvedImageView
435 };
436
437 const VkFramebufferCreateInfo framebufferCreateInfo =
438 {
439 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
440 DE_NULL, // const void* pNext;
441 0u, // VkFramebufferCreateFlags flags;
442 *m_renderPass, // VkRenderPass renderPass;
443 m_multisampling ? 2u : 1u, // deUint32 attachmentCount;
444 attachments, // const VkImageView* pAttachments;
445 m_renderSize, // deUint32 width;
446 m_renderSize, // deUint32 height;
447 1u, // deUint32 layers;
448 };
449
450 m_frameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
451 }
452
453 // Uniform Buffer
454 {
455 const VkBufferCreateInfo bufferCreateInfo =
456 {
457 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
458 DE_NULL, // const void* pNext;
459 0u, // VkBufferCreateFlags flags;
460 m_uniformBufferSize, // VkDeviceSize size;
461 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, // VkBufferUsageFlags usage;
462 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
463 1u, // deUint32 queueFamilyIndexCount;
464 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
465 };
466
467 m_uniformBuffer = createBuffer(vkd, vkDevice, &bufferCreateInfo);
468 m_uniformBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
469
470 VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset()));
471 }
472
473 // Descriptors
474 {
475 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
476 m_descriptorPool = descriptorPoolBuilder.build(vkd, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
477
478 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
479 m_descriptorSetLayout = descriptorSetLayoutBuilder.build(vkd, vkDevice);
480
481 const VkDescriptorSetAllocateInfo descriptorSetParams =
482 {
483 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
484 DE_NULL,
485 *m_descriptorPool,
486 1u,
487 &m_descriptorSetLayout.get(),
488 };
489
490 m_descriptorSet = allocateDescriptorSet(vkd, vkDevice, &descriptorSetParams);
491
492 const VkDescriptorBufferInfo descriptorBufferInfo =
493 {
494 *m_uniformBuffer, // VkBuffer buffer;
495 0u, // VkDeviceSize offset;
496 VK_WHOLE_SIZE // VkDeviceSize range;
497 };
498
499 const VkWriteDescriptorSet writeDescritporSet =
500 {
501 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
502 DE_NULL, // const void* pNext;
503 *m_descriptorSet, // VkDescriptorSet destSet;
504 0, // deUint32 destBinding;
505 0, // deUint32 destArrayElement;
506 1u, // deUint32 count;
507 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType;
508 DE_NULL, // const VkDescriptorImageInfo* pImageInfo;
509 &descriptorBufferInfo, // const VkDescriptorBufferInfo* pBufferInfo;
510 DE_NULL // const VkBufferView* pTexelBufferView;
511 };
512
513 vkd.updateDescriptorSets(vkDevice, 1u, &writeDescritporSet, 0u, DE_NULL);
514 }
515
516 // Pipeline Layout
517 {
518 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
519 {
520 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
521 DE_NULL, // const void* pNext;
522 0u, // VkPipelineLayoutCreateFlags flags;
523 1u, // deUint32 descriptorSetCount;
524 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
525 0u, // deUint32 pushConstantRangeCount;
526 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
527 };
528
529 m_pipelineLayout = createPipelineLayout(vkd, vkDevice, &pipelineLayoutCreateInfo);
530 }
531
532 // Shaders
533 {
534 m_vertexShaderModule = createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("vertext_shader"), 0);
535 m_fragmentShaderModule = createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("fragment_shader"), 0);
536 }
537
538 // Result Buffer
539 {
540 const VkBufferCreateInfo bufferCreateInfo =
541 {
542 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
543 DE_NULL, // const void* pNext;
544 0u, // VkBufferCreateFlags flags;
545 m_resultBufferSize, // VkDeviceSize size;
546 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
547 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
548 1u, // deUint32 queueFamilyIndexCount;
549 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
550 };
551
552 m_resultBuffer = createBuffer(vkd, vkDevice, &bufferCreateInfo);
553 m_resultBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
554
555 VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
556 }
557
558 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Sample count = " << getSampleCountFlagsStr(m_sampleCount) << tcu::TestLog::EndMessage;
559 m_context.getTestContext().getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
560 }
561
~BaseRenderingTestInstance(void)562 BaseRenderingTestInstance::~BaseRenderingTestInstance (void)
563 {
564 }
565
566
addImageTransitionBarrier(VkCommandBuffer commandBuffer,VkImage image,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags srcAccessMask,VkAccessFlags dstAccessMask,VkImageLayout oldLayout,VkImageLayout newLayout) const567 void BaseRenderingTestInstance::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
568 {
569
570 const DeviceInterface& vkd = m_context.getDeviceInterface();
571
572 const VkImageSubresourceRange subResourcerange =
573 {
574 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
575 0, // deUint32 baseMipLevel;
576 1, // deUint32 levelCount;
577 0, // deUint32 baseArrayLayer;
578 1 // deUint32 layerCount;
579 };
580
581 const VkImageMemoryBarrier imageBarrier =
582 {
583 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
584 DE_NULL, // const void* pNext;
585 srcAccessMask, // VkAccessFlags srcAccessMask;
586 dstAccessMask, // VkAccessFlags dstAccessMask;
587 oldLayout, // VkImageLayout oldLayout;
588 newLayout, // VkImageLayout newLayout;
589 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
590 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
591 image, // VkImage image;
592 subResourcerange // VkImageSubresourceRange subresourceRange;
593 };
594
595 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
596 }
597
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,VkPrimitiveTopology primitiveTopology)598 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
599 {
600 // default to color white
601 const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
602
603 drawPrimitives(result, vertexData, colorData, primitiveTopology);
604 }
605
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & positionData,const std::vector<tcu::Vec4> & colorData,VkPrimitiveTopology primitiveTopology)606 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology)
607 {
608 const DeviceInterface& vkd = m_context.getDeviceInterface();
609 const VkDevice vkDevice = m_context.getDevice();
610 const VkQueue queue = m_context.getUniversalQueue();
611 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
612 Allocator& allocator = m_context.getDefaultAllocator();
613 const size_t attributeBatchSize = positionData.size() * sizeof(tcu::Vec4);
614
615 Move<VkCommandBuffer> commandBuffer;
616 Move<VkPipeline> graphicsPipeline;
617 Move<VkBuffer> vertexBuffer;
618 de::MovePtr<Allocation> vertexBufferMemory;
619 const VkPhysicalDeviceProperties properties = m_context.getDeviceProperties();
620
621 if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
622 {
623 std::stringstream message;
624 message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
625 TCU_THROW(NotSupportedError, message.str().c_str());
626 }
627
628 // Create Graphics Pipeline
629 {
630 const VkVertexInputBindingDescription vertexInputBindingDescription =
631 {
632 0u, // deUint32 binding;
633 sizeof(tcu::Vec4), // deUint32 strideInBytes;
634 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
635 };
636
637 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
638 {
639 {
640 0u, // deUint32 location;
641 0u, // deUint32 binding;
642 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
643 0u // deUint32 offsetInBytes;
644 },
645 {
646 1u, // deUint32 location;
647 0u, // deUint32 binding;
648 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
649 (deUint32)attributeBatchSize // deUint32 offsetInBytes;
650 }
651 };
652
653 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
654 {
655 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
656 DE_NULL, // const void* pNext;
657 0, // VkPipelineVertexInputStateCreateFlags flags;
658 1u, // deUint32 bindingCount;
659 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
660 2u, // deUint32 attributeCount;
661 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
662 };
663
664 const std::vector<VkViewport> viewports (1, makeViewport(tcu::UVec2(m_renderSize)));
665 const std::vector<VkRect2D> scissors (1, makeRect2D(tcu::UVec2(m_renderSize)));
666
667 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
668 {
669 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
670 DE_NULL, // const void* pNext;
671 0u, // VkPipelineMultisampleStateCreateFlags flags;
672 m_sampleCount, // VkSampleCountFlagBits rasterizationSamples;
673 VK_FALSE, // VkBool32 sampleShadingEnable;
674 0.0f, // float minSampleShading;
675 DE_NULL, // const VkSampleMask* pSampleMask;
676 VK_FALSE, // VkBool32 alphaToCoverageEnable;
677 VK_FALSE // VkBool32 alphaToOneEnable;
678 };
679
680 graphicsPipeline = makeGraphicsPipeline(vkd, // const DeviceInterface& vk
681 vkDevice, // const VkDevice device
682 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
683 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
684 DE_NULL, // const VkShaderModule tessellationControlShaderModule
685 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
686 DE_NULL, // const VkShaderModule geometryShaderModule
687 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
688 *m_renderPass, // const VkRenderPass renderPass
689 viewports, // const std::vector<VkViewport>& viewports
690 scissors, // const std::vector<VkRect2D>& scissors
691 primitiveTopology, // const VkPrimitiveTopology topology
692 0u, // const deUint32 subpass
693 0u, // const deUint32 patchControlPoints
694 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
695 getRasterizationStateCreateInfo(), // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
696 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
697 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo,
698 getColorBlendStateCreateInfo()); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
699 }
700
701 // Create Vertex Buffer
702 {
703 const VkBufferCreateInfo vertexBufferParams =
704 {
705 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
706 DE_NULL, // const void* pNext;
707 0u, // VkBufferCreateFlags flags;
708 attributeBatchSize * 2, // VkDeviceSize size;
709 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
710 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
711 1u, // deUint32 queueFamilyCount;
712 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
713 };
714
715 vertexBuffer = createBuffer(vkd, vkDevice, &vertexBufferParams);
716 vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
717
718 VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
719
720 // Load vertices into vertex buffer
721 deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
722 deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize);
723 flushAlloc(vkd, vkDevice, *vertexBufferMemory);
724 }
725
726 // Create Command Buffer
727 commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
728
729 // Begin Command Buffer
730 beginCommandBuffer(vkd, *commandBuffer);
731
732 addImageTransitionBarrier(*commandBuffer, *m_image,
733 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask
734 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask
735 0, // VkAccessFlags srcAccessMask
736 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
737 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
738 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // VkImageLayout newLayout;
739
740 if (m_multisampling) {
741 addImageTransitionBarrier(*commandBuffer, *m_resolvedImage,
742 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask
743 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask
744 0, // VkAccessFlags srcAccessMask
745 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
746 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
747 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // VkImageLayout newLayout;
748 }
749
750 // Begin Render Pass
751 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));
752
753 const VkDeviceSize vertexBufferOffset = 0;
754
755 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
756 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
757 vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
758 vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
759 endRenderPass(vkd, *commandBuffer);
760
761 // Copy Image
762 copyImageToBuffer(vkd, *commandBuffer, m_multisampling ? *m_resolvedImage : *m_image, *m_resultBuffer, tcu::IVec2(m_renderSize, m_renderSize));
763
764 endCommandBuffer(vkd, *commandBuffer);
765
766 // Set Point Size
767 {
768 float pointSize = getPointSize();
769 deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
770 flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
771 }
772
773 // Submit
774 submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
775
776 invalidateAlloc(vkd, vkDevice, *m_resultBufferMemory);
777 tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
778 }
779
getLineWidth(void) const780 float BaseRenderingTestInstance::getLineWidth (void) const
781 {
782 return 1.0f;
783 }
784
getPointSize(void) const785 float BaseRenderingTestInstance::getPointSize (void) const
786 {
787 return 1.0f;
788 }
789
getRasterizationStateCreateInfo(void) const790 const VkPipelineRasterizationStateCreateInfo* BaseRenderingTestInstance::getRasterizationStateCreateInfo (void) const
791 {
792 static VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
793 {
794 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
795 DE_NULL, // const void* pNext;
796 0, // VkPipelineRasterizationStateCreateFlags flags;
797 false, // VkBool32 depthClipEnable;
798 false, // VkBool32 rasterizerDiscardEnable;
799 VK_POLYGON_MODE_FILL, // VkFillMode fillMode;
800 VK_CULL_MODE_NONE, // VkCullMode cullMode;
801 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
802 VK_FALSE, // VkBool32 depthBiasEnable;
803 0.0f, // float depthBias;
804 0.0f, // float depthBiasClamp;
805 0.0f, // float slopeScaledDepthBias;
806 getLineWidth(), // float lineWidth;
807 };
808
809 rasterizationStateCreateInfo.lineWidth = getLineWidth();
810 return &rasterizationStateCreateInfo;
811 }
812
getColorBlendStateCreateInfo(void) const813 const VkPipelineColorBlendStateCreateInfo* BaseRenderingTestInstance::getColorBlendStateCreateInfo (void) const
814 {
815 static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
816 {
817 false, // VkBool32 blendEnable;
818 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor;
819 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor;
820 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
821 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha;
822 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha;
823 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
824 (VK_COLOR_COMPONENT_R_BIT |
825 VK_COLOR_COMPONENT_G_BIT |
826 VK_COLOR_COMPONENT_B_BIT |
827 VK_COLOR_COMPONENT_A_BIT) // VkChannelFlags channelWriteMask;
828 };
829
830 static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
831 {
832 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
833 DE_NULL, // const void* pNext;
834 0, // VkPipelineColorBlendStateCreateFlags flags;
835 false, // VkBool32 logicOpEnable;
836 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
837 1u, // deUint32 attachmentCount;
838 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
839 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
840 };
841
842 return &colorBlendStateParams;
843 }
844
getTextureFormat(void) const845 const tcu::TextureFormat& BaseRenderingTestInstance::getTextureFormat (void) const
846 {
847 return m_textureFormat;
848 }
849
850 class BaseTriangleTestInstance : public BaseRenderingTestInstance
851 {
852 public:
853 BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount);
854 virtual tcu::TestStatus iterate (void);
855
856 private:
857 virtual void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
858
859 int m_iteration;
860 const int m_iterationCount;
861 VkPrimitiveTopology m_primitiveTopology;
862 bool m_allIterationsPassed;
863 };
864
BaseTriangleTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,VkSampleCountFlagBits sampleCount)865 BaseTriangleTestInstance::BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount)
866 : BaseRenderingTestInstance (context, sampleCount)
867 , m_iteration (0)
868 , m_iterationCount (3)
869 , m_primitiveTopology (primitiveTopology)
870 , m_allIterationsPassed (true)
871 {
872 }
873
iterate(void)874 tcu::TestStatus BaseTriangleTestInstance::iterate (void)
875 {
876 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
877 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
878 tcu::Surface resultImage (m_renderSize, m_renderSize);
879 std::vector<tcu::Vec4> drawBuffer;
880 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
881
882 generateTriangles(m_iteration, drawBuffer, triangles);
883
884 // draw image
885 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
886
887 // compare
888 {
889 bool compareOk;
890 RasterizationArguments args;
891 TriangleSceneSpec scene;
892
893 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
894
895 args.numSamples = m_multisampling ? 1 : 0;
896 args.subpixelBits = m_subpixelBits;
897 args.redBits = colorBits[0];
898 args.greenBits = colorBits[1];
899 args.blueBits = colorBits[2];
900
901 scene.triangles.swap(triangles);
902
903 compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
904
905 if (!compareOk)
906 m_allIterationsPassed = false;
907 }
908
909 // result
910 if (++m_iteration == m_iterationCount)
911 {
912 if (m_allIterationsPassed)
913 return tcu::TestStatus::pass("Pass");
914 else
915 return tcu::TestStatus::fail("Incorrect rasterization");
916 }
917 else
918 return tcu::TestStatus::incomplete();
919 }
920
921 class BaseLineTestInstance : public BaseRenderingTestInstance
922 {
923 public:
924 BaseLineTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
925 virtual tcu::TestStatus iterate (void);
926 virtual float getLineWidth (void) const;
927
928 private:
929 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
930
931 int m_iteration;
932 const int m_iterationCount;
933 VkPrimitiveTopology m_primitiveTopology;
934 const PrimitiveWideness m_primitiveWideness;
935 bool m_allIterationsPassed;
936 float m_maxLineWidth;
937 std::vector<float> m_lineWidths;
938 };
939
BaseLineTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)940 BaseLineTestInstance::BaseLineTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
941 : BaseRenderingTestInstance (context, sampleCount)
942 , m_iteration (0)
943 , m_iterationCount (3)
944 , m_primitiveTopology (primitiveTopology)
945 , m_primitiveWideness (wideness)
946 , m_allIterationsPassed (true)
947 , m_maxLineWidth (1.0f)
948 {
949 DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
950
951 if (!context.getDeviceProperties().limits.strictLines)
952 TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
953
954 // create line widths
955 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
956 {
957 m_lineWidths.resize(m_iterationCount, 1.0f);
958 }
959 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
960 {
961 if (!m_context.getDeviceFeatures().wideLines)
962 TCU_THROW(NotSupportedError , "wide line support required");
963
964 const float* range = context.getDeviceProperties().limits.lineWidthRange;
965
966 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
967
968 // no wide line support
969 if (range[1] <= 1.0f)
970 TCU_THROW(NotSupportedError, "wide line support required");
971
972 // set hand picked sizes
973 m_lineWidths.push_back(5.0f);
974 m_lineWidths.push_back(10.0f);
975 m_lineWidths.push_back(range[1]);
976 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
977
978 m_maxLineWidth = range[1];
979 }
980 else
981 DE_ASSERT(false);
982 }
983
iterate(void)984 tcu::TestStatus BaseLineTestInstance::iterate (void)
985 {
986 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
987 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
988 const float lineWidth = getLineWidth();
989 tcu::Surface resultImage (m_renderSize, m_renderSize);
990 std::vector<tcu::Vec4> drawBuffer;
991 std::vector<LineSceneSpec::SceneLine> lines;
992
993 // supported?
994 if (lineWidth <= m_maxLineWidth)
995 {
996 // gen data
997 generateLines(m_iteration, drawBuffer, lines);
998
999 // draw image
1000 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1001
1002 // compare
1003 {
1004 RasterizationArguments args;
1005 LineSceneSpec scene;
1006
1007
1008 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1009
1010 args.numSamples = m_multisampling ? 1 : 0;
1011 args.subpixelBits = m_subpixelBits;
1012 args.redBits = colorBits[0];
1013 args.greenBits = colorBits[1];
1014 args.blueBits = colorBits[2];
1015
1016 scene.lines.swap(lines);
1017 scene.lineWidth = lineWidth;
1018
1019 if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()))
1020 m_allIterationsPassed = false;
1021 }
1022 }
1023 else
1024 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1025
1026 // result
1027 if (++m_iteration == m_iterationCount)
1028 {
1029 if (m_allIterationsPassed)
1030 return tcu::TestStatus::pass("Pass");
1031 else
1032 return tcu::TestStatus::fail("Incorrect rasterization");
1033 }
1034 else
1035 return tcu::TestStatus::incomplete();
1036 }
1037
1038
getLineWidth(void) const1039 float BaseLineTestInstance::getLineWidth (void) const
1040 {
1041 return m_lineWidths[m_iteration];
1042 }
1043
1044
1045 class PointTestInstance : public BaseRenderingTestInstance
1046 {
1047 public:
1048 PointTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
1049 virtual tcu::TestStatus iterate (void);
1050 virtual float getPointSize (void) const;
1051
1052 private:
1053 virtual void generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
1054
1055 int m_iteration;
1056 const int m_iterationCount;
1057 const PrimitiveWideness m_primitiveWideness;
1058 bool m_allIterationsPassed;
1059 float m_maxPointSize;
1060 std::vector<float> m_pointSizes;
1061 };
1062
PointTestInstance(Context & context,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)1063 PointTestInstance::PointTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1064 : BaseRenderingTestInstance (context, sampleCount)
1065 , m_iteration (0)
1066 , m_iterationCount (3)
1067 , m_primitiveWideness (wideness)
1068 , m_allIterationsPassed (true)
1069 , m_maxPointSize (1.0f)
1070 {
1071 // create point sizes
1072 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1073 {
1074 m_pointSizes.resize(m_iterationCount, 1.0f);
1075 }
1076 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1077 {
1078 if (!m_context.getDeviceFeatures().largePoints)
1079 TCU_THROW(NotSupportedError , "large point support required");
1080
1081 const float* range = context.getDeviceProperties().limits.pointSizeRange;
1082
1083 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1084
1085 // no wide line support
1086 if (range[1] <= 1.0f)
1087 TCU_THROW(NotSupportedError , "wide point support required");
1088
1089 // set hand picked sizes
1090 m_pointSizes.push_back(10.0f);
1091 m_pointSizes.push_back(25.0f);
1092 m_pointSizes.push_back(range[1]);
1093 DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
1094
1095 m_maxPointSize = range[1];
1096 }
1097 else
1098 DE_ASSERT(false);
1099 }
1100
iterate(void)1101 tcu::TestStatus PointTestInstance::iterate (void)
1102 {
1103 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1104 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1105 const float pointSize = getPointSize();
1106 tcu::Surface resultImage (m_renderSize, m_renderSize);
1107 std::vector<tcu::Vec4> drawBuffer;
1108 std::vector<PointSceneSpec::ScenePoint> points;
1109
1110 // supported?
1111 if (pointSize <= m_maxPointSize)
1112 {
1113 // gen data
1114 generatePoints(m_iteration, drawBuffer, points);
1115
1116 // draw image
1117 drawPrimitives(resultImage, drawBuffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
1118
1119 // compare
1120 {
1121 bool compareOk;
1122 RasterizationArguments args;
1123 PointSceneSpec scene;
1124
1125 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1126
1127 args.numSamples = m_multisampling ? 1 : 0;
1128 args.subpixelBits = m_subpixelBits;
1129 args.redBits = colorBits[0];
1130 args.greenBits = colorBits[1];
1131 args.blueBits = colorBits[2];
1132
1133 scene.points.swap(points);
1134
1135 compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1136
1137 if (!compareOk)
1138 m_allIterationsPassed = false;
1139 }
1140 }
1141 else
1142 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1143
1144 // result
1145 if (++m_iteration == m_iterationCount)
1146 {
1147 if (m_allIterationsPassed)
1148 return tcu::TestStatus::pass("Pass");
1149 else
1150 return tcu::TestStatus::fail("Incorrect rasterization");
1151 }
1152 else
1153 return tcu::TestStatus::incomplete();
1154 }
1155
getPointSize(void) const1156 float PointTestInstance::getPointSize (void) const
1157 {
1158 return m_pointSizes[m_iteration];
1159 }
1160
generatePoints(int iteration,std::vector<tcu::Vec4> & outData,std::vector<PointSceneSpec::ScenePoint> & outPoints)1161 void PointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
1162 {
1163 outData.resize(6);
1164
1165 switch (iteration)
1166 {
1167 case 0:
1168 // \note: these values are chosen arbitrarily
1169 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f);
1170 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
1171 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f);
1172 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
1173 outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
1174 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f);
1175 break;
1176
1177 case 1:
1178 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1179 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1180 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1181 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1182 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
1183 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f);
1184 break;
1185
1186 case 2:
1187 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1188 outData[1] = tcu::Vec4( 0.3f, -0.9f, 0.0f, 1.0f);
1189 outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
1190 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f);
1191 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
1192 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f);
1193 break;
1194 }
1195
1196 outPoints.resize(outData.size());
1197 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1198 {
1199 outPoints[pointNdx].position = outData[pointNdx];
1200 outPoints[pointNdx].pointSize = getPointSize();
1201 }
1202
1203 // log
1204 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
1205 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1206 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
1207 }
1208
1209 template <typename ConcreteTestInstance>
1210 class BaseTestCase : public BaseRenderingTestCase
1211 {
1212 public:
BaseTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)1213 BaseTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1214 : BaseRenderingTestCase(context, name, description, sampleCount)
1215 {}
1216
createInstance(Context & context) const1217 virtual TestInstance* createInstance (Context& context) const
1218 {
1219 return new ConcreteTestInstance(context, m_sampleCount);
1220 }
1221 };
1222
1223 class TrianglesTestInstance : public BaseTriangleTestInstance
1224 {
1225 public:
TrianglesTestInstance(Context & context,VkSampleCountFlagBits sampleCount)1226 TrianglesTestInstance (Context& context, VkSampleCountFlagBits sampleCount)
1227 : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, sampleCount)
1228 {}
1229
1230 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1231 };
1232
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)1233 void TrianglesTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1234 {
1235 outData.resize(6);
1236
1237 switch (iteration)
1238 {
1239 case 0:
1240 // \note: these values are chosen arbitrarily
1241 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f);
1242 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
1243 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f);
1244 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
1245 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
1246 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f);
1247 break;
1248
1249 case 1:
1250 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1251 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1252 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1253 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1254 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
1255 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f);
1256 break;
1257
1258 case 2:
1259 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1260 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1261 outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
1262 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f);
1263 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
1264 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f);
1265 break;
1266 }
1267
1268 outTriangles.resize(2);
1269 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
1270 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false;
1271 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false;
1272
1273 outTriangles[1].positions[0] = outData[3]; outTriangles[1].sharedEdge[0] = false;
1274 outTriangles[1].positions[1] = outData[4]; outTriangles[1].sharedEdge[1] = false;
1275 outTriangles[1].positions[2] = outData[5]; outTriangles[1].sharedEdge[2] = false;
1276
1277 // log
1278 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
1279 for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
1280 {
1281 m_context.getTestContext().getLog()
1282 << tcu::TestLog::Message
1283 << "Triangle " << (triangleNdx+1) << ":"
1284 << "\n\t" << outTriangles[triangleNdx].positions[0]
1285 << "\n\t" << outTriangles[triangleNdx].positions[1]
1286 << "\n\t" << outTriangles[triangleNdx].positions[2]
1287 << tcu::TestLog::EndMessage;
1288 }
1289 }
1290
1291 class TriangleStripTestInstance : public BaseTriangleTestInstance
1292 {
1293 public:
TriangleStripTestInstance(Context & context,VkSampleCountFlagBits sampleCount)1294 TriangleStripTestInstance (Context& context, VkSampleCountFlagBits sampleCount)
1295 : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, sampleCount)
1296 {}
1297
1298 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1299 };
1300
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)1301 void TriangleStripTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1302 {
1303 outData.resize(5);
1304
1305 switch (iteration)
1306 {
1307 case 0:
1308 // \note: these values are chosen arbitrarily
1309 outData[0] = tcu::Vec4(-0.504f, 0.8f, 0.0f, 1.0f);
1310 outData[1] = tcu::Vec4(-0.2f, -0.2f, 0.0f, 1.0f);
1311 outData[2] = tcu::Vec4(-0.2f, 0.199f, 0.0f, 1.0f);
1312 outData[3] = tcu::Vec4( 0.5f, 0.201f, 0.0f, 1.0f);
1313 outData[4] = tcu::Vec4( 1.5f, 0.4f, 0.0f, 1.0f);
1314 break;
1315
1316 case 1:
1317 outData[0] = tcu::Vec4(-0.499f, 0.129f, 0.0f, 1.0f);
1318 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1319 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1320 outData[3] = tcu::Vec4( 0.11f, -0.31f, 0.0f, 1.0f);
1321 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
1322 break;
1323
1324 case 2:
1325 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1326 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1327 outData[2] = tcu::Vec4(-0.87f, -0.1f, 0.0f, 1.0f);
1328 outData[3] = tcu::Vec4(-0.11f, 0.19f, 0.0f, 1.0f);
1329 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
1330 break;
1331 }
1332
1333 outTriangles.resize(3);
1334 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
1335 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = true;
1336 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false;
1337
1338 outTriangles[1].positions[0] = outData[2]; outTriangles[1].sharedEdge[0] = true;
1339 outTriangles[1].positions[1] = outData[1]; outTriangles[1].sharedEdge[1] = false;
1340 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true;
1341
1342 outTriangles[2].positions[0] = outData[2]; outTriangles[2].sharedEdge[0] = true;
1343 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false;
1344 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false;
1345
1346 // log
1347 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1348 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1349 {
1350 m_context.getTestContext().getLog()
1351 << tcu::TestLog::Message
1352 << "\t" << outData[vtxNdx]
1353 << tcu::TestLog::EndMessage;
1354 }
1355 }
1356
1357 class TriangleFanTestInstance : public BaseTriangleTestInstance
1358 {
1359 public:
TriangleFanTestInstance(Context & context,VkSampleCountFlagBits sampleCount)1360 TriangleFanTestInstance (Context& context, VkSampleCountFlagBits sampleCount)
1361 : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, sampleCount)
1362 {}
1363
1364 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
1365 };
1366
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)1367 void TriangleFanTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
1368 {
1369 outData.resize(5);
1370
1371 switch (iteration)
1372 {
1373 case 0:
1374 // \note: these values are chosen arbitrarily
1375 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
1376 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
1377 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
1378 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
1379 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
1380 break;
1381
1382 case 1:
1383 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1384 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1385 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1386 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1387 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
1388 break;
1389
1390 case 2:
1391 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1392 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1393 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
1394 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1395 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
1396 break;
1397 }
1398
1399 outTriangles.resize(3);
1400 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false;
1401 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false;
1402 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = true;
1403
1404 outTriangles[1].positions[0] = outData[0]; outTriangles[1].sharedEdge[0] = true;
1405 outTriangles[1].positions[1] = outData[2]; outTriangles[1].sharedEdge[1] = false;
1406 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true;
1407
1408 outTriangles[2].positions[0] = outData[0]; outTriangles[2].sharedEdge[0] = true;
1409 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false;
1410 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false;
1411
1412 // log
1413 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1414 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1415 {
1416 m_context.getTestContext().getLog()
1417 << tcu::TestLog::Message
1418 << "\t" << outData[vtxNdx]
1419 << tcu::TestLog::EndMessage;
1420 }
1421 }
1422
1423 template <typename ConcreteTestInstance>
1424 class WidenessTestCase : public BaseRenderingTestCase
1425 {
1426 public:
WidenessTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)1427 WidenessTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1428 : BaseRenderingTestCase(context, name, description, sampleCount)
1429 , m_wideness(wideness)
1430 {}
1431
createInstance(Context & context) const1432 virtual TestInstance* createInstance (Context& context) const
1433 {
1434 return new ConcreteTestInstance(context, m_wideness, m_sampleCount);
1435 }
1436 protected:
1437 const PrimitiveWideness m_wideness;
1438 };
1439
1440 class LinesTestInstance : public BaseLineTestInstance
1441 {
1442 public:
LinesTestInstance(Context & context,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)1443 LinesTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1444 : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, sampleCount)
1445 {}
1446
1447 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1448 };
1449
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)1450 void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1451 {
1452 outData.resize(6);
1453
1454 switch (iteration)
1455 {
1456 case 0:
1457 // \note: these values are chosen arbitrarily
1458 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
1459 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
1460 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
1461 outData[3] = tcu::Vec4(-0.3f, 0.2f, 0.0f, 1.0f);
1462 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
1463 outData[5] = tcu::Vec4( 0.1f, 0.5f, 0.0f, 1.0f);
1464 break;
1465
1466 case 1:
1467 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1468 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1469 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1470 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1471 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f);
1472 outData[5] = tcu::Vec4( 0.18f, -0.2f, 0.0f, 1.0f);
1473 break;
1474
1475 case 2:
1476 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1477 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1478 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
1479 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1480 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f);
1481 outData[5] = tcu::Vec4( 0.8f, -0.7f, 0.0f, 1.0f);
1482 break;
1483 }
1484
1485 outLines.resize(3);
1486 outLines[0].positions[0] = outData[0];
1487 outLines[0].positions[1] = outData[1];
1488 outLines[1].positions[0] = outData[2];
1489 outLines[1].positions[1] = outData[3];
1490 outLines[2].positions[0] = outData[4];
1491 outLines[2].positions[1] = outData[5];
1492
1493 // log
1494 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
1495 for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
1496 {
1497 m_context.getTestContext().getLog()
1498 << tcu::TestLog::Message
1499 << "Line " << (lineNdx+1) << ":"
1500 << "\n\t" << outLines[lineNdx].positions[0]
1501 << "\n\t" << outLines[lineNdx].positions[1]
1502 << tcu::TestLog::EndMessage;
1503 }
1504 }
1505
1506 class LineStripTestInstance : public BaseLineTestInstance
1507 {
1508 public:
LineStripTestInstance(Context & context,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)1509 LineStripTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
1510 : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, sampleCount)
1511 {}
1512
1513 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1514 };
1515
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)1516 void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1517 {
1518 outData.resize(4);
1519
1520 switch (iteration)
1521 {
1522 case 0:
1523 // \note: these values are chosen arbitrarily
1524 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f);
1525 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f);
1526 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f);
1527 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f);
1528 break;
1529
1530 case 1:
1531 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1532 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f);
1533 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f);
1534 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1535 break;
1536
1537 case 2:
1538 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1539 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f);
1540 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f);
1541 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f);
1542 break;
1543 }
1544
1545 outLines.resize(3);
1546 outLines[0].positions[0] = outData[0];
1547 outLines[0].positions[1] = outData[1];
1548 outLines[1].positions[0] = outData[1];
1549 outLines[1].positions[1] = outData[2];
1550 outLines[2].positions[0] = outData[2];
1551 outLines[2].positions[1] = outData[3];
1552
1553 // log
1554 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1555 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1556 {
1557 m_context.getTestContext().getLog()
1558 << tcu::TestLog::Message
1559 << "\t" << outData[vtxNdx]
1560 << tcu::TestLog::EndMessage;
1561 }
1562 }
1563
1564 class FillRuleTestInstance : public BaseRenderingTestInstance
1565 {
1566 public:
1567 enum FillRuleCaseType
1568 {
1569 FILLRULECASE_BASIC = 0,
1570 FILLRULECASE_REVERSED,
1571 FILLRULECASE_CLIPPED_FULL,
1572 FILLRULECASE_CLIPPED_PARTIAL,
1573 FILLRULECASE_PROJECTED,
1574
1575 FILLRULECASE_LAST
1576 };
1577 FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount);
1578 virtual tcu::TestStatus iterate (void);
1579
1580 private:
1581
1582 virtual const VkPipelineColorBlendStateCreateInfo* getColorBlendStateCreateInfo (void) const;
1583 int getRenderSize (FillRuleCaseType type) const;
1584 int getNumIterations (FillRuleCaseType type) const;
1585 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const;
1586
1587 const FillRuleCaseType m_caseType;
1588 int m_iteration;
1589 const int m_iterationCount;
1590 bool m_allIterationsPassed;
1591
1592 };
1593
FillRuleTestInstance(Context & context,FillRuleCaseType type,VkSampleCountFlagBits sampleCount)1594 FillRuleTestInstance::FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount)
1595 : BaseRenderingTestInstance (context, sampleCount, getRenderSize(type))
1596 , m_caseType (type)
1597 , m_iteration (0)
1598 , m_iterationCount (getNumIterations(type))
1599 , m_allIterationsPassed (true)
1600 {
1601 DE_ASSERT(type < FILLRULECASE_LAST);
1602 }
1603
iterate(void)1604 tcu::TestStatus FillRuleTestInstance::iterate (void)
1605 {
1606 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1607 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1608 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1609 const int thresholdRed = 1 << (8 - colorBits[0]);
1610 const int thresholdGreen = 1 << (8 - colorBits[1]);
1611 const int thresholdBlue = 1 << (8 - colorBits[2]);
1612 tcu::Surface resultImage (m_renderSize, m_renderSize);
1613 std::vector<tcu::Vec4> drawBuffer;
1614
1615 generateTriangles(m_iteration, drawBuffer);
1616
1617 // draw image
1618 {
1619 const std::vector<tcu::Vec4> colorBuffer (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
1620
1621 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
1622
1623 drawPrimitives(resultImage, drawBuffer, colorBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1624 }
1625
1626 // verify no overdraw
1627 {
1628 const tcu::RGBA triangleColor = tcu::RGBA(127, 127, 127, 255);
1629 bool overdraw = false;
1630
1631 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
1632
1633 for (int y = 0; y < resultImage.getHeight(); ++y)
1634 for (int x = 0; x < resultImage.getWidth(); ++x)
1635 {
1636 const tcu::RGBA color = resultImage.getPixel(x, y);
1637
1638 // color values are greater than triangle color? Allow lower values for multisampled edges and background.
1639 if ((color.getRed() - triangleColor.getRed()) > thresholdRed ||
1640 (color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
1641 (color.getBlue() - triangleColor.getBlue()) > thresholdBlue)
1642 overdraw = true;
1643 }
1644
1645 // results
1646 if (!overdraw)
1647 m_context.getTestContext().getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
1648 else
1649 {
1650 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1651 m_allIterationsPassed = false;
1652 }
1653 }
1654
1655 // verify no missing fragments in the full viewport case
1656 if (m_caseType == FILLRULECASE_CLIPPED_FULL)
1657 {
1658 bool missingFragments = false;
1659
1660 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
1661
1662 for (int y = 0; y < resultImage.getHeight(); ++y)
1663 for (int x = 0; x < resultImage.getWidth(); ++x)
1664 {
1665 const tcu::RGBA color = resultImage.getPixel(x, y);
1666
1667 // black? (background)
1668 if (color.getRed() <= thresholdRed ||
1669 color.getGreen() <= thresholdGreen ||
1670 color.getBlue() <= thresholdBlue)
1671 missingFragments = true;
1672 }
1673
1674 // results
1675 if (!missingFragments)
1676 m_context.getTestContext().getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
1677 else
1678 {
1679 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1680
1681 m_allIterationsPassed = false;
1682 }
1683 }
1684
1685 m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1686 << tcu::TestLog::Image("Result", "Result", resultImage)
1687 << tcu::TestLog::EndImageSet;
1688
1689 // result
1690 if (++m_iteration == m_iterationCount)
1691 {
1692 if (m_allIterationsPassed)
1693 return tcu::TestStatus::pass("Pass");
1694 else
1695 return tcu::TestStatus::fail("Found invalid pixels");
1696 }
1697 else
1698 return tcu::TestStatus::incomplete();
1699 }
1700
getRenderSize(FillRuleCaseType type) const1701 int FillRuleTestInstance::getRenderSize (FillRuleCaseType type) const
1702 {
1703 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1704 return DEFAULT_RENDER_SIZE / 4;
1705 else
1706 return DEFAULT_RENDER_SIZE;
1707 }
1708
getNumIterations(FillRuleCaseType type) const1709 int FillRuleTestInstance::getNumIterations (FillRuleCaseType type) const
1710 {
1711 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1712 return 15;
1713 else
1714 return 2;
1715 }
1716
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData) const1717 void FillRuleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
1718 {
1719 switch (m_caseType)
1720 {
1721 case FILLRULECASE_BASIC:
1722 case FILLRULECASE_REVERSED:
1723 case FILLRULECASE_PROJECTED:
1724 {
1725 const int numRows = 4;
1726 const int numColumns = 4;
1727 const float quadSide = 0.15f;
1728 de::Random rnd (0xabcd);
1729
1730 outData.resize(6 * numRows * numColumns);
1731
1732 for (int col = 0; col < numColumns; ++col)
1733 for (int row = 0; row < numRows; ++row)
1734 {
1735 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);
1736 const float rotation = (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
1737 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1738 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x());
1739 const tcu::Vec2 quad[4] =
1740 {
1741 center + sideH + sideV,
1742 center + sideH - sideV,
1743 center - sideH - sideV,
1744 center - sideH + sideV,
1745 };
1746
1747 if (m_caseType == FILLRULECASE_BASIC)
1748 {
1749 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1750 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1751 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1752 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1753 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1754 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1755 }
1756 else if (m_caseType == FILLRULECASE_REVERSED)
1757 {
1758 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1759 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1760 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1761 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1762 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1763 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1764 }
1765 else if (m_caseType == FILLRULECASE_PROJECTED)
1766 {
1767 const float w0 = rnd.getFloat(0.1f, 4.0f);
1768 const float w1 = rnd.getFloat(0.1f, 4.0f);
1769 const float w2 = rnd.getFloat(0.1f, 4.0f);
1770 const float w3 = rnd.getFloat(0.1f, 4.0f);
1771
1772 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1773 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
1774 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1775 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1776 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1777 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
1778 }
1779 else
1780 DE_ASSERT(DE_FALSE);
1781 }
1782
1783 break;
1784 }
1785
1786 case FILLRULECASE_CLIPPED_PARTIAL:
1787 case FILLRULECASE_CLIPPED_FULL:
1788 {
1789 const float quadSide = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
1790 const tcu::Vec2 center = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
1791 const float rotation = (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
1792 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1793 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x());
1794 const tcu::Vec2 quad[4] =
1795 {
1796 center + sideH + sideV,
1797 center + sideH - sideV,
1798 center - sideH - sideV,
1799 center - sideH + sideV,
1800 };
1801
1802 outData.resize(6);
1803 outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1804 outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1805 outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1806 outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1807 outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1808 outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1809 break;
1810 }
1811
1812 default:
1813 DE_ASSERT(DE_FALSE);
1814 }
1815 }
1816
getColorBlendStateCreateInfo(void) const1817 const VkPipelineColorBlendStateCreateInfo* FillRuleTestInstance::getColorBlendStateCreateInfo (void) const
1818 {
1819 static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1820 {
1821 true, // VkBool32 blendEnable;
1822 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor;
1823 VK_BLEND_FACTOR_ONE, // VkBlend destBlendColor;
1824 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
1825 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha;
1826 VK_BLEND_FACTOR_ONE, // VkBlend destBlendAlpha;
1827 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
1828 (VK_COLOR_COMPONENT_R_BIT |
1829 VK_COLOR_COMPONENT_G_BIT |
1830 VK_COLOR_COMPONENT_B_BIT |
1831 VK_COLOR_COMPONENT_A_BIT) // VkChannelFlags channelWriteMask;
1832 };
1833
1834 static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1835 {
1836 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1837 DE_NULL, // const void* pNext;
1838 0, // VkPipelineColorBlendStateCreateFlags flags;
1839 false, // VkBool32 logicOpEnable;
1840 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1841 1u, // deUint32 attachmentCount;
1842 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
1843 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
1844 };
1845
1846 return &colorBlendStateParams;
1847 }
1848
1849
1850 class FillRuleTestCase : public BaseRenderingTestCase
1851 {
1852 public:
FillRuleTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,FillRuleTestInstance::FillRuleCaseType type,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)1853 FillRuleTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, FillRuleTestInstance::FillRuleCaseType type, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
1854 : BaseRenderingTestCase (context, name, description, sampleCount)
1855 , m_type (type)
1856 {}
1857
createInstance(Context & context) const1858 virtual TestInstance* createInstance (Context& context) const
1859 {
1860 return new FillRuleTestInstance(context, m_type, m_sampleCount);
1861 }
1862 protected:
1863 const FillRuleTestInstance::FillRuleCaseType m_type;
1864 };
1865
1866 class CullingTestInstance : public BaseRenderingTestInstance
1867 {
1868 public:
CullingTestInstance(Context & context,VkCullModeFlags cullMode,VkPrimitiveTopology primitiveTopology,VkFrontFace frontFace,VkPolygonMode polygonMode)1869 CullingTestInstance (Context& context, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode)
1870 : BaseRenderingTestInstance (context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
1871 , m_cullMode (cullMode)
1872 , m_primitiveTopology (primitiveTopology)
1873 , m_frontFace (frontFace)
1874 , m_polygonMode (polygonMode)
1875 , m_multisampling (true)
1876 {}
1877 virtual
1878 const VkPipelineRasterizationStateCreateInfo* getRasterizationStateCreateInfo (void) const;
1879
1880 tcu::TestStatus iterate (void);
1881
1882 private:
1883 void generateVertices (std::vector<tcu::Vec4>& outData) const;
1884 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
1885 void extractLines (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<LineSceneSpec::SceneLine>& outLines) const;
1886 void extractPoints (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<PointSceneSpec::ScenePoint>& outPoints) const;
1887 bool triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
1888
1889 const VkCullModeFlags m_cullMode;
1890 const VkPrimitiveTopology m_primitiveTopology;
1891 const VkFrontFace m_frontFace;
1892 const VkPolygonMode m_polygonMode;
1893 const bool m_multisampling;
1894 };
1895
1896
iterate(void)1897 tcu::TestStatus CullingTestInstance::iterate (void)
1898 {
1899 DE_ASSERT(m_polygonMode <= VK_POLYGON_MODE_POINT);
1900
1901 tcu::Surface resultImage (m_renderSize, m_renderSize);
1902 std::vector<tcu::Vec4> drawBuffer;
1903 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
1904 std::vector<PointSceneSpec::ScenePoint> points;
1905 std::vector<LineSceneSpec::SceneLine> lines;
1906
1907 const InstanceInterface& vk = m_context.getInstanceInterface();
1908 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1909 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(vk, physicalDevice);
1910
1911 if (!(deviceFeatures.fillModeNonSolid) && (m_polygonMode == VK_POLYGON_MODE_LINE || m_polygonMode == VK_POLYGON_MODE_POINT))
1912 TCU_THROW(NotSupportedError, "Wireframe fill modes are not supported");
1913
1914 // generate scene
1915 generateVertices(drawBuffer);
1916 extractTriangles(triangles, drawBuffer);
1917
1918 if (m_polygonMode == VK_POLYGON_MODE_LINE)
1919 extractLines(triangles ,lines);
1920 else if (m_polygonMode == VK_POLYGON_MODE_POINT)
1921 extractPoints(triangles, points);
1922
1923 // draw image
1924 {
1925 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting front face to " << m_frontFace << tcu::TestLog::EndMessage;
1926 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting cull face to " << m_cullMode << tcu::TestLog::EndMessage;
1927 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing test pattern (" << m_primitiveTopology << ")" << tcu::TestLog::EndMessage;
1928
1929 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1930 }
1931
1932 // compare
1933 {
1934 RasterizationArguments args;
1935 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1936 bool isCompareOk = false;
1937
1938 args.numSamples = m_multisampling ? 1 : 0;
1939 args.subpixelBits = m_subpixelBits;
1940 args.redBits = colorBits[0];
1941 args.greenBits = colorBits[1];
1942 args.blueBits = colorBits[2];
1943
1944 switch (m_polygonMode)
1945 {
1946 case VK_POLYGON_MODE_LINE:
1947 {
1948 LineSceneSpec scene;
1949 scene.lineWidth = 0;
1950 scene.lines.swap(lines);
1951 isCompareOk = verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1952 break;
1953 }
1954 case VK_POLYGON_MODE_POINT:
1955 {
1956 PointSceneSpec scene;
1957 scene.points.swap(points);
1958 isCompareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1959 break;
1960 }
1961 default:
1962 {
1963 TriangleSceneSpec scene;
1964 scene.triangles.swap(triangles);
1965 isCompareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), tcu::VERIFICATIONMODE_WEAK);
1966 break;
1967 }
1968 }
1969
1970 if (isCompareOk)
1971 return tcu::TestStatus::pass("Pass");
1972 else
1973 return tcu::TestStatus::fail("Incorrect rendering");
1974 }
1975 }
1976
generateVertices(std::vector<tcu::Vec4> & outData) const1977 void CullingTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
1978 {
1979 de::Random rnd(543210);
1980
1981 outData.resize(6);
1982 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1983 {
1984 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1985 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1986 outData[vtxNdx].z() = 0.0f;
1987 outData[vtxNdx].w() = 1.0f;
1988 }
1989 }
1990
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const1991 void CullingTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
1992 {
1993 const bool cullDirection = (m_cullMode == VK_CULL_MODE_FRONT_BIT) ^ (m_frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
1994
1995 // No triangles
1996 if (m_cullMode == VK_CULL_MODE_FRONT_AND_BACK)
1997 return;
1998
1999 switch (m_primitiveTopology)
2000 {
2001 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2002 {
2003 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2004 {
2005 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
2006 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
2007 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
2008
2009 if (triangleOrder(v0, v1, v2) != cullDirection)
2010 {
2011 TriangleSceneSpec::SceneTriangle tri;
2012 tri.positions[0] = v0; tri.sharedEdge[0] = false;
2013 tri.positions[1] = v1; tri.sharedEdge[1] = false;
2014 tri.positions[2] = v2; tri.sharedEdge[2] = false;
2015
2016 outTriangles.push_back(tri);
2017 }
2018 }
2019 break;
2020 }
2021
2022 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2023 {
2024 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2025 {
2026 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
2027 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
2028 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
2029
2030 if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
2031 {
2032 TriangleSceneSpec::SceneTriangle tri;
2033 tri.positions[0] = v0; tri.sharedEdge[0] = false;
2034 tri.positions[1] = v1; tri.sharedEdge[1] = false;
2035 tri.positions[2] = v2; tri.sharedEdge[2] = false;
2036
2037 outTriangles.push_back(tri);
2038 }
2039 }
2040 break;
2041 }
2042
2043 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2044 {
2045 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2046 {
2047 const tcu::Vec4& v0 = vertices[0];
2048 const tcu::Vec4& v1 = vertices[vtxNdx + 0];
2049 const tcu::Vec4& v2 = vertices[vtxNdx + 1];
2050
2051 if (triangleOrder(v0, v1, v2) != cullDirection)
2052 {
2053 TriangleSceneSpec::SceneTriangle tri;
2054 tri.positions[0] = v0; tri.sharedEdge[0] = false;
2055 tri.positions[1] = v1; tri.sharedEdge[1] = false;
2056 tri.positions[2] = v2; tri.sharedEdge[2] = false;
2057
2058 outTriangles.push_back(tri);
2059 }
2060 }
2061 break;
2062 }
2063
2064 default:
2065 DE_ASSERT(false);
2066 }
2067 }
2068
extractLines(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,std::vector<LineSceneSpec::SceneLine> & outLines) const2069 void CullingTestInstance::extractLines (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles,
2070 std::vector<LineSceneSpec::SceneLine>& outLines) const
2071 {
2072 for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
2073 {
2074 for (int vrtxNdx = 0; vrtxNdx < 2; ++vrtxNdx)
2075 {
2076 LineSceneSpec::SceneLine line;
2077 line.positions[0] = outTriangles.at(triNdx).positions[vrtxNdx];
2078 line.positions[1] = outTriangles.at(triNdx).positions[vrtxNdx + 1];
2079
2080 outLines.push_back(line);
2081 }
2082 LineSceneSpec::SceneLine line;
2083 line.positions[0] = outTriangles.at(triNdx).positions[2];
2084 line.positions[1] = outTriangles.at(triNdx).positions[0];
2085 outLines.push_back(line);
2086 }
2087 }
2088
extractPoints(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,std::vector<PointSceneSpec::ScenePoint> & outPoints) const2089 void CullingTestInstance::extractPoints (std::vector<TriangleSceneSpec::SceneTriangle> &outTriangles,
2090 std::vector<PointSceneSpec::ScenePoint> &outPoints) const
2091 {
2092 for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
2093 {
2094 for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
2095 {
2096 PointSceneSpec::ScenePoint point;
2097 point.position = outTriangles.at(triNdx).positions[vrtxNdx];
2098 point.pointSize = 1.0f;
2099
2100 outPoints.push_back(point);
2101 }
2102 }
2103 }
2104
triangleOrder(const tcu::Vec4 & v0,const tcu::Vec4 & v1,const tcu::Vec4 & v2) const2105 bool CullingTestInstance::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
2106 {
2107 const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
2108 const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
2109 const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
2110
2111 // cross
2112 return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) > 0;
2113 }
2114
2115
getRasterizationStateCreateInfo(void) const2116 const VkPipelineRasterizationStateCreateInfo* CullingTestInstance::getRasterizationStateCreateInfo (void) const
2117 {
2118 static VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
2119 {
2120 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2121 DE_NULL, // const void* pNext;
2122 0, // VkPipelineRasterizationStateCreateFlags flags;
2123 false, // VkBool32 depthClipEnable;
2124 false, // VkBool32 rasterizerDiscardEnable;
2125 VK_POLYGON_MODE_FILL, // VkFillMode fillMode;
2126 VK_CULL_MODE_NONE, // VkCullMode cullMode;
2127 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
2128 VK_FALSE, // VkBool32 depthBiasEnable;
2129 0.0f, // float depthBias;
2130 0.0f, // float depthBiasClamp;
2131 0.0f, // float slopeScaledDepthBias;
2132 getLineWidth(), // float lineWidth;
2133 };
2134
2135 rasterizationStateCreateInfo.lineWidth = getLineWidth();
2136 rasterizationStateCreateInfo.cullMode = m_cullMode;
2137 rasterizationStateCreateInfo.frontFace = m_frontFace;
2138 rasterizationStateCreateInfo.polygonMode = m_polygonMode;
2139
2140 return &rasterizationStateCreateInfo;
2141 }
2142
2143 class CullingTestCase : public BaseRenderingTestCase
2144 {
2145 public:
CullingTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkCullModeFlags cullMode,VkPrimitiveTopology primitiveTopology,VkFrontFace frontFace,VkPolygonMode polygonMode,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)2146 CullingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2147 : BaseRenderingTestCase (context, name, description, sampleCount)
2148 , m_cullMode (cullMode)
2149 , m_primitiveTopology (primitiveTopology)
2150 , m_frontFace (frontFace)
2151 , m_polygonMode (polygonMode)
2152 {}
2153
createInstance(Context & context) const2154 virtual TestInstance* createInstance (Context& context) const
2155 {
2156 return new CullingTestInstance(context, m_cullMode, m_primitiveTopology, m_frontFace, m_polygonMode);
2157 }
2158 protected:
2159 const VkCullModeFlags m_cullMode;
2160 const VkPrimitiveTopology m_primitiveTopology;
2161 const VkFrontFace m_frontFace;
2162 const VkPolygonMode m_polygonMode;
2163 };
2164
2165 class DiscardTestInstance : public BaseRenderingTestInstance
2166 {
2167 public:
DiscardTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,deBool queryFragmentShaderInvocations)2168 DiscardTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations)
2169 : BaseRenderingTestInstance (context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE)
2170 , m_primitiveTopology (primitiveTopology)
2171 , m_queryFragmentShaderInvocations (queryFragmentShaderInvocations)
2172 {}
2173
2174 virtual const VkPipelineRasterizationStateCreateInfo* getRasterizationStateCreateInfo (void) const;
2175 tcu::TestStatus iterate (void);
2176
2177 private:
2178 void generateVertices (std::vector<tcu::Vec4>& outData) const;
2179 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
2180 void extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const;
2181 void extractPoints (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const;
2182 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool);
2183
2184 const VkPrimitiveTopology m_primitiveTopology;
2185 const deBool m_queryFragmentShaderInvocations;
2186 };
2187
iterate(void)2188 tcu::TestStatus DiscardTestInstance::iterate (void)
2189 {
2190 const DeviceInterface& vkd = m_context.getDeviceInterface();
2191 const VkDevice vkDevice = m_context.getDevice();
2192 deUint64 queryResult = 0u;
2193 tcu::Surface resultImage (m_renderSize, m_renderSize);
2194 std::vector<tcu::Vec4> drawBuffer;
2195 std::vector<PointSceneSpec::ScenePoint> points;
2196 std::vector<LineSceneSpec::SceneLine> lines;
2197 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
2198
2199 generateVertices(drawBuffer);
2200
2201 switch (m_primitiveTopology)
2202 {
2203 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2204 extractPoints(points, drawBuffer);
2205 break;
2206
2207 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2208 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2209 extractLines(lines, drawBuffer);
2210 break;
2211
2212 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2213 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2214 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2215 extractTriangles(triangles, drawBuffer);
2216 break;
2217
2218 default:
2219 DE_ASSERT(false);
2220 }
2221
2222 const VkQueryPoolCreateInfo queryPoolCreateInfo =
2223 {
2224 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType
2225 DE_NULL, // const void* pNext
2226 (VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags
2227 VK_QUERY_TYPE_PIPELINE_STATISTICS , // VkQueryType queryType
2228 1u, // deUint32 entryCount
2229 VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT, // VkQueryPipelineStatisticFlags pipelineStatistics
2230 };
2231
2232 if (m_queryFragmentShaderInvocations)
2233 {
2234 Move<VkQueryPool> queryPool = createQueryPool(vkd, vkDevice, &queryPoolCreateInfo);
2235
2236 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology, queryPool);
2237 vkd.getQueryPoolResults(vkDevice, *queryPool, 0u, 1u, sizeof(deUint64), &queryResult, 0u, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
2238 }
2239 else
2240 BaseRenderingTestInstance::drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
2241
2242 // compare
2243 {
2244 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
2245
2246 const RasterizationArguments args =
2247 {
2248 0, // int numSamples;
2249 (int)m_subpixelBits, // int subpixelBits;
2250 colorBits[0], // int redBits;
2251 colorBits[1], // int greenBits;
2252 colorBits[2] // int blueBits;
2253 };
2254
2255 // Empty scene to compare to, primitives should be discarded before rasterization
2256 TriangleSceneSpec scene;
2257
2258 const bool isCompareOk = verifyTriangleGroupRasterization(resultImage,
2259 scene,
2260 args,
2261 m_context.getTestContext().getLog(),
2262 tcu::VERIFICATIONMODE_STRICT);
2263
2264 if (isCompareOk)
2265 {
2266 if (m_queryFragmentShaderInvocations && queryResult > 0u)
2267 return tcu::TestStatus::fail("Fragment shader invocations occured");
2268 else
2269 return tcu::TestStatus::pass("Pass");
2270 }
2271 else
2272 return tcu::TestStatus::fail("Incorrect rendering");
2273 }
2274 }
2275
generateVertices(std::vector<tcu::Vec4> & outData) const2276 void DiscardTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
2277 {
2278 de::Random rnd(12345);
2279
2280 outData.resize(6);
2281
2282 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
2283 {
2284 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2285 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2286 outData[vtxNdx].z() = 0.0f;
2287 outData[vtxNdx].w() = 1.0f;
2288 }
2289 }
2290
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const2291 void DiscardTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
2292 {
2293 switch (m_primitiveTopology)
2294 {
2295 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2296 {
2297 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2298 {
2299 TriangleSceneSpec::SceneTriangle tri;
2300 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
2301 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
2302 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
2303
2304 tri.positions[0] = v0;
2305 tri.positions[1] = v1;
2306 tri.positions[2] = v2;
2307
2308 outTriangles.push_back(tri);
2309 }
2310
2311 break;
2312 }
2313
2314 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2315 {
2316 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2317 {
2318 TriangleSceneSpec::SceneTriangle tri;
2319 const tcu::Vec4& v0 = vertices[vtxNdx + 0];
2320 const tcu::Vec4& v1 = vertices[vtxNdx + 1];
2321 const tcu::Vec4& v2 = vertices[vtxNdx + 2];
2322
2323 tri.positions[0] = v0;
2324 tri.positions[1] = v1;
2325 tri.positions[2] = v2;
2326
2327 outTriangles.push_back(tri);
2328 }
2329
2330 break;
2331 }
2332
2333 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2334 {
2335 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2336 {
2337 TriangleSceneSpec::SceneTriangle tri;
2338 const tcu::Vec4& v0 = vertices[0];
2339 const tcu::Vec4& v1 = vertices[vtxNdx + 0];
2340 const tcu::Vec4& v2 = vertices[vtxNdx + 1];
2341
2342 tri.positions[0] = v0;
2343 tri.positions[1] = v1;
2344 tri.positions[2] = v2;
2345
2346 outTriangles.push_back(tri);
2347 }
2348
2349 break;
2350 }
2351
2352 default:
2353 DE_ASSERT(false);
2354 }
2355 }
2356
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices) const2357 void DiscardTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const
2358 {
2359 switch (m_primitiveTopology)
2360 {
2361 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2362 {
2363 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
2364 {
2365 LineSceneSpec::SceneLine line;
2366
2367 line.positions[0] = vertices[vtxNdx + 0];
2368 line.positions[1] = vertices[vtxNdx + 1];
2369
2370 outLines.push_back(line);
2371 }
2372
2373 break;
2374 }
2375
2376 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2377 {
2378 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2379 {
2380 LineSceneSpec::SceneLine line;
2381
2382 line.positions[0] = vertices[vtxNdx + 0];
2383 line.positions[1] = vertices[vtxNdx + 1];
2384
2385 outLines.push_back(line);
2386 }
2387
2388 break;
2389 }
2390
2391 default:
2392 DE_ASSERT(false);
2393 }
2394 }
2395
extractPoints(std::vector<PointSceneSpec::ScenePoint> & outPoints,const std::vector<tcu::Vec4> & vertices) const2396 void DiscardTestInstance::extractPoints (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const
2397 {
2398 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
2399 {
2400 for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
2401 {
2402 PointSceneSpec::ScenePoint point;
2403
2404 point.position = vertices[vrtxNdx];
2405 point.pointSize = 1.0f;
2406
2407 outPoints.push_back(point);
2408 }
2409 }
2410 }
2411
getRasterizationStateCreateInfo(void) const2412 const VkPipelineRasterizationStateCreateInfo* DiscardTestInstance::getRasterizationStateCreateInfo (void) const
2413 {
2414 static const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
2415 {
2416 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2417 NULL, // const void* pNext;
2418 0, // VkPipelineRasterizationStateCreateFlags flags;
2419 VK_FALSE, // VkBool32 depthClipEnable;
2420 VK_TRUE, // VkBool32 rasterizerDiscardEnable;
2421 VK_POLYGON_MODE_FILL, // VkFillMode fillMode;
2422 VK_CULL_MODE_NONE, // VkCullMode cullMode;
2423 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
2424 VK_FALSE, // VkBool32 depthBiasEnable;
2425 0.0f, // float depthBias;
2426 0.0f, // float depthBiasClamp;
2427 0.0f, // float slopeScaledDepthBias;
2428 getLineWidth(), // float lineWidth;
2429 };
2430
2431 return &rasterizationStateCreateInfo;
2432 }
2433
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & positionData,VkPrimitiveTopology primitiveTopology,Move<VkQueryPool> & queryPool)2434 void DiscardTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool)
2435 {
2436 const DeviceInterface& vkd = m_context.getDeviceInterface();
2437 const VkDevice vkDevice = m_context.getDevice();
2438 const VkPhysicalDeviceProperties properties = m_context.getDeviceProperties();
2439 const VkQueue queue = m_context.getUniversalQueue();
2440 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2441 Allocator& allocator = m_context.getDefaultAllocator();
2442
2443 const size_t attributeBatchSize = positionData.size() * sizeof(tcu::Vec4);
2444 const VkDeviceSize vertexBufferOffset = 0;
2445 de::MovePtr<Allocation> vertexBufferMemory;
2446 Move<VkBuffer> vertexBuffer;
2447 Move<VkCommandBuffer> commandBuffer;
2448 Move<VkPipeline> graphicsPipeline;
2449
2450 if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
2451 {
2452 std::stringstream message;
2453 message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
2454 TCU_THROW(NotSupportedError, message.str().c_str());
2455 }
2456
2457 // Create Graphics Pipeline
2458 {
2459 const VkVertexInputBindingDescription vertexInputBindingDescription =
2460 {
2461 0u, // deUint32 binding;
2462 sizeof(tcu::Vec4), // deUint32 strideInBytes;
2463 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
2464 };
2465
2466 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
2467 {
2468 {
2469 0u, // deUint32 location;
2470 0u, // deUint32 binding;
2471 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
2472 0u // deUint32 offsetInBytes;
2473 },
2474 {
2475 1u, // deUint32 location;
2476 0u, // deUint32 binding;
2477 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
2478 (deUint32)attributeBatchSize // deUint32 offsetInBytes;
2479 }
2480 };
2481
2482 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
2483 {
2484 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
2485 DE_NULL, // const void* pNext;
2486 0, // VkPipelineVertexInputStateCreateFlags flags;
2487 1u, // deUint32 bindingCount;
2488 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2489 2u, // deUint32 attributeCount;
2490 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
2491 };
2492
2493 const std::vector<VkViewport> viewports (1, makeViewport(tcu::UVec2(m_renderSize)));
2494 const std::vector<VkRect2D> scissors (1, makeRect2D(tcu::UVec2(m_renderSize)));
2495
2496 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
2497 {
2498 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2499 DE_NULL, // const void* pNext;
2500 0u, // VkPipelineMultisampleStateCreateFlags flags;
2501 m_sampleCount, // VkSampleCountFlagBits rasterizationSamples;
2502 VK_FALSE, // VkBool32 sampleShadingEnable;
2503 0.0f, // float minSampleShading;
2504 DE_NULL, // const VkSampleMask* pSampleMask;
2505 VK_FALSE, // VkBool32 alphaToCoverageEnable;
2506 VK_FALSE // VkBool32 alphaToOneEnable;
2507 };
2508
2509 graphicsPipeline = makeGraphicsPipeline(vkd, // const DeviceInterface& vk
2510 vkDevice, // const VkDevice device
2511 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
2512 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
2513 DE_NULL, // const VkShaderModule tessellationControlShaderModule
2514 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
2515 DE_NULL, // const VkShaderModule geometryShaderModule
2516 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
2517 *m_renderPass, // const VkRenderPass renderPass
2518 viewports, // const std::vector<VkViewport>& viewports
2519 scissors, // const std::vector<VkRect2D>& scissors
2520 primitiveTopology, // const VkPrimitiveTopology topology
2521 0u, // const deUint32 subpass
2522 0u, // const deUint32 patchControlPoints
2523 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
2524 getRasterizationStateCreateInfo(), // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
2525 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
2526 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo,
2527 getColorBlendStateCreateInfo()); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
2528 }
2529
2530 // Create Vertex Buffer
2531 {
2532 const VkBufferCreateInfo vertexBufferParams =
2533 {
2534 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
2535 DE_NULL, // const void* pNext;
2536 0u, // VkBufferCreateFlags flags;
2537 attributeBatchSize * 2, // VkDeviceSize size;
2538 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
2539 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
2540 1u, // deUint32 queueFamilyCount;
2541 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
2542 };
2543
2544 const std::vector<tcu::Vec4> colorData (positionData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
2545
2546 vertexBuffer = createBuffer(vkd, vkDevice, &vertexBufferParams);
2547 vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
2548
2549 VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
2550
2551 // Load vertices into vertex buffer
2552 deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
2553 deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize);
2554 flushAlloc(vkd, vkDevice, *vertexBufferMemory);
2555 }
2556
2557 // Create Command Buffer
2558 commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2559
2560 // Begin Command Buffer
2561 beginCommandBuffer(vkd, *commandBuffer);
2562
2563 addImageTransitionBarrier(*commandBuffer, // VkCommandBuffer commandBuffer
2564 *m_image, // VkImage image
2565 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask
2566 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask
2567 0, // VkAccessFlags srcAccessMask
2568 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
2569 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
2570 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // VkImageLayout newLayout;
2571
2572 if (m_multisampling)
2573 {
2574 addImageTransitionBarrier(*commandBuffer, // VkCommandBuffer commandBuffer
2575 *m_resolvedImage, // VkImage image
2576 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask
2577 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask
2578 0, // VkAccessFlags srcAccessMask
2579 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask
2580 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
2581 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // VkImageLayout newLayout;
2582 }
2583
2584 // Reset query pool
2585 vkd.cmdResetQueryPool(*commandBuffer, *queryPool, 0u, 1u);
2586
2587 // Begin render pass and start query
2588 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));
2589 vkd.cmdBeginQuery(*commandBuffer, *queryPool, 0u, (VkQueryControlFlags)0u);
2590 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
2591 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
2592 vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
2593 vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
2594 endRenderPass(vkd, *commandBuffer);
2595 vkd.cmdEndQuery(*commandBuffer, *queryPool, 0u);
2596
2597 // Copy Image
2598 copyImageToBuffer(vkd, *commandBuffer, m_multisampling ? *m_resolvedImage : *m_image, *m_resultBuffer, tcu::IVec2(m_renderSize, m_renderSize));
2599
2600 endCommandBuffer(vkd, *commandBuffer);
2601
2602 // Set Point Size
2603 {
2604 float pointSize = getPointSize();
2605
2606 deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
2607 flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
2608 }
2609
2610 // Submit
2611 submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
2612
2613 invalidateAlloc(vkd, vkDevice, *m_resultBufferMemory);
2614 tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
2615 }
2616
2617 class DiscardTestCase : public BaseRenderingTestCase
2618 {
2619 public:
DiscardTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,deBool queryFragmentShaderInvocations,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)2620 DiscardTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2621 : BaseRenderingTestCase (context, name, description, sampleCount)
2622 , m_primitiveTopology (primitiveTopology)
2623 , m_queryFragmentShaderInvocations (queryFragmentShaderInvocations)
2624 {}
2625
createInstance(Context & context) const2626 virtual TestInstance* createInstance (Context& context) const
2627 {
2628 if (m_queryFragmentShaderInvocations && !context.getDeviceFeatures().pipelineStatisticsQuery)
2629 throw tcu::NotSupportedError("Pipeline statistics queries are not supported");
2630
2631 return new DiscardTestInstance (context, m_primitiveTopology, m_queryFragmentShaderInvocations);
2632 }
2633
2634 protected:
2635 const VkPrimitiveTopology m_primitiveTopology;
2636 const deBool m_queryFragmentShaderInvocations;
2637 };
2638
2639 class TriangleInterpolationTestInstance : public BaseRenderingTestInstance
2640 {
2641 public:
2642
TriangleInterpolationTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,int flags,VkSampleCountFlagBits sampleCount)2643 TriangleInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount)
2644 : BaseRenderingTestInstance (context, sampleCount, DEFAULT_RENDER_SIZE)
2645 , m_primitiveTopology (primitiveTopology)
2646 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
2647 , m_iterationCount (3)
2648 , m_iteration (0)
2649 , m_allIterationsPassed (true)
2650 , m_flatshade ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2651 {}
2652
2653 tcu::TestStatus iterate (void);
2654
2655
2656 private:
2657 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
2658 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
2659
2660
2661 VkPrimitiveTopology m_primitiveTopology;
2662 const bool m_projective;
2663 const int m_iterationCount;
2664 int m_iteration;
2665 bool m_allIterationsPassed;
2666 const deBool m_flatshade;
2667 };
2668
iterate(void)2669 tcu::TestStatus TriangleInterpolationTestInstance::iterate (void)
2670 {
2671 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
2672 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
2673 tcu::Surface resultImage (m_renderSize, m_renderSize);
2674 std::vector<tcu::Vec4> drawBuffer;
2675 std::vector<tcu::Vec4> colorBuffer;
2676 std::vector<TriangleSceneSpec::SceneTriangle> triangles;
2677
2678 // generate scene
2679 generateVertices(m_iteration, drawBuffer, colorBuffer);
2680 extractTriangles(triangles, drawBuffer, colorBuffer);
2681
2682 // log
2683 {
2684 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
2685 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2686 m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2687 }
2688
2689 // draw image
2690 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
2691
2692 // compare
2693 {
2694 RasterizationArguments args;
2695 TriangleSceneSpec scene;
2696 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
2697
2698 args.numSamples = m_multisampling ? 1 : 0;
2699 args.subpixelBits = m_subpixelBits;
2700 args.redBits = colorBits[0];
2701 args.greenBits = colorBits[1];
2702 args.blueBits = colorBits[2];
2703
2704 scene.triangles.swap(triangles);
2705
2706 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
2707 m_allIterationsPassed = false;
2708 }
2709
2710 // result
2711 if (++m_iteration == m_iterationCount)
2712 {
2713 if (m_allIterationsPassed)
2714 return tcu::TestStatus::pass("Pass");
2715 else
2716 return tcu::TestStatus::fail("Found invalid pixel values");
2717 }
2718 else
2719 return tcu::TestStatus::incomplete();
2720 }
2721
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const2722 void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
2723 {
2724 // use only red, green and blue
2725 const tcu::Vec4 colors[] =
2726 {
2727 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2728 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2729 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
2730 };
2731
2732 de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
2733
2734 outVertices.resize(6);
2735 outColors.resize(6);
2736
2737 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
2738 {
2739 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2740 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2741 outVertices[vtxNdx].z() = 0.0f;
2742
2743 if (!m_projective)
2744 outVertices[vtxNdx].w() = 1.0f;
2745 else
2746 {
2747 const float w = rnd.getFloat(0.2f, 4.0f);
2748
2749 outVertices[vtxNdx].x() *= w;
2750 outVertices[vtxNdx].y() *= w;
2751 outVertices[vtxNdx].z() *= w;
2752 outVertices[vtxNdx].w() = w;
2753 }
2754
2755 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
2756 }
2757 }
2758
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const2759 void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
2760 {
2761 switch (m_primitiveTopology)
2762 {
2763 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2764 {
2765 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
2766 {
2767 TriangleSceneSpec::SceneTriangle tri;
2768 tri.positions[0] = vertices[vtxNdx + 0];
2769 tri.positions[1] = vertices[vtxNdx + 1];
2770 tri.positions[2] = vertices[vtxNdx + 2];
2771 tri.sharedEdge[0] = false;
2772 tri.sharedEdge[1] = false;
2773 tri.sharedEdge[2] = false;
2774
2775 if (m_flatshade)
2776 {
2777 tri.colors[0] = colors[vtxNdx];
2778 tri.colors[1] = colors[vtxNdx];
2779 tri.colors[2] = colors[vtxNdx];
2780 }
2781 else
2782 {
2783 tri.colors[0] = colors[vtxNdx + 0];
2784 tri.colors[1] = colors[vtxNdx + 1];
2785 tri.colors[2] = colors[vtxNdx + 2];
2786 }
2787
2788 outTriangles.push_back(tri);
2789 }
2790 break;
2791 }
2792
2793 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2794 {
2795 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
2796 {
2797 TriangleSceneSpec::SceneTriangle tri;
2798 tri.positions[0] = vertices[vtxNdx + 0];
2799 tri.positions[1] = vertices[vtxNdx + 1];
2800 tri.positions[2] = vertices[vtxNdx + 2];
2801 tri.sharedEdge[0] = false;
2802 tri.sharedEdge[1] = false;
2803 tri.sharedEdge[2] = false;
2804
2805 if (m_flatshade)
2806 {
2807 tri.colors[0] = colors[vtxNdx];
2808 tri.colors[1] = colors[vtxNdx];
2809 tri.colors[2] = colors[vtxNdx];
2810 }
2811 else
2812 {
2813 tri.colors[0] = colors[vtxNdx + 0];
2814 tri.colors[1] = colors[vtxNdx + 1];
2815 tri.colors[2] = colors[vtxNdx + 2];
2816 }
2817
2818 outTriangles.push_back(tri);
2819 }
2820 break;
2821 }
2822
2823 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2824 {
2825 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2826 {
2827 TriangleSceneSpec::SceneTriangle tri;
2828 tri.positions[0] = vertices[0];
2829 tri.positions[1] = vertices[vtxNdx + 0];
2830 tri.positions[2] = vertices[vtxNdx + 1];
2831 tri.sharedEdge[0] = false;
2832 tri.sharedEdge[1] = false;
2833 tri.sharedEdge[2] = false;
2834
2835 if (m_flatshade)
2836 {
2837 tri.colors[0] = colors[vtxNdx];
2838 tri.colors[1] = colors[vtxNdx];
2839 tri.colors[2] = colors[vtxNdx];
2840 }
2841 else
2842 {
2843 tri.colors[0] = colors[0];
2844 tri.colors[1] = colors[vtxNdx + 0];
2845 tri.colors[2] = colors[vtxNdx + 1];
2846 }
2847
2848 outTriangles.push_back(tri);
2849 }
2850 break;
2851 }
2852
2853 default:
2854 DE_ASSERT(false);
2855 }
2856 }
2857
2858 class TriangleInterpolationTestCase : public BaseRenderingTestCase
2859 {
2860 public:
TriangleInterpolationTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,int flags,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)2861 TriangleInterpolationTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2862 : BaseRenderingTestCase (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2863 , m_primitiveTopology (primitiveTopology)
2864 , m_flags (flags)
2865 {}
2866
createInstance(Context & context) const2867 virtual TestInstance* createInstance (Context& context) const
2868 {
2869 return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount);
2870 }
2871 protected:
2872 const VkPrimitiveTopology m_primitiveTopology;
2873 const int m_flags;
2874 };
2875
2876 class LineInterpolationTestInstance : public BaseRenderingTestInstance
2877 {
2878 public:
2879 LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount);
2880
2881 virtual tcu::TestStatus iterate (void);
2882
2883 private:
2884 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
2885 void extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
2886 virtual float getLineWidth (void) const;
2887
2888 VkPrimitiveTopology m_primitiveTopology;
2889 const bool m_projective;
2890 const int m_iterationCount;
2891 const PrimitiveWideness m_primitiveWideness;
2892
2893 int m_iteration;
2894 bool m_allIterationsPassed;
2895 float m_maxLineWidth;
2896 std::vector<float> m_lineWidths;
2897 bool m_flatshade;
2898 };
2899
LineInterpolationTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,int flags,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount)2900 LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount)
2901 : BaseRenderingTestInstance (context, sampleCount)
2902 , m_primitiveTopology (primitiveTopology)
2903 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
2904 , m_iterationCount (3)
2905 , m_primitiveWideness (wideness)
2906 , m_iteration (0)
2907 , m_allIterationsPassed (true)
2908 , m_maxLineWidth (1.0f)
2909 , m_flatshade ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
2910 {
2911 DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
2912
2913 if (!context.getDeviceProperties().limits.strictLines)
2914 TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
2915
2916 // create line widths
2917 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
2918 {
2919 m_lineWidths.resize(m_iterationCount, 1.0f);
2920 }
2921 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
2922 {
2923 if (!m_context.getDeviceFeatures().wideLines)
2924 TCU_THROW(NotSupportedError , "wide line support required");
2925
2926 const float* range = context.getDeviceProperties().limits.lineWidthRange;
2927
2928 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
2929
2930 // no wide line support
2931 if (range[1] <= 1.0f)
2932 throw tcu::NotSupportedError("wide line support required");
2933
2934 // set hand picked sizes
2935 m_lineWidths.push_back(5.0f);
2936 m_lineWidths.push_back(10.0f);
2937 m_lineWidths.push_back(range[1]);
2938 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
2939
2940 m_maxLineWidth = range[1];
2941 }
2942 else
2943 DE_ASSERT(false);
2944 }
2945
iterate(void)2946 tcu::TestStatus LineInterpolationTestInstance::iterate (void)
2947 {
2948 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
2949 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
2950 const float lineWidth = getLineWidth();
2951 tcu::Surface resultImage (m_renderSize, m_renderSize);
2952 std::vector<tcu::Vec4> drawBuffer;
2953 std::vector<tcu::Vec4> colorBuffer;
2954 std::vector<LineSceneSpec::SceneLine> lines;
2955
2956 // supported?
2957 if (lineWidth <= m_maxLineWidth)
2958 {
2959 // generate scene
2960 generateVertices(m_iteration, drawBuffer, colorBuffer);
2961 extractLines(lines, drawBuffer, colorBuffer);
2962
2963 // log
2964 {
2965 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
2966 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2967 m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2968 }
2969
2970 // draw image
2971 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
2972
2973 // compare
2974 {
2975 RasterizationArguments args;
2976 LineSceneSpec scene;
2977
2978 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
2979
2980 args.numSamples = m_multisampling ? 1 : 0;
2981 args.subpixelBits = m_subpixelBits;
2982 args.redBits = colorBits[0];
2983 args.greenBits = colorBits[1];
2984 args.blueBits = colorBits[2];
2985
2986 scene.lines.swap(lines);
2987 scene.lineWidth = getLineWidth();
2988
2989 if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
2990 m_allIterationsPassed = false;
2991 }
2992 }
2993 else
2994 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
2995
2996 // result
2997 if (++m_iteration == m_iterationCount)
2998 {
2999 if (m_allIterationsPassed)
3000 return tcu::TestStatus::pass("Pass");
3001 else
3002 return tcu::TestStatus::fail("Incorrect rasterization");
3003 }
3004 else
3005 return tcu::TestStatus::incomplete();
3006 }
3007
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const3008 void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
3009 {
3010 // use only red, green and blue
3011 const tcu::Vec4 colors[] =
3012 {
3013 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
3014 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
3015 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
3016 };
3017
3018 de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
3019
3020 outVertices.resize(6);
3021 outColors.resize(6);
3022
3023 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
3024 {
3025 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
3026 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
3027 outVertices[vtxNdx].z() = 0.0f;
3028
3029 if (!m_projective)
3030 outVertices[vtxNdx].w() = 1.0f;
3031 else
3032 {
3033 const float w = rnd.getFloat(0.2f, 4.0f);
3034
3035 outVertices[vtxNdx].x() *= w;
3036 outVertices[vtxNdx].y() *= w;
3037 outVertices[vtxNdx].z() *= w;
3038 outVertices[vtxNdx].w() = w;
3039 }
3040
3041 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
3042 }
3043 }
3044
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const3045 void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
3046 {
3047 switch (m_primitiveTopology)
3048 {
3049 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
3050 {
3051 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
3052 {
3053 LineSceneSpec::SceneLine line;
3054 line.positions[0] = vertices[vtxNdx + 0];
3055 line.positions[1] = vertices[vtxNdx + 1];
3056
3057 if (m_flatshade)
3058 {
3059 line.colors[0] = colors[vtxNdx];
3060 line.colors[1] = colors[vtxNdx];
3061 }
3062 else
3063 {
3064 line.colors[0] = colors[vtxNdx + 0];
3065 line.colors[1] = colors[vtxNdx + 1];
3066 }
3067
3068 outLines.push_back(line);
3069 }
3070 break;
3071 }
3072
3073 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
3074 {
3075 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
3076 {
3077 LineSceneSpec::SceneLine line;
3078 line.positions[0] = vertices[vtxNdx + 0];
3079 line.positions[1] = vertices[vtxNdx + 1];
3080
3081 if (m_flatshade)
3082 {
3083 line.colors[0] = colors[vtxNdx];
3084 line.colors[1] = colors[vtxNdx];
3085 }
3086 else
3087 {
3088 line.colors[0] = colors[vtxNdx + 0];
3089 line.colors[1] = colors[vtxNdx + 1];
3090 }
3091
3092 outLines.push_back(line);
3093 }
3094 break;
3095 }
3096
3097 default:
3098 DE_ASSERT(false);
3099 }
3100 }
3101
getLineWidth(void) const3102 float LineInterpolationTestInstance::getLineWidth (void) const
3103 {
3104 return m_lineWidths[m_iteration];
3105 }
3106
3107 class LineInterpolationTestCase : public BaseRenderingTestCase
3108 {
3109 public:
LineInterpolationTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,int flags,PrimitiveWideness wideness,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)3110 LineInterpolationTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
3111 : BaseRenderingTestCase (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
3112 , m_primitiveTopology (primitiveTopology)
3113 , m_flags (flags)
3114 , m_wideness (wideness)
3115 {}
3116
createInstance(Context & context) const3117 virtual TestInstance* createInstance (Context& context) const
3118 {
3119 return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_sampleCount);
3120 }
3121 protected:
3122 const VkPrimitiveTopology m_primitiveTopology;
3123 const int m_flags;
3124 const PrimitiveWideness m_wideness;
3125 };
3126
createRasterizationTests(tcu::TestCaseGroup * rasterizationTests)3127 void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
3128 {
3129 tcu::TestContext& testCtx = rasterizationTests->getTestContext();
3130
3131 // .primitives
3132 {
3133 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives", "Primitive rasterization");
3134
3135 rasterizationTests->addChild(primitives);
3136
3137 primitives->addChild(new BaseTestCase<TrianglesTestInstance> (testCtx, "triangles", "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result"));
3138 primitives->addChild(new BaseTestCase<TriangleStripTestInstance> (testCtx, "triangle_strip", "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result"));
3139 primitives->addChild(new BaseTestCase<TriangleFanTestInstance> (testCtx, "triangle_fan", "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result"));
3140 primitives->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
3141 primitives->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "line_strip", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result", PRIMITIVEWIDENESS_NARROW));
3142 primitives->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
3143 primitives->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "line_strip_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
3144 primitives->addChild(new WidenessTestCase<PointTestInstance> (testCtx, "points", "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result", PRIMITIVEWIDENESS_WIDE));
3145 }
3146
3147 // .fill_rules
3148 {
3149 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules", "Primitive fill rules");
3150
3151 rasterizationTests->addChild(fillRules);
3152
3153 fillRules->addChild(new FillRuleTestCase(testCtx, "basic_quad", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_BASIC));
3154 fillRules->addChild(new FillRuleTestCase(testCtx, "basic_quad_reverse", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_REVERSED));
3155 fillRules->addChild(new FillRuleTestCase(testCtx, "clipped_full", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL));
3156 fillRules->addChild(new FillRuleTestCase(testCtx, "clipped_partly", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL));
3157 fillRules->addChild(new FillRuleTestCase(testCtx, "projected", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_PROJECTED));
3158 }
3159
3160 // .culling
3161 {
3162 static const struct CullMode
3163 {
3164 VkCullModeFlags mode;
3165 const char* prefix;
3166 } cullModes[] =
3167 {
3168 { VK_CULL_MODE_FRONT_BIT, "front_" },
3169 { VK_CULL_MODE_BACK_BIT, "back_" },
3170 { VK_CULL_MODE_FRONT_AND_BACK, "both_" },
3171 };
3172 static const struct PrimitiveType
3173 {
3174 VkPrimitiveTopology type;
3175 const char* name;
3176 } primitiveTypes[] =
3177 {
3178 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangles" },
3179 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip" },
3180 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan" },
3181 };
3182 static const struct FrontFaceOrder
3183 {
3184 VkFrontFace mode;
3185 const char* postfix;
3186 } frontOrders[] =
3187 {
3188 { VK_FRONT_FACE_COUNTER_CLOCKWISE, "" },
3189 { VK_FRONT_FACE_CLOCKWISE, "_reverse" },
3190 };
3191
3192 static const struct PolygonMode
3193 {
3194 VkPolygonMode mode;
3195 const char* name;
3196 } polygonModes[] =
3197 {
3198 { VK_POLYGON_MODE_FILL, "" },
3199 { VK_POLYGON_MODE_LINE, "_line" },
3200 { VK_POLYGON_MODE_POINT, "_point" }
3201 };
3202
3203 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling", "Culling");
3204
3205 rasterizationTests->addChild(culling);
3206
3207 for (int cullModeNdx = 0; cullModeNdx < DE_LENGTH_OF_ARRAY(cullModes); ++cullModeNdx)
3208 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
3209 for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders); ++frontOrderNdx)
3210 for (int polygonModeNdx = 0; polygonModeNdx < DE_LENGTH_OF_ARRAY(polygonModes); ++polygonModeNdx)
3211 {
3212 if (!(cullModes[cullModeNdx].mode == VK_CULL_MODE_FRONT_AND_BACK && polygonModes[polygonModeNdx].mode != VK_POLYGON_MODE_FILL))
3213 {
3214 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix + polygonModes[polygonModeNdx].name;
3215 culling->addChild(new CullingTestCase(testCtx, name, "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode, polygonModes[polygonModeNdx].mode));
3216 }
3217 }
3218 }
3219
3220 // .discard
3221 {
3222 static const struct PrimitiveType
3223 {
3224 VkPrimitiveTopology type;
3225 const char* name;
3226 } primitiveTypes[] =
3227 {
3228 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list" },
3229 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip" },
3230 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan" },
3231 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list" },
3232 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip" },
3233 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list" }
3234 };
3235
3236 static const struct queryPipeline
3237 {
3238 deBool useQuery;
3239 const char* name;
3240 } queryPipeline[] =
3241 {
3242 { DE_FALSE, "query_pipeline_false" },
3243 { DE_TRUE, "query_pipeline_true" },
3244 };
3245
3246 tcu::TestCaseGroup* const discard = new tcu::TestCaseGroup(testCtx, "discard", "Rasterizer discard");
3247
3248 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
3249 {
3250 tcu::TestCaseGroup* const primitive = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveNdx].name, "Rasterizer discard");
3251
3252 for (int useQueryNdx = 0; useQueryNdx < DE_LENGTH_OF_ARRAY(queryPipeline); useQueryNdx++)
3253 {
3254 const std::string name = std::string(queryPipeline[useQueryNdx].name);
3255
3256 primitive->addChild(new DiscardTestCase(testCtx, name, "Test primitive discarding.", primitiveTypes[primitiveNdx].type, queryPipeline[useQueryNdx].useQuery));
3257 }
3258
3259 discard->addChild(primitive);
3260 }
3261
3262 rasterizationTests->addChild(discard);
3263 }
3264
3265 // .interpolation
3266 {
3267 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
3268
3269 rasterizationTests->addChild(interpolation);
3270
3271 // .basic
3272 {
3273 tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation");
3274
3275 interpolation->addChild(basic);
3276
3277 basic->addChild(new TriangleInterpolationTestCase (testCtx, "triangles", "Verify triangle interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, INTERPOLATIONFLAGS_NONE));
3278 basic->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_strip", "Verify triangle strip interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, INTERPOLATIONFLAGS_NONE));
3279 basic->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_fan", "Verify triangle fan interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, INTERPOLATIONFLAGS_NONE));
3280 basic->addChild(new LineInterpolationTestCase (testCtx, "lines", "Verify line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW));
3281 basic->addChild(new LineInterpolationTestCase (testCtx, "line_strip", "Verify line strip interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW));
3282 basic->addChild(new LineInterpolationTestCase (testCtx, "lines_wide", "Verify wide line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE));
3283 basic->addChild(new LineInterpolationTestCase (testCtx, "line_strip_wide","Verify wide line strip interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE));
3284 }
3285
3286 // .projected
3287 {
3288 tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation");
3289
3290 interpolation->addChild(projected);
3291
3292 projected->addChild(new TriangleInterpolationTestCase (testCtx, "triangles", "Verify triangle interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, INTERPOLATIONFLAGS_PROJECTED));
3293 projected->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_strip", "Verify triangle strip interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, INTERPOLATIONFLAGS_PROJECTED));
3294 projected->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_fan", "Verify triangle fan interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, INTERPOLATIONFLAGS_PROJECTED));
3295 projected->addChild(new LineInterpolationTestCase (testCtx, "lines", "Verify line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_NARROW));
3296 projected->addChild(new LineInterpolationTestCase (testCtx, "line_strip", "Verify line strip interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_NARROW));
3297 projected->addChild(new LineInterpolationTestCase (testCtx, "lines_wide", "Verify wide line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_WIDE));
3298 projected->addChild(new LineInterpolationTestCase (testCtx, "line_strip_wide","Verify wide line strip interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_WIDE));
3299 }
3300 }
3301
3302 // .flatshading
3303 {
3304 tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading");
3305
3306 rasterizationTests->addChild(flatshading);
3307
3308 flatshading->addChild(new TriangleInterpolationTestCase (testCtx, "triangles", "Verify triangle flatshading", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, INTERPOLATIONFLAGS_FLATSHADE));
3309 flatshading->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_strip", "Verify triangle strip flatshading", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, INTERPOLATIONFLAGS_FLATSHADE));
3310 flatshading->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_fan", "Verify triangle fan flatshading", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, INTERPOLATIONFLAGS_FLATSHADE));
3311 flatshading->addChild(new LineInterpolationTestCase (testCtx, "lines", "Verify line flatshading", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_NARROW));
3312 flatshading->addChild(new LineInterpolationTestCase (testCtx, "line_strip", "Verify line strip flatshading", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_NARROW));
3313 flatshading->addChild(new LineInterpolationTestCase (testCtx, "lines_wide", "Verify wide line flatshading", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_WIDE));
3314 flatshading->addChild(new LineInterpolationTestCase (testCtx, "line_strip_wide","Verify wide line strip flatshading", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_WIDE));
3315 }
3316
3317 const VkSampleCountFlagBits samples[] =
3318 {
3319 VK_SAMPLE_COUNT_2_BIT,
3320 VK_SAMPLE_COUNT_4_BIT,
3321 VK_SAMPLE_COUNT_8_BIT,
3322 VK_SAMPLE_COUNT_16_BIT,
3323 VK_SAMPLE_COUNT_32_BIT,
3324 VK_SAMPLE_COUNT_64_BIT
3325 };
3326
3327 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
3328 {
3329 std::ostringstream caseName;
3330
3331 caseName << "_multisample_" << (2 << samplesNdx) << "_bit";
3332
3333 // .primitives
3334 {
3335 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization");
3336
3337 rasterizationTests->addChild(primitives);
3338
3339 primitives->addChild(new BaseTestCase<TrianglesTestInstance> (testCtx, "triangles", "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result", samples[samplesNdx]));
3340 primitives->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result", PRIMITIVEWIDENESS_NARROW, samples[samplesNdx]));
3341 primitives->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE, samples[samplesNdx]));
3342 primitives->addChild(new WidenessTestCase<PointTestInstance> (testCtx, "points", "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result", PRIMITIVEWIDENESS_WIDE, samples[samplesNdx]));
3343 }
3344
3345 // .fill_rules
3346 {
3347 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules");
3348
3349 rasterizationTests->addChild(fillRules);
3350
3351 fillRules->addChild(new FillRuleTestCase(testCtx, "basic_quad", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_BASIC, samples[samplesNdx]));
3352 fillRules->addChild(new FillRuleTestCase(testCtx, "basic_quad_reverse", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_REVERSED, samples[samplesNdx]));
3353 fillRules->addChild(new FillRuleTestCase(testCtx, "clipped_full", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL, samples[samplesNdx]));
3354 fillRules->addChild(new FillRuleTestCase(testCtx, "clipped_partly", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL, samples[samplesNdx]));
3355 fillRules->addChild(new FillRuleTestCase(testCtx, "projected", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_PROJECTED, samples[samplesNdx]));
3356 }
3357
3358 // .interpolation
3359 {
3360 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation");
3361
3362 rasterizationTests->addChild(interpolation);
3363
3364 interpolation->addChild(new TriangleInterpolationTestCase (testCtx, "triangles", "Verify triangle interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, INTERPOLATIONFLAGS_NONE, samples[samplesNdx]));
3365 interpolation->addChild(new LineInterpolationTestCase (testCtx, "lines", "Verify line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW, samples[samplesNdx]));
3366 interpolation->addChild(new LineInterpolationTestCase (testCtx, "lines_wide", "Verify wide line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE, samples[samplesNdx]));
3367 }
3368 }
3369 }
3370
3371 } // anonymous
3372
createTests(tcu::TestContext & testCtx)3373 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
3374 {
3375 return createTestGroup(testCtx, "rasterization", "Rasterization Tests", createRasterizationTests);
3376 }
3377
3378 } // rasterization
3379 } // vkt
3380