1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file vktPipelineRenderToImageTests.cpp 21 * \brief Render to image tests 22 *//*--------------------------------------------------------------------*/ 23 24#include "vktPipelineRenderToImageTests.hpp" 25#include "vktPipelineMakeUtil.hpp" 26#include "vktTestCase.hpp" 27#include "vktTestCaseUtil.hpp" 28#include "vktPipelineVertexUtil.hpp" 29#include "vktTestGroupUtil.hpp" 30 31#include "vkMemUtil.hpp" 32#include "vkQueryUtil.hpp" 33#include "vkTypeUtil.hpp" 34#include "vkRefUtil.hpp" 35#include "vkBuilderUtil.hpp" 36#include "vkPrograms.hpp" 37#include "vkImageUtil.hpp" 38 39#include "tcuTextureUtil.hpp" 40#include "tcuImageCompare.hpp" 41 42#include "deUniquePtr.hpp" 43#include "deSharedPtr.hpp" 44 45#include <string> 46#include <vector> 47 48namespace vkt 49{ 50namespace pipeline 51{ 52namespace 53{ 54using namespace vk; 55using de::UniquePtr; 56using de::MovePtr; 57using de::SharedPtr; 58using tcu::IVec3; 59using tcu::Vec4; 60using tcu::UVec4; 61using tcu::IVec4; 62using std::vector; 63 64typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView; 65typedef SharedPtr<Unique<VkPipeline> > SharedPtrVkPipeline; 66 67enum Constants 68{ 69 REFERENCE_COLOR_VALUE = 125 70}; 71 72struct CaseDef 73{ 74 VkImageViewType imageType; 75 IVec3 renderSize; 76 int numLayers; 77 VkFormat colorFormat; 78}; 79 80template<typename T> 81inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move) 82{ 83 return SharedPtr<Unique<T> >(new Unique<T>(move)); 84} 85 86template<typename T> 87inline VkDeviceSize sizeInBytes (const vector<T>& vec) 88{ 89 return vec.size() * sizeof(vec[0]); 90} 91 92Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 93 const VkDevice device, 94 const VkPipelineLayout pipelineLayout, 95 const VkRenderPass renderPass, 96 const VkShaderModule vertexModule, 97 const VkShaderModule fragmentModule, 98 const IVec3 renderSize, 99 const VkPrimitiveTopology topology, 100 const deUint32 subpass) 101{ 102 const VkVertexInputBindingDescription vertexInputBindingDescription = 103 { 104 0u, // uint32_t binding; 105 sizeof(Vertex4RGBA), // uint32_t stride; 106 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 107 }; 108 109 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = 110 { 111 { 112 0u, // uint32_t location; 113 0u, // uint32_t binding; 114 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 115 0u, // uint32_t offset; 116 }, 117 { 118 1u, // uint32_t location; 119 0u, // uint32_t binding; 120 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 121 sizeof(Vec4), // uint32_t offset; 122 } 123 }; 124 125 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 126 { 127 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 128 DE_NULL, // const void* pNext; 129 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 130 1u, // uint32_t vertexBindingDescriptionCount; 131 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 132 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount; 133 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 134 }; 135 136 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 137 { 138 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 139 DE_NULL, // const void* pNext; 140 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 141 topology, // VkPrimitiveTopology topology; 142 VK_FALSE, // VkBool32 primitiveRestartEnable; 143 }; 144 145 const VkViewport viewport = makeViewport( 146 0.0f, 0.0f, 147 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 148 0.0f, 1.0f); 149 150 const VkRect2D scissor = 151 { 152 makeOffset2D(0, 0), 153 makeExtent2D(renderSize.x(), renderSize.y()), 154 }; 155 156 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 157 { 158 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 159 DE_NULL, // const void* pNext; 160 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 161 1u, // uint32_t viewportCount; 162 &viewport, // const VkViewport* pViewports; 163 1u, // uint32_t scissorCount; 164 &scissor, // const VkRect2D* pScissors; 165 }; 166 167 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 168 { 169 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 170 DE_NULL, // const void* pNext; 171 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 172 VK_FALSE, // VkBool32 depthClampEnable; 173 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 174 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 175 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 176 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 177 VK_FALSE, // VkBool32 depthBiasEnable; 178 0.0f, // float depthBiasConstantFactor; 179 0.0f, // float depthBiasClamp; 180 0.0f, // float depthBiasSlopeFactor; 181 1.0f, // float lineWidth; 182 }; 183 184 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 185 { 186 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 187 DE_NULL, // const void* pNext; 188 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 189 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 190 VK_FALSE, // VkBool32 sampleShadingEnable; 191 0.0f, // float minSampleShading; 192 DE_NULL, // const VkSampleMask* pSampleMask; 193 VK_FALSE, // VkBool32 alphaToCoverageEnable; 194 VK_FALSE // VkBool32 alphaToOneEnable; 195 }; 196 197 const VkStencilOpState stencilOpState = makeStencilOpState( 198 VK_STENCIL_OP_KEEP, // stencil fail 199 VK_STENCIL_OP_KEEP, // depth & stencil pass 200 VK_STENCIL_OP_KEEP, // depth only fail 201 VK_COMPARE_OP_ALWAYS, // compare op 202 0u, // compare mask 203 0u, // write mask 204 0u); // reference 205 206 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 207 { 208 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 209 DE_NULL, // const void* pNext; 210 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 211 VK_FALSE, // VkBool32 depthTestEnable; 212 VK_FALSE, // VkBool32 depthWriteEnable; 213 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 214 VK_FALSE, // VkBool32 depthBoundsTestEnable; 215 VK_FALSE, // VkBool32 stencilTestEnable; 216 stencilOpState, // VkStencilOpState front; 217 stencilOpState, // VkStencilOpState back; 218 0.0f, // float minDepthBounds; 219 1.0f, // float maxDepthBounds; 220 }; 221 222 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 223 // Number of blend attachments must equal the number of color attachments during any subpass. 224 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 225 { 226 VK_FALSE, // VkBool32 blendEnable; 227 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 228 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 229 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 230 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 231 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 232 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 233 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 234 }; 235 236 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 237 { 238 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 239 DE_NULL, // const void* pNext; 240 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 241 VK_FALSE, // VkBool32 logicOpEnable; 242 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 243 1u, // deUint32 attachmentCount; 244 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 245 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 246 }; 247 248 const VkPipelineShaderStageCreateInfo pShaderStages[] = 249 { 250 { 251 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 252 DE_NULL, // const void* pNext; 253 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 254 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 255 vertexModule, // VkShaderModule module; 256 "main", // const char* pName; 257 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 258 }, 259 { 260 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 261 DE_NULL, // const void* pNext; 262 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 263 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 264 fragmentModule, // VkShaderModule module; 265 "main", // const char* pName; 266 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 267 } 268 }; 269 270 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 271 { 272 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 273 DE_NULL, // const void* pNext; 274 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 275 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; 276 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 277 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 278 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 279 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 280 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 281 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 282 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 283 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 284 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 285 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 286 pipelineLayout, // VkPipelineLayout layout; 287 renderPass, // VkRenderPass renderPass; 288 subpass, // deUint32 subpass; 289 DE_NULL, // VkPipeline basePipelineHandle; 290 0, // deInt32 basePipelineIndex; 291 }; 292 293 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 294} 295 296//! Make a render pass with one subpass per color attachment and one attachment per image layer. 297Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 298 const VkDevice device, 299 const VkFormat colorFormat, 300 const deUint32 numLayers) 301{ 302 const VkAttachmentDescription colorAttachmentDescription = 303 { 304 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 305 colorFormat, // VkFormat format; 306 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 307 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 308 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 309 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 310 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 311 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 312 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 313 }; 314 const vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription); 315 316 // Create a subpass for each attachment (each attachement is a layer of an arrayed image). 317 vector<VkAttachmentReference> colorAttachmentReferences(numLayers); 318 vector<VkSubpassDescription> subpasses; 319 320 for (deUint32 i = 0; i < numLayers; ++i) 321 { 322 const VkAttachmentReference attachmentRef = 323 { 324 i, // deUint32 attachment; 325 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 326 }; 327 colorAttachmentReferences[i] = attachmentRef; 328 329 const VkSubpassDescription subpassDescription = 330 { 331 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 332 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 333 0u, // deUint32 inputAttachmentCount; 334 DE_NULL, // const VkAttachmentReference* pInputAttachments; 335 1u, // deUint32 colorAttachmentCount; 336 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments; 337 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 338 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 339 0u, // deUint32 preserveAttachmentCount; 340 DE_NULL // const deUint32* pPreserveAttachments; 341 }; 342 subpasses.push_back(subpassDescription); 343 } 344 345 const VkRenderPassCreateInfo renderPassInfo = 346 { 347 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 348 DE_NULL, // const void* pNext; 349 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 350 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount; 351 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; 352 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 353 &subpasses[0], // const VkSubpassDescription* pSubpasses; 354 0u, // deUint32 dependencyCount; 355 DE_NULL // const VkSubpassDependency* pDependencies; 356 }; 357 358 return createRenderPass(vk, device, &renderPassInfo); 359} 360 361Move<VkImage> makeImage (const DeviceInterface& vk, 362 const VkDevice device, 363 VkImageCreateFlags flags, 364 VkImageType imageType, 365 const VkFormat format, 366 const IVec3& size, 367 const deUint32 numLayers, 368 const VkImageUsageFlags usage) 369{ 370 const VkImageCreateInfo imageParams = 371 { 372 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 373 DE_NULL, // const void* pNext; 374 flags, // VkImageCreateFlags flags; 375 imageType, // VkImageType imageType; 376 format, // VkFormat format; 377 makeExtent3D(size), // VkExtent3D extent; 378 1u, // deUint32 mipLevels; 379 numLayers, // deUint32 arrayLayers; 380 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 381 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 382 usage, // VkImageUsageFlags usage; 383 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 384 0u, // deUint32 queueFamilyIndexCount; 385 DE_NULL, // const deUint32* pQueueFamilyIndices; 386 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 387 }; 388 return createImage(vk, device, &imageParams); 389} 390 391inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage) 392{ 393 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage); 394 return createBuffer(vk, device, &bufferCreateInfo); 395} 396 397inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount) 398{ 399 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount)); 400} 401 402//! Get a reference clear value based on color format. 403VkClearValue getClearValue (const VkFormat format) 404{ 405 if (isUintFormat(format) || isIntFormat(format)) 406 return makeClearValueColorU32(REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE); 407 else 408 return makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f); 409} 410 411std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint) 412{ 413 std::ostringstream str; 414 if (numComponents == 1) 415 str << (isUint ? "uint" : isSint ? "int" : "float"); 416 else 417 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents; 418 419 return str.str(); 420} 421 422//! A half-viewport quad. Use with TRIANGLE_STRIP topology. 423vector<Vertex4RGBA> genFullQuadVertices (const int subpassCount, const vector<Vec4>& color) 424{ 425 vector<Vertex4RGBA> vectorData; 426 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx) 427 { 428 Vertex4RGBA data = 429 { 430 Vec4(0.0f, -1.0f, 0.0f, 1.0f), 431 color[subpassNdx % color.size()], 432 }; 433 vectorData.push_back(data); 434 data.position = Vec4(0.0f, 1.0f, 0.0f, 1.0f); 435 vectorData.push_back(data); 436 data.position = Vec4(1.0f, -1.0f, 0.0f, 1.0f); 437 vectorData.push_back(data); 438 data.position = Vec4(1.0f, 1.0f, 0.0f, 1.0f); 439 vectorData.push_back(data); 440 } 441 return vectorData; 442} 443 444VkImageType getImageType (const VkImageViewType viewType) 445{ 446 switch (viewType) 447 { 448 case VK_IMAGE_VIEW_TYPE_1D: 449 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 450 return VK_IMAGE_TYPE_1D; 451 452 case VK_IMAGE_VIEW_TYPE_2D: 453 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 454 case VK_IMAGE_VIEW_TYPE_CUBE: 455 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 456 return VK_IMAGE_TYPE_2D; 457 458 case VK_IMAGE_VIEW_TYPE_3D: 459 return VK_IMAGE_TYPE_3D; 460 461 default: 462 DE_ASSERT(0); 463 return VK_IMAGE_TYPE_LAST; 464 } 465} 466 467void initPrograms (SourceCollections& programCollection, const CaseDef caseDef) 468{ 469 const int numComponents = getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order); 470 const bool isUint = isUintFormat(caseDef.colorFormat); 471 const bool isSint = isIntFormat(caseDef.colorFormat); 472 473 // Vertex shader 474 { 475 std::ostringstream src; 476 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 477 << "\n" 478 << "layout(location = 0) in vec4 in_position;\n" 479 << "layout(location = 1) in vec4 in_color;\n" 480 << "layout(location = 0) out vec4 out_color;\n" 481 << "\n" 482 << "out gl_PerVertex {\n" 483 << " vec4 gl_Position;\n" 484 << "};\n" 485 << "\n" 486 << "void main(void)\n" 487 << "{\n" 488 << " gl_Position = in_position;\n" 489 << " out_color = in_color;\n" 490 << "}\n"; 491 492 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 493 } 494 495 // Fragment shader 496 { 497 std::ostringstream colorValue; 498 colorValue << REFERENCE_COLOR_VALUE; 499 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint); 500 const std::string colorInteger = (isUint || isSint ? " * "+colorFormat+"("+colorValue.str()+")" :""); 501 502 std::ostringstream src; 503 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 504 << "\n" 505 << "layout(location = 0) in vec4 in_color;\n" 506 << "layout(location = 0) out " << colorFormat << " o_color;\n" 507 << "\n" 508 << "void main(void)\n" 509 << "{\n" 510 << " o_color = " << colorFormat << "(" 511 << (numComponents == 1 ? "in_color.r" : 512 numComponents == 2 ? "in_color.rg" : 513 numComponents == 3 ? "in_color.rgb" : "in_color") 514 << colorInteger 515 << ");\n" 516 << "}\n"; 517 518 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 519 } 520} 521 522tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef, const Vec4* color, const int sizeColor) 523{ 524 const bool isInt = isUintFormat(caseDef.colorFormat) || isIntFormat(caseDef.colorFormat); 525 const tcu::PixelBufferAccess expectedImage (textureLevel); 526 527 if (isInt) 528 tcu::clear(expectedImage, tcu::IVec4(REFERENCE_COLOR_VALUE)); 529 else 530 tcu::clear(expectedImage, tcu::Vec4(1.0)); 531 532 for (int z = 0; z < expectedImage.getDepth(); ++z) 533 { 534 const Vec4& setColor = color[z % sizeColor]; 535 const IVec4 setColorInt = (static_cast<float>(REFERENCE_COLOR_VALUE) * setColor).cast<deInt32>(); 536 537 for (int y = 0; y < caseDef.renderSize.y(); ++y) 538 for (int x = caseDef.renderSize.x()/2; x < caseDef.renderSize.x(); ++x) 539 { 540 if (isInt) 541 expectedImage.setPixel(setColorInt, x, y, z); 542 else 543 expectedImage.setPixel(setColor, x, y, z); 544 } 545 } 546 return expectedImage; 547} 548 549tcu::TestStatus test (Context& context, const CaseDef caseDef) 550{ 551 if (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType && 552 (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1"))) 553 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported"); 554 555 const DeviceInterface& vk = context.getDeviceInterface(); 556 const VkDevice device = context.getDevice(); 557 const VkQueue queue = context.getUniversalQueue(); 558 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 559 Allocator& allocator = context.getDefaultAllocator(); 560 Move<VkImage> colorImage; 561 MovePtr<Allocation> colorImageAlloc; 562 const Vec4 color[] = 563 { 564 Vec4(0.9f, 0.0f, 0.0f, 1.0f), 565 Vec4(0.6f, 1.0f, 0.0f, 1.0f), 566 Vec4(0.3f, 0.0f, 1.0f, 1.0f), 567 Vec4(0.1f, 0.0f, 1.0f, 1.0f) 568 }; 569 570 const int numLayers = (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? caseDef.renderSize.z() : caseDef.numLayers); 571 const VkDeviceSize colorBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.renderSize.z() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)); 572 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 573 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); 574 575 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); 576 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); 577 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, caseDef.colorFormat, static_cast<deUint32>(numLayers))); 578 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device)); 579 vector<SharedPtrVkPipeline> pipeline; 580 const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex)); 581 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 582 583 vector<SharedPtrVkImageView> colorAttachments; 584 vector<VkImageView> attachmentHandles; 585 Move<VkBuffer> vertexBuffer; 586 MovePtr<Allocation> vertexBufferAlloc; 587 Move<VkFramebuffer> framebuffer; 588 589 //create colorImage 590 { 591 const VkImageViewCreateFlags flags = (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? (VkImageViewCreateFlags)VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageViewCreateFlags)0); 592 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 593 colorImage = makeImage(vk, device, flags, getImageType(caseDef.imageType), caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, colorImageUsage); 594 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any); 595 } 596 597 //create vertexBuffer 598 { 599 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numLayers, vector<Vec4>(color, color + DE_LENGTH_OF_ARRAY(color))); 600 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 601 602 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 603 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible); 604 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 605 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize); 606 } 607 608 //create attachmentHandles and pipelines 609 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx) 610 { 611 const VkImageViewType imageType = (VK_IMAGE_VIEW_TYPE_3D == caseDef.imageType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : 612 (VK_IMAGE_VIEW_TYPE_CUBE == caseDef.imageType || VK_IMAGE_VIEW_TYPE_CUBE_ARRAY == caseDef.imageType ? VK_IMAGE_VIEW_TYPE_2D : 613 caseDef.imageType)); 614 615 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, *colorImage, imageType, caseDef.colorFormat, makeColorSubresourceRange(layerNdx, 1)))); 616 attachmentHandles.push_back(**colorAttachments.back()); 617 618 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, 619 caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, static_cast<deUint32>(layerNdx)))); 620 } 621 622 framebuffer = makeFramebuffer(vk, device, *renderPass, numLayers, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y())); 623 624 beginCommandBuffer(vk, *cmdBuffer); 625 { 626 const vector<VkClearValue> clearValues (numLayers, getClearValue(caseDef.colorFormat)); 627 const VkRect2D renderArea = 628 { 629 makeOffset2D(0, 0), 630 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()), 631 }; 632 const VkRenderPassBeginInfo renderPassBeginInfo = 633 { 634 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 635 DE_NULL, // const void* pNext; 636 *renderPass, // VkRenderPass renderPass; 637 *framebuffer, // VkFramebuffer framebuffer; 638 renderArea, // VkRect2D renderArea; 639 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount; 640 &clearValues[0], // const VkClearValue* pClearValues; 641 }; 642 const VkDeviceSize vertexBufferOffset = 0ull; 643 644 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 645 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 646 } 647 648 //cmdDraw 649 for (deUint32 layerNdx = 0; layerNdx < static_cast<deUint32>(numLayers); ++layerNdx) 650 { 651 if (layerNdx != 0) 652 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 653 654 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]); 655 vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u); 656 } 657 658 vk.cmdEndRenderPass(*cmdBuffer); 659 660 // copy colorImage -> host visible colorBuffer 661 { 662 const VkImageMemoryBarrier imageBarriers[] = 663 { 664 { 665 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 666 DE_NULL, // const void* pNext; 667 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; 668 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; 669 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 670 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 671 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 672 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 673 *colorImage, // VkImage image; 674 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 675 } 676 }; 677 678 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 679 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers); 680 681 const VkBufferImageCopy region = 682 { 683 0ull, // VkDeviceSize bufferOffset; 684 0u, // uint32_t bufferRowLength; 685 0u, // uint32_t bufferImageHeight; 686 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource; 687 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 688 makeExtent3D(caseDef.renderSize), // VkExtent3D imageExtent; 689 }; 690 691 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion); 692 693 const VkBufferMemoryBarrier bufferBarriers[] = 694 { 695 { 696 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 697 DE_NULL, // const void* pNext; 698 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 699 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 700 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 701 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 702 *colorBuffer, // VkBuffer buffer; 703 0ull, // VkDeviceSize offset; 704 VK_WHOLE_SIZE, // VkDeviceSize size; 705 }, 706 }; 707 708 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 709 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL); 710 } 711 712 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 713 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 714 715 // Verify results 716 { 717 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); 718 719 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat); 720 const int depth = deMax32(caseDef.renderSize.z(), caseDef.numLayers); 721 tcu::TextureLevel textureLevel (format, caseDef.renderSize.x(), caseDef.renderSize.y(), depth); 722 const tcu::PixelBufferAccess expectedImage = getExpectedData (textureLevel, caseDef, color, DE_LENGTH_OF_ARRAY(color)); 723 const tcu::ConstPixelBufferAccess resultImage (format, caseDef.renderSize.x(), caseDef.renderSize.y(), depth, colorBufferAlloc->getHostPtr()); 724 725 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT)) 726 return tcu::TestStatus::fail("Fail"); 727 } 728 return tcu::TestStatus::pass("Pass"); 729} 730 731std::string getSizeString (const IVec3& size, const int numLayer) 732{ 733 std::ostringstream str; 734 str << size.x(); 735 if (size.y() > 1) str << "x" << size.y(); 736 if (size.z() > 1) str << "x" << size.z(); 737 if (numLayer > 1) str << "_" << numLayer; 738 739 return str.str(); 740} 741 742std::string getFormatString (const VkFormat format) 743{ 744 std::string name(getFormatName(format)); 745 return de::toLower(name.substr(10)); 746} 747 748std::string getShortImageViewTypeName (const VkImageViewType imageViewType) 749{ 750 std::string s(getImageViewTypeName(imageViewType)); 751 return de::toLower(s.substr(19)); 752} 753 754CaseDef caseDefWithFormat (CaseDef caseDef, const VkFormat format) 755{ 756 caseDef.colorFormat = format; 757 return caseDef; 758} 759 760void addTestCasesWithFunctions (tcu::TestCaseGroup* group) 761{ 762 const CaseDef caseDef[] = 763 { 764 { VK_IMAGE_VIEW_TYPE_1D, IVec3(54, 1, 1), 1, VK_FORMAT_UNDEFINED}, 765 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(54, 1, 1), 4, VK_FORMAT_UNDEFINED}, 766 { VK_IMAGE_VIEW_TYPE_2D, IVec3(22, 64, 1), 1, VK_FORMAT_UNDEFINED}, 767 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(22, 64, 1), 4, VK_FORMAT_UNDEFINED}, 768 { VK_IMAGE_VIEW_TYPE_3D, IVec3(22, 64, 7), 1, VK_FORMAT_UNDEFINED}, 769 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(35, 35, 1), 6, VK_FORMAT_UNDEFINED}, 770 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(35, 35, 1), 2*6, VK_FORMAT_UNDEFINED}, 771 }; 772 773 const VkFormat format[] = 774 { 775 VK_FORMAT_R8G8B8A8_UNORM, 776 VK_FORMAT_R32_UINT, 777 VK_FORMAT_R16G16_SINT, 778 VK_FORMAT_R32G32B32A32_SFLOAT, 779 }; 780 781 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx) 782 { 783 MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(group->getTestContext(), getShortImageViewTypeName(caseDef[sizeNdx].imageType).c_str(), "")); 784 { 785 MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeString(caseDef[sizeNdx].renderSize, caseDef[sizeNdx].numLayers).c_str(), "")); 786 787 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx) 788 addFunctionCaseWithPrograms(sizeGroup.get(), getFormatString(format[formatNdx]).c_str(), "", initPrograms, test, caseDefWithFormat(caseDef[sizeNdx], format[formatNdx])); 789 790 imageGroup->addChild(sizeGroup.release()); 791 } 792 group->addChild(imageGroup.release()); 793 } 794} 795 796} // anonymous ns 797 798tcu::TestCaseGroup* createRenderToImageTests (tcu::TestContext& testCtx) 799{ 800 return createTestGroup(testCtx, "render_to_image", "Render to image tests", addTestCasesWithFunctions); 801} 802 803} // pipeline 804} // vkt 805