1/*------------------------------------------------------------------------ 2* Vulkan Conformance Tests 3* ------------------------ 4* 5* Copyright (c) 2016 The Khronos Group Inc. 6* Copyright (c) 2023 LunarG, Inc. 7* Copyright (c) 2023 Nintendo 8* 9* Licensed under the Apache License, Version 2.0 (the "License"); 10* you may not use this file except in compliance with the License. 11* You may obtain a copy of the License at 12* 13* http://www.apache.org/licenses/LICENSE-2.0 14* 15* Unless required by applicable law or agreed to in writing, software 16* distributed under the License is distributed on an "AS IS" BASIS, 17* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18* See the License for the specific language governing permissions and 19* limitations under the License. 20* 21*//* 22* \file vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp 23* \brief Base class for tests that check results of multisample resolve 24* and/or values of individual samples 25*//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp" 28#include "vktPipelineMakeUtil.hpp" 29#include "vkBarrierUtil.hpp" 30#include "vkBuilderUtil.hpp" 31#include "vkQueryUtil.hpp" 32#include "vkTypeUtil.hpp" 33#include "vkCmdUtil.hpp" 34#include "vkObjUtil.hpp" 35#include "vkBufferWithMemory.hpp" 36#include "vkImageWithMemory.hpp" 37#include "tcuTestLog.hpp" 38#include <vector> 39 40namespace vkt 41{ 42namespace pipeline 43{ 44namespace multisample 45{ 46 47using namespace vk; 48 49void MSCaseBaseResolveAndPerSampleFetch::initPrograms (vk::SourceCollections& programCollection) const 50{ 51 // Create vertex shader 52 std::ostringstream vs; 53 54 vs << "#version 440\n" 55 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 56 << "\n" 57 << "out gl_PerVertex {\n" 58 << " vec4 gl_Position;\n" 59 << "};\n" 60 << "void main (void)\n" 61 << "{\n" 62 << " gl_Position = vs_in_position_ndc;\n" 63 << "}\n"; 64 65 programCollection.glslSources.add("per_sample_fetch_vs") << glu::VertexSource(vs.str()); 66 67 // Create fragment shader 68 std::ostringstream fs; 69 70 fs << "#version 440\n" 71 << "\n" 72 << "layout(location = 0) out vec4 fs_out_color;\n" 73 << "\n" 74 << "layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n" 75 << "\n" 76 << "layout(set = 0, binding = 1, std140) uniform SampleBlock {\n" 77 << " int sampleNdx;\n" 78 << "};\n" 79 << "void main (void)\n" 80 << "{\n" 81 << " fs_out_color = subpassLoad(imageMS, sampleNdx);\n" 82 << "}\n"; 83 84 programCollection.glslSources.add("per_sample_fetch_fs") << glu::FragmentSource(fs.str()); 85} 86 87MSInstanceBaseResolveAndPerSampleFetch::MSInstanceBaseResolveAndPerSampleFetch (Context& context, const ImageMSParams& imageMSParams) 88 : MultisampleInstanceBase(context, imageMSParams) {} 89 90VkPipelineMultisampleStateCreateInfo MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const 91{ 92 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = 93 { 94 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 95 DE_NULL, // const void* pNext; 96 (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; 97 imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples; 98 VK_TRUE, // VkBool32 sampleShadingEnable; 99 imageMSParams.shadingRate, // float minSampleShading; 100 DE_NULL, // const VkSampleMask* pSampleMask; 101 VK_FALSE, // VkBool32 alphaToCoverageEnable; 102 VK_FALSE, // VkBool32 alphaToOneEnable; 103 }; 104 105 return multisampleStateInfo; 106} 107 108const VkDescriptorSetLayout* MSInstanceBaseResolveAndPerSampleFetch::createMSPassDescSetLayout(const ImageMSParams& imageMSParams) 109{ 110 DE_UNREF(imageMSParams); 111 112 return DE_NULL; 113} 114 115const VkDescriptorSet* MSInstanceBaseResolveAndPerSampleFetch::createMSPassDescSet(const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout) 116{ 117 DE_UNREF(imageMSParams); 118 DE_UNREF(descSetLayout); 119 120 return DE_NULL; 121} 122 123tcu::TestStatus MSInstanceBaseResolveAndPerSampleFetch::iterate (void) 124{ 125 const InstanceInterface& instance = m_context.getInstanceInterface(); 126 const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); 127 const VkDevice device = m_context.getDevice(); 128 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 129 Allocator& allocator = m_context.getDefaultAllocator(); 130 const VkQueue queue = m_context.getUniversalQueue(); 131 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 132 133 VkImageCreateInfo imageMSInfo; 134 VkImageCreateInfo imageRSInfo; 135 const deUint32 firstSubpassAttachmentsCount = 2u; 136 137 // Check if image size does not exceed device limits 138 validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize); 139 140 // Check if device supports image format as color attachment 141 validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); 142 143 imageMSInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 144 imageMSInfo.pNext = DE_NULL; 145 imageMSInfo.flags = 0u; 146 imageMSInfo.imageType = mapImageType(m_imageType); 147 imageMSInfo.format = mapTextureFormat(m_imageFormat); 148 imageMSInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize)); 149 imageMSInfo.arrayLayers = getNumLayers(m_imageType, m_imageMSParams.imageSize); 150 imageMSInfo.mipLevels = 1u; 151 imageMSInfo.samples = m_imageMSParams.numSamples; 152 imageMSInfo.tiling = VK_IMAGE_TILING_OPTIMAL; 153 imageMSInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 154 imageMSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 155 imageMSInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 156 imageMSInfo.queueFamilyIndexCount = 0u; 157 imageMSInfo.pQueueFamilyIndices = DE_NULL; 158 159 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY) 160 { 161 imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; 162 } 163 164 validateImageInfo(instance, physicalDevice, imageMSInfo); 165 166 const de::UniquePtr<ImageWithMemory> imageMS(new ImageWithMemory(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any)); 167 168 imageRSInfo = imageMSInfo; 169 imageRSInfo.samples = VK_SAMPLE_COUNT_1_BIT; 170 imageRSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 171 172 validateImageInfo(instance, physicalDevice, imageRSInfo); 173 174 const de::UniquePtr<ImageWithMemory> imageRS(new ImageWithMemory(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any)); 175 176 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 177 178 std::vector<de::SharedPtr<ImageWithMemory> > imagesPerSampleVec(numSamples); 179 180 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 181 { 182 imagesPerSampleVec[sampleNdx] = de::SharedPtr<ImageWithMemory>(new ImageWithMemory(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any)); 183 } 184 185 // Create render pass 186 std::vector<VkAttachmentDescription> attachments(firstSubpassAttachmentsCount + numSamples); 187 188 { 189 const VkAttachmentDescription attachmentMSDesc = 190 { 191 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; 192 imageMSInfo.format, // VkFormat format; 193 imageMSInfo.samples, // VkSampleCountFlagBits samples; 194 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 195 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 196 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 197 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 198 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 199 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout; 200 }; 201 202 attachments[0] = attachmentMSDesc; 203 204 const VkAttachmentDescription attachmentRSDesc = 205 { 206 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags; 207 imageRSInfo.format, // VkFormat format; 208 imageRSInfo.samples, // VkSampleCountFlagBits samples; 209 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 210 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 211 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 212 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 213 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 214 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; 215 }; 216 217 attachments[1] = attachmentRSDesc; 218 219 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 220 { 221 attachments[firstSubpassAttachmentsCount + sampleNdx] = attachmentRSDesc; 222 } 223 } 224 225 const VkAttachmentReference attachmentMSColorRef = 226 { 227 0u, // deUint32 attachment; 228 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 229 }; 230 231 const VkAttachmentReference attachmentMSInputRef = 232 { 233 0u, // deUint32 attachment; 234 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout layout; 235 }; 236 237 const VkAttachmentReference attachmentRSColorRef = 238 { 239 1u, // deUint32 attachment; 240 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 241 }; 242 243 std::vector<VkAttachmentReference> perSampleAttachmentRef(numSamples); 244 245 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 246 { 247 const VkAttachmentReference attachmentRef = 248 { 249 firstSubpassAttachmentsCount + sampleNdx, // deUint32 attachment; 250 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 251 }; 252 253 perSampleAttachmentRef[sampleNdx] = attachmentRef; 254 } 255 256 std::vector<deUint32> preserveAttachments(1u + numSamples); 257 258 for (deUint32 attachNdx = 0u; attachNdx < 1u + numSamples; ++attachNdx) 259 { 260 preserveAttachments[attachNdx] = 1u + attachNdx; 261 } 262 263 std::vector<VkSubpassDescription> subpasses(1u + numSamples); 264 std::vector<VkSubpassDependency> subpassDependencies; 265 266 const VkSubpassDescription firstSubpassDesc = 267 { 268 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags; 269 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 270 0u, // deUint32 inputAttachmentCount; 271 DE_NULL, // const VkAttachmentReference* pInputAttachments; 272 1u, // deUint32 colorAttachmentCount; 273 &attachmentMSColorRef, // const VkAttachmentReference* pColorAttachments; 274 &attachmentRSColorRef, // const VkAttachmentReference* pResolveAttachments; 275 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 276 0u, // deUint32 preserveAttachmentCount; 277 DE_NULL // const deUint32* pPreserveAttachments; 278 }; 279 280 subpasses[0] = firstSubpassDesc; 281 282 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 283 { 284 const VkSubpassDescription subpassDesc = 285 { 286 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags; 287 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 288 1u, // deUint32 inputAttachmentCount; 289 &attachmentMSInputRef, // const VkAttachmentReference* pInputAttachments; 290 1u, // deUint32 colorAttachmentCount; 291 &perSampleAttachmentRef[sampleNdx], // const VkAttachmentReference* pColorAttachments; 292 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 293 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 294 1u + sampleNdx, // deUint32 preserveAttachmentCount; 295 dataPointer(preserveAttachments) // const deUint32* pPreserveAttachments; 296 }; 297 298 subpasses[1u + sampleNdx] = subpassDesc; 299 300 if (sampleNdx == 0u) 301 { 302 // The second subpass will be in charge of transitioning the multisample attachment from 303 // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. 304 const VkSubpassDependency subpassDependency = 305 { 306 0u, // uint32_t srcSubpass; 307 1u + sampleNdx, // uint32_t dstSubpass; 308 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask; 309 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask; 310 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 311 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; 312 0u, // VkDependencyFlags dependencyFlags; 313 }; 314 315 subpassDependencies.push_back(subpassDependency); 316 } 317 else 318 { 319 // Make sure subpass reads are in order. This serializes subpasses to make sure there are no layout transition hazards 320 // in the multisample image, from VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 321 // caused by parallel execution of several subpasses. 322 const VkSubpassDependency readDependency = 323 { 324 sampleNdx, // uint32_t srcSubpass; 325 1u + sampleNdx, // uint32_t dstSubpass; 326 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags srcStageMask; 327 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask; 328 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags srcAccessMask; 329 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; 330 0u, // VkDependencyFlags dependencyFlags; 331 }; 332 333 subpassDependencies.push_back(readDependency); 334 } 335 } 336 337 const VkRenderPassCreateInfo renderPassInfo = 338 { 339 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 340 DE_NULL, // const void* pNext; 341 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags; 342 static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount; 343 dataPointer(attachments), // const VkAttachmentDescription* pAttachments; 344 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 345 dataPointer(subpasses), // const VkSubpassDescription* pSubpasses; 346 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount; 347 dataPointer(subpassDependencies) // const VkSubpassDependency* pDependencies; 348 }; 349 350 RenderPassWrapper renderPass (m_imageMSParams.pipelineConstructionType, deviceInterface, device, &renderPassInfo); 351 352 const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers); 353 354 // Create color attachments image views 355 typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp; 356 std::vector<VkImageViewSp> imageViewsShPtrs(firstSubpassAttachmentsCount + numSamples); 357 std::vector<VkImage> images(firstSubpassAttachmentsCount + numSamples); 358 std::vector<VkImageView> imageViews(firstSubpassAttachmentsCount + numSamples); 359 360 images[0] = **imageMS; 361 images[1] = **imageRS; 362 363 imageViewsShPtrs[0] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange)); 364 imageViewsShPtrs[1] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange)); 365 366 imageViews[0] = **imageViewsShPtrs[0]; 367 imageViews[1] = **imageViewsShPtrs[1]; 368 369 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 370 { 371 images[firstSubpassAttachmentsCount + sampleNdx] = **imagesPerSampleVec[sampleNdx]; 372 imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imagesPerSampleVec[sampleNdx], mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange)); 373 imageViews[firstSubpassAttachmentsCount + sampleNdx] = **imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx]; 374 } 375 376 // Create framebuffer 377 const VkFramebufferCreateInfo framebufferInfo = 378 { 379 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 380 DE_NULL, // const void* pNext; 381 (VkFramebufferCreateFlags)0u, // VkFramebufferCreateFlags flags; 382 *renderPass, // VkRenderPass renderPass; 383 static_cast<deUint32>(imageViews.size()), // uint32_t attachmentCount; 384 dataPointer(imageViews), // const VkImageView* pAttachments; 385 imageMSInfo.extent.width, // uint32_t width; 386 imageMSInfo.extent.height, // uint32_t height; 387 imageMSInfo.arrayLayers, // uint32_t layers; 388 }; 389 390 renderPass.createFramebuffer(deviceInterface, device, &framebufferInfo, images); 391 392 const VkDescriptorSetLayout* descriptorSetLayoutMSPass = createMSPassDescSetLayout(m_imageMSParams); 393 394 // Create pipeline layout 395 const VkPipelineLayoutCreateInfo pipelineLayoutMSPassParams = 396 { 397 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 398 DE_NULL, // const void* pNext; 399 (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags; 400 descriptorSetLayoutMSPass ? 1u : 0u, // deUint32 setLayoutCount; 401 descriptorSetLayoutMSPass, // const VkDescriptorSetLayout* pSetLayouts; 402 0u, // deUint32 pushConstantRangeCount; 403 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 404 }; 405 406 const PipelineLayoutWrapper pipelineLayoutMSPass(m_imageMSParams.pipelineConstructionType, deviceInterface, device, &pipelineLayoutMSPassParams); 407 408 // Create vertex attributes data 409 const VertexDataDesc vertexDataDesc = getVertexDataDescripton(); 410 411 de::SharedPtr<BufferWithMemory> vertexBuffer = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)); 412 const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation(); 413 414 uploadVertexData(vertexBufferAllocation, vertexDataDesc); 415 416 flushAlloc(deviceInterface, device, vertexBufferAllocation); 417 418 const VkVertexInputBindingDescription vertexBinding = 419 { 420 0u, // deUint32 binding; 421 vertexDataDesc.dataStride, // deUint32 stride; 422 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; 423 }; 424 425 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 426 { 427 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 428 DE_NULL, // const void* pNext; 429 (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags; 430 1u, // uint32_t vertexBindingDescriptionCount; 431 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 432 static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()), // uint32_t vertexAttributeDescriptionCount; 433 dataPointer(vertexDataDesc.vertexAttribDescVec), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 434 }; 435 436 const std::vector<VkViewport> viewports { makeViewport(imageMSInfo.extent) }; 437 const std::vector<VkRect2D> scissors { makeRect2D(imageMSInfo.extent) }; 438 439 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = getMSStateCreateInfo(m_imageMSParams); 440 441 // Create graphics pipeline for multisample pass 442 const ShaderWrapper vsMSPassModule(ShaderWrapper(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0u)); 443 const ShaderWrapper fsMSPassModule(ShaderWrapper(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0u)); 444 445 GraphicsPipelineWrapper graphicsPipelineMSPass(instance, deviceInterface, physicalDevice, device, m_context.getDeviceExtensions(), m_imageMSParams.pipelineConstructionType); 446 graphicsPipelineMSPass.setDefaultColorBlendState() 447 .setDefaultDepthStencilState() 448 .setDefaultRasterizationState() 449 .setDefaultTopology(vertexDataDesc.primitiveTopology) 450 .setupVertexInputState(&vertexInputStateInfo) 451 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayoutMSPass, *renderPass, 0u, vsMSPassModule) 452 .setupFragmentShaderState(pipelineLayoutMSPass, *renderPass, 0u, fsMSPassModule, DE_NULL, &multisampleStateInfo) 453 .setupFragmentOutputState(*renderPass, 0u, DE_NULL, &multisampleStateInfo) 454 .setMonolithicPipelineLayout(pipelineLayoutMSPass) 455 .buildPipeline(); 456 457 std::vector<GraphicsPipelineWrapper> graphicsPipelinesPerSampleFetch; 458 graphicsPipelinesPerSampleFetch.reserve(numSamples); 459 460 // Create descriptor set layout 461 const Unique<VkDescriptorSetLayout> descriptorSetLayout( 462 DescriptorSetLayoutBuilder() 463 .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT) 464 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT) 465 .build(deviceInterface, device)); 466 467 const PipelineLayoutWrapper pipelineLayoutPerSampleFetchPass(m_imageMSParams.pipelineConstructionType, deviceInterface, device, *descriptorSetLayout); 468 469 const deUint32 bufferPerSampleFetchPassSize = 4u * (deUint32)sizeof(tcu::Vec4); 470 471 de::SharedPtr<BufferWithMemory> vertexBufferPerSampleFetchPass = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, makeBufferCreateInfo(bufferPerSampleFetchPassSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)); 472 473 // Create graphics pipelines for per sample texel fetch passes 474 { 475 const ShaderWrapper vsPerSampleFetchPassModule(ShaderWrapper(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_vs"), (VkShaderModuleCreateFlags)0u)); 476 const ShaderWrapper fsPerSampleFetchPassModule(ShaderWrapper(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_fs"), (VkShaderModuleCreateFlags)0u)); 477 478 std::vector<tcu::Vec4> vertices; 479 480 vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); 481 vertices.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)); 482 vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f)); 483 vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f)); 484 485 const Allocation& vertexAllocPerSampleFetchPass = vertexBufferPerSampleFetchPass->getAllocation(); 486 487 deMemcpy(vertexAllocPerSampleFetchPass.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(bufferPerSampleFetchPassSize)); 488 489 flushAlloc(deviceInterface, device, vertexAllocPerSampleFetchPass); 490 491 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 492 { 493 const deUint32 subpass = 1u + sampleNdx; 494 graphicsPipelinesPerSampleFetch.emplace_back(instance, deviceInterface, physicalDevice, device, m_context.getDeviceExtensions(), m_imageMSParams.pipelineConstructionType); 495 graphicsPipelinesPerSampleFetch.back() 496 .setDefaultMultisampleState() 497 .setDefaultColorBlendState() 498 .setDefaultDepthStencilState() 499 .setDefaultRasterizationState() 500 .setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) 501 .setupVertexInputState() 502 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayoutPerSampleFetchPass, *renderPass, subpass, vsPerSampleFetchPassModule) 503 .setupFragmentShaderState(pipelineLayoutPerSampleFetchPass, *renderPass, subpass, fsPerSampleFetchPassModule) 504 .setupFragmentOutputState(*renderPass, subpass) 505 .setMonolithicPipelineLayout(pipelineLayoutPerSampleFetchPass) 506 .buildPipeline(); 507 } 508 } 509 510 // Create descriptor pool 511 const Unique<VkDescriptorPool> descriptorPool( 512 DescriptorPoolBuilder() 513 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u) 514 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1u) 515 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 516 517 // Create descriptor set 518 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(deviceInterface, device, *descriptorPool, *descriptorSetLayout)); 519 520 const VkPhysicalDeviceLimits deviceLimits = getPhysicalDeviceProperties(instance, physicalDevice).limits; 521 522 VkDeviceSize uboOffsetAlignment = sizeof(deInt32) < deviceLimits.minUniformBufferOffsetAlignment ? deviceLimits.minUniformBufferOffsetAlignment : sizeof(deInt32); 523 524 uboOffsetAlignment += (deviceLimits.minUniformBufferOffsetAlignment - uboOffsetAlignment % deviceLimits.minUniformBufferOffsetAlignment) % deviceLimits.minUniformBufferOffsetAlignment; 525 526 const VkBufferCreateInfo bufferSampleIDInfo = makeBufferCreateInfo(uboOffsetAlignment * numSamples, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); 527 const de::UniquePtr<BufferWithMemory> bufferSampleID(new BufferWithMemory(deviceInterface, device, allocator, bufferSampleIDInfo, MemoryRequirement::HostVisible)); 528 529 std::vector<deUint32> sampleIDsOffsets(numSamples); 530 531 { 532 deInt8* sampleIDs = new deInt8[static_cast<deUint32>(uboOffsetAlignment) * numSamples]; 533 534 for (deInt32 sampleNdx = 0u; sampleNdx < static_cast<deInt32>(numSamples); ++sampleNdx) 535 { 536 sampleIDsOffsets[sampleNdx] = static_cast<deUint32>(sampleNdx * uboOffsetAlignment); 537 deInt8* samplePtr = sampleIDs + sampleIDsOffsets[sampleNdx]; 538 539 deMemcpy(samplePtr, &sampleNdx, sizeof(deInt32)); 540 } 541 542 deMemcpy(bufferSampleID->getAllocation().getHostPtr(), sampleIDs, static_cast<deUint32>(uboOffsetAlignment * numSamples)); 543 544 flushAlloc(deviceInterface, device, bufferSampleID->getAllocation()); 545 546 delete[] sampleIDs; 547 } 548 549 { 550 const VkDescriptorImageInfo descImageInfo = makeDescriptorImageInfo(DE_NULL, imageViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 551 const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**bufferSampleID, 0u, sizeof(deInt32)); 552 553 DescriptorSetUpdateBuilder() 554 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descImageInfo) 555 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &descBufferInfo) 556 .update(deviceInterface, device); 557 } 558 559 // Create command buffer for compute and transfer oparations 560 const Unique<VkCommandPool> commandPool(createCommandPool(deviceInterface, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 561 const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool)); 562 563 // Start recording commands 564 beginCommandBuffer(deviceInterface, *commandBuffer); 565 566 { 567 std::vector<VkImageMemoryBarrier> imageOutputAttachmentBarriers(firstSubpassAttachmentsCount + numSamples); 568 569 imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier 570 ( 571 0u, 572 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 573 VK_IMAGE_LAYOUT_UNDEFINED, 574 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 575 **imageMS, 576 fullImageRange 577 ); 578 579 imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier 580 ( 581 0u, 582 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 583 VK_IMAGE_LAYOUT_UNDEFINED, 584 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 585 **imageRS, 586 fullImageRange 587 ); 588 589 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 590 { 591 imageOutputAttachmentBarriers[firstSubpassAttachmentsCount + sampleNdx] = makeImageMemoryBarrier 592 ( 593 0u, 594 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 595 VK_IMAGE_LAYOUT_UNDEFINED, 596 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 597 **imagesPerSampleVec[sampleNdx], 598 fullImageRange 599 ); 600 } 601 602 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 603 static_cast<deUint32>(imageOutputAttachmentBarriers.size()), dataPointer(imageOutputAttachmentBarriers)); 604 } 605 606 { 607 const VkDeviceSize vertexStartOffset = 0u; 608 609 std::vector<VkClearValue> clearValues(firstSubpassAttachmentsCount + numSamples); 610 for (deUint32 attachmentNdx = 0u; attachmentNdx < firstSubpassAttachmentsCount + numSamples; ++attachmentNdx) 611 { 612 clearValues[attachmentNdx] = makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 613 } 614 615 renderPass.begin(deviceInterface, *commandBuffer, makeRect2D(0, 0, imageMSInfo.extent.width, imageMSInfo.extent.height), (deUint32)clearValues.size(), dataPointer(clearValues)); 616 617 // Bind graphics pipeline 618 graphicsPipelineMSPass.bind(*commandBuffer); 619 620 const VkDescriptorSet* descriptorSetMSPass = createMSPassDescSet(m_imageMSParams, descriptorSetLayoutMSPass); 621 622 if (descriptorSetMSPass) 623 { 624 // Bind descriptor set 625 deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutMSPass, 0u, 1u, descriptorSetMSPass, 0u, DE_NULL); 626 } 627 628 // Bind vertex buffer 629 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset); 630 631 // Perform a draw 632 deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u); 633 634 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 635 { 636 renderPass.nextSubpass(deviceInterface, *commandBuffer, VK_SUBPASS_CONTENTS_INLINE); 637 638 // Bind graphics pipeline 639 graphicsPipelinesPerSampleFetch[sampleNdx].bind(*commandBuffer); 640 641 // Bind descriptor set 642 deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPerSampleFetchPass, 0u, 1u, &descriptorSet.get(), 1u, &sampleIDsOffsets[sampleNdx]); 643 644 // Bind vertex buffer 645 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBufferPerSampleFetchPass->get(), &vertexStartOffset); 646 647 // Perform a draw 648 deviceInterface.cmdDraw(*commandBuffer, 4u, 1u, 0u, 0u); 649 } 650 651 // End render pass 652 renderPass.end(deviceInterface, *commandBuffer); 653 } 654 655 { 656 const VkImageMemoryBarrier imageRSTransferBarrier = makeImageMemoryBarrier 657 ( 658 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 659 VK_ACCESS_TRANSFER_READ_BIT, 660 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 661 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 662 **imageRS, 663 fullImageRange 664 ); 665 666 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageRSTransferBarrier); 667 } 668 669 // Copy data from imageRS to buffer 670 const deUint32 imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels, 1u); 671 672 const VkBufferCreateInfo bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 673 const de::UniquePtr<BufferWithMemory> bufferRS(new BufferWithMemory(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible)); 674 675 { 676 const VkBufferImageCopy bufferImageCopy = 677 { 678 0u, // VkDeviceSize bufferOffset; 679 0u, // deUint32 bufferRowLength; 680 0u, // deUint32 bufferImageHeight; 681 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource; 682 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 683 imageRSInfo.extent, // VkExtent3D imageExtent; 684 }; 685 686 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imageRS, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy); 687 } 688 689 { 690 const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier 691 ( 692 VK_ACCESS_TRANSFER_WRITE_BIT, 693 VK_ACCESS_HOST_READ_BIT, 694 bufferRS->get(), 695 0u, 696 imageRSSizeInBytes 697 ); 698 699 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL); 700 } 701 702 // Copy data from per sample images to buffers 703 std::vector<VkImageMemoryBarrier> imagesPerSampleTransferBarriers(numSamples); 704 705 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 706 { 707 imagesPerSampleTransferBarriers[sampleNdx] = makeImageMemoryBarrier 708 ( 709 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 710 VK_ACCESS_TRANSFER_READ_BIT, 711 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 712 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 713 **imagesPerSampleVec[sampleNdx], 714 fullImageRange 715 ); 716 } 717 718 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 719 static_cast<deUint32>(imagesPerSampleTransferBarriers.size()), dataPointer(imagesPerSampleTransferBarriers)); 720 721 std::vector<de::SharedPtr<BufferWithMemory> > buffersPerSample(numSamples); 722 723 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 724 { 725 buffersPerSample[sampleNdx] = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible)); 726 727 const VkBufferImageCopy bufferImageCopy = 728 { 729 0u, // VkDeviceSize bufferOffset; 730 0u, // deUint32 bufferRowLength; 731 0u, // deUint32 bufferImageHeight; 732 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource; 733 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 734 imageRSInfo.extent, // VkExtent3D imageExtent; 735 }; 736 737 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imagesPerSampleVec[sampleNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **buffersPerSample[sampleNdx], 1u, &bufferImageCopy); 738 } 739 740 std::vector<VkBufferMemoryBarrier> buffersPerSampleHostReadBarriers(numSamples); 741 742 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 743 { 744 buffersPerSampleHostReadBarriers[sampleNdx] = makeBufferMemoryBarrier 745 ( 746 VK_ACCESS_TRANSFER_WRITE_BIT, 747 VK_ACCESS_HOST_READ_BIT, 748 **buffersPerSample[sampleNdx], 749 0u, 750 imageRSSizeInBytes 751 ); 752 } 753 754 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 755 static_cast<deUint32>(buffersPerSampleHostReadBarriers.size()), dataPointer(buffersPerSampleHostReadBarriers), 0u, DE_NULL); 756 757 // End recording commands 758 endCommandBuffer(deviceInterface, *commandBuffer); 759 760 // Submit commands for execution and wait for completion 761 submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer); 762 763 // Retrieve data from bufferRS to host memory 764 const Allocation& bufferRSAlloc = bufferRS->getAllocation(); 765 766 invalidateAlloc(deviceInterface, device, bufferRSAlloc); 767 768 const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat, 769 imageRSInfo.extent.width, 770 imageRSInfo.extent.height, 771 imageRSInfo.extent.depth * imageRSInfo.arrayLayers, 772 bufferRSAlloc.getHostPtr()); 773 774 std::stringstream resolveName; 775 resolveName << "Resolve image " << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl; 776 777 m_context.getTestContext().getLog() 778 << tcu::TestLog::Section(resolveName.str(), resolveName.str()) 779 << tcu::LogImage("resolve", "", bufferRSData) 780 << tcu::TestLog::EndSection; 781 782 std::vector<tcu::ConstPixelBufferAccess> buffersPerSampleData(numSamples); 783 784 // Retrieve data from per sample buffers to host memory 785 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 786 { 787 const Allocation& bufferAlloc = buffersPerSample[sampleNdx]->getAllocation(); 788 789 invalidateAlloc(deviceInterface, device, bufferAlloc); 790 791 buffersPerSampleData[sampleNdx] = tcu::ConstPixelBufferAccess 792 ( 793 m_imageFormat, 794 imageRSInfo.extent.width, 795 imageRSInfo.extent.height, 796 imageRSInfo.extent.depth * imageRSInfo.arrayLayers, 797 bufferAlloc.getHostPtr() 798 ); 799 800 std::stringstream sampleName; 801 sampleName << "Sample " << sampleNdx << " image" << std::endl; 802 803 m_context.getTestContext().getLog() 804 << tcu::TestLog::Section(sampleName.str(), sampleName.str()) 805 << tcu::LogImage("sample", "", buffersPerSampleData[sampleNdx]) 806 << tcu::TestLog::EndSection; 807 } 808 809 return verifyImageData(imageMSInfo, imageRSInfo, buffersPerSampleData, bufferRSData); 810} 811 812} // multisample 813} // pipeline 814} // vkt 815