1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Multisample image Tests 22 *//*--------------------------------------------------------------------*/ 23 24#include "vktPipelineMultisampleImageTests.hpp" 25#include "vktPipelineMakeUtil.hpp" 26#include "vktTestCase.hpp" 27#include "vktTestCaseUtil.hpp" 28#include "vktPipelineVertexUtil.hpp" 29#include "vktTestGroupUtil.hpp" 30 31#include "vkMemUtil.hpp" 32#include "vkQueryUtil.hpp" 33#include "vkTypeUtil.hpp" 34#include "vkRefUtil.hpp" 35#include "vkBuilderUtil.hpp" 36#include "vkPrograms.hpp" 37#include "vkImageUtil.hpp" 38 39#include "tcuTextureUtil.hpp" 40#include "tcuTestLog.hpp" 41 42#include "deUniquePtr.hpp" 43#include "deSharedPtr.hpp" 44 45#include <string> 46 47namespace vkt 48{ 49namespace pipeline 50{ 51namespace 52{ 53using namespace vk; 54using de::UniquePtr; 55using de::MovePtr; 56using de::SharedPtr; 57using tcu::IVec2; 58using tcu::Vec4; 59 60typedef SharedPtr<Unique<VkImageView> > ImageViewSp; 61typedef SharedPtr<Unique<VkPipeline> > PipelineSp; 62 63//! Test case parameters 64struct CaseDef 65{ 66 IVec2 renderSize; 67 int numLayers; 68 VkFormat colorFormat; 69 VkSampleCountFlagBits numSamples; 70}; 71 72template<typename T> 73inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move) 74{ 75 return SharedPtr<Unique<T> >(new Unique<T>(move)); 76} 77 78template<typename T> 79inline VkDeviceSize sizeInBytes(const std::vector<T>& vec) 80{ 81 return vec.size() * sizeof(vec[0]); 82} 83 84//! Create a vector of derived pipelines, each with an increasing subpass index 85std::vector<PipelineSp> makeGraphicsPipelines (const DeviceInterface& vk, 86 const VkDevice device, 87 const deUint32 numSubpasses, 88 const VkPipelineLayout pipelineLayout, 89 const VkRenderPass renderPass, 90 const VkShaderModule vertexModule, 91 const VkShaderModule fragmentModule, 92 const IVec2 renderSize, 93 const VkSampleCountFlagBits numSamples, 94 const VkPrimitiveTopology topology) 95{ 96 const VkVertexInputBindingDescription vertexInputBindingDescription = 97 { 98 0u, // uint32_t binding; 99 sizeof(Vertex4RGBA), // uint32_t stride; 100 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 101 }; 102 103 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = 104 { 105 { 106 0u, // uint32_t location; 107 0u, // uint32_t binding; 108 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 109 0u, // uint32_t offset; 110 }, 111 { 112 1u, // uint32_t location; 113 0u, // uint32_t binding; 114 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 115 sizeof(Vec4), // uint32_t offset; 116 }, 117 }; 118 119 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 120 { 121 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 122 DE_NULL, // const void* pNext; 123 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 124 1u, // uint32_t vertexBindingDescriptionCount; 125 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 126 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount; 127 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 128 }; 129 130 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 131 { 132 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 133 DE_NULL, // const void* pNext; 134 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 135 topology, // VkPrimitiveTopology topology; 136 VK_FALSE, // VkBool32 primitiveRestartEnable; 137 }; 138 139 const VkViewport viewport = makeViewport( 140 0.0f, 0.0f, 141 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 142 0.0f, 1.0f); 143 144 const VkRect2D scissor = { 145 makeOffset2D(0, 0), 146 makeExtent2D(renderSize.x(), renderSize.y()), 147 }; 148 149 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 150 { 151 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 152 DE_NULL, // const void* pNext; 153 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 154 1u, // uint32_t viewportCount; 155 &viewport, // const VkViewport* pViewports; 156 1u, // uint32_t scissorCount; 157 &scissor, // const VkRect2D* pScissors; 158 }; 159 160 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 161 { 162 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 163 DE_NULL, // const void* pNext; 164 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 165 VK_FALSE, // VkBool32 depthClampEnable; 166 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 167 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 168 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 169 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 170 VK_FALSE, // VkBool32 depthBiasEnable; 171 0.0f, // float depthBiasConstantFactor; 172 0.0f, // float depthBiasClamp; 173 0.0f, // float depthBiasSlopeFactor; 174 1.0f, // float lineWidth; 175 }; 176 177 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 178 { 179 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 180 DE_NULL, // const void* pNext; 181 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 182 numSamples, // VkSampleCountFlagBits rasterizationSamples; 183 VK_FALSE, // VkBool32 sampleShadingEnable; 184 0.0f, // float minSampleShading; 185 DE_NULL, // const VkSampleMask* pSampleMask; 186 VK_FALSE, // VkBool32 alphaToCoverageEnable; 187 VK_FALSE // VkBool32 alphaToOneEnable; 188 }; 189 190 const VkStencilOpState stencilOpState = makeStencilOpState( 191 VK_STENCIL_OP_KEEP, // stencil fail 192 VK_STENCIL_OP_KEEP, // depth & stencil pass 193 VK_STENCIL_OP_KEEP, // depth only fail 194 VK_COMPARE_OP_ALWAYS, // compare op 195 0u, // compare mask 196 0u, // write mask 197 0u); // reference 198 199 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 200 { 201 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 202 DE_NULL, // const void* pNext; 203 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 204 VK_FALSE, // VkBool32 depthTestEnable; 205 VK_FALSE, // VkBool32 depthWriteEnable; 206 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 207 VK_FALSE, // VkBool32 depthBoundsTestEnable; 208 VK_FALSE, // VkBool32 stencilTestEnable; 209 stencilOpState, // VkStencilOpState front; 210 stencilOpState, // VkStencilOpState back; 211 0.0f, // float minDepthBounds; 212 1.0f, // float maxDepthBounds; 213 }; 214 215 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 216 // Number of blend attachments must equal the number of color attachments during any subpass. 217 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 218 { 219 VK_FALSE, // VkBool32 blendEnable; 220 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 221 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 222 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 223 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 224 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 225 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 226 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 227 }; 228 229 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 230 { 231 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 232 DE_NULL, // const void* pNext; 233 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 234 VK_FALSE, // VkBool32 logicOpEnable; 235 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 236 1u, // deUint32 attachmentCount; 237 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 238 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 239 }; 240 241 const VkPipelineShaderStageCreateInfo pShaderStages[] = 242 { 243 { 244 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 245 DE_NULL, // const void* pNext; 246 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 247 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 248 vertexModule, // VkShaderModule module; 249 "main", // const char* pName; 250 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 251 }, 252 { 253 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 254 DE_NULL, // const void* pNext; 255 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 256 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 257 fragmentModule, // VkShaderModule module; 258 "main", // const char* pName; 259 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 260 } 261 }; 262 263 DE_ASSERT(numSubpasses > 0u); 264 265 std::vector<VkGraphicsPipelineCreateInfo> graphicsPipelineInfos (0); 266 std::vector<VkPipeline> rawPipelines (numSubpasses, DE_NULL); 267 268 { 269 const VkPipelineCreateFlags firstPipelineFlags = (numSubpasses > 1u ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT 270 : (VkPipelineCreateFlagBits)0); 271 272 VkGraphicsPipelineCreateInfo createInfo = 273 { 274 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 275 DE_NULL, // const void* pNext; 276 firstPipelineFlags, // VkPipelineCreateFlags flags; 277 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; 278 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 279 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 280 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 281 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 282 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 283 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 284 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 285 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 286 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 287 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 288 pipelineLayout, // VkPipelineLayout layout; 289 renderPass, // VkRenderPass renderPass; 290 0u, // deUint32 subpass; 291 DE_NULL, // VkPipeline basePipelineHandle; 292 -1, // deInt32 basePipelineIndex; 293 }; 294 295 graphicsPipelineInfos.push_back(createInfo); 296 297 createInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; 298 createInfo.basePipelineIndex = 0; 299 300 for (deUint32 subpassNdx = 1u; subpassNdx < numSubpasses; ++subpassNdx) 301 { 302 createInfo.subpass = subpassNdx; 303 graphicsPipelineInfos.push_back(createInfo); 304 } 305 } 306 307 VK_CHECK(vk.createGraphicsPipelines(device, DE_NULL, static_cast<deUint32>(graphicsPipelineInfos.size()), &graphicsPipelineInfos[0], DE_NULL, &rawPipelines[0])); 308 309 std::vector<PipelineSp> pipelines; 310 311 for (std::vector<VkPipeline>::const_iterator it = rawPipelines.begin(); it != rawPipelines.end(); ++it) 312 pipelines.push_back(makeSharedPtr(Move<VkPipeline>(check<VkPipeline>(*it), Deleter<VkPipeline>(vk, device, DE_NULL)))); 313 314 return pipelines; 315} 316 317//! Make a render pass with one subpass per color attachment and one attachment per image layer. 318Move<VkRenderPass> makeMultisampleRenderPass (const DeviceInterface& vk, 319 const VkDevice device, 320 const VkFormat colorFormat, 321 const VkSampleCountFlagBits numSamples, 322 const deUint32 numLayers) 323{ 324 const VkAttachmentDescription colorAttachmentDescription = 325 { 326 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 327 colorFormat, // VkFormat format; 328 numSamples, // VkSampleCountFlagBits samples; 329 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 330 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 331 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 332 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 333 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 334 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 335 }; 336 const std::vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription); 337 338 // Create a subpass for each attachment (each attachement is a layer of an arrayed image). 339 340 std::vector<VkAttachmentReference> colorAttachmentReferences(numLayers); 341 std::vector<VkSubpassDescription> subpasses; 342 343 for (deUint32 i = 0; i < numLayers; ++i) 344 { 345 const VkAttachmentReference attachmentRef = 346 { 347 i, // deUint32 attachment; 348 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 349 }; 350 colorAttachmentReferences[i] = attachmentRef; 351 352 const VkSubpassDescription subpassDescription = 353 { 354 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 355 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 356 0u, // deUint32 inputAttachmentCount; 357 DE_NULL, // const VkAttachmentReference* pInputAttachments; 358 1u, // deUint32 colorAttachmentCount; 359 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments; 360 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 361 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 362 0u, // deUint32 preserveAttachmentCount; 363 DE_NULL // const deUint32* pPreserveAttachments; 364 }; 365 subpasses.push_back(subpassDescription); 366 } 367 368 const VkRenderPassCreateInfo renderPassInfo = 369 { 370 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 371 DE_NULL, // const void* pNext; 372 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 373 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount; 374 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; 375 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 376 &subpasses[0], // const VkSubpassDescription* pSubpasses; 377 0u, // deUint32 dependencyCount; 378 DE_NULL // const VkSubpassDependency* pDependencies; 379 }; 380 381 return createRenderPass(vk, device, &renderPassInfo); 382} 383 384//! A single-attachment, single-subpass render pass. 385Move<VkRenderPass> makeSimpleRenderPass (const DeviceInterface& vk, 386 const VkDevice device, 387 const VkFormat colorFormat) 388{ 389 const VkAttachmentDescription colorAttachmentDescription = 390 { 391 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 392 colorFormat, // VkFormat format; 393 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 394 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 395 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 396 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 397 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 398 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 399 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 400 }; 401 402 const VkAttachmentReference colorAttachmentRef = 403 { 404 0u, // deUint32 attachment; 405 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 406 }; 407 408 const VkSubpassDescription subpassDescription = 409 { 410 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 411 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 412 0u, // deUint32 inputAttachmentCount; 413 DE_NULL, // const VkAttachmentReference* pInputAttachments; 414 1u, // deUint32 colorAttachmentCount; 415 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments; 416 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 417 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 418 0u, // deUint32 preserveAttachmentCount; 419 DE_NULL // const deUint32* pPreserveAttachments; 420 }; 421 422 const VkRenderPassCreateInfo renderPassInfo = 423 { 424 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 425 DE_NULL, // const void* pNext; 426 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 427 1u, // deUint32 attachmentCount; 428 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; 429 1u, // deUint32 subpassCount; 430 &subpassDescription, // const VkSubpassDescription* pSubpasses; 431 0u, // deUint32 dependencyCount; 432 DE_NULL // const VkSubpassDependency* pDependencies; 433 }; 434 435 return createRenderPass(vk, device, &renderPassInfo); 436} 437 438Move<VkImage> makeImage (const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage) 439{ 440 const VkImageCreateInfo imageParams = 441 { 442 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 443 DE_NULL, // const void* pNext; 444 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 445 VK_IMAGE_TYPE_2D, // VkImageType imageType; 446 format, // VkFormat format; 447 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 448 1u, // deUint32 mipLevels; 449 numLayers, // deUint32 arrayLayers; 450 samples, // VkSampleCountFlagBits samples; 451 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 452 usage, // VkImageUsageFlags usage; 453 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 454 0u, // deUint32 queueFamilyIndexCount; 455 DE_NULL, // const deUint32* pQueueFamilyIndices; 456 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 457 }; 458 return createImage(vk, device, &imageParams); 459} 460 461//! Make a simplest sampler. 462Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device) 463{ 464 const VkSamplerCreateInfo samplerParams = 465 { 466 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; 467 DE_NULL, // const void* pNext; 468 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags; 469 VK_FILTER_NEAREST, // VkFilter magFilter; 470 VK_FILTER_NEAREST, // VkFilter minFilter; 471 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; 472 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU; 473 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV; 474 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW; 475 0.0f, // float mipLodBias; 476 VK_FALSE, // VkBool32 anisotropyEnable; 477 1.0f, // float maxAnisotropy; 478 VK_FALSE, // VkBool32 compareEnable; 479 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp; 480 0.0f, // float minLod; 481 0.0f, // float maxLod; 482 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor; 483 VK_FALSE, // VkBool32 unnormalizedCoordinates; 484 }; 485 return createSampler(vk, device, &samplerParams); 486} 487 488inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage) 489{ 490 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage); 491 return createBuffer(vk, device, &bufferCreateInfo); 492} 493 494inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount) 495{ 496 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount)); 497} 498 499inline VkImageSubresourceLayers makeColorSubresourceLayers (const int baseArrayLayer, const int layerCount) 500{ 501 return makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount)); 502} 503 504void checkImageFormatRequirements (const InstanceInterface& vki, 505 const VkPhysicalDevice physDevice, 506 const VkSampleCountFlagBits sampleCount, 507 const VkFormat format, 508 const VkImageUsageFlags usage) 509{ 510 VkPhysicalDeviceFeatures features; 511 vki.getPhysicalDeviceFeatures(physDevice, &features); 512 513 if (((usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) && !features.shaderStorageImageMultisample) 514 TCU_THROW(NotSupportedError, "Multisampled storage images are not supported"); 515 516 VkImageFormatProperties imageFormatProperties; 517 const VkResult imageFormatResult = vki.getPhysicalDeviceImageFormatProperties( 518 physDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, (VkImageCreateFlags)0, &imageFormatProperties); 519 520 if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED) 521 TCU_THROW(NotSupportedError, "Image format is not supported"); 522 523 if ((imageFormatProperties.sampleCounts & sampleCount) != sampleCount) 524 TCU_THROW(NotSupportedError, "Requested sample count is not supported"); 525} 526 527void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize bufferSize) 528{ 529 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(bufferSize)); 530 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize); 531} 532 533//! The default foreground color. 534inline Vec4 getPrimitiveColor (void) 535{ 536 return Vec4(1.0f, 0.0f, 0.0f, 1.0f); 537} 538 539//! Get a reference clear value based on color format. 540VkClearValue getClearValue (const VkFormat format) 541{ 542 if (isUintFormat(format) || isIntFormat(format)) 543 return makeClearValueColorU32(16, 32, 64, 96); 544 else 545 return makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f); 546} 547 548std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint) 549{ 550 std::ostringstream str; 551 if (numComponents == 1) 552 str << (isUint ? "uint" : isSint ? "int" : "float"); 553 else 554 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents; 555 556 return str.str(); 557} 558 559std::string getSamplerTypeStr (const int numLayers, const bool isUint, const bool isSint) 560{ 561 std::ostringstream str; 562 str << (isUint ? "u" : isSint ? "i" : "") << "sampler2DMS" << (numLayers > 1 ? "Array" : ""); 563 return str.str(); 564} 565 566//! Generate a gvec4 color literal. 567template<typename T> 568std::string getColorStr (const T* data, int numComponents, const bool isUint, const bool isSint) 569{ 570 const int maxIndex = 3; // 4 components max 571 572 std::ostringstream str; 573 str << (isUint ? "u" : isSint ? "i" : "") << "vec4("; 574 575 for (int i = 0; i < numComponents; ++i) 576 { 577 str << data[i] 578 << (i < maxIndex ? ", " : ""); 579 } 580 581 for (int i = numComponents; i < maxIndex + 1; ++i) 582 { 583 str << (i == maxIndex ? 1 : 0) 584 << (i < maxIndex ? ", " : ""); 585 } 586 587 str << ")"; 588 return str.str(); 589} 590 591//! Clear color literal value used by the sampling shader. 592std::string getReferenceClearColorStr (const VkFormat format, const int numComponents, const bool isUint, const bool isSint) 593{ 594 const VkClearColorValue clearColor = getClearValue(format).color; 595 if (isUint) 596 return getColorStr(clearColor.uint32, numComponents, isUint, isSint); 597 else if (isSint) 598 return getColorStr(clearColor.int32, numComponents, isUint, isSint); 599 else 600 return getColorStr(clearColor.float32, numComponents, isUint, isSint); 601} 602 603//! Primitive color literal value used by the sampling shader. 604std::string getReferencePrimitiveColorStr (int numComponents, const bool isUint, const bool isSint) 605{ 606 const Vec4 color = getPrimitiveColor(); 607 return getColorStr(color.getPtr(), numComponents, isUint, isSint); 608} 609 610inline int getNumSamples (const VkSampleCountFlagBits samples) 611{ 612 return static_cast<int>(samples); // enum bitmask actually matches the number of samples 613} 614 615//! A flat-colored shape with sharp angles to make antialiasing visible. 616std::vector<Vertex4RGBA> genTriangleVertices (void) 617{ 618 static const Vertex4RGBA data[] = 619 { 620 { 621 Vec4(-1.0f, 0.0f, 0.0f, 1.0f), 622 getPrimitiveColor(), 623 }, 624 { 625 Vec4(0.8f, 0.2f, 0.0f, 1.0f), 626 getPrimitiveColor(), 627 }, 628 { 629 Vec4(0.8f, -0.2f, 0.0f, 1.0f), 630 getPrimitiveColor(), 631 }, 632 }; 633 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data)); 634} 635 636//! A full-viewport quad. Use with TRIANGLE_STRIP topology. 637std::vector<Vertex4RGBA> genFullQuadVertices (void) 638{ 639 static const Vertex4RGBA data[] = 640 { 641 { 642 Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 643 Vec4(), // unused 644 }, 645 { 646 Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 647 Vec4(), // unused 648 }, 649 { 650 Vec4(1.0f, -1.0f, 0.0f, 1.0f), 651 Vec4(), // unused 652 }, 653 { 654 Vec4(1.0f, 1.0f, 0.0f, 1.0f), 655 Vec4(), // unused 656 }, 657 }; 658 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data)); 659} 660 661std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format) 662{ 663 const char* orderPart; 664 const char* typePart; 665 666 switch (format.order) 667 { 668 case tcu::TextureFormat::R: orderPart = "r"; break; 669 case tcu::TextureFormat::RG: orderPart = "rg"; break; 670 case tcu::TextureFormat::RGB: orderPart = "rgb"; break; 671 case tcu::TextureFormat::RGBA: orderPart = "rgba"; break; 672 673 default: 674 DE_ASSERT(false); 675 orderPart = DE_NULL; 676 } 677 678 switch (format.type) 679 { 680 case tcu::TextureFormat::FLOAT: typePart = "32f"; break; 681 case tcu::TextureFormat::HALF_FLOAT: typePart = "16f"; break; 682 683 case tcu::TextureFormat::UNSIGNED_INT32: typePart = "32ui"; break; 684 case tcu::TextureFormat::UNSIGNED_INT16: typePart = "16ui"; break; 685 case tcu::TextureFormat::UNSIGNED_INT8: typePart = "8ui"; break; 686 687 case tcu::TextureFormat::SIGNED_INT32: typePart = "32i"; break; 688 case tcu::TextureFormat::SIGNED_INT16: typePart = "16i"; break; 689 case tcu::TextureFormat::SIGNED_INT8: typePart = "8i"; break; 690 691 case tcu::TextureFormat::UNORM_INT16: typePart = "16"; break; 692 case tcu::TextureFormat::UNORM_INT8: typePart = "8"; break; 693 694 case tcu::TextureFormat::SNORM_INT16: typePart = "16_snorm"; break; 695 case tcu::TextureFormat::SNORM_INT8: typePart = "8_snorm"; break; 696 697 default: 698 DE_ASSERT(false); 699 typePart = DE_NULL; 700 } 701 702 return std::string() + orderPart + typePart; 703} 704 705std::string getShaderMultisampledImageType (const tcu::TextureFormat& format, const int numLayers) 706{ 707 const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" : 708 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" : ""; 709 710 std::ostringstream str; 711 str << formatPart << "image2DMS" << (numLayers > 1 ? "Array" : ""); 712 713 return str.str(); 714} 715 716void addSimpleVertexAndFragmentPrograms (SourceCollections& programCollection, const CaseDef caseDef) 717{ 718 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order); 719 const bool isUint = isUintFormat(caseDef.colorFormat); 720 const bool isSint = isIntFormat(caseDef.colorFormat); 721 722 // Vertex shader 723 { 724 std::ostringstream src; 725 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 726 << "\n" 727 << "layout(location = 0) in vec4 in_position;\n" 728 << "layout(location = 1) in vec4 in_color;\n" 729 << "layout(location = 0) out vec4 o_color;\n" 730 << "\n" 731 << "out gl_PerVertex {\n" 732 << " vec4 gl_Position;\n" 733 << "};\n" 734 << "\n" 735 << "void main(void)\n" 736 << "{\n" 737 << " gl_Position = in_position;\n" 738 << " o_color = in_color;\n" 739 << "}\n"; 740 741 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 742 } 743 744 // Fragment shader 745 { 746 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint); 747 748 std::ostringstream src; 749 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 750 << "\n" 751 << "layout(location = 0) in vec4 in_color;\n" 752 << "layout(location = 0) out " << colorFormat << " o_color;\n" 753 << "\n" 754 << "void main(void)\n" 755 << "{\n" 756 << " o_color = " << colorFormat << "(" // float color will be converted to int/uint here if needed 757 << (numComponents == 1 ? "in_color.r" : 758 numComponents == 2 ? "in_color.rg" : 759 numComponents == 3 ? "in_color.rgb" : "in_color") << ");\n" 760 << "}\n"; 761 762 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 763 } 764} 765 766//! Synchronously render to a multisampled color image. 767void renderMultisampledImage (Context& context, const CaseDef& caseDef, const VkImage colorImage) 768{ 769 const DeviceInterface& vk = context.getDeviceInterface(); 770 const VkDevice device = context.getDevice(); 771 const VkQueue queue = context.getUniversalQueue(); 772 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 773 Allocator& allocator = context.getDefaultAllocator(); 774 775 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 776 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 777 778 const VkRect2D renderArea = { 779 makeOffset2D(0, 0), 780 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()), 781 }; 782 783 { 784 // Create an image view (attachment) for each layer of the image 785 std::vector<ImageViewSp> colorAttachments; 786 std::vector<VkImageView> attachmentHandles; 787 for (int i = 0; i < caseDef.numLayers; ++i) 788 { 789 colorAttachments.push_back(makeSharedPtr(makeImageView( 790 vk, device, colorImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.colorFormat, makeColorSubresourceRange(i, 1)))); 791 attachmentHandles.push_back(**colorAttachments.back()); 792 } 793 794 // Vertex buffer 795 const std::vector<Vertex4RGBA> vertices = genTriangleVertices(); 796 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 797 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); 798 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible)); 799 800 { 801 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 802 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize); 803 } 804 805 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u)); 806 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u)); 807 const Unique<VkRenderPass> renderPass (makeMultisampleRenderPass (vk, device, caseDef.colorFormat, caseDef.numSamples, caseDef.numLayers)); 808 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0], 809 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()))); 810 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device)); 811 const std::vector<PipelineSp> pipelines (makeGraphicsPipelines (vk, device, caseDef.numLayers, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, 812 caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)); 813 814 beginCommandBuffer(vk, *cmdBuffer); 815 816 const std::vector<VkClearValue> clearValues(caseDef.numLayers, getClearValue(caseDef.colorFormat)); 817 818 const VkRenderPassBeginInfo renderPassBeginInfo = { 819 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 820 DE_NULL, // const void* pNext; 821 *renderPass, // VkRenderPass renderPass; 822 *framebuffer, // VkFramebuffer framebuffer; 823 renderArea, // VkRect2D renderArea; 824 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount; 825 &clearValues[0], // const VkClearValue* pClearValues; 826 }; 827 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 828 829 { 830 const VkDeviceSize vertexBufferOffset = 0ull; 831 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 832 } 833 834 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx) 835 { 836 if (layerNdx != 0) 837 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 838 839 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]); 840 841 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u); 842 } 843 844 vk.cmdEndRenderPass(*cmdBuffer); 845 846 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 847 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 848 } 849} 850 851namespace SampledImage 852{ 853 854void initPrograms (SourceCollections& programCollection, const CaseDef caseDef) 855{ 856 // Pass 1: Render to texture 857 858 addSimpleVertexAndFragmentPrograms(programCollection, caseDef); 859 860 // Pass 2: Sample texture 861 862 // Vertex shader 863 { 864 std::ostringstream src; 865 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 866 << "\n" 867 << "layout(location = 0) in vec4 in_position;\n" 868 << "\n" 869 << "out gl_PerVertex {\n" 870 << " vec4 gl_Position;\n" 871 << "};\n" 872 << "\n" 873 << "void main(void)\n" 874 << "{\n" 875 << " gl_Position = in_position;\n" 876 << "}\n"; 877 878 programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str()); 879 } 880 881 // Fragment shader 882 { 883 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order); 884 const bool isUint = isUintFormat(caseDef.colorFormat); 885 const bool isSint = isIntFormat(caseDef.colorFormat); 886 const std::string texelFormatStr = (isUint ? "uvec4" : isSint ? "ivec4" : "vec4"); 887 const std::string refClearColor = getReferenceClearColorStr(caseDef.colorFormat, numComponents, isUint, isSint); 888 const std::string refPrimitiveColor = getReferencePrimitiveColorStr(numComponents, isUint, isSint); 889 const std::string samplerTypeStr = getSamplerTypeStr(caseDef.numLayers, isUint, isSint); 890 891 std::ostringstream src; 892 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 893 << "\n" 894 << "layout(location = 0) out int o_status;\n" 895 << "\n" 896 << "layout(set = 0, binding = 0) uniform " << samplerTypeStr << " colorTexture;\n" 897 << "\n" 898 << "void main(void)\n" 899 << "{\n" 900 << " int checksum = 0;\n" 901 << "\n"; 902 903 if (caseDef.numLayers == 1) 904 src << " for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n" 905 << " " << texelFormatStr << " color = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), sampleNdx);\n" 906 << " if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n" 907 << " ++checksum;\n" 908 << " }\n"; 909 else 910 src << " for (int layerNdx = 0; layerNdx < " << caseDef.numLayers << "; ++layerNdx)\n" 911 << " for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n" 912 << " " << texelFormatStr << " color = texelFetch(colorTexture, ivec3(gl_FragCoord.xy, layerNdx), sampleNdx);\n" 913 << " if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n" 914 << " ++checksum;\n" 915 << " }\n"; 916 917 src << "\n" 918 << " o_status = checksum;\n" 919 << "}\n"; 920 921 programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str()); 922 } 923} 924 925tcu::TestStatus test (Context& context, const CaseDef caseDef) 926{ 927 const DeviceInterface& vk = context.getDeviceInterface(); 928 const InstanceInterface& vki = context.getInstanceInterface(); 929 const VkDevice device = context.getDevice(); 930 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 931 const VkQueue queue = context.getUniversalQueue(); 932 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 933 Allocator& allocator = context.getDefaultAllocator(); 934 935 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 936 937 checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, colorImageUsage); 938 939 { 940 tcu::TestLog& log = context.getTestContext().getLog(); 941 log << tcu::LogSection("Description", "") 942 << tcu::TestLog::Message << "Rendering to a multisampled image. Expecting all samples to be either a clear color or a primitive color." << tcu::TestLog::EndMessage 943 << tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage 944 << tcu::TestLog::EndSection; 945 } 946 947 // Multisampled color image 948 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage)); 949 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any)); 950 951 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 952 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 953 954 const VkRect2D renderArea = { 955 makeOffset2D(0, 0), 956 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()), 957 }; 958 959 // Step 1: Render to texture 960 { 961 renderMultisampledImage(context, caseDef, *colorImage); 962 } 963 964 // Step 2: Sample texture 965 { 966 // Color image view 967 const VkImageViewType colorImageViewType = (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY); 968 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers))); 969 const Unique<VkSampler> colorSampler (makeSampler(vk, device)); 970 971 // Checksum image 972 const VkFormat checksumFormat = VK_FORMAT_R32_SINT; 973 const Unique<VkImage> checksumImage (makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT, 974 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)); 975 const UniquePtr<Allocation> checksumImageAlloc (bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any)); 976 const Unique<VkImageView> checksumImageView (makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1))); 977 978 // Checksum buffer (for host reading) 979 const VkDeviceSize checksumBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat)); 980 const Unique<VkBuffer> checksumBuffer (makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 981 const UniquePtr<Allocation> checksumBufferAlloc (bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible)); 982 983 zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize); 984 985 // Vertex buffer 986 const std::vector<Vertex4RGBA> vertices = genFullQuadVertices(); 987 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices); 988 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); 989 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible)); 990 991 { 992 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize)); 993 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize); 994 } 995 996 // Descriptors 997 // \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan. 998 999 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder() 1000 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get()) 1001 .build(vk, device)); 1002 1003 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder() 1004 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 1005 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 1006 1007 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 1008 const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 1009 1010 DescriptorSetUpdateBuilder() 1011 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo) 1012 .update(vk, device); 1013 1014 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("sample_vert"), 0u)); 1015 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("sample_frag"), 0u)); 1016 const Unique<VkRenderPass> renderPass (makeSimpleRenderPass (vk, device, checksumFormat)); 1017 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 1u, &checksumImageView.get(), 1018 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()))); 1019 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout)); 1020 const std::vector<PipelineSp> pipelines (makeGraphicsPipelines (vk, device, 1u, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, 1021 caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)); 1022 1023 beginCommandBuffer(vk, *cmdBuffer); 1024 1025 // Prepare for sampling in the fragment shader 1026 { 1027 const VkImageMemoryBarrier barriers[] = 1028 { 1029 { 1030 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1031 DE_NULL, // const void* pNext; 1032 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; 1033 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags inputMask; 1034 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 1035 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout; 1036 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1037 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1038 *colorImage, // VkImage image; 1039 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange; 1040 }, 1041 }; 1042 1043 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1044 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 1045 } 1046 1047 const VkClearValue clearValue = makeClearValueColorU32(0u, 0u, 0u, 0u); 1048 1049 const VkRenderPassBeginInfo renderPassBeginInfo = { 1050 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 1051 DE_NULL, // const void* pNext; 1052 *renderPass, // VkRenderPass renderPass; 1053 *framebuffer, // VkFramebuffer framebuffer; 1054 renderArea, // VkRect2D renderArea; 1055 1u, // uint32_t clearValueCount; 1056 &clearValue, // const VkClearValue* pClearValues; 1057 }; 1058 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 1059 1060 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines.back()); 1061 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 1062 { 1063 const VkDeviceSize vertexBufferOffset = 0ull; 1064 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 1065 } 1066 1067 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u); 1068 vk.cmdEndRenderPass(*cmdBuffer); 1069 1070 // Prepare checksum image for copy 1071 { 1072 const VkImageMemoryBarrier barriers[] = 1073 { 1074 { 1075 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1076 DE_NULL, // const void* pNext; 1077 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; 1078 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; 1079 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 1080 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 1081 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1082 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1083 *checksumImage, // VkImage image; 1084 makeColorSubresourceRange(0, 1), // VkImageSubresourceRange subresourceRange; 1085 }, 1086 }; 1087 1088 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1089 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 1090 } 1091 // Checksum image -> host buffer 1092 { 1093 const VkBufferImageCopy region = 1094 { 1095 0ull, // VkDeviceSize bufferOffset; 1096 0u, // uint32_t bufferRowLength; 1097 0u, // uint32_t bufferImageHeight; 1098 makeColorSubresourceLayers(0, 1), // VkImageSubresourceLayers imageSubresource; 1099 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 1100 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D imageExtent; 1101 }; 1102 1103 vk.cmdCopyImageToBuffer(*cmdBuffer, *checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *checksumBuffer, 1u, ®ion); 1104 } 1105 // Buffer write barrier 1106 { 1107 const VkBufferMemoryBarrier barriers[] = 1108 { 1109 { 1110 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 1111 DE_NULL, // const void* pNext; 1112 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1113 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 1114 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1115 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1116 *checksumBuffer, // VkBuffer buffer; 1117 0ull, // VkDeviceSize offset; 1118 checksumBufferSize, // VkDeviceSize size; 1119 }, 1120 }; 1121 1122 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1123 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u); 1124 } 1125 1126 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1127 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1128 1129 // Verify result 1130 1131 { 1132 invalidateMappedMemoryRange(vk, device, checksumBufferAlloc->getMemory(), 0ull, checksumBufferSize); 1133 1134 const tcu::ConstPixelBufferAccess access(mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr()); 1135 const int numExpectedChecksum = getNumSamples(caseDef.numSamples) * caseDef.numLayers; 1136 1137 for (int y = 0; y < caseDef.renderSize.y(); ++y) 1138 for (int x = 0; x < caseDef.renderSize.x(); ++x) 1139 { 1140 if (access.getPixelInt(x, y).x() != numExpectedChecksum) 1141 return tcu::TestStatus::fail("Some samples have incorrect color"); 1142 } 1143 } 1144 } 1145 1146 return tcu::TestStatus::pass("OK"); 1147} 1148 1149} // SampledImage ns 1150 1151namespace StorageImage 1152{ 1153 1154void initPrograms (SourceCollections& programCollection, const CaseDef caseDef) 1155{ 1156 // Vertex & fragment 1157 1158 addSimpleVertexAndFragmentPrograms(programCollection, caseDef); 1159 1160 // Compute 1161 { 1162 const std::string imageTypeStr = getShaderMultisampledImageType(mapVkFormat(caseDef.colorFormat), caseDef.numLayers); 1163 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(caseDef.colorFormat)); 1164 const std::string signednessPrefix = isUintFormat(caseDef.colorFormat) ? "u" : isIntFormat(caseDef.colorFormat) ? "i" : ""; 1165 const std::string gvec4Expr = signednessPrefix + "vec4"; 1166 const std::string texelCoordStr = (caseDef.numLayers == 1 ? "ivec2(gx, gy)" : "ivec3(gx, gy, gz)"); 1167 1168 std::ostringstream src; 1169 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1170 << "layout(local_size_x = 1) in;\n" 1171 << "layout(set = 0, binding = 0, " << formatQualifierStr << ") uniform " << imageTypeStr << " u_msImage;\n" 1172 << "\n" 1173 << "void main(void)\n" 1174 << "{\n" 1175 << " int gx = int(gl_GlobalInvocationID.x);\n" 1176 << " int gy = int(gl_GlobalInvocationID.y);\n" 1177 << " int gz = int(gl_GlobalInvocationID.z);\n" 1178 << "\n" 1179 << " " << gvec4Expr << " prevColor = imageLoad(u_msImage, " << texelCoordStr << ", 0);\n" 1180 << " for (int sampleNdx = 1; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n" 1181 << " " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n" 1182 << " imageStore(u_msImage, " << texelCoordStr <<", sampleNdx, prevColor);\n" 1183 << " prevColor = color;\n" 1184 << " }\n" 1185 << " imageStore(u_msImage, " << texelCoordStr <<", 0, prevColor);\n" 1186 << "}\n"; 1187 1188 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str()); 1189 } 1190} 1191 1192//! Render a MS image, resolve it, and copy result to resolveBuffer. 1193void renderAndResolve (Context& context, const CaseDef& caseDef, const VkBuffer resolveBuffer, const bool useComputePass) 1194{ 1195 const DeviceInterface& vk = context.getDeviceInterface(); 1196 const VkDevice device = context.getDevice(); 1197 const VkQueue queue = context.getUniversalQueue(); 1198 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 1199 Allocator& allocator = context.getDefaultAllocator(); 1200 1201 // Multisampled color image 1202 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, 1203 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)); 1204 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any)); 1205 1206 const Unique<VkImage> resolveImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, VK_SAMPLE_COUNT_1_BIT, 1207 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)); 1208 const UniquePtr<Allocation> resolveImageAlloc (bindImage(vk, device, allocator, *resolveImage, MemoryRequirement::Any)); 1209 1210 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 1211 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1212 1213 // Working image barrier, we change it based on which rendering stages were executed so far. 1214 VkImageMemoryBarrier colorImageBarrier = 1215 { 1216 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1217 DE_NULL, // const void* pNext; 1218 (VkAccessFlags)0, // VkAccessFlags outputMask; 1219 (VkAccessFlags)0, // VkAccessFlags inputMask; 1220 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1221 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout newLayout; 1222 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1223 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1224 *colorImage, // VkImage image; 1225 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange; 1226 }; 1227 1228 // Pass 1: Render an image 1229 { 1230 renderMultisampledImage(context, caseDef, *colorImage); 1231 1232 colorImageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 1233 colorImageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1234 } 1235 1236 // Pass 2: Compute shader 1237 if (useComputePass) 1238 { 1239 // Descriptors 1240 1241 Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder() 1242 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) 1243 .build(vk, device)); 1244 1245 Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder() 1246 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u) 1247 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 1248 1249 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, 1250 (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY), 1251 caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers))); 1252 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 1253 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_GENERAL); 1254 1255 DescriptorSetUpdateBuilder() 1256 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo) 1257 .update(vk, device); 1258 1259 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout)); 1260 const Unique<VkShaderModule> shaderModule (createShaderModule (vk, device, context.getBinaryCollection().get("comp"), 0)); 1261 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL)); 1262 1263 beginCommandBuffer(vk, *cmdBuffer); 1264 1265 // Image layout for load/stores 1266 { 1267 colorImageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; 1268 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; 1269 1270 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 1271 0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier); 1272 1273 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask; 1274 colorImageBarrier.oldLayout = colorImageBarrier.newLayout; 1275 } 1276 // Dispatch 1277 { 1278 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 1279 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 1280 vk.cmdDispatch(*cmdBuffer, caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers); 1281 } 1282 1283 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1284 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1285 } 1286 1287 // Resolve and verify the image 1288 { 1289 beginCommandBuffer(vk, *cmdBuffer); 1290 1291 // Prepare for resolve 1292 { 1293 colorImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 1294 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; 1295 1296 const VkImageMemoryBarrier barriers[] = 1297 { 1298 colorImageBarrier, 1299 { 1300 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1301 DE_NULL, // const void* pNext; 1302 (VkAccessFlags)0, // VkAccessFlags outputMask; 1303 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags inputMask; 1304 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1305 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout; 1306 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1307 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1308 *resolveImage, // VkImage image; 1309 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange; 1310 }, 1311 }; 1312 1313 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1314 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 1315 1316 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask; 1317 colorImageBarrier.oldLayout = colorImageBarrier.newLayout; 1318 } 1319 // Resolve the image 1320 { 1321 const VkImageResolve resolveRegion = 1322 { 1323 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource; 1324 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset; 1325 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource; 1326 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset; 1327 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D extent; 1328 }; 1329 1330 vk.cmdResolveImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &resolveRegion); 1331 } 1332 // Prepare resolve image for copy 1333 { 1334 const VkImageMemoryBarrier barriers[] = 1335 { 1336 { 1337 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1338 DE_NULL, // const void* pNext; 1339 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags outputMask; 1340 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; 1341 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout; 1342 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 1343 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1344 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; 1345 *resolveImage, // VkImage image; 1346 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange; 1347 }, 1348 }; 1349 1350 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1351 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 1352 } 1353 // Copy resolved image to host-readable buffer 1354 { 1355 const VkBufferImageCopy copyRegion = 1356 { 1357 0ull, // VkDeviceSize bufferOffset; 1358 0u, // uint32_t bufferRowLength; 1359 0u, // uint32_t bufferImageHeight; 1360 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource; 1361 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 1362 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D imageExtent; 1363 }; 1364 1365 vk.cmdCopyImageToBuffer(*cmdBuffer, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resolveBuffer, 1u, ©Region); 1366 } 1367 1368 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1369 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 1370 } 1371} 1372 1373//! Exact image compare, but allow for some error when color format is integer. 1374bool compareImages (tcu::TestLog& log, const CaseDef& caseDef, const tcu::ConstPixelBufferAccess layeredReferenceImage, const tcu::ConstPixelBufferAccess layeredActualImage) 1375{ 1376 DE_ASSERT(caseDef.numSamples > 1); 1377 1378 const Vec4 goodColor = Vec4(0.0f, 1.0f, 0.0f, 1.0f); 1379 const Vec4 badColor = Vec4(1.0f, 0.0f, 0.0f, 1.0f); 1380 const bool isAnyIntFormat = isIntFormat(caseDef.colorFormat) || isUintFormat(caseDef.colorFormat); 1381 1382 // There should be no mismatched pixels for non-integer formats. Otherwise we may get a wrong color in a location where sample coverage isn't exactly 0 or 1. 1383 const int badPixelTolerance = (isAnyIntFormat ? 2 * caseDef.renderSize.x() : 0); 1384 int goodLayers = 0; 1385 1386 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx) 1387 { 1388 const tcu::ConstPixelBufferAccess referenceImage = tcu::getSubregion(layeredReferenceImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1); 1389 const tcu::ConstPixelBufferAccess actualImage = tcu::getSubregion(layeredActualImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1); 1390 const std::string imageName = "color layer " + de::toString(layerNdx); 1391 1392 tcu::TextureLevel errorMaskStorage (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), caseDef.renderSize.x(), caseDef.renderSize.y()); 1393 tcu::PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 1394 int numBadPixels = 0; 1395 1396 for (int y = 0; y < caseDef.renderSize.y(); ++y) 1397 for (int x = 0; x < caseDef.renderSize.x(); ++x) 1398 { 1399 if (isAnyIntFormat && (referenceImage.getPixelInt(x, y) == actualImage.getPixelInt(x, y))) 1400 errorMask.setPixel(goodColor, x, y); 1401 else if (referenceImage.getPixel(x, y) == actualImage.getPixel(x, y)) 1402 errorMask.setPixel(goodColor, x, y); 1403 else 1404 { 1405 ++numBadPixels; 1406 errorMask.setPixel(badColor, x, y); 1407 } 1408 } 1409 1410 if (numBadPixels <= badPixelTolerance) 1411 { 1412 ++goodLayers; 1413 1414 log << tcu::TestLog::ImageSet(imageName, imageName) 1415 << tcu::TestLog::Image("Result", "Result", actualImage) 1416 << tcu::TestLog::EndImageSet; 1417 } 1418 else 1419 { 1420 log << tcu::TestLog::ImageSet(imageName, imageName) 1421 << tcu::TestLog::Image("Result", "Result", actualImage) 1422 << tcu::TestLog::Image("Reference", "Reference", referenceImage) 1423 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask) 1424 << tcu::TestLog::EndImageSet; 1425 } 1426 } 1427 1428 if (goodLayers == caseDef.numLayers) 1429 { 1430 log << tcu::TestLog::Message << "All rendered images are correct." << tcu::TestLog::EndMessage; 1431 return true; 1432 } 1433 else 1434 { 1435 log << tcu::TestLog::Message << "FAILED: Some rendered images were incorrect." << tcu::TestLog::EndMessage; 1436 return false; 1437 } 1438} 1439 1440tcu::TestStatus test (Context& context, const CaseDef caseDef) 1441{ 1442 const DeviceInterface& vk = context.getDeviceInterface(); 1443 const InstanceInterface& vki = context.getInstanceInterface(); 1444 const VkDevice device = context.getDevice(); 1445 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 1446 Allocator& allocator = context.getDefaultAllocator(); 1447 1448 checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT); 1449 1450 { 1451 tcu::TestLog& log = context.getTestContext().getLog(); 1452 log << tcu::LogSection("Description", "") 1453 << tcu::TestLog::Message << "Rendering to a multisampled image. Image will be processed with a compute shader using OpImageRead and OpImageWrite." << tcu::TestLog::EndMessage 1454 << tcu::TestLog::Message << "Expecting the processed image to be roughly the same as the input image (deviation may occur for integer formats)." << tcu::TestLog::EndMessage 1455 << tcu::TestLog::EndSection; 1456 } 1457 1458 // Host-readable buffer 1459 const VkDeviceSize resolveBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)); 1460 const Unique<VkBuffer> resolveImageOneBuffer (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 1461 const UniquePtr<Allocation> resolveImageOneBufferAlloc (bindBuffer(vk, device, allocator, *resolveImageOneBuffer, MemoryRequirement::HostVisible)); 1462 const Unique<VkBuffer> resolveImageTwoBuffer (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 1463 const UniquePtr<Allocation> resolveImageTwoBufferAlloc (bindBuffer(vk, device, allocator, *resolveImageTwoBuffer, MemoryRequirement::HostVisible)); 1464 1465 zeroBuffer(vk, device, *resolveImageOneBufferAlloc, resolveBufferSize); 1466 zeroBuffer(vk, device, *resolveImageTwoBufferAlloc, resolveBufferSize); 1467 1468 // Render: repeat the same rendering twice to avoid non-essential API calls and layout transitions (e.g. copy). 1469 { 1470 renderAndResolve(context, caseDef, *resolveImageOneBuffer, false); // Pass 1: render a basic multisampled image 1471 renderAndResolve(context, caseDef, *resolveImageTwoBuffer, true); // Pass 2: the same but altered with a compute shader 1472 } 1473 1474 // Verify 1475 { 1476 invalidateMappedMemoryRange(vk, device, resolveImageOneBufferAlloc->getMemory(), resolveImageOneBufferAlloc->getOffset(), resolveBufferSize); 1477 invalidateMappedMemoryRange(vk, device, resolveImageTwoBufferAlloc->getMemory(), resolveImageTwoBufferAlloc->getOffset(), resolveBufferSize); 1478 1479 const tcu::PixelBufferAccess layeredImageOne (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageOneBufferAlloc->getHostPtr()); 1480 const tcu::ConstPixelBufferAccess layeredImageTwo (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageTwoBufferAlloc->getHostPtr()); 1481 1482 // Check all layers 1483 if (!compareImages(context.getTestContext().getLog(), caseDef, layeredImageOne, layeredImageTwo)) 1484 return tcu::TestStatus::fail("Rendered images are not correct"); 1485 } 1486 1487 return tcu::TestStatus::pass("OK"); 1488} 1489 1490} // StorageImage ns 1491 1492std::string getSizeLayerString (const IVec2& size, const int numLayers) 1493{ 1494 std::ostringstream str; 1495 str << size.x() << "x" << size.y() << "_" << numLayers; 1496 return str.str(); 1497} 1498 1499std::string getFormatString (const VkFormat format) 1500{ 1501 std::string name(getFormatName(format)); 1502 return de::toLower(name.substr(10)); 1503} 1504 1505void addTestCasesWithFunctions (tcu::TestCaseGroup* group, 1506 FunctionPrograms1<CaseDef>::Function initPrograms, 1507 FunctionInstance1<CaseDef>::Function testFunc) 1508{ 1509 const IVec2 size[] = 1510 { 1511 IVec2(64, 64), 1512 IVec2(79, 31), 1513 }; 1514 const int numLayers[] = 1515 { 1516 1, 4 1517 }; 1518 const VkSampleCountFlagBits samples[] = 1519 { 1520 VK_SAMPLE_COUNT_2_BIT, 1521 VK_SAMPLE_COUNT_4_BIT, 1522 VK_SAMPLE_COUNT_8_BIT, 1523 VK_SAMPLE_COUNT_16_BIT, 1524 VK_SAMPLE_COUNT_32_BIT, 1525 VK_SAMPLE_COUNT_64_BIT, 1526 }; 1527 const VkFormat format[] = 1528 { 1529 VK_FORMAT_R8G8B8A8_UNORM, 1530 VK_FORMAT_R32_UINT, 1531 VK_FORMAT_R16G16_SINT, 1532 VK_FORMAT_R32G32B32A32_SFLOAT, 1533 }; 1534 1535 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(size); ++sizeNdx) 1536 for (int layerNdx = 0; layerNdx < DE_LENGTH_OF_ARRAY(numLayers); ++layerNdx) 1537 { 1538 MovePtr<tcu::TestCaseGroup> sizeLayerGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeLayerString(size[sizeNdx], numLayers[layerNdx]).c_str(), "")); 1539 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx) 1540 { 1541 MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str(), "")); 1542 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx) 1543 { 1544 std::ostringstream caseName; 1545 caseName << "samples_" << getNumSamples(samples[samplesNdx]); 1546 1547 const CaseDef caseDef = 1548 { 1549 size[sizeNdx], // IVec2 renderSize; 1550 numLayers[layerNdx], // int numLayers; 1551 format[formatNdx], // VkFormat colorFormat; 1552 samples[samplesNdx], // VkSampleCountFlagBits numSamples; 1553 }; 1554 1555 addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), "", initPrograms, testFunc, caseDef); 1556 } 1557 sizeLayerGroup->addChild(formatGroup.release()); 1558 } 1559 group->addChild(sizeLayerGroup.release()); 1560 } 1561} 1562 1563void createSampledImageTestsInGroup (tcu::TestCaseGroup* group) 1564{ 1565 addTestCasesWithFunctions(group, SampledImage::initPrograms, SampledImage::test); 1566} 1567 1568void createStorageImageTestsInGroup (tcu::TestCaseGroup* group) 1569{ 1570 addTestCasesWithFunctions(group, StorageImage::initPrograms, StorageImage::test); 1571} 1572 1573} // anonymous ns 1574 1575//! Render to a multisampled image and sample from it in a fragment shader. 1576tcu::TestCaseGroup* createMultisampleSampledImageTests (tcu::TestContext& testCtx) 1577{ 1578 return createTestGroup(testCtx, "sampled_image", "Multisampled image direct sample access", createSampledImageTestsInGroup); 1579} 1580 1581//! Render to a multisampled image and access it with load/stores in a compute shader. 1582tcu::TestCaseGroup* createMultisampleStorageImageTests (tcu::TestContext& testCtx) 1583{ 1584 return createTestGroup(testCtx, "storage_image", "Multisampled image draw and read/write in compute shader", createStorageImageTestsInGroup); 1585} 1586 1587} // pipeline 1588} // vkt 1589