1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2022 The Khronos Group Inc. 6 * Copyright (c) 2022 Google Inc. 7 * Copyright (c) 2023 LunarG, Inc. 8 * Copyright (c) 2023 Nintendo 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file vktPipelineDescriptorLimits.cpp 24 * \brief Descriptor limit tests 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineDescriptorLimitsTests.hpp" 28#include "vktPipelineClearUtil.hpp" 29 30#include "vkBuilderUtil.hpp" 31#include "vkCmdUtil.hpp" 32#include "vkMemUtil.hpp" 33#include "vkImageUtil.hpp" 34#include "vkObjUtil.hpp" 35#include "vkQueryUtil.hpp" 36#include "vkTypeUtil.hpp" 37 38#include "tcuImageCompare.hpp" 39#include "tcuTestLog.hpp" 40#include "tcuTextureUtil.hpp" 41 42#include "deUniquePtr.hpp" 43 44#include <array> 45 46namespace vkt 47{ 48namespace pipeline 49{ 50 51using namespace vk; 52 53namespace 54{ 55 56enum class TestType 57{ 58 Samplers = 0, 59 UniformBuffers = 1, 60 StorageBuffers = 2, 61 SampledImages = 3, 62 StorageImages = 4, 63 InputAttachments = 5 64}; 65 66inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage) 67{ 68 const VkImageCreateInfo imageParams = 69 { 70 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 71 DE_NULL, // const void* pNext; 72 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 73 VK_IMAGE_TYPE_2D, // VkImageType imageType; 74 format, // VkFormat format; 75 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 76 1u, // deUint32 mipLevels; 77 1u, // deUint32 arrayLayers; 78 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 79 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 80 usage, // VkImageUsageFlags usage; 81 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 82 0u, // deUint32 queueFamilyIndexCount; 83 DE_NULL, // const deUint32* pQueueFamilyIndices; 84 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 85 }; 86 return imageParams; 87} 88 89tcu::TextureLevel generateColorImage (const VkFormat format, const tcu::IVec2 &renderSize, const tcu::Vec4 color) 90{ 91 tcu::TextureLevel image(mapVkFormat(format), renderSize.x(), renderSize.y()); 92 tcu::clear(image.getAccess(), color); 93 94 return image; 95} 96 97RenderPassWrapper makeRenderPassInputAttachment (const DeviceInterface& vk, 98 const VkDevice device, 99 const PipelineConstructionType pipelineConstructionType, 100 const VkFormat colorFormat) 101{ 102 const VkAttachmentDescription colorAttachmentDescription = 103 { 104 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags 105 colorFormat, // VkFormat format 106 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples 107 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp 108 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp 109 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp 110 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp 111 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout 112 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout 113 }; 114 115 const VkAttachmentDescription inputAttachmentDescription = 116 { 117 VkAttachmentDescriptionFlags(0), // VkAttachmentDescriptionFlags flags; 118 colorFormat, // VkFormat format; 119 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 120 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp; 121 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 122 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 123 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 124 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 125 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout; 126 }; 127 128 const std::vector<VkAttachmentDescription> attachmentDescriptions = { inputAttachmentDescription, inputAttachmentDescription, colorAttachmentDescription }; 129 130 const std::vector<VkAttachmentReference> inputAttachmentReferences = { { 0u, inputAttachmentDescription.finalLayout }, { 1u, inputAttachmentDescription.finalLayout } }; 131 132 const VkAttachmentReference colorAttachmentReference = { 2u, colorAttachmentDescription.finalLayout }; 133 134 const VkSubpassDescription subpassDescription = 135 { 136 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags 137 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint 138 static_cast<deUint32>(inputAttachmentReferences.size()), // deUint32 inputAttachmentCount 139 inputAttachmentReferences.data(), // const VkAttachmentReference* pInputAttachments 140 1u, // deUint32 colorAttachmentCount 141 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments 142 DE_NULL, // const VkAttachmentReference* pResolveAttachments 143 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment 144 0u, // deUint32 preserveAttachmentCount 145 DE_NULL // const deUint32* pPreserveAttachments 146 }; 147 148 const VkRenderPassCreateInfo renderPassInfo = 149 { 150 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType 151 DE_NULL, // const void* pNext 152 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags 153 (deUint32)attachmentDescriptions.size(), // deUint32 attachmentCount 154 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments 155 1u, // deUint32 subpassCount 156 &subpassDescription, // const VkSubpassDescription* pSubpasses 157 0u, // deUint32 dependencyCount 158 DE_NULL // const VkSubpassDependency* pDependencies 159 }; 160 161 return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo); 162} 163 164struct TestParams 165{ 166 TestParams (const PipelineConstructionType pipelineConstructionType, 167 const TestType testType, 168 const bool useCompShader, 169 const tcu::IVec2 framebufferSize, 170 const deUint32 descCount) 171 : m_pipelineConstructionType (pipelineConstructionType) 172 , m_testType (testType) 173 , m_useCompShader (useCompShader) 174 , m_framebufferSize (framebufferSize) 175 , m_descCount (descCount) 176 {} 177 178 const PipelineConstructionType m_pipelineConstructionType; 179 const TestType m_testType; 180 const bool m_useCompShader; 181 const tcu::IVec2 m_framebufferSize; 182 const deUint32 m_descCount; 183 184 deUint32 getDescCount() const 185 { 186 deUint32 descCnt = m_descCount; 187 188 if (m_testType == TestType::StorageBuffers && m_useCompShader) 189 descCnt = m_descCount - 1u; 190 191 return descCnt; 192 } 193}; 194 195class DescriptorLimitTestInstance : public vkt::TestInstance 196{ 197public: 198 DescriptorLimitTestInstance (Context& context, 199 const TestParams& params) 200 : vkt::TestInstance (context) 201 , m_params (params) 202 {} 203 204 ~DescriptorLimitTestInstance () 205 {} 206 207 virtual tcu::TestStatus iterate (void); 208 209private: 210 struct BufferInfo 211 { 212 tcu::Vec4 color; 213 }; 214 TestParams m_params; 215}; 216 217tcu::TestStatus DescriptorLimitTestInstance::iterate (void) 218{ 219 tcu::TestLog& log = m_context.getTestContext().getLog(); 220 const InstanceInterface& vki = m_context.getInstanceInterface(); 221 const DeviceInterface& vk = m_context.getDeviceInterface(); 222 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 223 const VkDevice vkDevice = m_context.getDevice(); 224 Allocator& allocator = m_context.getDefaultAllocator(); 225 const VkQueue queue = m_context.getUniversalQueue(); 226 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 227 VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 228 229 // Pick correct test parameters based on test type 230 const VkShaderStageFlags shaderStageFlags = m_params.m_useCompShader ? VkShaderStageFlags(VK_SHADER_STAGE_COMPUTE_BIT) : VkShaderStageFlags(VK_SHADER_STAGE_FRAGMENT_BIT); 231 const VkPipelineStageFlags pipelineStageFlags = m_params.m_useCompShader ? VkPipelineStageFlags(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) : VkPipelineStageFlags(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); 232 233 const VkImageUsageFlags imageFlags = m_params.m_testType == TestType::InputAttachments 234 ? VkImageUsageFlags(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) 235 : m_params.m_testType == TestType::StorageImages 236 ? VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT 237 : VkImageUsageFlags(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); 238 239 const VkImageLayout finalImageLayout = m_params.m_testType == TestType::InputAttachments 240 ? VkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) 241 : m_params.m_testType == TestType::StorageImages 242 ? VkImageLayout(VK_IMAGE_LAYOUT_GENERAL) 243 : VkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 244 245 // Create shaders 246 ShaderWrapper vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0u); 247 ShaderWrapper testedShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("test"), 0u); 248 249 // Create images 250 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 251 const Move<VkImage> colorImage (makeImage(vk, vkDevice, makeImageCreateInfo(m_params.m_framebufferSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))); 252 const de::MovePtr<Allocation> colorImageAlloc (bindImage(vk, vkDevice, allocator, *colorImage, MemoryRequirement::Any)); 253 const Move<VkImageView> colorImageView (makeImageView(vk, vkDevice, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)); 254 255 const Move<VkImage> inputImages[2] { (makeImage(vk, vkDevice, makeImageCreateInfo(m_params.m_framebufferSize, colorFormat, imageFlags))) 256 , (makeImage(vk, vkDevice, makeImageCreateInfo(m_params.m_framebufferSize, colorFormat, imageFlags))) }; 257 const de::MovePtr<Allocation> inputImageAllocs[2] { (bindImage(vk, vkDevice, allocator, *inputImages[0], MemoryRequirement::Any)) 258 , (bindImage(vk, vkDevice, allocator, *inputImages[1], MemoryRequirement::Any)) }; 259 Move<VkImageView> inputImageViews[2] { (makeImageView(vk, vkDevice, *inputImages[0], VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)) 260 , (makeImageView(vk, vkDevice, *inputImages[1], VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)) }; 261 262 std::array<tcu::Vec4, 2> testColors { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f) }; 263 264 const deUint32 descCount = m_params.getDescCount(); 265 266 for (int i = 0; i < 2; i++) 267 { 268 clearColorImage(vk, vkDevice, queue, queueFamilyIndex, inputImages[i].get(), 269 testColors[i], 270 VK_IMAGE_LAYOUT_UNDEFINED, 271 finalImageLayout, 272 pipelineStageFlags); 273 } 274 275 std::vector<VkImage> images; 276 std::vector<VkImageView> attachmentImages; 277 278 // Create Samplers 279 const tcu::Sampler sampler = tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), true); 280 const tcu::TextureFormat texFormat = mapVkFormat(colorFormat); 281 const VkSamplerCreateInfo samplerParams = mapSampler(sampler, texFormat); 282 283 Move<VkSampler> samplers[2] = { createSampler(vk, vkDevice, &samplerParams) 284 , createSampler(vk, vkDevice, &samplerParams) }; 285 286 // Create buffers 287 const deUint32 bufferElementSize = static_cast<deUint32>(sizeof(tcu::Vec4)); 288 289 const Move<VkBuffer> uboBuffers[2] { (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) 290 , (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) }; 291 292 const Move<VkBuffer> ssboBuffers[2] { (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) 293 , (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) }; 294 295 const Move<VkBuffer> compBufferResult (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)); 296 297 const de::MovePtr<Allocation> uboBufferAllocs[2] { (bindBuffer(vk, vkDevice, allocator, *uboBuffers[0], MemoryRequirement::HostVisible)) 298 , (bindBuffer(vk, vkDevice, allocator, *uboBuffers[1], MemoryRequirement::HostVisible)) }; 299 300 const de::MovePtr<Allocation> ssboBufferAllocs[2] { (bindBuffer(vk, vkDevice, allocator, *ssboBuffers[0], MemoryRequirement::HostVisible)) 301 , (bindBuffer(vk, vkDevice, allocator, *ssboBuffers[1], MemoryRequirement::HostVisible)) }; 302 303 const de::MovePtr<Allocation> ssboBufferAllocResult (bindBuffer(vk, vkDevice, allocator, *compBufferResult, MemoryRequirement::HostVisible)); 304 305 // Fill buffers 306 { 307 char* pPosUbos[2] = { static_cast<char*>(uboBufferAllocs[0]->getHostPtr()) 308 , static_cast<char*>(uboBufferAllocs[1]->getHostPtr()) }; 309 310 char* pPosSsbos[2] = { static_cast<char*>(ssboBufferAllocs[0]->getHostPtr()) 311 , static_cast<char*>(ssboBufferAllocs[1]->getHostPtr()) }; 312 313 char* pPosSsboResult = static_cast<char*>(ssboBufferAllocResult->getHostPtr()); 314 315 *((tcu::Vec4*)pPosUbos[0]) = testColors[0]; 316 *((tcu::Vec4*)pPosUbos[1]) = testColors[1]; 317 318 flushAlloc(vk, vkDevice, *uboBufferAllocs[0]); 319 flushAlloc(vk, vkDevice, *uboBufferAllocs[1]); 320 321 *((tcu::Vec4*)pPosSsbos[0]) = testColors[0]; 322 *((tcu::Vec4*)pPosSsbos[1]) = testColors[1]; 323 324 flushAlloc(vk, vkDevice, *ssboBufferAllocs[0]); 325 flushAlloc(vk, vkDevice, *ssboBufferAllocs[1]); 326 327 *((tcu::Vec4*)pPosSsboResult) = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); 328 329 flushAlloc(vk, vkDevice, *ssboBufferAllocResult); 330 } 331 332 if (m_params.m_testType == TestType::InputAttachments) 333 { 334 for (deUint32 image = 0; image < 2; image++) 335 { 336 images.push_back(*inputImages[image]); 337 attachmentImages.push_back(*inputImageViews[image]); 338 } 339 } 340 341 images.push_back(*colorImage); 342 attachmentImages.push_back(*colorImageView); 343 344 // Result image buffer for fragment shader run 345 const VkDeviceSize resultImageBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * m_params.m_framebufferSize.x() * m_params.m_framebufferSize.y(); 346 const Move<VkBuffer> resultImageBuffer (makeBuffer(vk, vkDevice, resultImageBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); 347 const de::MovePtr<Allocation> resultImageBufferAlloc (bindBuffer(vk, vkDevice, allocator, *resultImageBuffer, MemoryRequirement::HostVisible)); 348 349 // Create vertex buffer 350 const deUint32 numVertices = 6; 351 const VkDeviceSize vertexBufferSizeBytes = 256; 352 Move<VkBuffer> vertexBuffer = (makeBuffer(vk, vkDevice, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); 353 de::MovePtr<Allocation> vertexBufferAlloc = (bindBuffer(vk, vkDevice, allocator, *vertexBuffer, MemoryRequirement::HostVisible)); 354 355 { 356 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr()); 357 358 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f); 359 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f); 360 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f); 361 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f); 362 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f); 363 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f); 364 365 flushAlloc(vk, vkDevice, *vertexBufferAlloc); 366 } 367 368 // Descriptor pool and descriptor set 369 DescriptorPoolBuilder poolBuilder; 370 371 // If compute pipeline is used for testing something else than SSBOs, 372 // one SSBO descriptor is still needed for writing of the test result. 373 if (m_params.m_testType != TestType::StorageBuffers && m_params.m_useCompShader) 374 { 375 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u); 376 } 377 378 if (m_params.m_testType == TestType::Samplers) 379 { 380 poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descCount); 381 } 382 383 if (m_params.m_testType == TestType::UniformBuffers) 384 { 385 poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descCount); 386 } 387 388 if (m_params.m_testType == TestType::StorageBuffers) 389 { 390 // We must be an extra careful here. 391 // Since the result buffer as well the input buffers are allocated from the same descriptor pool 392 // full descriptor count should be used while allocating the pool when compute shader is used. 393 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_params.m_descCount); 394 } 395 396 if (m_params.m_testType == TestType::SampledImages) 397 { 398 poolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descCount); 399 } 400 401 if (m_params.m_testType == TestType::StorageImages) 402 { 403 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descCount); 404 } 405 406 if (m_params.m_testType == TestType::InputAttachments) 407 { 408 poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, descCount); 409 } 410 411 const Move<VkDescriptorPool> descriptorPool = poolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u + (m_params.m_useCompShader ? 1u : 0u)); 412 413 DescriptorSetLayoutBuilder layoutBuilderAttachments; 414 415 if (m_params.m_testType == TestType::Samplers) 416 { 417 for (uint32_t i = 0; i < descCount; i++) 418 { 419 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, shaderStageFlags); 420 } 421 } 422 423 if (m_params.m_testType == TestType::UniformBuffers) 424 { 425 for (uint32_t i = 0; i < descCount; i++) 426 { 427 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, shaderStageFlags); 428 } 429 } 430 431 if (m_params.m_testType == TestType::StorageBuffers) 432 { 433 for (uint32_t i = 0; i < descCount; i++) 434 { 435 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, shaderStageFlags); 436 } 437 } 438 439 if (m_params.m_testType == TestType::SampledImages) 440 { 441 for (uint32_t i = 0; i < descCount; i++) 442 { 443 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, shaderStageFlags); 444 } 445 } 446 447 if (m_params.m_testType == TestType::StorageImages) 448 { 449 for (uint32_t i = 0; i < descCount; i++) 450 { 451 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStageFlags); 452 } 453 } 454 455 if (m_params.m_testType == TestType::InputAttachments) 456 { 457 for (uint32_t i = 0; i < descCount; i++) 458 { 459 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT); 460 } 461 } 462 463 const Move<VkDescriptorSetLayout> descriptorSetLayout = layoutBuilderAttachments.build(vk, vkDevice); 464 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, vkDevice, descriptorPool.get(), descriptorSetLayout.get()); 465 466 467 DescriptorSetLayoutBuilder layoutBuilderAttachmentsResult; 468 469 Move<VkDescriptorSetLayout> descriptorSetLayoutResult; 470 Move<VkDescriptorSet> descriptorSetResult; 471 472 if (m_params.m_useCompShader) 473 { 474 layoutBuilderAttachmentsResult.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); 475 476 descriptorSetLayoutResult = layoutBuilderAttachmentsResult.build(vk, vkDevice); 477 descriptorSetResult = makeDescriptorSet(vk, vkDevice, descriptorPool.get(), descriptorSetLayoutResult.get()); 478 } 479 480 // Setup renderpass and framebuffer. 481 RenderPassWrapper renderPass; 482 if (m_params.m_testType == TestType::InputAttachments) 483 renderPass = (makeRenderPassInputAttachment(vk, vkDevice, m_params.m_pipelineConstructionType, colorFormat)); 484 else 485 renderPass = (RenderPassWrapper(m_params.m_pipelineConstructionType, vk, vkDevice, colorFormat)); 486 487 renderPass.createFramebuffer(vk, vkDevice, static_cast<deUint32>(attachmentImages.size()), images.data(), attachmentImages.data(), m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y()); 488 489 // Command buffer 490 const Move<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 491 const Move<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 492 493 std::vector<VkClearValue> clearColorValues; 494 495 if (m_params.m_testType == TestType::InputAttachments) 496 { 497 clearColorValues.push_back(defaultClearValue(colorFormat)); 498 clearColorValues.push_back(defaultClearValue(colorFormat)); 499 } 500 501 clearColorValues.push_back(defaultClearValue(colorFormat)); 502 503 const VkDeviceSize vertexBufferOffset = 0ull; 504 505 // Bind buffers 506 const vk::VkDescriptorImageInfo imageInfos[2] = { makeDescriptorImageInfo(*samplers[0], *inputImageViews[0], m_params.m_testType == TestType::StorageImages 507 ? VK_IMAGE_LAYOUT_GENERAL 508 : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) 509 , makeDescriptorImageInfo(*samplers[1], *inputImageViews[1], m_params.m_testType == TestType::StorageImages 510 ? VK_IMAGE_LAYOUT_GENERAL 511 : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) }; 512 513 const vk::VkDescriptorBufferInfo uboInfos[2] = { makeDescriptorBufferInfo(*uboBuffers[0], 0u, bufferElementSize) 514 , makeDescriptorBufferInfo(*uboBuffers[1], 0u, bufferElementSize) }; 515 516 const vk::VkDescriptorBufferInfo ssboInfos[2] = { makeDescriptorBufferInfo(*ssboBuffers[0], 0u, bufferElementSize) 517 , makeDescriptorBufferInfo(*ssboBuffers[1], 0u, bufferElementSize) }; 518 519 const vk::VkDescriptorBufferInfo ssboInfoResult = makeDescriptorBufferInfo(*compBufferResult, 0u, bufferElementSize); 520 521 DescriptorSetUpdateBuilder updateBuilder; 522 523 if (m_params.m_useCompShader) 524 { 525 updateBuilder.writeSingle(*descriptorSetResult, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfoResult); 526 } 527 528 if (m_params.m_testType == TestType::Samplers) 529 { 530 for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++) 531 { 532 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfos[0]); 533 } 534 535 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfos[1]); 536 } 537 538 if (m_params.m_testType == TestType::UniformBuffers) 539 { 540 for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++) 541 { 542 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboInfos[0]); 543 } 544 545 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboInfos[1]); 546 } 547 548 if (m_params.m_testType == TestType::StorageBuffers) 549 { 550 for (deUint32 bufferID = 0; bufferID < (descCount - 1u); bufferID++) 551 { 552 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfos[0]); 553 } 554 555 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfos[1]); 556 } 557 558 if (m_params.m_testType == TestType::SampledImages) 559 { 560 for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++) 561 { 562 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfos[0]); 563 } 564 565 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfos[1]); 566 } 567 568 if (m_params.m_testType == TestType::StorageImages) 569 { 570 for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++) 571 { 572 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfos[0]); 573 } 574 575 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfos[1]); 576 } 577 578 if (m_params.m_testType == TestType::InputAttachments) 579 { 580 for (deUint32 bufferID = 0; bufferID < descCount - 1u; bufferID++) 581 { 582 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[0]); 583 } 584 585 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descCount - 1u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[1]); 586 } 587 588 updateBuilder.update(vk, vkDevice); 589 590 // Create pipeline layout 591 std::vector<VkDescriptorSetLayout> descSetLayouts = { descriptorSetLayout.get() }; 592 593 if (m_params.m_useCompShader) 594 { 595 descSetLayouts.push_back(descriptorSetLayoutResult.get()); 596 } 597 598 const VkPipelineLayoutCreateInfo pipelineLayoutInfo = 599 { 600 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 601 DE_NULL, // const void* pNext; 602 0u, // VkPipelineLayoutCreateFlags flags; 603 static_cast<deUint32>(descSetLayouts.size()), // deUint32 descriptorSetCount; 604 descSetLayouts.data(), // const VkDescriptorSetLayout* pSetLayouts; 605 0u, // deUint32 pushConstantRangeCount; 606 DE_NULL // const VkPushDescriptorRange* pPushDescriptorRanges; 607 }; 608 609 const PipelineLayoutWrapper pipelineLayout (m_params.m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutInfo); 610 Move<VkPipeline> computePipeline {}; 611 GraphicsPipelineWrapper graphicsPipelineWrapper { vki, vk, physicalDevice, vkDevice, m_context.getDeviceExtensions(), m_params.m_pipelineConstructionType }; 612 613 if (m_params.m_useCompShader) 614 { 615 computePipeline = (makeComputePipeline(vk, vkDevice, pipelineLayout.get(), testedShaderModule.getModule())); 616 } 617 else 618 { 619 const std::vector<VkViewport> viewports { makeViewport(m_params.m_framebufferSize) }; 620 const std::vector<VkRect2D> scissors { makeRect2D(m_params.m_framebufferSize) }; 621 VkSampleMask sampleMask = 0x1; 622 623 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo 624 { 625 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType 626 DE_NULL, // const void* pNext 627 0u, // VkPipelineMultisampleStateCreateFlags flags 628 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples 629 DE_FALSE, // VkBool32 sampleShadingEnable 630 0.0f, // float minSampleShading 631 &sampleMask, // const VkSampleMask* pSampleMask 632 DE_FALSE, // VkBool32 alphaToCoverageEnable 633 DE_FALSE, // VkBool32 alphaToOneEnable 634 }; 635 636 graphicsPipelineWrapper.setDefaultDepthStencilState() 637 .setDefaultColorBlendState() 638 .setDefaultRasterizationState() 639 .setupVertexInputState() 640 .setupPreRasterizationShaderState(viewports, 641 scissors, 642 pipelineLayout, 643 renderPass.get(), 644 0u, 645 vertexShaderModule) 646 .setupFragmentShaderState(pipelineLayout, 647 renderPass.get(), 648 0u, 649 testedShaderModule, 650 DE_NULL, 651 &multisampleStateCreateInfo) 652 .setupFragmentOutputState(renderPass.get(), 0u, DE_NULL, &multisampleStateCreateInfo) 653 .setMonolithicPipelineLayout(pipelineLayout) 654 .buildPipeline(); 655 } 656 657 beginCommandBuffer(vk, *cmdBuffer); 658 659 if (m_params.m_useCompShader) 660 { 661 const std::vector<VkDescriptorSet> descSets = { descriptorSet.get(), descriptorSetResult.get() }; 662 663 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.get()); 664 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, static_cast<deUint32>(descSets.size()), descSets.data(), 0u, DE_NULL); 665 vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u); 666 } 667 else 668 { 669 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y()), static_cast<deUint32>(clearColorValues.size()), clearColorValues.data()); 670 graphicsPipelineWrapper.bind(*cmdBuffer); 671 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 672 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 673 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u); 674 renderPass.end(vk, *cmdBuffer); 675 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *resultImageBuffer, m_params.m_framebufferSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); 676 } 677 678 endCommandBuffer(vk, *cmdBuffer); 679 680 submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer); 681 682 // Check results 683 if (!m_params.m_useCompShader) 684 { 685 invalidateAlloc(vk, vkDevice, *resultImageBufferAlloc); 686 687 const tcu::ConstPixelBufferAccess imagePixelAccess (mapVkFormat(colorFormat), m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y(), 1, resultImageBufferAlloc->getHostPtr()); 688 const tcu::TextureLevel referenceTexture = generateColorImage(colorFormat, m_params.m_framebufferSize, testColors[1]); 689 690 if (!tcu::floatThresholdCompare(log, "Compare color output", "Image result comparison", referenceTexture.getAccess(), imagePixelAccess, tcu::Vec4(0.0f), tcu::COMPARE_LOG_RESULT)) 691 return tcu::TestStatus::fail("Rendered color image is not correct"); 692 } 693 else 694 { 695 invalidateAlloc(vk, vkDevice, *ssboBufferAllocResult); 696 const tcu::Vec4 resultValue = *static_cast<tcu::Vec4*>(ssboBufferAllocResult->getHostPtr()); 697 698 if (!(resultValue == tcu::Vec4(0.0, 1.0, 0.0, 1.0))) 699 return tcu::TestStatus::fail("Result buffer value is not correct"); 700 } 701 702 return tcu::TestStatus::pass("Success"); 703} 704 705class DescriptorLimitTest : public vkt::TestCase 706{ 707public: 708 DescriptorLimitTest (tcu::TestContext& testContext, 709 const std::string& name, 710 const TestParams& params) 711 : TestCase(testContext, name) 712 , m_params (params) 713 {} 714 715 virtual ~DescriptorLimitTest (void) 716 {} 717 718 virtual void initPrograms (SourceCollections& programCollection) const; 719 virtual void checkSupport (Context& context) const; 720 virtual TestInstance* createInstance (Context& context) const; 721 722private: 723 TestParams m_params; 724}; 725 726void DescriptorLimitTest::initPrograms (SourceCollections& sourceCollections) const 727{ 728 std::ostringstream testTypeStr; 729 std::ostringstream fragResultStr; 730 std::ostringstream compResultStr; 731 const deUint32 descCount = m_params.getDescCount(); 732 733 if (m_params.m_testType == TestType::Samplers) 734 { 735 testTypeStr << "layout(set = 0, binding = " << descCount - 1u << ") uniform sampler2D texSamplerInput;\n"; 736 737 fragResultStr << " const vec2 coords = vec2(0, 0);\n" 738 << " fragColor = texture(texSamplerInput, coords);\n"; 739 740 compResultStr << " const vec2 coords = vec2(0, 0);\n" 741 << " outputData.color = texture(texSamplerInput, coords);\n"; 742 } 743 744 if (m_params.m_testType == TestType::UniformBuffers) 745 { 746 testTypeStr << "layout(set = 0, binding = " << descCount - 1u << ") uniform uboInput\n" 747 << "{\n" 748 << " vec4 color;\n" 749 << "} inputData;\n" 750 << "\n"; 751 752 fragResultStr << " fragColor = inputData.color;\n"; 753 compResultStr << " outputData.color = inputData.color;\n"; 754 } 755 756 if (m_params.m_testType == TestType::StorageBuffers) 757 { 758 testTypeStr << "layout(set = 0, binding = " << (descCount - 1u) << ") readonly buffer ssboInput\n" 759 << "{\n" 760 << " vec4 color;\n" 761 << "} inputData;\n" 762 << "\n"; 763 764 fragResultStr << " fragColor = inputData.color;\n"; 765 compResultStr << " outputData.color = inputData.color;\n"; 766 } 767 768 if (m_params.m_testType == TestType::SampledImages) 769 { 770 testTypeStr << "#extension GL_EXT_samplerless_texture_functions : enable\n" 771 << "layout(set = 0, binding = " << descCount - 1u << ") uniform texture2D imageInput;\n"; 772 773 fragResultStr << " fragColor = texelFetch(imageInput, ivec2(gl_FragCoord.xy), 0);\n"; 774 compResultStr << " const ivec2 coords = ivec2(0, 0);\n" 775 << " outputData.color = texelFetch(imageInput, coords, 0);\n"; 776 } 777 778 if (m_params.m_testType == TestType::StorageImages) 779 { 780 testTypeStr << "#extension GL_EXT_samplerless_texture_functions : enable\n" 781 << "layout(set = 0, binding = " << descCount - 1u << ", rgba8) uniform image2D imageInput;\n"; 782 783 fragResultStr << " fragColor = imageLoad(imageInput, ivec2(gl_FragCoord.xy));\n"; 784 compResultStr << " const ivec2 coords = ivec2(0, 0);\n" 785 << " outputData.color = imageLoad(imageInput, coords);\n"; 786 } 787 788 if (m_params.m_testType == TestType::InputAttachments) 789 { 790 testTypeStr << "layout (input_attachment_index = 1, set = 0, binding = " << descCount - 1u << ") uniform subpassInput imageInput;\n"; 791 792 fragResultStr << " fragColor = subpassLoad(imageInput);\n"; 793 compResultStr << " outputData.color = vec4(0.0, 0.0, 0.0, 1.0);\n"; 794 } 795 796 std::ostringstream vertexSrc; 797 vertexSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 798 << "\n" 799 << "layout(location = 0) in vec4 position;\n" 800 << "\n" 801 << "void main (void)\n" 802 << "{\n" 803 << " gl_Position = position;\n" 804 << "}\n"; 805 806 sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc.str()); 807 808 std::ostringstream testSrc; 809 810 if (!m_params.m_useCompShader) 811 { 812 testSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 813 << "\n" 814 << "layout(location = 0) out vec4 fragColor;\n" 815 << "\n" 816 << testTypeStr.str() 817 << "void main (void)\n" 818 << "{\n" 819 << fragResultStr.str() 820 << "}\n"; 821 822 sourceCollections.glslSources.add("test") << glu::FragmentSource(testSrc.str()); 823 } 824 else 825 { 826 testSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 827 << "\n" 828 // Input attachments are not supported by compute shaders. 829 << (m_params.m_testType != TestType::InputAttachments ? testTypeStr.str() : "") 830 << "layout(set = 1, binding = 0) buffer ssboOutput\n" 831 << "{\n" 832 << " vec4 color;\n" 833 << "} outputData;\n" 834 << "\n" 835 << "void main (void)\n" 836 << "{\n" 837 << compResultStr.str() 838 << "}\n"; 839 840 sourceCollections.glslSources.add("test") << glu::ComputeSource(testSrc.str()); 841 } 842} 843 844void DescriptorLimitTest::checkSupport (Context& context) const 845{ 846 const InstanceInterface& vki = context.getInstanceInterface(); 847 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 848 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits; 849 850 // We have to make sure, that we don't bind anything outside of valid descriptor binding locations determined by maxPerStageResources. 851 if (m_params.m_descCount > limits.maxPerStageResources - 1u) 852 TCU_THROW(NotSupportedError, "maxPerStageResources (" + std::to_string(limits.maxPerStageResources) + ")"); 853 854 if (m_params.m_testType == TestType::Samplers) 855 { 856 if(m_params.m_descCount > limits.maxPerStageDescriptorSamplers) 857 TCU_THROW(NotSupportedError, "maxPerStageDescriptorSamplers (" + std::to_string(limits.maxPerStageDescriptorSamplers) + ")"); 858 } 859 860 if (m_params.m_testType == TestType::UniformBuffers) 861 { 862 if (m_params.m_descCount > limits.maxPerStageDescriptorUniformBuffers) 863 TCU_THROW(NotSupportedError, "maxPerStageDescriptorUniformBuffers (" + std::to_string(limits.maxPerStageDescriptorUniformBuffers) + ")"); 864 } 865 866 if (m_params.m_testType == TestType::StorageBuffers) 867 { 868 if (m_params.m_descCount > limits.maxPerStageDescriptorStorageBuffers) 869 TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageBuffers (" + std::to_string(limits.maxPerStageDescriptorStorageBuffers) + ")"); 870 } 871 872 if (m_params.m_testType == TestType::SampledImages) 873 { 874 if (m_params.m_descCount > limits.maxPerStageDescriptorSampledImages) 875 TCU_THROW(NotSupportedError, "maxPerStageDescriptorSampledImages (" + std::to_string(limits.maxPerStageDescriptorSampledImages) + ")"); 876 } 877 878 if (m_params.m_testType == TestType::StorageImages) 879 { 880 if (m_params.m_descCount > limits.maxPerStageDescriptorStorageImages) 881 TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageImages (" + std::to_string(limits.maxPerStageDescriptorStorageImages) + ")"); 882 } 883 884 if (m_params.m_testType == TestType::InputAttachments) 885 { 886 if (m_params.m_descCount > limits.maxPerStageDescriptorInputAttachments) 887 TCU_THROW(NotSupportedError, "maxPerStageDescriptorInputAttachments (" + std::to_string(limits.maxPerStageDescriptorInputAttachments) + ")"); 888 } 889 890 checkPipelineConstructionRequirements(vki, physDevice, m_params.m_pipelineConstructionType); 891} 892 893TestInstance* DescriptorLimitTest::createInstance (Context& context) const 894{ 895 return new DescriptorLimitTestInstance(context, m_params); 896} 897 898} 899 900tcu::TestCaseGroup* createDescriptorLimitsTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 901{ 902 de::MovePtr<tcu::TestCaseGroup> descriptorLimitTestGroup (new tcu::TestCaseGroup(testCtx, "descriptor_limits")); 903 const tcu::IVec2 frameBufferSize = tcu::IVec2(32, 32); 904 905 const std::vector<deUint32> numDescriptors = 906 { 907 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 908 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u, 909 31u, 32u, 63u, 64u, 100u, 127u, 128u, 199u, 200u, 910 256u, 512u, 1024u, 2048u, 4096u, 8192u, 16384u, 32768u, 65535u 911 }; 912 913 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) 914 { 915 de::MovePtr<tcu::TestCaseGroup> computeShaderGroup(new tcu::TestCaseGroup(testCtx, "compute_shader")); 916 917 for (const auto& descId : numDescriptors) 918 { 919 const deUint32 testValue = descId; 920 921 { 922 TestParams params(pipelineConstructionType, TestType::Samplers, true, frameBufferSize, testValue); 923 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), params)); 924 } 925 926 { 927 TestParams params(pipelineConstructionType, TestType::UniformBuffers, true, frameBufferSize, testValue); 928 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), params)); 929 } 930 931 { 932 TestParams params(pipelineConstructionType, TestType::StorageBuffers, true, frameBufferSize, testValue); 933 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), params)); 934 } 935 936 { 937 TestParams params(pipelineConstructionType, TestType::SampledImages, true, frameBufferSize, testValue); 938 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), params)); 939 } 940 941 { 942 TestParams params(pipelineConstructionType, TestType::StorageImages, true, frameBufferSize, testValue); 943 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), params)); 944 } 945 } 946 947 descriptorLimitTestGroup->addChild(computeShaderGroup.release()); 948 } 949 950 de::MovePtr<tcu::TestCaseGroup> fragmentShaderGroup(new tcu::TestCaseGroup(testCtx, "fragment_shader")); 951 952 for (const auto& descId : numDescriptors) 953 { 954 const deUint32 testValue = descId; 955 956 { 957 TestParams params(pipelineConstructionType, TestType::Samplers, false, frameBufferSize, testValue); 958 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), params)); 959 } 960 961 { 962 TestParams params(pipelineConstructionType, TestType::UniformBuffers, false, frameBufferSize, testValue); 963 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), params)); 964 } 965 966 { 967 TestParams params(pipelineConstructionType, TestType::StorageBuffers, false, frameBufferSize, testValue); 968 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), params)); 969 } 970 971 { 972 TestParams params(pipelineConstructionType, TestType::SampledImages, false, frameBufferSize, testValue); 973 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), params)); 974 } 975 976 { 977 TestParams params(pipelineConstructionType, TestType::StorageImages, false, frameBufferSize, testValue); 978 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), params)); 979 } 980 981 if (!vk::isConstructionTypeShaderObject(pipelineConstructionType)) 982 { 983 TestParams params(pipelineConstructionType, TestType::InputAttachments, false, frameBufferSize, testValue); 984 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "input_attachments_" + std::to_string(testValue), params)); 985 } 986 } 987 988 descriptorLimitTestGroup->addChild(fragmentShaderGroup.release()); 989 990 return descriptorLimitTestGroup.release(); 991} 992 993} // pipeline 994} // vkt 995