1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * Copyright (c) 2016 The Android Open Source Project 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Multisampled image load/store Tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktImageMultisampleLoadStoreTests.hpp" 26 #include "vktTestCaseUtil.hpp" 27 #include "vktImageTestsUtil.hpp" 28 #include "vktImageLoadStoreUtil.hpp" 29 #include "vktImageTexture.hpp" 30 31 #include "vkDefs.hpp" 32 #include "vkRef.hpp" 33 #include "vkRefUtil.hpp" 34 #include "vkPlatform.hpp" 35 #include "vkPrograms.hpp" 36 #include "vkMemUtil.hpp" 37 #include "vkBuilderUtil.hpp" 38 #include "vkQueryUtil.hpp" 39 #include "vkImageUtil.hpp" 40 41 #include "deUniquePtr.hpp" 42 43 #include "tcuTextureUtil.hpp" 44 45 #include <string> 46 #include <vector> 47 48 namespace vkt 49 { 50 namespace image 51 { 52 namespace 53 { 54 using namespace vk; 55 using de::MovePtr; 56 using de::UniquePtr; 57 using tcu::IVec3; 58 59 static const VkFormat CHECKSUM_IMAGE_FORMAT = VK_FORMAT_R32_SINT; 60 61 struct CaseDef 62 { 63 Texture texture; 64 VkFormat format; 65 VkSampleCountFlagBits numSamples; 66 bool singleLayerBind; 67 }; 68 69 // Multisampled storage image test. 70 // 71 // Pass 1: Write a slightly different color pattern per-sample to the whole image. 72 // Pass 2: Read samples of the same image and check if color values are in the expected range. 73 // Write back results as a checksum image and verify them on the host. 74 // Each checksum image pixel should contain an integer equal to the number of samples. 75 76 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef) 77 { 78 const int dimension = (caseDef.singleLayerBind ? caseDef.texture.layerDimension() : caseDef.texture.dimension()); 79 const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : ""); 80 81 const ImageType usedImageType = (caseDef.singleLayerBind ? getImageTypeForSingleLayer(caseDef.texture.type()) : caseDef.texture.type()); 82 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(caseDef.format)); 83 const std::string msImageTypeStr = getShaderImageType(mapVkFormat(caseDef.format), usedImageType, (caseDef.texture.numSamples() > 1)); 84 85 const std::string xMax = de::toString(caseDef.texture.size().x() - 1); 86 const std::string yMax = de::toString(caseDef.texture.size().y() - 1); 87 const std::string signednessPrefix = isUintFormat(caseDef.format) ? "u" : isIntFormat(caseDef.format) ? "i" : ""; 88 const std::string gvec4Expr = signednessPrefix + "vec4"; 89 const int numColorComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.format).order); 90 91 const float storeColorScale = computeStoreColorScale(caseDef.format, caseDef.texture.size()); 92 const float storeColorBias = computeStoreColorBias(caseDef.format); 93 DE_ASSERT(colorScaleAndBiasAreValid(caseDef.format, storeColorScale, storeColorBias)); 94 95 const std::string colorScaleExpr = (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale)) 96 + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")"); 97 const std::string colorExpr = 98 gvec4Expr + "(" 99 + "gx^gy^gz^(sampleNdx >> 5)^(sampleNdx & 31), " // we "split" sampleNdx to keep this value in [0, 31] range for numSamples = 64 case 100 + (numColorComponents > 1 ? "(" + xMax + "-gx)^gy^gz, " : "0, ") 101 + (numColorComponents > 2 ? "gx^(" + yMax + "-gy)^gz, " : "0, ") 102 + (numColorComponents > 3 ? "(" + xMax + "-gx)^(" + yMax + "-gy)^gz" : "1") 103 + ")" + colorScaleExpr; 104 105 // Store shader 106 { 107 std::ostringstream src; 108 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 109 << "\n" 110 << "layout(local_size_x = 1) in;\n" 111 << "layout(set = 0, binding = 1, " << formatQualifierStr << ") writeonly uniform " << msImageTypeStr << " u_msImage;\n"; 112 113 if (caseDef.singleLayerBind) 114 src << "layout(set = 0, binding = 0) readonly uniform Constants {\n" 115 << " int u_layerNdx;\n" 116 << "};\n"; 117 118 src << "\n" 119 << "void main (void)\n" 120 << "{\n" 121 << " int gx = int(gl_GlobalInvocationID.x);\n" 122 << " int gy = int(gl_GlobalInvocationID.y);\n" 123 << " int gz = " << (caseDef.singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n" 124 << "\n" 125 << " for (int sampleNdx = 0; sampleNdx < " << caseDef.texture.numSamples() <<"; ++sampleNdx) {\n" 126 << " imageStore(u_msImage, " << texelCoordStr << ", sampleNdx, " << colorExpr << ");\n" 127 << " }\n" 128 << "}\n"; 129 130 programCollection.glslSources.add("comp_store") << glu::ComputeSource(src.str()); 131 } 132 133 // Load shader 134 { 135 const tcu::TextureFormat checksumFormat = mapVkFormat(CHECKSUM_IMAGE_FORMAT); 136 const std::string checksumImageTypeStr = getShaderImageType(checksumFormat, usedImageType); 137 const bool useExactCompare = isIntegerFormat(caseDef.format); 138 139 std::ostringstream src; 140 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 141 << "\n" 142 << "layout(local_size_x = 1) in;\n" 143 << "layout(set = 0, binding = 1, " << formatQualifierStr << ") readonly uniform " << msImageTypeStr << " u_msImage;\n" 144 << "layout(set = 0, binding = 2, " << getShaderImageFormatQualifier(checksumFormat) << ") writeonly uniform " << checksumImageTypeStr << " u_checksumImage;\n"; 145 146 if (caseDef.singleLayerBind) 147 src << "layout(set = 0, binding = 0) readonly uniform Constants {\n" 148 << " int u_layerNdx;\n" 149 << "};\n"; 150 151 src << "\n" 152 << "void main (void)\n" 153 << "{\n" 154 << " int gx = int(gl_GlobalInvocationID.x);\n" 155 << " int gy = int(gl_GlobalInvocationID.y);\n" 156 << " int gz = " << (caseDef.singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n" 157 << "\n" 158 << " int checksum = 0;\n" 159 << " for (int sampleNdx = 0; sampleNdx < " << caseDef.texture.numSamples() <<"; ++sampleNdx) {\n" 160 << " " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n"; 161 162 if (useExactCompare) 163 src << " if (color == " << colorExpr << ")\n" 164 << " ++checksum;\n"; 165 else 166 src << " " << gvec4Expr << " diff = abs(abs(color) - abs(" << colorExpr << "));\n" 167 << " if (all(lessThan(diff, " << gvec4Expr << "(0.02))))\n" 168 << " ++checksum;\n"; 169 170 src << " }\n" 171 << "\n" 172 << " imageStore(u_checksumImage, " << texelCoordStr << ", ivec4(checksum));\n" 173 << "}\n"; 174 175 programCollection.glslSources.add("comp_load") << glu::ComputeSource(src.str()); 176 } 177 } 178 179 void checkRequirements (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const CaseDef& caseDef) 180 { 181 VkPhysicalDeviceFeatures features; 182 vki.getPhysicalDeviceFeatures(physDevice, &features); 183 184 if (!features.shaderStorageImageMultisample) 185 TCU_THROW(NotSupportedError, "Multisampled storage images are not supported"); 186 187 VkImageFormatProperties imageFormatProperties; 188 const VkResult imageFormatResult = vki.getPhysicalDeviceImageFormatProperties( 189 physDevice, caseDef.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_STORAGE_BIT, (VkImageCreateFlags)0, &imageFormatProperties); 190 191 if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED) 192 TCU_THROW(NotSupportedError, "Format is not supported"); 193 194 if ((imageFormatProperties.sampleCounts & caseDef.numSamples) != caseDef.numSamples) 195 TCU_THROW(NotSupportedError, "Requested sample count is not supported"); 196 } 197 198 //! Helper function to deal with per-layer resources. 199 void insertImageViews (const DeviceInterface& vk, const VkDevice device, const CaseDef& caseDef, const VkFormat format, const VkImage image, std::vector<SharedVkImageView>* const pOutImageViews) 200 { 201 if (caseDef.singleLayerBind) 202 { 203 pOutImageViews->clear(); 204 pOutImageViews->resize(caseDef.texture.numLayers()); 205 for (int layerNdx = 0; layerNdx < caseDef.texture.numLayers(); ++layerNdx) 206 { 207 (*pOutImageViews)[layerNdx] = makeVkSharedPtr(makeImageView( 208 vk, device, image, mapImageViewType(getImageTypeForSingleLayer(caseDef.texture.type())), format, 209 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u))); 210 } 211 } 212 else // bind all layers at once 213 { 214 pOutImageViews->clear(); 215 pOutImageViews->resize(1); 216 (*pOutImageViews)[0] = makeVkSharedPtr(makeImageView( 217 vk, device, image, mapImageViewType(caseDef.texture.type()), format, 218 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, caseDef.texture.numLayers()))); 219 } 220 } 221 222 //! Helper function to deal with per-layer resources. 223 void insertDescriptorSets (const DeviceInterface& vk, const VkDevice device, const CaseDef& caseDef, const VkDescriptorPool descriptorPool, const VkDescriptorSetLayout descriptorSetLayout, std::vector<SharedVkDescriptorSet>* const pOutDescriptorSets) 224 { 225 if (caseDef.singleLayerBind) 226 { 227 pOutDescriptorSets->clear(); 228 pOutDescriptorSets->resize(caseDef.texture.numLayers()); 229 for (int layerNdx = 0; layerNdx < caseDef.texture.numLayers(); ++layerNdx) 230 (*pOutDescriptorSets)[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout)); 231 } 232 else // bind all layers at once 233 { 234 pOutDescriptorSets->clear(); 235 pOutDescriptorSets->resize(1); 236 (*pOutDescriptorSets)[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout)); 237 } 238 } 239 240 tcu::TestStatus test (Context& context, const CaseDef caseDef) 241 { 242 const InstanceInterface& vki = context.getInstanceInterface(); 243 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 244 const DeviceInterface& vk = context.getDeviceInterface(); 245 const VkDevice device = context.getDevice(); 246 const VkQueue queue = context.getUniversalQueue(); 247 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 248 Allocator& allocator = context.getDefaultAllocator(); 249 250 checkRequirements(vki, physDevice, caseDef); 251 252 // Images 253 254 const UniquePtr<Image> msImage(new Image( 255 vk, device, allocator, makeImageCreateInfo(caseDef.texture, caseDef.format, VK_IMAGE_USAGE_STORAGE_BIT, 0u), MemoryRequirement::Any)); 256 257 const UniquePtr<Image> checksumImage(new Image( 258 vk, device, allocator, 259 makeImageCreateInfo(Texture(caseDef.texture, 1), CHECKSUM_IMAGE_FORMAT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u), 260 MemoryRequirement::Any)); 261 262 // Buffer used to pass constants to the shader. 263 264 const int numLayers = caseDef.texture.numLayers(); 265 const VkDeviceSize bufferChunkSize = getOptimalUniformBufferChunkSize(vki, physDevice, sizeof(deInt32)); 266 const VkDeviceSize constantsBufferSizeBytes = numLayers * bufferChunkSize; 267 UniquePtr<Buffer> constantsBuffer (new Buffer(vk, device, allocator, makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), 268 MemoryRequirement::HostVisible)); 269 270 { 271 const Allocation& alloc = constantsBuffer->getAllocation(); 272 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr()); 273 274 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes)); 275 276 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx) 277 { 278 deInt32* const valuePtr = reinterpret_cast<deInt32*>(basePtr + layerNdx * bufferChunkSize); 279 *valuePtr = layerNdx; 280 } 281 282 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes); 283 } 284 285 const VkDeviceSize resultBufferSizeBytes = getImageSizeBytes(caseDef.texture.size(), CHECKSUM_IMAGE_FORMAT); 286 UniquePtr<Buffer> resultBuffer (new Buffer(vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), 287 MemoryRequirement::HostVisible)); 288 289 { 290 const Allocation& alloc = resultBuffer->getAllocation(); 291 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(resultBufferSizeBytes)); 292 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes); 293 } 294 295 // Descriptors 296 297 Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder() 298 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 299 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) 300 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) 301 .build(vk, device)); 302 303 Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder() 304 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers) 305 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers) 306 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers) 307 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers)); 308 309 std::vector<SharedVkDescriptorSet> allDescriptorSets; 310 std::vector<SharedVkImageView> allMultisampledImageViews; 311 std::vector<SharedVkImageView> allChecksumImageViews; 312 313 insertDescriptorSets(vk, device, caseDef, *descriptorPool, *descriptorSetLayout, &allDescriptorSets); 314 insertImageViews (vk, device, caseDef, caseDef.format, **msImage, &allMultisampledImageViews); 315 insertImageViews (vk, device, caseDef, CHECKSUM_IMAGE_FORMAT, **checksumImage, &allChecksumImageViews); 316 317 // Prepare commands 318 319 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout)); 320 const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex)); 321 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); 322 323 const tcu::IVec3 workSize = (caseDef.singleLayerBind ? caseDef.texture.layerSize() : caseDef.texture.size()); 324 const int loopNumLayers = (caseDef.singleLayerBind ? numLayers : 1); 325 const VkImageSubresourceRange subresourceAllLayers = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, caseDef.texture.numLayers()); 326 327 // Pass 1: Write MS image 328 { 329 const Unique<VkShaderModule> shaderModule (createShaderModule (vk, device, context.getBinaryCollection().get("comp_store"), 0)); 330 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); 331 332 beginCommandBuffer(vk, *cmdBuffer); 333 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 334 335 { 336 const VkImageMemoryBarrier barriers[] = 337 { 338 makeImageMemoryBarrier((VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **msImage, subresourceAllLayers), 339 makeImageMemoryBarrier((VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **checksumImage, subresourceAllLayers), 340 }; 341 342 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 343 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 344 } 345 346 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx) 347 { 348 const VkDescriptorSet descriptorSet = **allDescriptorSets[layerNdx]; 349 const VkDescriptorImageInfo descriptorMultiImageInfo = makeDescriptorImageInfo(DE_NULL, **allMultisampledImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL); 350 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(constantsBuffer->get(), layerNdx*bufferChunkSize, bufferChunkSize); 351 352 DescriptorSetUpdateBuilder() 353 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo) 354 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorMultiImageInfo) 355 .update(vk, device); 356 357 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL); 358 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z()); 359 } 360 361 endCommandBuffer(vk, *cmdBuffer); 362 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 363 } 364 365 // Pass 2: "Resolve" MS image in compute shader 366 { 367 const Unique<VkShaderModule> shaderModule (createShaderModule (vk, device, context.getBinaryCollection().get("comp_load"), 0)); 368 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); 369 370 beginCommandBuffer(vk, *cmdBuffer); 371 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 372 373 { 374 const VkImageMemoryBarrier barriers[] = 375 { 376 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, **msImage, subresourceAllLayers), 377 }; 378 379 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 380 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 381 } 382 383 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx) 384 { 385 const VkDescriptorSet descriptorSet = **allDescriptorSets[layerNdx]; 386 const VkDescriptorImageInfo descriptorMultiImageInfo = makeDescriptorImageInfo(DE_NULL, **allMultisampledImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL); 387 const VkDescriptorImageInfo descriptorChecksumImageInfo = makeDescriptorImageInfo(DE_NULL, **allChecksumImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL); 388 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(constantsBuffer->get(), layerNdx*bufferChunkSize, bufferChunkSize); 389 390 DescriptorSetUpdateBuilder() 391 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo) 392 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorMultiImageInfo) 393 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorChecksumImageInfo) 394 .update(vk, device); 395 396 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL); 397 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z()); 398 } 399 400 endCommandBuffer(vk, *cmdBuffer); 401 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 402 } 403 404 // Retrieve result 405 { 406 beginCommandBuffer(vk, *cmdBuffer); 407 408 { 409 const VkImageMemoryBarrier barriers[] = 410 { 411 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **checksumImage, subresourceAllLayers), 412 }; 413 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 414 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 415 } 416 { 417 const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(caseDef.texture.layerSize()), caseDef.texture.numLayers()); 418 vk.cmdCopyImageToBuffer(*cmdBuffer, **checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **resultBuffer, 1u, ©Region); 419 } 420 { 421 const VkBufferMemoryBarrier barriers[] = 422 { 423 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **resultBuffer, 0ull, resultBufferSizeBytes), 424 }; 425 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 426 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, 0u, DE_NULL); 427 } 428 429 endCommandBuffer(vk, *cmdBuffer); 430 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 431 } 432 433 // Verify 434 { 435 const Allocation& alloc = resultBuffer->getAllocation(); 436 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes); 437 438 const IVec3 imageSize = caseDef.texture.size(); 439 const deInt32* pDataPtr = static_cast<deInt32*>(alloc.getHostPtr()); 440 const deInt32 expectedChecksum = caseDef.texture.numSamples(); 441 442 for (int layer = 0; layer < imageSize.z(); ++layer) 443 for (int y = 0; y < imageSize.y(); ++y) 444 for (int x = 0; x < imageSize.x(); ++x) 445 { 446 if (*pDataPtr != expectedChecksum) 447 { 448 context.getTestContext().getLog() 449 << tcu::TestLog::Message << "Some sample colors were incorrect at (x, y, layer) = (" << x << ", " << y << ", " << layer << ")" << tcu::TestLog::EndMessage 450 << tcu::TestLog::Message << "Checksum value is " << *pDataPtr << " but expected " << expectedChecksum << tcu::TestLog::EndMessage; 451 452 return tcu::TestStatus::fail("Some sample colors were incorrect"); 453 } 454 ++pDataPtr; 455 } 456 457 return tcu::TestStatus::pass("OK"); 458 } 459 } 460 461 } // anonymous ns 462 463 tcu::TestCaseGroup* createImageMultisampleLoadStoreTests (tcu::TestContext& testCtx) 464 { 465 const Texture textures[] = 466 { 467 // \note Shader code is tweaked to work with image size of 32, take a look if this needs to be modified. 468 Texture(IMAGE_TYPE_2D, tcu::IVec3(32, 32, 1), 1), 469 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(32, 32, 1), 4), 470 }; 471 472 static const VkFormat formats[] = 473 { 474 VK_FORMAT_R32G32B32A32_SFLOAT, 475 VK_FORMAT_R16G16B16A16_SFLOAT, 476 VK_FORMAT_R32_SFLOAT, 477 478 VK_FORMAT_R32G32B32A32_UINT, 479 VK_FORMAT_R16G16B16A16_UINT, 480 VK_FORMAT_R8G8B8A8_UINT, 481 VK_FORMAT_R32_UINT, 482 483 VK_FORMAT_R32G32B32A32_SINT, 484 VK_FORMAT_R16G16B16A16_SINT, 485 VK_FORMAT_R8G8B8A8_SINT, 486 VK_FORMAT_R32_SINT, 487 488 VK_FORMAT_R8G8B8A8_UNORM, 489 490 VK_FORMAT_R8G8B8A8_SNORM, 491 }; 492 493 static const VkSampleCountFlagBits samples[] = 494 { 495 VK_SAMPLE_COUNT_2_BIT, 496 VK_SAMPLE_COUNT_4_BIT, 497 VK_SAMPLE_COUNT_8_BIT, 498 VK_SAMPLE_COUNT_16_BIT, 499 VK_SAMPLE_COUNT_32_BIT, 500 VK_SAMPLE_COUNT_64_BIT, 501 }; 502 503 MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_multisample", "Multisampled image store and load")); 504 505 for (int baseTextureNdx = 0; baseTextureNdx < DE_LENGTH_OF_ARRAY(textures); ++baseTextureNdx) 506 { 507 const Texture& baseTexture = textures[baseTextureNdx]; 508 MovePtr<tcu::TestCaseGroup> imageViewGroup (new tcu::TestCaseGroup(testCtx, getImageTypeName(baseTexture.type()).c_str(), "")); 509 const int numLayerBindModes = (baseTexture.numLayers() == 1 ? 1 : 2); 510 511 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) 512 for (int layerBindMode = 0; layerBindMode < numLayerBindModes; ++layerBindMode) 513 { 514 const bool singleLayerBind = (layerBindMode != 0); 515 const std::string formatGroupName = getFormatShortString(formats[formatNdx]) + (singleLayerBind ? "_single_layer" : ""); 516 MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatGroupName.c_str(), "")); 517 518 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx) 519 { 520 const std::string samplesCaseName = "samples_" + de::toString(samples[samplesNdx]); 521 522 const CaseDef caseDef = 523 { 524 Texture(baseTexture, samples[samplesNdx]), 525 formats[formatNdx], 526 samples[samplesNdx], 527 singleLayerBind, 528 }; 529 530 addFunctionCaseWithPrograms(formatGroup.get(), samplesCaseName, "", initPrograms, test, caseDef); 531 } 532 imageViewGroup->addChild(formatGroup.release()); 533 } 534 testGroup->addChild(imageViewGroup.release()); 535 } 536 537 return testGroup.release(); 538 } 539 540 } // image 541 } // vkt 542