vktPipelineBlendTests.cpp revision 978d3d585aa549eb1e729b51e9d85fc6477240f9
1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Imagination Technologies Ltd. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Blend Tests 23 *//*--------------------------------------------------------------------*/ 24 25#include "vktPipelineBlendTests.hpp" 26#include "vktPipelineClearUtil.hpp" 27#include "vktPipelineImageUtil.hpp" 28#include "vktPipelineVertexUtil.hpp" 29#include "vktPipelineUniqueRandomIterator.hpp" 30#include "vktPipelineReferenceRenderer.hpp" 31#include "vktTestCase.hpp" 32#include "vkImageUtil.hpp" 33#include "vkMemUtil.hpp" 34#include "vkPlatform.hpp" 35#include "vkPrograms.hpp" 36#include "vkQueryUtil.hpp" 37#include "vkRef.hpp" 38#include "vkRefUtil.hpp" 39#include "tcuImageCompare.hpp" 40#include "tcuPlatform.hpp" 41#include "tcuTextureUtil.hpp" 42#include "deRandom.hpp" 43#include "deStringUtil.hpp" 44#include "deUniquePtr.hpp" 45#include <cstring> 46#include <set> 47#include <sstream> 48#include <vector> 49 50namespace vkt 51{ 52namespace pipeline 53{ 54 55using namespace vk; 56 57namespace 58{ 59 60bool isSupportedBlendFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format) 61{ 62 VkFormatProperties formatProps; 63 64 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps); 65 66 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) && 67 (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT); 68} 69 70class BlendStateUniqueRandomIterator : public UniqueRandomIterator<VkPipelineColorBlendAttachmentState> 71{ 72public: 73 BlendStateUniqueRandomIterator (deUint32 numberOfCombinations, int seed); 74 virtual ~BlendStateUniqueRandomIterator (void) {} 75 VkPipelineColorBlendAttachmentState getIndexedValue (deUint32 index); 76 77private: 78 const static VkBlendFactor m_blendFactors[]; 79 const static VkBlendOp m_blendOps[]; 80 81 // Pre-calculated constants 82 const static deUint32 m_blendFactorsLength; 83 const static deUint32 m_blendFactorsLength2; 84 const static deUint32 m_blendFactorsLength3; 85 const static deUint32 m_blendFactorsLength4; 86 const static deUint32 m_blendOpsLength; 87 88 // Total number of cross-combinations of (srcBlendColor x destBlendColor x blendOpColor x srcBlendAlpha x destBlendAlpha x blendOpAlpha) 89 const static deUint32 m_totalBlendStates; 90}; 91 92class BlendTest : public vkt::TestCase 93{ 94public: 95 enum 96 { 97 QUAD_COUNT = 4 98 }; 99 100 const static VkColorComponentFlags s_colorWriteMasks[QUAD_COUNT]; 101 const static tcu::Vec4 s_blendConst; 102 103 BlendTest (tcu::TestContext& testContext, 104 const std::string& name, 105 const std::string& description, 106 const VkFormat colorFormat, 107 const VkPipelineColorBlendAttachmentState blendStates[QUAD_COUNT]); 108 virtual ~BlendTest (void); 109 virtual void initPrograms (SourceCollections& sourceCollections) const; 110 virtual TestInstance* createInstance (Context& context) const; 111 112private: 113 const VkFormat m_colorFormat; 114 VkPipelineColorBlendAttachmentState m_blendStates[QUAD_COUNT]; 115}; 116 117class BlendTestInstance : public vkt::TestInstance 118{ 119public: 120 BlendTestInstance (Context& context, const VkFormat colorFormat, const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]); 121 virtual ~BlendTestInstance (void); 122 virtual tcu::TestStatus iterate (void); 123 124private: 125 static float getNormChannelThreshold (const tcu::TextureFormat& format, int numBits); 126 static tcu::Vec4 getFormatThreshold (const tcu::TextureFormat& format); 127 tcu::TestStatus verifyImage (void); 128 129 VkPipelineColorBlendAttachmentState m_blendStates[BlendTest::QUAD_COUNT]; 130 131 const tcu::UVec2 m_renderSize; 132 const VkFormat m_colorFormat; 133 134 VkImageCreateInfo m_colorImageCreateInfo; 135 Move<VkImage> m_colorImage; 136 de::MovePtr<Allocation> m_colorImageAlloc; 137 Move<VkImageView> m_colorAttachmentView; 138 Move<VkRenderPass> m_renderPass; 139 Move<VkFramebuffer> m_framebuffer; 140 141 Move<VkShaderModule> m_vertexShaderModule; 142 Move<VkShaderModule> m_fragmentShaderModule; 143 144 Move<VkBuffer> m_vertexBuffer; 145 std::vector<Vertex4RGBA> m_vertices; 146 de::MovePtr<Allocation> m_vertexBufferAlloc; 147 148 Move<VkPipelineLayout> m_pipelineLayout; 149 Move<VkPipeline> m_graphicsPipelines[BlendTest::QUAD_COUNT]; 150 151 Move<VkCommandPool> m_cmdPool; 152 Move<VkCommandBuffer> m_cmdBuffer; 153 154 Move<VkFence> m_fence; 155}; 156 157 158// BlendStateUniqueRandomIterator 159 160const VkBlendFactor BlendStateUniqueRandomIterator::m_blendFactors[] = 161{ 162 VK_BLEND_FACTOR_ZERO, 163 VK_BLEND_FACTOR_ONE, 164 VK_BLEND_FACTOR_SRC_COLOR, 165 VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, 166 VK_BLEND_FACTOR_DST_COLOR, 167 VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, 168 VK_BLEND_FACTOR_SRC_ALPHA, 169 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, 170 VK_BLEND_FACTOR_DST_ALPHA, 171 VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, 172 VK_BLEND_FACTOR_CONSTANT_COLOR, 173 VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, 174 VK_BLEND_FACTOR_CONSTANT_ALPHA, 175 VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, 176 VK_BLEND_FACTOR_SRC_ALPHA_SATURATE 177}; 178 179const VkBlendOp BlendStateUniqueRandomIterator::m_blendOps[] = 180{ 181 VK_BLEND_OP_ADD, 182 VK_BLEND_OP_SUBTRACT, 183 VK_BLEND_OP_REVERSE_SUBTRACT, 184 VK_BLEND_OP_MIN, 185 VK_BLEND_OP_MAX 186}; 187 188const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength = DE_LENGTH_OF_ARRAY(m_blendFactors); 189const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength2 = m_blendFactorsLength * m_blendFactorsLength; 190const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength3 = m_blendFactorsLength2 * m_blendFactorsLength; 191const deUint32 BlendStateUniqueRandomIterator::m_blendFactorsLength4 = m_blendFactorsLength3 * m_blendFactorsLength; 192const deUint32 BlendStateUniqueRandomIterator::m_blendOpsLength = DE_LENGTH_OF_ARRAY(m_blendOps); 193const deUint32 BlendStateUniqueRandomIterator::m_totalBlendStates = m_blendFactorsLength4 * m_blendOpsLength * m_blendOpsLength; 194 195 196BlendStateUniqueRandomIterator::BlendStateUniqueRandomIterator (deUint32 numberOfCombinations, int seed) 197 : UniqueRandomIterator<VkPipelineColorBlendAttachmentState>(numberOfCombinations, m_totalBlendStates, seed) 198{ 199} 200 201VkPipelineColorBlendAttachmentState BlendStateUniqueRandomIterator::getIndexedValue (deUint32 index) 202{ 203 const deUint32 blendOpAlphaIndex = index / (m_blendFactorsLength4 * m_blendOpsLength); 204 const deUint32 blendOpAlphaSeqIndex = blendOpAlphaIndex * (m_blendFactorsLength4 * m_blendOpsLength); 205 206 const deUint32 destBlendAlphaIndex = (index - blendOpAlphaSeqIndex) / (m_blendFactorsLength3 * m_blendOpsLength); 207 const deUint32 destBlendAlphaSeqIndex = destBlendAlphaIndex * (m_blendFactorsLength3 * m_blendOpsLength); 208 209 const deUint32 srcBlendAlphaIndex = (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex) / (m_blendFactorsLength2 * m_blendOpsLength); 210 const deUint32 srcBlendAlphaSeqIndex = srcBlendAlphaIndex * (m_blendFactorsLength2 * m_blendOpsLength); 211 212 const deUint32 blendOpColorIndex = (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex) / m_blendFactorsLength2; 213 const deUint32 blendOpColorSeqIndex = blendOpColorIndex * m_blendFactorsLength2; 214 215 const deUint32 destBlendColorIndex = (index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex) / m_blendFactorsLength; 216 const deUint32 destBlendColorSeqIndex = destBlendColorIndex * m_blendFactorsLength; 217 218 const deUint32 srcBlendColorIndex = index - blendOpAlphaSeqIndex - destBlendAlphaSeqIndex - srcBlendAlphaSeqIndex - blendOpColorSeqIndex - destBlendColorSeqIndex; 219 220 const VkPipelineColorBlendAttachmentState blendAttachmentState = 221 { 222 true, // VkBool32 blendEnable; 223 m_blendFactors[srcBlendColorIndex], // VkBlendFactor srcColorBlendFactor; 224 m_blendFactors[destBlendColorIndex], // VkBlendFactor dstColorBlendFactor; 225 m_blendOps[blendOpColorIndex], // VkBlendOp colorBlendOp; 226 m_blendFactors[srcBlendAlphaIndex], // VkBlendFactor srcAlphaBlendFactor; 227 m_blendFactors[destBlendAlphaIndex], // VkBlendFactor dstAlphaBlendFactor; 228 m_blendOps[blendOpAlphaIndex], // VkBlendOp alphaBlendOp; 229 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask; 230 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT 231 }; 232 233 return blendAttachmentState; 234} 235 236 237// BlendTest 238 239const VkColorComponentFlags BlendTest::s_colorWriteMasks[BlendTest::QUAD_COUNT] = { VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT, // Pair of channels: R & G 240 VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT, // Pair of channels: G & B 241 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, // Pair of channels: B & A 242 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT }; // All channels 243 244const tcu::Vec4 BlendTest::s_blendConst = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f); 245 246BlendTest::BlendTest (tcu::TestContext& testContext, 247 const std::string& name, 248 const std::string& description, 249 const VkFormat colorFormat, 250 const VkPipelineColorBlendAttachmentState blendStates[QUAD_COUNT]) 251 : vkt::TestCase (testContext, name, description) 252 , m_colorFormat(colorFormat) 253{ 254 deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * QUAD_COUNT); 255} 256 257BlendTest::~BlendTest (void) 258{ 259} 260 261TestInstance* BlendTest::createInstance(Context& context) const 262{ 263 return new BlendTestInstance(context, m_colorFormat, m_blendStates); 264} 265 266void BlendTest::initPrograms (SourceCollections& sourceCollections) const 267{ 268 std::ostringstream fragmentSource; 269 270 sourceCollections.glslSources.add("color_vert") << glu::VertexSource( 271 "#version 310 es\n" 272 "layout(location = 0) in highp vec4 position;\n" 273 "layout(location = 1) in highp vec4 color;\n" 274 "layout(location = 0) out highp vec4 vtxColor;\n" 275 "void main (void)\n" 276 "{\n" 277 " gl_Position = position;\n" 278 " vtxColor = color;\n" 279 "}\n"); 280 281 fragmentSource << "#version 310 es\n" 282 "layout(location = 0) in highp vec4 vtxColor;\n" 283 "layout(location = 0) out highp vec4 fragColor;\n" 284 "void main (void)\n" 285 "{\n" 286 " fragColor = vtxColor;\n" 287 "}\n"; 288 289 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource.str()); 290} 291 292 293// BlendTestInstance 294 295BlendTestInstance::BlendTestInstance (Context& context, 296 const VkFormat colorFormat, 297 const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]) 298 : vkt::TestInstance (context) 299 , m_renderSize (32, 32) 300 , m_colorFormat (colorFormat) 301{ 302 const DeviceInterface& vk = m_context.getDeviceInterface(); 303 const VkDevice vkDevice = m_context.getDevice(); 304 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 305 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 306 307 // Copy depth operators 308 deMemcpy(m_blendStates, blendStates, sizeof(VkPipelineColorBlendAttachmentState) * BlendTest::QUAD_COUNT); 309 310 // Create color image 311 { 312 if (!isSupportedBlendFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_colorFormat)) 313 throw tcu::NotSupportedError(std::string("Unsupported color blending format: ") + getFormatName(m_colorFormat)); 314 315 const VkImageCreateInfo colorImageParams = 316 { 317 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 318 DE_NULL, // const void* pNext; 319 0u, // VkImageCreateFlags flags; 320 VK_IMAGE_TYPE_2D, // VkImageType imageType; 321 m_colorFormat, // VkFormat format; 322 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent; 323 1u, // deUint32 mipLevels; 324 1u, // deUint32 arrayLayers; 325 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 326 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 327 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 328 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 329 1u, // deUint32 queueFamilyIndexCount; 330 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 331 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 332 }; 333 334 m_colorImageCreateInfo = colorImageParams; 335 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo); 336 337 // Allocate and bind color image memory 338 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any); 339 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset())); 340 } 341 342 // Create color attachment view 343 { 344 const VkImageViewCreateInfo colorAttachmentViewParams = 345 { 346 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 347 DE_NULL, // const void* pNext; 348 0u, // VkImageViewCreateFlags flags; 349 *m_colorImage, // VkImage image; 350 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 351 m_colorFormat, // VkFormat format; 352 {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}, 353 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 354 }; 355 356 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); 357 } 358 359 // Create render pass 360 { 361 const VkAttachmentDescription colorAttachmentDescription = 362 { 363 0u, // VkAttachmentDescriptionFlags flags; 364 m_colorFormat, // VkFormat format; 365 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 366 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 367 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 368 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 369 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 370 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 371 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 372 }; 373 374 const VkAttachmentReference colorAttachmentReference = 375 { 376 0u, // deUint32 attachment; 377 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 378 }; 379 380 const VkSubpassDescription subpassDescription = 381 { 382 0u, // VkSubpassDescriptionFlag flags; 383 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 384 0u, // deUint32 inputAttachmentCount; 385 DE_NULL, // const VkAttachmentReference* pInputAttachments; 386 1u, // deUint32 colorAttachmentCount; 387 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; 388 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 389 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 390 0u, // deUint32 preserveAttachmentCount; 391 DE_NULL // const VkAttachmentReference* pPreserveAttachments; 392 }; 393 394 const VkRenderPassCreateInfo renderPassParams = 395 { 396 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 397 DE_NULL, // const void* pNext; 398 0u, // VkRenderPassCreateFlags flags; 399 1u, // deUint32 attachmentCount; 400 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; 401 1u, // deUint32 subpassCount; 402 &subpassDescription, // const VkSubpassDescription* pSubpasses; 403 0u, // deUint32 dependencyCount; 404 DE_NULL // const VkSubpassDependency* pDependencies; 405 }; 406 407 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams); 408 } 409 410 // Create framebuffer 411 { 412 const VkFramebufferCreateInfo framebufferParams = 413 { 414 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 415 DE_NULL, // const void* pNext; 416 0u, // VkFramebufferCreateFlags flags; 417 *m_renderPass, // VkRenderPass renderPass; 418 1u, // deUint32 attachmentCount; 419 &m_colorAttachmentView.get(), // const VkImageView* pAttachments; 420 (deUint32)m_renderSize.x(), // deUint32 width; 421 (deUint32)m_renderSize.y(), // deUint32 height; 422 1u // deUint32 layers; 423 }; 424 425 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); 426 } 427 428 // Create pipeline layout 429 { 430 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 431 { 432 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 433 DE_NULL, // const void* pNext; 434 0u, // VkPipelineLayoutCreateFlags flags; 435 0u, // deUint32 setLayoutCount; 436 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; 437 0u, // deUint32 pushConstantRangeCount; 438 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 439 }; 440 441 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); 442 } 443 444 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0); 445 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0); 446 447 // Create pipeline 448 { 449 const VkPipelineShaderStageCreateInfo shaderStages[2] = 450 { 451 { 452 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 453 DE_NULL, // const void* pNext; 454 0u, // VkPipelineShaderStageCreateFlags flags; 455 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 456 *m_vertexShaderModule, // VkShaderModule module; 457 "main", // const char* pName; 458 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 459 }, 460 { 461 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 462 DE_NULL, // const void* pNext; 463 0u, // VkPipelineShaderStageCreateFlags flags; 464 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 465 *m_fragmentShaderModule, // VkShaderModule module; 466 "main", // const char* pName; 467 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 468 } 469 }; 470 471 const VkVertexInputBindingDescription vertexInputBindingDescription = 472 { 473 0u, // deUint32 binding; 474 sizeof(Vertex4RGBA), // deUint32 strideInBytes; 475 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate; 476 }; 477 478 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = 479 { 480 { 481 0u, // deUint32 location; 482 0u, // deUint32 binding; 483 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 484 0u // deUint32 offset; 485 }, 486 { 487 1u, // deUint32 location; 488 0u, // deUint32 binding; 489 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 490 (deUint32)(sizeof(float) * 4), // deUint32 offset; 491 } 492 }; 493 494 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 495 { 496 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 497 DE_NULL, // const void* pNext; 498 0u, // VkPipelineVertexInputStateCreateFlags flags; 499 1u, // deUint32 vertexBindingDescriptionCount; 500 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 501 2u, // deUint32 vertexAttributeDescriptionCount; 502 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 503 }; 504 505 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = 506 { 507 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 508 DE_NULL, // const void* pNext; 509 0u, // VkPipelineInputAssemblyStateCreateFlags flags; 510 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology; 511 false // VkBool32 primitiveRestartEnable; 512 }; 513 514 const VkViewport viewport = 515 { 516 0.0f, // float x; 517 0.0f, // float y; 518 (float)m_renderSize.x(), // float width; 519 (float)m_renderSize.y(), // float height; 520 0.0f, // float minDepth; 521 1.0f // float maxDepth; 522 }; 523 524 const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }; 525 526 const VkPipelineViewportStateCreateInfo viewportStateParams = 527 { 528 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 529 DE_NULL, // const void* pNext; 530 0u, // VkPipelineViewportStateCreateFlags flags; 531 1u, // deUint32 viewportCount; 532 &viewport, // const VkViewport* pViewports; 533 1u, // deUint32 scissorCount; 534 &scissor // const VkRect2D* pScissors; 535 }; 536 537 const VkPipelineRasterizationStateCreateInfo rasterStateParams = 538 { 539 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 540 DE_NULL, // const void* pNext; 541 0u, // VkPipelineRasterizationStateCreateFlags flags; 542 false, // VkBool32 depthClampEnable; 543 false, // VkBool32 rasterizerDiscardEnable; 544 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 545 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 546 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 547 false, // VkBool32 depthBiasEnable; 548 0.0f, // float depthBiasConstantFactor; 549 0.0f, // float depthBiasClamp; 550 0.0f, // float depthBiasSlopeFactor; 551 1.0f // float lineWidth; 552 }; 553 554 const VkPipelineMultisampleStateCreateInfo multisampleStateParams = 555 { 556 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 557 DE_NULL, // const void* pNext; 558 0u, // VkPipelineMultisampleStateCreateFlags flags; 559 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 560 false, // VkBool32 sampleShadingEnable; 561 0.0f, // float minSampleShading; 562 DE_NULL, // const VkSampleMask* pSampleMask; 563 false, // VkBool32 alphaToCoverageEnable; 564 false // VkBool32 alphaToOneEnable; 565 }; 566 567 const VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = 568 { 569 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 570 DE_NULL, // const void* pNext; 571 0u, // VkPipelineDepthStencilStateCreateFlags flags; 572 false, // VkBool32 depthTestEnable; 573 false, // VkBool32 depthWriteEnable; 574 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 575 false, // VkBool32 depthBoundsTestEnable; 576 false, // VkBool32 stencilTestEnable; 577 // VkStencilOpState front; 578 { 579 VK_STENCIL_OP_KEEP, // VkStencilOp failOp; 580 VK_STENCIL_OP_KEEP, // VkStencilOp passOp; 581 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; 582 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 583 0u, // deUint32 compareMask; 584 0u, // deUint32 writeMask; 585 0u // deUint32 reference; 586 }, 587 // VkStencilOpState back; 588 { 589 VK_STENCIL_OP_KEEP, // VkStencilOp failOp; 590 VK_STENCIL_OP_KEEP, // VkStencilOp passOp; 591 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; 592 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 593 0u, // deUint32 compareMask; 594 0u, // deUint32 writeMask; 595 0u // deUint32 reference; 596 }, 597 -1.0f, // float minDepthBounds; 598 +1.0f // float maxDepthBounds; 599 }; 600 601 // The color blend attachment will be set up before creating the graphics pipeline. 602 VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 603 { 604 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 605 DE_NULL, // const void* pNext; 606 0u, // VkPipelineColorBlendStateCreateFlags flags; 607 false, // VkBool32 logicOpEnable; 608 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 609 0u, // deUint32 attachmentCount; 610 DE_NULL, // const VkPipelineColorBlendAttachmentState* pAttachments; 611 { // float blendConstants[4]; 612 BlendTest::s_blendConst.x(), 613 BlendTest::s_blendConst.y(), 614 BlendTest::s_blendConst.z(), 615 BlendTest::s_blendConst.w() 616 } 617 }; 618 619 const VkPipelineDynamicStateCreateInfo dynamicStateParams = 620 { 621 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; 622 DE_NULL, // const void* pNext; 623 0u, // VkPipelineDynamicStateCreateFlags flags; 624 0u, // deUint32 dynamicStateCount; 625 DE_NULL // const VkDynamicState* pDynamicStates; 626 }; 627 628 const VkGraphicsPipelineCreateInfo graphicsPipelineParams = 629 { 630 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 631 DE_NULL, // const void* pNext; 632 0u, // VkPipelineCreateFlags flags; 633 2u, // deUint32 stageCount; 634 shaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 635 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 636 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 637 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 638 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; 639 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 640 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 641 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 642 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 643 &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 644 *m_pipelineLayout, // VkPipelineLayout layout; 645 *m_renderPass, // VkRenderPass renderPass; 646 0u, // deUint32 subpass; 647 0u, // VkPipeline basePipelineHandle; 648 0u // deInt32 basePipelineIndex; 649 }; 650 651 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 652 { 653 colorBlendStateParams.attachmentCount = 1u; 654 colorBlendStateParams.pAttachments = &m_blendStates[quadNdx]; 655 m_graphicsPipelines[quadNdx] = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams); 656 } 657 } 658 659 // Create vertex buffer 660 { 661 const VkBufferCreateInfo vertexBufferParams = 662 { 663 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 664 DE_NULL, // const void* pNext; 665 0u, // VkBufferCreateFlags flags; 666 1024u, // VkDeviceSize size; 667 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 668 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 669 1u, // deUint32 queueFamilyIndexCount; 670 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 671 }; 672 673 m_vertices = createOverlappingQuads(); 674 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); 675 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible); 676 677 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); 678 679 // Adjust vertex colors 680 if (!isFloatFormat(m_colorFormat)) 681 { 682 const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(mapVkFormat(m_colorFormat)); 683 for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++) 684 m_vertices[vertexNdx].color = (m_vertices[vertexNdx].color - formatInfo.lookupBias) / formatInfo.lookupScale; 685 } 686 687 // Upload vertex data 688 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA)); 689 690 const VkMappedMemoryRange flushRange = 691 { 692 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; 693 DE_NULL, // const void* pNext; 694 m_vertexBufferAlloc->getMemory(), // VkDeviceMemory memory; 695 m_vertexBufferAlloc->getOffset(), // VkDeviceSize offset; 696 vertexBufferParams.size // VkDeviceSize size; 697 }; 698 699 vk.flushMappedMemoryRanges(vkDevice, 1, &flushRange); 700 } 701 702 // Create command pool 703 { 704 const VkCommandPoolCreateInfo cmdPoolParams = 705 { 706 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 707 DE_NULL, // const void* pNext; 708 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags; 709 queueFamilyIndex // deUint32 queueFamilyIndex; 710 }; 711 712 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams); 713 } 714 715 // Create command buffer 716 { 717 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = 718 { 719 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; 720 DE_NULL, // const void* pNext; 721 *m_cmdPool, // VkCommandPool commandPool; 722 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; 723 1u, // deUint32 bufferCount; 724 }; 725 726 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 727 { 728 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 729 DE_NULL, // const void* pNext; 730 0u, // VkCommandBufferUsageFlags flags; 731 (const VkCommandBufferInheritanceInfo*)DE_NULL, 732 }; 733 734 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat); 735 736 const VkRenderPassBeginInfo renderPassBeginInfo = 737 { 738 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 739 DE_NULL, // const void* pNext; 740 *m_renderPass, // VkRenderPass renderPass; 741 *m_framebuffer, // VkFramebuffer framebuffer; 742 { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea; 743 1, // deUint32 clearValueCount; 744 &attachmentClearValue // const VkClearValue* pClearValues; 745 }; 746 747 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo); 748 749 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo)); 750 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 751 752 const VkDeviceSize quadOffset = (m_vertices.size() / BlendTest::QUAD_COUNT) * sizeof(Vertex4RGBA); 753 754 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 755 { 756 VkDeviceSize vertexBufferOffset = quadOffset * quadNdx; 757 758 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]); 759 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset); 760 vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / BlendTest::QUAD_COUNT), 1, 0, 0); 761 } 762 763 vk.cmdEndRenderPass(*m_cmdBuffer); 764 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); 765 } 766 767 // Create fence 768 { 769 const VkFenceCreateInfo fenceParams = 770 { 771 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; 772 DE_NULL, // const void* pNext; 773 0u // VkFenceCreateFlags flags; 774 }; 775 776 m_fence = createFence(vk, vkDevice, &fenceParams); 777 } 778} 779 780BlendTestInstance::~BlendTestInstance (void) 781{ 782} 783 784tcu::TestStatus BlendTestInstance::iterate (void) 785{ 786 const DeviceInterface& vk = m_context.getDeviceInterface(); 787 const VkDevice vkDevice = m_context.getDevice(); 788 const VkQueue queue = m_context.getUniversalQueue(); 789 const VkSubmitInfo submitInfo = 790 { 791 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 792 DE_NULL, // const void* pNext; 793 0u, // deUint32 waitSemaphoreCount; 794 DE_NULL, // const VkSemaphore* pWaitSemaphores; 795 (const VkPipelineStageFlags*)DE_NULL, 796 1u, // deUint32 commandBufferCount; 797 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers; 798 0u, // deUint32 signalSemaphoreCount; 799 DE_NULL // const VkSemaphore* pSignalSemaphores; 800 }; 801 802 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get())); 803 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence)); 804 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */)); 805 806 return verifyImage(); 807} 808 809float BlendTestInstance::getNormChannelThreshold (const tcu::TextureFormat& format, int numBits) 810{ 811 switch (tcu::getTextureChannelClass(format.type)) 812 { 813 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: return BlendTest::QUAD_COUNT / static_cast<float>((1 << numBits) - 1); 814 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: return BlendTest::QUAD_COUNT / static_cast<float>((1 << (numBits - 1)) - 1); 815 default: 816 break; 817 } 818 819 DE_ASSERT(false); 820 return 0.0f; 821} 822 823tcu::Vec4 BlendTestInstance::getFormatThreshold (const tcu::TextureFormat& format) 824{ 825 using tcu::Vec4; 826 using tcu::TextureFormat; 827 828 Vec4 threshold(0.01f); 829 830 switch (format.type) 831 { 832 case TextureFormat::UNORM_BYTE_44: 833 threshold = Vec4(getNormChannelThreshold(format, 4), getNormChannelThreshold(format, 4), 1.0f, 1.0f); 834 break; 835 836 case TextureFormat::UNORM_SHORT_565: 837 threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 6), getNormChannelThreshold(format, 5), 1.0f); 838 break; 839 840 case TextureFormat::UNORM_SHORT_555: 841 threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 1.0f); 842 break; 843 844 case TextureFormat::UNORM_SHORT_4444: 845 threshold = Vec4(getNormChannelThreshold(format, 4)); 846 break; 847 848 case TextureFormat::UNORM_SHORT_5551: 849 threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 0.1f); 850 break; 851 852 case TextureFormat::UNORM_INT_1010102_REV: 853 case TextureFormat::SNORM_INT_1010102_REV: 854 threshold = Vec4(getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), 0.34f); 855 break; 856 857 case TextureFormat::UNORM_INT8: 858 case TextureFormat::SNORM_INT8: 859 threshold = Vec4(getNormChannelThreshold(format, 8)); 860 break; 861 862 case TextureFormat::UNORM_INT16: 863 case TextureFormat::SNORM_INT16: 864 threshold = Vec4(getNormChannelThreshold(format, 16)); 865 break; 866 867 case TextureFormat::UNORM_INT32: 868 case TextureFormat::SNORM_INT32: 869 threshold = Vec4(getNormChannelThreshold(format, 32)); 870 break; 871 872 case TextureFormat::HALF_FLOAT: 873 threshold = Vec4(0.005f); 874 break; 875 876 case TextureFormat::FLOAT: 877 threshold = Vec4(0.00001f); 878 break; 879 880 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: 881 threshold = Vec4(0.02f, 0.02f, 0.0625f, 1.0f); 882 break; 883 884 case TextureFormat::UNSIGNED_INT_999_E5_REV: 885 threshold = Vec4(0.05f, 0.05f, 0.05f, 1.0f); 886 break; 887 888 default: 889 DE_ASSERT(false); 890 } 891 892 // Return value matching the channel order specified by the format 893 if (format.order == tcu::TextureFormat::BGR || format.order == tcu::TextureFormat::BGRA) 894 return threshold.swizzle(2, 1, 0, 3); 895 else 896 return threshold; 897} 898 899tcu::TestStatus BlendTestInstance::verifyImage (void) 900{ 901 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat); 902 const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat(); // Undefined depth/stencil format 903 const ColorVertexShader vertexShader; 904 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuDepthFormat); 905 const rr::Program program (&vertexShader, &fragmentShader); 906 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program); 907 bool compareOk = false; 908 909 // Render reference image 910 { 911 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 912 { 913 const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx]; 914 915 // Set blend state 916 rr::RenderState renderState (refRenderer.getViewportState()); 917 renderState.fragOps.blendMode = rr::BLENDMODE_STANDARD; 918 renderState.fragOps.blendRGBState.srcFunc = mapVkBlendFactor(blendState.srcColorBlendFactor); 919 renderState.fragOps.blendRGBState.dstFunc = mapVkBlendFactor(blendState.dstColorBlendFactor); 920 renderState.fragOps.blendRGBState.equation = mapVkBlendOp(blendState.colorBlendOp); 921 renderState.fragOps.blendAState.srcFunc = mapVkBlendFactor(blendState.srcAlphaBlendFactor); 922 renderState.fragOps.blendAState.dstFunc = mapVkBlendFactor(blendState.dstAlphaBlendFactor); 923 renderState.fragOps.blendAState.equation = mapVkBlendOp(blendState.alphaBlendOp); 924 renderState.fragOps.blendColor = BlendTest::s_blendConst; 925 renderState.fragOps.colorMask = mapVkColorComponentFlags(BlendTest::s_colorWriteMasks[quadNdx]); 926 927 refRenderer.draw(renderState, 928 rr::PRIMITIVETYPE_TRIANGLES, 929 std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6, 930 m_vertices.begin() + (quadNdx + 1) * 6)); 931 } 932 } 933 934 935 // Compare result with reference image 936 { 937 const DeviceInterface& vk = m_context.getDeviceInterface(); 938 const VkDevice vkDevice = m_context.getDevice(); 939 const VkQueue queue = m_context.getUniversalQueue(); 940 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 941 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 942 de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release()); 943 const tcu::Vec4 threshold (getFormatThreshold(tcuColorFormat)); 944 945 compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), 946 "FloatImageCompare", 947 "Image comparison", 948 refRenderer.getAccess(), 949 result->getAccess(), 950 threshold, 951 tcu::COMPARE_LOG_RESULT); 952 } 953 954 if (compareOk) 955 return tcu::TestStatus::pass("Result image matches reference"); 956 else 957 return tcu::TestStatus::fail("Image mismatch"); 958} 959 960} // anonymous 961 962std::string getBlendStateName (const VkPipelineColorBlendAttachmentState& blendState) 963{ 964 const char* shortBlendFactorNames[] = 965 { 966 "z", // VK_BLEND_ZERO 967 "o", // VK_BLEND_ONE 968 "sc", // VK_BLEND_SRC_COLOR 969 "1msc", // VK_BLEND_ONE_MINUS_SRC_COLOR 970 "dc", // VK_BLEND_DEST_COLOR 971 "1mdc", // VK_BLEND_ONE_MINUS_DEST_COLOR 972 "sa", // VK_BLEND_SRC_ALPHA 973 "1msa", // VK_BLEND_ONE_MINUS_SRC_ALPHA 974 "da", // VK_BLEND_DEST_ALPHA 975 "1mda", // VK_BLEND_ONE_MINUS_DEST_ALPHA 976 "cc", // VK_BLEND_CONSTANT_COLOR 977 "1mcc", // VK_BLEND_ONE_MINUS_CONSTANT_COLOR 978 "ca", // VK_BLEND_CONSTANT_ALPHA 979 "1mca", // VK_BLEND_ONE_MINUS_CONSTANT_ALPHA 980 "sas" // VK_BLEND_SRC_ALPHA_SATURATE 981 }; 982 983 const char* blendOpNames[] = 984 { 985 "add", // VK_BLEND_OP_ADD 986 "sub", // VK_BLEND_OP_SUBTRACT 987 "rsub", // VK_BLEND_OP_REVERSE_SUBTRACT 988 "min", // VK_BLEND_OP_MIN 989 "max", // VK_BLEND_OP_MAX 990 }; 991 992 std::ostringstream shortName; 993 994 shortName << "color_" << shortBlendFactorNames[blendState.srcColorBlendFactor] << "_" << shortBlendFactorNames[blendState.dstColorBlendFactor] << "_" << blendOpNames[blendState.colorBlendOp]; 995 shortName << "_alpha_" << shortBlendFactorNames[blendState.srcAlphaBlendFactor] << "_" << shortBlendFactorNames[blendState.dstAlphaBlendFactor] << "_" << blendOpNames[blendState.alphaBlendOp]; 996 997 return shortName.str(); 998} 999 1000std::string getBlendStateSetName (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]) 1001{ 1002 std::ostringstream name; 1003 1004 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 1005 { 1006 name << getBlendStateName(blendStates[quadNdx]); 1007 1008 if (quadNdx < BlendTest::QUAD_COUNT - 1) 1009 name << "-"; 1010 } 1011 1012 return name.str(); 1013} 1014 1015std::string getBlendStateSetDescription (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]) 1016{ 1017 std::ostringstream description; 1018 1019 description << "Draws " << BlendTest::QUAD_COUNT << " quads with the following blend states:\n"; 1020 1021 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 1022 description << blendStates[quadNdx] << "\n"; 1023 1024 return description.str(); 1025} 1026 1027std::string getFormatCaseName (VkFormat format) 1028{ 1029 const std::string fullName = getFormatName(format); 1030 1031 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_")); 1032 1033 return de::toLower(fullName.substr(10)); 1034} 1035 1036tcu::TestCaseGroup* createBlendTests (tcu::TestContext& testCtx) 1037{ 1038 const deUint32 blendStatesPerFormat = 100 * BlendTest::QUAD_COUNT; 1039 1040 // Formats that are dEQP-compatible, non-integer and uncompressed 1041 const VkFormat blendFormats[] = 1042 { 1043 VK_FORMAT_R4G4_UNORM_PACK8, 1044 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 1045 VK_FORMAT_R5G6B5_UNORM_PACK16, 1046 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 1047 VK_FORMAT_R8_UNORM, 1048 VK_FORMAT_R8_SNORM, 1049 VK_FORMAT_R8_SRGB, 1050 VK_FORMAT_R8G8_UNORM, 1051 VK_FORMAT_R8G8_SNORM, 1052 VK_FORMAT_R8G8_SRGB, 1053 VK_FORMAT_R8G8B8_UNORM, 1054 VK_FORMAT_R8G8B8_SNORM, 1055 VK_FORMAT_R8G8B8_SRGB, 1056 VK_FORMAT_R8G8B8A8_UNORM, 1057 VK_FORMAT_R8G8B8A8_SNORM, 1058 VK_FORMAT_R8G8B8A8_SRGB, 1059 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 1060 VK_FORMAT_R16_UNORM, 1061 VK_FORMAT_R16_SNORM, 1062 VK_FORMAT_R16_SFLOAT, 1063 VK_FORMAT_R16G16_UNORM, 1064 VK_FORMAT_R16G16_SNORM, 1065 VK_FORMAT_R16G16_SFLOAT, 1066 VK_FORMAT_R16G16B16_UNORM, 1067 VK_FORMAT_R16G16B16_SNORM, 1068 VK_FORMAT_R16G16B16_SFLOAT, 1069 VK_FORMAT_R16G16B16A16_UNORM, 1070 VK_FORMAT_R16G16B16A16_SNORM, 1071 VK_FORMAT_R16G16B16A16_SFLOAT, 1072 VK_FORMAT_R32_SFLOAT, 1073 VK_FORMAT_R32G32_SFLOAT, 1074 VK_FORMAT_R32G32B32_SFLOAT, 1075 VK_FORMAT_R32G32B32A32_SFLOAT, 1076 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 1077 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 1078 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 1079 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 1080 }; 1081 1082 de::MovePtr<tcu::TestCaseGroup> blendTests (new tcu::TestCaseGroup(testCtx, "blend", "Blend tests")); 1083 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Uses different blend formats")); 1084 BlendStateUniqueRandomIterator blendStateItr (blendStatesPerFormat, 123); 1085 1086 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(blendFormats); formatNdx++) 1087 { 1088 const VkFormat format = blendFormats[formatNdx]; 1089 de::MovePtr<tcu::TestCaseGroup> formatTest (new tcu::TestCaseGroup(testCtx, 1090 getFormatCaseName(format).c_str(), 1091 (std::string("Uses format ") + getFormatName(format)).c_str())); 1092 de::MovePtr<tcu::TestCaseGroup> blendStateTests; 1093 { 1094 std::ostringstream blendStateDescription; 1095 blendStateDescription << "Combines blend factors, operators and channel write masks. The constant color used in all tests is " << BlendTest::s_blendConst; 1096 blendStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", blendStateDescription.str().c_str())); 1097 } 1098 1099 blendStateItr.reset(); 1100 1101 while (blendStateItr.hasNext()) 1102 { 1103 VkPipelineColorBlendAttachmentState quadBlendConfigs[BlendTest::QUAD_COUNT]; 1104 1105 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 1106 { 1107 quadBlendConfigs[quadNdx] = blendStateItr.next(); 1108 quadBlendConfigs[quadNdx].colorWriteMask = BlendTest::s_colorWriteMasks[quadNdx]; 1109 } 1110 1111 blendStateTests->addChild(new BlendTest(testCtx, 1112 getBlendStateSetName(quadBlendConfigs), 1113 getBlendStateSetDescription(quadBlendConfigs), 1114 format, 1115 quadBlendConfigs)); 1116 } 1117 formatTest->addChild(blendStateTests.release()); 1118 formatTests->addChild(formatTest.release()); 1119 } 1120 blendTests->addChild(formatTests.release()); 1121 1122 return blendTests.release(); 1123} 1124 1125} // pipeline 1126} // vkt 1127