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