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::__anon6ccf44290111::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::__anon6ccf44290111::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 const VkMemoryBarrier barrier = {
702 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
703 nullptr, // pNext
704 VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask
705 VK_ACCESS_HOST_READ_BIT, // dstAccessMask
706 };
707 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
708 (VkDependencyFlags)0, 1, &barrier, 0, nullptr, 0, nullptr);
709 }
710 else
711 {
712 renderPass.begin(vk, *cmdBuffer,
713 makeRect2D(0, 0, m_params.m_framebufferSize.x(), m_params.m_framebufferSize.y()),
714 static_cast<uint32_t>(clearColorValues.size()), clearColorValues.data());
715 graphicsPipelineWrapper.bind(*cmdBuffer);
716 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
717 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
718 &descriptorSet.get(), 0u, DE_NULL);
719 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
720 renderPass.end(vk, *cmdBuffer);
721 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *resultImageBuffer, m_params.m_framebufferSize,
722 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
723 }
724
725 endCommandBuffer(vk, *cmdBuffer);
726
727 submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
728
729 // Check results
730 if (!m_params.m_useCompShader)
731 {
732 invalidateAlloc(vk, vkDevice, *resultImageBufferAlloc);
733
734 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), m_params.m_framebufferSize.x(),
735 m_params.m_framebufferSize.y(), 1,
736 resultImageBufferAlloc->getHostPtr());
737 const tcu::TextureLevel referenceTexture =
738 generateColorImage(colorFormat, m_params.m_framebufferSize, testColors[1]);
739
740 if (!tcu::floatThresholdCompare(log, "Compare color output", "Image result comparison",
741 referenceTexture.getAccess(), imagePixelAccess, tcu::Vec4(0.0f),
742 tcu::COMPARE_LOG_RESULT))
743 return tcu::TestStatus::fail("Rendered color image is not correct");
744 }
745 else
746 {
747 invalidateAlloc(vk, vkDevice, *ssboBufferAllocResult);
748 const tcu::Vec4 resultValue = *static_cast<tcu::Vec4 *>(ssboBufferAllocResult->getHostPtr());
749
750 if (!(resultValue == tcu::Vec4(0.0, 1.0, 0.0, 1.0)))
751 return tcu::TestStatus::fail("Result buffer value is not correct");
752 }
753
754 return tcu::TestStatus::pass("Success");
755 }
756
757 class DescriptorLimitTest : public vkt::TestCase
758 {
759 public:
DescriptorLimitTest(tcu::TestContext & testContext,const std::string & name,const TestParams & params)760 DescriptorLimitTest(tcu::TestContext &testContext, const std::string &name, const TestParams ¶ms)
761 : TestCase(testContext, name)
762 , m_params(params)
763 {
764 }
765
~DescriptorLimitTest(void)766 virtual ~DescriptorLimitTest(void)
767 {
768 }
769
770 virtual void initPrograms(SourceCollections &programCollection) const;
771 virtual void checkSupport(Context &context) const;
772 virtual TestInstance *createInstance(Context &context) const;
773
774 private:
775 TestParams m_params;
776 };
777
initPrograms(SourceCollections & sourceCollections) const778 void DescriptorLimitTest::initPrograms(SourceCollections &sourceCollections) const
779 {
780 std::ostringstream testTypeStr;
781 std::ostringstream fragResultStr;
782 std::ostringstream compResultStr;
783 const uint32_t descCount = m_params.getDescCount();
784
785 if (m_params.m_testType == TestType::Samplers)
786 {
787 testTypeStr << "layout(set = 0, binding = " << descCount - 1u << ") uniform sampler2D texSamplerInput;\n";
788
789 fragResultStr << " const vec2 coords = vec2(0, 0);\n"
790 << " fragColor = texture(texSamplerInput, coords);\n";
791
792 compResultStr << " const vec2 coords = vec2(0, 0);\n"
793 << " outputData.color = texture(texSamplerInput, coords);\n";
794 }
795
796 if (m_params.m_testType == TestType::UniformBuffers)
797 {
798 testTypeStr << "layout(set = 0, binding = " << descCount - 1u << ") uniform uboInput\n"
799 << "{\n"
800 << " vec4 color;\n"
801 << "} inputData;\n"
802 << "\n";
803
804 fragResultStr << " fragColor = inputData.color;\n";
805 compResultStr << " outputData.color = inputData.color;\n";
806 }
807
808 if (m_params.m_testType == TestType::StorageBuffers)
809 {
810 testTypeStr << "layout(set = 0, binding = " << (descCount - 1u) << ") readonly buffer ssboInput\n"
811 << "{\n"
812 << " vec4 color;\n"
813 << "} inputData;\n"
814 << "\n";
815
816 fragResultStr << " fragColor = inputData.color;\n";
817 compResultStr << " outputData.color = inputData.color;\n";
818 }
819
820 if (m_params.m_testType == TestType::SampledImages)
821 {
822 testTypeStr << "#extension GL_EXT_samplerless_texture_functions : enable\n"
823 << "layout(set = 0, binding = " << descCount - 1u << ") uniform texture2D imageInput;\n";
824
825 fragResultStr << " fragColor = texelFetch(imageInput, ivec2(gl_FragCoord.xy), 0);\n";
826 compResultStr << " const ivec2 coords = ivec2(0, 0);\n"
827 << " outputData.color = texelFetch(imageInput, coords, 0);\n";
828 }
829
830 if (m_params.m_testType == TestType::StorageImages)
831 {
832 testTypeStr << "#extension GL_EXT_samplerless_texture_functions : enable\n"
833 << "layout(set = 0, binding = " << descCount - 1u << ", rgba8) uniform image2D imageInput;\n";
834
835 fragResultStr << " fragColor = imageLoad(imageInput, ivec2(gl_FragCoord.xy));\n";
836 compResultStr << " const ivec2 coords = ivec2(0, 0);\n"
837 << " outputData.color = imageLoad(imageInput, coords);\n";
838 }
839
840 if (m_params.m_testType == TestType::InputAttachments)
841 {
842 testTypeStr << "layout (input_attachment_index = 1, set = 0, binding = " << descCount - 1u
843 << ") uniform subpassInput imageInput;\n";
844
845 fragResultStr << " fragColor = subpassLoad(imageInput);\n";
846 compResultStr << " outputData.color = vec4(0.0, 0.0, 0.0, 1.0);\n";
847 }
848
849 std::ostringstream vertexSrc;
850 vertexSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
851 << "\n"
852 << "layout(location = 0) in vec4 position;\n"
853 << "\n"
854 << "void main (void)\n"
855 << "{\n"
856 << " gl_Position = position;\n"
857 << "}\n";
858
859 sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc.str());
860
861 std::ostringstream testSrc;
862
863 if (!m_params.m_useCompShader)
864 {
865 testSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
866 << "\n"
867 << "layout(location = 0) out vec4 fragColor;\n"
868 << "\n"
869 << testTypeStr.str() << "void main (void)\n"
870 << "{\n"
871 << fragResultStr.str() << "}\n";
872
873 sourceCollections.glslSources.add("test") << glu::FragmentSource(testSrc.str());
874 }
875 else
876 {
877 testSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
878 << "\n"
879 // Input attachments are not supported by compute shaders.
880 << (m_params.m_testType != TestType::InputAttachments ? testTypeStr.str() : "")
881 << "layout(set = 1, binding = 0) buffer ssboOutput\n"
882 << "{\n"
883 << " vec4 color;\n"
884 << "} outputData;\n"
885 << "\n"
886 << "void main (void)\n"
887 << "{\n"
888 << compResultStr.str() << "}\n";
889
890 sourceCollections.glslSources.add("test") << glu::ComputeSource(testSrc.str());
891 }
892 }
893
checkSupport(Context & context) const894 void DescriptorLimitTest::checkSupport(Context &context) const
895 {
896 const InstanceInterface &vki = context.getInstanceInterface();
897 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
898 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
899 #ifdef CTS_USES_VULKANSC
900 const VkPhysicalDeviceVulkanSC10Properties scProps = getPhysicalDeviceVulkanSC10Properties(vki, physDevice);
901
902 if (m_params.m_descCount > scProps.maxDescriptorSetLayoutBindings)
903 TCU_THROW(NotSupportedError,
904 "maxDescriptorSetLayoutBindings (" + std::to_string(scProps.maxDescriptorSetLayoutBindings) + ")");
905 #endif // CTS_USES_VULKANSC
906
907 // We have to make sure, that we don't bind anything outside of valid descriptor binding locations determined by maxPerStageResources.
908 if (m_params.m_descCount > limits.maxPerStageResources - 1u)
909 TCU_THROW(NotSupportedError, "maxPerStageResources (" + std::to_string(limits.maxPerStageResources) + ")");
910
911 if (m_params.m_testType == TestType::Samplers)
912 {
913 if (m_params.m_descCount > limits.maxPerStageDescriptorSamplers)
914 TCU_THROW(NotSupportedError,
915 "maxPerStageDescriptorSamplers (" + std::to_string(limits.maxPerStageDescriptorSamplers) + ")");
916 }
917
918 if (m_params.m_testType == TestType::UniformBuffers)
919 {
920 if (m_params.m_descCount > limits.maxPerStageDescriptorUniformBuffers)
921 TCU_THROW(NotSupportedError, "maxPerStageDescriptorUniformBuffers (" +
922 std::to_string(limits.maxPerStageDescriptorUniformBuffers) + ")");
923 }
924
925 if (m_params.m_testType == TestType::StorageBuffers)
926 {
927 if (m_params.m_descCount > limits.maxPerStageDescriptorStorageBuffers)
928 TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageBuffers (" +
929 std::to_string(limits.maxPerStageDescriptorStorageBuffers) + ")");
930 }
931
932 if (m_params.m_testType == TestType::SampledImages)
933 {
934 if (m_params.m_descCount > limits.maxPerStageDescriptorSampledImages)
935 TCU_THROW(NotSupportedError, "maxPerStageDescriptorSampledImages (" +
936 std::to_string(limits.maxPerStageDescriptorSampledImages) + ")");
937 }
938
939 if (m_params.m_testType == TestType::StorageImages)
940 {
941 if (m_params.m_descCount > limits.maxPerStageDescriptorStorageImages)
942 TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageImages (" +
943 std::to_string(limits.maxPerStageDescriptorStorageImages) + ")");
944 }
945
946 if (m_params.m_testType == TestType::InputAttachments)
947 {
948 if (m_params.m_descCount > limits.maxPerStageDescriptorInputAttachments)
949 TCU_THROW(NotSupportedError, "maxPerStageDescriptorInputAttachments (" +
950 std::to_string(limits.maxPerStageDescriptorInputAttachments) + ")");
951 }
952
953 checkPipelineConstructionRequirements(vki, physDevice, m_params.m_pipelineConstructionType);
954 }
955
createInstance(Context & context) const956 TestInstance *DescriptorLimitTest::createInstance(Context &context) const
957 {
958 return new DescriptorLimitTestInstance(context, m_params);
959 }
960
961 } // namespace
962
createDescriptorLimitsTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)963 tcu::TestCaseGroup *createDescriptorLimitsTests(tcu::TestContext &testCtx,
964 PipelineConstructionType pipelineConstructionType)
965 {
966 de::MovePtr<tcu::TestCaseGroup> descriptorLimitTestGroup(new tcu::TestCaseGroup(testCtx, "descriptor_limits"));
967 const tcu::IVec2 frameBufferSize = tcu::IVec2(32, 32);
968
969 const std::vector<uint32_t> numDescriptors = {3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u,
970 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u,
971 31u, 32u, 63u, 64u, 100u, 127u, 128u, 199u, 200u,
972 256u, 512u, 1024u, 2048u, 4096u, 8192u, 16384u, 32768u, 65535u};
973
974 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
975 {
976 de::MovePtr<tcu::TestCaseGroup> computeShaderGroup(new tcu::TestCaseGroup(testCtx, "compute_shader"));
977
978 for (const auto &descId : numDescriptors)
979 {
980 const uint32_t testValue = descId;
981
982 {
983 TestParams params(pipelineConstructionType, TestType::Samplers, true, frameBufferSize, testValue);
984 computeShaderGroup->addChild(
985 new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), params));
986 }
987
988 {
989 TestParams params(pipelineConstructionType, TestType::UniformBuffers, true, frameBufferSize, testValue);
990 computeShaderGroup->addChild(
991 new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), params));
992 }
993
994 {
995 TestParams params(pipelineConstructionType, TestType::StorageBuffers, true, frameBufferSize, testValue);
996 computeShaderGroup->addChild(
997 new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), params));
998 }
999
1000 {
1001 TestParams params(pipelineConstructionType, TestType::SampledImages, true, frameBufferSize, testValue);
1002 computeShaderGroup->addChild(
1003 new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), params));
1004 }
1005
1006 {
1007 TestParams params(pipelineConstructionType, TestType::StorageImages, true, frameBufferSize, testValue);
1008 computeShaderGroup->addChild(
1009 new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), params));
1010 }
1011 }
1012
1013 descriptorLimitTestGroup->addChild(computeShaderGroup.release());
1014 }
1015
1016 de::MovePtr<tcu::TestCaseGroup> fragmentShaderGroup(new tcu::TestCaseGroup(testCtx, "fragment_shader"));
1017
1018 for (const auto &descId : numDescriptors)
1019 {
1020 const uint32_t testValue = descId;
1021
1022 {
1023 TestParams params(pipelineConstructionType, TestType::Samplers, false, frameBufferSize, testValue);
1024 fragmentShaderGroup->addChild(
1025 new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), params));
1026 }
1027
1028 {
1029 TestParams params(pipelineConstructionType, TestType::UniformBuffers, false, frameBufferSize, testValue);
1030 fragmentShaderGroup->addChild(
1031 new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), params));
1032 }
1033
1034 {
1035 TestParams params(pipelineConstructionType, TestType::StorageBuffers, false, frameBufferSize, testValue);
1036 fragmentShaderGroup->addChild(
1037 new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), params));
1038 }
1039
1040 {
1041 TestParams params(pipelineConstructionType, TestType::SampledImages, false, frameBufferSize, testValue);
1042 fragmentShaderGroup->addChild(
1043 new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), params));
1044 }
1045
1046 {
1047 TestParams params(pipelineConstructionType, TestType::StorageImages, false, frameBufferSize, testValue);
1048 fragmentShaderGroup->addChild(
1049 new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), params));
1050 }
1051
1052 if (!vk::isConstructionTypeShaderObject(pipelineConstructionType))
1053 {
1054 TestParams params(pipelineConstructionType, TestType::InputAttachments, false, frameBufferSize, testValue);
1055 fragmentShaderGroup->addChild(
1056 new DescriptorLimitTest(testCtx, "input_attachments_" + std::to_string(testValue), params));
1057 }
1058 }
1059
1060 descriptorLimitTestGroup->addChild(fragmentShaderGroup.release());
1061
1062 return descriptorLimitTestGroup.release();
1063 }
1064
1065 } // namespace pipeline
1066 } // namespace vkt
1067