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 "vkQueryUtil.hpp" 35#include "vkTypeUtil.hpp" 36#include "vkRefUtil.hpp" 37#include "vkBuilderUtil.hpp" 38#include "vkPrograms.hpp" 39#include "vkImageUtil.hpp" 40 41#include "tcuTextureUtil.hpp" 42#include "tcuImageCompare.hpp" 43 44#include "deUniquePtr.hpp" 45#include "deSharedPtr.hpp" 46 47#include <string> 48#include <vector> 49 50namespace vkt 51{ 52namespace pipeline 53{ 54namespace 55{ 56using namespace vk; 57using de::UniquePtr; 58using de::MovePtr; 59using de::SharedPtr; 60using tcu::IVec3; 61using tcu::Vec4; 62using tcu::UVec4; 63using tcu::IVec4; 64using std::vector; 65 66static const VkFormat COLOR_FORMAT = VK_FORMAT_R8G8B8A8_UNORM; 67 68typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView; 69typedef SharedPtr<Unique<VkPipeline> > SharedPtrVkPipeline; 70 71struct CaseDef 72{ 73 VkImageViewType imageType; 74 IVec3 renderSize; 75 IVec3 attachmentSize; 76 deUint32 numLayers; 77 bool multisample; 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 92VkImageType getImageType(const VkImageViewType viewType) 93{ 94 switch (viewType) 95 { 96 case VK_IMAGE_VIEW_TYPE_1D: 97 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 98 return VK_IMAGE_TYPE_1D; 99 100 case VK_IMAGE_VIEW_TYPE_2D: 101 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 102 case VK_IMAGE_VIEW_TYPE_CUBE: 103 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 104 return VK_IMAGE_TYPE_2D; 105 106 case VK_IMAGE_VIEW_TYPE_3D: 107 return VK_IMAGE_TYPE_3D; 108 109 default: 110 DE_ASSERT(0); 111 return VK_IMAGE_TYPE_LAST; 112 } 113} 114 115//! Make a render pass with one subpass per color attachment and one attachment per image layer. 116Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 117 const VkDevice device, 118 const VkFormat colorFormat, 119 const deUint32 numLayers, 120 const bool multisample) 121{ 122 vector<VkAttachmentDescription> attachmentDescriptions (numLayers); 123 deUint32 attachmentIndex = 0; 124 vector<VkAttachmentReference> colorAttachmentReferences (numLayers); 125 vector<VkSubpassDescription> subpasses; 126 127 for (deUint32 i = 0; i < numLayers; i++) 128 { 129 VkAttachmentDescription colorAttachmentDescription = 130 { 131 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags; 132 colorFormat, // VkFormat format; 133 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples; 134 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; 135 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 136 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 137 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 138 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout; 139 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 140 }; 141 attachmentDescriptions[attachmentIndex++] = colorAttachmentDescription; 142 } 143 144 // Create a subpass for each attachment (each attachment is a layer of an arrayed image). 145 for (deUint32 i = 0; i < numLayers; ++i) 146 { 147 const VkAttachmentReference attachmentRef = 148 { 149 i, // deUint32 attachment; 150 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 151 }; 152 colorAttachmentReferences[i] = attachmentRef; 153 154 const VkSubpassDescription subpassDescription = 155 { 156 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 157 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 158 0u, // deUint32 inputAttachmentCount; 159 DE_NULL, // const VkAttachmentReference* pInputAttachments; 160 1u, // deUint32 colorAttachmentCount; 161 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments; 162 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 163 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 164 0u, // deUint32 preserveAttachmentCount; 165 DE_NULL // const deUint32* pPreserveAttachments; 166 }; 167 subpasses.push_back(subpassDescription); 168 } 169 170 const VkRenderPassCreateInfo renderPassInfo = 171 { 172 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 173 DE_NULL, // const void* pNext; 174 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 175 numLayers, // deUint32 attachmentCount; 176 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; 177 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 178 &subpasses[0], // const VkSubpassDescription* pSubpasses; 179 0u, // deUint32 dependencyCount; 180 DE_NULL // const VkSubpassDependency* pDependencies; 181 }; 182 183 return createRenderPass(vk, device, &renderPassInfo); 184} 185 186Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 187 const VkDevice device, 188 const VkPipelineLayout pipelineLayout, 189 const VkRenderPass renderPass, 190 const VkShaderModule vertexModule, 191 const VkShaderModule fragmentModule, 192 const IVec3 renderSize, 193 const VkPrimitiveTopology topology, 194 const deUint32 subpass, 195 const bool hasAttachments, 196 const bool multisample) 197{ 198 const VkVertexInputBindingDescription vertexInputBindingDescription = 199 { 200 0u, // uint32_t binding; 201 sizeof(tcu::Vec4), // uint32_t stride; 202 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 203 }; 204 205 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = 206 { 207 { 208 0u, // uint32_t location; 209 0u, // uint32_t binding; 210 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 211 0u, // uint32_t offset; 212 }, 213 }; 214 215 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 216 { 217 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 218 DE_NULL, // const void* pNext; 219 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 220 1u, // uint32_t vertexBindingDescriptionCount; 221 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 222 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount; 223 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 224 }; 225 226 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 227 { 228 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 229 DE_NULL, // const void* pNext; 230 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 231 topology, // VkPrimitiveTopology topology; 232 VK_FALSE, // VkBool32 primitiveRestartEnable; 233 }; 234 235 const VkViewport viewport = makeViewport( 236 0.0f, 0.0f, 237 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 238 0.0f, 1.0f); 239 240 // We must set the scissor rect to the renderSize, since the renderArea specified 241 // during the begin render pass command does not ensure that rendering is strictly 242 // limited to the rect provided there and the spec clearly states that the scissor 243 // must be configured appropriately to ensure this 244 const VkRect2D scissor = 245 { 246 makeOffset2D(0, 0), 247 makeExtent2D(renderSize.x(), renderSize.y()), 248 }; 249 250 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 251 { 252 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 253 DE_NULL, // const void* pNext; 254 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 255 1u, // uint32_t viewportCount; 256 &viewport, // const VkViewport* pViewports; 257 1u, // uint32_t scissorCount; 258 &scissor, // const VkRect2D* pScissors; 259 }; 260 261 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 262 { 263 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 264 DE_NULL, // const void* pNext; 265 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 266 VK_FALSE, // VkBool32 depthClampEnable; 267 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 268 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 269 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 270 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 271 VK_FALSE, // VkBool32 depthBiasEnable; 272 0.0f, // float depthBiasConstantFactor; 273 0.0f, // float depthBiasClamp; 274 0.0f, // float depthBiasSlopeFactor; 275 1.0f, // float lineWidth; 276 }; 277 278 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 279 { 280 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 281 DE_NULL, // const void* pNext; 282 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 283 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits rasterizationSamples; 284 !multisample ? VK_FALSE : VK_TRUE, // VkBool32 sampleShadingEnable; 285 1.0f, // float minSampleShading; 286 DE_NULL, // const VkSampleMask* pSampleMask; 287 VK_FALSE, // VkBool32 alphaToCoverageEnable; 288 VK_FALSE // VkBool32 alphaToOneEnable; 289 }; 290 291 const VkStencilOpState stencilOpState = makeStencilOpState( 292 VK_STENCIL_OP_KEEP, // stencil fail 293 VK_STENCIL_OP_KEEP, // depth & stencil pass 294 VK_STENCIL_OP_KEEP, // depth only fail 295 VK_COMPARE_OP_ALWAYS, // compare op 296 0u, // compare mask 297 0u, // write mask 298 0u); // reference 299 300 const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 301 { 302 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 303 DE_NULL, // const void* pNext; 304 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 305 VK_FALSE, // VkBool32 depthTestEnable; 306 VK_FALSE, // VkBool32 depthWriteEnable; 307 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 308 VK_FALSE, // VkBool32 depthBoundsTestEnable; 309 VK_FALSE, // VkBool32 stencilTestEnable; 310 stencilOpState, // VkStencilOpState front; 311 stencilOpState, // VkStencilOpState back; 312 0.0f, // float minDepthBounds; 313 1.0f, // float maxDepthBounds; 314 }; 315 316 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 317 // Number of blend attachments must equal the number of color attachments during any subpass. 318 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 319 { 320 VK_FALSE, // VkBool32 blendEnable; 321 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 322 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 323 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 324 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 325 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 326 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 327 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 328 }; 329 330 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 331 { 332 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 333 DE_NULL, // const void* pNext; 334 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 335 VK_FALSE, // VkBool32 logicOpEnable; 336 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 337 hasAttachments ? 1u : 0u, // deUint32 attachmentCount; 338 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 339 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 340 }; 341 342 const VkPipelineShaderStageCreateInfo pShaderStages[] = 343 { 344 { 345 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 346 DE_NULL, // const void* pNext; 347 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 348 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 349 vertexModule, // VkShaderModule module; 350 "main", // const char* pName; 351 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 352 }, 353 { 354 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 355 DE_NULL, // const void* pNext; 356 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 357 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 358 fragmentModule, // VkShaderModule module; 359 "main", // const char* pName; 360 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 361 } 362 }; 363 364 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 365 { 366 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 367 DE_NULL, // const void* pNext; 368 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 369 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; 370 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 371 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 372 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 373 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 374 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 375 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 376 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 377 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 378 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 379 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 380 pipelineLayout, // VkPipelineLayout layout; 381 renderPass, // VkRenderPass renderPass; 382 subpass, // deUint32 subpass; 383 DE_NULL, // VkPipeline basePipelineHandle; 384 0, // deInt32 basePipelineIndex; 385 }; 386 387 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 388} 389 390Move<VkImage> makeImage (const DeviceInterface& vk, 391 const VkDevice device, 392 const VkImageCreateFlags flags, 393 const VkImageType imageType, 394 const VkFormat format, 395 const IVec3& size, 396 const deUint32 numLayers, 397 const VkImageUsageFlags usage, 398 const bool multisample) 399{ 400 const VkImageCreateInfo imageParams = 401 { 402 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 403 DE_NULL, // const void* pNext; 404 flags, // VkImageCreateFlags flags; 405 imageType, // VkImageType imageType; 406 format, // VkFormat format; 407 makeExtent3D(size), // VkExtent3D extent; 408 1u, // deUint32 mipLevels; 409 numLayers, // deUint32 arrayLayers; 410 multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 411 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 412 usage, // VkImageUsageFlags usage; 413 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 414 0u, // deUint32 queueFamilyIndexCount; 415 DE_NULL, // const deUint32* pQueueFamilyIndices; 416 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 417 }; 418 419 return createImage(vk, device, &imageParams); 420} 421 422vector<tcu::Vec4> genFullQuadVertices (const int subpassCount) 423{ 424 vector<tcu::Vec4> vectorData; 425 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx) 426 { 427 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); 428 vectorData.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f)); 429 vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f)); 430 vectorData.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f)); 431 } 432 return vectorData; 433} 434 435void initColorPrograms (SourceCollections& programCollection, const CaseDef caseDef) 436{ 437 (void)caseDef; 438 439 // Vertex shader 440 { 441 std::ostringstream src; 442 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 443 << "\n" 444 << "layout(location = 0) in vec4 in_position;\n" 445 << "\n" 446 << "out gl_PerVertex {\n" 447 << " vec4 gl_Position;\n" 448 << "};\n" 449 << "\n" 450 << "void main(void)\n" 451 << "{\n" 452 << " gl_Position = in_position;\n" 453 << "}\n"; 454 455 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 456 } 457 458 // Fragment shader 459 { 460 std::ostringstream src; 461 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 462 << "\n" 463 << "layout(location = 0) out vec4 o_color;\n" 464 << "\n" 465 << "void main(void)\n" 466 << "{\n" 467 << " o_color = vec4(1.0, 0.5, 0.25, 1.0);\n" 468 << "}\n"; 469 470 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 471 } 472} 473 474tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef) 475{ 476 const tcu::PixelBufferAccess expectedImage (textureLevel); 477 const int renderDepth = deMax32(caseDef.renderSize.z(), caseDef.numLayers); 478 479 for (int z = 0; z < expectedImage.getDepth(); ++z) 480 { 481 for (int y = 0; y < expectedImage.getHeight(); ++y) 482 { 483 for (int x = 0; x < expectedImage.getWidth(); ++x) 484 { 485 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth) 486 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z); 487 else 488 expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z); 489 } 490 } 491 } 492 return expectedImage; 493} 494 495inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage) 496{ 497 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage); 498 return createBuffer(vk, device, &bufferCreateInfo); 499} 500 501inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount) 502{ 503 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount); 504} 505 506// Tests rendering to a a framebuffer with color attachments larger than the 507// framebuffer dimensions and verifies that rendering does not affect the areas 508// of the attachment outside the framebuffer dimensions. Tests both single-sample 509// and multi-sample configurations. 510tcu::TestStatus test (Context& context, const CaseDef caseDef) 511{ 512 const DeviceInterface& vk = context.getDeviceInterface(); 513 const VkDevice device = context.getDevice(); 514 const VkQueue queue = context.getUniversalQueue(); 515 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 516 Allocator& allocator = context.getDefaultAllocator(); 517 518 // Color image for rendering in single-sample tests or resolve target for multi-sample tests 519 Move<VkImage> colorImage; 520 MovePtr<Allocation> colorImageAlloc; 521 522 // For multisampled tests, this is the rendering target 523 Move<VkImage> msColorImage; 524 MovePtr<Allocation> msColorImageAlloc; 525 526 // Host memory buffer where we will copy the rendered image for verification 527 const deUint32 att_size_x = caseDef.attachmentSize.x(); 528 const deUint32 att_size_y = caseDef.attachmentSize.y(); 529 const deUint32 att_size_z = caseDef.attachmentSize.z(); 530 const VkDeviceSize colorBufferSize = att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT)); 531 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 532 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); 533 534 Move<VkBuffer> vertexBuffer; 535 MovePtr<Allocation> vertexBufferAlloc; 536 537 vector<SharedPtrVkImageView> colorAttachments; 538 vector<VkImageView> attachmentHandles; 539 540 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device)); 541 vector<SharedPtrVkPipeline> pipeline; 542 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample)); 543 Move<VkFramebuffer> framebuffer; 544 545 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u)); 546 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u)); 547 548 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 549 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 550 551 const VkImageViewType imageViewType = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY 552 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType; 553 554 // create vertexBuffer 555 { 556 const vector<tcu::Vec4> vertices = genFullQuadVertices(caseDef.numLayers); 557 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 558 559 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 560 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible); 561 562 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 563 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize); 564 } 565 566 // create colorImage (and msColorImage) using the configured attachmentsize 567 { 568 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 569 570 colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, 571 caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false); 572 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any); 573 574 if (caseDef.multisample) 575 { 576 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 577 578 msColorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, 579 caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true); 580 msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any); 581 } 582 } 583 584 // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor 585 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx) 586 { 587 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage, 588 imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1)))); 589 attachmentHandles.push_back(**colorAttachments.back()); 590 591 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, 592 caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, true, caseDef.multisample))); 593 } 594 595 // create framebuffer 596 framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0], 597 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y())); 598 599 // record command buffer 600 beginCommandBuffer(vk, *cmdBuffer); 601 { 602 // Clear the entire image attachment to black 603 { 604 const VkImageMemoryBarrier imageLayoutBarriers[] = 605 { 606 { 607 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 608 DE_NULL, // const void* pNext; 609 0u, // VkAccessFlags srcAccessMask; 610 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; 611 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 612 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; 613 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 614 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 615 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image; 616 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 617 }, 618 }; 619 620 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u, 621 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers); 622 623 const VkImageSubresourceRange ranges = makeColorSubresourceRange(0, caseDef.numLayers); 624 const VkClearColorValue clearColor = 625 { 626 {0.0f, 0.0f, 0.0f, 1.0f} 627 }; 628 vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges); 629 630 const VkImageMemoryBarrier imageClearBarriers[] = 631 { 632 { 633 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 634 DE_NULL, // const void* pNext; 635 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 636 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; 637 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; 638 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 639 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 640 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 641 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image; 642 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 643 }, 644 }; 645 646 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 647 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers); 648 } 649 650 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment) 651 { 652 const VkRect2D renderArea = 653 { 654 makeOffset2D(0, 0), 655 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()), 656 }; 657 const VkRenderPassBeginInfo renderPassBeginInfo = 658 { 659 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 660 DE_NULL, // const void* pNext; 661 *renderPass, // VkRenderPass renderPass; 662 *framebuffer, // VkFramebuffer framebuffer; 663 renderArea, // VkRect2D renderArea; 664 0, // uint32_t clearValueCount; 665 DE_NULL, // const VkClearValue* pClearValues; 666 }; 667 const VkDeviceSize vertexBufferOffset = 0ull; 668 669 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 670 { 671 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 672 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx) 673 { 674 if (layerNdx != 0) 675 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 676 677 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]); 678 vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u); 679 } 680 } 681 vk.cmdEndRenderPass(*cmdBuffer); 682 } 683 684 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage) 685 if (caseDef.multisample) 686 { 687 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving 688 const VkImageMemoryBarrier imageBarriers[] = 689 { 690 { 691 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 692 DE_NULL, // const void* pNext; 693 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 694 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 695 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 696 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 697 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 698 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 699 *msColorImage, // VkImage image; 700 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 701 }, 702 { 703 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 704 DE_NULL, // const void* pNext; 705 (VkAccessFlags)0, // VkAccessFlags srcAccessMask; 706 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; 707 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 708 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout; 709 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 710 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 711 *colorImage, // VkImage image; 712 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 713 } 714 }; 715 716 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 717 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers); 718 719 const VkImageResolve region = 720 { 721 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource; 722 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset; 723 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource; 724 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset; 725 makeExtent3D(caseDef.attachmentSize) // VkExtent3D extent; 726 }; 727 728 vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); 729 } 730 731 // copy colorImage to host visible colorBuffer 732 { 733 const VkImageMemoryBarrier imageBarriers[] = 734 { 735 { 736 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 737 DE_NULL, // const void* pNext; 738 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), 739 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 740 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 741 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 742 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 743 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 744 *colorImage, // VkImage image; 745 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange; 746 } 747 }; 748 749 vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 750 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers); 751 752 const VkBufferImageCopy region = 753 { 754 0ull, // VkDeviceSize bufferOffset; 755 0u, // uint32_t bufferRowLength; 756 0u, // uint32_t bufferImageHeight; 757 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource; 758 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 759 makeExtent3D(caseDef.attachmentSize), // VkExtent3D imageExtent; 760 }; 761 762 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion); 763 764 const VkBufferMemoryBarrier bufferBarriers[] = 765 { 766 { 767 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 768 DE_NULL, // const void* pNext; 769 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 770 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 771 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 772 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 773 *colorBuffer, // VkBuffer buffer; 774 0ull, // VkDeviceSize offset; 775 VK_WHOLE_SIZE, // VkDeviceSize size; 776 }, 777 }; 778 779 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 780 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL); 781 } 782 } // beginCommandBuffer 783 784 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 785 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 786 787 // Verify results 788 { 789 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); 790 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT); 791 const int depth = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers); 792 tcu::TextureLevel textureLevel (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth); 793 const tcu::PixelBufferAccess expectedImage = getExpectedData(textureLevel, caseDef); 794 const tcu::ConstPixelBufferAccess resultImage (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr()); 795 796 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT)) 797 return tcu::TestStatus::fail("Fail"); 798 } 799 800 return tcu::TestStatus::pass("Pass"); 801} 802 803void initImagePrograms (SourceCollections& programCollection, const bool multisample) 804{ 805 // Vertex shader 806 { 807 std::ostringstream src; 808 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 809 << "\n" 810 << "layout(location = 0) in vec4 in_position;\n" 811 << "\n" 812 << "out gl_PerVertex {\n" 813 << " vec4 gl_Position;\n" 814 << "};\n" 815 << "\n" 816 << "void main(void)\n" 817 << "{\n" 818 << " gl_Position = in_position;\n" 819 << "}\n"; 820 821 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 822 } 823 824 // Fragment shader 825 { 826 std::ostringstream src; 827 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 828 << "\n" 829 << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n" 830 << "\n" 831 << "void main(void)\n" 832 << "{\n"; 833 if (!multisample) 834 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n"; 835 else 836 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n"; 837 src << "}\n"; 838 839 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 840 } 841} 842 843//! Make a render pass with no attachments 844Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device) 845{ 846 // Create a single subpass with no attachment references 847 vector<VkSubpassDescription> subpasses; 848 849 const VkSubpassDescription subpassDescription = 850 { 851 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 852 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 853 0u, // deUint32 inputAttachmentCount; 854 DE_NULL, // const VkAttachmentReference* pInputAttachments; 855 0u, // deUint32 colorAttachmentCount; 856 DE_NULL, // const VkAttachmentReference* pColorAttachments; 857 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 858 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 859 0u, // deUint32 preserveAttachmentCount; 860 DE_NULL // const deUint32* pPreserveAttachments; 861 }; 862 subpasses.push_back(subpassDescription); 863 864 const VkRenderPassCreateInfo renderPassInfo = 865 { 866 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 867 DE_NULL, // const void* pNext; 868 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 869 0, // deUint32 attachmentCount; 870 DE_NULL, // const VkAttachmentDescription* pAttachments; 871 1, // deUint32 subpassCount; 872 &subpasses[0], // const VkSubpassDescription* pSubpasses; 873 0u, // deUint32 dependencyCount; 874 DE_NULL // const VkSubpassDependency* pDependencies; 875 }; 876 877 return createRenderPass(vk, device, &renderPassInfo); 878} 879 880tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel) 881{ 882 const tcu::PixelBufferAccess expectedImage (textureLevel); 883 for (int z = 0; z < expectedImage.getDepth(); ++z) 884 { 885 for (int y = 0; y < expectedImage.getHeight(); ++y) 886 { 887 for (int x = 0; x < expectedImage.getWidth(); ++x) 888 { 889 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z); 890 } 891 } 892 } 893 return expectedImage; 894} 895 896vector<tcu::Vec4> genPointVertices (void) 897{ 898 vector<tcu::Vec4> vectorData; 899 vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1)); 900 vectorData.push_back(Vec4(-0.25f, 0.25f, 0, 1)); 901 vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1)); 902 vectorData.push_back(Vec4(0.25f, 0.25f, 0, 1)); 903 return vectorData; 904} 905 906// Tests rendering to a framebuffer without color attachments, checking that 907// the fragment shader is run even in the absence of color output. In this case 908// we render 4 point primitives and we make the fragment shader write to a 909// different pixel of an image via an imageStore command. For the single-sampled 910// configuration we use a 4x1 image to record the output and for the 911// multi-sampled case we use a 4x4 image to record all 16 samples produced by 912// 4-sample multi-sampling 913tcu::TestStatus testNoAtt (Context& context, const bool multisample) 914{ 915 const VkPhysicalDeviceFeatures features = context.getDeviceFeatures(); 916 if (!features.fragmentStoresAndAtomics) 917 throw tcu::NotSupportedError("fragmentStoresAndAtomics feature not supported"); 918 if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID 919 throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported"); 920 if (multisample && !features.sampleRateShading) // MS shader uses gl_SampleID 921 throw tcu::NotSupportedError("sampleRateShading feature not supported"); 922 923 const DeviceInterface& vk = context.getDeviceInterface(); 924 const VkDevice device = context.getDevice(); 925 const VkQueue queue = context.getUniversalQueue(); 926 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 927 Allocator& allocator = context.getDefaultAllocator(); 928 const IVec3 renderSize (32, 32, 1); 929 930 Move<VkBuffer> vertexBuffer; 931 MovePtr<Allocation> vertexBufferAlloc; 932 933 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); 934 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); 935 936 // Create image where we will record the writes. For single-sampled cases this is a 4x1 image 937 // and for multi-sampled cases this is a 4x<num_samples> image. 938 const deUint8 numSamples = multisample ? 4 : 1; 939 const deUint8 imageWidth = 4; 940 const deUint8 imageHeight = numSamples; 941 const deUint8 imageDepth = 1; 942 const deUint8 imageLayers = 1; 943 const IVec3 imageDim = IVec3(imageWidth, imageHeight, imageDepth); 944 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT; 945 const Move<VkImage> image = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false); 946 const VkImageSubresourceRange imageSubresourceRange = makeColorSubresourceRange(0u, imageLayers); 947 const MovePtr<Allocation> imageAlloc = bindImage(vk, device, allocator, *image, MemoryRequirement::Any); 948 const Move<VkImageView> imageView = makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange); 949 950 // Create a buffer where we will copy the image for verification 951 const VkDeviceSize colorBufferSize = imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT)); 952 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 953 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); 954 955 // Create pipeline descriptor set for the image 956 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder() 957 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) 958 .build(vk, device); 959 960 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder() 961 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1) 962 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 963 964 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout); 965 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL); 966 DescriptorSetUpdateBuilder() 967 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo) 968 .update(vk, device); 969 970 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout)); 971 vector<SharedPtrVkPipeline> pipeline; 972 const Unique<VkRenderPass> renderPass (makeRenderPassNoAtt (vk, device)); 973 Move<VkFramebuffer> framebuffer; 974 975 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 976 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); 977 978 // create vertexBuffer 979 { 980 const vector<tcu::Vec4> vertices = genPointVertices(); 981 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 982 983 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 984 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible); 985 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 986 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize); 987 } 988 989 // Create render pass and pipeline 990 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, 991 renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, false, multisample))); 992 framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y()); 993 994 // Record command buffer 995 beginCommandBuffer(vk, *cmdBuffer); 996 { 997 // shader image layout transition undefined -> general 998 { 999 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier( 1000 0u, VK_ACCESS_SHADER_WRITE_BIT, 1001 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 1002 *image, imageSubresourceRange); 1003 1004 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 1005 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier); 1006 } 1007 1008 // Render pass 1009 { 1010 const VkRect2D renderArea = 1011 { 1012 makeOffset2D(0, 0), 1013 makeExtent2D(renderSize.x(), renderSize.y()), 1014 }; 1015 const VkRenderPassBeginInfo renderPassBeginInfo = 1016 { 1017 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 1018 DE_NULL, // const void* pNext; 1019 *renderPass, // VkRenderPass renderPass; 1020 *framebuffer, // VkFramebuffer framebuffer; 1021 renderArea, // VkRect2D renderArea; 1022 0, // uint32_t clearValueCount; 1023 DE_NULL, // const VkClearValue* pClearValues; 1024 }; 1025 const VkDeviceSize vertexBufferOffset = 0ull; 1026 1027 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 1028 1029 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]); 1030 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 1031 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 1032 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u); 1033 1034 vk.cmdEndRenderPass(*cmdBuffer); 1035 } 1036 1037 // copy image to host visible colorBuffer 1038 { 1039 const VkImageMemoryBarrier imageBarriers[] = 1040 { 1041 { 1042 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1043 DE_NULL, // const void* pNext; 1044 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1045 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 1046 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout; 1047 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 1048 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1049 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1050 *image, // VkImage image; 1051 makeColorSubresourceRange(0, 1) // VkImageSubresourceRange subresourceRange; 1052 } 1053 }; 1054 1055 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1056 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers); 1057 1058 const VkBufferImageCopy region = 1059 { 1060 0ull, // VkDeviceSize bufferOffset; 1061 0u, // uint32_t bufferRowLength; 1062 0u, // uint32_t bufferImageHeight; 1063 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1), // VkImageSubresourceLayers imageSubresource; 1064 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 1065 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)), // VkExtent3D imageExtent; 1066 }; 1067 1068 vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion); 1069 1070 const VkBufferMemoryBarrier bufferBarriers[] = 1071 { 1072 { 1073 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 1074 DE_NULL, // const void* pNext; 1075 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1076 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 1077 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1078 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1079 *colorBuffer, // VkBuffer buffer; 1080 0ull, // VkDeviceSize offset; 1081 VK_WHOLE_SIZE, // VkDeviceSize size; 1082 }, 1083 }; 1084 1085 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1086 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL); 1087 } 1088 } // beginCommandBuffer 1089 1090 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1091 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1092 1093 // Verify results 1094 { 1095 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1096 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT); 1097 tcu::TextureLevel textureLevel (format, imageWidth, imageHeight, imageDepth); 1098 const tcu::PixelBufferAccess expectedImage = getExpectedDataNoAtt(textureLevel); 1099 const tcu::ConstPixelBufferAccess resultImage (format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr()); 1100 1101 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT)) 1102 return tcu::TestStatus::fail("Fail"); 1103 } 1104 1105 return tcu::TestStatus::pass("Pass"); 1106} 1107 1108std::string getShortImageViewTypeName (const VkImageViewType imageViewType) 1109{ 1110 std::string s (getImageViewTypeName(imageViewType)); 1111 return de::toLower(s.substr(19)); 1112} 1113 1114std::string getSizeString (const CaseDef& caseDef) 1115{ 1116 std::ostringstream str; 1117 1118 str << caseDef.renderSize.x(); 1119 if (caseDef.renderSize.y() > 1) str << "x" << caseDef.renderSize.y(); 1120 if (caseDef.renderSize.z() > 1) str << "x" << caseDef.renderSize.z(); 1121 1122 str << "_" << caseDef.attachmentSize.x(); 1123 1124 if (caseDef.attachmentSize.y() > 1) str << "x" << caseDef.attachmentSize.y(); 1125 if (caseDef.attachmentSize.z() > 1) str << "x" << caseDef.attachmentSize.z(); 1126 if (caseDef.numLayers > 1) str << "_" << caseDef.numLayers; 1127 1128 return str.str(); 1129} 1130 1131std::string getTestCaseString (const CaseDef& caseDef) 1132{ 1133 std::ostringstream str; 1134 1135 str << getShortImageViewTypeName (caseDef.imageType).c_str(); 1136 str << "_"; 1137 str << getSizeString(caseDef); 1138 1139 if (caseDef.multisample) 1140 str << "_ms"; 1141 1142 return str.str(); 1143} 1144 1145void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group) 1146{ 1147 1148 // Add test cases for attachment strictly sizes larger than the framebuffer 1149 const CaseDef caseDef[] = 1150 { 1151 // Single-sample test cases 1152 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false }, 1153 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false }, 1154 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false }, 1155 { VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false }, 1156 1157 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(64, 1, 1), 4, false }, 1158 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(48, 1, 1), 4, false }, 1159 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(39, 1, 1), 4, false }, 1160 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(19, 1, 1), IVec3(32, 1, 1), 4, false }, 1161 1162 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false }, 1163 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false }, 1164 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false }, 1165 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false }, 1166 1167 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, false }, 1168 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, false }, 1169 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, false }, 1170 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, false }, 1171 1172 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(64, 64, 1), 6, false }, 1173 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(48, 48, 1), 6, false }, 1174 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(39, 41, 1), 6, false }, 1175 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(19, 27, 1), IVec3(32, 32, 1), 6, false }, 1176 1177 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 6*2, false }, 1178 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 6*2, false }, 1179 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 6*2, false }, 1180 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 6*2, false }, 1181 1182 // Multi-sample test cases 1183 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true }, 1184 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true }, 1185 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true }, 1186 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true }, 1187 1188 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, true }, 1189 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, true }, 1190 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, true }, 1191 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, true }, 1192 }; 1193 1194 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx) 1195 addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]); 1196 1197 // Add tests for the case where there are no color attachments but the 1198 // fragment shader writes to an image via imageStore(). 1199 addFunctionCaseWithPrograms(group, "no_attachments", "", initImagePrograms, testNoAtt, false); 1200 addFunctionCaseWithPrograms(group, "no_attachments_ms", "", initImagePrograms, testNoAtt, true); 1201} 1202 1203} // anonymous ns 1204 1205tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx) 1206{ 1207 return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions); 1208} 1209 1210} // pipeline 1211} // vkt 1212