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 47 #include <vector> 48 49 using namespace vk; 50 51 namespace vkt 52 { 53 namespace rasterization 54 { 55 namespace 56 { 57 58 using tcu::RasterizationArguments; 59 using tcu::TriangleSceneSpec; 60 using tcu::PointSceneSpec; 61 using tcu::LineSceneSpec; 62 using tcu::LineInterpolationMethod; 63 64 static const char* const s_shaderVertexTemplate = "#version 310 es\n" 65 "layout(location = 0) in highp vec4 a_position;\n" 66 "layout(location = 1) in highp vec4 a_color;\n" 67 "layout(location = 0) ${INTERPOLATION}out highp vec4 v_color;\n" 68 "layout (set=0, binding=0) uniform PointSize {\n" 69 " highp float u_pointSize;\n" 70 "};\n" 71 "void main ()\n" 72 "{\n" 73 " gl_Position = a_position;\n" 74 " gl_PointSize = u_pointSize;\n" 75 " v_color = a_color;\n" 76 "}\n"; 77 78 static const char* const s_shaderFragmentTemplate = "#version 310 es\n" 79 "layout(location = 0) out highp vec4 fragColor;\n" 80 "layout(location = 0) ${INTERPOLATION}in highp vec4 v_color;\n" 81 "void main ()\n" 82 "{\n" 83 " fragColor = v_color;\n" 84 "}\n"; 85 enum InterpolationCaseFlags 86 { 87 INTERPOLATIONFLAGS_NONE = 0, 88 INTERPOLATIONFLAGS_PROJECTED = (1 << 1), 89 INTERPOLATIONFLAGS_FLATSHADE = (1 << 2), 90 }; 91 92 enum PrimitiveWideness 93 { 94 PRIMITIVEWIDENESS_NARROW = 0, 95 PRIMITIVEWIDENESS_WIDE, 96 97 PRIMITIVEWIDENESS_LAST 98 }; 99 100 class BaseRenderingTestCase : public TestCase 101 { 102 public: 103 BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deBool flatshade = DE_FALSE); 104 virtual ~BaseRenderingTestCase (void); 105 106 virtual void initPrograms (vk::SourceCollections& programCollection) const; 107 108 protected: 109 const VkSampleCountFlagBits m_sampleCount; 110 const deBool m_flatshade; 111 }; 112 113 BaseRenderingTestCase::BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount, deBool flatshade) 114 : TestCase(context, name, description) 115 , m_sampleCount (sampleCount) 116 , m_flatshade (flatshade) 117 { 118 } 119 120 void BaseRenderingTestCase::initPrograms (vk::SourceCollections& programCollection) const 121 { 122 tcu::StringTemplate vertexSource (s_shaderVertexTemplate); 123 tcu::StringTemplate fragmentSource (s_shaderFragmentTemplate); 124 std::map<std::string, std::string> params; 125 126 params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : (""); 127 128 programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vertexSource.specialize(params)); 129 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fragmentSource.specialize(params)); 130 } 131 132 BaseRenderingTestCase::~BaseRenderingTestCase (void) 133 { 134 } 135 136 class BaseRenderingTestInstance : public TestInstance 137 { 138 public: 139 enum { 140 DEFAULT_RENDER_SIZE = 256 141 }; 142 143 BaseRenderingTestInstance (Context& context, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deUint32 renderSize = DEFAULT_RENDER_SIZE); 144 ~BaseRenderingTestInstance (void); 145 146 protected: 147 void addImageTransitionBarrier (VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const; 148 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology); 149 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, VkPrimitiveTopology primitiveTopology); 150 virtual float getLineWidth (void) const; 151 virtual float getPointSize (void) const; 152 153 virtual 154 const VkPipelineRasterizationStateCreateInfo* getRasterizationStateCreateInfo (void) const; 155 156 virtual 157 const VkPipelineColorBlendStateCreateInfo* getColorBlendStateCreateInfo (void) const; 158 159 const tcu::TextureFormat& getTextureFormat (void) const; 160 161 const deUint32 m_renderSize; 162 const VkSampleCountFlagBits m_sampleCount; 163 const deUint32 m_subpixelBits; 164 const deBool m_multisampling; 165 166 const VkFormat m_imageFormat; 167 const tcu::TextureFormat m_textureFormat; 168 Move<VkCommandPool> m_commandPool; 169 170 Move<VkImage> m_image; 171 de::MovePtr<Allocation> m_imageMemory; 172 Move<VkImageView> m_imageView; 173 174 Move<VkImage> m_resolvedImage; 175 de::MovePtr<Allocation> m_resolvedImageMemory; 176 Move<VkImageView> m_resolvedImageView; 177 178 Move<VkRenderPass> m_renderPass; 179 Move<VkFramebuffer> m_frameBuffer; 180 181 Move<VkDescriptorPool> m_descriptorPool; 182 Move<VkDescriptorSet> m_descriptorSet; 183 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 184 185 Move<VkBuffer> m_uniformBuffer; 186 de::MovePtr<Allocation> m_uniformBufferMemory; 187 const VkDeviceSize m_uniformBufferSize; 188 189 Move<VkPipelineLayout> m_pipelineLayout; 190 191 Move<VkShaderModule> m_vertexShaderModule; 192 Move<VkShaderModule> m_fragmentShaderModule; 193 194 Move<VkFence> m_fence; 195 196 Move<VkBuffer> m_resultBuffer; 197 de::MovePtr<Allocation> m_resultBufferMemory; 198 const VkDeviceSize m_resultBufferSize; 199 }; 200 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 // Fence 539 m_fence = createFence(vkd, vkDevice); 540 541 // Result Buffer 542 { 543 const VkBufferCreateInfo bufferCreateInfo = 544 { 545 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 546 DE_NULL, // const void* pNext; 547 0u, // VkBufferCreateFlags flags; 548 m_resultBufferSize, // VkDeviceSize size; 549 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; 550 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 551 1u, // deUint32 queueFamilyIndexCount; 552 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 553 }; 554 555 m_resultBuffer = createBuffer(vkd, vkDevice, &bufferCreateInfo); 556 m_resultBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible); 557 558 VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset())); 559 } 560 561 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Sample count = " << getSampleCountFlagsStr(m_sampleCount) << tcu::TestLog::EndMessage; 562 m_context.getTestContext().getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage; 563 } 564 565 BaseRenderingTestInstance::~BaseRenderingTestInstance (void) 566 { 567 } 568 569 570 void BaseRenderingTestInstance::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const 571 { 572 573 const DeviceInterface& vkd = m_context.getDeviceInterface(); 574 575 const VkImageSubresourceRange subResourcerange = 576 { 577 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 578 0, // deUint32 baseMipLevel; 579 1, // deUint32 levelCount; 580 0, // deUint32 baseArrayLayer; 581 1 // deUint32 layerCount; 582 }; 583 584 const VkImageMemoryBarrier imageBarrier = 585 { 586 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 587 DE_NULL, // const void* pNext; 588 srcAccessMask, // VkAccessFlags srcAccessMask; 589 dstAccessMask, // VkAccessFlags dstAccessMask; 590 oldLayout, // VkImageLayout oldLayout; 591 newLayout, // VkImageLayout newLayout; 592 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 593 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 594 image, // VkImage image; 595 subResourcerange // VkImageSubresourceRange subresourceRange; 596 }; 597 598 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier); 599 } 600 601 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology) 602 { 603 // default to color white 604 const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); 605 606 drawPrimitives(result, vertexData, colorData, primitiveTopology); 607 } 608 609 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology) 610 { 611 const DeviceInterface& vkd = m_context.getDeviceInterface(); 612 const VkDevice vkDevice = m_context.getDevice(); 613 const VkQueue queue = m_context.getUniversalQueue(); 614 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 615 Allocator& allocator = m_context.getDefaultAllocator(); 616 const size_t attributeBatchSize = positionData.size() * sizeof(tcu::Vec4); 617 618 Move<VkCommandBuffer> commandBuffer; 619 Move<VkPipeline> graphicsPipeline; 620 Move<VkBuffer> vertexBuffer; 621 de::MovePtr<Allocation> vertexBufferMemory; 622 const VkPhysicalDeviceProperties properties = m_context.getDeviceProperties(); 623 624 if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset) 625 { 626 std::stringstream message; 627 message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ")."; 628 TCU_THROW(NotSupportedError, message.str().c_str()); 629 } 630 631 // Create Graphics Pipeline 632 { 633 const VkPipelineShaderStageCreateInfo shaderStageParams[2] = 634 { 635 { 636 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 637 DE_NULL, // const void* pNext; 638 0, // VkPipelineShaderStageCreateFlags flags; 639 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStage stage; 640 *m_vertexShaderModule, // VkShader shader; 641 "main", // const char* pName; 642 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 643 }, 644 { 645 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 646 DE_NULL, // const void* pNext; 647 0, // VkPipelineShaderStageCreateFlags flags; 648 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStage stage; 649 *m_fragmentShaderModule, // VkShader shader; 650 "main", // const char* pName; 651 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 652 } 653 }; 654 655 const VkVertexInputBindingDescription vertexInputBindingDescription = 656 { 657 0u, // deUint32 binding; 658 sizeof(tcu::Vec4), // deUint32 strideInBytes; 659 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate; 660 }; 661 662 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = 663 { 664 { 665 0u, // deUint32 location; 666 0u, // deUint32 binding; 667 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 668 0u // deUint32 offsetInBytes; 669 }, 670 { 671 1u, // deUint32 location; 672 0u, // deUint32 binding; 673 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 674 (deUint32)attributeBatchSize // deUint32 offsetInBytes; 675 } 676 }; 677 678 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 679 { 680 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 681 DE_NULL, // const void* pNext; 682 0, // VkPipelineVertexInputStateCreateFlags flags; 683 1u, // deUint32 bindingCount; 684 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 685 2u, // deUint32 attributeCount; 686 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 687 }; 688 689 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = 690 { 691 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 692 DE_NULL, // const void* pNext; 693 0, // VkPipelineInputAssemblyStateCreateFlags flags; 694 primitiveTopology, // VkPrimitiveTopology topology; 695 false // VkBool32 primitiveRestartEnable; 696 }; 697 698 const VkViewport viewport = 699 { 700 0.0f, // float originX; 701 0.0f, // float originY; 702 (float)m_renderSize, // float width; 703 (float)m_renderSize, // float height; 704 0.0f, // float minDepth; 705 1.0f // float maxDepth; 706 }; 707 708 const VkRect2D scissor = 709 { 710 { 0, 0 }, // VkOffset2D offset; 711 { m_renderSize, m_renderSize } // VkExtent2D extent; 712 }; 713 714 const VkPipelineViewportStateCreateInfo viewportStateParams = 715 { 716 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 717 DE_NULL, // const void* pNext; 718 0, // VkPipelineViewportStateCreateFlags flags; 719 1u, // deUint32 viewportCount; 720 &viewport, // const VkViewport* pViewports; 721 1u, // deUint32 scissorCount; 722 &scissor // const VkRect2D* pScissors; 723 }; 724 725 const VkPipelineMultisampleStateCreateInfo multisampleStateParams = 726 { 727 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 728 DE_NULL, // const void* pNext; 729 0u, // VkPipelineMultisampleStateCreateFlags flags; 730 m_sampleCount, // VkSampleCountFlagBits rasterizationSamples; 731 VK_FALSE, // VkBool32 sampleShadingEnable; 732 0.0f, // float minSampleShading; 733 DE_NULL, // const VkSampleMask* pSampleMask; 734 VK_FALSE, // VkBool32 alphaToCoverageEnable; 735 VK_FALSE // VkBool32 alphaToOneEnable; 736 }; 737 738 const VkGraphicsPipelineCreateInfo graphicsPipelineParams = 739 { 740 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 741 DE_NULL, // const void* pNext; 742 0u, // VkPipelineCreateFlags flags; 743 2u, // deUint32 stageCount; 744 shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages; 745 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 746 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 747 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 748 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; 749 getRasterizationStateCreateInfo(), // const VkPipelineRasterStateCreateInfo* pRasterizationState; 750 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 751 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 752 getColorBlendStateCreateInfo(), // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 753 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 754 *m_pipelineLayout, // VkPipelineLayout layout; 755 *m_renderPass, // VkRenderPass renderPass; 756 0u, // deUint32 subpass; 757 0u, // VkPipeline basePipelineHandle; 758 0u // deInt32 basePipelineIndex; 759 }; 760 761 graphicsPipeline = createGraphicsPipeline(vkd, vkDevice, DE_NULL, &graphicsPipelineParams); 762 } 763 764 // Create Vertex Buffer 765 { 766 const VkBufferCreateInfo vertexBufferParams = 767 { 768 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 769 DE_NULL, // const void* pNext; 770 0u, // VkBufferCreateFlags flags; 771 attributeBatchSize * 2, // VkDeviceSize size; 772 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 773 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 774 1u, // deUint32 queueFamilyCount; 775 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 776 }; 777 778 vertexBuffer = createBuffer(vkd, vkDevice, &vertexBufferParams); 779 vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible); 780 781 VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset())); 782 783 // Load vertices into vertex buffer 784 deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize); 785 deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize); 786 flushMappedMemoryRange(vkd, vkDevice, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset(), vertexBufferParams.size); 787 } 788 789 // Create Command Buffer 790 commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 791 792 // Begin Command Buffer 793 { 794 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 795 { 796 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 797 DE_NULL, // const void* pNext; 798 0u, // VkCmdBufferOptimizeFlags flags; 799 DE_NULL // const VkCommandBufferInheritanceInfo* pInheritanceInfo; 800 }; 801 802 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &cmdBufferBeginInfo)); 803 } 804 805 addImageTransitionBarrier(*commandBuffer, *m_image, 806 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask 807 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask 808 0, // VkAccessFlags srcAccessMask 809 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask 810 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 811 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // VkImageLayout newLayout; 812 813 if (m_multisampling) { 814 addImageTransitionBarrier(*commandBuffer, *m_resolvedImage, 815 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // VkPipelineStageFlags srcStageMask 816 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // VkPipelineStageFlags dstStageMask 817 0, // VkAccessFlags srcAccessMask 818 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask 819 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 820 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); // VkImageLayout newLayout; 821 } 822 823 // Begin Render Pass 824 { 825 const VkClearValue clearValue = makeClearValueColorF32(0.0, 0.0, 0.0, 1.0); 826 827 const VkRenderPassBeginInfo renderPassBeginInfo = 828 { 829 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 830 DE_NULL, // const void* pNext; 831 *m_renderPass, // VkRenderPass renderPass; 832 *m_frameBuffer, // VkFramebuffer framebuffer; 833 { 834 { 0, 0 }, 835 { m_renderSize, m_renderSize } 836 }, // VkRect2D renderArea; 837 1u, // deUint32 clearValueCount; 838 &clearValue // const VkClearValue* pClearValues; 839 }; 840 841 vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 842 } 843 844 const VkDeviceSize vertexBufferOffset = 0; 845 846 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline); 847 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL); 848 vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset); 849 vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0); 850 vkd.cmdEndRenderPass(*commandBuffer); 851 852 // Copy Image 853 { 854 855 const VkBufferMemoryBarrier bufferBarrier = 856 { 857 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 858 DE_NULL, // const void* pNext; 859 VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask; 860 VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask; 861 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 862 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 863 *m_resultBuffer, // VkBuffer buffer; 864 0u, // VkDeviceSize offset; 865 m_resultBufferSize // VkDeviceSize size; 866 }; 867 868 const VkBufferImageCopy copyRegion = 869 { 870 0u, // VkDeviceSize bufferOffset; 871 m_renderSize, // deUint32 bufferRowLength; 872 m_renderSize, // deUint32 bufferImageHeight; 873 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u }, // VkImageSubresourceCopy imageSubresource; 874 { 0, 0, 0 }, // VkOffset3D imageOffset; 875 { m_renderSize, m_renderSize, 1u } // VkExtent3D imageExtent; 876 }; 877 878 addImageTransitionBarrier(*commandBuffer, 879 m_multisampling ? *m_resolvedImage : *m_image, 880 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask 881 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask 882 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask 883 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask 884 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 885 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); // VkImageLayout newLayout;) 886 887 if (m_multisampling) 888 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_resolvedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, ©Region); 889 else 890 vkd.cmdCopyImageToBuffer(*commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, ©Region); 891 892 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); 893 } 894 895 VK_CHECK(vkd.endCommandBuffer(*commandBuffer)); 896 897 // Set Point Size 898 { 899 float pointSize = getPointSize(); 900 deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize); 901 flushMappedMemoryRange(vkd, vkDevice, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset(), m_uniformBufferSize); 902 } 903 904 // Submit 905 { 906 const VkSubmitInfo submitInfo = 907 { 908 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 909 DE_NULL, // const void* pNext; 910 0u, // deUint32 waitSemaphoreCount; 911 DE_NULL, // const VkSemaphore* pWaitSemaphores; 912 DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask; 913 1u, // deUint32 commandBufferCount; 914 &commandBuffer.get(), // const VkCommandBuffer* pCommandBuffers; 915 0u, // deUint32 signalSemaphoreCount; 916 DE_NULL, // const VkSemaphore* pSignalSemaphores; 917 }; 918 919 VK_CHECK(vkd.resetFences(vkDevice, 1, &m_fence.get())); 920 VK_CHECK(vkd.queueSubmit(queue, 1, &submitInfo, *m_fence)); 921 VK_CHECK(vkd.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */)); 922 } 923 924 invalidateMappedMemoryRange(vkd, vkDevice, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset(), m_resultBufferSize); 925 tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr())); 926 } 927 928 float BaseRenderingTestInstance::getLineWidth (void) const 929 { 930 return 1.0f; 931 } 932 933 float BaseRenderingTestInstance::getPointSize (void) const 934 { 935 return 1.0f; 936 } 937 938 const VkPipelineRasterizationStateCreateInfo* BaseRenderingTestInstance::getRasterizationStateCreateInfo (void) const 939 { 940 static VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = 941 { 942 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 943 DE_NULL, // const void* pNext; 944 0, // VkPipelineRasterizationStateCreateFlags flags; 945 false, // VkBool32 depthClipEnable; 946 false, // VkBool32 rasterizerDiscardEnable; 947 VK_POLYGON_MODE_FILL, // VkFillMode fillMode; 948 VK_CULL_MODE_NONE, // VkCullMode cullMode; 949 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 950 VK_FALSE, // VkBool32 depthBiasEnable; 951 0.0f, // float depthBias; 952 0.0f, // float depthBiasClamp; 953 0.0f, // float slopeScaledDepthBias; 954 getLineWidth(), // float lineWidth; 955 }; 956 957 rasterizationStateCreateInfo.lineWidth = getLineWidth(); 958 return &rasterizationStateCreateInfo; 959 } 960 961 const VkPipelineColorBlendStateCreateInfo* BaseRenderingTestInstance::getColorBlendStateCreateInfo (void) const 962 { 963 static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 964 { 965 false, // VkBool32 blendEnable; 966 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor; 967 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor; 968 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; 969 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha; 970 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha; 971 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; 972 (VK_COLOR_COMPONENT_R_BIT | 973 VK_COLOR_COMPONENT_G_BIT | 974 VK_COLOR_COMPONENT_B_BIT | 975 VK_COLOR_COMPONENT_A_BIT) // VkChannelFlags channelWriteMask; 976 }; 977 978 static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 979 { 980 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 981 DE_NULL, // const void* pNext; 982 0, // VkPipelineColorBlendStateCreateFlags flags; 983 false, // VkBool32 logicOpEnable; 984 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 985 1u, // deUint32 attachmentCount; 986 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 987 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; 988 }; 989 990 return &colorBlendStateParams; 991 } 992 993 const tcu::TextureFormat& BaseRenderingTestInstance::getTextureFormat (void) const 994 { 995 return m_textureFormat; 996 } 997 998 class BaseTriangleTestInstance : public BaseRenderingTestInstance 999 { 1000 public: 1001 BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount); 1002 virtual tcu::TestStatus iterate (void); 1003 1004 private: 1005 virtual void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL; 1006 1007 int m_iteration; 1008 const int m_iterationCount; 1009 VkPrimitiveTopology m_primitiveTopology; 1010 bool m_allIterationsPassed; 1011 }; 1012 1013 BaseTriangleTestInstance::BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount) 1014 : BaseRenderingTestInstance (context, sampleCount) 1015 , m_iteration (0) 1016 , m_iterationCount (3) 1017 , m_primitiveTopology (primitiveTopology) 1018 , m_allIterationsPassed (true) 1019 { 1020 } 1021 1022 tcu::TestStatus BaseTriangleTestInstance::iterate (void) 1023 { 1024 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 1025 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), iterationDescription, iterationDescription); 1026 tcu::Surface resultImage (m_renderSize, m_renderSize); 1027 std::vector<tcu::Vec4> drawBuffer; 1028 std::vector<TriangleSceneSpec::SceneTriangle> triangles; 1029 1030 generateTriangles(m_iteration, drawBuffer, triangles); 1031 1032 // draw image 1033 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology); 1034 1035 // compare 1036 { 1037 bool compareOk; 1038 RasterizationArguments args; 1039 TriangleSceneSpec scene; 1040 1041 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat()); 1042 1043 args.numSamples = m_multisampling ? 1 : 0; 1044 args.subpixelBits = m_subpixelBits; 1045 args.redBits = colorBits[0]; 1046 args.greenBits = colorBits[1]; 1047 args.blueBits = colorBits[2]; 1048 1049 scene.triangles.swap(triangles); 1050 1051 compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()); 1052 1053 if (!compareOk) 1054 m_allIterationsPassed = false; 1055 } 1056 1057 // result 1058 if (++m_iteration == m_iterationCount) 1059 { 1060 if (m_allIterationsPassed) 1061 return tcu::TestStatus::pass("Pass"); 1062 else 1063 return tcu::TestStatus::fail("Incorrect rasterization"); 1064 } 1065 else 1066 return tcu::TestStatus::incomplete(); 1067 } 1068 1069 class BaseLineTestInstance : public BaseRenderingTestInstance 1070 { 1071 public: 1072 BaseLineTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount); 1073 virtual tcu::TestStatus iterate (void); 1074 virtual float getLineWidth (void) const; 1075 1076 private: 1077 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL; 1078 1079 int m_iteration; 1080 const int m_iterationCount; 1081 VkPrimitiveTopology m_primitiveTopology; 1082 const PrimitiveWideness m_primitiveWideness; 1083 bool m_allIterationsPassed; 1084 float m_maxLineWidth; 1085 std::vector<float> m_lineWidths; 1086 }; 1087 1088 BaseLineTestInstance::BaseLineTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount) 1089 : BaseRenderingTestInstance (context, sampleCount) 1090 , m_iteration (0) 1091 , m_iterationCount (3) 1092 , m_primitiveTopology (primitiveTopology) 1093 , m_primitiveWideness (wideness) 1094 , m_allIterationsPassed (true) 1095 , m_maxLineWidth (1.0f) 1096 { 1097 DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST); 1098 1099 if (!context.getDeviceProperties().limits.strictLines) 1100 TCU_THROW(NotSupportedError, "Strict rasterization is not supported"); 1101 1102 // create line widths 1103 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW) 1104 { 1105 m_lineWidths.resize(m_iterationCount, 1.0f); 1106 } 1107 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) 1108 { 1109 if (!m_context.getDeviceFeatures().wideLines) 1110 TCU_THROW(NotSupportedError , "wide line support required"); 1111 1112 const float* range = context.getDeviceProperties().limits.lineWidthRange; 1113 1114 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage; 1115 1116 // no wide line support 1117 if (range[1] <= 1.0f) 1118 TCU_THROW(NotSupportedError, "wide line support required"); 1119 1120 // set hand picked sizes 1121 m_lineWidths.push_back(5.0f); 1122 m_lineWidths.push_back(10.0f); 1123 m_lineWidths.push_back(range[1]); 1124 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount); 1125 1126 m_maxLineWidth = range[1]; 1127 } 1128 else 1129 DE_ASSERT(false); 1130 } 1131 1132 tcu::TestStatus BaseLineTestInstance::iterate (void) 1133 { 1134 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 1135 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), iterationDescription, iterationDescription); 1136 const float lineWidth = getLineWidth(); 1137 tcu::Surface resultImage (m_renderSize, m_renderSize); 1138 std::vector<tcu::Vec4> drawBuffer; 1139 std::vector<LineSceneSpec::SceneLine> lines; 1140 1141 // supported? 1142 if (lineWidth <= m_maxLineWidth) 1143 { 1144 // gen data 1145 generateLines(m_iteration, drawBuffer, lines); 1146 1147 // draw image 1148 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology); 1149 1150 // compare 1151 { 1152 RasterizationArguments args; 1153 LineSceneSpec scene; 1154 1155 1156 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat()); 1157 1158 args.numSamples = m_multisampling ? 1 : 0; 1159 args.subpixelBits = m_subpixelBits; 1160 args.redBits = colorBits[0]; 1161 args.greenBits = colorBits[1]; 1162 args.blueBits = colorBits[2]; 1163 1164 scene.lines.swap(lines); 1165 scene.lineWidth = lineWidth; 1166 1167 if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog())) 1168 m_allIterationsPassed = false; 1169 } 1170 } 1171 else 1172 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage; 1173 1174 // result 1175 if (++m_iteration == m_iterationCount) 1176 { 1177 if (m_allIterationsPassed) 1178 return tcu::TestStatus::pass("Pass"); 1179 else 1180 return tcu::TestStatus::fail("Incorrect rasterization"); 1181 } 1182 else 1183 return tcu::TestStatus::incomplete(); 1184 } 1185 1186 1187 float BaseLineTestInstance::getLineWidth (void) const 1188 { 1189 return m_lineWidths[m_iteration]; 1190 } 1191 1192 1193 class PointTestInstance : public BaseRenderingTestInstance 1194 { 1195 public: 1196 PointTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount); 1197 virtual tcu::TestStatus iterate (void); 1198 virtual float getPointSize (void) const; 1199 1200 private: 1201 virtual void generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints); 1202 1203 int m_iteration; 1204 const int m_iterationCount; 1205 const PrimitiveWideness m_primitiveWideness; 1206 bool m_allIterationsPassed; 1207 float m_maxPointSize; 1208 std::vector<float> m_pointSizes; 1209 }; 1210 1211 PointTestInstance::PointTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount) 1212 : BaseRenderingTestInstance (context, sampleCount) 1213 , m_iteration (0) 1214 , m_iterationCount (3) 1215 , m_primitiveWideness (wideness) 1216 , m_allIterationsPassed (true) 1217 , m_maxPointSize (1.0f) 1218 { 1219 // create point sizes 1220 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW) 1221 { 1222 m_pointSizes.resize(m_iterationCount, 1.0f); 1223 } 1224 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) 1225 { 1226 if (!m_context.getDeviceFeatures().largePoints) 1227 TCU_THROW(NotSupportedError , "large point support required"); 1228 1229 const float* range = context.getDeviceProperties().limits.pointSizeRange; 1230 1231 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage; 1232 1233 // no wide line support 1234 if (range[1] <= 1.0f) 1235 TCU_THROW(NotSupportedError , "wide point support required"); 1236 1237 // set hand picked sizes 1238 m_pointSizes.push_back(10.0f); 1239 m_pointSizes.push_back(25.0f); 1240 m_pointSizes.push_back(range[1]); 1241 DE_ASSERT((int)m_pointSizes.size() == m_iterationCount); 1242 1243 m_maxPointSize = range[1]; 1244 } 1245 else 1246 DE_ASSERT(false); 1247 } 1248 1249 tcu::TestStatus PointTestInstance::iterate (void) 1250 { 1251 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 1252 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), iterationDescription, iterationDescription); 1253 const float pointSize = getPointSize(); 1254 tcu::Surface resultImage (m_renderSize, m_renderSize); 1255 std::vector<tcu::Vec4> drawBuffer; 1256 std::vector<PointSceneSpec::ScenePoint> points; 1257 1258 // supported? 1259 if (pointSize <= m_maxPointSize) 1260 { 1261 // gen data 1262 generatePoints(m_iteration, drawBuffer, points); 1263 1264 // draw image 1265 drawPrimitives(resultImage, drawBuffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST); 1266 1267 // compare 1268 { 1269 bool compareOk; 1270 RasterizationArguments args; 1271 PointSceneSpec scene; 1272 1273 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat()); 1274 1275 args.numSamples = m_multisampling ? 1 : 0; 1276 args.subpixelBits = m_subpixelBits; 1277 args.redBits = colorBits[0]; 1278 args.greenBits = colorBits[1]; 1279 args.blueBits = colorBits[2]; 1280 1281 scene.points.swap(points); 1282 1283 compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()); 1284 1285 if (!compareOk) 1286 m_allIterationsPassed = false; 1287 } 1288 } 1289 else 1290 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage; 1291 1292 // result 1293 if (++m_iteration == m_iterationCount) 1294 { 1295 if (m_allIterationsPassed) 1296 return tcu::TestStatus::pass("Pass"); 1297 else 1298 return tcu::TestStatus::fail("Incorrect rasterization"); 1299 } 1300 else 1301 return tcu::TestStatus::incomplete(); 1302 } 1303 1304 float PointTestInstance::getPointSize (void) const 1305 { 1306 return m_pointSizes[m_iteration]; 1307 } 1308 1309 void PointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints) 1310 { 1311 outData.resize(6); 1312 1313 switch (iteration) 1314 { 1315 case 0: 1316 // \note: these values are chosen arbitrarily 1317 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f); 1318 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 1319 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f); 1320 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 1321 outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f); 1322 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f); 1323 break; 1324 1325 case 1: 1326 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 1327 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 1328 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 1329 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1330 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 1331 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f); 1332 break; 1333 1334 case 2: 1335 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 1336 outData[1] = tcu::Vec4( 0.3f, -0.9f, 0.0f, 1.0f); 1337 outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f); 1338 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f); 1339 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 1340 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f); 1341 break; 1342 } 1343 1344 outPoints.resize(outData.size()); 1345 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx) 1346 { 1347 outPoints[pointNdx].position = outData[pointNdx]; 1348 outPoints[pointNdx].pointSize = getPointSize(); 1349 } 1350 1351 // log 1352 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage; 1353 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx) 1354 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage; 1355 } 1356 1357 template <typename ConcreteTestInstance> 1358 class BaseTestCase : public BaseRenderingTestCase 1359 { 1360 public: 1361 BaseTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT) 1362 : BaseRenderingTestCase(context, name, description, sampleCount) 1363 {} 1364 1365 virtual TestInstance* createInstance (Context& context) const 1366 { 1367 return new ConcreteTestInstance(context, m_sampleCount); 1368 } 1369 }; 1370 1371 class TrianglesTestInstance : public BaseTriangleTestInstance 1372 { 1373 public: 1374 TrianglesTestInstance (Context& context, VkSampleCountFlagBits sampleCount) 1375 : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, sampleCount) 1376 {} 1377 1378 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles); 1379 }; 1380 1381 void TrianglesTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) 1382 { 1383 outData.resize(6); 1384 1385 switch (iteration) 1386 { 1387 case 0: 1388 // \note: these values are chosen arbitrarily 1389 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f); 1390 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 1391 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f); 1392 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 1393 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f); 1394 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f); 1395 break; 1396 1397 case 1: 1398 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 1399 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 1400 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 1401 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1402 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 1403 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f); 1404 break; 1405 1406 case 2: 1407 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 1408 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 1409 outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f); 1410 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f); 1411 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 1412 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f); 1413 break; 1414 } 1415 1416 outTriangles.resize(2); 1417 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false; 1418 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false; 1419 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false; 1420 1421 outTriangles[1].positions[0] = outData[3]; outTriangles[1].sharedEdge[0] = false; 1422 outTriangles[1].positions[1] = outData[4]; outTriangles[1].sharedEdge[1] = false; 1423 outTriangles[1].positions[2] = outData[5]; outTriangles[1].sharedEdge[2] = false; 1424 1425 // log 1426 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage; 1427 for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx) 1428 { 1429 m_context.getTestContext().getLog() 1430 << tcu::TestLog::Message 1431 << "Triangle " << (triangleNdx+1) << ":" 1432 << "\n\t" << outTriangles[triangleNdx].positions[0] 1433 << "\n\t" << outTriangles[triangleNdx].positions[1] 1434 << "\n\t" << outTriangles[triangleNdx].positions[2] 1435 << tcu::TestLog::EndMessage; 1436 } 1437 } 1438 1439 class TriangleStripTestInstance : public BaseTriangleTestInstance 1440 { 1441 public: 1442 TriangleStripTestInstance (Context& context, VkSampleCountFlagBits sampleCount) 1443 : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, sampleCount) 1444 {} 1445 1446 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles); 1447 }; 1448 1449 void TriangleStripTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) 1450 { 1451 outData.resize(5); 1452 1453 switch (iteration) 1454 { 1455 case 0: 1456 // \note: these values are chosen arbitrarily 1457 outData[0] = tcu::Vec4(-0.504f, 0.8f, 0.0f, 1.0f); 1458 outData[1] = tcu::Vec4(-0.2f, -0.2f, 0.0f, 1.0f); 1459 outData[2] = tcu::Vec4(-0.2f, 0.199f, 0.0f, 1.0f); 1460 outData[3] = tcu::Vec4( 0.5f, 0.201f, 0.0f, 1.0f); 1461 outData[4] = tcu::Vec4( 1.5f, 0.4f, 0.0f, 1.0f); 1462 break; 1463 1464 case 1: 1465 outData[0] = tcu::Vec4(-0.499f, 0.129f, 0.0f, 1.0f); 1466 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 1467 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 1468 outData[3] = tcu::Vec4( 0.11f, -0.31f, 0.0f, 1.0f); 1469 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 1470 break; 1471 1472 case 2: 1473 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 1474 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 1475 outData[2] = tcu::Vec4(-0.87f, -0.1f, 0.0f, 1.0f); 1476 outData[3] = tcu::Vec4(-0.11f, 0.19f, 0.0f, 1.0f); 1477 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 1478 break; 1479 } 1480 1481 outTriangles.resize(3); 1482 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false; 1483 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = true; 1484 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false; 1485 1486 outTriangles[1].positions[0] = outData[2]; outTriangles[1].sharedEdge[0] = true; 1487 outTriangles[1].positions[1] = outData[1]; outTriangles[1].sharedEdge[1] = false; 1488 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true; 1489 1490 outTriangles[2].positions[0] = outData[2]; outTriangles[2].sharedEdge[0] = true; 1491 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false; 1492 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false; 1493 1494 // log 1495 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage; 1496 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 1497 { 1498 m_context.getTestContext().getLog() 1499 << tcu::TestLog::Message 1500 << "\t" << outData[vtxNdx] 1501 << tcu::TestLog::EndMessage; 1502 } 1503 } 1504 1505 class TriangleFanTestInstance : public BaseTriangleTestInstance 1506 { 1507 public: 1508 TriangleFanTestInstance (Context& context, VkSampleCountFlagBits sampleCount) 1509 : BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, sampleCount) 1510 {} 1511 1512 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles); 1513 }; 1514 1515 void TriangleFanTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) 1516 { 1517 outData.resize(5); 1518 1519 switch (iteration) 1520 { 1521 case 0: 1522 // \note: these values are chosen arbitrarily 1523 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f); 1524 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 1525 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f); 1526 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 1527 outData[4] = tcu::Vec4(-1.5f, -0.4f, 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 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 1536 break; 1537 1538 case 2: 1539 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 1540 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 1541 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f); 1542 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1543 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 1544 break; 1545 } 1546 1547 outTriangles.resize(3); 1548 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false; 1549 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false; 1550 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = true; 1551 1552 outTriangles[1].positions[0] = outData[0]; outTriangles[1].sharedEdge[0] = true; 1553 outTriangles[1].positions[1] = outData[2]; outTriangles[1].sharedEdge[1] = false; 1554 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true; 1555 1556 outTriangles[2].positions[0] = outData[0]; outTriangles[2].sharedEdge[0] = true; 1557 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false; 1558 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false; 1559 1560 // log 1561 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage; 1562 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 1563 { 1564 m_context.getTestContext().getLog() 1565 << tcu::TestLog::Message 1566 << "\t" << outData[vtxNdx] 1567 << tcu::TestLog::EndMessage; 1568 } 1569 } 1570 1571 template <typename ConcreteTestInstance> 1572 class WidenessTestCase : public BaseRenderingTestCase 1573 { 1574 public: 1575 WidenessTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT) 1576 : BaseRenderingTestCase(context, name, description, sampleCount) 1577 , m_wideness(wideness) 1578 {} 1579 1580 virtual TestInstance* createInstance (Context& context) const 1581 { 1582 return new ConcreteTestInstance(context, m_wideness, m_sampleCount); 1583 } 1584 protected: 1585 const PrimitiveWideness m_wideness; 1586 }; 1587 1588 class LinesTestInstance : public BaseLineTestInstance 1589 { 1590 public: 1591 LinesTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount) 1592 : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, sampleCount) 1593 {} 1594 1595 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines); 1596 }; 1597 1598 void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) 1599 { 1600 outData.resize(6); 1601 1602 switch (iteration) 1603 { 1604 case 0: 1605 // \note: these values are chosen arbitrarily 1606 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f); 1607 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 1608 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f); 1609 outData[3] = tcu::Vec4(-0.3f, 0.2f, 0.0f, 1.0f); 1610 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f); 1611 outData[5] = tcu::Vec4( 0.1f, 0.5f, 0.0f, 1.0f); 1612 break; 1613 1614 case 1: 1615 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 1616 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 1617 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 1618 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1619 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 1620 outData[5] = tcu::Vec4( 0.18f, -0.2f, 0.0f, 1.0f); 1621 break; 1622 1623 case 2: 1624 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 1625 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 1626 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f); 1627 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1628 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 1629 outData[5] = tcu::Vec4( 0.8f, -0.7f, 0.0f, 1.0f); 1630 break; 1631 } 1632 1633 outLines.resize(3); 1634 outLines[0].positions[0] = outData[0]; 1635 outLines[0].positions[1] = outData[1]; 1636 outLines[1].positions[0] = outData[2]; 1637 outLines[1].positions[1] = outData[3]; 1638 outLines[2].positions[0] = outData[4]; 1639 outLines[2].positions[1] = outData[5]; 1640 1641 // log 1642 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage; 1643 for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx) 1644 { 1645 m_context.getTestContext().getLog() 1646 << tcu::TestLog::Message 1647 << "Line " << (lineNdx+1) << ":" 1648 << "\n\t" << outLines[lineNdx].positions[0] 1649 << "\n\t" << outLines[lineNdx].positions[1] 1650 << tcu::TestLog::EndMessage; 1651 } 1652 } 1653 1654 class LineStripTestInstance : public BaseLineTestInstance 1655 { 1656 public: 1657 LineStripTestInstance (Context& context, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount) 1658 : BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, sampleCount) 1659 {} 1660 1661 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines); 1662 }; 1663 1664 void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) 1665 { 1666 outData.resize(4); 1667 1668 switch (iteration) 1669 { 1670 case 0: 1671 // \note: these values are chosen arbitrarily 1672 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f); 1673 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 1674 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f); 1675 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 1676 break; 1677 1678 case 1: 1679 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 1680 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 1681 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 1682 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1683 break; 1684 1685 case 2: 1686 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 1687 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 1688 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f); 1689 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1690 break; 1691 } 1692 1693 outLines.resize(3); 1694 outLines[0].positions[0] = outData[0]; 1695 outLines[0].positions[1] = outData[1]; 1696 outLines[1].positions[0] = outData[1]; 1697 outLines[1].positions[1] = outData[2]; 1698 outLines[2].positions[0] = outData[2]; 1699 outLines[2].positions[1] = outData[3]; 1700 1701 // log 1702 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage; 1703 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 1704 { 1705 m_context.getTestContext().getLog() 1706 << tcu::TestLog::Message 1707 << "\t" << outData[vtxNdx] 1708 << tcu::TestLog::EndMessage; 1709 } 1710 } 1711 1712 class FillRuleTestInstance : public BaseRenderingTestInstance 1713 { 1714 public: 1715 enum FillRuleCaseType 1716 { 1717 FILLRULECASE_BASIC = 0, 1718 FILLRULECASE_REVERSED, 1719 FILLRULECASE_CLIPPED_FULL, 1720 FILLRULECASE_CLIPPED_PARTIAL, 1721 FILLRULECASE_PROJECTED, 1722 1723 FILLRULECASE_LAST 1724 }; 1725 FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount); 1726 virtual tcu::TestStatus iterate (void); 1727 1728 private: 1729 1730 virtual const VkPipelineColorBlendStateCreateInfo* getColorBlendStateCreateInfo (void) const; 1731 int getRenderSize (FillRuleCaseType type) const; 1732 int getNumIterations (FillRuleCaseType type) const; 1733 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const; 1734 1735 const FillRuleCaseType m_caseType; 1736 int m_iteration; 1737 const int m_iterationCount; 1738 bool m_allIterationsPassed; 1739 1740 }; 1741 1742 FillRuleTestInstance::FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount) 1743 : BaseRenderingTestInstance (context, sampleCount, getRenderSize(type)) 1744 , m_caseType (type) 1745 , m_iteration (0) 1746 , m_iterationCount (getNumIterations(type)) 1747 , m_allIterationsPassed (true) 1748 { 1749 DE_ASSERT(type < FILLRULECASE_LAST); 1750 } 1751 1752 tcu::TestStatus FillRuleTestInstance::iterate (void) 1753 { 1754 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 1755 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), iterationDescription, iterationDescription); 1756 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat()); 1757 const int thresholdRed = 1 << (8 - colorBits[0]); 1758 const int thresholdGreen = 1 << (8 - colorBits[1]); 1759 const int thresholdBlue = 1 << (8 - colorBits[2]); 1760 tcu::Surface resultImage (m_renderSize, m_renderSize); 1761 std::vector<tcu::Vec4> drawBuffer; 1762 1763 generateTriangles(m_iteration, drawBuffer); 1764 1765 // draw image 1766 { 1767 const std::vector<tcu::Vec4> colorBuffer (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f)); 1768 1769 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage; 1770 1771 drawPrimitives(resultImage, drawBuffer, colorBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); 1772 } 1773 1774 // verify no overdraw 1775 { 1776 const tcu::RGBA triangleColor = tcu::RGBA(127, 127, 127, 255); 1777 bool overdraw = false; 1778 1779 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage; 1780 1781 for (int y = 0; y < resultImage.getHeight(); ++y) 1782 for (int x = 0; x < resultImage.getWidth(); ++x) 1783 { 1784 const tcu::RGBA color = resultImage.getPixel(x, y); 1785 1786 // color values are greater than triangle color? Allow lower values for multisampled edges and background. 1787 if ((color.getRed() - triangleColor.getRed()) > thresholdRed || 1788 (color.getGreen() - triangleColor.getGreen()) > thresholdGreen || 1789 (color.getBlue() - triangleColor.getBlue()) > thresholdBlue) 1790 overdraw = true; 1791 } 1792 1793 // results 1794 if (!overdraw) 1795 m_context.getTestContext().getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage; 1796 else 1797 { 1798 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage; 1799 m_allIterationsPassed = false; 1800 } 1801 } 1802 1803 // verify no missing fragments in the full viewport case 1804 if (m_caseType == FILLRULECASE_CLIPPED_FULL) 1805 { 1806 bool missingFragments = false; 1807 1808 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage; 1809 1810 for (int y = 0; y < resultImage.getHeight(); ++y) 1811 for (int x = 0; x < resultImage.getWidth(); ++x) 1812 { 1813 const tcu::RGBA color = resultImage.getPixel(x, y); 1814 1815 // black? (background) 1816 if (color.getRed() <= thresholdRed || 1817 color.getGreen() <= thresholdGreen || 1818 color.getBlue() <= thresholdBlue) 1819 missingFragments = true; 1820 } 1821 1822 // results 1823 if (!missingFragments) 1824 m_context.getTestContext().getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage; 1825 else 1826 { 1827 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage; 1828 1829 m_allIterationsPassed = false; 1830 } 1831 } 1832 1833 m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering") 1834 << tcu::TestLog::Image("Result", "Result", resultImage) 1835 << tcu::TestLog::EndImageSet; 1836 1837 // result 1838 if (++m_iteration == m_iterationCount) 1839 { 1840 if (m_allIterationsPassed) 1841 return tcu::TestStatus::pass("Pass"); 1842 else 1843 return tcu::TestStatus::fail("Found invalid pixels"); 1844 } 1845 else 1846 return tcu::TestStatus::incomplete(); 1847 } 1848 1849 int FillRuleTestInstance::getRenderSize (FillRuleCaseType type) const 1850 { 1851 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL) 1852 return DEFAULT_RENDER_SIZE / 4; 1853 else 1854 return DEFAULT_RENDER_SIZE; 1855 } 1856 1857 int FillRuleTestInstance::getNumIterations (FillRuleCaseType type) const 1858 { 1859 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL) 1860 return 15; 1861 else 1862 return 2; 1863 } 1864 1865 void FillRuleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const 1866 { 1867 switch (m_caseType) 1868 { 1869 case FILLRULECASE_BASIC: 1870 case FILLRULECASE_REVERSED: 1871 case FILLRULECASE_PROJECTED: 1872 { 1873 const int numRows = 4; 1874 const int numColumns = 4; 1875 const float quadSide = 0.15f; 1876 de::Random rnd (0xabcd); 1877 1878 outData.resize(6 * numRows * numColumns); 1879 1880 for (int col = 0; col < numColumns; ++col) 1881 for (int row = 0; row < numRows; ++row) 1882 { 1883 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); 1884 const float rotation = (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f; 1885 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation)); 1886 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x()); 1887 const tcu::Vec2 quad[4] = 1888 { 1889 center + sideH + sideV, 1890 center + sideH - sideV, 1891 center - sideH - sideV, 1892 center - sideH + sideV, 1893 }; 1894 1895 if (m_caseType == FILLRULECASE_BASIC) 1896 { 1897 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1898 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f); 1899 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1900 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1901 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1902 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f); 1903 } 1904 else if (m_caseType == FILLRULECASE_REVERSED) 1905 { 1906 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1907 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f); 1908 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1909 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1910 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1911 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f); 1912 } 1913 else if (m_caseType == FILLRULECASE_PROJECTED) 1914 { 1915 const float w0 = rnd.getFloat(0.1f, 4.0f); 1916 const float w1 = rnd.getFloat(0.1f, 4.0f); 1917 const float w2 = rnd.getFloat(0.1f, 4.0f); 1918 const float w3 = rnd.getFloat(0.1f, 4.0f); 1919 1920 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0); 1921 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1); 1922 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2); 1923 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2); 1924 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0); 1925 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3); 1926 } 1927 else 1928 DE_ASSERT(DE_FALSE); 1929 } 1930 1931 break; 1932 } 1933 1934 case FILLRULECASE_CLIPPED_PARTIAL: 1935 case FILLRULECASE_CLIPPED_FULL: 1936 { 1937 const float quadSide = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f); 1938 const tcu::Vec2 center = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f)); 1939 const float rotation = (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f; 1940 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation)); 1941 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x()); 1942 const tcu::Vec2 quad[4] = 1943 { 1944 center + sideH + sideV, 1945 center + sideH - sideV, 1946 center - sideH - sideV, 1947 center - sideH + sideV, 1948 }; 1949 1950 outData.resize(6); 1951 outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1952 outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f); 1953 outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1954 outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1955 outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1956 outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f); 1957 break; 1958 } 1959 1960 default: 1961 DE_ASSERT(DE_FALSE); 1962 } 1963 } 1964 1965 const VkPipelineColorBlendStateCreateInfo* FillRuleTestInstance::getColorBlendStateCreateInfo (void) const 1966 { 1967 static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 1968 { 1969 true, // VkBool32 blendEnable; 1970 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor; 1971 VK_BLEND_FACTOR_ONE, // VkBlend destBlendColor; 1972 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; 1973 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha; 1974 VK_BLEND_FACTOR_ONE, // VkBlend destBlendAlpha; 1975 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; 1976 (VK_COLOR_COMPONENT_R_BIT | 1977 VK_COLOR_COMPONENT_G_BIT | 1978 VK_COLOR_COMPONENT_B_BIT | 1979 VK_COLOR_COMPONENT_A_BIT) // VkChannelFlags channelWriteMask; 1980 }; 1981 1982 static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 1983 { 1984 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 1985 DE_NULL, // const void* pNext; 1986 0, // VkPipelineColorBlendStateCreateFlags flags; 1987 false, // VkBool32 logicOpEnable; 1988 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 1989 1u, // deUint32 attachmentCount; 1990 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 1991 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; 1992 }; 1993 1994 return &colorBlendStateParams; 1995 } 1996 1997 1998 class FillRuleTestCase : public BaseRenderingTestCase 1999 { 2000 public: 2001 FillRuleTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, FillRuleTestInstance::FillRuleCaseType type, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT) 2002 : BaseRenderingTestCase (context, name, description, sampleCount) 2003 , m_type (type) 2004 {} 2005 2006 virtual TestInstance* createInstance (Context& context) const 2007 { 2008 return new FillRuleTestInstance(context, m_type, m_sampleCount); 2009 } 2010 protected: 2011 const FillRuleTestInstance::FillRuleCaseType m_type; 2012 }; 2013 2014 class CullingTestInstance : public BaseRenderingTestInstance 2015 { 2016 public: 2017 CullingTestInstance (Context& context, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode) 2018 : BaseRenderingTestInstance (context, VK_SAMPLE_COUNT_1_BIT, DEFAULT_RENDER_SIZE) 2019 , m_cullMode (cullMode) 2020 , m_primitiveTopology (primitiveTopology) 2021 , m_frontFace (frontFace) 2022 , m_polygonMode (polygonMode) 2023 , m_multisampling (true) 2024 {} 2025 virtual 2026 const VkPipelineRasterizationStateCreateInfo* getRasterizationStateCreateInfo (void) const; 2027 2028 tcu::TestStatus iterate (void); 2029 2030 private: 2031 void generateVertices (std::vector<tcu::Vec4>& outData) const; 2032 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const; 2033 void extractLines (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<LineSceneSpec::SceneLine>& outLines) const; 2034 void extractPoints (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<PointSceneSpec::ScenePoint>& outPoints) const; 2035 bool triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const; 2036 2037 const VkCullModeFlags m_cullMode; 2038 const VkPrimitiveTopology m_primitiveTopology; 2039 const VkFrontFace m_frontFace; 2040 const VkPolygonMode m_polygonMode; 2041 const bool m_multisampling; 2042 }; 2043 2044 2045 tcu::TestStatus CullingTestInstance::iterate (void) 2046 { 2047 DE_ASSERT(m_polygonMode <= VK_POLYGON_MODE_POINT); 2048 2049 tcu::Surface resultImage (m_renderSize, m_renderSize); 2050 std::vector<tcu::Vec4> drawBuffer; 2051 std::vector<TriangleSceneSpec::SceneTriangle> triangles; 2052 std::vector<PointSceneSpec::ScenePoint> points; 2053 std::vector<LineSceneSpec::SceneLine> lines; 2054 2055 const InstanceInterface& vk = m_context.getInstanceInterface(); 2056 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 2057 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(vk, physicalDevice); 2058 2059 if (!(deviceFeatures.fillModeNonSolid) && (m_polygonMode == VK_POLYGON_MODE_LINE || m_polygonMode == VK_POLYGON_MODE_POINT)) 2060 TCU_THROW(NotSupportedError, "Wireframe fill modes are not supported"); 2061 2062 // generate scene 2063 generateVertices(drawBuffer); 2064 extractTriangles(triangles, drawBuffer); 2065 2066 if (m_polygonMode == VK_POLYGON_MODE_LINE) 2067 extractLines(triangles ,lines); 2068 else if (m_polygonMode == VK_POLYGON_MODE_POINT) 2069 extractPoints(triangles, points); 2070 2071 // draw image 2072 { 2073 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting front face to " << m_frontFace << tcu::TestLog::EndMessage; 2074 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting cull face to " << m_cullMode << tcu::TestLog::EndMessage; 2075 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing test pattern (" << m_primitiveTopology << ")" << tcu::TestLog::EndMessage; 2076 2077 drawPrimitives(resultImage, drawBuffer, m_primitiveTopology); 2078 } 2079 2080 // compare 2081 { 2082 RasterizationArguments args; 2083 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat()); 2084 bool isCompareOk = false; 2085 2086 args.numSamples = m_multisampling ? 1 : 0; 2087 args.subpixelBits = m_subpixelBits; 2088 args.redBits = colorBits[0]; 2089 args.greenBits = colorBits[1]; 2090 args.blueBits = colorBits[2]; 2091 2092 switch (m_polygonMode) 2093 { 2094 case VK_POLYGON_MODE_LINE: 2095 { 2096 LineSceneSpec scene; 2097 scene.lineWidth = 0; 2098 scene.lines.swap(lines); 2099 isCompareOk = verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()); 2100 break; 2101 } 2102 case VK_POLYGON_MODE_POINT: 2103 { 2104 PointSceneSpec scene; 2105 scene.points.swap(points); 2106 isCompareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()); 2107 break; 2108 } 2109 default: 2110 { 2111 TriangleSceneSpec scene; 2112 scene.triangles.swap(triangles); 2113 isCompareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), tcu::VERIFICATIONMODE_WEAK); 2114 break; 2115 } 2116 } 2117 2118 if (isCompareOk) 2119 return tcu::TestStatus::pass("Pass"); 2120 else 2121 return tcu::TestStatus::fail("Incorrect rendering"); 2122 } 2123 } 2124 2125 void CullingTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const 2126 { 2127 de::Random rnd(543210); 2128 2129 outData.resize(6); 2130 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 2131 { 2132 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f); 2133 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f); 2134 outData[vtxNdx].z() = 0.0f; 2135 outData[vtxNdx].w() = 1.0f; 2136 } 2137 } 2138 2139 void CullingTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const 2140 { 2141 const bool cullDirection = (m_cullMode == VK_CULL_MODE_FRONT_BIT) ^ (m_frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE); 2142 2143 // No triangles 2144 if (m_cullMode == VK_CULL_MODE_FRONT_AND_BACK) 2145 return; 2146 2147 switch (m_primitiveTopology) 2148 { 2149 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 2150 { 2151 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3) 2152 { 2153 const tcu::Vec4& v0 = vertices[vtxNdx + 0]; 2154 const tcu::Vec4& v1 = vertices[vtxNdx + 1]; 2155 const tcu::Vec4& v2 = vertices[vtxNdx + 2]; 2156 2157 if (triangleOrder(v0, v1, v2) != cullDirection) 2158 { 2159 TriangleSceneSpec::SceneTriangle tri; 2160 tri.positions[0] = v0; tri.sharedEdge[0] = false; 2161 tri.positions[1] = v1; tri.sharedEdge[1] = false; 2162 tri.positions[2] = v2; tri.sharedEdge[2] = false; 2163 2164 outTriangles.push_back(tri); 2165 } 2166 } 2167 break; 2168 } 2169 2170 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 2171 { 2172 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx) 2173 { 2174 const tcu::Vec4& v0 = vertices[vtxNdx + 0]; 2175 const tcu::Vec4& v1 = vertices[vtxNdx + 1]; 2176 const tcu::Vec4& v2 = vertices[vtxNdx + 2]; 2177 2178 if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0))) 2179 { 2180 TriangleSceneSpec::SceneTriangle tri; 2181 tri.positions[0] = v0; tri.sharedEdge[0] = false; 2182 tri.positions[1] = v1; tri.sharedEdge[1] = false; 2183 tri.positions[2] = v2; tri.sharedEdge[2] = false; 2184 2185 outTriangles.push_back(tri); 2186 } 2187 } 2188 break; 2189 } 2190 2191 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 2192 { 2193 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx) 2194 { 2195 const tcu::Vec4& v0 = vertices[0]; 2196 const tcu::Vec4& v1 = vertices[vtxNdx + 0]; 2197 const tcu::Vec4& v2 = vertices[vtxNdx + 1]; 2198 2199 if (triangleOrder(v0, v1, v2) != cullDirection) 2200 { 2201 TriangleSceneSpec::SceneTriangle tri; 2202 tri.positions[0] = v0; tri.sharedEdge[0] = false; 2203 tri.positions[1] = v1; tri.sharedEdge[1] = false; 2204 tri.positions[2] = v2; tri.sharedEdge[2] = false; 2205 2206 outTriangles.push_back(tri); 2207 } 2208 } 2209 break; 2210 } 2211 2212 default: 2213 DE_ASSERT(false); 2214 } 2215 } 2216 2217 void CullingTestInstance::extractLines (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, 2218 std::vector<LineSceneSpec::SceneLine>& outLines) const 2219 { 2220 for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx) 2221 { 2222 for (int vrtxNdx = 0; vrtxNdx < 2; ++vrtxNdx) 2223 { 2224 LineSceneSpec::SceneLine line; 2225 line.positions[0] = outTriangles.at(triNdx).positions[vrtxNdx]; 2226 line.positions[1] = outTriangles.at(triNdx).positions[vrtxNdx + 1]; 2227 2228 outLines.push_back(line); 2229 } 2230 LineSceneSpec::SceneLine line; 2231 line.positions[0] = outTriangles.at(triNdx).positions[2]; 2232 line.positions[1] = outTriangles.at(triNdx).positions[0]; 2233 outLines.push_back(line); 2234 } 2235 } 2236 2237 void CullingTestInstance::extractPoints (std::vector<TriangleSceneSpec::SceneTriangle> &outTriangles, 2238 std::vector<PointSceneSpec::ScenePoint> &outPoints) const 2239 { 2240 for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx) 2241 { 2242 for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx) 2243 { 2244 PointSceneSpec::ScenePoint point; 2245 point.position = outTriangles.at(triNdx).positions[vrtxNdx]; 2246 point.pointSize = 1.0f; 2247 2248 outPoints.push_back(point); 2249 } 2250 } 2251 } 2252 2253 bool CullingTestInstance::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const 2254 { 2255 const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w(); 2256 const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w(); 2257 const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w(); 2258 2259 // cross 2260 return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) > 0; 2261 } 2262 2263 2264 const VkPipelineRasterizationStateCreateInfo* CullingTestInstance::getRasterizationStateCreateInfo (void) const 2265 { 2266 static VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = 2267 { 2268 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 2269 DE_NULL, // const void* pNext; 2270 0, // VkPipelineRasterizationStateCreateFlags flags; 2271 false, // VkBool32 depthClipEnable; 2272 false, // VkBool32 rasterizerDiscardEnable; 2273 VK_POLYGON_MODE_FILL, // VkFillMode fillMode; 2274 VK_CULL_MODE_NONE, // VkCullMode cullMode; 2275 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 2276 VK_FALSE, // VkBool32 depthBiasEnable; 2277 0.0f, // float depthBias; 2278 0.0f, // float depthBiasClamp; 2279 0.0f, // float slopeScaledDepthBias; 2280 getLineWidth(), // float lineWidth; 2281 }; 2282 2283 rasterizationStateCreateInfo.lineWidth = getLineWidth(); 2284 rasterizationStateCreateInfo.cullMode = m_cullMode; 2285 rasterizationStateCreateInfo.frontFace = m_frontFace; 2286 rasterizationStateCreateInfo.polygonMode = m_polygonMode; 2287 2288 return &rasterizationStateCreateInfo; 2289 } 2290 2291 class CullingTestCase : public BaseRenderingTestCase 2292 { 2293 public: 2294 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) 2295 : BaseRenderingTestCase (context, name, description, sampleCount) 2296 , m_cullMode (cullMode) 2297 , m_primitiveTopology (primitiveTopology) 2298 , m_frontFace (frontFace) 2299 , m_polygonMode (polygonMode) 2300 {} 2301 2302 virtual TestInstance* createInstance (Context& context) const 2303 { 2304 return new CullingTestInstance(context, m_cullMode, m_primitiveTopology, m_frontFace, m_polygonMode); 2305 } 2306 protected: 2307 const VkCullModeFlags m_cullMode; 2308 const VkPrimitiveTopology m_primitiveTopology; 2309 const VkFrontFace m_frontFace; 2310 const VkPolygonMode m_polygonMode; 2311 }; 2312 2313 class TriangleInterpolationTestInstance : public BaseRenderingTestInstance 2314 { 2315 public: 2316 2317 TriangleInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount) 2318 : BaseRenderingTestInstance (context, sampleCount, DEFAULT_RENDER_SIZE) 2319 , m_primitiveTopology (primitiveTopology) 2320 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0) 2321 , m_iterationCount (3) 2322 , m_iteration (0) 2323 , m_allIterationsPassed (true) 2324 , m_flatshade ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0) 2325 {} 2326 2327 tcu::TestStatus iterate (void); 2328 2329 2330 private: 2331 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const; 2332 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const; 2333 2334 2335 VkPrimitiveTopology m_primitiveTopology; 2336 const bool m_projective; 2337 const int m_iterationCount; 2338 int m_iteration; 2339 bool m_allIterationsPassed; 2340 const deBool m_flatshade; 2341 }; 2342 2343 tcu::TestStatus TriangleInterpolationTestInstance::iterate (void) 2344 { 2345 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 2346 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription); 2347 tcu::Surface resultImage (m_renderSize, m_renderSize); 2348 std::vector<tcu::Vec4> drawBuffer; 2349 std::vector<tcu::Vec4> colorBuffer; 2350 std::vector<TriangleSceneSpec::SceneTriangle> triangles; 2351 2352 // generate scene 2353 generateVertices(m_iteration, drawBuffer, colorBuffer); 2354 extractTriangles(triangles, drawBuffer, colorBuffer); 2355 2356 // log 2357 { 2358 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage; 2359 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx) 2360 m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage; 2361 } 2362 2363 // draw image 2364 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology); 2365 2366 // compare 2367 { 2368 RasterizationArguments args; 2369 TriangleSceneSpec scene; 2370 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat()); 2371 2372 args.numSamples = m_multisampling ? 1 : 0; 2373 args.subpixelBits = m_subpixelBits; 2374 args.redBits = colorBits[0]; 2375 args.greenBits = colorBits[1]; 2376 args.blueBits = colorBits[2]; 2377 2378 scene.triangles.swap(triangles); 2379 2380 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog())) 2381 m_allIterationsPassed = false; 2382 } 2383 2384 // result 2385 if (++m_iteration == m_iterationCount) 2386 { 2387 if (m_allIterationsPassed) 2388 return tcu::TestStatus::pass("Pass"); 2389 else 2390 return tcu::TestStatus::fail("Found invalid pixel values"); 2391 } 2392 else 2393 return tcu::TestStatus::incomplete(); 2394 } 2395 2396 void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const 2397 { 2398 // use only red, green and blue 2399 const tcu::Vec4 colors[] = 2400 { 2401 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), 2402 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), 2403 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), 2404 }; 2405 2406 de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology); 2407 2408 outVertices.resize(6); 2409 outColors.resize(6); 2410 2411 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx) 2412 { 2413 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f); 2414 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f); 2415 outVertices[vtxNdx].z() = 0.0f; 2416 2417 if (!m_projective) 2418 outVertices[vtxNdx].w() = 1.0f; 2419 else 2420 { 2421 const float w = rnd.getFloat(0.2f, 4.0f); 2422 2423 outVertices[vtxNdx].x() *= w; 2424 outVertices[vtxNdx].y() *= w; 2425 outVertices[vtxNdx].z() *= w; 2426 outVertices[vtxNdx].w() = w; 2427 } 2428 2429 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)]; 2430 } 2431 } 2432 2433 void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const 2434 { 2435 switch (m_primitiveTopology) 2436 { 2437 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 2438 { 2439 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3) 2440 { 2441 TriangleSceneSpec::SceneTriangle tri; 2442 tri.positions[0] = vertices[vtxNdx + 0]; 2443 tri.positions[1] = vertices[vtxNdx + 1]; 2444 tri.positions[2] = vertices[vtxNdx + 2]; 2445 tri.sharedEdge[0] = false; 2446 tri.sharedEdge[1] = false; 2447 tri.sharedEdge[2] = false; 2448 2449 if (m_flatshade) 2450 { 2451 tri.colors[0] = colors[vtxNdx]; 2452 tri.colors[1] = colors[vtxNdx]; 2453 tri.colors[2] = colors[vtxNdx]; 2454 } 2455 else 2456 { 2457 tri.colors[0] = colors[vtxNdx + 0]; 2458 tri.colors[1] = colors[vtxNdx + 1]; 2459 tri.colors[2] = colors[vtxNdx + 2]; 2460 } 2461 2462 outTriangles.push_back(tri); 2463 } 2464 break; 2465 } 2466 2467 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 2468 { 2469 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx) 2470 { 2471 TriangleSceneSpec::SceneTriangle tri; 2472 tri.positions[0] = vertices[vtxNdx + 0]; 2473 tri.positions[1] = vertices[vtxNdx + 1]; 2474 tri.positions[2] = vertices[vtxNdx + 2]; 2475 tri.sharedEdge[0] = false; 2476 tri.sharedEdge[1] = false; 2477 tri.sharedEdge[2] = false; 2478 2479 if (m_flatshade) 2480 { 2481 tri.colors[0] = colors[vtxNdx]; 2482 tri.colors[1] = colors[vtxNdx]; 2483 tri.colors[2] = colors[vtxNdx]; 2484 } 2485 else 2486 { 2487 tri.colors[0] = colors[vtxNdx + 0]; 2488 tri.colors[1] = colors[vtxNdx + 1]; 2489 tri.colors[2] = colors[vtxNdx + 2]; 2490 } 2491 2492 outTriangles.push_back(tri); 2493 } 2494 break; 2495 } 2496 2497 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 2498 { 2499 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx) 2500 { 2501 TriangleSceneSpec::SceneTriangle tri; 2502 tri.positions[0] = vertices[0]; 2503 tri.positions[1] = vertices[vtxNdx + 0]; 2504 tri.positions[2] = vertices[vtxNdx + 1]; 2505 tri.sharedEdge[0] = false; 2506 tri.sharedEdge[1] = false; 2507 tri.sharedEdge[2] = false; 2508 2509 if (m_flatshade) 2510 { 2511 tri.colors[0] = colors[vtxNdx]; 2512 tri.colors[1] = colors[vtxNdx]; 2513 tri.colors[2] = colors[vtxNdx]; 2514 } 2515 else 2516 { 2517 tri.colors[0] = colors[0]; 2518 tri.colors[1] = colors[vtxNdx + 0]; 2519 tri.colors[2] = colors[vtxNdx + 1]; 2520 } 2521 2522 outTriangles.push_back(tri); 2523 } 2524 break; 2525 } 2526 2527 default: 2528 DE_ASSERT(false); 2529 } 2530 } 2531 2532 class TriangleInterpolationTestCase : public BaseRenderingTestCase 2533 { 2534 public: 2535 TriangleInterpolationTestCase (tcu::TestContext& context, const std::string& name, const std::string& description, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT) 2536 : BaseRenderingTestCase (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0) 2537 , m_primitiveTopology (primitiveTopology) 2538 , m_flags (flags) 2539 {} 2540 2541 virtual TestInstance* createInstance (Context& context) const 2542 { 2543 return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount); 2544 } 2545 protected: 2546 const VkPrimitiveTopology m_primitiveTopology; 2547 const int m_flags; 2548 }; 2549 2550 class LineInterpolationTestInstance : public BaseRenderingTestInstance 2551 { 2552 public: 2553 LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount); 2554 2555 virtual tcu::TestStatus iterate (void); 2556 2557 private: 2558 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const; 2559 void extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const; 2560 virtual float getLineWidth (void) const; 2561 2562 VkPrimitiveTopology m_primitiveTopology; 2563 const bool m_projective; 2564 const int m_iterationCount; 2565 const PrimitiveWideness m_primitiveWideness; 2566 2567 int m_iteration; 2568 bool m_allIterationsPassed; 2569 float m_maxLineWidth; 2570 std::vector<float> m_lineWidths; 2571 bool m_flatshade; 2572 }; 2573 2574 LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, VkSampleCountFlagBits sampleCount) 2575 : BaseRenderingTestInstance (context, sampleCount) 2576 , m_primitiveTopology (primitiveTopology) 2577 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0) 2578 , m_iterationCount (3) 2579 , m_primitiveWideness (wideness) 2580 , m_iteration (0) 2581 , m_allIterationsPassed (true) 2582 , m_maxLineWidth (1.0f) 2583 , m_flatshade ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0) 2584 { 2585 DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST); 2586 2587 if (!context.getDeviceProperties().limits.strictLines) 2588 TCU_THROW(NotSupportedError, "Strict rasterization is not supported"); 2589 2590 // create line widths 2591 if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW) 2592 { 2593 m_lineWidths.resize(m_iterationCount, 1.0f); 2594 } 2595 else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) 2596 { 2597 if (!m_context.getDeviceFeatures().wideLines) 2598 TCU_THROW(NotSupportedError , "wide line support required"); 2599 2600 const float* range = context.getDeviceProperties().limits.lineWidthRange; 2601 2602 m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage; 2603 2604 // no wide line support 2605 if (range[1] <= 1.0f) 2606 throw tcu::NotSupportedError("wide line support required"); 2607 2608 // set hand picked sizes 2609 m_lineWidths.push_back(5.0f); 2610 m_lineWidths.push_back(10.0f); 2611 m_lineWidths.push_back(range[1]); 2612 DE_ASSERT((int)m_lineWidths.size() == m_iterationCount); 2613 2614 m_maxLineWidth = range[1]; 2615 } 2616 else 2617 DE_ASSERT(false); 2618 } 2619 2620 tcu::TestStatus LineInterpolationTestInstance::iterate (void) 2621 { 2622 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 2623 const tcu::ScopedLogSection section (m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription); 2624 const float lineWidth = getLineWidth(); 2625 tcu::Surface resultImage (m_renderSize, m_renderSize); 2626 std::vector<tcu::Vec4> drawBuffer; 2627 std::vector<tcu::Vec4> colorBuffer; 2628 std::vector<LineSceneSpec::SceneLine> lines; 2629 2630 // supported? 2631 if (lineWidth <= m_maxLineWidth) 2632 { 2633 // generate scene 2634 generateVertices(m_iteration, drawBuffer, colorBuffer); 2635 extractLines(lines, drawBuffer, colorBuffer); 2636 2637 // log 2638 { 2639 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage; 2640 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx) 2641 m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage; 2642 } 2643 2644 // draw image 2645 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology); 2646 2647 // compare 2648 { 2649 RasterizationArguments args; 2650 LineSceneSpec scene; 2651 2652 tcu::IVec4 colorBits = tcu::getTextureFormatBitDepth(getTextureFormat()); 2653 2654 args.numSamples = m_multisampling ? 1 : 0; 2655 args.subpixelBits = m_subpixelBits; 2656 args.redBits = colorBits[0]; 2657 args.greenBits = colorBits[1]; 2658 args.blueBits = colorBits[2]; 2659 2660 scene.lines.swap(lines); 2661 scene.lineWidth = getLineWidth(); 2662 2663 if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog())) 2664 m_allIterationsPassed = false; 2665 } 2666 } 2667 else 2668 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage; 2669 2670 // result 2671 if (++m_iteration == m_iterationCount) 2672 { 2673 if (m_allIterationsPassed) 2674 return tcu::TestStatus::pass("Pass"); 2675 else 2676 return tcu::TestStatus::fail("Incorrect rasterization"); 2677 } 2678 else 2679 return tcu::TestStatus::incomplete(); 2680 } 2681 2682 void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const 2683 { 2684 // use only red, green and blue 2685 const tcu::Vec4 colors[] = 2686 { 2687 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), 2688 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), 2689 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), 2690 }; 2691 2692 de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology); 2693 2694 outVertices.resize(6); 2695 outColors.resize(6); 2696 2697 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx) 2698 { 2699 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f); 2700 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f); 2701 outVertices[vtxNdx].z() = 0.0f; 2702 2703 if (!m_projective) 2704 outVertices[vtxNdx].w() = 1.0f; 2705 else 2706 { 2707 const float w = rnd.getFloat(0.2f, 4.0f); 2708 2709 outVertices[vtxNdx].x() *= w; 2710 outVertices[vtxNdx].y() *= w; 2711 outVertices[vtxNdx].z() *= w; 2712 outVertices[vtxNdx].w() = w; 2713 } 2714 2715 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)]; 2716 } 2717 } 2718 2719 void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const 2720 { 2721 switch (m_primitiveTopology) 2722 { 2723 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 2724 { 2725 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2) 2726 { 2727 LineSceneSpec::SceneLine line; 2728 line.positions[0] = vertices[vtxNdx + 0]; 2729 line.positions[1] = vertices[vtxNdx + 1]; 2730 2731 if (m_flatshade) 2732 { 2733 line.colors[0] = colors[vtxNdx]; 2734 line.colors[1] = colors[vtxNdx]; 2735 } 2736 else 2737 { 2738 line.colors[0] = colors[vtxNdx + 0]; 2739 line.colors[1] = colors[vtxNdx + 1]; 2740 } 2741 2742 outLines.push_back(line); 2743 } 2744 break; 2745 } 2746 2747 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 2748 { 2749 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx) 2750 { 2751 LineSceneSpec::SceneLine line; 2752 line.positions[0] = vertices[vtxNdx + 0]; 2753 line.positions[1] = vertices[vtxNdx + 1]; 2754 2755 if (m_flatshade) 2756 { 2757 line.colors[0] = colors[vtxNdx]; 2758 line.colors[1] = colors[vtxNdx]; 2759 } 2760 else 2761 { 2762 line.colors[0] = colors[vtxNdx + 0]; 2763 line.colors[1] = colors[vtxNdx + 1]; 2764 } 2765 2766 outLines.push_back(line); 2767 } 2768 break; 2769 } 2770 2771 default: 2772 DE_ASSERT(false); 2773 } 2774 } 2775 2776 float LineInterpolationTestInstance::getLineWidth (void) const 2777 { 2778 return m_lineWidths[m_iteration]; 2779 } 2780 2781 class LineInterpolationTestCase : public BaseRenderingTestCase 2782 { 2783 public: 2784 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) 2785 : BaseRenderingTestCase (context, name, description, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0) 2786 , m_primitiveTopology (primitiveTopology) 2787 , m_flags (flags) 2788 , m_wideness (wideness) 2789 {} 2790 2791 virtual TestInstance* createInstance (Context& context) const 2792 { 2793 return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_sampleCount); 2794 } 2795 protected: 2796 const VkPrimitiveTopology m_primitiveTopology; 2797 const int m_flags; 2798 const PrimitiveWideness m_wideness; 2799 }; 2800 2801 void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests) 2802 { 2803 tcu::TestContext& testCtx = rasterizationTests->getTestContext(); 2804 2805 // .primitives 2806 { 2807 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives", "Primitive rasterization"); 2808 2809 rasterizationTests->addChild(primitives); 2810 2811 primitives->addChild(new BaseTestCase<TrianglesTestInstance> (testCtx, "triangles", "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result")); 2812 primitives->addChild(new BaseTestCase<TriangleStripTestInstance> (testCtx, "triangle_strip", "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result")); 2813 primitives->addChild(new BaseTestCase<TriangleFanTestInstance> (testCtx, "triangle_fan", "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result")); 2814 primitives->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result", PRIMITIVEWIDENESS_NARROW)); 2815 primitives->addChild(new WidenessTestCase<LineStripTestInstance> (testCtx, "line_strip", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result", PRIMITIVEWIDENESS_NARROW)); 2816 primitives->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines_wide", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE)); 2817 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)); 2818 primitives->addChild(new WidenessTestCase<PointTestInstance> (testCtx, "points", "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result", PRIMITIVEWIDENESS_WIDE)); 2819 } 2820 2821 // .fill_rules 2822 { 2823 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules", "Primitive fill rules"); 2824 2825 rasterizationTests->addChild(fillRules); 2826 2827 fillRules->addChild(new FillRuleTestCase(testCtx, "basic_quad", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_BASIC)); 2828 fillRules->addChild(new FillRuleTestCase(testCtx, "basic_quad_reverse", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_REVERSED)); 2829 fillRules->addChild(new FillRuleTestCase(testCtx, "clipped_full", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL)); 2830 fillRules->addChild(new FillRuleTestCase(testCtx, "clipped_partly", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL)); 2831 fillRules->addChild(new FillRuleTestCase(testCtx, "projected", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_PROJECTED)); 2832 } 2833 2834 // .culling 2835 { 2836 static const struct CullMode 2837 { 2838 VkCullModeFlags mode; 2839 const char* prefix; 2840 } cullModes[] = 2841 { 2842 { VK_CULL_MODE_FRONT_BIT, "front_" }, 2843 { VK_CULL_MODE_BACK_BIT, "back_" }, 2844 { VK_CULL_MODE_FRONT_AND_BACK, "both_" }, 2845 }; 2846 static const struct PrimitiveType 2847 { 2848 VkPrimitiveTopology type; 2849 const char* name; 2850 } primitiveTypes[] = 2851 { 2852 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangles" }, 2853 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip" }, 2854 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan" }, 2855 }; 2856 static const struct FrontFaceOrder 2857 { 2858 VkFrontFace mode; 2859 const char* postfix; 2860 } frontOrders[] = 2861 { 2862 { VK_FRONT_FACE_COUNTER_CLOCKWISE, "" }, 2863 { VK_FRONT_FACE_CLOCKWISE, "_reverse" }, 2864 }; 2865 2866 static const struct PolygonMode 2867 { 2868 VkPolygonMode mode; 2869 const char* name; 2870 } polygonModes[] = 2871 { 2872 { VK_POLYGON_MODE_FILL, "" }, 2873 { VK_POLYGON_MODE_LINE, "_line" }, 2874 { VK_POLYGON_MODE_POINT, "_point" } 2875 }; 2876 2877 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling", "Culling"); 2878 2879 rasterizationTests->addChild(culling); 2880 2881 for (int cullModeNdx = 0; cullModeNdx < DE_LENGTH_OF_ARRAY(cullModes); ++cullModeNdx) 2882 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx) 2883 for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders); ++frontOrderNdx) 2884 for (int polygonModeNdx = 0; polygonModeNdx < DE_LENGTH_OF_ARRAY(polygonModes); ++polygonModeNdx) 2885 { 2886 if (!(cullModes[cullModeNdx].mode == VK_CULL_MODE_FRONT_AND_BACK && polygonModes[polygonModeNdx].mode != VK_POLYGON_MODE_FILL)) 2887 { 2888 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix + polygonModes[polygonModeNdx].name; 2889 culling->addChild(new CullingTestCase(testCtx, name, "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode, polygonModes[polygonModeNdx].mode)); 2890 } 2891 } 2892 } 2893 2894 // .interpolation 2895 { 2896 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation"); 2897 2898 rasterizationTests->addChild(interpolation); 2899 2900 // .basic 2901 { 2902 tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation"); 2903 2904 interpolation->addChild(basic); 2905 2906 basic->addChild(new TriangleInterpolationTestCase (testCtx, "triangles", "Verify triangle interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, INTERPOLATIONFLAGS_NONE)); 2907 basic->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_strip", "Verify triangle strip interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, INTERPOLATIONFLAGS_NONE)); 2908 basic->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_fan", "Verify triangle fan interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, INTERPOLATIONFLAGS_NONE)); 2909 basic->addChild(new LineInterpolationTestCase (testCtx, "lines", "Verify line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW)); 2910 basic->addChild(new LineInterpolationTestCase (testCtx, "line_strip", "Verify line strip interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW)); 2911 basic->addChild(new LineInterpolationTestCase (testCtx, "lines_wide", "Verify wide line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE)); 2912 basic->addChild(new LineInterpolationTestCase (testCtx, "line_strip_wide","Verify wide line strip interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE)); 2913 } 2914 2915 // .projected 2916 { 2917 tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation"); 2918 2919 interpolation->addChild(projected); 2920 2921 projected->addChild(new TriangleInterpolationTestCase (testCtx, "triangles", "Verify triangle interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, INTERPOLATIONFLAGS_PROJECTED)); 2922 projected->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_strip", "Verify triangle strip interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, INTERPOLATIONFLAGS_PROJECTED)); 2923 projected->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_fan", "Verify triangle fan interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, INTERPOLATIONFLAGS_PROJECTED)); 2924 projected->addChild(new LineInterpolationTestCase (testCtx, "lines", "Verify line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_NARROW)); 2925 projected->addChild(new LineInterpolationTestCase (testCtx, "line_strip", "Verify line strip interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_NARROW)); 2926 projected->addChild(new LineInterpolationTestCase (testCtx, "lines_wide", "Verify wide line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_WIDE)); 2927 projected->addChild(new LineInterpolationTestCase (testCtx, "line_strip_wide","Verify wide line strip interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, PRIMITIVEWIDENESS_WIDE)); 2928 } 2929 } 2930 2931 // .flatshading 2932 { 2933 tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading"); 2934 2935 rasterizationTests->addChild(flatshading); 2936 2937 flatshading->addChild(new TriangleInterpolationTestCase (testCtx, "triangles", "Verify triangle flatshading", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, INTERPOLATIONFLAGS_FLATSHADE)); 2938 flatshading->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_strip", "Verify triangle strip flatshading", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, INTERPOLATIONFLAGS_FLATSHADE)); 2939 flatshading->addChild(new TriangleInterpolationTestCase (testCtx, "triangle_fan", "Verify triangle fan flatshading", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, INTERPOLATIONFLAGS_FLATSHADE)); 2940 flatshading->addChild(new LineInterpolationTestCase (testCtx, "lines", "Verify line flatshading", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_NARROW)); 2941 flatshading->addChild(new LineInterpolationTestCase (testCtx, "line_strip", "Verify line strip flatshading", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_NARROW)); 2942 flatshading->addChild(new LineInterpolationTestCase (testCtx, "lines_wide", "Verify wide line flatshading", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_WIDE)); 2943 flatshading->addChild(new LineInterpolationTestCase (testCtx, "line_strip_wide","Verify wide line strip flatshading", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, INTERPOLATIONFLAGS_FLATSHADE, PRIMITIVEWIDENESS_WIDE)); 2944 } 2945 2946 const VkSampleCountFlagBits samples[] = 2947 { 2948 VK_SAMPLE_COUNT_2_BIT, 2949 VK_SAMPLE_COUNT_4_BIT, 2950 VK_SAMPLE_COUNT_8_BIT, 2951 VK_SAMPLE_COUNT_16_BIT, 2952 VK_SAMPLE_COUNT_32_BIT, 2953 VK_SAMPLE_COUNT_64_BIT 2954 }; 2955 2956 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++) 2957 { 2958 std::ostringstream caseName; 2959 2960 caseName << "_multisample_" << (2 << samplesNdx) << "_bit"; 2961 2962 // .primitives 2963 { 2964 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization"); 2965 2966 rasterizationTests->addChild(primitives); 2967 2968 primitives->addChild(new BaseTestCase<TrianglesTestInstance> (testCtx, "triangles", "Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result", samples[samplesNdx])); 2969 primitives->addChild(new WidenessTestCase<LinesTestInstance> (testCtx, "lines", "Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result", PRIMITIVEWIDENESS_NARROW, samples[samplesNdx])); 2970 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])); 2971 primitives->addChild(new WidenessTestCase<PointTestInstance> (testCtx, "points", "Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result", PRIMITIVEWIDENESS_WIDE, samples[samplesNdx])); 2972 } 2973 2974 // .fill_rules 2975 { 2976 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules"); 2977 2978 rasterizationTests->addChild(fillRules); 2979 2980 fillRules->addChild(new FillRuleTestCase(testCtx, "basic_quad", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_BASIC, samples[samplesNdx])); 2981 fillRules->addChild(new FillRuleTestCase(testCtx, "basic_quad_reverse", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_REVERSED, samples[samplesNdx])); 2982 fillRules->addChild(new FillRuleTestCase(testCtx, "clipped_full", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL, samples[samplesNdx])); 2983 fillRules->addChild(new FillRuleTestCase(testCtx, "clipped_partly", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL, samples[samplesNdx])); 2984 fillRules->addChild(new FillRuleTestCase(testCtx, "projected", "Verify fill rules", FillRuleTestInstance::FILLRULECASE_PROJECTED, samples[samplesNdx])); 2985 } 2986 2987 // .interpolation 2988 { 2989 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation"); 2990 2991 rasterizationTests->addChild(interpolation); 2992 2993 interpolation->addChild(new TriangleInterpolationTestCase (testCtx, "triangles", "Verify triangle interpolation", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, INTERPOLATIONFLAGS_NONE, samples[samplesNdx])); 2994 interpolation->addChild(new LineInterpolationTestCase (testCtx, "lines", "Verify line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_NARROW, samples[samplesNdx])); 2995 interpolation->addChild(new LineInterpolationTestCase (testCtx, "lines_wide", "Verify wide line interpolation", VK_PRIMITIVE_TOPOLOGY_LINE_LIST, INTERPOLATIONFLAGS_NONE, PRIMITIVEWIDENESS_WIDE, samples[samplesNdx])); 2996 } 2997 } 2998 } 2999 3000 } // anonymous 3001 3002 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx) 3003 { 3004 return createTestGroup(testCtx, "rasterization", "Rasterization Tests", createRasterizationTests); 3005 } 3006 3007 } // rasterization 3008 } // vkt 3009