1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2018 The Khronos Group Inc. 6 * Copyright (c) 2018 Google Inc. 7 * Copyright (c) 2015 Imagination Technologies Ltd. 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Tests attachments unused by subpasses 24 *//*--------------------------------------------------------------------*/ 25 26 #include "vktRenderPassUnusedAttachmentTests.hpp" 27 #include "pipeline/vktPipelineImageUtil.hpp" 28 #include "vktTestCase.hpp" 29 #include "vkImageUtil.hpp" 30 #include "vkMemUtil.hpp" 31 #include "vkPlatform.hpp" 32 #include "vkPrograms.hpp" 33 #include "vkQueryUtil.hpp" 34 #include "vkCmdUtil.hpp" 35 #include "vkRef.hpp" 36 #include "vkRefUtil.hpp" 37 #include "vkTypeUtil.hpp" 38 #include "vkCmdUtil.hpp" 39 #include "vkObjUtil.hpp" 40 #include "tcuImageCompare.hpp" 41 #include "tcuPlatform.hpp" 42 #include "tcuTextureUtil.hpp" 43 #include "tcuTestLog.hpp" 44 #include "deStringUtil.hpp" 45 #include "deUniquePtr.hpp" 46 #include "deRandom.hpp" 47 #include <cstring> 48 #include <set> 49 #include <sstream> 50 #include <vector> 51 52 namespace vkt 53 { 54 namespace renderpass 55 { 56 57 using namespace vk; 58 59 namespace 60 { 61 62 struct TestParams 63 { 64 VkAttachmentLoadOp loadOp; 65 VkAttachmentStoreOp storeOp; 66 VkAttachmentLoadOp stencilLoadOp; 67 VkAttachmentStoreOp stencilStoreOp; 68 RenderPassType renderPassType; 69 }; 70 71 struct Vertex4RGBA 72 { 73 tcu::Vec4 position; 74 tcu::Vec4 color; 75 }; 76 77 std::vector<Vertex4RGBA> createQuad (void) 78 { 79 std::vector<Vertex4RGBA> vertices; 80 81 const float size = 0.8f; 82 const tcu::Vec4 color (0.2f, 0.3f, 0.1f, 1.0f); 83 const Vertex4RGBA lowerLeftVertex = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color}; 84 const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, 0.0f, 1.0f), color}; 85 const Vertex4RGBA upperLeftVertex = {tcu::Vec4(-size, size, 0.0f, 1.0f), color}; 86 const Vertex4RGBA upperRightVertex = {tcu::Vec4(size, size, 0.0f, 1.0f), color}; 87 88 vertices.push_back(lowerLeftVertex); 89 vertices.push_back(lowerRightVertex); 90 vertices.push_back(upperLeftVertex); 91 vertices.push_back(upperLeftVertex); 92 vertices.push_back(lowerRightVertex); 93 vertices.push_back(upperRightVertex); 94 95 return vertices; 96 } 97 98 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo> 99 Move<VkRenderPass> createRenderPass (const DeviceInterface& vk, 100 VkDevice vkDevice, 101 const TestParams testParams) 102 { 103 const VkImageAspectFlags aspectMask = testParams.renderPassType == RENDERPASS_TYPE_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT; 104 const AttachmentDesc attachmentDescriptions[] = 105 { 106 // Result attachment 107 AttachmentDesc ( 108 DE_NULL, // const void* pNext 109 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags 110 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format 111 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples 112 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp 113 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp 114 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp 115 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp 116 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout 117 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout 118 ), 119 // Unused attachment 120 AttachmentDesc ( 121 DE_NULL, // const void* pNext 122 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags 123 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format 124 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples 125 testParams.loadOp, // VkAttachmentLoadOp loadOp 126 testParams.storeOp, // VkAttachmentStoreOp storeOp 127 testParams.stencilLoadOp, // VkAttachmentLoadOp stencilLoadOp 128 testParams.stencilStoreOp, // VkAttachmentStoreOp stencilStoreOp 129 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout 130 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout 131 ), 132 // Input attachment 133 AttachmentDesc ( 134 DE_NULL, // const void* pNext 135 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags 136 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format 137 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples 138 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp 139 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp 140 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp 141 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp 142 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout 143 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout 144 ) 145 }; 146 147 // Note: Attachment 1 is not referenced by any subpass. 148 const AttachmentRef resultAttachmentRefSubpass0 ( 149 DE_NULL, // const void* pNext 150 2u, // deUint32 attachment 151 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout 152 aspectMask // VkImageAspectFlags aspectMask 153 ); 154 155 const AttachmentRef resultAttachmentRefSubpass1 ( 156 DE_NULL, // const void* pNext 157 0u, // deUint32 attachment 158 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout 159 aspectMask // VkImageAspectFlags aspectMask 160 ); 161 162 const AttachmentRef inputAttachmentRefSubpass1 ( 163 DE_NULL, // const void* pNext 164 2u, // deUint32 attachment 165 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout 166 aspectMask // VkImageAspectFlags aspectMask 167 ); 168 169 const SubpassDesc subpassDescriptions[] = 170 { 171 SubpassDesc ( 172 DE_NULL, 173 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags 174 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint 175 0u, // deUint32 viewMask 176 0u, // deUint32 inputAttachmentCount 177 DE_NULL, // const VkAttachmentReference* pInputAttachments 178 1u, // deUint32 colorAttachmentCount 179 &resultAttachmentRefSubpass0, // const VkAttachmentReference* pColorAttachments 180 DE_NULL, // const VkAttachmentReference* pResolveAttachments 181 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment 182 0u, // deUint32 preserveAttachmentCount 183 DE_NULL // const deUint32* pPreserveAttachments 184 ), 185 SubpassDesc ( 186 DE_NULL, 187 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags 188 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint 189 0u, // deUint32 viewMask 190 1u, // deUint32 inputAttachmentCount 191 &inputAttachmentRefSubpass1, // const VkAttachmentReference* pInputAttachments 192 1u, // deUint32 colorAttachmentCount 193 &resultAttachmentRefSubpass1, // const VkAttachmentReference* pColorAttachments 194 DE_NULL, // const VkAttachmentReference* pResolveAttachments 195 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment 196 0u, // deUint32 preserveAttachmentCount 197 DE_NULL // const deUint32* pPreserveAttachments 198 ) 199 }; 200 201 const SubpassDep subpassDependency ( 202 DE_NULL, // const void* pNext 203 0u, // uint32_t srcSubpass 204 1u, // uint32_t dstSubpass 205 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask 206 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask 207 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask 208 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask 209 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags 210 0u // deInt32 viewOffset 211 ); 212 213 const RenderPassCreateInfo renderPassInfo ( 214 DE_NULL, // const void* pNext 215 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags 216 3u, // deUint32 attachmentCount 217 attachmentDescriptions, // const VkAttachmentDescription* pAttachments 218 2u, // deUint32 subpassCount 219 subpassDescriptions, // const VkSubpassDescription* pSubpasses 220 1u, // deUint32 dependencyCount 221 &subpassDependency, // const VkSubpassDependency* pDependencies 222 0u, // deUint32 correlatedViewMaskCount 223 DE_NULL // const deUint32* pCorrelatedViewMasks 224 ); 225 226 return renderPassInfo.createRenderPass(vk, vkDevice); 227 } 228 229 class UnusedAttachmentTest : public vkt::TestCase 230 { 231 public: 232 UnusedAttachmentTest (tcu::TestContext& testContext, 233 const std::string& name, 234 const std::string& description, 235 const TestParams& testParams); 236 virtual ~UnusedAttachmentTest (void); 237 virtual void initPrograms (SourceCollections& sourceCollections) const; 238 virtual TestInstance* createInstance (Context& context) const; 239 private: 240 const TestParams m_testParams; 241 }; 242 243 class UnusedAttachmentTestInstance : public vkt::TestInstance 244 { 245 public: 246 UnusedAttachmentTestInstance (Context& context, 247 const TestParams& testParams); 248 virtual ~UnusedAttachmentTestInstance (void); 249 virtual tcu::TestStatus iterate (void); 250 template<typename RenderpassSubpass> 251 void createCommandBuffer (const DeviceInterface& vk, 252 VkDevice vkDevice); 253 private: 254 tcu::TestStatus verifyImage (void); 255 256 const tcu::UVec2 m_renderSize; 257 258 Move<VkImage> m_colorImage; 259 de::MovePtr<Allocation> m_colorImageAlloc; 260 Move<VkImageView> m_colorAttachmentView; 261 262 Move<VkImage> m_unusedImage; 263 de::MovePtr<Allocation> m_unusedImageAlloc; 264 Move<VkImageView> m_unusedAttachmentView; 265 266 Move<VkImage> m_inputImage; 267 de::MovePtr<Allocation> m_inputImageAlloc; 268 Move<VkImageView> m_inputAttachmentView; 269 270 Move<VkDescriptorSetLayout> m_descriptorSetLayoutSubpass0; 271 Move<VkDescriptorSetLayout> m_descriptorSetLayoutSubpass1; 272 Move<VkDescriptorPool> m_descriptorPool; 273 Move<VkDescriptorSet> m_descriptorSetSubpass1; 274 Move<VkRenderPass> m_renderPass; 275 Move<VkFramebuffer> m_framebuffer; 276 277 Move<VkShaderModule> m_vertexShaderModule; 278 Move<VkShaderModule> m_fragmentShaderModuleSubpass0; 279 Move<VkShaderModule> m_fragmentShaderModuleSubpass1; 280 281 Move<VkBuffer> m_vertexBuffer; 282 std::vector<Vertex4RGBA> m_vertices; 283 de::MovePtr<Allocation> m_vertexBufferAlloc; 284 285 Move<VkBuffer> m_backingBuffer; 286 de::MovePtr<Allocation> m_backingBufferAlloc; 287 288 Move<VkPipelineLayout> m_pipelineLayoutSubpass0; 289 Move<VkPipelineLayout> m_pipelineLayoutSubpass1; 290 Move<VkPipeline> m_graphicsPipelineSubpass0; 291 Move<VkPipeline> m_graphicsPipelineSubpass1; 292 293 Move<VkCommandPool> m_cmdPool; 294 Move<VkCommandBuffer> m_cmdBuffer; 295 }; 296 297 UnusedAttachmentTest::UnusedAttachmentTest (tcu::TestContext& testContext, 298 const std::string& name, 299 const std::string& description, 300 const TestParams& testParams) 301 : vkt::TestCase (testContext, name, description) 302 , m_testParams (testParams) 303 { 304 } 305 306 UnusedAttachmentTest::~UnusedAttachmentTest (void) 307 { 308 } 309 310 TestInstance* UnusedAttachmentTest::createInstance (Context& context) const 311 { 312 return new UnusedAttachmentTestInstance(context, m_testParams); 313 } 314 315 void UnusedAttachmentTest::initPrograms (SourceCollections& sourceCollections) const 316 { 317 std::ostringstream fragmentSource; 318 319 sourceCollections.glslSources.add("color_vert") << glu::VertexSource( 320 "#version 450\n" 321 "layout(location = 0) in highp vec4 position;\n" 322 "layout(location = 1) in highp vec4 color;\n" 323 "layout(location = 0) out highp vec4 vtxColor;\n" 324 "void main (void)\n" 325 "{\n" 326 " gl_Position = position;\n" 327 " vtxColor = color;\n" 328 "}\n"); 329 330 sourceCollections.glslSources.add("color_frag_sb0") << glu::FragmentSource( 331 "#version 450\n" 332 "layout(location = 0) in highp vec4 vtxColor;\n" 333 "layout(location = 0) out highp vec4 fragColor;\n" 334 "void main (void)\n" 335 "{\n" 336 " fragColor = vtxColor;\n" 337 "}\n"); 338 339 sourceCollections.glslSources.add("color_frag_sb1") << glu::FragmentSource( 340 "#version 450\n" 341 "layout(location = 0) in highp vec4 vtxColor;\n" 342 "layout(location = 0) out highp vec4 fragColor;\n" 343 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;" 344 "void main (void)\n" 345 "{\n" 346 " fragColor = subpassLoad(inputColor) + vtxColor;\n" 347 "}\n"); 348 } 349 350 UnusedAttachmentTestInstance::UnusedAttachmentTestInstance (Context& context, 351 const TestParams& testParams) 352 : vkt::TestInstance (context) 353 , m_renderSize (32u, 32u) 354 , m_vertices (createQuad()) 355 { 356 const DeviceInterface& vk = m_context.getDeviceInterface(); 357 const VkDevice vkDevice = m_context.getDevice(); 358 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 359 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 360 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 361 362 // Check for renderpass2 extension if used 363 if (testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2) 364 context.requireDeviceExtension("VK_KHR_create_renderpass2"); 365 366 // Create color image 367 { 368 const VkImageCreateInfo colorImageParams = 369 { 370 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 371 DE_NULL, // const void* pNext; 372 0u, // VkImageCreateFlags flags; 373 VK_IMAGE_TYPE_2D, // VkImageType imageType; 374 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 375 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent; 376 1u, // deUint32 mipLevels; 377 1u, // deUint32 arrayLayers; 378 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 379 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 380 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 381 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 382 1u, // deUint32 queueFamilyIndexCount; 383 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 384 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 385 }; 386 387 m_colorImage = createImage(vk, vkDevice, &colorImageParams); 388 389 // Allocate and bind color image memory 390 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any); 391 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset())); 392 } 393 394 // Create image which is not used by any subpass 395 { 396 const VkImageCreateInfo unusedImageParams = 397 { 398 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 399 DE_NULL, // const void* pNext; 400 0u, // VkImageCreateFlags flags; 401 VK_IMAGE_TYPE_2D, // VkImageType imageType; 402 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 403 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent; 404 1u, // deUint32 mipLevels; 405 1u, // deUint32 arrayLayers; 406 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 407 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 408 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT 409 | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; 410 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 411 1u, // deUint32 queueFamilyIndexCount; 412 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 413 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 414 }; 415 416 m_unusedImage = createImage(vk, vkDevice, &unusedImageParams); 417 418 // Allocate and bind unused image memory 419 VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vk, vkDevice, *m_unusedImage); 420 421 m_unusedImageAlloc = memAlloc.allocate(memoryRequirements, MemoryRequirement::Any); 422 VK_CHECK(vk.bindImageMemory(vkDevice, *m_unusedImage, m_unusedImageAlloc->getMemory(), m_unusedImageAlloc->getOffset())); 423 424 // Clear image with specific value to verify the contents don't change 425 { 426 const VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 427 Move<VkCommandPool> cmdPool; 428 Move<VkCommandBuffer> cmdBuffer; 429 430 VkClearValue clearValue; 431 clearValue.color.float32[0] = 0.1f; 432 clearValue.color.float32[1] = 0.2f; 433 clearValue.color.float32[2] = 0.3f; 434 clearValue.color.float32[3] = 0.4f; 435 436 // Create command pool and buffer 437 cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 438 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 439 440 const VkImageMemoryBarrier preImageBarrier = 441 { 442 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 443 DE_NULL, // const void* pNext; 444 0u, // VkAccessFlags srcAccessMask; 445 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask; 446 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 447 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; 448 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 449 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 450 *m_unusedImage, // VkImage image; 451 { // VkImageSubresourceRange subresourceRange; 452 aspectMask, // VkImageAspect aspect; 453 0u, // deUint32 baseMipLevel; 454 1u, // deUint32 mipLevels; 455 0u, // deUint32 baseArraySlice; 456 1u // deUint32 arraySize; 457 } 458 }; 459 460 const VkImageMemoryBarrier postImageBarrier = 461 { 462 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 463 DE_NULL, // const void* pNext; 464 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 465 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask; 466 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; 467 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 468 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 469 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 470 *m_unusedImage, // VkImage image; 471 { // VkImageSubresourceRange subresourceRange; 472 aspectMask, // VkImageAspect aspect; 473 0u, // deUint32 baseMipLevel; 474 1u, // deUint32 mipLevels; 475 0u, // deUint32 baseArraySlice; 476 1u // deUint32 arraySize; 477 } 478 }; 479 480 const VkImageSubresourceRange clearRange = 481 { 482 aspectMask, // VkImageAspectFlags aspectMask; 483 0u, // deUint32 baseMipLevel; 484 1u, // deUint32 levelCount; 485 0u, // deUint32 baseArrayLayer; 486 1u // deUint32 layerCount; 487 }; 488 489 // Clear image 490 beginCommandBuffer(vk, *cmdBuffer); 491 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier); 492 vk.cmdClearColorImage(*cmdBuffer, *m_unusedImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &clearRange); 493 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier); 494 endCommandBuffer(vk, *cmdBuffer); 495 496 submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get()); 497 } 498 } 499 500 // Create input image 501 { 502 const VkImageCreateInfo inputImageParams = 503 { 504 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 505 DE_NULL, // const void* pNext; 506 0u, // VkImageCreateFlags flags; 507 VK_IMAGE_TYPE_2D, // VkImageType imageType; 508 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 509 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent; 510 1u, // deUint32 mipLevels; 511 1u, // deUint32 arrayLayers; 512 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 513 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 514 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, // VkImageUsageFlags usage; 515 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 516 1u, // deUint32 queueFamilyIndexCount; 517 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 518 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 519 }; 520 521 m_inputImage = createImage(vk, vkDevice, &inputImageParams); 522 523 // Allocate and bind input image memory 524 m_inputImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_inputImage), MemoryRequirement::Any); 525 VK_CHECK(vk.bindImageMemory(vkDevice, *m_inputImage, m_inputImageAlloc->getMemory(), m_inputImageAlloc->getOffset())); 526 } 527 528 // Create color attachment view 529 { 530 const VkImageViewCreateInfo colorAttachmentViewParams = 531 { 532 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 533 DE_NULL, // const void* pNext; 534 0u, // VkImageViewCreateFlags flags; 535 *m_colorImage, // VkImage image; 536 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 537 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 538 componentMappingRGBA, // VkChannelMapping channels; 539 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 540 }; 541 542 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); 543 } 544 545 // Create unused attachment view 546 { 547 const VkImageViewCreateInfo unusedAttachmentViewParams = 548 { 549 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 550 DE_NULL, // const void* pNext; 551 0u, // VkImageViewCreateFlags flags; 552 *m_unusedImage, // VkImage image; 553 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 554 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 555 componentMappingRGBA, // VkChannelMapping channels; 556 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 557 }; 558 559 m_unusedAttachmentView = createImageView(vk, vkDevice, &unusedAttachmentViewParams); 560 } 561 562 // Create input attachment view 563 { 564 const VkImageViewCreateInfo inputAttachmentViewParams = 565 { 566 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 567 DE_NULL, // const void* pNext; 568 0u, // VkImageViewCreateFlags flags; 569 *m_inputImage, // VkImage image; 570 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 571 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 572 componentMappingRGBA, // VkChannelMapping channels; 573 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 574 }; 575 576 m_inputAttachmentView = createImageView(vk, vkDevice, &inputAttachmentViewParams); 577 } 578 579 // Create render pass 580 if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY) 581 m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams); 582 else 583 m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams); 584 585 // Create framebuffer 586 { 587 const VkImageView imageViews[] = 588 { 589 *m_colorAttachmentView, 590 *m_unusedAttachmentView, 591 *m_inputAttachmentView 592 }; 593 594 const VkFramebufferCreateInfo framebufferParams = 595 { 596 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 597 DE_NULL, // const void* pNext; 598 0u, // VkFramebufferCreateFlags flags; 599 *m_renderPass, // VkRenderPass renderPass; 600 3u, // deUint32 attachmentCount; 601 imageViews, // const VkImageView* pAttachments; 602 (deUint32)m_renderSize.x(), // deUint32 width; 603 (deUint32)m_renderSize.y(), // deUint32 height; 604 1u // deUint32 layers; 605 }; 606 607 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); 608 } 609 610 // Create pipeline layout for subpass 0 611 { 612 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = 613 { 614 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType 615 DE_NULL, // const void* pNext 616 0u, // VkDescriptorSetLayoutCreateFlags flags 617 0u, // deUint32 bindingCount 618 DE_NULL // const VkDescriptorSetLayoutBinding* pBindings 619 }; 620 m_descriptorSetLayoutSubpass0 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams); 621 622 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 623 { 624 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 625 DE_NULL, // const void* pNext; 626 0u, // VkPipelineLayoutCreateFlags flags; 627 1u, // deUint32 setLayoutCount; 628 &m_descriptorSetLayoutSubpass0.get(), // const VkDescriptorSetLayout* pSetLayouts; 629 0u, // deUint32 pushConstantRangeCount; 630 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 631 }; 632 633 m_pipelineLayoutSubpass0 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); 634 } 635 636 // Create pipeline layout for subpass 1 637 { 638 const VkDescriptorSetLayoutBinding layoutBinding = 639 { 640 0u, // deUint32 binding; 641 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType; 642 1u, // deUint32 descriptorCount; 643 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags; 644 DE_NULL // const VkSampler* pImmutableSamplers; 645 }; 646 647 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutParams = 648 { 649 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType 650 DE_NULL, // const void* pNext 651 0u, // VkDescriptorSetLayoutCreateFlags flags 652 1u, // deUint32 bindingCount 653 &layoutBinding // const VkDescriptorSetLayoutBinding* pBindings 654 }; 655 m_descriptorSetLayoutSubpass1 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams); 656 657 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 658 { 659 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 660 DE_NULL, // const void* pNext; 661 0u, // VkPipelineLayoutCreateFlags flags; 662 1u, // deUint32 setLayoutCount; 663 &m_descriptorSetLayoutSubpass1.get(), // const VkDescriptorSetLayout* pSetLayouts; 664 0u, // deUint32 pushConstantRangeCount; 665 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 666 }; 667 668 m_pipelineLayoutSubpass1 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); 669 } 670 671 // Update descriptor set 672 { 673 const VkDescriptorPoolSize descriptorPoolSize = 674 { 675 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType type; 676 1u // deUint32 descriptorCount; 677 }; 678 679 const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = 680 { 681 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType 682 DE_NULL, // const void* pNext 683 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags 684 1u, // deUint32 maxSets 685 1u, // deUint32 poolSizeCount 686 &descriptorPoolSize // const VkDescriptorPoolSize* pPoolSizes 687 }; 688 689 m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo); 690 691 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = 692 { 693 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType 694 DE_NULL, // const void* pNext 695 *m_descriptorPool, // VkDescriptorPool descriptorPool 696 1u, // deUint32 descriptorSetCount 697 &m_descriptorSetLayoutSubpass1.get(), // const VkDescriptorSetLayout* pSetLayouts 698 }; 699 700 m_descriptorSetSubpass1 = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo); 701 702 const VkDescriptorImageInfo inputImageInfo = 703 { 704 DE_NULL, // VkSampleri sampler; 705 *m_inputAttachmentView, // VkImageView imageView; 706 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout; 707 }; 708 709 const VkWriteDescriptorSet descriptorWrite = 710 { 711 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType; 712 DE_NULL, // const void* pNext; 713 *m_descriptorSetSubpass1, // VkDescriptorSet dstSet; 714 0u, // deUint32 dstBinding; 715 0u, // deUint32 dstArrayElement; 716 1u, // deUint32 descriptorCount; 717 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType; 718 &inputImageInfo, // const VkDescriptorImageInfo* pImageInfo; 719 DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo; 720 DE_NULL // const VkBufferView* pTexelBufferView; 721 }; 722 723 vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL); 724 } 725 726 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0); 727 m_fragmentShaderModuleSubpass0 = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb0"), 0); 728 m_fragmentShaderModuleSubpass1 = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb1"), 0); 729 730 // Create pipelines 731 { 732 const VkVertexInputBindingDescription vertexInputBindingDescription = 733 { 734 0u, // deUint32 binding; 735 sizeof(Vertex4RGBA), // deUint32 strideInBytes; 736 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate; 737 }; 738 739 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = 740 { 741 { 742 0u, // deUint32 location; 743 0u, // deUint32 binding; 744 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 745 0u // deUint32 offset; 746 }, 747 { 748 1u, // deUint32 location; 749 0u, // deUint32 binding; 750 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 751 (deUint32)(sizeof(float) * 4), // deUint32 offset; 752 } 753 }; 754 755 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 756 { 757 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 758 DE_NULL, // const void* pNext; 759 0u, // VkPipelineVertexInputStateCreateFlags flags; 760 1u, // deUint32 vertexBindingDescriptionCount; 761 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 762 2u, // deUint32 vertexAttributeDescriptionCount; 763 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 764 }; 765 766 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize)); 767 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize)); 768 769 { 770 m_graphicsPipelineSubpass0 = makeGraphicsPipeline(vk, // const DeviceInterface& vk 771 vkDevice, // const VkDevice device 772 *m_pipelineLayoutSubpass0, // const VkPipelineLayout pipelineLayout 773 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule 774 DE_NULL, // const VkShaderModule tessellationControlModule 775 DE_NULL, // const VkShaderModule tessellationEvalModule 776 DE_NULL, // const VkShaderModule geometryShaderModule 777 *m_fragmentShaderModuleSubpass0, // const VkShaderModule fragmentShaderModule 778 *m_renderPass, // const VkRenderPass renderPass 779 viewports, // const std::vector<VkViewport>& viewports 780 scissors, // const std::vector<VkRect2D>& scissors 781 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology 782 0u, // const deUint32 subpass 783 0u, // const deUint32 patchControlPoints 784 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo 785 786 m_graphicsPipelineSubpass1 = makeGraphicsPipeline(vk, // const DeviceInterface& vk 787 vkDevice, // const VkDevice device 788 *m_pipelineLayoutSubpass1, // const VkPipelineLayout pipelineLayout 789 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule 790 DE_NULL, // const VkShaderModule tessellationControlModule 791 DE_NULL, // const VkShaderModule tessellationEvalModule 792 DE_NULL, // const VkShaderModule geometryShaderModule 793 *m_fragmentShaderModuleSubpass1, // const VkShaderModule fragmentShaderModule 794 *m_renderPass, // const VkRenderPass renderPass 795 viewports, // const std::vector<VkViewport>& viewports 796 scissors, // const std::vector<VkRect2D>& scissors 797 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology 798 1u, // const deUint32 subpass 799 0u, // const deUint32 patchControlPoints 800 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo 801 } 802 } 803 804 // Create vertex buffer 805 { 806 const VkBufferCreateInfo vertexBufferParams = 807 { 808 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 809 DE_NULL, // const void* pNext; 810 0u, // VkBufferCreateFlags flags; 811 (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size; 812 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 813 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 814 1u, // deUint32 queueFamilyIndexCount; 815 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 816 }; 817 818 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); 819 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible); 820 821 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); 822 823 // Upload vertex data 824 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA)); 825 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc); 826 } 827 828 // Create command pool 829 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 830 831 // Create command buffer 832 if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY) 833 createCommandBuffer<RenderpassSubpass1>(vk, vkDevice); 834 else 835 createCommandBuffer<RenderpassSubpass2>(vk, vkDevice); 836 } 837 838 UnusedAttachmentTestInstance::~UnusedAttachmentTestInstance (void) 839 { 840 } 841 842 template<typename RenderpassSubpass> 843 void UnusedAttachmentTestInstance::createCommandBuffer (const DeviceInterface& vk, 844 VkDevice vkDevice) 845 { 846 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo (DE_NULL, VK_SUBPASS_CONTENTS_INLINE); 847 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo (DE_NULL); 848 849 const VkClearValue attachmentClearValues[] = 850 { 851 makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f), // color 852 makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f), // unused 853 makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f) // input 854 }; 855 856 const VkDeviceSize vertexBufferOffset = 0; 857 858 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 859 860 beginCommandBuffer(vk, *m_cmdBuffer, 0u); 861 862 const VkRenderPassBeginInfo renderPassBeginInfo = 863 { 864 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 865 DE_NULL, // const void* pNext; 866 *m_renderPass, // VkRenderPass renderPass; 867 *m_framebuffer, // VkFramebuffer framebuffer; 868 makeRect2D(m_renderSize), // VkRect2D renderArea; 869 3u, // uint32_t clearValueCount; 870 attachmentClearValues // const VkClearValue* pClearValues; 871 }; 872 RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo); 873 874 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass0); 875 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset); 876 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0); 877 vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 878 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass1); 879 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutSubpass1, 0, 1, &m_descriptorSetSubpass1.get(), 0, DE_NULL); 880 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0); 881 882 RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo); 883 endCommandBuffer(vk, *m_cmdBuffer); 884 } 885 886 tcu::TestStatus UnusedAttachmentTestInstance::iterate (void) 887 { 888 const DeviceInterface& vk = m_context.getDeviceInterface(); 889 const VkDevice vkDevice = m_context.getDevice(); 890 const VkQueue queue = m_context.getUniversalQueue(); 891 892 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get()); 893 894 return verifyImage(); 895 } 896 897 tcu::TestStatus UnusedAttachmentTestInstance::verifyImage (void) 898 { 899 const DeviceInterface& vk = m_context.getDeviceInterface(); 900 const VkDevice vkDevice = m_context.getDevice(); 901 const VkQueue queue = m_context.getUniversalQueue(); 902 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 903 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 904 de::UniquePtr<tcu::TextureLevel> textureLevelResult (pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release()); 905 const tcu::ConstPixelBufferAccess& resultAccess = textureLevelResult->getAccess(); 906 de::UniquePtr<tcu::TextureLevel> textureLevelUnused (pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_unusedImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release()); 907 const tcu::ConstPixelBufferAccess& unusedAccess = textureLevelUnused->getAccess(); 908 tcu::TestLog& log = m_context.getTestContext().getLog(); 909 910 // Log images 911 log << tcu::TestLog::ImageSet("Result", "Result images") 912 << tcu::TestLog::Image("Rendered", "Rendered image", resultAccess) 913 << tcu::TestLog::Image("Unused", "Unused image", unusedAccess) 914 << tcu::TestLog::EndImageSet; 915 916 // Check the unused image data hasn't changed. 917 for (int y = 0; y < unusedAccess.getHeight(); y++) 918 for (int x = 0; x < unusedAccess.getWidth(); x++) 919 { 920 const tcu::Vec4 color = unusedAccess.getPixel(x, y); 921 const tcu::Vec4 refColor = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f); 922 for (deUint32 cpnt = 0; cpnt < 4; cpnt++) 923 if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f) 924 return tcu::TestStatus::fail("Unused image contents has changed."); 925 } 926 927 // Check for rendered result. Just a quick sanity check to see if correct color is found at the center of the quad. 928 const tcu::Vec4 resultColor = resultAccess.getPixel(resultAccess.getWidth() / 2, resultAccess.getHeight() / 2); 929 const tcu::Vec4 refColor = tcu::Vec4(0.4f, 0.6f, 0.2f, 1.0f); 930 for (deUint32 cpnt = 0; cpnt < 4; cpnt++) 931 if (de::abs(resultColor[cpnt] - refColor[cpnt]) > 0.01f) 932 return tcu::TestStatus::fail("Result image mismatch"); 933 934 return tcu::TestStatus::pass("Pass"); 935 } 936 937 std::string loadOpToString (VkAttachmentLoadOp loadOp) 938 { 939 switch (loadOp) 940 { 941 case VK_ATTACHMENT_LOAD_OP_LOAD: 942 return "load"; 943 case VK_ATTACHMENT_LOAD_OP_CLEAR: 944 return "clear"; 945 case VK_ATTACHMENT_LOAD_OP_DONT_CARE: 946 return "dontcare"; 947 default: 948 DE_FATAL("unexpected attachment load op"); 949 return ""; 950 }; 951 } 952 953 std::string storeOpToString (VkAttachmentStoreOp storeOp) 954 { 955 switch (storeOp) 956 { 957 case VK_ATTACHMENT_STORE_OP_STORE: 958 return "store"; 959 case VK_ATTACHMENT_STORE_OP_DONT_CARE: 960 return "dontcare"; 961 default: 962 DE_FATAL("unexpected attachment store op"); 963 return ""; 964 }; 965 } 966 967 } // anonymous 968 969 tcu::TestCaseGroup* createRenderPassUnusedAttachmentTests (tcu::TestContext& testCtx, const RenderPassType renderPassType) 970 { 971 de::MovePtr<tcu::TestCaseGroup> unusedAttTests (new tcu::TestCaseGroup(testCtx, "unused_attachment", "Unused attachment tests")); 972 973 const VkAttachmentLoadOp loadOps[] = 974 { 975 VK_ATTACHMENT_LOAD_OP_LOAD, 976 VK_ATTACHMENT_LOAD_OP_CLEAR, 977 VK_ATTACHMENT_LOAD_OP_DONT_CARE 978 }; 979 980 const VkAttachmentStoreOp storeOps[] = 981 { 982 VK_ATTACHMENT_STORE_OP_STORE, 983 VK_ATTACHMENT_STORE_OP_DONT_CARE 984 }; 985 986 for (deUint32 loadOpIdx = 0; loadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpIdx++) 987 { 988 de::MovePtr<tcu::TestCaseGroup> loadOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("loadop") + loadOpToString(loadOps[loadOpIdx])).c_str(), "")); 989 990 for (deUint32 storeOpIdx = 0; storeOpIdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpIdx++) 991 { 992 de::MovePtr<tcu::TestCaseGroup> storeOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("storeop") + storeOpToString(storeOps[storeOpIdx])).c_str(), "")); 993 994 for (deUint32 stencilLoadOpIdx = 0; stencilLoadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); stencilLoadOpIdx++) 995 { 996 de::MovePtr<tcu::TestCaseGroup> stencilLoadOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("stencilloadop") + loadOpToString(loadOps[stencilLoadOpIdx])).c_str(), "")); 997 998 for (deUint32 stencilStoreOpIdx = 0; stencilStoreOpIdx < DE_LENGTH_OF_ARRAY(storeOps); stencilStoreOpIdx++) 999 { 1000 TestParams params; 1001 const std::string testName = std::string("stencilstoreop") + storeOpToString(storeOps[stencilStoreOpIdx]); 1002 1003 params.loadOp = loadOps[loadOpIdx]; 1004 params.storeOp = storeOps[storeOpIdx]; 1005 params.stencilLoadOp = loadOps[stencilLoadOpIdx]; 1006 params.stencilStoreOp = storeOps[stencilStoreOpIdx]; 1007 params.renderPassType = renderPassType; 1008 1009 stencilLoadOpGroup->addChild(new UnusedAttachmentTest(testCtx, testName, "", params)); 1010 } 1011 storeOpGroup->addChild(stencilLoadOpGroup.release()); 1012 } 1013 loadOpGroup->addChild(storeOpGroup.release()); 1014 } 1015 unusedAttTests->addChild(loadOpGroup.release()); 1016 } 1017 1018 return unusedAttTests.release(); 1019 } 1020 1021 } // renderpass 1022 } // vkt 1023