1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2022 The Khronos Group Inc.
6 * Copyright (c) 2022 Google Inc.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \file vktPipelineDescriptorLimits.cpp
22 * \brief Descriptor limit tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktPipelineDescriptorLimitsTests.hpp"
26 #include "vktPipelineClearUtil.hpp"
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"
36 #include "tcuImageCompare.hpp"
37 #include "tcuTestLog.hpp"
38 #include "tcuTextureUtil.hpp"
40 #include "deUniquePtr.hpp"
64 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
66 const VkImageCreateInfo imageParams =
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;
87 tcu::TextureLevel generateColorImage (const VkFormat format, const tcu::IVec2 &renderSize, const tcu::Vec4 color)
89 tcu::TextureLevel image(mapVkFormat(format), renderSize.x(), renderSize.y());
90 tcu::clear(image.getAccess(), color);
95 Move<VkRenderPass> makeRenderPassInputAttachment (const DeviceInterface& vk,
96 const VkDevice device,
97 const VkFormat colorFormat)
99 const VkAttachmentDescription colorAttachmentDescription =
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
112 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;
125 const std::vector<VkAttachmentDescription> attachmentDescriptions = { inputAttachmentDescription, inputAttachmentDescription, colorAttachmentDescription };
127 const std::vector<VkAttachmentReference> inputAttachmentReferences = { { 0u, inputAttachmentDescription.finalLayout }, { 1u, inputAttachmentDescription.finalLayout } };
129 const VkAttachmentReference colorAttachmentReference = { 2u, colorAttachmentDescription.finalLayout };
131 const VkSubpassDescription subpassDescription =
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
145 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 (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
158 return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
161 class DescriptorLimitTestInstance : public vkt::TestInstance
164 DescriptorLimitTestInstance (Context& context,
165 const PipelineConstructionType pipelineConstructionType,
166 const TestType testType,
167 const bool useCompShader,
168 const tcu::IVec2 framebufferSize,
169 const deUint32 descCount)
170 : vkt::TestInstance (context)
171 , m_pipelineConstructionType (pipelineConstructionType)
172 , m_testType (testType)
173 , m_useCompShader (useCompShader)
174 , m_framebufferSize (framebufferSize)
175 , m_descCount (descCount)
178 ~DescriptorLimitTestInstance ()
181 virtual tcu::TestStatus iterate (void);
189 const PipelineConstructionType m_pipelineConstructionType;
190 const TestType m_testType;
191 const bool m_useCompShader;
192 const tcu::IVec2 m_framebufferSize;
193 const deUint32 m_descCount;
196 tcu::TestStatus DescriptorLimitTestInstance::iterate (void)
198 tcu::TestLog& log = m_context.getTestContext().getLog();
199 const DeviceInterface& vk = m_context.getDeviceInterface();
200 const VkDevice vkDevice = m_context.getDevice();
201 Allocator& allocator = m_context.getDefaultAllocator();
202 const VkQueue queue = m_context.getUniversalQueue();
203 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
204 VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
206 // Pick correct test parameters based on test type
207 const VkShaderStageFlags shaderStageFlags = m_useCompShader ? VkShaderStageFlags(VK_SHADER_STAGE_COMPUTE_BIT) : VkShaderStageFlags(VK_SHADER_STAGE_FRAGMENT_BIT);
208 const VkPipelineStageFlags pipelineStageFlags = m_useCompShader ? VkPipelineStageFlags(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) : VkPipelineStageFlags(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
210 const VkImageUsageFlags imageFlags = m_testType == TestType::InputAttachments
211 ? VkImageUsageFlags(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
212 : m_testType == TestType::StorageImages
213 ? VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
214 : VkImageUsageFlags(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
216 const VkImageLayout finalImageLayout = m_testType == TestType::InputAttachments
217 ? VkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
218 : m_testType == TestType::StorageImages
219 ? VkImageLayout(VK_IMAGE_LAYOUT_GENERAL)
220 : VkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
223 Move<VkShaderModule> vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0u);
224 Move<VkShaderModule> testedShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("test"), 0u);
227 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
228 const Move<VkImage> colorImage (makeImage(vk, vkDevice, makeImageCreateInfo(m_framebufferSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
229 const de::MovePtr<Allocation> colorImageAlloc (bindImage(vk, vkDevice, allocator, *colorImage, MemoryRequirement::Any));
230 const Move<VkImageView> colorImageView (makeImageView(vk, vkDevice, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
232 const Move<VkImage> inputImages[2] { (makeImage(vk, vkDevice, makeImageCreateInfo(m_framebufferSize, colorFormat, imageFlags)))
233 , (makeImage(vk, vkDevice, makeImageCreateInfo(m_framebufferSize, colorFormat, imageFlags))) };
234 const de::MovePtr<Allocation> inputImageAllocs[2] { (bindImage(vk, vkDevice, allocator, *inputImages[0], MemoryRequirement::Any))
235 , (bindImage(vk, vkDevice, allocator, *inputImages[1], MemoryRequirement::Any)) };
236 Move<VkImageView> inputImageViews[2] { (makeImageView(vk, vkDevice, *inputImages[0], VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange))
237 , (makeImageView(vk, vkDevice, *inputImages[1], VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)) };
239 std::array<tcu::Vec4, 2> testColors { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f) };
241 for (int i = 0; i < 2; i++)
243 clearColorImage(vk, vkDevice, queue, queueFamilyIndex, inputImages[i].get(),
245 VK_IMAGE_LAYOUT_UNDEFINED,
250 std::vector<VkImageView> attachmentImages;
253 const tcu::Sampler sampler = tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), true);
254 const tcu::TextureFormat texFormat = mapVkFormat(colorFormat);
255 const VkSamplerCreateInfo samplerParams = mapSampler(sampler, texFormat);
257 Move<VkSampler> samplers[2] = { createSampler(vk, vkDevice, &samplerParams)
258 , createSampler(vk, vkDevice, &samplerParams) };
261 const deUint32 bufferElementSize = static_cast<deUint32>(sizeof(tcu::Vec4));
263 const Move<VkBuffer> uboBuffers[2] { (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT))
264 , (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) };
266 const Move<VkBuffer> ssboBuffers[2] { (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
267 , (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) };
269 const Move<VkBuffer> compBufferResult (makeBuffer(vk, vkDevice, bufferElementSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
271 const de::MovePtr<Allocation> uboBufferAllocs[2] { (bindBuffer(vk, vkDevice, allocator, *uboBuffers[0], MemoryRequirement::HostVisible))
272 , (bindBuffer(vk, vkDevice, allocator, *uboBuffers[1], MemoryRequirement::HostVisible)) };
274 const de::MovePtr<Allocation> ssboBufferAllocs[2] { (bindBuffer(vk, vkDevice, allocator, *ssboBuffers[0], MemoryRequirement::HostVisible))
275 , (bindBuffer(vk, vkDevice, allocator, *ssboBuffers[1], MemoryRequirement::HostVisible)) };
277 const de::MovePtr<Allocation> ssboBufferAllocResult (bindBuffer(vk, vkDevice, allocator, *compBufferResult, MemoryRequirement::HostVisible));
281 char* pPosUbos[2] = { static_cast<char*>(uboBufferAllocs[0]->getHostPtr())
282 , static_cast<char*>(uboBufferAllocs[1]->getHostPtr()) };
284 char* pPosSsbos[2] = { static_cast<char*>(ssboBufferAllocs[0]->getHostPtr())
285 , static_cast<char*>(ssboBufferAllocs[1]->getHostPtr()) };
287 char* pPosSsboResult = static_cast<char*>(ssboBufferAllocResult->getHostPtr());
289 *((tcu::Vec4*)pPosUbos[0]) = testColors[0];
290 *((tcu::Vec4*)pPosUbos[1]) = testColors[1];
292 flushAlloc(vk, vkDevice, *uboBufferAllocs[0]);
293 flushAlloc(vk, vkDevice, *uboBufferAllocs[1]);
295 *((tcu::Vec4*)pPosSsbos[0]) = testColors[0];
296 *((tcu::Vec4*)pPosSsbos[1]) = testColors[1];
298 flushAlloc(vk, vkDevice, *ssboBufferAllocs[0]);
299 flushAlloc(vk, vkDevice, *ssboBufferAllocs[1]);
301 *((tcu::Vec4*)pPosSsboResult) = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
303 flushAlloc(vk, vkDevice, *ssboBufferAllocResult);
306 if (m_testType == TestType::InputAttachments)
308 for (deUint32 image = 0; image < 2; image++)
310 attachmentImages.push_back(*inputImageViews[image]);
314 attachmentImages.push_back(*colorImageView);
316 // Result image buffer for fragment shader run
317 const VkDeviceSize resultImageBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * m_framebufferSize.x() * m_framebufferSize.y();
318 const Move<VkBuffer> resultImageBuffer (makeBuffer(vk, vkDevice, resultImageBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
319 const de::MovePtr<Allocation> resultImageBufferAlloc (bindBuffer(vk, vkDevice, allocator, *resultImageBuffer, MemoryRequirement::HostVisible));
321 // Create vertex buffer
322 const deUint32 numVertices = 6;
323 const VkDeviceSize vertexBufferSizeBytes = 256;
324 Move<VkBuffer> vertexBuffer = (makeBuffer(vk, vkDevice, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
325 de::MovePtr<Allocation> vertexBufferAlloc = (bindBuffer(vk, vkDevice, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
328 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
330 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
331 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
332 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f);
333 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f);
334 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f);
335 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
337 flushAlloc(vk, vkDevice, *vertexBufferAlloc);
340 // Descriptor pool and descriptor set
341 DescriptorPoolBuilder poolBuilder;
343 // If compute pipeline is used for testing something else than SSBOs,
344 // one SSBO descriptor is still needed for writing of the test result.
345 if (m_testType != TestType::StorageBuffers && m_useCompShader)
347 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
350 if (m_testType == TestType::Samplers)
352 poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, m_descCount);
355 if (m_testType == TestType::UniformBuffers)
357 poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, m_descCount);
360 if (m_testType == TestType::StorageBuffers)
362 // We must be an extra careful here, since we are actually adding another bind for ssbo result buffer
363 // when compute shader is used.
364 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_descCount + (m_useCompShader ? 1u : 0u));
367 if (m_testType == TestType::SampledImages)
369 poolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, m_descCount);
372 if (m_testType == TestType::StorageImages)
374 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, m_descCount);
377 if (m_testType == TestType::InputAttachments)
379 poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_descCount);
382 const Move<VkDescriptorPool> descriptorPool = poolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u + (m_useCompShader ? 1u : 0u));
384 DescriptorSetLayoutBuilder layoutBuilderAttachments;
386 if (m_testType == TestType::Samplers)
388 for (uint32_t i = 0; i < m_descCount; i++)
390 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, shaderStageFlags);
394 if (m_testType == TestType::UniformBuffers)
396 for (uint32_t i = 0; i < m_descCount; i++)
398 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, shaderStageFlags);
402 if (m_testType == TestType::StorageBuffers)
404 for (uint32_t i = 0; i < m_descCount; i++)
406 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, shaderStageFlags);
410 if (m_testType == TestType::SampledImages)
412 for (uint32_t i = 0; i < m_descCount; i++)
414 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, shaderStageFlags);
418 if (m_testType == TestType::StorageImages)
420 for (uint32_t i = 0; i < m_descCount; i++)
422 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStageFlags);
426 if (m_testType == TestType::InputAttachments)
428 for (uint32_t i = 0; i < m_descCount; i++)
430 layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
434 const Move<VkDescriptorSetLayout> descriptorSetLayout = layoutBuilderAttachments.build(vk, vkDevice);
435 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, vkDevice, descriptorPool.get(), descriptorSetLayout.get());
438 DescriptorSetLayoutBuilder layoutBuilderAttachmentsResult;
440 Move<VkDescriptorSetLayout> descriptorSetLayoutResult;
441 Move<VkDescriptorSet> descriptorSetResult;
445 layoutBuilderAttachmentsResult.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
447 descriptorSetLayoutResult = layoutBuilderAttachmentsResult.build(vk, vkDevice);
448 descriptorSetResult = makeDescriptorSet(vk, vkDevice, descriptorPool.get(), descriptorSetLayoutResult.get());
451 // Setup renderpass and framebuffer.
452 const Move<VkRenderPass> renderPass (m_testType == TestType::InputAttachments
453 ? (makeRenderPassInputAttachment(vk, vkDevice, colorFormat))
454 : (makeRenderPass(vk, vkDevice, colorFormat)));
456 const Move<VkFramebuffer> framebuffer (makeFramebuffer(vk, vkDevice, *renderPass, static_cast<deUint32>(attachmentImages.size()), attachmentImages.data(), m_framebufferSize.x(), m_framebufferSize.y()));
459 const Move<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
460 const Move<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
462 std::vector<VkClearValue> clearColorValues;
464 if (m_testType == TestType::InputAttachments)
466 clearColorValues.push_back(defaultClearValue(colorFormat));
467 clearColorValues.push_back(defaultClearValue(colorFormat));
470 clearColorValues.push_back(defaultClearValue(colorFormat));
472 const VkDeviceSize vertexBufferOffset = 0ull;
475 const vk::VkDescriptorImageInfo imageInfos[2] = { makeDescriptorImageInfo(*samplers[0], *inputImageViews[0], m_testType == TestType::StorageImages
476 ? VK_IMAGE_LAYOUT_GENERAL
477 : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
478 , makeDescriptorImageInfo(*samplers[1], *inputImageViews[1], m_testType == TestType::StorageImages
479 ? VK_IMAGE_LAYOUT_GENERAL
480 : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) };
482 const vk::VkDescriptorBufferInfo uboInfos[2] = { makeDescriptorBufferInfo(*uboBuffers[0], 0u, bufferElementSize)
483 , makeDescriptorBufferInfo(*uboBuffers[1], 0u, bufferElementSize) };
485 const vk::VkDescriptorBufferInfo ssboInfos[2] = { makeDescriptorBufferInfo(*ssboBuffers[0], 0u, bufferElementSize)
486 , makeDescriptorBufferInfo(*ssboBuffers[1], 0u, bufferElementSize) };
488 const vk::VkDescriptorBufferInfo ssboInfoResult = makeDescriptorBufferInfo(*compBufferResult, 0u, bufferElementSize);
490 DescriptorSetUpdateBuilder updateBuilder;
494 updateBuilder.writeSingle(*descriptorSetResult, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfoResult);
497 if (m_testType == TestType::Samplers)
499 for (deUint32 bufferID = 0; bufferID < m_descCount - 1u; bufferID++)
501 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfos[0]);
504 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_descCount - 1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfos[1]);
507 if (m_testType == TestType::UniformBuffers)
509 for (deUint32 bufferID = 0; bufferID < m_descCount - 1u; bufferID++)
511 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboInfos[0]);
514 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_descCount - 1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uboInfos[1]);
517 if (m_testType == TestType::StorageBuffers)
519 for (deUint32 bufferID = 0; bufferID < m_descCount - 1u; bufferID++)
521 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfos[0]);
524 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_descCount - 1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &ssboInfos[1]);
527 if (m_testType == TestType::SampledImages)
529 for (deUint32 bufferID = 0; bufferID < m_descCount - 1u; bufferID++)
531 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfos[0]);
534 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_descCount - 1u), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfos[1]);
537 if (m_testType == TestType::StorageImages)
539 for (deUint32 bufferID = 0; bufferID < m_descCount - 1u; bufferID++)
541 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfos[0]);
544 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_descCount - 1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfos[1]);
547 if (m_testType == TestType::InputAttachments)
549 for (deUint32 bufferID = 0; bufferID < m_descCount - 1u; bufferID++)
551 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bufferID), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[0]);
554 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(m_descCount - 1u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[1]);
557 updateBuilder.update(vk, vkDevice);
559 // Create pipeline layout
560 std::vector<VkDescriptorSetLayout> descSetLayouts = { descriptorSetLayout.get() };
564 descSetLayouts.push_back(descriptorSetLayoutResult.get());
567 const VkPipelineLayoutCreateInfo pipelineLayoutInfo =
569 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
570 DE_NULL, // const void* pNext;
571 0u, // VkPipelineLayoutCreateFlags flags;
572 static_cast<deUint32>(descSetLayouts.size()), // deUint32 descriptorSetCount;
573 descSetLayouts.data(), // const VkDescriptorSetLayout* pSetLayouts;
574 0u, // deUint32 pushConstantRangeCount;
575 DE_NULL // const VkPushDescriptorRange* pPushDescriptorRanges;
578 const Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutInfo);
579 Move<VkPipeline> computePipeline {};
580 GraphicsPipelineWrapper graphicsPipelineWrapper { vk, vkDevice, m_pipelineConstructionType };
584 computePipeline = (makeComputePipeline(vk, vkDevice, pipelineLayout.get(), testedShaderModule.get()));
588 const std::vector<VkViewport> viewports { makeViewport(m_framebufferSize) };
589 const std::vector<VkRect2D> scissors { makeRect2D(m_framebufferSize) };
590 VkSampleMask sampleMask = 0x1;
592 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
594 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
595 DE_NULL, // const void* pNext
596 0u, // VkPipelineMultisampleStateCreateFlags flags
597 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples
598 DE_FALSE, // VkBool32 sampleShadingEnable
599 0.0f, // float minSampleShading
600 &sampleMask, // const VkSampleMask* pSampleMask
601 DE_FALSE, // VkBool32 alphaToCoverageEnable
602 DE_FALSE, // VkBool32 alphaToOneEnable
605 graphicsPipelineWrapper.setDefaultDepthStencilState()
606 .setDefaultColorBlendState()
607 .setDefaultRasterizationState()
608 .setupVertexInputState()
609 .setupPreRasterizationShaderState(viewports,
611 pipelineLayout.get(),
614 vertexShaderModule.get())
615 .setupFragmentShaderState(pipelineLayout.get(),
618 testedShaderModule.get(),
620 &multisampleStateCreateInfo)
621 .setupFragmentOutputState(renderPass.get(), 0u, DE_NULL, &multisampleStateCreateInfo)
622 .setMonolithicPipelineLayout(pipelineLayout.get())
626 beginCommandBuffer(vk, *cmdBuffer);
630 const std::vector<VkDescriptorSet> descSets = { descriptorSet.get(), descriptorSetResult.get() };
632 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.get());
633 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, static_cast<deUint32>(descSets.size()), descSets.data(), 0u, DE_NULL);
634 vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u);
638 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, m_framebufferSize.x(), m_framebufferSize.y()), static_cast<deUint32>(clearColorValues.size()), clearColorValues.data());
639 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineWrapper.getPipeline());
640 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
641 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
642 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
643 endRenderPass(vk, *cmdBuffer);
644 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *resultImageBuffer, m_framebufferSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
647 endCommandBuffer(vk, *cmdBuffer);
649 submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
652 if (!m_useCompShader)
654 invalidateAlloc(vk, vkDevice, *resultImageBufferAlloc);
656 const tcu::ConstPixelBufferAccess imagePixelAccess (mapVkFormat(colorFormat), m_framebufferSize.x(), m_framebufferSize.y(), 1, resultImageBufferAlloc->getHostPtr());
657 const tcu::TextureLevel referenceTexture = generateColorImage(colorFormat, m_framebufferSize, testColors[1]);
659 if (!tcu::floatThresholdCompare(log, "Compare color output", "Image result comparison", referenceTexture.getAccess(), imagePixelAccess, tcu::Vec4(0.0f), tcu::COMPARE_LOG_RESULT))
660 return tcu::TestStatus::fail("Rendered color image is not correct");
664 invalidateAlloc(vk, vkDevice, *ssboBufferAllocResult);
665 const tcu::Vec4 resultValue = *static_cast<tcu::Vec4*>(ssboBufferAllocResult->getHostPtr());
667 if (!(resultValue == tcu::Vec4(0.0, 1.0, 0.0, 1.0)))
668 return tcu::TestStatus::fail("Result buffer value is not correct");
671 return tcu::TestStatus::pass("Success");
674 class DescriptorLimitTest : public vkt::TestCase
677 DescriptorLimitTest (tcu::TestContext& testContext,
678 const std::string& name,
679 const std::string& description,
680 const PipelineConstructionType pipelineConstructionType,
681 const TestType testType,
682 const bool useCompShader,
683 const tcu::IVec2 framebufferSize,
684 const deUint32 descCount)
685 : TestCase(testContext, name, description)
686 , m_pipelineConstructionType (pipelineConstructionType)
687 , m_testType (testType)
688 , m_useCompShader (useCompShader)
689 , m_framebufferSize (framebufferSize)
690 , m_descCount (descCount)
693 virtual ~DescriptorLimitTest (void)
696 virtual void initPrograms (SourceCollections& programCollection) const;
697 virtual void checkSupport (Context& context) const;
698 virtual TestInstance* createInstance (Context& context) const;
701 const PipelineConstructionType m_pipelineConstructionType;
702 const TestType m_testType;
703 const bool m_useCompShader;
704 const tcu::IVec2 m_framebufferSize;
705 const deUint32 m_descCount;
708 void DescriptorLimitTest::initPrograms (SourceCollections& sourceCollections) const
710 std::ostringstream testTypeStr;
711 std::ostringstream fragResultStr;
712 std::ostringstream compResultStr;
714 if (m_testType == TestType::Samplers)
716 testTypeStr << "layout(set = 0, binding = " << m_descCount - 1u << ") uniform sampler2D texSamplerInput;\n";
718 fragResultStr << " const vec2 coords = vec2(0, 0);\n"
719 << " fragColor = texture(texSamplerInput, coords);\n";
721 compResultStr << " const vec2 coords = vec2(0, 0);\n"
722 << " outputData.color = texture(texSamplerInput, coords);\n";
725 if (m_testType == TestType::UniformBuffers)
727 testTypeStr << "layout(set = 0, binding = " << m_descCount - 1u << ") uniform uboInput\n"
733 fragResultStr << " fragColor = inputData.color;\n";
734 compResultStr << " outputData.color = inputData.color;\n";
737 if (m_testType == TestType::StorageBuffers)
739 testTypeStr << "layout(set = 0, binding = " << m_descCount - 1u << ") readonly buffer ssboInput\n"
745 fragResultStr << " fragColor = inputData.color;\n";
746 compResultStr << " outputData.color = inputData.color;\n";
749 if (m_testType == TestType::SampledImages)
751 testTypeStr << "#extension GL_EXT_samplerless_texture_functions : enable\n"
752 << "layout(set = 0, binding = " << m_descCount - 1u << ") uniform texture2D imageInput;\n";
754 fragResultStr << " fragColor = texelFetch(imageInput, ivec2(gl_FragCoord.xy), 0);\n";
755 compResultStr << " const ivec2 coords = ivec2(0, 0);\n"
756 << " outputData.color = texelFetch(imageInput, coords, 0);\n";
759 if (m_testType == TestType::StorageImages)
761 testTypeStr << "#extension GL_EXT_samplerless_texture_functions : enable\n"
762 << "layout(set = 0, binding = " << m_descCount - 1u << ", rgba8) uniform image2D imageInput;\n";
764 fragResultStr << " fragColor = imageLoad(imageInput, ivec2(gl_FragCoord.xy));\n";
765 compResultStr << " const ivec2 coords = ivec2(0, 0);\n"
766 << " outputData.color = imageLoad(imageInput, coords);\n";
769 if (m_testType == TestType::InputAttachments)
771 testTypeStr << "layout (input_attachment_index = 0, set = 0, binding = " << m_descCount - 1u << ") uniform subpassInput imageInput;\n";
773 fragResultStr << " fragColor = subpassLoad(imageInput);\n";
774 compResultStr << " outputData.color = vec4(0.0, 0.0, 0.0, 1.0);\n";
777 std::ostringstream vertexSrc;
778 vertexSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
780 << "layout(location = 0) in vec4 position;\n"
782 << "void main (void)\n"
784 << " gl_Position = position;\n"
787 sourceCollections.glslSources.add("vert") << glu::VertexSource(vertexSrc.str());
789 std::ostringstream testSrc;
791 if (!m_useCompShader)
793 testSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
795 << "layout(location = 0) out vec4 fragColor;\n"
798 << "void main (void)\n"
800 << fragResultStr.str()
803 sourceCollections.glslSources.add("test") << glu::FragmentSource(testSrc.str());
807 testSrc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
809 // Input attachments are not supported by compute shaders.
810 << (m_testType != TestType::InputAttachments ? testTypeStr.str() : "")
811 << "layout(set = 1, binding = 0) buffer ssboOutput\n"
816 << "void main (void)\n"
818 << compResultStr.str()
821 sourceCollections.glslSources.add("test") << glu::ComputeSource(testSrc.str());
825 void DescriptorLimitTest::checkSupport (Context& context) const
827 const InstanceInterface& vki = context.getInstanceInterface();
828 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
829 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
831 // We have to make sure, that we don't bind anything outside of valid descriptor binding locations determined by maxPerStageResources.
832 if (m_descCount > limits.maxPerStageResources - 1u)
833 TCU_THROW(NotSupportedError, "maxPerStageResources (" + std::to_string(limits.maxPerStageResources) + ")");
835 if (m_testType == TestType::Samplers)
837 if(m_descCount > limits.maxPerStageDescriptorSamplers)
838 TCU_THROW(NotSupportedError, "maxPerStageDescriptorSamplers (" + std::to_string(limits.maxPerStageDescriptorSamplers) + ")");
841 if (m_testType == TestType::UniformBuffers)
843 if (m_descCount > limits.maxPerStageDescriptorUniformBuffers)
844 TCU_THROW(NotSupportedError, "maxPerStageDescriptorUniformBuffers (" + std::to_string(limits.maxPerStageDescriptorUniformBuffers) + ")");
847 if (m_testType == TestType::StorageBuffers)
849 if (m_descCount > limits.maxPerStageDescriptorStorageBuffers)
850 TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageBuffers (" + std::to_string(limits.maxPerStageDescriptorStorageBuffers) + ")");
853 if (m_testType == TestType::SampledImages)
855 if (m_descCount > limits.maxPerStageDescriptorSampledImages)
856 TCU_THROW(NotSupportedError, "maxPerStageDescriptorSampledImages (" + std::to_string(limits.maxPerStageDescriptorSampledImages) + ")");
859 if (m_testType == TestType::StorageImages)
861 if (m_descCount > limits.maxPerStageDescriptorStorageImages)
862 TCU_THROW(NotSupportedError, "maxPerStageDescriptorStorageImages (" + std::to_string(limits.maxPerStageDescriptorStorageImages) + ")");
865 if (m_testType == TestType::InputAttachments)
867 if (m_descCount > limits.maxPerStageDescriptorInputAttachments)
868 TCU_THROW(NotSupportedError, "maxPerStageDescriptorInputAttachments (" + std::to_string(limits.maxPerStageDescriptorInputAttachments) + ")");
871 checkPipelineLibraryRequirements(vki, physDevice, m_pipelineConstructionType);
874 TestInstance* DescriptorLimitTest::createInstance (Context& context) const
876 return new DescriptorLimitTestInstance(context, m_pipelineConstructionType, m_testType, m_useCompShader, m_framebufferSize, m_descCount);
881 tcu::TestCaseGroup* createDescriptorLimitsTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
883 de::MovePtr<tcu::TestCaseGroup> descriptorLimitTestGroup (new tcu::TestCaseGroup(testCtx, "descriptor_limits", "Descriptor limits tests"));
884 const tcu::IVec2 frameBufferSize = tcu::IVec2(32, 32);
886 const std::vector<deUint32> numDescriptors =
888 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u,
889 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u,
890 31u, 32u, 63u, 64u, 100u, 127u, 128u, 199u, 200u,
891 256u, 512u, 1024u, 2048u, 4096u, 8192u, 16384u, 32768u, 65535u
894 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
896 de::MovePtr<tcu::TestCaseGroup> computeShaderGroup(new tcu::TestCaseGroup(testCtx, "compute_shader", "Compute shader test group"));
898 for (const auto& descId : numDescriptors)
900 const deUint32 testValue = descId;
902 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), "", pipelineConstructionType, TestType::Samplers, true, frameBufferSize, testValue));
903 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), "", pipelineConstructionType, TestType::UniformBuffers, true, frameBufferSize, testValue));
904 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), "", pipelineConstructionType, TestType::StorageBuffers, true, frameBufferSize, testValue));
905 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), "", pipelineConstructionType, TestType::SampledImages, true, frameBufferSize, testValue));
906 computeShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), "", pipelineConstructionType, TestType::StorageImages, true, frameBufferSize, testValue));
909 descriptorLimitTestGroup->addChild(computeShaderGroup.release());
912 de::MovePtr<tcu::TestCaseGroup> fragmentShaderGroup(new tcu::TestCaseGroup(testCtx, "fragment_shader", "Fragment shader test group"));
914 for (const auto& descId : numDescriptors)
916 const deUint32 testValue = descId;
918 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "samplers_" + std::to_string(testValue), "", pipelineConstructionType, TestType::Samplers, false, frameBufferSize, testValue));
919 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "uniform_buffers_" + std::to_string(testValue), "", pipelineConstructionType, TestType::UniformBuffers, false, frameBufferSize, testValue));
920 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_buffers_" + std::to_string(testValue), "", pipelineConstructionType, TestType::StorageBuffers, false, frameBufferSize, testValue));
921 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "sampled_images_" + std::to_string(testValue), "", pipelineConstructionType, TestType::SampledImages, false, frameBufferSize, testValue));
922 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "storage_images_" + std::to_string(testValue), "", pipelineConstructionType, TestType::StorageImages, false, frameBufferSize, testValue));
923 fragmentShaderGroup->addChild(new DescriptorLimitTest(testCtx, "input_attachments_" + std::to_string(testValue), "", pipelineConstructionType, TestType::InputAttachments, false, frameBufferSize, testValue));
926 descriptorLimitTestGroup->addChild(fragmentShaderGroup.release());
928 return descriptorLimitTestGroup.release();