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 0.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 VkGraphicsPipelineCreateInfo graphicsPipelineParams = 620 { 621 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 622 DE_NULL, // const void* pNext; 623 0u, // VkPipelineCreateFlags flags; 624 2u, // deUint32 stageCount; 625 shaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 626 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 627 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 628 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 629 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; 630 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 631 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 632 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 633 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 634 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 635 *m_pipelineLayout, // VkPipelineLayout layout; 636 *m_renderPass, // VkRenderPass renderPass; 637 0u, // deUint32 subpass; 638 0u, // VkPipeline basePipelineHandle; 639 0u // deInt32 basePipelineIndex; 640 }; 641 642 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 643 { 644 colorBlendStateParams.attachmentCount = 1u; 645 colorBlendStateParams.pAttachments = &m_blendStates[quadNdx]; 646 m_graphicsPipelines[quadNdx] = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams); 647 } 648 } 649 650 // Create vertex buffer 651 { 652 const VkBufferCreateInfo vertexBufferParams = 653 { 654 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 655 DE_NULL, // const void* pNext; 656 0u, // VkBufferCreateFlags flags; 657 1024u, // VkDeviceSize size; 658 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 659 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 660 1u, // deUint32 queueFamilyIndexCount; 661 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 662 }; 663 664 m_vertices = createOverlappingQuads(); 665 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); 666 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible); 667 668 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); 669 670 // Adjust vertex colors 671 if (!isFloatFormat(m_colorFormat)) 672 { 673 const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(mapVkFormat(m_colorFormat)); 674 for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++) 675 m_vertices[vertexNdx].color = (m_vertices[vertexNdx].color - formatInfo.lookupBias) / formatInfo.lookupScale; 676 } 677 678 // Upload vertex data 679 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA)); 680 681 const VkMappedMemoryRange flushRange = 682 { 683 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; 684 DE_NULL, // const void* pNext; 685 m_vertexBufferAlloc->getMemory(), // VkDeviceMemory memory; 686 m_vertexBufferAlloc->getOffset(), // VkDeviceSize offset; 687 vertexBufferParams.size // VkDeviceSize size; 688 }; 689 690 vk.flushMappedMemoryRanges(vkDevice, 1, &flushRange); 691 } 692 693 // Create command pool 694 { 695 const VkCommandPoolCreateInfo cmdPoolParams = 696 { 697 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 698 DE_NULL, // const void* pNext; 699 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags; 700 queueFamilyIndex // deUint32 queueFamilyIndex; 701 }; 702 703 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams); 704 } 705 706 // Create command buffer 707 { 708 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = 709 { 710 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; 711 DE_NULL, // const void* pNext; 712 *m_cmdPool, // VkCommandPool commandPool; 713 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; 714 1u, // deUint32 bufferCount; 715 }; 716 717 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 718 { 719 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 720 DE_NULL, // const void* pNext; 721 0u, // VkCommandBufferUsageFlags flags; 722 (const VkCommandBufferInheritanceInfo*)DE_NULL, 723 }; 724 725 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat); 726 727 const VkRenderPassBeginInfo renderPassBeginInfo = 728 { 729 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 730 DE_NULL, // const void* pNext; 731 *m_renderPass, // VkRenderPass renderPass; 732 *m_framebuffer, // VkFramebuffer framebuffer; 733 { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea; 734 1, // deUint32 clearValueCount; 735 &attachmentClearValue // const VkClearValue* pClearValues; 736 }; 737 738 // Color image layout transition 739 const VkImageMemoryBarrier imageLayoutBarrier = 740 { 741 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 742 DE_NULL, // const void* pNext; 743 (VkAccessFlags)0, // VkAccessFlags srcAccessMask; 744 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; 745 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 746 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 747 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 748 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 749 *m_colorImage, // VkImage image; 750 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 751 }; 752 753 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo); 754 755 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo)); 756 757 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 758 0u, DE_NULL, 0u, DE_NULL, 1u, &imageLayoutBarrier); 759 760 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 761 762 const VkDeviceSize quadOffset = (m_vertices.size() / BlendTest::QUAD_COUNT) * sizeof(Vertex4RGBA); 763 764 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 765 { 766 VkDeviceSize vertexBufferOffset = quadOffset * quadNdx; 767 768 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines[quadNdx]); 769 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset); 770 vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / BlendTest::QUAD_COUNT), 1, 0, 0); 771 } 772 773 vk.cmdEndRenderPass(*m_cmdBuffer); 774 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); 775 } 776 777 // Create fence 778 { 779 const VkFenceCreateInfo fenceParams = 780 { 781 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; 782 DE_NULL, // const void* pNext; 783 0u // VkFenceCreateFlags flags; 784 }; 785 786 m_fence = createFence(vk, vkDevice, &fenceParams); 787 } 788} 789 790BlendTestInstance::~BlendTestInstance (void) 791{ 792} 793 794tcu::TestStatus BlendTestInstance::iterate (void) 795{ 796 const DeviceInterface& vk = m_context.getDeviceInterface(); 797 const VkDevice vkDevice = m_context.getDevice(); 798 const VkQueue queue = m_context.getUniversalQueue(); 799 const VkSubmitInfo submitInfo = 800 { 801 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 802 DE_NULL, // const void* pNext; 803 0u, // deUint32 waitSemaphoreCount; 804 DE_NULL, // const VkSemaphore* pWaitSemaphores; 805 (const VkPipelineStageFlags*)DE_NULL, 806 1u, // deUint32 commandBufferCount; 807 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers; 808 0u, // deUint32 signalSemaphoreCount; 809 DE_NULL // const VkSemaphore* pSignalSemaphores; 810 }; 811 812 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get())); 813 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence)); 814 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */)); 815 816 return verifyImage(); 817} 818 819float BlendTestInstance::getNormChannelThreshold (const tcu::TextureFormat& format, int numBits) 820{ 821 switch (tcu::getTextureChannelClass(format.type)) 822 { 823 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: return BlendTest::QUAD_COUNT / static_cast<float>((1 << numBits) - 1); 824 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: return BlendTest::QUAD_COUNT / static_cast<float>((1 << (numBits - 1)) - 1); 825 default: 826 break; 827 } 828 829 DE_ASSERT(false); 830 return 0.0f; 831} 832 833tcu::Vec4 BlendTestInstance::getFormatThreshold (const tcu::TextureFormat& format) 834{ 835 using tcu::Vec4; 836 using tcu::TextureFormat; 837 838 Vec4 threshold(0.01f); 839 840 switch (format.type) 841 { 842 case TextureFormat::UNORM_BYTE_44: 843 threshold = Vec4(getNormChannelThreshold(format, 4), getNormChannelThreshold(format, 4), 1.0f, 1.0f); 844 break; 845 846 case TextureFormat::UNORM_SHORT_565: 847 threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 6), getNormChannelThreshold(format, 5), 1.0f); 848 break; 849 850 case TextureFormat::UNORM_SHORT_555: 851 threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 1.0f); 852 break; 853 854 case TextureFormat::UNORM_SHORT_4444: 855 threshold = Vec4(getNormChannelThreshold(format, 4)); 856 break; 857 858 case TextureFormat::UNORM_SHORT_5551: 859 threshold = Vec4(getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), getNormChannelThreshold(format, 5), 0.1f); 860 break; 861 862 case TextureFormat::UNORM_INT_1010102_REV: 863 case TextureFormat::SNORM_INT_1010102_REV: 864 threshold = Vec4(getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), getNormChannelThreshold(format, 10), 0.34f); 865 break; 866 867 case TextureFormat::UNORM_INT8: 868 case TextureFormat::SNORM_INT8: 869 threshold = Vec4(getNormChannelThreshold(format, 8)); 870 break; 871 872 case TextureFormat::UNORM_INT16: 873 case TextureFormat::SNORM_INT16: 874 threshold = Vec4(getNormChannelThreshold(format, 16)); 875 break; 876 877 case TextureFormat::UNORM_INT32: 878 case TextureFormat::SNORM_INT32: 879 threshold = Vec4(getNormChannelThreshold(format, 32)); 880 break; 881 882 case TextureFormat::HALF_FLOAT: 883 threshold = Vec4(0.005f); 884 break; 885 886 case TextureFormat::FLOAT: 887 threshold = Vec4(0.00001f); 888 break; 889 890 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: 891 threshold = Vec4(0.02f, 0.02f, 0.0625f, 1.0f); 892 break; 893 894 case TextureFormat::UNSIGNED_INT_999_E5_REV: 895 threshold = Vec4(0.05f, 0.05f, 0.05f, 1.0f); 896 break; 897 898 default: 899 DE_ASSERT(false); 900 } 901 902 // Return value matching the channel order specified by the format 903 if (format.order == tcu::TextureFormat::BGR || format.order == tcu::TextureFormat::BGRA) 904 return threshold.swizzle(2, 1, 0, 3); 905 else 906 return threshold; 907} 908 909tcu::TestStatus BlendTestInstance::verifyImage (void) 910{ 911 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat); 912 const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat(); // Undefined depth/stencil format 913 const ColorVertexShader vertexShader; 914 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuDepthFormat); 915 const rr::Program program (&vertexShader, &fragmentShader); 916 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program); 917 bool compareOk = false; 918 919 // Render reference image 920 { 921 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 922 { 923 const VkPipelineColorBlendAttachmentState& blendState = m_blendStates[quadNdx]; 924 925 // Set blend state 926 rr::RenderState renderState (refRenderer.getViewportState()); 927 renderState.fragOps.blendMode = rr::BLENDMODE_STANDARD; 928 renderState.fragOps.blendRGBState.srcFunc = mapVkBlendFactor(blendState.srcColorBlendFactor); 929 renderState.fragOps.blendRGBState.dstFunc = mapVkBlendFactor(blendState.dstColorBlendFactor); 930 renderState.fragOps.blendRGBState.equation = mapVkBlendOp(blendState.colorBlendOp); 931 renderState.fragOps.blendAState.srcFunc = mapVkBlendFactor(blendState.srcAlphaBlendFactor); 932 renderState.fragOps.blendAState.dstFunc = mapVkBlendFactor(blendState.dstAlphaBlendFactor); 933 renderState.fragOps.blendAState.equation = mapVkBlendOp(blendState.alphaBlendOp); 934 renderState.fragOps.blendColor = BlendTest::s_blendConst; 935 renderState.fragOps.colorMask = mapVkColorComponentFlags(BlendTest::s_colorWriteMasks[quadNdx]); 936 937 refRenderer.draw(renderState, 938 rr::PRIMITIVETYPE_TRIANGLES, 939 std::vector<Vertex4RGBA>(m_vertices.begin() + quadNdx * 6, 940 m_vertices.begin() + (quadNdx + 1) * 6)); 941 } 942 } 943 944 945 // Compare result with reference image 946 { 947 const DeviceInterface& vk = m_context.getDeviceInterface(); 948 const VkDevice vkDevice = m_context.getDevice(); 949 const VkQueue queue = m_context.getUniversalQueue(); 950 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 951 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 952 de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release()); 953 const tcu::Vec4 threshold (getFormatThreshold(tcuColorFormat)); 954 955 compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), 956 "FloatImageCompare", 957 "Image comparison", 958 refRenderer.getAccess(), 959 result->getAccess(), 960 threshold, 961 tcu::COMPARE_LOG_RESULT); 962 } 963 964 if (compareOk) 965 return tcu::TestStatus::pass("Result image matches reference"); 966 else 967 return tcu::TestStatus::fail("Image mismatch"); 968} 969 970} // anonymous 971 972std::string getBlendStateName (const VkPipelineColorBlendAttachmentState& blendState) 973{ 974 const char* shortBlendFactorNames[] = 975 { 976 "z", // VK_BLEND_ZERO 977 "o", // VK_BLEND_ONE 978 "sc", // VK_BLEND_SRC_COLOR 979 "1msc", // VK_BLEND_ONE_MINUS_SRC_COLOR 980 "dc", // VK_BLEND_DEST_COLOR 981 "1mdc", // VK_BLEND_ONE_MINUS_DEST_COLOR 982 "sa", // VK_BLEND_SRC_ALPHA 983 "1msa", // VK_BLEND_ONE_MINUS_SRC_ALPHA 984 "da", // VK_BLEND_DEST_ALPHA 985 "1mda", // VK_BLEND_ONE_MINUS_DEST_ALPHA 986 "cc", // VK_BLEND_CONSTANT_COLOR 987 "1mcc", // VK_BLEND_ONE_MINUS_CONSTANT_COLOR 988 "ca", // VK_BLEND_CONSTANT_ALPHA 989 "1mca", // VK_BLEND_ONE_MINUS_CONSTANT_ALPHA 990 "sas" // VK_BLEND_SRC_ALPHA_SATURATE 991 }; 992 993 const char* blendOpNames[] = 994 { 995 "add", // VK_BLEND_OP_ADD 996 "sub", // VK_BLEND_OP_SUBTRACT 997 "rsub", // VK_BLEND_OP_REVERSE_SUBTRACT 998 "min", // VK_BLEND_OP_MIN 999 "max", // VK_BLEND_OP_MAX 1000 }; 1001 1002 std::ostringstream shortName; 1003 1004 shortName << "color_" << shortBlendFactorNames[blendState.srcColorBlendFactor] << "_" << shortBlendFactorNames[blendState.dstColorBlendFactor] << "_" << blendOpNames[blendState.colorBlendOp]; 1005 shortName << "_alpha_" << shortBlendFactorNames[blendState.srcAlphaBlendFactor] << "_" << shortBlendFactorNames[blendState.dstAlphaBlendFactor] << "_" << blendOpNames[blendState.alphaBlendOp]; 1006 1007 return shortName.str(); 1008} 1009 1010std::string getBlendStateSetName (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]) 1011{ 1012 std::ostringstream name; 1013 1014 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 1015 { 1016 name << getBlendStateName(blendStates[quadNdx]); 1017 1018 if (quadNdx < BlendTest::QUAD_COUNT - 1) 1019 name << "-"; 1020 } 1021 1022 return name.str(); 1023} 1024 1025std::string getBlendStateSetDescription (const VkPipelineColorBlendAttachmentState blendStates[BlendTest::QUAD_COUNT]) 1026{ 1027 std::ostringstream description; 1028 1029 description << "Draws " << BlendTest::QUAD_COUNT << " quads with the following blend states:\n"; 1030 1031 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 1032 description << blendStates[quadNdx] << "\n"; 1033 1034 return description.str(); 1035} 1036 1037std::string getFormatCaseName (VkFormat format) 1038{ 1039 const std::string fullName = getFormatName(format); 1040 1041 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_")); 1042 1043 return de::toLower(fullName.substr(10)); 1044} 1045 1046tcu::TestCaseGroup* createBlendTests (tcu::TestContext& testCtx) 1047{ 1048 const deUint32 blendStatesPerFormat = 100 * BlendTest::QUAD_COUNT; 1049 1050 // Formats that are dEQP-compatible, non-integer and uncompressed 1051 const VkFormat blendFormats[] = 1052 { 1053 VK_FORMAT_R4G4_UNORM_PACK8, 1054 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 1055 VK_FORMAT_R5G6B5_UNORM_PACK16, 1056 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 1057 VK_FORMAT_R8_UNORM, 1058 VK_FORMAT_R8_SNORM, 1059 VK_FORMAT_R8_SRGB, 1060 VK_FORMAT_R8G8_UNORM, 1061 VK_FORMAT_R8G8_SNORM, 1062 VK_FORMAT_R8G8_SRGB, 1063 VK_FORMAT_R8G8B8_UNORM, 1064 VK_FORMAT_R8G8B8_SNORM, 1065 VK_FORMAT_R8G8B8_SRGB, 1066 VK_FORMAT_R8G8B8A8_UNORM, 1067 VK_FORMAT_R8G8B8A8_SNORM, 1068 VK_FORMAT_R8G8B8A8_SRGB, 1069 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 1070 VK_FORMAT_R16_UNORM, 1071 VK_FORMAT_R16_SNORM, 1072 VK_FORMAT_R16_SFLOAT, 1073 VK_FORMAT_R16G16_UNORM, 1074 VK_FORMAT_R16G16_SNORM, 1075 VK_FORMAT_R16G16_SFLOAT, 1076 VK_FORMAT_R16G16B16_UNORM, 1077 VK_FORMAT_R16G16B16_SNORM, 1078 VK_FORMAT_R16G16B16_SFLOAT, 1079 VK_FORMAT_R16G16B16A16_UNORM, 1080 VK_FORMAT_R16G16B16A16_SNORM, 1081 VK_FORMAT_R16G16B16A16_SFLOAT, 1082 VK_FORMAT_R32_SFLOAT, 1083 VK_FORMAT_R32G32_SFLOAT, 1084 VK_FORMAT_R32G32B32_SFLOAT, 1085 VK_FORMAT_R32G32B32A32_SFLOAT, 1086 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 1087 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 1088 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 1089 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 1090 }; 1091 1092 de::MovePtr<tcu::TestCaseGroup> blendTests (new tcu::TestCaseGroup(testCtx, "blend", "Blend tests")); 1093 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Uses different blend formats")); 1094 BlendStateUniqueRandomIterator blendStateItr (blendStatesPerFormat, 123); 1095 1096 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(blendFormats); formatNdx++) 1097 { 1098 const VkFormat format = blendFormats[formatNdx]; 1099 de::MovePtr<tcu::TestCaseGroup> formatTest (new tcu::TestCaseGroup(testCtx, 1100 getFormatCaseName(format).c_str(), 1101 (std::string("Uses format ") + getFormatName(format)).c_str())); 1102 de::MovePtr<tcu::TestCaseGroup> blendStateTests; 1103 { 1104 std::ostringstream blendStateDescription; 1105 blendStateDescription << "Combines blend factors, operators and channel write masks. The constant color used in all tests is " << BlendTest::s_blendConst; 1106 blendStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states", blendStateDescription.str().c_str())); 1107 } 1108 1109 blendStateItr.reset(); 1110 1111 while (blendStateItr.hasNext()) 1112 { 1113 VkPipelineColorBlendAttachmentState quadBlendConfigs[BlendTest::QUAD_COUNT]; 1114 1115 for (int quadNdx = 0; quadNdx < BlendTest::QUAD_COUNT; quadNdx++) 1116 { 1117 quadBlendConfigs[quadNdx] = blendStateItr.next(); 1118 quadBlendConfigs[quadNdx].colorWriteMask = BlendTest::s_colorWriteMasks[quadNdx]; 1119 } 1120 1121 blendStateTests->addChild(new BlendTest(testCtx, 1122 getBlendStateSetName(quadBlendConfigs), 1123 getBlendStateSetDescription(quadBlendConfigs), 1124 format, 1125 quadBlendConfigs)); 1126 } 1127 formatTest->addChild(blendStateTests.release()); 1128 formatTests->addChild(formatTest.release()); 1129 } 1130 blendTests->addChild(formatTests.release()); 1131 1132 return blendTests.release(); 1133} 1134 1135} // pipeline 1136} // vkt 1137