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
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)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
generateColorImage(const VkFormat format,const tcu::IVec2 & renderSize,const tcu::Vec4 color)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
makeRenderPassInputAttachment(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)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:
DescriptorLimitTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const TestType testType,const bool useCompShader,const tcu::IVec2 framebufferSize,const deUint32 descCount)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
~DescriptorLimitTestInstance()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
iterate(void)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:
DescriptorLimitTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const PipelineConstructionType pipelineConstructionType,const TestType testType,const bool useCompShader,const tcu::IVec2 framebufferSize,const deUint32 descCount)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
~DescriptorLimitTest(void)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
initPrograms(SourceCollections & sourceCollections) const708 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
checkSupport(Context & context) const825 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
createInstance(Context & context) const874 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
createDescriptorLimitsTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)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
933