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