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