• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2024 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20 * \file
21 * \brief Subgroups uniform descriptor indexing tests
22 *//*--------------------------------------------------------------------*/
23 
24 #include "vktSubgroupsUniformDescriptorIndexingTests.hpp"
25 #include "vkBufferWithMemory.hpp"
26 #include "vkBarrierUtil.hpp"
27 #include "vkBuilderUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "deSTLUtil.hpp"
35 #include "tcuStringTemplate.hpp"
36 
37 #include <string_view>
38 #include <array>
39 #include <map>
40 
41 namespace
42 {
43 using namespace vk;
44 using namespace vkt;
45 using namespace tcu;
46 
47 class UniformDescriptorIndexingTestCaseTestInstance : public TestInstance
48 {
49 public:
50     UniformDescriptorIndexingTestCaseTestInstance(Context &context, VkDescriptorType descriptorType);
51     ~UniformDescriptorIndexingTestCaseTestInstance() = default;
52 
53     tcu::TestStatus iterate(void) override;
54 
55 protected:
56     Move<VkRenderPass> setupRenderPass(uint32_t inputAttachmentCount) const;
57 
58     void setupImages(uint32_t imagesCount, uint32_t imageSize, VkImageUsageFlags usage,
59                      uint32_t descriptorImageInfosOffset = 0);
60     void setupStorageBuffers(uint32_t buffersCount, const std::vector<float> &clearColors, VkBufferUsageFlags usage);
61     void setupUniformBuffers(uint32_t descriptorCount, const std::vector<float> &clearColors);
62     void setupTexelBuffer(uint32_t descriptorCount, const std::vector<float> &clearColors, VkBufferUsageFlags usage);
63 
64     VkImageCreateInfo getImageCreateInfo(VkFormat format, VkExtent3D extent, VkImageUsageFlags usage) const;
65 
66     using BufferWithMemoryPtr = std::unique_ptr<BufferWithMemory>;
67     using BufferWithMemoryVec = std::vector<BufferWithMemoryPtr>;
68     using BufferViewPtr       = Move<VkBufferView>;
69     using BufferViewVec       = std::vector<BufferViewPtr>;
70     using ImageWithMemoryPtr  = std::unique_ptr<ImageWithMemory>;
71     using ImageViewPtr        = Move<VkImageView>;
72     using ImageWithMemoryVec  = std::vector<ImageWithMemoryPtr>;
73     using ImageViewVec        = std::vector<ImageViewPtr>;
74     using SamplerPtr          = Move<VkSampler>;
75     using SamplerVec          = std::vector<SamplerPtr>;
76 
77 protected:
78     const uint32_t m_imageSize   = 32;
79     const VkFormat m_imageFormat = VK_FORMAT_R8_UNORM;
80     const VkImageSubresourceRange m_imageSubresourceRange =
81         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
82     VkDescriptorType m_descriptorType;
83 
84     ImageWithMemoryVec m_imagesWithMemoryVec;
85     ImageViewVec m_imagesViewVec;
86     BufferWithMemoryVec m_buffersWithMemoryVec;
87     BufferViewVec m_buffersViewVec;
88     SamplerVec m_samplersVec;
89 
90     std::vector<VkImageView> m_framebufferImageViews;
91     std::vector<VkDescriptorImageInfo> m_imageInfos;
92     std::vector<VkDescriptorBufferInfo> m_bufferInfos;
93     std::vector<VkBufferView> m_bufferViewsRaw;
94 };
95 
UniformDescriptorIndexingTestCaseTestInstance(Context & context,VkDescriptorType descriptorType)96 UniformDescriptorIndexingTestCaseTestInstance::UniformDescriptorIndexingTestCaseTestInstance(
97     Context &context, VkDescriptorType descriptorType)
98     : TestInstance(context)
99     , m_descriptorType(descriptorType)
100 {
101 }
102 
iterate(void)103 tcu::TestStatus UniformDescriptorIndexingTestCaseTestInstance::iterate(void)
104 {
105     struct TestConfig
106     {
107         uint32_t descriptorCount; // number of descriptor of tested type
108         uint32_t imagesCount;     // number of images required by the test (not counting color attachment)
109         uint32_t buffersCount;    // number of buffers required by the test
110         uint32_t samplersCount;   // number of samplers required by the test
111         uint32_t minGroupsCount;  // minimal allowed number of unique colors found in output image
112 
113         TestConfig(uint32_t descriptors, uint32_t images, uint32_t buffers, uint32_t samplers, uint32_t minExpected)
114             : descriptorCount(descriptors)
115             , imagesCount(images)
116             , buffersCount(buffers)
117             , samplersCount(samplers)
118             , minGroupsCount(minExpected)
119         {
120         }
121     };
122 
123     // note: minGroupsCount was arbitrarily selected basing on results returned by implementations;
124     //       there is no obvious verification method for those tests and number of returned groups
125     //       of fragments depends from used image size and from noize used in shader
126     static const std::map<VkDescriptorType, TestConfig> configurationMap{
127         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, TestConfig(4, 0, 4, 0, 4)},
128         {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, TestConfig(12, 0, 1, 0, 9)},
129         {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, TestConfig(16, 0, 1, 0, 5)},
130         {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, TestConfig(16, 0, 1, 0, 5)},
131         {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, TestConfig(4, 4, 0, 0, 4)},
132         {VK_DESCRIPTOR_TYPE_SAMPLER, TestConfig(4, 1, 0, 4, 2)},
133         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, TestConfig(16, 16, 0, 1, 10)},
134         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TestConfig(4, 4, 0, 4, 4)},
135         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, TestConfig(4, 4, 0, 0, 4)},
136     };
137 
138     auto [descriptorCount, imagesCount, buffersCount, samplersCount, minGroupsCount] =
139         configurationMap.at(m_descriptorType);
140 
141     // create vector of required number of clear values
142     std::vector<float> clearColors(descriptorCount + 1, 0.0f);
143     std::vector<VkClearValue> clearValues(descriptorCount + 1);
144     for (uint32_t i = 1; i < (uint32_t)clearColors.size(); ++i)
145     {
146         clearColors[i] = float(i) / float(descriptorCount + 1);
147         clearValues[i] = makeClearValueColor(tcu::Vec4(clearColors[i]));
148     }
149 
150     const VkExtent3D extent   = makeExtent3D(m_imageSize, m_imageSize, 1u);
151     const DeviceInterface &vk = m_context.getDeviceInterface();
152     const VkDevice device     = m_context.getDevice();
153     Allocator &allocator      = m_context.getDefaultAllocator();
154 
155     VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
156     const std::vector<VkViewport> viewports{makeViewport(extent)};
157     const std::vector<VkRect2D> scissors{makeRect2D(extent)};
158 
159     // create image that will be used as color attachment to which we will write test result
160     const auto srl(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
161     const auto copyRegion(makeBufferImageCopy(extent, srl));
162     const VkImageUsageFlags imageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
163     const auto imageLayout((m_descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
164                                VK_IMAGE_LAYOUT_GENERAL :
165                                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
166     ImageWithBuffer outImageWithBuffer(vk, device, allocator, extent, m_imageFormat, imageUsage, VK_IMAGE_TYPE_2D,
167                                        m_imageSubresourceRange);
168     auto outImageView(makeImageView(vk, device, outImageWithBuffer.getImage(), VK_IMAGE_VIEW_TYPE_2D, m_imageFormat,
169                                     m_imageSubresourceRange));
170 
171     m_framebufferImageViews.push_back(*outImageView);
172 
173     if (imagesCount)
174     {
175         m_imagesWithMemoryVec.resize(imagesCount);
176         m_imagesViewVec.resize(imagesCount);
177 
178         // include number of required samplers when allocating DescriptorImageInfo (when there are samplers there are always also images);
179         // but dont include samplersCount when combined image sampler case is executed as images and samplers share DescriptorImageInfos
180         uint32_t imageInfoCount =
181             imagesCount + samplersCount * (m_descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
182         m_imageInfos = std::vector<VkDescriptorImageInfo>(
183             imageInfoCount, makeDescriptorImageInfo(VK_NULL_HANDLE, VK_NULL_HANDLE, imageLayout));
184 
185         if (m_descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
186             setupImages(imagesCount, 3, VK_IMAGE_USAGE_SAMPLED_BIT, samplersCount);
187         else if (m_descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
188             setupImages(imagesCount, 3, VK_IMAGE_USAGE_SAMPLED_BIT);
189         else if (m_descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
190             setupImages(imagesCount, 3, VK_IMAGE_USAGE_SAMPLED_BIT);
191         else if (m_descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
192             setupImages(imagesCount, 3, VK_IMAGE_USAGE_STORAGE_BIT);
193         else if (m_descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
194             setupImages(imagesCount, m_imageSize, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
195     }
196 
197     if (buffersCount)
198     {
199         m_buffersWithMemoryVec.resize(buffersCount);
200         m_bufferInfos = std::vector<VkDescriptorBufferInfo>(descriptorCount,
201                                                             makeDescriptorBufferInfo(VK_NULL_HANDLE, 0, VK_WHOLE_SIZE));
202 
203         if (m_descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
204             setupUniformBuffers(descriptorCount, clearColors);
205         else if (m_descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
206             setupStorageBuffers(buffersCount, clearColors, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
207         else if (m_descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
208             setupTexelBuffer(descriptorCount, clearColors, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
209         else if (m_descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)
210             setupTexelBuffer(descriptorCount, clearColors, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT);
211     }
212 
213     if (samplersCount)
214     {
215         m_samplersVec.resize(samplersCount);
216 
217         // ofset imageInfos only for sampled image case
218         uint32_t descriptorImageInfosOffset = (m_descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) * descriptorCount;
219 
220         VkSamplerCreateInfo samplerCreateInfo = initVulkanStructure();
221         samplerCreateInfo.borderColor         = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
222         VkSamplerAddressMode addressModes[4] = {VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
223                                                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
224                                                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER};
225         for (uint32_t i = 0; i < samplersCount; ++i)
226         {
227             samplerCreateInfo.addressModeU                       = addressModes[i % 4];
228             m_samplersVec[i]                                     = createSampler(vk, device, &samplerCreateInfo);
229             m_imageInfos[descriptorImageInfosOffset + i].sampler = *m_samplersVec[i];
230         }
231     }
232 
233     DescriptorPoolBuilder descriptorPoolBuilder;
234     descriptorPoolBuilder.addType(m_descriptorType, descriptorCount);
235     DescriptorSetLayoutBuilder descriptorSetLayoutBuilder;
236     descriptorSetLayoutBuilder.addBinding(m_descriptorType, descriptorCount, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
237 
238     // some cases require additional descriptor types that are neede to be able to check currently tested ones
239     if (m_descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
240     {
241         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1);
242         descriptorSetLayoutBuilder.addIndexedBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT,
243                                                      4, nullptr);
244     }
245     else if (m_descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
246     {
247         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1);
248         descriptorSetLayoutBuilder.addIndexedBinding(VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT,
249                                                      descriptorCount, nullptr);
250     }
251 
252     // create descriptors
253     const auto descriptorPool(
254         descriptorPoolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
255     const auto descriptorSetLayout(descriptorSetLayoutBuilder.build(vk, device));
256     const auto descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
257 
258     DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
259     descriptorSetUpdateBuilder.write(*descriptorSet, 0, 0, descriptorCount, m_descriptorType,
260                                      de::dataOrNull(m_imageInfos), de::dataOrNull(m_bufferInfos),
261                                      de::dataOrNull(m_bufferViewsRaw));
262 
263     if (m_descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
264         descriptorSetUpdateBuilder.write(*descriptorSet, descriptorCount, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
265                                          &m_imageInfos[descriptorCount], 0, 0);
266     else if (m_descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
267         descriptorSetUpdateBuilder.write(*descriptorSet, descriptorCount, 0, 1, VK_DESCRIPTOR_TYPE_SAMPLER,
268                                          &m_imageInfos[descriptorCount], 0, 0);
269 
270     descriptorSetUpdateBuilder.update(vk, device);
271 
272     const auto pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
273     auto &bc(m_context.getBinaryCollection());
274     const auto vertModule(createShaderModule(vk, device, bc.get("vert")));
275     const auto fragModule(createShaderModule(vk, device, bc.get("frag")));
276     const uint32_t inputsCount((m_descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) * descriptorCount);
277     const auto renderPass(setupRenderPass(inputsCount));
278     const auto framebuffer(makeFramebuffer(vk, device, *renderPass, (uint32_t)m_framebufferImageViews.size(),
279                                            m_framebufferImageViews.data(), m_imageSize, m_imageSize));
280     const auto pipeline(makeGraphicsPipeline(vk, device, *pipelineLayout, *vertModule, VK_NULL_HANDLE, VK_NULL_HANDLE,
281                                              VK_NULL_HANDLE, *fragModule, *renderPass, viewports, scissors,
282                                              VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 0, &vertexInputState));
283 
284     // prepare barriers needed by all test variants
285     const auto beforeClearBarrier(makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
286                                                          VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_NULL_HANDLE,
287                                                          m_imageSubresourceRange));
288     const auto afterClearBarrier(makeImageMemoryBarrier(
289         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
290         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageLayout, VK_NULL_HANDLE, m_imageSubresourceRange));
291     const auto beforeCopyBarrier(makeImageMemoryBarrier(
292         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
293         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outImageWithBuffer.getImage(), m_imageSubresourceRange));
294     const auto bufferAccessMask((m_descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ? VK_ACCESS_UNIFORM_READ_BIT :
295                                                                                           VK_ACCESS_SHADER_READ_BIT);
296     const auto beforeDrawBarrier(
297         makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, bufferAccessMask, VK_NULL_HANDLE, 0, VK_WHOLE_SIZE));
298 
299     const auto queueFamilyIndex(m_context.getUniversalQueueFamilyIndex());
300     const auto cmdPool(
301         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
302     const auto cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
303 
304     beginCommandBuffer(vk, *cmdBuffer);
305 
306     if (imagesCount)
307     {
308         std::vector<VkImageMemoryBarrier> beforeClearBarriers(imagesCount, beforeClearBarrier);
309         std::vector<VkImageMemoryBarrier> afterClearBarriers(imagesCount, afterClearBarrier);
310 
311         for (uint32_t i = 0; i < imagesCount; ++i)
312         {
313             beforeClearBarriers[i].image = **m_imagesWithMemoryVec[i];
314             afterClearBarriers[i].image  = **m_imagesWithMemoryVec[i];
315         }
316 
317         vk.cmdPipelineBarrier(*cmdBuffer, 0, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0, 0, 0, 0, imagesCount,
318                               beforeClearBarriers.data());
319         for (uint32_t i = 0; i < imagesCount; ++i)
320             vk.cmdClearColorImage(*cmdBuffer, **m_imagesWithMemoryVec[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
321                                   &clearValues[i + 1].color, 1, &m_imageSubresourceRange);
322         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u, 0, 0,
323                               0, 0, imagesCount, afterClearBarriers.data());
324     }
325 
326     if (buffersCount)
327     {
328         std::vector<VkBufferMemoryBarrier> beforeDrawBarriers(buffersCount, beforeDrawBarrier);
329         for (uint32_t i = 0; i < buffersCount; ++i)
330             beforeDrawBarriers[i].buffer = **m_buffersWithMemoryVec[i];
331 
332         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0,
333                               0, buffersCount, beforeDrawBarriers.data(), 0, 0);
334     }
335 
336     // draw single triangle big enough to cover whole framebuffer
337     beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, scissors[0], 1, clearValues.data());
338     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
339     vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u,
340                              0);
341     vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
342     endRenderPass(vk, *cmdBuffer);
343 
344     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
345                           0, 0, 0, 0, 1u, &beforeCopyBarrier);
346     vk.cmdCopyImageToBuffer(*cmdBuffer, outImageWithBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
347                             outImageWithBuffer.getBuffer(), 1u, &copyRegion);
348 
349     endCommandBuffer(vk, *cmdBuffer);
350 
351     submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
352 
353     const auto &outBufferAllocation = outImageWithBuffer.getBufferAllocation();
354     invalidateAlloc(vk, device, outBufferAllocation);
355 
356     // count number of fragments that have same values
357     uint8_t *outBufferPtr = static_cast<uint8_t *>(outBufferAllocation.getHostPtr());
358     std::map<uint32_t, uint32_t> resultMap;
359     for (uint32_t i = 0; i < m_imageSize * m_imageSize; ++i)
360     {
361         uint32_t value   = outBufferPtr[i];
362         resultMap[value] = resultMap[value] + 1;
363     }
364 
365     // make sure that none of fragments has background color and there is expected number of color groups
366     if ((resultMap.count(0) == 0) && (resultMap.size() >= minGroupsCount) && (resultMap.size() <= descriptorCount))
367         return tcu::TestStatus::pass("Pass");
368 
369     tcu::PixelBufferAccess resultAccess(mapVkFormat(m_imageFormat), m_imageSize, m_imageSize, 1, outBufferPtr);
370     m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result", "")
371                                         << tcu::TestLog::Image("Output", "", resultAccess) << tcu::TestLog::EndImageSet;
372 
373     if (resultMap.count(0))
374         return tcu::TestStatus::fail(std::to_string(resultMap[0]) + " fragments have background color");
375 
376     return tcu::TestStatus::fail(std::to_string(resultMap.size()) + " groups, expected <" +
377                                  std::to_string(minGroupsCount) + ", " + std::to_string(descriptorCount) + ">");
378 }
379 
setupRenderPass(uint32_t inputAttachmentCount) const380 Move<VkRenderPass> UniformDescriptorIndexingTestCaseTestInstance::setupRenderPass(uint32_t inputAttachmentCount) const
381 {
382     const DeviceInterface &vk = m_context.getDeviceInterface();
383     const VkDevice device     = m_context.getDevice();
384 
385     const VkAttachmentDescription defaultAttachmentDescription{
386         0,                                       // VkAttachmentDescriptionFlags flags
387         m_imageFormat,                           // VkFormat                     format
388         VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits        samples
389         VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp           loadOp
390         VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp          storeOp
391         VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp           stencilLoadOp
392         VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp          stencilStoreOp
393         VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout                initialLayout
394         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout                finalLayout
395     };
396 
397     std::vector<VkAttachmentDescription> attachmentDescriptions(1 + inputAttachmentCount, defaultAttachmentDescription);
398     const VkAttachmentReference colorAttachmentRef{0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
399     std::vector<VkAttachmentReference> inputAttachmentsRefs(4, {0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL});
400 
401     for (uint32_t i = 0; i < inputAttachmentCount; i++)
402     {
403         auto &inputAttachment              = attachmentDescriptions[i + 1];
404         inputAttachment.loadOp             = VK_ATTACHMENT_LOAD_OP_LOAD;
405         inputAttachment.initialLayout      = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
406         inputAttachment.finalLayout        = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
407         inputAttachmentsRefs[i].attachment = i + 1;
408     };
409 
410     const VkSubpassDescription subpassDescription{
411         (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags      flags
412         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint            pipelineBindPoint
413         inputAttachmentCount,            // uint32_t                       inputAttachmentCount
414         inputAttachmentsRefs.data(),     // const VkAttachmentReference*   pInputAttachments
415         1u,                              // uint32_t                       colorAttachmentCount
416         &colorAttachmentRef,             // const VkAttachmentReference*   pColorAttachments
417         nullptr,                         // const VkAttachmentReference*   pResolveAttachments
418         nullptr,                         // const VkAttachmentReference*   pDepthStencilAttachment
419         0u,                              // uint32_t                       preserveAttachmentCount
420         nullptr                          // const uint32_t*                pPreserveAttachments
421     };
422 
423     const VkRenderPassCreateInfo renderPassInfo{
424         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType                sType
425         nullptr,                                   // const void*                    pNext
426         (VkRenderPassCreateFlags)0,                // VkRenderPassCreateFlags        flags
427         (uint32_t)attachmentDescriptions.size(),   // uint32_t                       attachmentCount
428         attachmentDescriptions.data(),             // const VkAttachmentDescription* pAttachments
429         1u,                                        // uint32_t                       subpassCount
430         &subpassDescription,                       // const VkSubpassDescription*    pSubpasses
431         0u,                                        // uint32_t                       dependencyCount
432         nullptr                                    // const VkSubpassDependency*     pDependencies
433     };
434 
435     return createRenderPass(vk, device, &renderPassInfo, nullptr);
436 }
437 
setupImages(uint32_t imagesCount,uint32_t imageSize,VkImageUsageFlags usage,uint32_t descriptorImageInfosOffset)438 void UniformDescriptorIndexingTestCaseTestInstance::setupImages(uint32_t imagesCount, uint32_t imageSize,
439                                                                 VkImageUsageFlags usage,
440                                                                 uint32_t descriptorImageInfosOffset)
441 {
442     const DeviceInterface &vk = m_context.getDeviceInterface();
443     const VkDevice device     = m_context.getDevice();
444     Allocator &allocator      = m_context.getDefaultAllocator();
445 
446     VkImageUsageFlags finalUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | usage;
447     const bool isAttachment      = usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
448     const VkExtent3D extent      = makeExtent3D(imageSize, imageSize, 1u);
449     const VkImageCreateInfo imageCreateInfo(getImageCreateInfo(m_imageFormat, extent, finalUsage));
450 
451     // create additional images that will be used as input attachments
452     if (isAttachment)
453         m_framebufferImageViews.resize(imagesCount + 1);
454 
455     for (uint32_t i = 0; i < imagesCount; ++i)
456     {
457         m_imagesWithMemoryVec[i] =
458             ImageWithMemoryPtr(new ImageWithMemory(vk, device, allocator, imageCreateInfo, vk::MemoryRequirement::Any));
459         m_imagesViewVec[i] = makeImageView(vk, device, **m_imagesWithMemoryVec[i], VK_IMAGE_VIEW_TYPE_2D, m_imageFormat,
460                                            m_imageSubresourceRange);
461         m_imageInfos[descriptorImageInfosOffset + i].imageView = *m_imagesViewVec[i];
462 
463         if (isAttachment)
464             m_framebufferImageViews[i + 1] = *m_imagesViewVec[i]; // first view is output color attachment
465     }
466 }
467 
setupStorageBuffers(uint32_t buffersCount,const std::vector<float> & clearColors,VkBufferUsageFlags usage)468 void UniformDescriptorIndexingTestCaseTestInstance::setupStorageBuffers(uint32_t buffersCount,
469                                                                         const std::vector<float> &clearColors,
470                                                                         VkBufferUsageFlags usage)
471 {
472     const DeviceInterface &vk = m_context.getDeviceInterface();
473     const VkDevice device     = m_context.getDevice();
474     Allocator &allocator      = m_context.getDefaultAllocator();
475 
476     VkDeviceSize bufferValuesCount(m_imageSize * m_imageSize);
477     auto bufferCreateInfo(
478         makeBufferCreateInfo(bufferValuesCount * sizeof(float), VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage));
479 
480     for (uint32_t i = 0; i < buffersCount; ++i)
481     {
482         m_buffersWithMemoryVec[i] = BufferWithMemoryPtr(
483             new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
484         m_bufferInfos[i]    = {**m_buffersWithMemoryVec[i], 0, VK_WHOLE_SIZE};
485         auto *bufferHostPtr = static_cast<float *>(m_buffersWithMemoryVec[i]->getAllocation().getHostPtr());
486 
487         std::fill(bufferHostPtr, bufferHostPtr + bufferValuesCount,
488                   clearColors[1 + i % uint32_t(clearColors.size() - 1)]);
489         flushAlloc(vk, device, m_buffersWithMemoryVec[i]->getAllocation());
490     }
491 }
492 
setupUniformBuffers(uint32_t descriptorCount,const std::vector<float> & clearColors)493 void UniformDescriptorIndexingTestCaseTestInstance::setupUniformBuffers(uint32_t descriptorCount,
494                                                                         const std::vector<float> &clearColors)
495 {
496     const DeviceInterface &vk = m_context.getDeviceInterface();
497     const VkDevice device     = m_context.getDevice();
498     Allocator &allocator      = m_context.getDefaultAllocator();
499 
500     const VkDeviceSize alignment(m_context.getDeviceProperties().limits.minUniformBufferOffsetAlignment);
501     const VkDeviceSize roundedSize(deAlign64(sizeof(float), static_cast<uint32_t>(alignment)));
502 
503     VkBufferCreateInfo bufferCreateInfo(makeBufferCreateInfo(
504         descriptorCount * roundedSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT));
505     m_buffersWithMemoryVec[0] = BufferWithMemoryPtr(
506         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
507 
508     auto *bufferHostPtr = static_cast<uint8_t *>(m_buffersWithMemoryVec[0]->getAllocation().getHostPtr());
509     for (uint32_t i = 0; i < descriptorCount; ++i)
510     {
511         auto &info  = m_bufferInfos[i];
512         info.buffer = **m_buffersWithMemoryVec[0];
513         info.offset = i * roundedSize;
514         info.range  = roundedSize;
515 
516         float data = clearColors[i + 1];
517         deMemcpy(bufferHostPtr + info.offset, &data, sizeof(float));
518     }
519 
520     flushAlloc(vk, device, m_buffersWithMemoryVec[0]->getAllocation());
521 }
522 
setupTexelBuffer(uint32_t descriptorCount,const std::vector<float> & clearColors,VkBufferUsageFlags usage)523 void UniformDescriptorIndexingTestCaseTestInstance::setupTexelBuffer(uint32_t descriptorCount,
524                                                                      const std::vector<float> &clearColors,
525                                                                      VkBufferUsageFlags usage)
526 {
527     const InstanceInterface &vki = m_context.getInstanceInterface();
528     const DeviceInterface &vk    = m_context.getDeviceInterface();
529     const VkDevice device        = m_context.getDevice();
530     Allocator &allocator         = m_context.getDefaultAllocator();
531 
532     auto alignment = m_context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
533     if (m_context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
534     {
535         VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties = initVulkanStructure();
536         VkPhysicalDeviceProperties2 properties2 = initVulkanStructure(&alignmentProperties);
537         vki.getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &properties2);
538 
539         bool isUniformTexelBuffer     = (usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT);
540         VkBool32 singleTexelAlignment = isUniformTexelBuffer ?
541                                             alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
542                                             alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
543         VkDeviceSize align = isUniformTexelBuffer ? alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
544                                                     alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
545         alignment          = align;
546         if (singleTexelAlignment)
547             alignment = de::min(4u, (uint32_t)align);
548     }
549 
550     const uint32_t viewItems(2);
551     const VkDeviceSize usedViewSize(viewItems * sizeof(float));
552     const VkDeviceSize requiredAlignment(alignment - usedViewSize % alignment);
553     const VkDeviceSize alignedViewSize(usedViewSize + requiredAlignment);
554     const VkDeviceSize bufferSize(descriptorCount * alignedViewSize);
555     auto bufferCreateInfo(makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage));
556 
557     m_buffersWithMemoryVec[0] = BufferWithMemoryPtr(
558         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
559     m_bufferInfos[0]    = {**m_buffersWithMemoryVec[0], 0, VK_WHOLE_SIZE};
560     auto &allocation    = m_buffersWithMemoryVec[0]->getAllocation();
561     auto *bufferHostPtr = static_cast<char *>(allocation.getHostPtr());
562 
563     VkBufferViewCreateInfo bufferViewCreateInfo = initVulkanStructure();
564     bufferViewCreateInfo.buffer                 = **m_buffersWithMemoryVec[0];
565     bufferViewCreateInfo.format                 = m_imageFormat;
566     bufferViewCreateInfo.range                  = usedViewSize;
567 
568     m_bufferViewsRaw.resize(descriptorCount);
569     m_buffersViewVec.resize(descriptorCount);
570     for (uint32_t i = 0; i < descriptorCount; ++i)
571     {
572         bufferViewCreateInfo.offset = i * alignedViewSize;
573         m_buffersViewVec[i]         = createBufferView(vk, device, &bufferViewCreateInfo);
574         m_bufferViewsRaw[i]         = *m_buffersViewVec[i];
575 
576         float *viewStart = reinterpret_cast<float *>(bufferHostPtr + bufferViewCreateInfo.offset);
577         std::fill(viewStart, viewStart + viewItems, clearColors[1 + i % uint32_t(clearColors.size() - 1)]);
578     }
579 
580     flushAlloc(vk, device, allocation);
581 }
582 
getImageCreateInfo(VkFormat format,VkExtent3D extent,VkImageUsageFlags usage) const583 VkImageCreateInfo UniformDescriptorIndexingTestCaseTestInstance::getImageCreateInfo(VkFormat format, VkExtent3D extent,
584                                                                                     VkImageUsageFlags usage) const
585 {
586     return {
587         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType       sType
588         nullptr,                             // const void*           pNext
589         0u,                                  // VkImageCreateFlags    flags
590         VK_IMAGE_TYPE_2D,                    // VkImageType           imageType
591         format,                              // VkFormat              format
592         extent,                              // VkExtent3D            extent
593         1u,                                  // uint32_t              mipLevels
594         1u,                                  // uint32_t              arrayLayers
595         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples
596         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling         tiling
597         usage,                               // VkImageUsageFlags     usage
598         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode         sharingMode
599         0u,                                  // uint32_t              queueFamilyIndexCount
600         nullptr,                             // const uint32_t*       pQueueFamilyIndices
601         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout         initialLayout
602     };
603 };
604 
605 class UniformDescriptorIndexingTestCase : public vkt::TestCase
606 {
607 public:
608     UniformDescriptorIndexingTestCase(TestContext &testCtx, const std::string &name, VkDescriptorType descriptorType);
609     virtual ~UniformDescriptorIndexingTestCase(void) = default;
610     virtual void checkSupport(Context &context) const override;
611     virtual void initPrograms(SourceCollections &programCollection) const override;
612     virtual TestInstance *createInstance(Context &context) const override;
613 
614 private:
615     VkDescriptorType m_descriptorType;
616 };
617 
UniformDescriptorIndexingTestCase(TestContext & testCtx,const std::string & name,VkDescriptorType descriptorType)618 UniformDescriptorIndexingTestCase::UniformDescriptorIndexingTestCase(TestContext &testCtx, const std::string &name,
619                                                                      VkDescriptorType descriptorType)
620     : vkt::TestCase(testCtx, name)
621     , m_descriptorType(descriptorType)
622 {
623 }
624 
checkSupport(Context & context) const625 void UniformDescriptorIndexingTestCase::checkSupport(Context &context) const
626 {
627     const auto &sProperties = context.getSubgroupProperties();
628     if (sProperties.subgroupSize == 1)
629         TCU_THROW(NotSupportedError, "subgroupSize is 1");
630     if ((sProperties.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) == 0)
631         TCU_THROW(NotSupportedError, "fragment stage doesn't support subgroup operations");
632 
633     const auto &diFeatures = context.getDescriptorIndexingFeatures();
634     if (!diFeatures.runtimeDescriptorArray)
635         TCU_THROW(NotSupportedError, "runtimeDescriptorArray not supported");
636 
637     switch (m_descriptorType)
638     {
639     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
640         if (!diFeatures.shaderStorageBufferArrayNonUniformIndexing)
641             TCU_THROW(NotSupportedError,
642                       "Non-uniform indexing over storage buffer descriptor arrays is not supported.");
643         break;
644     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
645         if (!diFeatures.shaderUniformBufferArrayNonUniformIndexing)
646             TCU_THROW(NotSupportedError, "Non-uniform indexing for uniform buffer descriptor arrays is not supported.");
647         break;
648     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
649         if (!diFeatures.shaderStorageTexelBufferArrayNonUniformIndexing)
650             TCU_THROW(NotSupportedError,
651                       "Non-uniform indexing for storage texel buffer descriptor arrays is not supported.");
652         break;
653     case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
654         if (!diFeatures.shaderUniformTexelBufferArrayNonUniformIndexing)
655             TCU_THROW(NotSupportedError,
656                       "Non-uniform indexing for uniform texel buffer descriptor arrays is not supported.");
657         break;
658     case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
659         if (!diFeatures.shaderInputAttachmentArrayNonUniformIndexing)
660             TCU_THROW(NotSupportedError,
661                       "Non-uniform indexing over input attachment descriptor arrays is not supported.");
662         break;
663     case VK_DESCRIPTOR_TYPE_SAMPLER:
664         if (!diFeatures.shaderSampledImageArrayNonUniformIndexing)
665             TCU_THROW(NotSupportedError, "Non-uniform indexing over sampler descriptor arrays is not supported.");
666         break;
667     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
668         if (!diFeatures.shaderSampledImageArrayNonUniformIndexing)
669             TCU_THROW(NotSupportedError, "Non-uniform indexing over sampled image descriptor arrays is not supported.");
670         break;
671     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
672         if (!diFeatures.shaderSampledImageArrayNonUniformIndexing)
673             TCU_THROW(NotSupportedError,
674                       "Non-uniform indexing over combined image sampler descriptor arrays is not supported.");
675         break;
676     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
677         if (!diFeatures.shaderStorageImageArrayNonUniformIndexing)
678             TCU_THROW(NotSupportedError, "Non-uniform indexing over storage image descriptor arrays is not supported.");
679         break;
680     default:
681         DE_FATAL("Unknown Descriptor Type");
682         break;
683     }
684 }
685 
initPrograms(SourceCollections & programCollection) const686 void UniformDescriptorIndexingTestCase::initPrograms(SourceCollections &programCollection) const
687 {
688     const SpirvVersion spirvVersion(vk::SPIRV_VERSION_1_3);
689     const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, spirvVersion, 0u);
690 
691     struct ShaderConfiguration
692     {
693         std::map<std::string, std::string> specializationMap;
694 
695         ShaderConfiguration(const std::string &declaration, const std::string &count, const std::string &accessMethod,
696                             const std::string &extraDeclarations, const std::string &extraLayout)
697             : specializationMap{{"declaration", declaration},
698                                 {"count", count},
699                                 {"accessMethod", accessMethod},
700                                 {"extraDeclarations", extraDeclarations},
701                                 {"extraLayout", extraLayout}}
702         {
703         }
704     };
705 
706     const std::map<VkDescriptorType, ShaderConfiguration> shaderPartsMap{
707         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, ShaderConfiguration("buffer Data { float c; }", "4", "data[i].c", "", "")},
708         {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
709          ShaderConfiguration("uniform Data { float c; }", "12", "data[i].c", "", "")},
710         {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
711          ShaderConfiguration("uniform imageBuffer", "16", "imageLoad(data[i], 0).r", "", "r8,")},
712         {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
713          ShaderConfiguration("uniform samplerBuffer", "16", "texelFetch(data[i], 0).r", "", "")},
714         {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
715          ShaderConfiguration("uniform subpassInput", "4", "subpassLoad(data[i]).r", "", "input_attachment_index=0,")},
716         {VK_DESCRIPTOR_TYPE_SAMPLER,
717          ShaderConfiguration("uniform sampler", "4", "texture(sampler2D(tex, data[i]), vec2(1.5)).r",
718                              "layout(binding = 4) uniform texture2D tex;\n", "")},
719         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
720          ShaderConfiguration("uniform texture2D", "16", "texture(sampler2D(data[i], samp), vec2(0.5)).r",
721                              "layout(binding = 16) uniform sampler samp;\n", "")},
722         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
723          ShaderConfiguration("uniform sampler2D", "4", "texture(data[i], uvec2(0.5)).r", "", "")},
724         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
725          ShaderConfiguration("uniform image2D", "4", "imageLoad(data[i], ivec2(0)).r", "", "r8,")},
726     };
727 
728     std::string fragTemplate =
729         "#version 450\n"
730         "#extension GL_KHR_shader_subgroup_ballot: enable\n"
731         "#extension GL_EXT_nonuniform_qualifier: enable\n"
732         "layout(location = 0) out highp float fragColor;\n"
733         "layout(${extraLayout}binding = 0) ${declaration} data[];\n"
734         "${extraDeclarations}"
735         "void main (void)\n"
736         "{\n"
737         // use cosine to generate pseudo-random value for each fragment; coordinates of each fragment are used
738         // to calculate angle for cosine; both coordinates are multiplied by big numbers in order to make small
739         // change in coordinates produce completely different cosine value; amplitude is also multiplied by big
740         // number before calculating fraction in order to reduce any visible pattern for selected image size;
741         // there was no reason why those numbers were hosen and they could be replaced with any other big
742         // numbers to get different noize
743         "  const float noize = fract(9876.54 * cos(654.3267 * gl_FragCoord.x + 1234.5678 * gl_FragCoord.y));\n"
744         // pseudo-randomly select material for fragment
745         "  const uint materialIndex = uint(noize * ${count});\n"
746         "  fragColor.r = 0.0;\n"
747         // do a "peeling loop" - iterate over each unique index used such that the accessed resource
748         // is always uniform within the subgroup; and in a way that it's not uniform across the draw
749         "  for(;;)\n"
750         "  {\n"
751         "    uint i = subgroupBroadcastFirst(materialIndex);\n"
752         "    if(i == materialIndex)\n"
753         "    {\n"
754         //     we don't use nonuniformEXT(i) - that is the purpose of tests in this file
755         "      fragColor.r = ${accessMethod};\n"
756         "      break;\n"
757         "    }\n"
758         "  }\n"
759         "}\n";
760 
761     // draw single triangle big enough to cover whole framebuffer
762     programCollection.glslSources.add("vert")
763         << glu::VertexSource("#version 450\n"
764                              "void main (void)\n"
765                              "{\n"
766                              "  const float x = -1.0 + 4.0 * ((gl_VertexIndex & 2)>>1);\n"
767                              "  const float y = -1.0 + 4.0 * (gl_VertexIndex % 2);\n"
768                              "  gl_Position = vec4(x, y, 0.0, 1.0);\n"
769                              "}\n");
770 
771     auto &specializationMap = shaderPartsMap.at(m_descriptorType).specializationMap;
772     programCollection.glslSources.add("frag")
773         << glu::FragmentSource(StringTemplate(fragTemplate).specialize(specializationMap)) << buildOptions;
774 }
775 
createInstance(Context & context) const776 TestInstance *UniformDescriptorIndexingTestCase::createInstance(Context &context) const
777 {
778     return new UniformDescriptorIndexingTestCaseTestInstance(context, m_descriptorType);
779 }
780 
781 } // unnamed namespace
782 
783 namespace vkt::subgroups
784 {
785 
createSubgroupsUniformDescriptorIndexingTests(tcu::TestContext & testCtx)786 tcu::TestCaseGroup *createSubgroupsUniformDescriptorIndexingTests(tcu::TestContext &testCtx)
787 {
788     std::pair<const char *, VkDescriptorType> caseList[]{
789         {
790             "storage_buffer",
791             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
792         },
793         {
794             "storage_texel_buffer",
795             VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
796         },
797         {
798             "uniform_texel_buffer",
799             VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
800         },
801         {
802             "storage_image",
803             VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
804         },
805         {
806             "sampler",
807             VK_DESCRIPTOR_TYPE_SAMPLER,
808         },
809         {
810             "sampled_image",
811             VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
812         },
813         {
814             "combined_image_sampler",
815             VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
816         },
817         {
818             "uniform_buffer",
819             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
820         },
821         {
822             "input_attachment",
823             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
824         },
825     };
826 
827     de::MovePtr<TestCaseGroup> group(new TestCaseGroup(testCtx, "uniform_descriptor_indexing"));
828     for (auto &[name, type] : caseList)
829         group->addChild(new UniformDescriptorIndexingTestCase(testCtx, name, type));
830 
831     return group.release();
832 }
833 
834 } // namespace vkt::subgroups
835