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 size Tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktImageSizeTests.hpp" 26 #include "vktTestCaseUtil.hpp" 27 #include "vktImageTestsUtil.hpp" 28 #include "vktImageTexture.hpp" 29 30 #include "vkDefs.hpp" 31 #include "vkRef.hpp" 32 #include "vkRefUtil.hpp" 33 #include "vkPlatform.hpp" 34 #include "vkPrograms.hpp" 35 #include "vkMemUtil.hpp" 36 #include "vkBuilderUtil.hpp" 37 #include "vkImageUtil.hpp" 38 39 #include "deUniquePtr.hpp" 40 #include "deStringUtil.hpp" 41 42 #include <string> 43 44 using namespace vk; 45 46 namespace vkt 47 { 48 namespace image 49 { 50 namespace 51 { 52 53 //! Get a texture based on image type and suggested size. 54 Texture getTexture (const ImageType imageType, const tcu::IVec3& size) 55 { 56 switch (imageType) 57 { 58 case IMAGE_TYPE_1D: 59 case IMAGE_TYPE_BUFFER: 60 return Texture(imageType, tcu::IVec3(size.x(), 1, 1), 1); 61 62 case IMAGE_TYPE_1D_ARRAY: 63 return Texture(imageType, tcu::IVec3(size.x(), 1, 1), size.y()); 64 65 case IMAGE_TYPE_2D: 66 return Texture(imageType, tcu::IVec3(size.x(), size.y(), 1), 1); 67 68 case IMAGE_TYPE_2D_ARRAY: 69 return Texture(imageType, tcu::IVec3(size.x(), size.y(), 1), size.z()); 70 71 case IMAGE_TYPE_CUBE: 72 return Texture(imageType, tcu::IVec3(size.x(), size.x(), 1), 6); 73 74 case IMAGE_TYPE_CUBE_ARRAY: 75 return Texture(imageType, tcu::IVec3(size.x(), size.x(), 1), 2*6); 76 77 case IMAGE_TYPE_3D: 78 return Texture(imageType, size, 1); 79 80 default: 81 DE_FATAL("Internal error"); 82 return Texture(IMAGE_TYPE_LAST, tcu::IVec3(), 0); 83 } 84 } 85 86 inline VkImageCreateInfo makeImageCreateInfo (const Texture& texture, const VkFormat format) 87 { 88 const VkImageCreateInfo imageParams = 89 { 90 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 91 DE_NULL, // const void* pNext; 92 (isCube(texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u), // VkImageCreateFlags flags; 93 mapImageType(texture.type()), // VkImageType imageType; 94 format, // VkFormat format; 95 makeExtent3D(texture.layerSize()), // VkExtent3D extent; 96 1u, // deUint32 mipLevels; 97 (deUint32)texture.numLayers(), // deUint32 arrayLayers; 98 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 99 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 100 VK_IMAGE_USAGE_STORAGE_BIT, // VkImageUsageFlags usage; 101 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 102 0u, // deUint32 queueFamilyIndexCount; 103 DE_NULL, // const deUint32* pQueueFamilyIndices; 104 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 105 }; 106 return imageParams; 107 } 108 109 //! Interpret the memory as IVec3 110 inline tcu::IVec3 readIVec3 (const void* const data) 111 { 112 const int* const p = reinterpret_cast<const int* const>(data); 113 return tcu::IVec3(p[0], p[1], p[2]); 114 } 115 116 tcu::IVec3 getExpectedImageSizeResult (const Texture& texture) 117 { 118 // GLSL imageSize() function returns: 119 // z = 0 for cubes 120 // z = N for cube arrays, where N is the number of cubes 121 // y or z = L where L is the number of layers for other array types (e.g. 1D array, 2D array) 122 // z = D where D is the depth of 3d image 123 124 const tcu::IVec3 size = texture.size(); 125 const int numCubeFaces = 6; 126 127 switch (texture.type()) 128 { 129 case IMAGE_TYPE_1D: 130 case IMAGE_TYPE_BUFFER: 131 return tcu::IVec3(size.x(), 0, 0); 132 133 case IMAGE_TYPE_1D_ARRAY: 134 case IMAGE_TYPE_2D: 135 case IMAGE_TYPE_CUBE: 136 return tcu::IVec3(size.x(), size.y(), 0); 137 138 case IMAGE_TYPE_2D_ARRAY: 139 case IMAGE_TYPE_3D: 140 return size; 141 142 case IMAGE_TYPE_CUBE_ARRAY: 143 return tcu::IVec3(size.x(), size.y(), size.z() / numCubeFaces); 144 145 default: 146 DE_FATAL("Internal error"); 147 return tcu::IVec3(); 148 } 149 } 150 151 class SizeTest : public TestCase 152 { 153 public: 154 enum TestFlags 155 { 156 FLAG_READONLY_IMAGE = 1u << 0, 157 FLAG_WRITEONLY_IMAGE = 1u << 1, 158 }; 159 160 SizeTest (tcu::TestContext& testCtx, 161 const std::string& name, 162 const std::string& description, 163 const Texture& texture, 164 const VkFormat format, 165 const deUint32 flags = 0); 166 167 void initPrograms (SourceCollections& programCollection) const; 168 TestInstance* createInstance (Context& context) const; 169 170 private: 171 const Texture m_texture; 172 const VkFormat m_format; 173 const bool m_useReadonly; 174 const bool m_useWriteonly; 175 }; 176 177 SizeTest::SizeTest (tcu::TestContext& testCtx, 178 const std::string& name, 179 const std::string& description, 180 const Texture& texture, 181 const VkFormat format, 182 const deUint32 flags) 183 : TestCase (testCtx, name, description) 184 , m_texture (texture) 185 , m_format (format) 186 , m_useReadonly ((flags & FLAG_READONLY_IMAGE) != 0) 187 , m_useWriteonly ((flags & FLAG_WRITEONLY_IMAGE) != 0) 188 { 189 // We expect at least one flag to be set. 190 DE_ASSERT(m_useReadonly || m_useWriteonly); 191 } 192 193 void SizeTest::initPrograms (SourceCollections& programCollection) const 194 { 195 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format)); 196 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), m_texture.type()); 197 const int dimension = m_texture.dimension(); 198 199 std::ostringstream accessQualifier; 200 if (m_useReadonly) 201 accessQualifier << " readonly"; 202 if (m_useWriteonly) 203 accessQualifier << " writeonly"; 204 205 std::ostringstream src; 206 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n" 207 << "\n" 208 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 209 << "layout (binding = 0, " << formatQualifierStr << ")" << accessQualifier.str() << " uniform highp " << imageTypeStr << " u_image;\n" 210 << "layout (binding = 1) writeonly buffer Output {\n" 211 << " ivec3 size;\n" 212 << "} sb_out;\n" 213 << "\n" 214 << "void main (void)\n" 215 << "{\n" 216 << (dimension == 1 ? 217 " sb_out.size = ivec3(imageSize(u_image), 0, 0);\n" 218 : dimension == 2 || m_texture.type() == IMAGE_TYPE_CUBE ? // cubes return ivec2 219 " sb_out.size = ivec3(imageSize(u_image), 0);\n" 220 : dimension == 3 ? // cube arrays return ivec3 221 " sb_out.size = imageSize(u_image);\n" 222 : "") 223 << "}\n"; 224 225 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str()); 226 } 227 228 //! Build a case name, e.g. "readonly_writeonly_32x32" 229 std::string getCaseName (const Texture& texture, const deUint32 flags) 230 { 231 std::ostringstream str; 232 str << ((flags & SizeTest::FLAG_READONLY_IMAGE) != 0 ? "readonly_" : "") 233 << ((flags & SizeTest::FLAG_WRITEONLY_IMAGE) != 0 ? "writeonly_" : ""); 234 235 const int numComponents = texture.dimension(); 236 for (int i = 0; i < numComponents; ++i) 237 str << (i == 0 ? "" : "x") << texture.size()[i]; 238 239 return str.str(); 240 } 241 242 //! Base test instance for image and buffer tests 243 class SizeTestInstance : public TestInstance 244 { 245 public: 246 SizeTestInstance (Context& context, 247 const Texture& texture, 248 const VkFormat format); 249 250 tcu::TestStatus iterate (void); 251 252 virtual ~SizeTestInstance (void) {} 253 254 protected: 255 virtual VkDescriptorSetLayout prepareDescriptors (void) = 0; 256 virtual VkDescriptorSet getDescriptorSet (void) const = 0; 257 virtual void commandBeforeCompute (const VkCommandBuffer cmdBuffer) = 0; 258 259 const Texture m_texture; 260 const VkFormat m_format; 261 const VkDeviceSize m_resultBufferSizeBytes; 262 de::MovePtr<Buffer> m_resultBuffer; //!< Shader writes the output here. 263 }; 264 265 SizeTestInstance::SizeTestInstance (Context& context, const Texture& texture, const VkFormat format) 266 : TestInstance (context) 267 , m_texture (texture) 268 , m_format (format) 269 , m_resultBufferSizeBytes (3 * sizeof(deUint32)) // ivec3 in shader 270 { 271 const DeviceInterface& vk = m_context.getDeviceInterface(); 272 const VkDevice device = m_context.getDevice(); 273 Allocator& allocator = m_context.getDefaultAllocator(); 274 275 // Create an SSBO for shader output. 276 277 m_resultBuffer = de::MovePtr<Buffer>(new Buffer( 278 vk, device, allocator, 279 makeBufferCreateInfo(m_resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), 280 MemoryRequirement::HostVisible)); 281 } 282 283 tcu::TestStatus SizeTestInstance::iterate (void) 284 { 285 const DeviceInterface& vk = m_context.getDeviceInterface(); 286 const VkDevice device = m_context.getDevice(); 287 const VkQueue queue = m_context.getUniversalQueue(); 288 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 289 290 // Create memory barriers. 291 292 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier( 293 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, 294 m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes); 295 296 // Create the pipeline. 297 298 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0)); 299 300 const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors(); 301 const VkDescriptorSet descriptorSet = getDescriptorSet(); 302 303 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout)); 304 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); 305 306 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 307 const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 308 309 beginCommandBuffer(vk, *cmdBuffer); 310 311 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 312 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL); 313 314 commandBeforeCompute(*cmdBuffer); 315 vk.cmdDispatch(*cmdBuffer, 1, 1, 1); 316 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); 317 318 endCommandBuffer(vk, *cmdBuffer); 319 320 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 321 322 // Compare the result. 323 324 const Allocation& bufferAlloc = m_resultBuffer->getAllocation(); 325 invalidateMappedMemoryRange(vk, device, bufferAlloc.getMemory(), bufferAlloc.getOffset(), m_resultBufferSizeBytes); 326 327 const tcu::IVec3 resultSize = readIVec3(bufferAlloc.getHostPtr()); 328 const tcu::IVec3 expectedSize = getExpectedImageSizeResult(m_texture); 329 330 if (resultSize != expectedSize) 331 return tcu::TestStatus::fail("Incorrect imageSize(): expected " + de::toString(expectedSize) + " but got " + de::toString(resultSize)); 332 else 333 return tcu::TestStatus::pass("Passed"); 334 } 335 336 class ImageSizeTestInstance : public SizeTestInstance 337 { 338 public: 339 ImageSizeTestInstance (Context& context, 340 const Texture& texture, 341 const VkFormat format); 342 343 protected: 344 VkDescriptorSetLayout prepareDescriptors (void); 345 void commandBeforeCompute (const VkCommandBuffer cmdBuffer); 346 347 VkDescriptorSet getDescriptorSet (void) const { return *m_descriptorSet; } 348 349 de::MovePtr<Image> m_image; 350 Move<VkImageView> m_imageView; 351 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 352 Move<VkDescriptorPool> m_descriptorPool; 353 Move<VkDescriptorSet> m_descriptorSet; 354 }; 355 356 ImageSizeTestInstance::ImageSizeTestInstance (Context& context, const Texture& texture, const VkFormat format) 357 : SizeTestInstance (context, texture, format) 358 { 359 const DeviceInterface& vk = m_context.getDeviceInterface(); 360 const VkDevice device = m_context.getDevice(); 361 Allocator& allocator = m_context.getDefaultAllocator(); 362 363 // Create an image. Its data be uninitialized, as we're not reading from it. 364 365 m_image = de::MovePtr<Image>(new Image(vk, device, allocator, makeImageCreateInfo(m_texture, m_format), MemoryRequirement::Any)); 366 367 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers()); 368 m_imageView = makeImageView(vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format, subresourceRange); 369 } 370 371 VkDescriptorSetLayout ImageSizeTestInstance::prepareDescriptors (void) 372 { 373 const DeviceInterface& vk = m_context.getDeviceInterface(); 374 const VkDevice device = m_context.getDevice(); 375 376 m_descriptorSetLayout = DescriptorSetLayoutBuilder() 377 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) 378 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 379 .build(vk, device); 380 381 m_descriptorPool = DescriptorPoolBuilder() 382 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) 383 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 384 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 385 386 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout); 387 388 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL); 389 const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes); 390 391 DescriptorSetUpdateBuilder() 392 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo) 393 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo) 394 .update(vk, device); 395 396 return *m_descriptorSetLayout; 397 } 398 399 void ImageSizeTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer) 400 { 401 const DeviceInterface& vk = m_context.getDeviceInterface(); 402 403 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers()); 404 const VkImageMemoryBarrier barrierSetImageLayout = makeImageMemoryBarrier( 405 0u, 0u, 406 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, 407 m_image->get(), subresourceRange); 408 409 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierSetImageLayout); 410 } 411 412 class BufferSizeTestInstance : public SizeTestInstance 413 { 414 public: 415 BufferSizeTestInstance (Context& context, 416 const Texture& texture, 417 const VkFormat format); 418 419 protected: 420 VkDescriptorSetLayout prepareDescriptors (void); 421 422 void commandBeforeCompute (const VkCommandBuffer) {} 423 VkDescriptorSet getDescriptorSet (void) const { return *m_descriptorSet; } 424 425 de::MovePtr<Buffer> m_imageBuffer; 426 Move<VkBufferView> m_bufferView; 427 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 428 Move<VkDescriptorPool> m_descriptorPool; 429 Move<VkDescriptorSet> m_descriptorSet; 430 }; 431 432 BufferSizeTestInstance::BufferSizeTestInstance (Context& context, const Texture& texture, const VkFormat format) 433 : SizeTestInstance (context, texture, format) 434 { 435 const DeviceInterface& vk = m_context.getDeviceInterface(); 436 const VkDevice device = m_context.getDevice(); 437 Allocator& allocator = m_context.getDefaultAllocator(); 438 439 // Create a texel storage buffer. Its data be uninitialized, as we're not reading from it. 440 441 const VkDeviceSize imageSizeBytes = getImageSizeBytes(m_texture.size(), m_format); 442 m_imageBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator, 443 makeBufferCreateInfo(imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), MemoryRequirement::Any)); 444 445 m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, imageSizeBytes); 446 } 447 448 VkDescriptorSetLayout BufferSizeTestInstance::prepareDescriptors (void) 449 { 450 const DeviceInterface& vk = m_context.getDeviceInterface(); 451 const VkDevice device = m_context.getDevice(); 452 453 m_descriptorSetLayout = DescriptorSetLayoutBuilder() 454 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 455 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 456 .build(vk, device); 457 458 m_descriptorPool = DescriptorPoolBuilder() 459 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) 460 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 461 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 462 463 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout); 464 465 const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes); 466 467 DescriptorSetUpdateBuilder() 468 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get()) 469 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo) 470 .update(vk, device); 471 472 return *m_descriptorSetLayout; 473 } 474 475 TestInstance* SizeTest::createInstance (Context& context) const 476 { 477 if (m_texture.type() == IMAGE_TYPE_BUFFER) 478 return new BufferSizeTestInstance(context, m_texture, m_format); 479 else 480 return new ImageSizeTestInstance(context, m_texture, m_format); 481 } 482 483 static const ImageType s_imageTypes[] = 484 { 485 IMAGE_TYPE_1D, 486 IMAGE_TYPE_1D_ARRAY, 487 IMAGE_TYPE_2D, 488 IMAGE_TYPE_2D_ARRAY, 489 IMAGE_TYPE_3D, 490 IMAGE_TYPE_CUBE, 491 IMAGE_TYPE_CUBE_ARRAY, 492 IMAGE_TYPE_BUFFER, 493 }; 494 495 //! Base sizes used to generate actual image/buffer sizes in the test. 496 static const tcu::IVec3 s_baseImageSizes[] = 497 { 498 tcu::IVec3(32, 32, 32), 499 tcu::IVec3(12, 34, 56), 500 tcu::IVec3(1, 1, 1), 501 tcu::IVec3(7, 1, 1), 502 }; 503 504 static const deUint32 s_flags[] = 505 { 506 SizeTest::FLAG_READONLY_IMAGE, 507 SizeTest::FLAG_WRITEONLY_IMAGE, 508 SizeTest::FLAG_READONLY_IMAGE | SizeTest::FLAG_WRITEONLY_IMAGE, 509 }; 510 511 } // anonymous ns 512 513 tcu::TestCaseGroup* createImageSizeTests (tcu::TestContext& testCtx) 514 { 515 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "image_size", "imageSize() cases")); 516 517 const VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT; 518 519 for (int imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++imageTypeNdx) 520 { 521 de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(s_imageTypes[imageTypeNdx]).c_str(), "")); 522 523 for (int flagNdx = 0; flagNdx < DE_LENGTH_OF_ARRAY(s_flags); ++flagNdx) 524 for (int imageSizeNdx = 0; imageSizeNdx < DE_LENGTH_OF_ARRAY(s_baseImageSizes); ++imageSizeNdx) 525 { 526 const Texture texture = getTexture(s_imageTypes[imageTypeNdx], s_baseImageSizes[imageSizeNdx]); 527 imageGroup->addChild(new SizeTest(testCtx, getCaseName(texture, s_flags[flagNdx]), "", texture, format, s_flags[flagNdx])); 528 } 529 530 testGroup->addChild(imageGroup.release()); 531 } 532 return testGroup.release(); 533 } 534 535 } // image 536 } // vkt 537