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