1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2017 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 vktPipelineFramebuferAttachmentTests.cpp 21 * \brief Render to a framebuffer with attachments of different sizes and with 22 * no attachments at all 23 * 24 *//*--------------------------------------------------------------------*/ 25 26 #include "vktPipelineFramebufferAttachmentTests.hpp" 27 #include "vktPipelineMakeUtil.hpp" 28 #include "vktTestCase.hpp" 29 #include "vktTestCaseUtil.hpp" 30 #include "vktPipelineVertexUtil.hpp" 31 #include "vktTestGroupUtil.hpp" 32 33 #include "vkMemUtil.hpp" 34 #include "vkBarrierUtil.hpp" 35 #include "vkQueryUtil.hpp" 36 #include "vkTypeUtil.hpp" 37 #include "vkRefUtil.hpp" 38 #include "vkBuilderUtil.hpp" 39 #include "vkPrograms.hpp" 40 #include "vkImageUtil.hpp" 41 #include "vkCmdUtil.hpp" 42 #include "vkObjUtil.hpp" 43 44 #include "tcuTextureUtil.hpp" 45 #include "tcuImageCompare.hpp" 46 47 #include "deUniquePtr.hpp" 48 #include "deSharedPtr.hpp" 49 50 #include <string> 51 #include <vector> 52 53 namespace vkt 54 { 55 namespace pipeline 56 { 57 namespace 58 { 59 using namespace vk; 60 using de::UniquePtr; 61 using de::MovePtr; 62 using de::SharedPtr; 63 using tcu::IVec3; 64 using tcu::Vec4; 65 using tcu::UVec4; 66 using tcu::IVec4; 67 using std::vector; 68 69 static const VkFormat COLOR_FORMAT = VK_FORMAT_R8G8B8A8_UNORM; 70 71 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView; 72 typedef SharedPtr<Unique<VkPipeline> > SharedPtrVkPipeline; 73 74 struct CaseDef 75 { 76 VkImageViewType imageType; 77 IVec3 renderSize; 78 IVec3 attachmentSize; 79 deUint32 numLayers; 80 bool multisample; 81 }; 82 83 template<typename T> 84 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move) 85 { 86 return SharedPtr<Unique<T> >(new Unique<T>(move)); 87 } 88 89 template<typename T> 90 inline VkDeviceSize sizeInBytes(const vector<T>& vec) 91 { 92 return vec.size() * sizeof(vec[0]); 93 } 94 95 VkImageType getImageType(const VkImageViewType viewType) 96 { 97 switch (viewType) 98 { 99 case VK_IMAGE_VIEW_TYPE_1D: 100 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 101 return VK_IMAGE_TYPE_1D; 102 103 case VK_IMAGE_VIEW_TYPE_2D: 104 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 105 case VK_IMAGE_VIEW_TYPE_CUBE: 106 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 107 return VK_IMAGE_TYPE_2D; 108 109 case VK_IMAGE_VIEW_TYPE_3D: 110 return VK_IMAGE_TYPE_3D; 111 112 default: 113 DE_ASSERT(0); 114 return VK_IMAGE_TYPE_LAST; 115 } 116 } 117 118 //! Make a render pass with one subpass per color attachment and one attachment per image layer. 119 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 120 const VkDevice device, 121 const VkFormat colorFormat, 122 const deUint32 numLayers, 123 const bool multisample) 124 { 125 vector<VkAttachmentDescription> attachmentDescriptions (numLayers); 126 deUint32 attachmentIndex = 0; 127 vector<VkAttachmentReference> colorAttachmentReferences (numLayers); 128 vector<VkSubpassDescription> subpasses; 129 130 for (deUint32 i = 0; i < numLayers; i++) 131 { 132 VkAttachmentDescription colorAttachmentDescription = 133 { 134 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags; 135 colorFormat, // VkFormat format; 136 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples; 137 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; 138 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 139 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 140 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 141 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout; 142 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 143 }; 144 attachmentDescriptions[attachmentIndex++] = colorAttachmentDescription; 145 } 146 147 // Create a subpass for each attachment (each attachment is a layer of an arrayed image). 148 for (deUint32 i = 0; i < numLayers; ++i) 149 { 150 const VkAttachmentReference attachmentRef = 151 { 152 i, // deUint32 attachment; 153 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 154 }; 155 colorAttachmentReferences[i] = attachmentRef; 156 157 const VkSubpassDescription subpassDescription = 158 { 159 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 160 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 161 0u, // deUint32 inputAttachmentCount; 162 DE_NULL, // const VkAttachmentReference* pInputAttachments; 163 1u, // deUint32 colorAttachmentCount; 164 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments; 165 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 166 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 167 0u, // deUint32 preserveAttachmentCount; 168 DE_NULL // const deUint32* pPreserveAttachments; 169 }; 170 subpasses.push_back(subpassDescription); 171 } 172 173 const VkRenderPassCreateInfo renderPassInfo = 174 { 175 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 176 DE_NULL, // const void* pNext; 177 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 178 numLayers, // deUint32 attachmentCount; 179 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; 180 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 181 &subpasses[0], // const VkSubpassDescription* pSubpasses; 182 0u, // deUint32 dependencyCount; 183 DE_NULL // const VkSubpassDependency* pDependencies; 184 }; 185 186 return createRenderPass(vk, device, &renderPassInfo); 187 } 188 189 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 190 const VkDevice device, 191 const VkPipelineLayout pipelineLayout, 192 const VkRenderPass renderPass, 193 const VkShaderModule vertexModule, 194 const VkShaderModule fragmentModule, 195 const IVec3 renderSize, 196 const VkPrimitiveTopology topology, 197 const deUint32 subpass, 198 const deUint32 numAttachments, 199 const bool multisample) 200 { 201 const std::vector<VkViewport> viewports (1, makeViewport(renderSize)); 202 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize)); 203 204 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 205 206 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 207 { 208 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 209 DE_NULL, // const void* pNext; 210 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 211 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits rasterizationSamples; 212 VK_FALSE, // VkBool32 sampleShadingEnable; 213 1.0f, // float minSampleShading; 214 DE_NULL, // const VkSampleMask* pSampleMask; 215 VK_FALSE, // VkBool32 alphaToCoverageEnable; 216 VK_FALSE // VkBool32 alphaToOneEnable; 217 }; 218 219 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 220 { 221 VK_FALSE, // VkBool32 blendEnable; 222 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 223 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 224 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 225 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 226 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 227 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 228 colorComponentsAll // VkColorComponentFlags colorWriteMask; 229 }; 230 231 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates; 232 for (deUint32 attachmentIdx = 0; attachmentIdx < numAttachments; attachmentIdx++) 233 colorBlendAttachmentStates.push_back(pipelineColorBlendAttachmentState); 234 235 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 236 { 237 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 238 DE_NULL, // const void* pNext; 239 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 240 VK_FALSE, // VkBool32 logicOpEnable; 241 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 242 numAttachments, // deUint32 attachmentCount; 243 numAttachments == 0 ? DE_NULL : &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments; 244 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]; 245 }; 246 247 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk 248 device, // const VkDevice device 249 pipelineLayout, // const VkPipelineLayout pipelineLayout 250 vertexModule, // const VkShaderModule vertexShaderModule 251 DE_NULL, // const VkShaderModule tessellationControlModule 252 DE_NULL, // const VkShaderModule tessellationEvalModule 253 DE_NULL, // const VkShaderModule geometryShaderModule 254 fragmentModule, // const VkShaderModule fragmentShaderModule 255 renderPass, // const VkRenderPass renderPass 256 viewports, // const std::vector<VkViewport>& viewports 257 scissors, // const std::vector<VkRect2D>& scissors 258 topology, // const VkPrimitiveTopology topology 259 subpass, // const deUint32 subpass 260 0u, // const deUint32 patchControlPoints 261 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo 262 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo 263 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo 264 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo 265 &pipelineColorBlendStateInfo); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo 266 } 267 268 Move<VkImage> makeImage (const DeviceInterface& vk, 269 const VkDevice device, 270 const VkImageCreateFlags flags, 271 const VkImageType imageType, 272 const VkFormat format, 273 const IVec3& size, 274 const deUint32 numLayers, 275 const VkImageUsageFlags usage, 276 const bool multisample) 277 { 278 const VkImageCreateInfo imageParams = 279 { 280 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 281 DE_NULL, // const void* pNext; 282 flags, // VkImageCreateFlags flags; 283 imageType, // VkImageType imageType; 284 format, // VkFormat format; 285 makeExtent3D(size), // VkExtent3D extent; 286 1u, // deUint32 mipLevels; 287 numLayers, // deUint32 arrayLayers; 288 multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 289 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 290 usage, // VkImageUsageFlags usage; 291 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 292 0u, // deUint32 queueFamilyIndexCount; 293 DE_NULL, // const deUint32* pQueueFamilyIndices; 294 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 295 }; 296 297 return createImage(vk, device, &imageParams); 298 } 299 300 vector<tcu::Vec4> genFullQuadVertices (const int subpassCount) 301 { 302 vector<tcu::Vec4> vectorData; 303 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx) 304 { 305 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); 306 vectorData.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f)); 307 vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f)); 308 vectorData.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f)); 309 } 310 return vectorData; 311 } 312 313 void initColorPrograms (SourceCollections& programCollection, const CaseDef caseDef) 314 { 315 (void)caseDef; 316 317 // Vertex shader 318 { 319 std::ostringstream src; 320 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 321 << "\n" 322 << "layout(location = 0) in vec4 in_position;\n" 323 << "\n" 324 << "out gl_PerVertex {\n" 325 << " vec4 gl_Position;\n" 326 << "};\n" 327 << "\n" 328 << "void main(void)\n" 329 << "{\n" 330 << " gl_Position = in_position;\n" 331 << "}\n"; 332 333 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 334 } 335 336 // Fragment shader 337 { 338 std::ostringstream src; 339 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 340 << "\n" 341 << "layout(location = 0) out vec4 o_color;\n" 342 << "\n" 343 << "void main(void)\n" 344 << "{\n" 345 << " o_color = vec4(1.0, 0.5, 0.25, 1.0);\n" 346 << "}\n"; 347 348 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 349 } 350 } 351 352 tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef) 353 { 354 const tcu::PixelBufferAccess expectedImage (textureLevel); 355 const int renderDepth = deMax32(caseDef.renderSize.z(), caseDef.numLayers); 356 357 for (int z = 0; z < expectedImage.getDepth(); ++z) 358 { 359 for (int y = 0; y < expectedImage.getHeight(); ++y) 360 { 361 for (int x = 0; x < expectedImage.getWidth(); ++x) 362 { 363 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth) 364 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z); 365 else 366 expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z); 367 } 368 } 369 } 370 return expectedImage; 371 } 372 373 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage) 374 { 375 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage); 376 return createBuffer(vk, device, &bufferCreateInfo); 377 } 378 379 inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount) 380 { 381 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount); 382 } 383 384 // Tests rendering to a a framebuffer with color attachments larger than the 385 // framebuffer dimensions and verifies that rendering does not affect the areas 386 // of the attachment outside the framebuffer dimensions. Tests both single-sample 387 // and multi-sample configurations. 388 tcu::TestStatus test (Context& context, const CaseDef caseDef) 389 { 390 const DeviceInterface& vk = context.getDeviceInterface(); 391 const VkDevice device = context.getDevice(); 392 const VkQueue queue = context.getUniversalQueue(); 393 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 394 Allocator& allocator = context.getDefaultAllocator(); 395 396 // Color image for rendering in single-sample tests or resolve target for multi-sample tests 397 Move<VkImage> colorImage; 398 MovePtr<Allocation> colorImageAlloc; 399 400 // For multisampled tests, this is the rendering target 401 Move<VkImage> msColorImage; 402 MovePtr<Allocation> msColorImageAlloc; 403 404 // Host memory buffer where we will copy the rendered image for verification 405 const deUint32 att_size_x = caseDef.attachmentSize.x(); 406 const deUint32 att_size_y = caseDef.attachmentSize.y(); 407 const deUint32 att_size_z = caseDef.attachmentSize.z(); 408 const VkDeviceSize colorBufferSize = att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT)); 409 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 410 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); 411 412 Move<VkBuffer> vertexBuffer; 413 MovePtr<Allocation> vertexBufferAlloc; 414 415 vector<SharedPtrVkImageView> colorAttachments; 416 vector<VkImageView> attachmentHandles; 417 418 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device)); 419 vector<SharedPtrVkPipeline> pipeline; 420 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample)); 421 Move<VkFramebuffer> framebuffer; 422 423 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u)); 424 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u)); 425 426 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 427 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 428 429 const VkImageViewType imageViewType = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY 430 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType; 431 432 // create vertexBuffer 433 { 434 const vector<tcu::Vec4> vertices = genFullQuadVertices(caseDef.numLayers); 435 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 436 437 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 438 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible); 439 440 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 441 flushAlloc(vk, device, *vertexBufferAlloc); 442 } 443 444 // create colorImage (and msColorImage) using the configured attachmentsize 445 { 446 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 447 448 colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, 449 caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false); 450 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any); 451 452 if (caseDef.multisample) 453 { 454 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 455 456 msColorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, 457 caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true); 458 msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any); 459 } 460 } 461 462 // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor 463 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx) 464 { 465 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage, 466 imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1)))); 467 attachmentHandles.push_back(**colorAttachments.back()); 468 469 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, 470 caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u, caseDef.multisample))); 471 } 472 473 // create framebuffer 474 framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0], 475 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y())); 476 477 // record command buffer 478 beginCommandBuffer(vk, *cmdBuffer); 479 { 480 // Clear the entire image attachment to black 481 { 482 const VkImageMemoryBarrier imageLayoutBarriers[] = 483 { 484 { 485 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 486 DE_NULL, // const void* pNext; 487 0u, // VkAccessFlags srcAccessMask; 488 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; 489 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 490 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; 491 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 492 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 493 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image; 494 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 495 }, 496 }; 497 498 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 499 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers); 500 501 const VkImageSubresourceRange ranges = makeColorSubresourceRange(0, caseDef.numLayers); 502 const VkClearColorValue clearColor = 503 { 504 {0.0f, 0.0f, 0.0f, 1.0f} 505 }; 506 vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges); 507 508 const VkImageMemoryBarrier imageClearBarriers[] = 509 { 510 { 511 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 512 DE_NULL, // const void* pNext; 513 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 514 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; 515 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; 516 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 517 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 518 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 519 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image; 520 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 521 }, 522 }; 523 524 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 525 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers); 526 } 527 528 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment) 529 { 530 const VkDeviceSize vertexBufferOffset = 0ull; 531 532 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y())); 533 { 534 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 535 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx) 536 { 537 if (layerNdx != 0) 538 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 539 540 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]); 541 vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u); 542 } 543 } 544 endRenderPass(vk, *cmdBuffer); 545 } 546 547 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage) 548 if (caseDef.multisample) 549 { 550 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving 551 const VkImageMemoryBarrier imageBarriers[] = 552 { 553 { 554 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 555 DE_NULL, // const void* pNext; 556 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 557 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 558 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 559 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 560 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 561 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 562 *msColorImage, // VkImage image; 563 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 564 }, 565 { 566 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 567 DE_NULL, // const void* pNext; 568 (VkAccessFlags)0, // VkAccessFlags srcAccessMask; 569 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; 570 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 571 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 572 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 573 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 574 *colorImage, // VkImage image; 575 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 576 } 577 }; 578 579 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 580 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers); 581 582 const VkImageResolve region = 583 { 584 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource; 585 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset; 586 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource; 587 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset; 588 makeExtent3D(caseDef.attachmentSize) // VkExtent3D extent; 589 }; 590 591 vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); 592 } 593 594 // copy colorImage to host visible colorBuffer 595 { 596 const VkImageMemoryBarrier imageBarriers[] = 597 { 598 { 599 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 600 DE_NULL, // const void* pNext; 601 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), 602 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 603 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 604 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 605 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 606 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 607 *colorImage, // VkImage image; 608 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 609 } 610 }; 611 612 vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 613 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers); 614 615 const VkBufferImageCopy region = 616 { 617 0ull, // VkDeviceSize bufferOffset; 618 0u, // uint32_t bufferRowLength; 619 0u, // uint32_t bufferImageHeight; 620 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource; 621 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 622 makeExtent3D(caseDef.attachmentSize), // VkExtent3D imageExtent; 623 }; 624 625 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion); 626 627 const VkBufferMemoryBarrier bufferBarriers[] = 628 { 629 { 630 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 631 DE_NULL, // const void* pNext; 632 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 633 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 634 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 635 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 636 *colorBuffer, // VkBuffer buffer; 637 0ull, // VkDeviceSize offset; 638 VK_WHOLE_SIZE, // VkDeviceSize size; 639 }, 640 }; 641 642 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 643 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL); 644 } 645 } // beginCommandBuffer 646 647 endCommandBuffer(vk, *cmdBuffer); 648 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 649 650 // Verify results 651 { 652 invalidateAlloc(vk, device, *colorBufferAlloc); 653 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT); 654 const int depth = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers); 655 tcu::TextureLevel textureLevel (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth); 656 const tcu::PixelBufferAccess expectedImage = getExpectedData(textureLevel, caseDef); 657 const tcu::ConstPixelBufferAccess resultImage (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr()); 658 659 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT)) 660 return tcu::TestStatus::fail("Fail"); 661 } 662 663 return tcu::TestStatus::pass("Pass"); 664 } 665 666 void initImagePrograms (SourceCollections& programCollection, const bool multisample) 667 { 668 // Vertex shader 669 { 670 std::ostringstream src; 671 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 672 << "\n" 673 << "layout(location = 0) in vec4 in_position;\n" 674 << "\n" 675 << "out gl_PerVertex {\n" 676 << " vec4 gl_Position;\n" 677 << " float gl_PointSize;\n" 678 << "};\n" 679 << "\n" 680 << "void main(void)\n" 681 << "{\n" 682 << " gl_Position = in_position;\n" 683 << " gl_PointSize = 1.0f;\n" 684 << "}\n"; 685 686 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 687 } 688 689 // Fragment shader 690 { 691 std::ostringstream src; 692 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 693 << "\n" 694 << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n" 695 << "\n" 696 << "void main(void)\n" 697 << "{\n"; 698 if (!multisample) 699 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n"; 700 else 701 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n"; 702 src << "}\n"; 703 704 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 705 } 706 } 707 708 //! Make a render pass with no attachments 709 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device) 710 { 711 // Create a single subpass with no attachment references 712 vector<VkSubpassDescription> subpasses; 713 714 const VkSubpassDescription subpassDescription = 715 { 716 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 717 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 718 0u, // deUint32 inputAttachmentCount; 719 DE_NULL, // const VkAttachmentReference* pInputAttachments; 720 0u, // deUint32 colorAttachmentCount; 721 DE_NULL, // const VkAttachmentReference* pColorAttachments; 722 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 723 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 724 0u, // deUint32 preserveAttachmentCount; 725 DE_NULL // const deUint32* pPreserveAttachments; 726 }; 727 subpasses.push_back(subpassDescription); 728 729 const VkRenderPassCreateInfo renderPassInfo = 730 { 731 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 732 DE_NULL, // const void* pNext; 733 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 734 0, // deUint32 attachmentCount; 735 DE_NULL, // const VkAttachmentDescription* pAttachments; 736 1, // deUint32 subpassCount; 737 &subpasses[0], // const VkSubpassDescription* pSubpasses; 738 0u, // deUint32 dependencyCount; 739 DE_NULL // const VkSubpassDependency* pDependencies; 740 }; 741 742 return createRenderPass(vk, device, &renderPassInfo); 743 } 744 745 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel) 746 { 747 const tcu::PixelBufferAccess expectedImage (textureLevel); 748 for (int z = 0; z < expectedImage.getDepth(); ++z) 749 { 750 for (int y = 0; y < expectedImage.getHeight(); ++y) 751 { 752 for (int x = 0; x < expectedImage.getWidth(); ++x) 753 { 754 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z); 755 } 756 } 757 } 758 return expectedImage; 759 } 760 761 vector<tcu::Vec4> genPointVertices (void) 762 { 763 vector<tcu::Vec4> vectorData; 764 vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1)); 765 vectorData.push_back(Vec4(-0.25f, 0.25f, 0, 1)); 766 vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1)); 767 vectorData.push_back(Vec4(0.25f, 0.25f, 0, 1)); 768 return vectorData; 769 } 770 771 // Tests rendering to a framebuffer without color attachments, checking that 772 // the fragment shader is run even in the absence of color output. In this case 773 // we render 4 point primitives and we make the fragment shader write to a 774 // different pixel of an image via an imageStore command. For the single-sampled 775 // configuration we use a 4x1 image to record the output and for the 776 // multi-sampled case we use a 4x4 image to record all 16 samples produced by 777 // 4-sample multi-sampling 778 tcu::TestStatus testNoAtt (Context& context, const bool multisample) 779 { 780 const VkPhysicalDeviceFeatures features = context.getDeviceFeatures(); 781 if (!features.fragmentStoresAndAtomics) 782 throw tcu::NotSupportedError("fragmentStoresAndAtomics feature not supported"); 783 if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID 784 throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported"); 785 if (multisample && !features.sampleRateShading) // MS shader uses gl_SampleID 786 throw tcu::NotSupportedError("sampleRateShading feature not supported"); 787 788 const DeviceInterface& vk = context.getDeviceInterface(); 789 const VkDevice device = context.getDevice(); 790 const VkQueue queue = context.getUniversalQueue(); 791 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 792 Allocator& allocator = context.getDefaultAllocator(); 793 const IVec3 renderSize (32, 32, 1); 794 795 Move<VkBuffer> vertexBuffer; 796 MovePtr<Allocation> vertexBufferAlloc; 797 798 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); 799 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); 800 801 // Create image where we will record the writes. For single-sampled cases this is a 4x1 image 802 // and for multi-sampled cases this is a 4x<num_samples> image. 803 const deUint8 numSamples = multisample ? 4 : 1; 804 const deUint8 imageWidth = 4; 805 const deUint8 imageHeight = numSamples; 806 const deUint8 imageDepth = 1; 807 const deUint8 imageLayers = 1; 808 const IVec3 imageDim = IVec3(imageWidth, imageHeight, imageDepth); 809 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT; 810 const Move<VkImage> image = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false); 811 const VkImageSubresourceRange imageSubresourceRange = makeColorSubresourceRange(0u, imageLayers); 812 const MovePtr<Allocation> imageAlloc = bindImage(vk, device, allocator, *image, MemoryRequirement::Any); 813 const Move<VkImageView> imageView = makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange); 814 815 // Create a buffer where we will copy the image for verification 816 const VkDeviceSize colorBufferSize = imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT)); 817 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 818 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); 819 820 // Create pipeline descriptor set for the image 821 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder() 822 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) 823 .build(vk, device); 824 825 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder() 826 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1) 827 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 828 829 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout); 830 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL); 831 DescriptorSetUpdateBuilder() 832 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo) 833 .update(vk, device); 834 835 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout)); 836 vector<SharedPtrVkPipeline> pipeline; 837 const Unique<VkRenderPass> renderPass (makeRenderPassNoAtt (vk, device)); 838 Move<VkFramebuffer> framebuffer; 839 840 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 841 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); 842 843 // create vertexBuffer 844 { 845 const vector<tcu::Vec4> vertices = genPointVertices(); 846 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 847 848 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 849 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible); 850 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 851 flushAlloc(vk, device, *vertexBufferAlloc); 852 } 853 854 // Create render pass and pipeline 855 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, 856 renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, multisample))); 857 framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y()); 858 859 // Record command buffer 860 beginCommandBuffer(vk, *cmdBuffer); 861 { 862 // shader image layout transition undefined -> general 863 { 864 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier( 865 0u, VK_ACCESS_SHADER_WRITE_BIT, 866 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 867 *image, imageSubresourceRange); 868 869 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 870 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier); 871 } 872 873 // Render pass 874 { 875 const VkDeviceSize vertexBufferOffset = 0ull; 876 877 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y())); 878 879 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]); 880 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 881 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 882 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u); 883 884 endRenderPass(vk, *cmdBuffer); 885 } 886 887 // copy image to host visible colorBuffer 888 { 889 const VkImageMemoryBarrier imageBarriers[] = 890 { 891 { 892 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 893 DE_NULL, // const void* pNext; 894 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask; 895 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 896 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout; 897 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 898 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 899 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 900 *image, // VkImage image; 901 makeColorSubresourceRange(0, 1) // VkImageSubresourceRange subresourceRange; 902 } 903 }; 904 905 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 906 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers); 907 908 const VkBufferImageCopy region = 909 { 910 0ull, // VkDeviceSize bufferOffset; 911 0u, // uint32_t bufferRowLength; 912 0u, // uint32_t bufferImageHeight; 913 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1), // VkImageSubresourceLayers imageSubresource; 914 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 915 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)), // VkExtent3D imageExtent; 916 }; 917 918 vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion); 919 920 const VkBufferMemoryBarrier bufferBarriers[] = 921 { 922 { 923 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 924 DE_NULL, // const void* pNext; 925 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 926 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 927 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 928 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 929 *colorBuffer, // VkBuffer buffer; 930 0ull, // VkDeviceSize offset; 931 VK_WHOLE_SIZE, // VkDeviceSize size; 932 }, 933 }; 934 935 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 936 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL); 937 } 938 } // beginCommandBuffer 939 940 endCommandBuffer(vk, *cmdBuffer); 941 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 942 943 // Verify results 944 { 945 invalidateAlloc(vk, device, *colorBufferAlloc); 946 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT); 947 tcu::TextureLevel textureLevel (format, imageWidth, imageHeight, imageDepth); 948 const tcu::PixelBufferAccess expectedImage = getExpectedDataNoAtt(textureLevel); 949 const tcu::ConstPixelBufferAccess resultImage (format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr()); 950 951 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT)) 952 return tcu::TestStatus::fail("Fail"); 953 } 954 955 return tcu::TestStatus::pass("Pass"); 956 } 957 958 //! Make a render pass with three color attachments 959 Move<VkRenderPass> makeRenderPassDifferentAttachmentSizes (const DeviceInterface& vk, 960 const VkDevice device, 961 const VkFormat colorFormat, 962 deUint32 numAttachments, 963 const bool multisample) 964 { 965 vector<VkAttachmentDescription> attachmentDescriptions (numAttachments); 966 vector<VkAttachmentReference> colorAttachmentReferences (numAttachments); 967 968 for (deUint32 i = 0; i < numAttachments; i++) 969 { 970 VkAttachmentDescription colorAttachmentDescription = 971 { 972 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags; 973 colorFormat, // VkFormat format; 974 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples; 975 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; 976 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 977 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 978 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 979 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout; 980 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 981 }; 982 attachmentDescriptions[i] = colorAttachmentDescription; 983 984 const VkAttachmentReference attachmentRef = 985 { 986 i, // deUint32 attachment; 987 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 988 }; 989 colorAttachmentReferences[i] = attachmentRef; 990 } 991 992 const VkSubpassDescription subpassDescription = 993 { 994 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 995 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 996 0u, // deUint32 inputAttachmentCount; 997 DE_NULL, // const VkAttachmentReference* pInputAttachments; 998 numAttachments, // deUint32 colorAttachmentCount; 999 &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments; 1000 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 1001 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 1002 0u, // deUint32 preserveAttachmentCount; 1003 DE_NULL // const deUint32* pPreserveAttachments; 1004 }; 1005 1006 const VkRenderPassCreateInfo renderPassInfo = 1007 { 1008 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 1009 DE_NULL, // const void* pNext; 1010 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 1011 numAttachments, // deUint32 attachmentCount; 1012 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; 1013 1u, // deUint32 subpassCount; 1014 &subpassDescription, // const VkSubpassDescription* pSubpasses; 1015 0u, // deUint32 dependencyCount; 1016 DE_NULL // const VkSubpassDependency* pDependencies; 1017 }; 1018 1019 return createRenderPass(vk, device, &renderPassInfo); 1020 } 1021 1022 // Tests framebuffer with attachments of different sizes 1023 tcu::TestStatus testDifferentAttachmentSizes (Context& context, const CaseDef caseDef) 1024 { 1025 const DeviceInterface& vk = context.getDeviceInterface(); 1026 const VkDevice device = context.getDevice(); 1027 const VkQueue queue = context.getUniversalQueue(); 1028 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 1029 Allocator& allocator = context.getDefaultAllocator(); 1030 const deUint32 numRenderTargets = 3; 1031 1032 // Color images for rendering in single-sample tests or resolve targets for multi-sample tests 1033 Move<VkImage> colorImages[numRenderTargets]; 1034 MovePtr<Allocation> colorImageAllocs[numRenderTargets]; 1035 1036 // For multisampled tests, these are the rendering targets 1037 Move<VkImage> msColorImages[numRenderTargets]; 1038 MovePtr<Allocation> msColorImageAllocs[numRenderTargets]; 1039 1040 Move<VkBuffer> colorBuffers[numRenderTargets]; 1041 MovePtr<Allocation> colorBufferAllocs[numRenderTargets]; 1042 1043 // Vary attachment sizes by adding an offset to the base size. 1044 const IVec3 attachmentSizes[] = 1045 { 1046 caseDef.attachmentSize, 1047 caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0), 1048 caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0) 1049 }; 1050 1051 // Use unique clear color for each render target to verify no leaking happens between render target clears. 1052 const VkClearColorValue clearColors[] = 1053 { 1054 {{1.0f, 0.0f, 0.0f, 1.0f}}, 1055 {{0.0f, 1.0f, 0.0f, 1.0f}}, 1056 {{0.0f, 0.0f, 1.0f, 1.0f}} 1057 }; 1058 1059 Move<VkBuffer> vertexBuffer; 1060 MovePtr<Allocation> vertexBufferAlloc; 1061 1062 vector<SharedPtrVkImageView> colorAttachments; 1063 vector<VkImageView> attachmentHandles; 1064 1065 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device)); 1066 Move<VkPipeline> pipeline; 1067 const Unique<VkRenderPass> renderPass (makeRenderPassDifferentAttachmentSizes(vk, device, COLOR_FORMAT, numRenderTargets, caseDef.multisample)); 1068 Move<VkFramebuffer> framebuffer; 1069 1070 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u)); 1071 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u)); 1072 1073 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 1074 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1075 1076 const VkImageViewType imageViewType = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY 1077 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType; 1078 1079 const VkImageSubresourceRange range = makeColorSubresourceRange(0, 1); 1080 1081 // create color buffers 1082 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++) 1083 { 1084 // Host memory buffer where we will copy the rendered image for verification 1085 const deUint32 att_size_x = attachmentSizes[renderTargetIdx].x(); 1086 const deUint32 att_size_y = attachmentSizes[renderTargetIdx].y(); 1087 const deUint32 att_size_z = attachmentSizes[renderTargetIdx].z(); 1088 const VkDeviceSize colorBufferSize = att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT)); 1089 colorBuffers[renderTargetIdx] = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 1090 colorBufferAllocs[renderTargetIdx] = bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible); 1091 } 1092 1093 // create vertexBuffer 1094 { 1095 const vector<tcu::Vec4> vertices = genFullQuadVertices(1); 1096 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 1097 1098 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 1099 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible); 1100 1101 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 1102 flushAlloc(vk, device, *vertexBufferAlloc); 1103 } 1104 1105 // create colorImages (and msColorImages) using the configured attachmentsize 1106 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++) 1107 { 1108 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 1109 colorImages[renderTargetIdx] = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, 1110 attachmentSizes[renderTargetIdx], 1, colorImageUsage, false); 1111 colorImageAllocs[renderTargetIdx] = bindImage(vk, device, allocator, *colorImages[renderTargetIdx], MemoryRequirement::Any); 1112 1113 if (caseDef.multisample) 1114 { 1115 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 1116 1117 msColorImages[renderTargetIdx] = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, attachmentSizes[renderTargetIdx], 1, msImageUsage, true); 1118 msColorImageAllocs[renderTargetIdx] = bindImage(vk, device, allocator, *msColorImages[renderTargetIdx], MemoryRequirement::Any); 1119 } 1120 } 1121 1122 // create attachmentHandles. We use the renderSize for viewport and scissor 1123 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++) 1124 { 1125 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx], imageViewType, COLOR_FORMAT, range))); 1126 attachmentHandles.push_back(**colorAttachments.back()); 1127 } 1128 1129 pipeline = makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, numRenderTargets, caseDef.multisample); 1130 1131 // create framebuffer 1132 framebuffer = makeFramebuffer(vk, device, *renderPass, numRenderTargets, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y())); 1133 1134 // record command buffer 1135 beginCommandBuffer(vk, *cmdBuffer); 1136 1137 // Clear image attachments 1138 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++) 1139 { 1140 { 1141 const VkImageMemoryBarrier imageLayoutBarriers[] = 1142 { 1143 { 1144 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1145 DE_NULL, // const void* pNext; 1146 0u, // VkAccessFlags srcAccessMask; 1147 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; 1148 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1149 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; 1150 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1151 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1152 caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], // VkImage image; 1153 range // VkImageSubresourceRange subresourceRange; 1154 }, 1155 }; 1156 1157 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1158 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers); 1159 1160 vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColors[renderTargetIdx], 1u, &range); 1161 1162 const VkImageMemoryBarrier imageClearBarriers[] = 1163 { 1164 { 1165 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1166 DE_NULL, // const void* pNext; 1167 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1168 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; 1169 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; 1170 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 1171 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1172 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1173 caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], // VkImage image; 1174 range // VkImageSubresourceRange subresourceRange; 1175 }, 1176 }; 1177 1178 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers); 1179 } 1180 } 1181 1182 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment) 1183 { 1184 const VkDeviceSize vertexBufferOffset = 0ull; 1185 1186 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y())); 1187 { 1188 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 1189 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 1190 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u); 1191 } 1192 endRenderPass(vk, *cmdBuffer); 1193 } 1194 1195 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage) 1196 if (caseDef.multisample) 1197 { 1198 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++) 1199 { 1200 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving 1201 const VkImageMemoryBarrier imageBarriers[] = 1202 { 1203 { 1204 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1205 DE_NULL, // const void* pNext; 1206 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 1207 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 1208 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 1209 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 1210 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1211 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1212 *msColorImages[renderTargetIdx], // VkImage image; 1213 range // VkImageSubresourceRange subresourceRange; 1214 }, 1215 { 1216 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1217 DE_NULL, // const void* pNext; 1218 (VkAccessFlags)0, // VkAccessFlags srcAccessMask; 1219 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; 1220 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1221 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 1222 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1223 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1224 *colorImages[renderTargetIdx], // VkImage image; 1225 range // VkImageSubresourceRange subresourceRange; 1226 } 1227 }; 1228 1229 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1230 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers); 1231 1232 const VkImageResolve region = 1233 { 1234 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1), // VkImageSubresourceLayers srcSubresource; 1235 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset; 1236 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1), // VkImageSubresourceLayers dstSubresource; 1237 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset; 1238 makeExtent3D(attachmentSizes[renderTargetIdx]) // VkExtent3D extent; 1239 }; 1240 1241 vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); 1242 } 1243 } 1244 1245 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++) 1246 { 1247 // copy colorImage to host visible colorBuffer 1248 const VkImageMemoryBarrier imageBarrier = 1249 { 1250 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1251 DE_NULL, // const void* pNext; 1252 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), 1253 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 1254 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 1255 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 1256 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1257 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1258 *colorImages[renderTargetIdx], // VkImage image; 1259 range // VkImageSubresourceRange subresourceRange; 1260 }; 1261 1262 vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1263 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier); 1264 1265 const VkBufferImageCopy region = 1266 { 1267 0ull, // VkDeviceSize bufferOffset; 1268 0u, // uint32_t bufferRowLength; 1269 0u, // uint32_t bufferImageHeight; 1270 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; 1271 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 1272 makeExtent3D(attachmentSizes[renderTargetIdx]), // VkExtent3D imageExtent; 1273 }; 1274 1275 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffers[renderTargetIdx], 1u, ®ion); 1276 1277 const VkBufferMemoryBarrier bufferBarrier = 1278 { 1279 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 1280 DE_NULL, // const void* pNext; 1281 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1282 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 1283 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1284 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1285 *colorBuffers[renderTargetIdx], // VkBuffer buffer; 1286 0ull, // VkDeviceSize offset; 1287 VK_WHOLE_SIZE, // VkDeviceSize size; 1288 }; 1289 1290 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1291 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL); 1292 } 1293 1294 endCommandBuffer(vk, *cmdBuffer); 1295 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1296 1297 // Verify results 1298 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++) 1299 { 1300 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT); 1301 const IVec3 size = attachmentSizes[renderTargetIdx]; 1302 tcu::TextureLevel textureLevel (format, size.x(), size.y(), size.z()); 1303 const tcu::PixelBufferAccess expectedImage (textureLevel); 1304 1305 const tcu::Vec4 expectedColors[] = 1306 { 1307 tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f), 1308 tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f), 1309 tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f) 1310 }; 1311 1312 invalidateAlloc(vk, device, *colorBufferAllocs[renderTargetIdx]); 1313 1314 for (int z = 0; z < expectedImage.getDepth(); ++z) 1315 { 1316 for (int y = 0; y < expectedImage.getHeight(); ++y) 1317 { 1318 for (int x = 0; x < expectedImage.getWidth(); ++x) 1319 { 1320 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z()) 1321 expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z); 1322 else 1323 expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z); 1324 } 1325 } 1326 } 1327 const tcu::ConstPixelBufferAccess resultImage (format, size.x(), size.y(), size.z(), colorBufferAllocs[renderTargetIdx]->getHostPtr()); 1328 1329 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), (std::string("Image Comparison of render target ") + de::toString(renderTargetIdx)).c_str(), "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT)) 1330 return tcu::TestStatus::fail("Fail"); 1331 } 1332 1333 return tcu::TestStatus::pass("Pass"); 1334 } 1335 1336 tcu::TestStatus testUnusedAtt (Context& context) 1337 { 1338 const DeviceInterface& vk = context.getDeviceInterface(); 1339 const VkDevice device = context.getDevice(); 1340 const Move<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex())); 1341 const Move<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1342 1343 const VkAttachmentReference attRef = 1344 { 1345 VK_ATTACHMENT_UNUSED, 1346 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 1347 }; 1348 1349 const VkSubpassDescription subpass = 1350 { 1351 0, 1352 VK_PIPELINE_BIND_POINT_GRAPHICS, 1353 0, 1354 DE_NULL, 1355 1, 1356 &attRef, 1357 DE_NULL, 1358 DE_NULL, 1359 0, 1360 DE_NULL 1361 }; 1362 1363 const VkRenderPassCreateInfo renderPassCreateInfo = 1364 { 1365 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 1366 DE_NULL, 1367 0, 1368 0, 1369 DE_NULL, 1370 1, 1371 &subpass, 1372 0, 1373 DE_NULL 1374 }; 1375 1376 const Move<VkRenderPass> renderPass = createRenderPass(vk, device, &renderPassCreateInfo, DE_NULL); 1377 1378 const VkFramebufferCreateInfo framebufferCreateInfo = 1379 { 1380 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 1381 DE_NULL, 1382 0, 1383 *renderPass, 1384 0, 1385 DE_NULL, 1386 32, 1387 32, 1388 1 1389 }; 1390 1391 const Move<VkFramebuffer> framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo, DE_NULL); 1392 1393 beginCommandBuffer(vk, *cmdBuffer); 1394 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, 32u, 32u)); 1395 endRenderPass(vk, *cmdBuffer); 1396 endCommandBuffer(vk, *cmdBuffer); 1397 1398 return tcu::TestStatus::pass("Pass"); 1399 } 1400 1401 void initDifferentAttachmentSizesPrograms (SourceCollections& programCollection, const CaseDef caseDef) 1402 { 1403 DE_UNREF(caseDef); 1404 1405 // Vertex shader 1406 { 1407 std::ostringstream src; 1408 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1409 << "\n" 1410 << "layout(location = 0) in vec4 in_position;\n" 1411 << "\n" 1412 << "out gl_PerVertex {\n" 1413 << " vec4 gl_Position;\n" 1414 << "};\n" 1415 << "\n" 1416 << "void main(void)\n" 1417 << "{\n" 1418 << " gl_Position = in_position;\n" 1419 << "}\n"; 1420 1421 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 1422 } 1423 1424 // Fragment shader 1425 { 1426 std::ostringstream src; 1427 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1428 << "\n" 1429 << "layout(location = 0) out vec4 o_color0;\n" 1430 << "layout(location = 1) out vec4 o_color1;\n" 1431 << "layout(location = 2) out vec4 o_color2;\n" 1432 << "\n" 1433 << "void main(void)\n" 1434 << "{\n" 1435 << " o_color0 = vec4(1.0, 0.5, 0.25, 1.0);\n" 1436 << " o_color1 = vec4(0.5, 1.0, 0.25, 1.0);\n" 1437 << " o_color2 = vec4(0.25, 0.5, 1.0, 1.0);\n" 1438 << "}\n"; 1439 1440 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 1441 } 1442 } 1443 1444 std::string getShortImageViewTypeName (const VkImageViewType imageViewType) 1445 { 1446 std::string s (getImageViewTypeName(imageViewType)); 1447 return de::toLower(s.substr(19)); 1448 } 1449 1450 std::string getSizeString (const CaseDef& caseDef) 1451 { 1452 std::ostringstream str; 1453 1454 str << caseDef.renderSize.x(); 1455 if (caseDef.renderSize.y() > 1) str << "x" << caseDef.renderSize.y(); 1456 if (caseDef.renderSize.z() > 1) str << "x" << caseDef.renderSize.z(); 1457 1458 str << "_" << caseDef.attachmentSize.x(); 1459 1460 if (caseDef.attachmentSize.y() > 1) str << "x" << caseDef.attachmentSize.y(); 1461 if (caseDef.attachmentSize.z() > 1) str << "x" << caseDef.attachmentSize.z(); 1462 if (caseDef.numLayers > 1) str << "_" << caseDef.numLayers; 1463 1464 return str.str(); 1465 } 1466 1467 std::string getTestCaseString (const CaseDef& caseDef) 1468 { 1469 std::ostringstream str; 1470 1471 str << getShortImageViewTypeName (caseDef.imageType).c_str(); 1472 str << "_"; 1473 str << getSizeString(caseDef); 1474 1475 if (caseDef.multisample) 1476 str << "_ms"; 1477 1478 return str.str(); 1479 } 1480 1481 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group) 1482 { 1483 1484 // Add test cases for attachment strictly sizes larger than the framebuffer 1485 const CaseDef caseDef[] = 1486 { 1487 // Single-sample test cases 1488 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false }, 1489 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false }, 1490 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false }, 1491 { VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false }, 1492 1493 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(64, 1, 1), 4, false }, 1494 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(48, 1, 1), 4, false }, 1495 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(39, 1, 1), 4, false }, 1496 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(19, 1, 1), IVec3(32, 1, 1), 4, false }, 1497 1498 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false }, 1499 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false }, 1500 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false }, 1501 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false }, 1502 1503 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, false }, 1504 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, false }, 1505 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, false }, 1506 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, false }, 1507 1508 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(64, 64, 1), 6, false }, 1509 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(48, 48, 1), 6, false }, 1510 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(39, 41, 1), 6, false }, 1511 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(19, 27, 1), IVec3(32, 32, 1), 6, false }, 1512 1513 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 6*2, false }, 1514 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 6*2, false }, 1515 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 6*2, false }, 1516 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 6*2, false }, 1517 1518 // Multi-sample test cases 1519 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true }, 1520 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true }, 1521 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true }, 1522 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true }, 1523 1524 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, true }, 1525 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, true }, 1526 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, true }, 1527 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, true }, 1528 }; 1529 1530 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx) 1531 addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]); 1532 1533 // Add tests for the case where there are no color attachments but the 1534 // fragment shader writes to an image via imageStore(). 1535 addFunctionCaseWithPrograms(group, "no_attachments", "", initImagePrograms, testNoAtt, false); 1536 addFunctionCaseWithPrograms(group, "no_attachments_ms", "", initImagePrograms, testNoAtt, true); 1537 1538 // Test render pass with attachment set as unused. 1539 addFunctionCase(group, "unused_attachment", "", testUnusedAtt); 1540 1541 const CaseDef differentAttachmentSizesCaseDef[] = 1542 { 1543 // Single-sample test cases 1544 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false }, 1545 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false }, 1546 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false }, 1547 { VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false }, 1548 1549 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false }, 1550 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false }, 1551 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false }, 1552 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false }, 1553 1554 // Multi-sample test cases 1555 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true }, 1556 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true }, 1557 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true }, 1558 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true } 1559 }; 1560 1561 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx) 1562 addFunctionCaseWithPrograms(group, (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(), "", initDifferentAttachmentSizesPrograms, testDifferentAttachmentSizes, differentAttachmentSizesCaseDef[sizeNdx]); 1563 } 1564 1565 } // anonymous ns 1566 1567 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx) 1568 { 1569 return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions); 1570 } 1571 1572 } // pipeline 1573 } // vkt 1574