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