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 Image load/store Tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktImageLoadStoreTests.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 #include "deSharedPtr.hpp" 43 #include "deStringUtil.hpp" 44 45 #include "tcuImageCompare.hpp" 46 #include "tcuTexture.hpp" 47 #include "tcuTextureUtil.hpp" 48 #include "tcuFloat.hpp" 49 50 #include <string> 51 #include <vector> 52 53 using namespace vk; 54 55 namespace vkt 56 { 57 namespace image 58 { 59 namespace 60 { 61 62 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture) 63 { 64 return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers()); 65 } 66 67 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer) 68 { 69 switch (texture.type()) 70 { 71 case IMAGE_TYPE_1D: 72 case IMAGE_TYPE_2D: 73 case IMAGE_TYPE_BUFFER: 74 // Not layered 75 DE_ASSERT(layer == 0); 76 return access; 77 78 case IMAGE_TYPE_1D_ARRAY: 79 return tcu::getSubregion(access, 0, layer, access.getWidth(), 1); 80 81 case IMAGE_TYPE_2D_ARRAY: 82 case IMAGE_TYPE_CUBE: 83 case IMAGE_TYPE_CUBE_ARRAY: 84 case IMAGE_TYPE_3D: // 3d texture is treated as if depth was the layers 85 return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1); 86 87 default: 88 DE_FATAL("Internal test error"); 89 return tcu::ConstPixelBufferAccess(); 90 } 91 } 92 93 //! \return true if all layers match in both pixel buffers 94 bool comparePixelBuffers (tcu::TestLog& log, 95 const Texture& texture, 96 const VkFormat format, 97 const tcu::ConstPixelBufferAccess reference, 98 const tcu::ConstPixelBufferAccess result) 99 { 100 DE_ASSERT(reference.getFormat() == result.getFormat()); 101 DE_ASSERT(reference.getSize() == result.getSize()); 102 103 const bool intFormat = isIntegerFormat(format); 104 const bool is3d = (texture.type() == IMAGE_TYPE_3D); 105 const int numLayersOrSlices = (is3d ? texture.size().z() : texture.numLayers()); 106 const int numCubeFaces = 6; 107 108 int passedLayers = 0; 109 for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx) 110 { 111 const std::string comparisonName = "Comparison" + de::toString(layerNdx); 112 const std::string comparisonDesc = "Image Comparison, " + 113 (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) : 114 is3d ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx)); 115 116 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx); 117 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx); 118 119 bool ok = false; 120 if (intFormat) 121 ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT); 122 else 123 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT); 124 125 if (ok) 126 ++passedLayers; 127 } 128 return passedLayers == numLayersOrSlices; 129 } 130 131 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values) 132 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access) 133 { 134 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT); 135 136 for (int z = 0; z < access.getDepth(); ++z) 137 for (int y = 0; y < access.getHeight(); ++y) 138 for (int x = 0; x < access.getWidth(); ++x) 139 { 140 const tcu::Vec4 color(access.getPixel(x, y, z)); 141 tcu::Vec4 newColor = color; 142 143 for (int i = 0; i < 4; ++i) 144 { 145 if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT) 146 { 147 const tcu::Float16 f(color[i]); 148 if (f.isDenorm() || f.isInf() || f.isNaN()) 149 newColor[i] = 0.0f; 150 } 151 else 152 { 153 const tcu::Float32 f(color[i]); 154 if (f.isDenorm() || f.isInf() || f.isNaN()) 155 newColor[i] = 0.0f; 156 } 157 } 158 159 if (newColor != color) 160 access.setPixel(newColor, x, y, z); 161 } 162 } 163 164 //!< replace invalid pixels in the image (-128) 165 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access) 166 { 167 DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT); 168 169 for (int z = 0; z < access.getDepth(); ++z) 170 for (int y = 0; y < access.getHeight(); ++y) 171 for (int x = 0; x < access.getWidth(); ++x) 172 { 173 const tcu::IVec4 color(access.getPixelInt(x, y, z)); 174 tcu::IVec4 newColor = color; 175 176 for (int i = 0; i < 4; ++i) 177 { 178 const deInt32 oldColor(color[i]); 179 if (oldColor == -128) newColor[i] = -127; 180 } 181 182 if (newColor != color) 183 access.setPixel(newColor, x, y, z); 184 } 185 } 186 187 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat) 188 { 189 // Generate a reference image data using the storage format 190 191 tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z()); 192 const tcu::PixelBufferAccess access = reference.getAccess(); 193 194 const float storeColorScale = computeStoreColorScale(imageFormat, imageSize); 195 const float storeColorBias = computeStoreColorBias(imageFormat); 196 197 const bool intFormat = isIntegerFormat(imageFormat); 198 const int xMax = imageSize.x() - 1; 199 const int yMax = imageSize.y() - 1; 200 201 for (int z = 0; z < imageSize.z(); ++z) 202 for (int y = 0; y < imageSize.y(); ++y) 203 for (int x = 0; x < imageSize.x(); ++x) 204 { 205 const tcu::IVec4 color(x^y^z, (xMax - x)^y^z, x^(yMax - y)^z, (xMax - x)^(yMax - y)^z); 206 207 if (intFormat) 208 access.setPixel(color, x, y, z); 209 else 210 access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z); 211 } 212 213 // If the image is to be accessed as a float texture, get rid of invalid values 214 215 if (isFloatFormat(readFormat) && imageFormat != readFormat) 216 replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr())); 217 if (isSnormFormat(readFormat) && imageFormat != readFormat) 218 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr())); 219 220 return reference; 221 } 222 223 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat) 224 { 225 return generateReferenceImage(imageSize, imageFormat, imageFormat); 226 } 227 228 void flipHorizontally (const tcu::PixelBufferAccess access) 229 { 230 const int xMax = access.getWidth() - 1; 231 const int halfWidth = access.getWidth() / 2; 232 233 if (isIntegerFormat(mapTextureFormat(access.getFormat()))) 234 for (int z = 0; z < access.getDepth(); z++) 235 for (int y = 0; y < access.getHeight(); y++) 236 for (int x = 0; x < halfWidth; x++) 237 { 238 const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z); 239 access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z); 240 access.setPixel(temp, x, y, z); 241 } 242 else 243 for (int z = 0; z < access.getDepth(); z++) 244 for (int y = 0; y < access.getHeight(); y++) 245 for (int x = 0; x < halfWidth; x++) 246 { 247 const tcu::Vec4 temp = access.getPixel(xMax - x, y, z); 248 access.setPixel(access.getPixel(x, y, z), xMax - x, y, z); 249 access.setPixel(temp, x, y, z); 250 } 251 } 252 253 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1) 254 { 255 return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize(); 256 } 257 258 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture) 259 { 260 const DeviceInterface& vk = context.getDeviceInterface(); 261 262 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers()); 263 const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier( 264 VK_ACCESS_SHADER_WRITE_BIT, 0u, 265 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, 266 image, fullImageSubresourceRange); 267 268 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier); 269 } 270 271 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes) 272 { 273 const DeviceInterface& vk = context.getDeviceInterface(); 274 275 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier( 276 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, 277 buffer, 0ull, bufferSizeBytes); 278 279 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); 280 } 281 282 //! Copy all layers of an image to a buffer. 283 void commandCopyImageToBuffer (Context& context, 284 const VkCommandBuffer cmdBuffer, 285 const VkImage image, 286 const VkBuffer buffer, 287 const VkDeviceSize bufferSizeBytes, 288 const Texture& texture) 289 { 290 const DeviceInterface& vk = context.getDeviceInterface(); 291 292 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers()); 293 const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier( 294 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 295 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 296 image, fullImageSubresourceRange); 297 298 const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture); 299 300 const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier( 301 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, 302 buffer, 0ull, bufferSizeBytes); 303 304 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier); 305 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ©Region); 306 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©Barrier, 0, (const VkImageMemoryBarrier*)DE_NULL); 307 } 308 309 class StoreTest : public TestCase 310 { 311 public: 312 enum TestFlags 313 { 314 FLAG_SINGLE_LAYER_BIND = 0x1, //!< Run the shader multiple times, each time binding a different layer. 315 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 0x2, //!< Declare the format of the images in the shader code 316 }; 317 318 StoreTest (tcu::TestContext& testCtx, 319 const std::string& name, 320 const std::string& description, 321 const Texture& texture, 322 const VkFormat format, 323 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER); 324 325 void initPrograms (SourceCollections& programCollection) const; 326 327 TestInstance* createInstance (Context& context) const; 328 329 private: 330 const Texture m_texture; 331 const VkFormat m_format; 332 const bool m_declareImageFormatInShader; 333 const bool m_singleLayerBind; 334 }; 335 336 StoreTest::StoreTest (tcu::TestContext& testCtx, 337 const std::string& name, 338 const std::string& description, 339 const Texture& texture, 340 const VkFormat format, 341 const deUint32 flags) 342 : TestCase (testCtx, name, description) 343 , m_texture (texture) 344 , m_format (format) 345 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0) 346 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0) 347 { 348 if (m_singleLayerBind) 349 DE_ASSERT(m_texture.numLayers() > 1); 350 } 351 352 void StoreTest::initPrograms (SourceCollections& programCollection) const 353 { 354 const float storeColorScale = computeStoreColorScale(m_format, m_texture.size()); 355 const float storeColorBias = computeStoreColorBias(m_format); 356 DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias)); 357 358 const std::string xMax = de::toString(m_texture.size().x() - 1); 359 const std::string yMax = de::toString(m_texture.size().y() - 1); 360 const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : ""; 361 const std::string colorBaseExpr = signednessPrefix + "vec4(" 362 + "gx^gy^gz, " 363 + "(" + xMax + "-gx)^gy^gz, " 364 + "gx^(" + yMax + "-gy)^gz, " 365 + "(" + xMax + "-gx)^(" + yMax + "-gy)^gz)"; 366 367 const std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale)) 368 + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")"); 369 370 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension()); 371 const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : ""); 372 373 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type()); 374 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format)); 375 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType); 376 377 for (deUint32 variant = 0; variant <= 1; variant++) 378 { 379 std::ostringstream src; 380 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n" 381 << "\n" 382 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"; 383 if (variant == 0) 384 src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n"; 385 else 386 src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n"; 387 388 if (m_singleLayerBind) 389 src << "layout (binding = 1) readonly uniform Constants {\n" 390 << " int u_layerNdx;\n" 391 << "};\n"; 392 393 src << "\n" 394 << "void main (void)\n" 395 << "{\n" 396 << " int gx = int(gl_GlobalInvocationID.x);\n" 397 << " int gy = int(gl_GlobalInvocationID.y);\n" 398 << " int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n" 399 << " imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n" 400 << "}\n"; 401 402 programCollection.glslSources.add(variant == 0 ? "comp" : "comp_fmt_unknown") << glu::ComputeSource(src.str()); 403 } 404 } 405 406 //! Generic test iteration algorithm for image tests 407 class BaseTestInstance : public TestInstance 408 { 409 public: 410 BaseTestInstance (Context& context, 411 const Texture& texture, 412 const VkFormat format, 413 const bool declareImageFormatInShader, 414 const bool singleLayerBind); 415 416 tcu::TestStatus iterate (void); 417 418 virtual ~BaseTestInstance (void) {} 419 420 protected: 421 virtual VkDescriptorSetLayout prepareDescriptors (void) = 0; 422 virtual tcu::TestStatus verifyResult (void) = 0; 423 424 virtual void commandBeforeCompute (const VkCommandBuffer cmdBuffer) = 0; 425 virtual void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer) = 0; 426 virtual void commandAfterCompute (const VkCommandBuffer cmdBuffer) = 0; 427 428 virtual void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, 429 const VkPipelineLayout pipelineLayout, 430 const int layerNdx) = 0; 431 virtual void checkRequirements (void) {}; 432 433 const Texture m_texture; 434 const VkFormat m_format; 435 const bool m_declareImageFormatInShader; 436 const bool m_singleLayerBind; 437 }; 438 439 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind) 440 : TestInstance (context) 441 , m_texture (texture) 442 , m_format (format) 443 , m_declareImageFormatInShader (declareImageFormatInShader) 444 , m_singleLayerBind (singleLayerBind) 445 { 446 } 447 448 tcu::TestStatus BaseTestInstance::iterate (void) 449 { 450 checkRequirements(); 451 452 const DeviceInterface& vk = m_context.getDeviceInterface(); 453 const VkDevice device = m_context.getDevice(); 454 const VkQueue queue = m_context.getUniversalQueue(); 455 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 456 457 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get(m_declareImageFormatInShader ? "comp" : "comp_fmt_unknown"), 0)); 458 459 const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors(); 460 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout)); 461 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); 462 463 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT, queueFamilyIndex)); 464 const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 465 466 beginCommandBuffer(vk, *cmdBuffer); 467 468 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 469 commandBeforeCompute(*cmdBuffer); 470 471 const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size()); 472 const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1); 473 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx) 474 { 475 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx); 476 477 if (layerNdx > 0) 478 commandBetweenShaderInvocations(*cmdBuffer); 479 480 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z()); 481 } 482 483 commandAfterCompute(*cmdBuffer); 484 485 endCommandBuffer(vk, *cmdBuffer); 486 487 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 488 489 return verifyResult(); 490 } 491 492 //! Base store test implementation 493 class StoreTestInstance : public BaseTestInstance 494 { 495 public: 496 StoreTestInstance (Context& context, 497 const Texture& texture, 498 const VkFormat format, 499 const bool declareImageFormatInShader, 500 const bool singleLayerBind); 501 502 protected: 503 tcu::TestStatus verifyResult (void); 504 505 // Add empty implementations for functions that might be not needed 506 void commandBeforeCompute (const VkCommandBuffer) {} 507 void commandBetweenShaderInvocations (const VkCommandBuffer) {} 508 void commandAfterCompute (const VkCommandBuffer) {} 509 void checkRequirements (void); 510 511 de::MovePtr<Buffer> m_imageBuffer; 512 const VkDeviceSize m_imageSizeBytes; 513 }; 514 515 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind) 516 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind) 517 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format)) 518 { 519 const DeviceInterface& vk = m_context.getDeviceInterface(); 520 const VkDevice device = m_context.getDevice(); 521 Allocator& allocator = m_context.getDefaultAllocator(); 522 523 // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances. 524 525 m_imageBuffer = de::MovePtr<Buffer>(new Buffer( 526 vk, device, allocator, 527 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT), 528 MemoryRequirement::HostVisible)); 529 } 530 531 tcu::TestStatus StoreTestInstance::verifyResult (void) 532 { 533 const DeviceInterface& vk = m_context.getDeviceInterface(); 534 const VkDevice device = m_context.getDevice(); 535 536 const tcu::IVec3 imageSize = m_texture.size(); 537 const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format); 538 539 const Allocation& alloc = m_imageBuffer->getAllocation(); 540 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes); 541 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, alloc.getHostPtr()); 542 543 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result)) 544 return tcu::TestStatus::pass("Passed"); 545 else 546 return tcu::TestStatus::fail("Image comparison failed"); 547 } 548 549 void StoreTestInstance::checkRequirements (void) 550 { 551 const VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures(); 552 553 if (!m_declareImageFormatInShader && !features.shaderStorageImageWriteWithoutFormat) 554 throw tcu::NotSupportedError("shaderStorageImageWriteWithoutFormat feature not supported"); 555 } 556 557 //! Store test for images 558 class ImageStoreTestInstance : public StoreTestInstance 559 { 560 public: 561 ImageStoreTestInstance (Context& context, 562 const Texture& texture, 563 const VkFormat format, 564 const bool declareImageFormatInShader, 565 const bool singleLayerBind); 566 567 protected: 568 VkDescriptorSetLayout prepareDescriptors (void); 569 void commandBeforeCompute (const VkCommandBuffer cmdBuffer); 570 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer); 571 void commandAfterCompute (const VkCommandBuffer cmdBuffer); 572 573 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, 574 const VkPipelineLayout pipelineLayout, 575 const int layerNdx); 576 577 de::MovePtr<Image> m_image; 578 de::MovePtr<Buffer> m_constantsBuffer; 579 const VkDeviceSize m_constantsBufferChunkSizeBytes; 580 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 581 Move<VkDescriptorPool> m_descriptorPool; 582 std::vector<SharedVkDescriptorSet> m_allDescriptorSets; 583 std::vector<SharedVkImageView> m_allImageViews; 584 }; 585 586 ImageStoreTestInstance::ImageStoreTestInstance (Context& context, 587 const Texture& texture, 588 const VkFormat format, 589 const bool declareImageFormatInShader, 590 const bool singleLayerBind) 591 : StoreTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind) 592 , m_constantsBufferChunkSizeBytes (getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32))) 593 , m_allDescriptorSets (texture.numLayers()) 594 , m_allImageViews (texture.numLayers()) 595 { 596 const DeviceInterface& vk = m_context.getDeviceInterface(); 597 const VkDevice device = m_context.getDevice(); 598 Allocator& allocator = m_context.getDefaultAllocator(); 599 600 m_image = de::MovePtr<Image>(new Image( 601 vk, device, allocator, 602 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u), 603 MemoryRequirement::Any)); 604 605 // This buffer will be used to pass constants to the shader 606 607 const int numLayers = m_texture.numLayers(); 608 const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes; 609 m_constantsBuffer = de::MovePtr<Buffer>(new Buffer( 610 vk, device, allocator, 611 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), 612 MemoryRequirement::HostVisible)); 613 614 { 615 const Allocation& alloc = m_constantsBuffer->getAllocation(); 616 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr()); 617 618 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes)); 619 620 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx) 621 { 622 deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes); 623 *valuePtr = static_cast<deUint32>(layerNdx); 624 } 625 626 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes); 627 } 628 } 629 630 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void) 631 { 632 const DeviceInterface& vk = m_context.getDeviceInterface(); 633 const VkDevice device = m_context.getDevice(); 634 635 const int numLayers = m_texture.numLayers(); 636 m_descriptorSetLayout = DescriptorSetLayoutBuilder() 637 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) 638 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 639 .build(vk, device); 640 641 m_descriptorPool = DescriptorPoolBuilder() 642 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers) 643 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers) 644 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers); 645 646 if (m_singleLayerBind) 647 { 648 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx) 649 { 650 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout)); 651 m_allImageViews[layerNdx] = makeVkSharedPtr(makeImageView( 652 vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format, 653 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u))); 654 } 655 } 656 else // bind all layers at once 657 { 658 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout)); 659 m_allImageViews[0] = makeVkSharedPtr(makeImageView( 660 vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format, 661 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers))); 662 } 663 664 return *m_descriptorSetLayout; // not passing the ownership 665 } 666 667 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx) 668 { 669 const DeviceInterface& vk = m_context.getDeviceInterface(); 670 const VkDevice device = m_context.getDevice(); 671 672 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx]; 673 const VkImageView imageView = **m_allImageViews[layerNdx]; 674 675 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL); 676 677 // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before. 678 const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo( 679 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes); 680 681 DescriptorSetUpdateBuilder() 682 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo) 683 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo) 684 .update(vk, device); 685 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL); 686 } 687 688 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer) 689 { 690 const DeviceInterface& vk = m_context.getDeviceInterface(); 691 692 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers()); 693 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier( 694 0u, 0u, 695 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 696 m_image->get(), fullImageSubresourceRange); 697 698 const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes; 699 const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier( 700 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, 701 m_constantsBuffer->get(), 0ull, constantsBufferSize); 702 703 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier); 704 } 705 706 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer) 707 { 708 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture); 709 } 710 711 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer) 712 { 713 commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture); 714 } 715 716 //! Store test for buffers 717 class BufferStoreTestInstance : public StoreTestInstance 718 { 719 public: 720 BufferStoreTestInstance (Context& context, 721 const Texture& texture, 722 const VkFormat format, 723 const bool declareImageFormatInShader); 724 725 protected: 726 VkDescriptorSetLayout prepareDescriptors (void); 727 void commandAfterCompute (const VkCommandBuffer cmdBuffer); 728 729 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, 730 const VkPipelineLayout pipelineLayout, 731 const int layerNdx); 732 733 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 734 Move<VkDescriptorPool> m_descriptorPool; 735 Move<VkDescriptorSet> m_descriptorSet; 736 Move<VkBufferView> m_bufferView; 737 }; 738 739 BufferStoreTestInstance::BufferStoreTestInstance (Context& context, 740 const Texture& texture, 741 const VkFormat format, 742 const bool declareImageFormatInShader) 743 : StoreTestInstance(context, texture, format, declareImageFormatInShader, false) 744 { 745 } 746 747 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void) 748 { 749 const DeviceInterface& vk = m_context.getDeviceInterface(); 750 const VkDevice device = m_context.getDevice(); 751 752 m_descriptorSetLayout = DescriptorSetLayoutBuilder() 753 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 754 .build(vk, device); 755 756 m_descriptorPool = DescriptorPoolBuilder() 757 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) 758 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 759 760 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout); 761 m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes); 762 763 return *m_descriptorSetLayout; // not passing the ownership 764 } 765 766 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx) 767 { 768 DE_ASSERT(layerNdx == 0); 769 DE_UNREF(layerNdx); 770 771 const VkDevice device = m_context.getDevice(); 772 const DeviceInterface& vk = m_context.getDeviceInterface(); 773 774 DescriptorSetUpdateBuilder() 775 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get()) 776 .update(vk, device); 777 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL); 778 } 779 780 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer) 781 { 782 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes); 783 } 784 785 class LoadStoreTest : public TestCase 786 { 787 public: 788 enum TestFlags 789 { 790 FLAG_SINGLE_LAYER_BIND = 1 << 0, //!< Run the shader multiple times, each time binding a different layer. 791 FLAG_RESTRICT_IMAGES = 1 << 1, //!< If given, images in the shader will be qualified with "restrict". 792 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER = 1 << 2, //!< Declare the format of the images in the shader code 793 }; 794 795 LoadStoreTest (tcu::TestContext& testCtx, 796 const std::string& name, 797 const std::string& description, 798 const Texture& texture, 799 const VkFormat format, 800 const VkFormat imageFormat, 801 const deUint32 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER); 802 803 void initPrograms (SourceCollections& programCollection) const; 804 TestInstance* createInstance (Context& context) const; 805 806 private: 807 const Texture m_texture; 808 const VkFormat m_format; //!< Format as accessed in the shader 809 const VkFormat m_imageFormat; //!< Storage format 810 const bool m_declareImageFormatInShader; //!< Whether the shader will specify the format layout qualifier of the images 811 const bool m_singleLayerBind; 812 const bool m_restrictImages; 813 }; 814 815 LoadStoreTest::LoadStoreTest (tcu::TestContext& testCtx, 816 const std::string& name, 817 const std::string& description, 818 const Texture& texture, 819 const VkFormat format, 820 const VkFormat imageFormat, 821 const deUint32 flags) 822 : TestCase (testCtx, name, description) 823 , m_texture (texture) 824 , m_format (format) 825 , m_imageFormat (imageFormat) 826 , m_declareImageFormatInShader ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0) 827 , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0) 828 , m_restrictImages ((flags & FLAG_RESTRICT_IMAGES) != 0) 829 { 830 if (m_singleLayerBind) 831 DE_ASSERT(m_texture.numLayers() > 1); 832 833 DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat)); 834 } 835 836 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const 837 { 838 const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension()); 839 const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type()); 840 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format)); 841 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType); 842 const std::string maybeRestrictStr = (m_restrictImages ? "restrict " : ""); 843 const std::string xMax = de::toString(m_texture.size().x() - 1); 844 845 for (deUint32 variant = 0; variant <= 1; variant++) 846 { 847 std::ostringstream src; 848 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n" 849 << "\n"; 850 if (variant != 0) 851 { 852 src << "#extension GL_EXT_shader_image_load_formatted : require\n"; 853 } 854 src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"; 855 if (variant == 0) 856 src << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n"; 857 else 858 src << "layout (binding = 0) " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n"; 859 src << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n" 860 << "\n" 861 << "void main (void)\n" 862 << "{\n" 863 << (dimension == 1 ? 864 " int pos = int(gl_GlobalInvocationID.x);\n" 865 " imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n" 866 : dimension == 2 ? 867 " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n" 868 " imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n" 869 : dimension == 3 ? 870 " ivec3 pos = ivec3(gl_GlobalInvocationID);\n" 871 " imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n" 872 : "") 873 << "}\n"; 874 875 programCollection.glslSources.add(variant == 0 ? "comp" : "comp_fmt_unknown") << glu::ComputeSource(src.str()); 876 } 877 } 878 879 //! Load/store test base implementation 880 class LoadStoreTestInstance : public BaseTestInstance 881 { 882 public: 883 LoadStoreTestInstance (Context& context, 884 const Texture& texture, 885 const VkFormat format, 886 const VkFormat imageFormat, 887 const bool declareImageFormatInShader, 888 const bool singleLayerBind); 889 890 protected: 891 virtual Buffer* getResultBuffer (void) const = 0; //!< Get the buffer that contains the result image 892 893 tcu::TestStatus verifyResult (void); 894 895 // Add empty implementations for functions that might be not needed 896 void commandBeforeCompute (const VkCommandBuffer) {} 897 void commandBetweenShaderInvocations (const VkCommandBuffer) {} 898 void commandAfterCompute (const VkCommandBuffer) {} 899 void checkRequirements (void); 900 901 de::MovePtr<Buffer> m_imageBuffer; //!< Source data and helper buffer 902 const VkDeviceSize m_imageSizeBytes; 903 const VkFormat m_imageFormat; //!< Image format (for storage, may be different than texture format) 904 tcu::TextureLevel m_referenceImage; //!< Used as input data and later to verify result image 905 }; 906 907 LoadStoreTestInstance::LoadStoreTestInstance (Context& context, 908 const Texture& texture, 909 const VkFormat format, 910 const VkFormat imageFormat, 911 const bool declareImageFormatInShader, 912 const bool singleLayerBind) 913 : BaseTestInstance (context, texture, format, declareImageFormatInShader, singleLayerBind) 914 , m_imageSizeBytes (getImageSizeBytes(texture.size(), format)) 915 , m_imageFormat (imageFormat) 916 , m_referenceImage (generateReferenceImage(texture.size(), imageFormat, format)) 917 { 918 const DeviceInterface& vk = m_context.getDeviceInterface(); 919 const VkDevice device = m_context.getDevice(); 920 Allocator& allocator = m_context.getDefaultAllocator(); 921 922 // A helper buffer with enough space to hold the whole image. 923 924 m_imageBuffer = de::MovePtr<Buffer>(new Buffer( 925 vk, device, allocator, 926 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT), 927 MemoryRequirement::HostVisible)); 928 929 // Copy reference data to buffer for subsequent upload to image. 930 931 const Allocation& alloc = m_imageBuffer->getAllocation(); 932 deMemcpy(alloc.getHostPtr(), m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes)); 933 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes); 934 } 935 936 tcu::TestStatus LoadStoreTestInstance::verifyResult (void) 937 { 938 const DeviceInterface& vk = m_context.getDeviceInterface(); 939 const VkDevice device = m_context.getDevice(); 940 941 // Apply the same transformation as done in the shader 942 const tcu::PixelBufferAccess reference = m_referenceImage.getAccess(); 943 flipHorizontally(reference); 944 945 const Allocation& alloc = getResultBuffer()->getAllocation(); 946 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes); 947 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), alloc.getHostPtr()); 948 949 if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result)) 950 return tcu::TestStatus::pass("Passed"); 951 else 952 return tcu::TestStatus::fail("Image comparison failed"); 953 } 954 955 void LoadStoreTestInstance::checkRequirements (void) 956 { 957 const VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures(); 958 959 if (!m_declareImageFormatInShader && !features.shaderStorageImageReadWithoutFormat) 960 throw tcu::NotSupportedError("shaderStorageImageReadWithoutFormat feature not supported"); 961 } 962 963 964 //! Load/store test for images 965 class ImageLoadStoreTestInstance : public LoadStoreTestInstance 966 { 967 public: 968 ImageLoadStoreTestInstance (Context& context, 969 const Texture& texture, 970 const VkFormat format, 971 const VkFormat imageFormat, 972 const bool declareImageFormatInShader, 973 const bool singleLayerBind); 974 975 protected: 976 VkDescriptorSetLayout prepareDescriptors (void); 977 void commandBeforeCompute (const VkCommandBuffer cmdBuffer); 978 void commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer); 979 void commandAfterCompute (const VkCommandBuffer cmdBuffer); 980 981 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, 982 const VkPipelineLayout pipelineLayout, 983 const int layerNdx); 984 985 Buffer* getResultBuffer (void) const { return m_imageBuffer.get(); } 986 987 de::MovePtr<Image> m_imageSrc; 988 de::MovePtr<Image> m_imageDst; 989 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 990 Move<VkDescriptorPool> m_descriptorPool; 991 std::vector<SharedVkDescriptorSet> m_allDescriptorSets; 992 std::vector<SharedVkImageView> m_allSrcImageViews; 993 std::vector<SharedVkImageView> m_allDstImageViews; 994 }; 995 996 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context& context, 997 const Texture& texture, 998 const VkFormat format, 999 const VkFormat imageFormat, 1000 const bool declareImageFormatInShader, 1001 const bool singleLayerBind) 1002 : LoadStoreTestInstance (context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind) 1003 , m_allDescriptorSets (texture.numLayers()) 1004 , m_allSrcImageViews (texture.numLayers()) 1005 , m_allDstImageViews (texture.numLayers()) 1006 { 1007 const DeviceInterface& vk = m_context.getDeviceInterface(); 1008 const VkDevice device = m_context.getDevice(); 1009 Allocator& allocator = m_context.getDefaultAllocator(); 1010 const VkImageCreateFlags imageFlags = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT); 1011 1012 m_imageSrc = de::MovePtr<Image>(new Image( 1013 vk, device, allocator, 1014 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags), 1015 MemoryRequirement::Any)); 1016 1017 m_imageDst = de::MovePtr<Image>(new Image( 1018 vk, device, allocator, 1019 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags), 1020 MemoryRequirement::Any)); 1021 } 1022 1023 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void) 1024 { 1025 const VkDevice device = m_context.getDevice(); 1026 const DeviceInterface& vk = m_context.getDeviceInterface(); 1027 1028 const int numLayers = m_texture.numLayers(); 1029 m_descriptorSetLayout = DescriptorSetLayoutBuilder() 1030 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) 1031 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) 1032 .build(vk, device); 1033 1034 m_descriptorPool = DescriptorPoolBuilder() 1035 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers) 1036 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers) 1037 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers); 1038 1039 if (m_singleLayerBind) 1040 { 1041 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx) 1042 { 1043 const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type())); 1044 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u); 1045 1046 m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout)); 1047 m_allSrcImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange)); 1048 m_allDstImageViews[layerNdx] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange)); 1049 } 1050 } 1051 else // bind all layers at once 1052 { 1053 const VkImageViewType viewType = mapImageViewType(m_texture.type()); 1054 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers); 1055 1056 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout)); 1057 m_allSrcImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange)); 1058 m_allDstImageViews[0] = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange)); 1059 } 1060 1061 return *m_descriptorSetLayout; // not passing the ownership 1062 } 1063 1064 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx) 1065 { 1066 const VkDevice device = m_context.getDevice(); 1067 const DeviceInterface& vk = m_context.getDeviceInterface(); 1068 1069 const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx]; 1070 const VkImageView srcImageView = **m_allSrcImageViews[layerNdx]; 1071 const VkImageView dstImageView = **m_allDstImageViews[layerNdx]; 1072 1073 const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL); 1074 const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL); 1075 1076 DescriptorSetUpdateBuilder() 1077 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo) 1078 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo) 1079 .update(vk, device); 1080 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL); 1081 } 1082 1083 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer) 1084 { 1085 const DeviceInterface& vk = m_context.getDeviceInterface(); 1086 1087 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers()); 1088 { 1089 const VkImageMemoryBarrier preCopyImageBarriers[] = 1090 { 1091 makeImageMemoryBarrier( 1092 0u, VK_ACCESS_TRANSFER_WRITE_BIT, 1093 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1094 m_imageSrc->get(), fullImageSubresourceRange), 1095 makeImageMemoryBarrier( 1096 0u, VK_ACCESS_SHADER_WRITE_BIT, 1097 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 1098 m_imageDst->get(), fullImageSubresourceRange) 1099 }; 1100 1101 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier( 1102 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 1103 m_imageBuffer->get(), 0ull, m_imageSizeBytes); 1104 1105 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, 1106 (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers); 1107 } 1108 { 1109 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier( 1110 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, 1111 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, 1112 m_imageSrc->get(), fullImageSubresourceRange); 1113 1114 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture); 1115 1116 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region); 1117 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy); 1118 } 1119 } 1120 1121 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer) 1122 { 1123 commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture); 1124 } 1125 1126 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer) 1127 { 1128 commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture); 1129 } 1130 1131 //! Load/store test for buffers 1132 class BufferLoadStoreTestInstance : public LoadStoreTestInstance 1133 { 1134 public: 1135 BufferLoadStoreTestInstance (Context& context, 1136 const Texture& texture, 1137 const VkFormat format, 1138 const VkFormat imageFormat, 1139 const bool declareImageFormatInShader); 1140 1141 protected: 1142 VkDescriptorSetLayout prepareDescriptors (void); 1143 void commandAfterCompute (const VkCommandBuffer cmdBuffer); 1144 1145 void commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, 1146 const VkPipelineLayout pipelineLayout, 1147 const int layerNdx); 1148 1149 Buffer* getResultBuffer (void) const { return m_imageBufferDst.get(); } 1150 1151 de::MovePtr<Buffer> m_imageBufferDst; 1152 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 1153 Move<VkDescriptorPool> m_descriptorPool; 1154 Move<VkDescriptorSet> m_descriptorSet; 1155 Move<VkBufferView> m_bufferViewSrc; 1156 Move<VkBufferView> m_bufferViewDst; 1157 }; 1158 1159 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context& context, 1160 const Texture& texture, 1161 const VkFormat format, 1162 const VkFormat imageFormat, 1163 const bool declareImageFormatInShader) 1164 : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false) 1165 { 1166 const DeviceInterface& vk = m_context.getDeviceInterface(); 1167 const VkDevice device = m_context.getDevice(); 1168 Allocator& allocator = m_context.getDefaultAllocator(); 1169 1170 // Create a destination buffer. 1171 1172 m_imageBufferDst = de::MovePtr<Buffer>(new Buffer( 1173 vk, device, allocator, 1174 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), 1175 MemoryRequirement::HostVisible)); 1176 } 1177 1178 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void) 1179 { 1180 const DeviceInterface& vk = m_context.getDeviceInterface(); 1181 const VkDevice device = m_context.getDevice(); 1182 1183 m_descriptorSetLayout = DescriptorSetLayoutBuilder() 1184 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 1185 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 1186 .build(vk, device); 1187 1188 m_descriptorPool = DescriptorPoolBuilder() 1189 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) 1190 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) 1191 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 1192 1193 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout); 1194 m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes); 1195 m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), m_format, 0ull, m_imageSizeBytes); 1196 1197 return *m_descriptorSetLayout; // not passing the ownership 1198 } 1199 1200 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx) 1201 { 1202 DE_ASSERT(layerNdx == 0); 1203 DE_UNREF(layerNdx); 1204 1205 const VkDevice device = m_context.getDevice(); 1206 const DeviceInterface& vk = m_context.getDeviceInterface(); 1207 1208 DescriptorSetUpdateBuilder() 1209 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewSrc.get()) 1210 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get()) 1211 .update(vk, device); 1212 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL); 1213 } 1214 1215 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer) 1216 { 1217 commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes); 1218 } 1219 1220 TestInstance* StoreTest::createInstance (Context& context) const 1221 { 1222 if (m_texture.type() == IMAGE_TYPE_BUFFER) 1223 return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader); 1224 else 1225 return new ImageStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_singleLayerBind); 1226 } 1227 1228 TestInstance* LoadStoreTest::createInstance (Context& context) const 1229 { 1230 if (m_texture.type() == IMAGE_TYPE_BUFFER) 1231 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader); 1232 else 1233 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind); 1234 } 1235 1236 static const Texture s_textures[] = 1237 { 1238 Texture(IMAGE_TYPE_1D, tcu::IVec3(64, 1, 1), 1), 1239 Texture(IMAGE_TYPE_1D_ARRAY, tcu::IVec3(64, 1, 1), 8), 1240 Texture(IMAGE_TYPE_2D, tcu::IVec3(64, 64, 1), 1), 1241 Texture(IMAGE_TYPE_2D_ARRAY, tcu::IVec3(64, 64, 1), 8), 1242 Texture(IMAGE_TYPE_3D, tcu::IVec3(64, 64, 8), 1), 1243 Texture(IMAGE_TYPE_CUBE, tcu::IVec3(64, 64, 1), 6), 1244 Texture(IMAGE_TYPE_CUBE_ARRAY, tcu::IVec3(64, 64, 1), 2*6), 1245 Texture(IMAGE_TYPE_BUFFER, tcu::IVec3(64, 1, 1), 1), 1246 }; 1247 1248 const Texture& getTestTexture (const ImageType imageType) 1249 { 1250 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx) 1251 if (s_textures[textureNdx].type() == imageType) 1252 return s_textures[textureNdx]; 1253 1254 DE_FATAL("Internal error"); 1255 return s_textures[0]; 1256 } 1257 1258 static const VkFormat s_formats[] = 1259 { 1260 VK_FORMAT_R32G32B32A32_SFLOAT, 1261 VK_FORMAT_R16G16B16A16_SFLOAT, 1262 VK_FORMAT_R32_SFLOAT, 1263 1264 VK_FORMAT_R32G32B32A32_UINT, 1265 VK_FORMAT_R16G16B16A16_UINT, 1266 VK_FORMAT_R8G8B8A8_UINT, 1267 VK_FORMAT_R32_UINT, 1268 1269 VK_FORMAT_R32G32B32A32_SINT, 1270 VK_FORMAT_R16G16B16A16_SINT, 1271 VK_FORMAT_R8G8B8A8_SINT, 1272 VK_FORMAT_R32_SINT, 1273 1274 VK_FORMAT_R8G8B8A8_UNORM, 1275 1276 VK_FORMAT_R8G8B8A8_SNORM, 1277 }; 1278 1279 } // anonymous ns 1280 1281 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx) 1282 { 1283 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases")); 1284 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images")); 1285 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images")); 1286 1287 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx) 1288 { 1289 const Texture& texture = s_textures[textureNdx]; 1290 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), "")); 1291 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), "")); 1292 const bool isLayered = (texture.numLayers() > 1); 1293 1294 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx) 1295 { 1296 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx])); 1297 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0)); 1298 1299 if (isLayered) 1300 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "", 1301 texture, s_formats[formatNdx], 1302 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER)); 1303 } 1304 1305 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release()); 1306 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release()); 1307 } 1308 1309 testGroup->addChild(testGroupWithFormat.release()); 1310 testGroup->addChild(testGroupWithoutFormat.release()); 1311 1312 return testGroup.release(); 1313 } 1314 1315 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx) 1316 { 1317 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()")); 1318 de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images")); 1319 de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images")); 1320 1321 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx) 1322 { 1323 const Texture& texture = s_textures[textureNdx]; 1324 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), "")); 1325 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), "")); 1326 const bool isLayered = (texture.numLayers() > 1); 1327 1328 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx) 1329 { 1330 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx])); 1331 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0)); 1332 1333 if (isLayered) 1334 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "", 1335 texture, s_formats[formatNdx], s_formats[formatNdx], 1336 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER)); 1337 } 1338 1339 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release()); 1340 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release()); 1341 } 1342 1343 testGroup->addChild(testGroupWithFormat.release()); 1344 testGroup->addChild(testGroupWithoutFormat.release()); 1345 1346 return testGroup.release(); 1347 } 1348 1349 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx) 1350 { 1351 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats")); 1352 1353 for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx) 1354 { 1355 const Texture& texture = s_textures[textureNdx]; 1356 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), "")); 1357 1358 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx) 1359 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx) 1360 { 1361 const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]); 1362 if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx])) 1363 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx])); 1364 } 1365 testGroup->addChild(groupByImageViewType.release()); 1366 } 1367 1368 return testGroup.release(); 1369 } 1370 1371 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name) 1372 { 1373 const VkFormat format = VK_FORMAT_R32G32B32A32_UINT; 1374 const Texture& texture = getTestTexture(imageType); 1375 return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER)); 1376 } 1377 1378 } // image 1379 } // vkt 1380