1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 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 Vulkan Decriptor Indexing Tests
22 *//*--------------------------------------------------------------------*/
23 
24 #include <algorithm>
25 #include <iostream>
26 #include <iterator>
27 #include <functional>
28 #include <sstream>
29 #include <utility>
30 #include <vector>
31 
32 #include "vktDescriptorSetsIndexingTests.hpp"
33 
34 #include "vkBuilderUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkDefs.hpp"
37 #include "vkObjUtil.hpp"
38 #include "vkPlatform.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkQueryUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 
43 #include "tcuTestLog.hpp"
44 #include "tcuResource.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuCommandLine.hpp"
47 #include "tcuStringTemplate.hpp"
48 #include "tcuSurface.hpp"
49 #include "tcuVectorUtil.hpp"
50 
51 #include "deRandom.hpp"
52 #include "deMath.h"
53 #include "deStringUtil.hpp"
54 
55 namespace vkt
56 {
57 namespace DescriptorIndexing
58 {
59 namespace
60 {
61 using namespace vk;
62 using tcu::PixelBufferAccess;
63 using tcu::UVec2;
64 using tcu::Vec4;
65 
66 static const VkExtent3D RESOLUTION = {64, 64, 1};
67 
68 constexpr uint32_t kMinWorkGroupSize = 2u;
69 constexpr uint32_t kMaxWorkGroupSize = 128u;
70 
71 #define MAX_DESCRIPTORS 4200
72 #define FUZZY_COMPARE false
73 
74 #define BINDING_TestObject 0
75 #define BINDING_Additional 1
76 #define BINDING_DescriptorEnumerator 2
77 
78 static const VkExtent3D smallImageExtent = {4, 4, 1};
79 static const VkExtent3D bigImageExtent   = {32, 32, 1};
80 
81 #ifndef CTS_USES_VULKANSC
82 static const VkDescriptorType VK_DESCRIPTOR_TYPE_UNDEFINED = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
83 #else
84 static const VkDescriptorType VK_DESCRIPTOR_TYPE_UNDEFINED = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
85 #endif
86 
87 struct BindingUniformBufferData
88 {
89     tcu::Vec4 c;
90 };
91 
92 struct BindingStorageBufferData
93 {
94     tcu::Vec4 cnew;
95     tcu::Vec4 cold;
96 };
97 
98 struct TestCaseParams
99 {
100     VkDescriptorType descriptorType; // used only to distinguish test class instance
101     VkShaderStageFlags stageFlags;   // used only to build a proper program
102     VkExtent3D frameResolution;      // target frame buffer resolution
103     bool updateAfterBind;            // whether a test will use update after bind feature
104     bool calculateInLoop;            // perform calculation in a loop
105     bool usesMipMaps;                // this makes a sense and affects in image test cases only
106     bool minNonUniform;              // whether a test will use the minimum nonUniform decorations
107     bool lifetimeCheck;              // fill unused descriptors with resource that will be deleted before draw
108 };
109 
110 struct TestParams
111 {
112     VkShaderStageFlags stageFlags;
113     VkDescriptorType descriptorType;
114     VkDescriptorType additionalDescriptorType;
115     bool copyBuffersToImages;
116     bool allowVertexStoring;
117     VkExtent3D frameResolution;
118     bool updateAfterBind;
119     bool calculateInLoop;
120     bool usesMipMaps;
121     bool minNonUniform;
122     bool lifetimeCheck;
123 
TestParamsvkt::DescriptorIndexing::__anon7412b3740111::TestParams124     TestParams(VkShaderStageFlags stageFlags_, VkDescriptorType descriptorType_,
125                VkDescriptorType additionalDescriptorType_, bool copyBuffersToImages_, bool allowVertexStoring_,
126                const TestCaseParams &caseParams)
127         : stageFlags(stageFlags_)
128         , descriptorType(descriptorType_)
129         , additionalDescriptorType(additionalDescriptorType_)
130         , copyBuffersToImages(copyBuffersToImages_)
131         , allowVertexStoring(allowVertexStoring_)
132         , frameResolution(caseParams.frameResolution)
133         , updateAfterBind(caseParams.updateAfterBind)
134         , calculateInLoop(caseParams.calculateInLoop)
135         , usesMipMaps(caseParams.usesMipMaps)
136         , minNonUniform(caseParams.minNonUniform)
137         , lifetimeCheck(caseParams.lifetimeCheck)
138     {
139     }
140 };
141 
142 struct DescriptorEnumerator
143 {
144     ut::BufferHandleAllocSp buffer;
145     ut::BufferViewSp bufferView;
146     VkDeviceSize bufferSize;
147 
148     Move<VkDescriptorSetLayout> descriptorSetLayout;
149     Move<VkDescriptorPool> descriptorPool;
150     Move<VkDescriptorSet> descriptorSet;
151 
152     void init(const vkt::Context &context, uint32_t vertexCount, uint32_t availableDescriptorCount);
153     void update(const vkt::Context &context);
154 };
155 
156 struct IterateCommonVariables
157 {
158     // An amount of descriptors of a given type available on the platform
159     uint32_t availableDescriptorCount;
160     // An amount of valid descriptors that have connected a buffers to them
161     uint32_t validDescriptorCount;
162     // As the name suggests, sometimes it is used as invocationCount
163     uint32_t vertexCount;
164     VkRect2D renderArea;
165     VkDeviceSize dataAlignment;
166     uint32_t lowerBound;
167     uint32_t upperBound;
168 
169     DescriptorEnumerator descriptorEnumerator;
170 
171     ut::BufferHandleAllocSp vertexAttributesBuffer;
172     ut::BufferHandleAllocSp descriptorsBuffer;
173     ut::BufferHandleAllocSp unusedDescriptorsBuffer;
174     std::vector<VkDescriptorBufferInfo> descriptorsBufferInfos;
175     std::vector<ut::BufferViewSp> descriptorsBufferViews;
176     std::vector<ut::ImageViewSp> descriptorImageViews;
177     std::vector<ut::SamplerSp> descriptorSamplers;
178     std::vector<ut::ImageHandleAllocSp> descriptorsImages;
179     // Only need a single resource to fill all unused descriptors. Using vector for compatibility with utility
180     std::vector<VkDescriptorBufferInfo> unusedDescriptorsBufferInfos;
181     std::vector<ut::BufferViewSp> unusedDescriptorsBufferViews;
182     std::vector<ut::ImageViewSp> unusedDescriptorImageViews;
183     std::vector<ut::SamplerSp> unusedDescriptorSamplers;
184     std::vector<ut::ImageHandleAllocSp> unusedDescriptorsImages;
185     ut::FrameBufferSp frameBuffer;
186 
187     Move<VkDescriptorSetLayout> descriptorSetLayout;
188     Move<VkDescriptorPool> descriptorPool;
189     Move<VkDescriptorSet> descriptorSet;
190     Move<VkPipelineLayout> pipelineLayout;
191     Move<VkRenderPass> renderPass;
192     Move<VkPipeline> pipeline;
193     Move<VkCommandBuffer> commandBuffer;
194 };
195 
196 class CommonDescriptorInstance : public TestInstance
197 {
198 public:
199     CommonDescriptorInstance(Context &context, const TestParams &testParams);
200 
201     uint32_t computeAvailableDescriptorCount(VkDescriptorType descriptorType, bool reserveUniformTexelBuffer) const;
202 
203     Move<VkDescriptorSetLayout> createDescriptorSetLayout(bool reserveUniformTexelBuffer,
204                                                           uint32_t &descriptorCount) const;
205 
206     Move<VkDescriptorPool> createDescriptorPool(uint32_t descriptorCount) const;
207 
208     Move<VkDescriptorSet> createDescriptorSet(VkDescriptorPool dsPool, VkDescriptorSetLayout dsLayout) const;
209 
210     struct attributes
211     {
212         typedef tcu::Vec4 vec4;
213         typedef tcu::Vec2 vec2;
214         typedef tcu::IVec4 ivec4;
215         vec4 position;
216         vec2 normalpos;
217         ivec4 index;
operator ()vkt::DescriptorIndexing::__anon7412b3740111::CommonDescriptorInstance::attributes218         attributes &operator()(const vec4 &pos)
219         {
220             position = pos;
221 
222             normalpos.x() = (pos.x() + 1.0f) / 2.0f;
223             normalpos.y() = (pos.y() + 1.0f) / 2.0f;
224 
225             return *this;
226         }
227     };
228     void createVertexAttributeBuffer(ut::BufferHandleAllocSp &buffer, uint32_t availableDescriptorCount) const;
229 
230     static std::string substBinding(uint32_t binding, const char *str);
231 
232     static const char *getVertexShaderProlog(void);
233     static const char *getFragmentShaderProlog(void);
234     static const char *getComputeShaderProlog(void);
235 
236     static const char *getShaderEpilog(void);
237 
238     static bool performWritesInVertex(VkDescriptorType descriptorType);
239 
240     static bool performWritesInVertex(VkDescriptorType descriptorType, const Context &context);
241 
242     static std::string getShaderAsm(VkShaderStageFlagBits shaderType, const TestCaseParams &testCaseParams,
243                                     bool allowVertexStoring);
244 
245     static std::string getShaderSource(VkShaderStageFlagBits shaderType, const TestCaseParams &testCaseParams,
246                                        bool allowVertexStoring);
247 
248     static std::string getColorAccess(VkDescriptorType descriptorType, const char *indexVariableName, bool usesMipMaps);
249 
250     static std::string getFragmentReturnSource(const std::string &colorAccess);
251 
252     static std::string getFragmentLoopSource(const std::string &colorAccess1, const std::string &colorAccess2);
253 
254     virtual Move<VkRenderPass> createRenderPass(const IterateCommonVariables &variables);
255 
256     struct push_constant
257     {
258         int32_t lowerBound;
259         int32_t upperBound;
260     };
261     VkPushConstantRange makePushConstantRange(void) const;
262 
263     Move<VkPipelineLayout> createPipelineLayout(const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts) const;
264 
265     // Creates graphics or compute pipeline and appropriate shaders' modules according the testCaseParams.stageFlags
266     // In the case of compute pipeline renderPass parameter is ignored.
267     // Viewport will be created with a width and a height taken from testCaseParam.fragResolution.
268     Move<VkPipeline> createPipeline(VkPipelineLayout pipelineLayout, VkRenderPass renderPass);
269 
270     virtual void createFramebuffer(ut::FrameBufferSp &frameBuffer, VkRenderPass renderPass,
271                                    const IterateCommonVariables &variables);
272 
273     // Creates one big stagging buffer cutted out on chunks that can accomodate an element of elementSize size
274     VkDeviceSize createBuffers(std::vector<VkDescriptorBufferInfo> &bufferInfos, ut::BufferHandleAllocSp &buffer,
275                                uint32_t elementCount, uint32_t elementSize, VkDeviceSize alignment,
276                                VkBufferUsageFlags bufferUsage);
277 
278     // Creates and binds an imagesCount of images with given parameters.
279     // Additionally creates stagging buffer for their data and PixelBufferAccess for particular images.
280     VkDeviceSize createImages(std::vector<ut::ImageHandleAllocSp> &images,
281                               std::vector<VkDescriptorBufferInfo> &bufferInfos, ut::BufferHandleAllocSp &buffer,
282                               VkBufferUsageFlags bufferUsage, const VkExtent3D &imageExtent, VkFormat imageFormat,
283                               VkImageLayout imageLayout, uint32_t imageCount, bool withMipMaps = false);
284 
285     void createBuffersViews(std::vector<ut::BufferViewSp> &views,
286                             const std::vector<VkDescriptorBufferInfo> &bufferInfos, VkFormat format);
287 
288     void createImagesViews(std::vector<ut::ImageViewSp> &views, const std::vector<ut::ImageHandleAllocSp> &images,
289                            VkFormat format);
290 
291     virtual void copyBuffersToImages(IterateCommonVariables &variables);
292 
293     virtual void copyImagesToBuffers(IterateCommonVariables &variables);
294 
295     PixelBufferAccess getPixelAccess(uint32_t imageIndex, const VkExtent3D &imageExtent, VkFormat imageFormat,
296                                      const std::vector<VkDescriptorBufferInfo> &bufferInfos,
297                                      const ut::BufferHandleAllocSp &buffer, uint32_t mipLevel = 0u) const;
298 
299     virtual void createAndPopulateDescriptors(IterateCommonVariables &variables)       = 0;
300     virtual void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) = 0;
301 
302     virtual void updateDescriptors(IterateCommonVariables &variables);
303     void updateUnusedDescriptors(IterateCommonVariables &variables);
304 
305     void destroyUnusedResources(IterateCommonVariables &variables);
306 
307     virtual void iterateCollectResults(ut::UpdatablePixelBufferAccessPtr &result,
308                                        const IterateCommonVariables &variables, bool fromTest);
309 
310     void iterateCommandSetup(IterateCommonVariables &variables);
311 
312     void iterateCommandBegin(IterateCommonVariables &variables, bool firstPass = true);
313 
314     void iterateCommandEnd(IterateCommonVariables &variables, ut::UpdatablePixelBufferAccessPtr &programResult,
315                            ut::UpdatablePixelBufferAccessPtr &referenceResult, bool collectBeforeSubmit = true);
316 
317     bool iterateVerifyResults(IterateCommonVariables &variables, ut::UpdatablePixelBufferAccessPtr programResult,
318                               ut::UpdatablePixelBufferAccessPtr referenceResult);
319 
320     Move<VkCommandBuffer> createCmdBuffer(void);
321 
322     void commandBindPipeline(VkCommandBuffer commandBuffer, VkPipeline pipeline);
323 
324     void commandBindVertexAttributes(VkCommandBuffer commandBuffer,
325                                      const ut::BufferHandleAllocSp &vertexAttributesBuffer);
326 
327     void commandBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout,
328                                    VkDescriptorSet descriptorSet, uint32_t descriptorSetIndex);
329 
330     void commandReadFrameBuffer(ut::BufferHandleAllocSp &content, VkCommandBuffer commandBuffer,
331                                 const ut::FrameBufferSp &frameBuffer);
332     ut::UpdatablePixelBufferAccessPtr commandReadFrameBuffer(VkCommandBuffer commandBuffer,
333                                                              const ut::FrameBufferSp &frameBuffer);
334 
335     Move<VkFence> commandSubmit(VkCommandBuffer commandBuffer);
336 
337     virtual bool verifyVertexWriteResults(IterateCommonVariables &variables);
338 
339 protected:
340     virtual tcu::TestStatus iterate(void);
341 
342 protected:
343     const VkDevice m_vkd;
344     const DeviceInterface &m_vki;
345     Allocator &m_allocator;
346     const VkQueue m_queue;
347     const uint32_t m_queueFamilyIndex;
348     const Move<VkCommandPool> m_commandPool;
349     const VkFormat m_colorFormat;
350     const TestParams m_testParams;
351     static const tcu::Vec4 m_clearColor;
352     const std::vector<float> m_colorScheme;
353     const uint32_t m_schemeSize;
354 
355 private:
356     Move<VkPipeline> createGraphicsPipeline(VkPipelineLayout pipelineLayout, VkRenderPass renderPass);
357 
358     Move<VkPipeline> createComputePipeline(VkPipelineLayout pipelineLayout);
359 
360     void constructShaderModules(void);
361 
362     static std::vector<float> createColorScheme();
363 
364     Move<VkShaderModule> m_vertexModule;
365     Move<VkShaderModule> m_fragmentModule;
366     Move<VkShaderModule> m_computeModule;
367 };
368 const tcu::Vec4 CommonDescriptorInstance::m_clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
369 
init(const vkt::Context & context,uint32_t vertexCount,uint32_t availableDescriptorCount)370 void DescriptorEnumerator::init(const vkt::Context &context, uint32_t vertexCount, uint32_t availableDescriptorCount)
371 {
372     const VkDevice device                  = context.getDevice();
373     const DeviceInterface &deviceInterface = context.getDeviceInterface();
374 
375     const VkFormat imageFormat = VK_FORMAT_R32G32B32A32_SINT;
376     typedef ut::mapVkFormat2Type<imageFormat>::type pixelType;
377     const VkDeviceSize dataSize        = vertexCount * sizeof(pixelType);
378     const std::vector<uint32_t> primes = ut::generatePrimes(availableDescriptorCount);
379     const uint32_t primeCount          = static_cast<uint32_t>(primes.size());
380 
381     std::vector<pixelType> data(vertexCount);
382     // e.g. 2,3,5,7,11,13,2,3,5,7,...
383     for (uint32_t idx = 0; idx < vertexCount; ++idx)
384     {
385         data[idx].x() = static_cast<pixelType::Element>(primes[idx % primeCount]);
386         data[idx].y() = static_cast<pixelType::Element>(idx);
387     }
388 
389     bufferSize = ut::createBufferAndBind(buffer, context, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, dataSize);
390     deMemcpy(buffer->alloc->getHostPtr(), data.data(), static_cast<size_t>(dataSize));
391 
392     const VkBufferViewCreateInfo bufferViewCreateInfo = {
393         VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // sType
394         nullptr,                                   // pNext
395         0u,                                        // flags
396         *(buffer.get()->buffer),                   // buffer
397         imageFormat,                               // format
398         0u,                                        // offset
399         bufferSize,                                // range
400     };
401 
402     bufferView =
403         ut::BufferViewSp(new Move<VkBufferView>(vk::createBufferView(deviceInterface, device, &bufferViewCreateInfo)));
404 
405     const VkDescriptorSetLayoutBinding binding = {
406         BINDING_DescriptorEnumerator,            // binding
407         VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, // descriptorType
408         1u,                                      // descriptorCount
409         VK_SHADER_STAGE_ALL,                     // stageFlags
410         nullptr,                                 // pImmutableSamplers
411     };
412 
413     const VkDescriptorSetLayoutCreateInfo layoutCreateInfo = {
414         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
415         nullptr,  // pNext
416         0u,       // flags
417         1u,       // bindingCount
418         &binding, // pBindings
419     };
420 
421     descriptorSetLayout = vk::createDescriptorSetLayout(deviceInterface, device, &layoutCreateInfo);
422     descriptorPool      = DescriptorPoolBuilder()
423                          .addType(binding.descriptorType)
424                          .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
425 
426     const VkDescriptorSetAllocateInfo dsAllocInfo = {
427         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
428         nullptr,                                        // pNext
429         *descriptorPool,                                // descriptorPool
430         1u,                                             // descriptorSetCount
431         &(*descriptorSetLayout)                         // pSetLayouts
432     };
433 
434     descriptorSet = vk::allocateDescriptorSet(deviceInterface, device, &dsAllocInfo);
435 }
436 
update(const vkt::Context & context)437 void DescriptorEnumerator::update(const vkt::Context &context)
438 {
439     const VkDescriptorBufferInfo bufferInfo = {
440         *(buffer.get()->buffer), // buffer
441         0u,                      // offset
442         bufferSize,              // range
443     };
444 
445     const VkWriteDescriptorSet writeInfo = {
446         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
447         nullptr,                                 // pNext
448         *descriptorSet,                          // dstSet
449         BINDING_DescriptorEnumerator,            // dstBinding
450         0u,                                      // dstArrayElement
451         1u,                                      // descriptorCount
452         VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, // descriptorType
453         nullptr,                                 // pImageInfo
454         &bufferInfo,                             // pBufferInfo
455         &(**bufferView),                         // pTexelBufferView
456     };
457 
458     context.getDeviceInterface().updateDescriptorSets(context.getDevice(), 1u, &writeInfo, 0u, nullptr);
459 }
460 
CommonDescriptorInstance(Context & context,const TestParams & testParams)461 CommonDescriptorInstance::CommonDescriptorInstance(Context &context, const TestParams &testParams)
462     : TestInstance(context)
463     , m_vkd(context.getDevice())
464     , m_vki(context.getDeviceInterface())
465     , m_allocator(context.getDefaultAllocator())
466     , m_queue(context.getUniversalQueue())
467     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
468     , m_commandPool(vk::createCommandPool(
469           m_vki, m_vkd, (VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT),
470           m_queueFamilyIndex))
471     , m_colorFormat(VK_FORMAT_R32G32B32A32_SFLOAT)
472     , m_testParams(testParams)
473     , m_colorScheme(createColorScheme())
474     , m_schemeSize(static_cast<uint32_t>(m_colorScheme.size()))
475 {
476 }
477 
computeAvailableDescriptorCount(VkDescriptorType descriptorType,bool reserveUniformTexelBuffer) const478 uint32_t CommonDescriptorInstance::computeAvailableDescriptorCount(VkDescriptorType descriptorType,
479                                                                    bool reserveUniformTexelBuffer) const
480 {
481     DE_UNREF(descriptorType);
482     const uint32_t vertexCount = m_testParams.frameResolution.width * m_testParams.frameResolution.height;
483     const uint32_t availableDescriptorsOnDevice = ut::DeviceProperties(m_context).computeMaxPerStageDescriptorCount(
484         m_testParams.descriptorType, m_testParams.updateAfterBind, reserveUniformTexelBuffer);
485     return deMinu32(deMinu32(vertexCount, availableDescriptorsOnDevice), MAX_DESCRIPTORS);
486 }
487 
createDescriptorSetLayout(bool reserveUniformTexelBuffer,uint32_t & descriptorCount) const488 Move<VkDescriptorSetLayout> CommonDescriptorInstance::createDescriptorSetLayout(bool reserveUniformTexelBuffer,
489                                                                                 uint32_t &descriptorCount) const
490 {
491     descriptorCount = computeAvailableDescriptorCount(m_testParams.descriptorType, reserveUniformTexelBuffer);
492 
493     bool optional = (m_testParams.additionalDescriptorType != VK_DESCRIPTOR_TYPE_UNDEFINED);
494 
495     const VkShaderStageFlags bindingStageFlags = (m_testParams.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ?
496                                                      VkShaderStageFlags{VK_SHADER_STAGE_FRAGMENT_BIT} :
497                                                      m_testParams.stageFlags;
498 
499     const VkDescriptorSetLayoutBinding bindings[] = {{
500                                                          BINDING_TestObject,          // binding
501                                                          m_testParams.descriptorType, // descriptorType
502                                                          descriptorCount,             // descriptorCount
503                                                          bindingStageFlags,           // stageFlags
504                                                          nullptr,                     // pImmutableSamplers
505                                                      },
506                                                      {
507                                                          BINDING_Additional,                    // binding
508                                                          m_testParams.additionalDescriptorType, // descriptorType
509                                                          1,                                     // descriptorCount
510                                                          bindingStageFlags,                     // stageFlags
511                                                          nullptr,                               // pImmutableSamplers
512                                                      }};
513 
514     const VkDescriptorBindingFlags bindingFlagUpdateAfterBind =
515         m_testParams.updateAfterBind ? VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT : 0;
516 
517     const VkDescriptorBindingFlags bindingFlags[] = {
518         VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | bindingFlagUpdateAfterBind,
519         VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | bindingFlagUpdateAfterBind};
520 
521     const VkDescriptorSetLayoutBindingFlagsCreateInfo bindingCreateInfo = {
522         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, nullptr,
523         optional ? 2u : 1u, // bindingCount
524         bindingFlags,       // pBindingFlags
525     };
526 
527     const VkDescriptorSetLayoutCreateFlags layoutCreateFlags =
528         m_testParams.updateAfterBind ? VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT : 0;
529 
530     const VkDescriptorSetLayoutCreateInfo layoutCreateInfo = {
531         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
532         &bindingCreateInfo, // pNext
533         layoutCreateFlags,  // flags
534         optional ? 2u : 1u, // bindingCount
535         bindings,           // pBindings
536     };
537 
538     return vk::createDescriptorSetLayout(m_vki, m_vkd, &layoutCreateInfo);
539 }
540 
createDescriptorPool(uint32_t descriptorCount) const541 Move<VkDescriptorPool> CommonDescriptorInstance::createDescriptorPool(uint32_t descriptorCount) const
542 {
543     const VkDescriptorPoolCreateFlags pcf =
544         m_testParams.updateAfterBind ? VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT : 0;
545 
546     DescriptorPoolBuilder builder;
547 
548     builder.addType(m_testParams.descriptorType, descriptorCount);
549 
550     if (m_testParams.additionalDescriptorType != VK_DESCRIPTOR_TYPE_UNDEFINED)
551         builder.addType(m_testParams.additionalDescriptorType, 1);
552 
553     return builder.build(m_vki, m_vkd, (VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT | pcf), 1u);
554 }
555 
createDescriptorSet(VkDescriptorPool dsPool,VkDescriptorSetLayout dsLayout) const556 Move<VkDescriptorSet> CommonDescriptorInstance::createDescriptorSet(VkDescriptorPool dsPool,
557                                                                     VkDescriptorSetLayout dsLayout) const
558 {
559     const VkDescriptorSetAllocateInfo dsAllocInfo = {
560         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType;
561         nullptr,                                        // pNext;
562         dsPool,                                         // descriptorPool;
563         1u,                                             // descriptorSetCount
564         &dsLayout                                       // pSetLayouts
565     };
566 
567     return vk::allocateDescriptorSet(m_vki, m_vkd, &dsAllocInfo);
568 }
569 
createVertexAttributeBuffer(ut::BufferHandleAllocSp & buffer,uint32_t availableDescriptorCount) const570 void CommonDescriptorInstance::createVertexAttributeBuffer(ut::BufferHandleAllocSp &buffer,
571                                                            uint32_t availableDescriptorCount) const
572 {
573     float xSize = 0.0f;
574     float ySize = 0.0f;
575 
576     const uint32_t invocationCount = m_testParams.frameResolution.width * m_testParams.frameResolution.height;
577     const std::vector<Vec4> vertices =
578         ut::createVertices(m_testParams.frameResolution.width, m_testParams.frameResolution.height, xSize, ySize);
579     const std::vector<uint32_t> primes = ut::generatePrimes(availableDescriptorCount);
580     const uint32_t primeCount          = static_cast<uint32_t>(primes.size());
581 
582     std::vector<attributes> data(vertices.size());
583     std::transform(vertices.begin(), vertices.end(), data.begin(), attributes());
584 
585     for (uint32_t invIdx = 0; invIdx < invocationCount; ++invIdx)
586     {
587         // r: 2,3,5,7,11,13,2,3,5,7,...
588         data[invIdx].index.x() = primes[invIdx % primeCount];
589 
590         // b, a: not used
591         data[invIdx].index.z() = 0;
592         data[invIdx].index.w() = 0;
593     }
594 
595     // g: 0,0,2,3,0,5,0,7,0,0,0,11,0,13,...
596     for (uint32_t primeIdx = 0; primeIdx < primeCount; ++primeIdx)
597     {
598         const uint32_t prime = primes[primeIdx];
599         DE_ASSERT(prime < invocationCount);
600         data[prime].index.y() = prime;
601     }
602 
603     const VkDeviceSize dataSize = data.size() * sizeof(attributes);
604 
605     VkDeviceSize deviceSize = ut::createBufferAndBind(buffer, m_context, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, dataSize);
606 
607     deMemcpy(buffer->alloc->getHostPtr(), data.data(), static_cast<size_t>(deviceSize));
608 
609     vk::flushAlloc(m_vki, m_vkd, *buffer->alloc);
610 }
611 
substBinding(uint32_t binding,const char * str)612 std::string CommonDescriptorInstance::substBinding(uint32_t binding, const char *str)
613 {
614     std::map<std::string, std::string> vars;
615     vars["?"] = de::toString(binding);
616     return tcu::StringTemplate(str).specialize(vars);
617 }
618 
getVertexShaderProlog(void)619 const char *CommonDescriptorInstance::getVertexShaderProlog(void)
620 {
621     return "layout(location = 0) in  vec4  in_position;    \n"
622            "layout(location = 1) in  vec2  in_normalpos;    \n"
623            "layout(location = 2) in  ivec4 index;            \n"
624            "layout(location = 0) out vec2  normalpos;        \n"
625            "layout(location = 1) out int   rIndex;            \n"
626            "layout(location = 2) out int   gIndex;            \n"
627            "void main(void)                                \n"
628            "{                                                \n"
629            "    gl_PointSize = 0.2f;                        \n"
630            "    normalpos = in_normalpos;                    \n"
631            "    gl_Position = in_position;                    \n"
632            "    rIndex = index.x;                            \n"
633            "    gIndex = index.y;                            \n";
634 }
635 
getFragmentShaderProlog(void)636 const char *CommonDescriptorInstance::getFragmentShaderProlog(void)
637 {
638     return "layout(location = 0) out vec4     FragColor;    \n"
639            "layout(location = 0) in flat vec2 normalpos;    \n"
640            "layout(location = 1) in flat int  rIndex;        \n"
641            "layout(location = 2) in flat int  gIndex;        \n"
642            "void main(void)                                \n"
643            "{                                                \n";
644 }
645 
getComputeShaderProlog(void)646 const char *CommonDescriptorInstance::getComputeShaderProlog(void)
647 {
648     return "layout(constant_id=0) const int local_size_x_val = 1;                \n"
649            "layout(constant_id=1) const int local_size_y_val = 1;                \n"
650            "layout(constant_id=2) const int local_size_z_val = 1;                \n"
651            "layout(local_size_x_id=0,local_size_y_id=1,local_size_z_id=2) in;    \n"
652            "void main(void)                                                    \n"
653            "{                                                                    \n";
654 }
655 
getShaderEpilog(void)656 const char *CommonDescriptorInstance::getShaderEpilog(void)
657 {
658     return "}                                            \n";
659 }
660 
constructShaderModules(void)661 void CommonDescriptorInstance::constructShaderModules(void)
662 {
663     tcu::TestLog &log = m_context.getTestContext().getLog();
664 
665     // Must construct at least one stage.
666     DE_ASSERT(m_testParams.stageFlags &
667               (VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT));
668 
669     if (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT)
670     {
671         const std::string name =
672             ut::buildShaderName(VK_SHADER_STAGE_COMPUTE_BIT, m_testParams.descriptorType, m_testParams.updateAfterBind,
673                                 m_testParams.calculateInLoop, m_testParams.minNonUniform, false);
674         m_computeModule = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name),
675                                                  (VkShaderModuleCreateFlags)0);
676     }
677     if (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT)
678     {
679         const std::string name = ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testParams.descriptorType,
680                                                      m_testParams.updateAfterBind, m_testParams.calculateInLoop,
681                                                      m_testParams.minNonUniform, m_testParams.allowVertexStoring);
682         m_fragmentModule       = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name),
683                                                         (VkShaderModuleCreateFlags)0);
684         log << tcu::TestLog::Message << "Finally used fragment shader: " << name << '\n' << tcu::TestLog::EndMessage;
685     }
686     if (m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT)
687     {
688         const std::string name = ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testParams.descriptorType,
689                                                      m_testParams.updateAfterBind, m_testParams.calculateInLoop,
690                                                      m_testParams.minNonUniform, m_testParams.allowVertexStoring);
691         m_vertexModule         = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name),
692                                                         (VkShaderModuleCreateFlags)0);
693         log << tcu::TestLog::Message << "Finally used vertex shader: " << name << '\n' << tcu::TestLog::EndMessage;
694     }
695 }
696 
createRenderPass(const IterateCommonVariables & variables)697 Move<VkRenderPass> CommonDescriptorInstance::createRenderPass(const IterateCommonVariables &variables)
698 {
699     DE_UNREF(variables);
700     if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) ||
701         (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT))
702     {
703         // Use VK_ATTACHMENT_LOAD_OP_LOAD to make the utility function select initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
704         return vk::makeRenderPass(m_vki, m_vkd, m_colorFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
705     }
706     return Move<VkRenderPass>();
707 }
708 
makePushConstantRange(void) const709 VkPushConstantRange CommonDescriptorInstance::makePushConstantRange(void) const
710 {
711     const VkPushConstantRange pcr = {
712         m_testParams.stageFlags,                     // stageFlags
713         0u,                                          // offset
714         static_cast<uint32_t>(sizeof(push_constant)) // size
715     };
716     return pcr;
717 }
718 
createPipelineLayout(const std::vector<VkDescriptorSetLayout> & descriptorSetLayouts) const719 Move<VkPipelineLayout> CommonDescriptorInstance::createPipelineLayout(
720     const std::vector<VkDescriptorSetLayout> &descriptorSetLayouts) const
721 {
722     const VkPushConstantRange pcr = makePushConstantRange();
723 
724     const VkPipelineLayoutCreateInfo createInfo = {
725         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // sType
726         nullptr,                                            // pNext
727         (VkPipelineLayoutCreateFlags)0,                     // flags
728         static_cast<uint32_t>(descriptorSetLayouts.size()), // setLayoutCount
729         descriptorSetLayouts.data(),                        // pSetLayouts;
730         m_testParams.calculateInLoop ? 1u : 0u,             // pushConstantRangeCount
731         m_testParams.calculateInLoop ? &pcr : nullptr,      // pPushConstantRanges
732     };
733 
734     return vk::createPipelineLayout(m_vki, m_vkd, &createInfo);
735 }
736 
createFramebuffer(ut::FrameBufferSp & frameBuffer,VkRenderPass renderPass,const IterateCommonVariables & variables)737 void CommonDescriptorInstance::createFramebuffer(ut::FrameBufferSp &frameBuffer, VkRenderPass renderPass,
738                                                  const IterateCommonVariables &variables)
739 {
740     DE_UNREF(variables);
741     ut::createFrameBuffer(frameBuffer, m_context, m_testParams.frameResolution, m_colorFormat, renderPass);
742 }
743 
createPipeline(VkPipelineLayout pipelineLayout,VkRenderPass renderPass)744 Move<VkPipeline> CommonDescriptorInstance::createPipeline(VkPipelineLayout pipelineLayout, VkRenderPass renderPass)
745 {
746     DE_ASSERT(VK_SHADER_STAGE_ALL != m_testParams.stageFlags);
747 
748     constructShaderModules();
749 
750     return (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ? createComputePipeline(pipelineLayout) :
751                                                                      createGraphicsPipeline(pipelineLayout, renderPass);
752 }
753 
createComputePipeline(VkPipelineLayout pipelineLayout)754 Move<VkPipeline> CommonDescriptorInstance::createComputePipeline(VkPipelineLayout pipelineLayout)
755 {
756     const tcu::IVec3 workGroupSize((m_testParams.calculateInLoop ? kMaxWorkGroupSize : kMinWorkGroupSize), 1, 1);
757     const auto intSize    = sizeof(int);
758     const auto intSizeU32 = static_cast<uint32_t>(intSize);
759 
760     const std::vector<VkSpecializationMapEntry> mapEntries{
761         makeSpecializationMapEntry(0u, intSizeU32 * 0u, intSize),
762         makeSpecializationMapEntry(1u, intSizeU32 * 1u, intSize),
763         makeSpecializationMapEntry(2u, intSizeU32 * 2u, intSize),
764     };
765 
766     const VkSpecializationInfo workGroupSizeInfo = {
767         static_cast<uint32_t>(mapEntries.size()), // uint32_t mapEntryCount;
768         mapEntries.data(),                        // const VkSpecializationMapEntry* pMapEntries;
769         sizeof(workGroupSize),                    // size_t dataSize;
770         &workGroupSize,                           // const void* pData;
771     };
772 
773     const VkPipelineShaderStageCreateInfo shaderStageCreateInfo = {
774         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
775         nullptr,                             // pNext
776         (VkPipelineShaderStageCreateFlags)0, // flags
777         VK_SHADER_STAGE_COMPUTE_BIT,         // stage
778         *m_computeModule,                    // module
779         "main",                              // pName
780         &workGroupSizeInfo,                  // pSpecializationInfo
781     };
782 
783     const VkComputePipelineCreateInfo pipelineCreateInfo = {
784         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
785         nullptr,               // pNext
786         0u,                    // flags
787         shaderStageCreateInfo, // stage
788         pipelineLayout,        // layout
789         VK_NULL_HANDLE,        // basePipelineHandle
790         0u,                    // basePipelineIndex
791     };
792     return vk::createComputePipeline(m_vki, m_vkd, VK_NULL_HANDLE, &pipelineCreateInfo);
793 }
794 
createGraphicsPipeline(VkPipelineLayout pipelineLayout,VkRenderPass renderPass)795 Move<VkPipeline> CommonDescriptorInstance::createGraphicsPipeline(VkPipelineLayout pipelineLayout,
796                                                                   VkRenderPass renderPass)
797 {
798     const VkVertexInputBindingDescription bindingDescriptions[] = {
799         {
800             0u,                          // binding
801             sizeof(attributes),          // stride
802             VK_VERTEX_INPUT_RATE_VERTEX, // inputRate
803         },
804     };
805 
806     const VkVertexInputAttributeDescription attributeDescriptions[] = {
807         {
808             0u,                                            // location
809             0u,                                            // binding
810             ut::mapType2vkFormat<attributes::vec4>::value, // format
811             0u                                             // offset
812         },                                                 // @in_position
813         {
814             1u,                                             // location
815             0u,                                             // binding
816             ut::mapType2vkFormat<attributes::vec2>::value,  // format
817             static_cast<uint32_t>(sizeof(attributes::vec4)) // offset
818         },                                                  // @normalpos
819         {
820             2u,                                                                        // location
821             0u,                                                                        // binding
822             ut::mapType2vkFormat<attributes::ivec4>::value,                            // format
823             static_cast<uint32_t>(sizeof(attributes::vec2) + sizeof(attributes::vec4)) // offset
824         },                                                                             // @index
825     };
826 
827     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = {
828         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
829         nullptr,
830         (VkPipelineVertexInputStateCreateFlags)0,  // flags
831         DE_LENGTH_OF_ARRAY(bindingDescriptions),   // vertexBindingDescriptionCount
832         bindingDescriptions,                       // pVertexBindingDescriptions
833         DE_LENGTH_OF_ARRAY(attributeDescriptions), // vertexAttributeDescriptionCount
834         attributeDescriptions                      // pVertexAttributeDescriptions
835     };
836 
837     const VkDynamicState dynamicStates[] = {VK_DYNAMIC_STATE_SCISSOR};
838 
839     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
840         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // sType
841         nullptr,                                              // pNext
842         0u,                                                   // flags
843         DE_LENGTH_OF_ARRAY(dynamicStates),                    // dynamicStateCount
844         dynamicStates                                         // pDynamicStates
845     };
846 
847     const std::vector<VkViewport> viewports(
848         1, makeViewport(m_testParams.frameResolution.width, m_testParams.frameResolution.height));
849     const std::vector<VkRect2D> scissors(1, makeRect2D(0u, 0u));
850 
851     DE_ASSERT(m_vertexModule && m_fragmentModule);
852 
853     return vk::makeGraphicsPipeline(m_vki,                            // vk
854                                     m_vkd,                            // device
855                                     pipelineLayout,                   // pipelineLayout
856                                     *m_vertexModule,                  // vertexShaderModule
857                                     VK_NULL_HANDLE,                   // tessellationControlModule
858                                     VK_NULL_HANDLE,                   // tessellationEvalModule
859                                     VK_NULL_HANDLE,                   // geometryShaderModule
860                                     *m_fragmentModule,                // fragmentShaderModule
861                                     renderPass,                       // renderPass
862                                     viewports,                        // viewports
863                                     scissors,                         // scissors
864                                     VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // topology
865                                     0U,                               // subpass
866                                     0U,                               // patchControlPoints
867                                     &vertexInputStateCreateInfo,      // vertexInputStateCreateInfo
868                                     nullptr,                          // rasterizationStateCreateInfo
869                                     nullptr,                          // multisampleStateCreateInfo
870                                     nullptr,                          // depthStencilStateCreateInfo
871                                     nullptr,                          // colorBlendStateCreateInfo
872                                     &dynamicStateCreateInfo);         // dynamicStateCreateInfo
873 }
874 
createBuffers(std::vector<VkDescriptorBufferInfo> & bufferInfos,ut::BufferHandleAllocSp & buffer,uint32_t elementCount,uint32_t elementSize,VkDeviceSize alignment,VkBufferUsageFlags bufferUsage)875 VkDeviceSize CommonDescriptorInstance::createBuffers(std::vector<VkDescriptorBufferInfo> &bufferInfos,
876                                                      ut::BufferHandleAllocSp &buffer, uint32_t elementCount,
877                                                      uint32_t elementSize, VkDeviceSize alignment,
878                                                      VkBufferUsageFlags bufferUsage)
879 {
880     const VkDeviceSize roundedSize = deAlign64(elementSize, alignment);
881     VkDeviceSize bufferSize = ut::createBufferAndBind(buffer, m_context, bufferUsage, (roundedSize * elementCount));
882 
883     for (uint32_t elementIdx = 0; elementIdx < elementCount; ++elementIdx)
884     {
885         const VkDescriptorBufferInfo bufferInfo = {
886             *buffer.get()->buffer,    //buffer;
887             elementIdx * roundedSize, //offset;
888             elementSize,              // range;
889 
890         };
891         bufferInfos.push_back(bufferInfo);
892     }
893 
894     return bufferSize;
895 }
896 
createImages(std::vector<ut::ImageHandleAllocSp> & images,std::vector<VkDescriptorBufferInfo> & bufferInfos,ut::BufferHandleAllocSp & buffer,VkBufferUsageFlags bufferUsage,const VkExtent3D & imageExtent,VkFormat imageFormat,VkImageLayout imageLayout,uint32_t imageCount,bool withMipMaps)897 VkDeviceSize CommonDescriptorInstance::createImages(std::vector<ut::ImageHandleAllocSp> &images,
898                                                     std::vector<VkDescriptorBufferInfo> &bufferInfos,
899                                                     ut::BufferHandleAllocSp &buffer, VkBufferUsageFlags bufferUsage,
900                                                     const VkExtent3D &imageExtent, VkFormat imageFormat,
901                                                     VkImageLayout imageLayout, uint32_t imageCount, bool withMipMaps)
902 
903 {
904     const uint32_t imageSize = ut::computeImageSize(imageExtent, imageFormat, withMipMaps);
905 
906     const VkDeviceSize bufferSize =
907         createBuffers(bufferInfos, buffer, imageCount, imageSize, sizeof(tcu::Vec4), bufferUsage);
908 
909     for (uint32_t imageIdx = 0; imageIdx < imageCount; ++imageIdx)
910     {
911         ut::ImageHandleAllocSp image;
912         ut::createImageAndBind(image, m_context, imageFormat, imageExtent, imageLayout, withMipMaps);
913         images.push_back(image);
914     }
915 
916     return bufferSize;
917 }
918 
createBuffersViews(std::vector<ut::BufferViewSp> & views,const std::vector<VkDescriptorBufferInfo> & bufferInfos,VkFormat format)919 void CommonDescriptorInstance::createBuffersViews(std::vector<ut::BufferViewSp> &views,
920                                                   const std::vector<VkDescriptorBufferInfo> &bufferInfos,
921                                                   VkFormat format)
922 {
923     const uint32_t infoCount = static_cast<uint32_t>(bufferInfos.size());
924     for (uint32_t infoIdx = 0; infoIdx < infoCount; ++infoIdx)
925     {
926         const VkDescriptorBufferInfo &bufferInfo    = bufferInfos[infoIdx];
927         const VkBufferViewCreateInfo bufferViewInfo = {
928             VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // sType
929             nullptr,                                   // pNext
930             (VkBufferViewCreateFlags)0,                // flags
931             bufferInfo.buffer,                         // buffer
932             format,                                    // format
933             bufferInfo.offset,                         // offset
934             bufferInfo.range                           // range;
935         };
936         views.push_back(ut::BufferViewSp(new Move<VkBufferView>(vk::createBufferView(m_vki, m_vkd, &bufferViewInfo))));
937     }
938 }
939 
createImagesViews(std::vector<ut::ImageViewSp> & views,const std::vector<ut::ImageHandleAllocSp> & images,VkFormat format)940 void CommonDescriptorInstance::createImagesViews(std::vector<ut::ImageViewSp> &views,
941                                                  const std::vector<ut::ImageHandleAllocSp> &images, VkFormat format)
942 {
943     const uint32_t imageCount = static_cast<uint32_t>(images.size());
944     for (uint32_t imageIdx = 0; imageIdx < imageCount; ++imageIdx)
945     {
946         const VkImageViewCreateInfo createInfo = {
947             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
948             nullptr,                                  // pNext
949             (VkImageViewCreateFlags)0,                // flags
950             *images[imageIdx]->image,                 // image
951             VK_IMAGE_VIEW_TYPE_2D,                    // viewType
952             format,                                   // format
953             vk::makeComponentMappingRGBA(),           // components
954             {
955                 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
956                 (uint32_t)0,               // baseMipLevel
957                 images[imageIdx]->levels,  // mipLevels
958                 (uint32_t)0,               // baseArrayLayer
959                 (uint32_t)1u,              // arraySize
960             },
961         };
962         views.push_back(ut::ImageViewSp(new Move<VkImageView>(vk::createImageView(m_vki, m_vkd, &createInfo))));
963     }
964 }
965 
copyBuffersToImages(IterateCommonVariables & variables)966 void CommonDescriptorInstance::copyBuffersToImages(IterateCommonVariables &variables)
967 {
968     const uint32_t infoCount = static_cast<uint32_t>(variables.descriptorsBufferInfos.size());
969     DE_ASSERT(variables.descriptorsImages.size() == infoCount);
970     const VkPipelineStageFlagBits dstStageMask = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ?
971                                                      VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT :
972                                                      VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
973     for (uint32_t infoIdx = 0; infoIdx < infoCount; ++infoIdx)
974     {
975         ut::recordCopyBufferToImage(*variables.commandBuffer,                       // commandBuffer
976                                     m_vki,                                          // interface
977                                     VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,              // srcStageMask
978                                     dstStageMask,                                   // dstStageMask
979                                     variables.descriptorsBufferInfos[infoIdx],      // bufferInfo
980                                     *(variables.descriptorsImages[infoIdx]->image), // image
981                                     variables.descriptorsImages[infoIdx]->extent,   // imageExtent
982                                     variables.descriptorsImages[infoIdx]->format,   // imageFormat
983                                     VK_IMAGE_LAYOUT_UNDEFINED,                      // oldImageLayout
984                                     VK_IMAGE_LAYOUT_GENERAL,                        // newImageLayout
985                                     variables.descriptorsImages[infoIdx]->levels);  // mipLevelCount
986     }
987 }
988 
copyImagesToBuffers(IterateCommonVariables & variables)989 void CommonDescriptorInstance::copyImagesToBuffers(IterateCommonVariables &variables)
990 {
991     const uint32_t infoCount = static_cast<uint32_t>(variables.descriptorsBufferInfos.size());
992     DE_ASSERT(variables.descriptorsImages.size() == infoCount);
993     const VkPipelineStageFlagBits srcStageMask = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ?
994                                                      VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT :
995                                                      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
996 
997     for (uint32_t infoIdx = 0; infoIdx < infoCount; ++infoIdx)
998     {
999         ut::recordCopyImageToBuffer(*variables.commandBuffer,                       // commandBuffer
1000                                     m_vki,                                          // interface
1001                                     srcStageMask,                                   // srcStageMask
1002                                     VK_PIPELINE_STAGE_HOST_BIT,                     // dstStageMask
1003                                     *(variables.descriptorsImages[infoIdx]->image), // image
1004                                     variables.descriptorsImages[infoIdx]->extent,   // imageExtent
1005                                     variables.descriptorsImages[infoIdx]->format,   // imageFormat
1006                                     VK_IMAGE_LAYOUT_GENERAL,                        // oldImageLayout
1007                                     VK_IMAGE_LAYOUT_GENERAL,                        // newImageLayout
1008                                     variables.descriptorsBufferInfos[infoIdx]);     // bufferInfo
1009     }
1010 }
1011 
getPixelAccess(uint32_t imageIndex,const VkExtent3D & imageExtent,VkFormat imageFormat,const std::vector<VkDescriptorBufferInfo> & bufferInfos,const ut::BufferHandleAllocSp & buffer,uint32_t mipLevel) const1012 PixelBufferAccess CommonDescriptorInstance::getPixelAccess(uint32_t imageIndex, const VkExtent3D &imageExtent,
1013                                                            VkFormat imageFormat,
1014                                                            const std::vector<VkDescriptorBufferInfo> &bufferInfos,
1015                                                            const ut::BufferHandleAllocSp &buffer,
1016                                                            uint32_t mipLevel) const
1017 {
1018     DE_ASSERT(bufferInfos[imageIndex].buffer == *buffer.get()->buffer);
1019     DE_ASSERT(ut::computeImageSize(imageExtent, imageFormat, true, (mipLevel ? ut::maxDeUint32 : 0)) <=
1020               bufferInfos[imageIndex].range);
1021     DE_ASSERT(imageExtent.width >> mipLevel);
1022     DE_ASSERT(imageExtent.height >> mipLevel);
1023 
1024     uint32_t mipOffset = 0;
1025 
1026     for (uint32_t level = 0; mipLevel && level < mipLevel; ++level)
1027     {
1028         mipOffset += ut::computeImageSize(imageExtent, imageFormat, true, level);
1029     }
1030 
1031     unsigned char *hostPtr = static_cast<unsigned char *>(buffer->alloc->getHostPtr());
1032     unsigned char *data    = hostPtr + bufferInfos[imageIndex].offset + mipOffset;
1033     return tcu::PixelBufferAccess(vk::mapVkFormat(imageFormat), (imageExtent.width >> mipLevel),
1034                                   (imageExtent.height >> mipLevel), imageExtent.depth, data);
1035 }
1036 
updateDescriptors(IterateCommonVariables & variables)1037 void CommonDescriptorInstance::updateDescriptors(IterateCommonVariables &variables)
1038 {
1039     const std::vector<uint32_t> primes = ut::generatePrimes(variables.availableDescriptorCount);
1040     const uint32_t primeCount          = static_cast<uint32_t>(primes.size());
1041 
1042     for (uint32_t primeIdx = 0; primeIdx < primeCount; ++primeIdx)
1043     {
1044         const VkDescriptorBufferInfo *pBufferInfo = nullptr;
1045         const VkDescriptorImageInfo *pImageInfo   = nullptr;
1046         const VkBufferView *pTexelBufferView      = nullptr;
1047 
1048         VkDescriptorImageInfo imageInfo = {static_cast<VkSampler>(0), static_cast<VkImageView>(0),
1049                                            VK_IMAGE_LAYOUT_GENERAL};
1050 
1051         switch (m_testParams.descriptorType)
1052         {
1053         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1054         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1055         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1056         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1057         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1058         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1059         {
1060             pBufferInfo = &variables.descriptorsBufferInfos[primeIdx];
1061             switch (m_testParams.descriptorType)
1062             {
1063             case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1064             case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1065                 pTexelBufferView = &(**variables.descriptorsBufferViews[primeIdx]);
1066                 break;
1067             default:
1068                 break;
1069             }
1070         }
1071         break;
1072 
1073         case VK_DESCRIPTOR_TYPE_SAMPLER:
1074             imageInfo.sampler = **variables.descriptorSamplers[primeIdx];
1075             pImageInfo        = &imageInfo;
1076             break;
1077 
1078         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1079         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1080         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1081             imageInfo.imageView = **variables.descriptorImageViews[primeIdx];
1082             pImageInfo          = &imageInfo;
1083             break;
1084 
1085         default:
1086             break;
1087         }
1088 
1089         const VkWriteDescriptorSet writeInfo = {
1090             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1091             nullptr,                                // pNext
1092             *variables.descriptorSet,               // descriptorSet
1093             BINDING_TestObject,                     // descriptorBinding;
1094             primes[primeIdx],                       // elementIndex
1095             1u,                                     // descriptorCount
1096             m_testParams.descriptorType,            // descriptorType
1097             pImageInfo,                             // pImageInfo
1098             pBufferInfo,                            // pBufferInfo
1099             pTexelBufferView                        // pTexelBufferView
1100         };
1101 
1102         m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, nullptr);
1103     }
1104 }
1105 
updateUnusedDescriptors(IterateCommonVariables & variables)1106 void CommonDescriptorInstance::updateUnusedDescriptors(IterateCommonVariables &variables)
1107 {
1108     const std::vector<uint32_t> primes = ut::generatePrimes(variables.availableDescriptorCount);
1109     const uint32_t primeCount          = static_cast<uint32_t>(primes.size());
1110     uint32_t primeIndex                = 0u;
1111 
1112     for (uint32_t i = 0u; i < variables.availableDescriptorCount; ++i)
1113     {
1114         if (primeIndex < primeCount && i == primes[primeIndex])
1115         {
1116             ++primeIndex;
1117             continue;
1118         }
1119 
1120         const VkDescriptorBufferInfo *pBufferInfo = DE_NULL;
1121         const VkDescriptorImageInfo *pImageInfo   = DE_NULL;
1122         const VkBufferView *pTexelBufferView      = DE_NULL;
1123 
1124         VkDescriptorImageInfo imageInfo = {static_cast<VkSampler>(0), static_cast<VkImageView>(0),
1125                                            VK_IMAGE_LAYOUT_GENERAL};
1126 
1127         switch (m_testParams.descriptorType)
1128         {
1129         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1130         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1131         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1132         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1133         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1134         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1135         {
1136             pBufferInfo = &variables.unusedDescriptorsBufferInfos[0];
1137             switch (m_testParams.descriptorType)
1138             {
1139             case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1140             case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1141                 pTexelBufferView = &(**variables.unusedDescriptorsBufferViews[0]);
1142                 break;
1143             default:
1144                 break;
1145             }
1146         }
1147         break;
1148 
1149         case VK_DESCRIPTOR_TYPE_SAMPLER:
1150             imageInfo.sampler = **variables.unusedDescriptorSamplers[0];
1151             pImageInfo        = &imageInfo;
1152             break;
1153 
1154         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1155         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1156         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1157             imageInfo.imageView = **variables.unusedDescriptorImageViews[0];
1158             pImageInfo          = &imageInfo;
1159             break;
1160 
1161         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1162             imageInfo.sampler   = **variables.unusedDescriptorSamplers[0];
1163             imageInfo.imageView = **variables.unusedDescriptorImageViews[0];
1164             pImageInfo          = &imageInfo;
1165             break;
1166 
1167         default:
1168             break;
1169         }
1170 
1171         const VkWriteDescriptorSet writeInfo = {
1172             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1173             DE_NULL,                                // pNext
1174             *variables.descriptorSet,               // descriptorSet
1175             BINDING_TestObject,                     // descriptorBinding;
1176             i,                                      // elementIndex
1177             1u,                                     // descriptorCount
1178             m_testParams.descriptorType,            // descriptorType
1179             pImageInfo,                             // pImageInfo
1180             pBufferInfo,                            // pBufferInfo
1181             pTexelBufferView                        // pTexelBufferView
1182         };
1183 
1184         m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL);
1185     }
1186 }
1187 
destroyUnusedResources(IterateCommonVariables & variables)1188 void CommonDescriptorInstance::destroyUnusedResources(IterateCommonVariables &variables)
1189 {
1190     variables.unusedDescriptorsBufferInfos.clear();
1191     variables.unusedDescriptorsBufferViews.clear();
1192     variables.unusedDescriptorImageViews.clear();
1193     variables.unusedDescriptorSamplers.clear();
1194     variables.unusedDescriptorsImages.clear();
1195 }
1196 
iterateCommandSetup(IterateCommonVariables & variables)1197 void CommonDescriptorInstance::iterateCommandSetup(IterateCommonVariables &variables)
1198 {
1199     variables.dataAlignment = 0;
1200 
1201     variables.renderArea.offset.x      = 0;
1202     variables.renderArea.offset.y      = 0;
1203     variables.renderArea.extent.width  = m_testParams.frameResolution.width;
1204     variables.renderArea.extent.height = m_testParams.frameResolution.height;
1205 
1206     variables.vertexCount = m_testParams.frameResolution.width * m_testParams.frameResolution.height;
1207 
1208     variables.lowerBound = 0;
1209     variables.upperBound = variables.vertexCount;
1210 
1211     variables.descriptorSetLayout =
1212         createDescriptorSetLayout(m_testParams.calculateInLoop, variables.availableDescriptorCount);
1213     variables.validDescriptorCount = ut::computePrimeCount(variables.availableDescriptorCount);
1214     variables.descriptorPool       = createDescriptorPool(variables.availableDescriptorCount);
1215     variables.descriptorSet        = createDescriptorSet(*variables.descriptorPool, *variables.descriptorSetLayout);
1216 
1217     std::vector<VkDescriptorSetLayout> descriptorSetLayouts;
1218     descriptorSetLayouts.push_back(*variables.descriptorSetLayout);
1219     if (m_testParams.calculateInLoop)
1220     {
1221         variables.descriptorEnumerator.init(m_context, variables.vertexCount, variables.availableDescriptorCount);
1222         descriptorSetLayouts.push_back(*variables.descriptorEnumerator.descriptorSetLayout);
1223     }
1224 
1225     variables.pipelineLayout = createPipelineLayout(descriptorSetLayouts);
1226 
1227     createAndPopulateDescriptors(variables);
1228 
1229     variables.renderPass = createRenderPass(variables);
1230     variables.pipeline   = createPipeline(*variables.pipelineLayout, *variables.renderPass);
1231 
1232     variables.commandBuffer = createCmdBuffer();
1233 
1234     if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) ||
1235         (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT))
1236     {
1237         createVertexAttributeBuffer(variables.vertexAttributesBuffer, variables.availableDescriptorCount);
1238         createFramebuffer(variables.frameBuffer, *variables.renderPass, variables);
1239     }
1240 
1241     if (m_testParams.calculateInLoop)
1242     {
1243         variables.descriptorEnumerator.update(m_context);
1244     }
1245 
1246     if (!m_testParams.updateAfterBind)
1247     {
1248         updateDescriptors(variables);
1249     }
1250 }
1251 
iterateCommandBegin(IterateCommonVariables & variables,bool firstPass)1252 void CommonDescriptorInstance::iterateCommandBegin(IterateCommonVariables &variables, bool firstPass)
1253 {
1254     if (m_testParams.lifetimeCheck)
1255     {
1256         createAndPopulateUnusedDescriptors(variables);
1257 
1258         if (!m_testParams.updateAfterBind)
1259             updateUnusedDescriptors(variables);
1260     }
1261 
1262     vk::beginCommandBuffer(m_vki, *variables.commandBuffer);
1263 
1264     // Clear color attachment, and transition it to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
1265     if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) ||
1266         (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT))
1267     {
1268         if (firstPass)
1269         {
1270             const VkImageMemoryBarrier preImageBarrier = {
1271                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType        sType
1272                 nullptr,                                // const void*            pNext
1273                 0u,                                     // VkAccessFlags        srcAccessMask
1274                 VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags        dstAccessMask
1275                 VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout        oldLayout
1276                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout        newLayout
1277                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t                srcQueueFamilyIndex
1278                 VK_QUEUE_FAMILY_IGNORED,                // uint32_t                dstQueueFamilyIndex
1279                 *variables.frameBuffer->image->image,   // VkImage                image
1280                 {
1281                     VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
1282                     0u,                        // uint32_t                baseMipLevel
1283                     VK_REMAINING_MIP_LEVELS,   // uint32_t                mipLevels,
1284                     0u,                        // uint32_t                baseArray
1285                     VK_REMAINING_ARRAY_LAYERS, // uint32_t                arraySize
1286                 }};
1287 
1288             m_vki.cmdPipelineBarrier(*variables.commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1289                                      VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0,
1290                                      (const VkMemoryBarrier *)nullptr, 0, (const VkBufferMemoryBarrier *)nullptr, 1,
1291                                      &preImageBarrier);
1292 
1293             const VkClearColorValue clearColorValue = makeClearValueColor(m_clearColor).color;
1294 
1295             m_vki.cmdClearColorImage(*variables.commandBuffer, *variables.frameBuffer->image->image,
1296                                      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColorValue, 1,
1297                                      &preImageBarrier.subresourceRange);
1298 
1299             const VkImageMemoryBarrier postImageBarrier = {
1300                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType        sType
1301                 nullptr,                                // const void*            pNext
1302                 VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags        srcAccessMask
1303                 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1304                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags        dstAccessMask
1305                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,     // VkImageLayout        oldLayout
1306                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        newLayout
1307                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t                srcQueueFamilyIndex
1308                 VK_QUEUE_FAMILY_IGNORED,                  // uint32_t                dstQueueFamilyIndex
1309                 *variables.frameBuffer->image->image,     // VkImage                image
1310                 {
1311                     VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
1312                     0u,                        // uint32_t                baseMipLevel
1313                     VK_REMAINING_MIP_LEVELS,   // uint32_t                mipLevels,
1314                     0u,                        // uint32_t                baseArray
1315                     VK_REMAINING_ARRAY_LAYERS, // uint32_t                arraySize
1316                 }};
1317 
1318             m_vki.cmdPipelineBarrier(*variables.commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1319                                      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0,
1320                                      (const VkMemoryBarrier *)nullptr, 0, (const VkBufferMemoryBarrier *)nullptr, 1,
1321                                      &postImageBarrier);
1322         }
1323     }
1324 
1325     if (m_testParams.calculateInLoop)
1326     {
1327         deRandom rnd;
1328         deRandom_init(&rnd, static_cast<uint32_t>(m_testParams.descriptorType));
1329         const uint32_t quarter = variables.vertexCount / 4;
1330 
1331         variables.lowerBound = deRandom_getUint32(&rnd) % quarter;
1332         variables.upperBound = (deRandom_getUint32(&rnd) % quarter) + (3 * quarter);
1333 
1334         const push_constant pc = {static_cast<int32_t>(variables.lowerBound),
1335                                   static_cast<int32_t>(variables.upperBound)};
1336 
1337         m_vki.cmdPushConstants(*variables.commandBuffer, *variables.pipelineLayout, m_testParams.stageFlags, 0u,
1338                                static_cast<uint32_t>(sizeof(pc)), &pc);
1339     }
1340 
1341     if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) ||
1342         (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT))
1343     {
1344         commandBindVertexAttributes(*variables.commandBuffer, variables.vertexAttributesBuffer);
1345     }
1346 
1347     if (m_testParams.calculateInLoop)
1348     {
1349         commandBindDescriptorSets(*variables.commandBuffer, *variables.pipelineLayout,
1350                                   *variables.descriptorEnumerator.descriptorSet, 1);
1351     }
1352 
1353     if (!ut::isDynamicDescriptor(m_testParams.descriptorType))
1354     {
1355         commandBindDescriptorSets(*variables.commandBuffer, *variables.pipelineLayout, *variables.descriptorSet, 0);
1356     }
1357 
1358     commandBindPipeline(*variables.commandBuffer, *variables.pipeline);
1359 }
1360 
iterate(void)1361 tcu::TestStatus CommonDescriptorInstance::iterate(void)
1362 {
1363     IterateCommonVariables v;
1364     ut::UpdatablePixelBufferAccessPtr programResult;
1365     ut::UpdatablePixelBufferAccessPtr referenceResult;
1366 
1367     bool firstPass = true;
1368 
1369     iterateCommandSetup(v);
1370 
1371     v.renderArea.extent.width  = m_testParams.frameResolution.width / 4;
1372     v.renderArea.extent.height = m_testParams.frameResolution.height / 4;
1373 
1374     for (int x = 0; x < 4; x++)
1375         for (int y = 0; y < 4; y++)
1376         {
1377             iterateCommandBegin(v, firstPass);
1378 
1379             if (true == firstPass && true == m_testParams.copyBuffersToImages)
1380             {
1381                 copyBuffersToImages(v);
1382             }
1383 
1384             firstPass = false;
1385 
1386             if (true == m_testParams.updateAfterBind)
1387             {
1388                 updateDescriptors(v);
1389             }
1390 
1391             v.renderArea.offset.x = x * m_testParams.frameResolution.width / 4;
1392             v.renderArea.offset.y = y * m_testParams.frameResolution.height / 4;
1393 
1394             vk::VkRect2D scissor = makeRect2D(v.renderArea.offset.x, v.renderArea.offset.y, v.renderArea.extent.width,
1395                                               v.renderArea.extent.height);
1396             m_vki.cmdSetScissor(*v.commandBuffer, 0u, 1u, &scissor);
1397 
1398             vk::beginRenderPass(m_vki, *v.commandBuffer, *v.renderPass, *v.frameBuffer->buffer, v.renderArea,
1399                                 m_clearColor);
1400             m_vki.cmdDraw(*v.commandBuffer, v.vertexCount, 1u, 0u, 0u);
1401             vk::endRenderPass(m_vki, *v.commandBuffer);
1402 
1403             iterateCommandEnd(v, programResult, referenceResult);
1404             programResult->invalidate();
1405         }
1406 
1407     if (iterateVerifyResults(v, programResult, referenceResult))
1408         return tcu::TestStatus::pass("Pass");
1409     return tcu::TestStatus::fail("Failed -- check log for details");
1410 }
1411 
createColorScheme(void)1412 std::vector<float> CommonDescriptorInstance::createColorScheme(void)
1413 {
1414     std::vector<float> cs;
1415     int divider = 2;
1416     for (int i = 0; i < 10; ++i)
1417     {
1418         cs.push_back(1.0f / float(divider));
1419         divider *= 2;
1420     }
1421     return cs;
1422 }
1423 
iterateCommandEnd(IterateCommonVariables & variables,ut::UpdatablePixelBufferAccessPtr & programResult,ut::UpdatablePixelBufferAccessPtr & referenceResult,bool collectBeforeSubmit)1424 void CommonDescriptorInstance::iterateCommandEnd(IterateCommonVariables &variables,
1425                                                  ut::UpdatablePixelBufferAccessPtr &programResult,
1426                                                  ut::UpdatablePixelBufferAccessPtr &referenceResult,
1427                                                  bool collectBeforeSubmit)
1428 {
1429     // Destroy unused descriptor resources to test there's no issues as allowed by the spec
1430     if (m_testParams.lifetimeCheck)
1431         destroyUnusedResources(variables);
1432 
1433     if (collectBeforeSubmit)
1434     {
1435         iterateCollectResults(programResult, variables, true);
1436         iterateCollectResults(referenceResult, variables, false);
1437     }
1438 
1439     VK_CHECK(m_vki.endCommandBuffer(*variables.commandBuffer));
1440     Move<VkFence> fence = commandSubmit(*variables.commandBuffer);
1441     m_vki.waitForFences(m_vkd, 1, &(*fence), true, ~0ull);
1442 
1443     if (false == collectBeforeSubmit)
1444     {
1445         iterateCollectResults(programResult, variables, true);
1446         iterateCollectResults(referenceResult, variables, false);
1447     }
1448     m_context.resetCommandPoolForVKSC(m_vkd, *m_commandPool);
1449 }
1450 
iterateVerifyResults(IterateCommonVariables & variables,ut::UpdatablePixelBufferAccessPtr programResult,ut::UpdatablePixelBufferAccessPtr referenceResult)1451 bool CommonDescriptorInstance::iterateVerifyResults(IterateCommonVariables &variables,
1452                                                     ut::UpdatablePixelBufferAccessPtr programResult,
1453                                                     ut::UpdatablePixelBufferAccessPtr referenceResult)
1454 {
1455     bool result = false;
1456     if (FUZZY_COMPARE)
1457     {
1458         result = tcu::fuzzyCompare(m_context.getTestContext().getLog(), "Fuzzy Compare", "Comparison result",
1459                                    *referenceResult.get(), *programResult.get(), 0.02f, tcu::COMPARE_LOG_EVERYTHING);
1460     }
1461     else
1462     {
1463         result = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Float Threshold Compare",
1464                                             "Comparison result", *referenceResult.get(), *programResult.get(),
1465                                             tcu::Vec4(0.02f, 0.02f, 0.02f, 0.02f), tcu::COMPARE_LOG_EVERYTHING);
1466     }
1467 
1468     if (m_testParams.allowVertexStoring)
1469     {
1470         result = (verifyVertexWriteResults(variables) && result);
1471     }
1472 
1473     return result;
1474 }
1475 
iterateCollectResults(ut::UpdatablePixelBufferAccessPtr & result,const IterateCommonVariables & variables,bool fromTest)1476 void CommonDescriptorInstance::iterateCollectResults(ut::UpdatablePixelBufferAccessPtr &result,
1477                                                      const IterateCommonVariables &variables, bool fromTest)
1478 {
1479     if (fromTest)
1480     {
1481         result = commandReadFrameBuffer(*variables.commandBuffer, variables.frameBuffer);
1482     }
1483     else
1484     {
1485         result = ut::UpdatablePixelBufferAccessPtr(
1486             new ut::PixelBufferAccessAllocation(vk::mapVkFormat(m_colorFormat), m_testParams.frameResolution));
1487 
1488         for (uint32_t y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y)
1489         {
1490             for (uint32_t x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum)
1491             {
1492                 const float component = m_colorScheme[(pixelNum % variables.validDescriptorCount) % m_schemeSize];
1493                 result->setPixel(tcu::Vec4(component, component, component, 1.0f), x, y);
1494             }
1495         }
1496     }
1497 }
1498 
createCmdBuffer(void)1499 Move<VkCommandBuffer> CommonDescriptorInstance::createCmdBuffer(void)
1500 {
1501     return vk::allocateCommandBuffer(m_vki, m_vkd, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1502 }
1503 
commandSubmit(VkCommandBuffer cmd)1504 Move<VkFence> CommonDescriptorInstance::commandSubmit(VkCommandBuffer cmd)
1505 {
1506     Move<VkFence> fence(vk::createFence(m_vki, m_vkd));
1507 
1508     const VkSubmitInfo submitInfo = {
1509         VK_STRUCTURE_TYPE_SUBMIT_INFO,                      // sType
1510         nullptr,                                            // pNext
1511         0u,                                                 // waitSemaphoreCount
1512         static_cast<VkSemaphore *>(nullptr),                // pWaitSemaphores
1513         static_cast<const VkPipelineStageFlags *>(nullptr), // pWaitDstStageMask
1514         1u,                                                 // commandBufferCount
1515         &cmd,                                               // pCommandBuffers
1516         0u,                                                 // signalSemaphoreCount
1517         static_cast<VkSemaphore *>(nullptr)                 // pSignalSemaphores
1518     };
1519 
1520     VK_CHECK(m_vki.queueSubmit(m_queue, 1u, &submitInfo, *fence));
1521 
1522     return fence;
1523 }
1524 
verifyVertexWriteResults(IterateCommonVariables & variables)1525 bool CommonDescriptorInstance::verifyVertexWriteResults(IterateCommonVariables &variables)
1526 {
1527     DE_UNREF(variables);
1528     return true;
1529 }
1530 
commandBindPipeline(VkCommandBuffer commandBuffer,VkPipeline pipeline)1531 void CommonDescriptorInstance::commandBindPipeline(VkCommandBuffer commandBuffer, VkPipeline pipeline)
1532 {
1533     const VkPipelineBindPoint pipelineBindingPoint = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ?
1534                                                          VK_PIPELINE_BIND_POINT_COMPUTE :
1535                                                          VK_PIPELINE_BIND_POINT_GRAPHICS;
1536     m_vki.cmdBindPipeline(commandBuffer, pipelineBindingPoint, pipeline);
1537 }
1538 
commandBindVertexAttributes(VkCommandBuffer commandBuffer,const ut::BufferHandleAllocSp & vertexAttributesBuffer)1539 void CommonDescriptorInstance::commandBindVertexAttributes(VkCommandBuffer commandBuffer,
1540                                                            const ut::BufferHandleAllocSp &vertexAttributesBuffer)
1541 {
1542     const VkDeviceSize offsets[] = {0u};
1543     const VkBuffer buffers[]     = {*vertexAttributesBuffer->buffer};
1544     m_vki.cmdBindVertexBuffers(commandBuffer, 0u, 1u, buffers, offsets);
1545 }
1546 
commandBindDescriptorSets(VkCommandBuffer commandBuffer,VkPipelineLayout pipelineLayout,VkDescriptorSet descriptorSet,uint32_t descriptorSetIndex)1547 void CommonDescriptorInstance::commandBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout,
1548                                                          VkDescriptorSet descriptorSet, uint32_t descriptorSetIndex)
1549 {
1550     const VkPipelineBindPoint pipelineBindingPoint = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ?
1551                                                          VK_PIPELINE_BIND_POINT_COMPUTE :
1552                                                          VK_PIPELINE_BIND_POINT_GRAPHICS;
1553     m_vki.cmdBindDescriptorSets(commandBuffer, pipelineBindingPoint, pipelineLayout, descriptorSetIndex, 1u,
1554                                 &descriptorSet, 0u, static_cast<uint32_t *>(nullptr));
1555 }
1556 
commandReadFrameBuffer(VkCommandBuffer commandBuffer,const ut::FrameBufferSp & frameBuffer)1557 ut::UpdatablePixelBufferAccessPtr CommonDescriptorInstance::commandReadFrameBuffer(VkCommandBuffer commandBuffer,
1558                                                                                    const ut::FrameBufferSp &frameBuffer)
1559 {
1560     ut::BufferHandleAllocSp frameBufferContent;
1561     commandReadFrameBuffer(frameBufferContent, commandBuffer, frameBuffer);
1562     return ut::UpdatablePixelBufferAccessPtr(new ut::PixelBufferAccessBuffer(
1563         m_vkd, m_vki, vk::mapVkFormat(m_colorFormat), m_testParams.frameResolution,
1564         de::SharedPtr<Move<VkBuffer>>(new Move<VkBuffer>(frameBufferContent->buffer)),
1565         de::SharedPtr<de::MovePtr<Allocation>>(new de::MovePtr<Allocation>(frameBufferContent->alloc))));
1566 }
1567 
commandReadFrameBuffer(ut::BufferHandleAllocSp & content,VkCommandBuffer commandBuffer,const ut::FrameBufferSp & frameBuffer)1568 void CommonDescriptorInstance::commandReadFrameBuffer(ut::BufferHandleAllocSp &content, VkCommandBuffer commandBuffer,
1569                                                       const ut::FrameBufferSp &frameBuffer)
1570 {
1571     Move<VkBuffer> buffer;
1572     de::MovePtr<Allocation> allocation;
1573 
1574     const VkDeviceSize bufferSize = ut::computeImageSize(frameBuffer->image);
1575 
1576     // create a buffer and an host allocation for it
1577     {
1578         const VkBufferCreateInfo bufferCreateInfo = {
1579             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
1580             nullptr,                              // pNext
1581             0u,                                   // flags
1582             bufferSize,                           // size
1583             VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // usage
1584             VK_SHARING_MODE_EXCLUSIVE,            // sharingMode
1585             1u,                                   // queueFamilyIndexCoun
1586             &m_queueFamilyIndex                   // pQueueFamilyIndices
1587         };
1588 
1589         buffer = vk::createBuffer(m_vki, m_vkd, &bufferCreateInfo);
1590         const VkMemoryRequirements memRequirements(vk::getBufferMemoryRequirements(m_vki, m_vkd, *buffer));
1591         allocation = m_allocator.allocate(memRequirements, MemoryRequirement::HostVisible);
1592 
1593         VK_CHECK(m_vki.bindBufferMemory(m_vkd, *buffer, allocation->getMemory(), allocation->getOffset()));
1594     }
1595 
1596     const VkImage &image = *frameBuffer->image->image;
1597 
1598     VkImageSubresourceRange subresourceRange = {
1599         VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1600         0u,                        // baseMipLevel
1601         1u,                        // levelCount
1602         0u,                        // baseArrayLayer
1603         1u                         // layerCount
1604     };
1605 
1606     const VkImageMemoryBarrier barrierBefore = {
1607         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // sType;
1608         nullptr,                                  // pNext;
1609         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // srcAccessMask;
1610         VK_ACCESS_TRANSFER_READ_BIT,              // dstAccessMask;
1611         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
1612         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,     // newLayout;
1613         VK_QUEUE_FAMILY_IGNORED,                  // srcQueueFamilyIndex;
1614         VK_QUEUE_FAMILY_IGNORED,                  // dstQueueFamilyIndex;
1615         image,                                    // image;
1616         subresourceRange                          // subresourceRange;
1617     };
1618 
1619     const VkBufferImageCopy copyRegion = {
1620         0u,                                // bufferOffset
1621         frameBuffer->image->extent.width,  // bufferRowLength
1622         frameBuffer->image->extent.height, // bufferImageHeight
1623         {
1624             // VkImageSubresourceLayers
1625             VK_IMAGE_ASPECT_COLOR_BIT, // aspect
1626             0u,                        // mipLevel
1627             0u,                        // baseArrayLayer
1628             1u,                        // layerCount
1629         },
1630         {0, 0, 0},                 // imageOffset
1631         frameBuffer->image->extent // imageExtent
1632     };
1633 
1634     const VkBufferMemoryBarrier bufferBarrier = {
1635         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType;
1636         nullptr,                                 // pNext;
1637         VK_ACCESS_TRANSFER_WRITE_BIT,            // srcAccessMask;
1638         VK_ACCESS_HOST_READ_BIT,                 // dstAccessMask;
1639         VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex;
1640         VK_QUEUE_FAMILY_IGNORED,                 // dstQueueFamilyIndex;
1641         *buffer,                                 // buffer;
1642         0u,                                      // offset;
1643         bufferSize                               // size;
1644     };
1645 
1646     const VkImageMemoryBarrier barrierAfter = {
1647         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,   // sType;
1648         nullptr,                                  // pNext;
1649         VK_ACCESS_TRANSFER_READ_BIT,              // srcAccessMask;
1650         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // dstAccessMask;
1651         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,     // oldLayout;
1652         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout;
1653         VK_QUEUE_FAMILY_IGNORED,                  // srcQueueFamilyIndex;
1654         VK_QUEUE_FAMILY_IGNORED,                  // dstQueueFamilyIndex;
1655         image,                                    // image
1656         subresourceRange                          // subresourceRange
1657     };
1658 
1659     m_vki.cmdPipelineBarrier(commandBuffer, // commandBuffer
1660                              VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1661                              VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask, dstStageMask
1662                              (VkDependencyFlags)0,           // dependencyFlags
1663                              0u, nullptr,                    // memoryBarrierCount, pMemoryBarriers
1664                              0u, nullptr,                    // bufferBarrierCount, pBufferBarriers
1665                              1u, &barrierBefore);            // imageBarrierCount, pImageBarriers
1666 
1667     m_vki.cmdCopyImageToBuffer(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u, &copyRegion);
1668 
1669     m_vki.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1670                              VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0u,
1671                              nullptr, 1u, &bufferBarrier, 1u, &barrierAfter);
1672 
1673     content = ut::BufferHandleAllocSp(new ut::BufferHandleAlloc(buffer, allocation));
1674 }
1675 
getColorAccess(VkDescriptorType descriptorType,const char * indexVariableName,bool usesMipMaps)1676 std::string CommonDescriptorInstance::getColorAccess(VkDescriptorType descriptorType, const char *indexVariableName,
1677                                                      bool usesMipMaps)
1678 {
1679     std::string text;
1680     std::map<std::string, std::string> vars;
1681     vars["INDEX"] = indexVariableName;
1682 
1683     switch (descriptorType)
1684     {
1685     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1686     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1687         text = "data[nonuniformEXT(${INDEX})].c";
1688         break;
1689     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1690     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1691         text = "data[nonuniformEXT(${INDEX})].cold";
1692         break;
1693     case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1694         text = "subpassLoad(data[nonuniformEXT(${INDEX})]).rgba";
1695         break;
1696     case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1697         text = "texelFetch(data[nonuniformEXT(${INDEX})], 0)";
1698         break;
1699     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1700         text = "imageLoad(data[nonuniformEXT(${INDEX})], 0)";
1701         break;
1702     case VK_DESCRIPTOR_TYPE_SAMPLER:
1703         text = usesMipMaps ? "textureLod(nonuniformEXT(sampler2D(tex, data[${INDEX}])), normalpos, 1)" :
1704                              "texture(   nonuniformEXT(sampler2D(tex, data[${INDEX}])), normalpos   )";
1705         break;
1706     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1707         text = usesMipMaps ? "textureLod( nonuniformEXT(sampler2D(data[${INDEX}], samp)), vec2(0,0), "
1708                              "textureQueryLevels(nonuniformEXT(sampler2D(data[${INDEX}], samp)))-1)" :
1709                              "texture(    nonuniformEXT(sampler2D(data[${INDEX}], samp)), vec2(0,0)   )";
1710         break;
1711     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1712         text = usesMipMaps ? "textureLod( data[nonuniformEXT(${INDEX})], uvec2(0,0), "
1713                              "textureQueryLevels(data[nonuniformEXT(${INDEX})])-1)" :
1714                              "texture(    data[nonuniformEXT(${INDEX})], uvec2(0,0)   )";
1715         break;
1716     default:
1717         TCU_THROW(InternalError, "Not implemented descriptor type");
1718     }
1719 
1720     return tcu::StringTemplate(text).specialize(vars);
1721 }
1722 
getFragmentReturnSource(const std::string & colorAccess)1723 std::string CommonDescriptorInstance::getFragmentReturnSource(const std::string &colorAccess)
1724 {
1725     return "  FragColor = " + colorAccess + ";\n";
1726 }
1727 
getFragmentLoopSource(const std::string & colorAccess1,const std::string & colorAccess2)1728 std::string CommonDescriptorInstance::getFragmentLoopSource(const std::string &colorAccess1,
1729                                                             const std::string &colorAccess2)
1730 {
1731     std::map<std::string, std::string> vars;
1732     vars["COLOR_ACCESS_1"] = colorAccess1;
1733     vars["COLOR_ACCESS_2"] = colorAccess2;
1734 
1735     const char *s = "  vec4 sumClr1 = vec4(0,0,0,0);        \n"
1736                     "  vec4 sumClr2 = vec4(0,0,0,0);        \n"
1737                     "  for (int i = pc.lowerBound; i < pc.upperBound; ++i)    \n"
1738                     "  {\n"
1739                     "    int loopIdx = texelFetch(iter, i).x;                \n"
1740                     "    sumClr1 += ${COLOR_ACCESS_2} + ${COLOR_ACCESS_1};    \n"
1741                     "    sumClr2 += ${COLOR_ACCESS_2};                        \n"
1742                     "  }\n"
1743                     "  FragColor = vec4(((sumClr1 - sumClr2) / float(pc.upperBound - pc.lowerBound)).rgb, 1);    \n";
1744 
1745     return tcu::StringTemplate(s).specialize(vars);
1746 }
1747 
performWritesInVertex(VkDescriptorType descriptorType)1748 bool CommonDescriptorInstance::performWritesInVertex(VkDescriptorType descriptorType)
1749 {
1750     switch (descriptorType)
1751     {
1752     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1753     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1754     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1755         return true;
1756     default:
1757         return false;
1758     }
1759 }
1760 
performWritesInVertex(VkDescriptorType descriptorType,const Context & context)1761 bool CommonDescriptorInstance::performWritesInVertex(VkDescriptorType descriptorType, const Context &context)
1762 {
1763     ut::DeviceProperties dp(context);
1764     const VkPhysicalDeviceFeatures &feats = dp.physicalDeviceFeatures();
1765     return feats.vertexPipelineStoresAndAtomics && CommonDescriptorInstance::performWritesInVertex(descriptorType);
1766 }
1767 
getShaderAsm(VkShaderStageFlagBits shaderType,const TestCaseParams & testCaseParams,bool allowVertexStoring)1768 std::string CommonDescriptorInstance::getShaderAsm(VkShaderStageFlagBits shaderType,
1769                                                    const TestCaseParams &testCaseParams, bool allowVertexStoring)
1770 {
1771     std::stringstream s;
1772     switch (shaderType)
1773     {
1774     case VK_SHADER_STAGE_VERTEX_BIT:
1775         switch (testCaseParams.descriptorType)
1776         {
1777         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1778         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1779         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1780             s << "               OpCapability Shader\n";
1781             s << "               OpCapability SampledBuffer\n";
1782             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
1783             s << "               OpMemoryModel Logical GLSL450\n";
1784             s << "               OpEntryPoint Vertex %main \"main\" %_ %position %in_position %normalpos %in_normalpos "
1785                  "%vIndex %gl_VertexIndex %rIndex %index %gIndex %bIndex %aIndex\n";
1786             s << "               OpSource GLSL 450\n";
1787             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
1788             s << "               OpSourceExtension \"GL_EXT_texture_buffer\"\n";
1789             s << "               OpName %main \"main\"\n";
1790             s << "               OpName %gl_PerVertex \"gl_PerVertex\"\n";
1791             s << "               OpMemberName %gl_PerVertex 0 \"gl_Position\"\n";
1792             s << "               OpMemberName %gl_PerVertex 1 \"gl_PointSize\"\n";
1793             s << "               OpMemberName %gl_PerVertex 2 \"gl_ClipDistance\"\n";
1794             s << "               OpMemberName %gl_PerVertex 3 \"gl_CullDistance\"\n";
1795             s << "               OpName %_ \"\"\n";
1796             s << "               OpName %position \"position\"\n";
1797             s << "               OpName %in_position \"in_position\"\n";
1798             s << "               OpName %normalpos \"normalpos\"\n";
1799             s << "               OpName %in_normalpos \"in_normalpos\"\n";
1800             s << "               OpName %vIndex \"vIndex\"\n";
1801             s << "               OpName %gl_VertexIndex \"gl_VertexIndex\"\n";
1802             s << "               OpName %rIndex \"rIndex\"\n";
1803             s << "               OpName %index \"index\"\n";
1804             s << "               OpName %gIndex \"gIndex\"\n";
1805             s << "               OpName %bIndex \"bIndex\"\n";
1806             s << "               OpName %aIndex \"aIndex\"\n";
1807             s << "               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n";
1808             s << "               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n";
1809             s << "               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n";
1810             s << "               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance\n";
1811             s << "               OpDecorate %gl_PerVertex Block\n";
1812             s << "               OpDecorate %position Location 0\n";
1813             s << "               OpDecorate %in_position Location 0\n";
1814             s << "               OpDecorate %normalpos Location 1\n";
1815             s << "               OpDecorate %in_normalpos Location 1\n";
1816             s << "               OpDecorate %vIndex Location 2\n";
1817             s << "               OpDecorate %gl_VertexIndex BuiltIn VertexIndex\n";
1818             s << "               OpDecorate %rIndex Location 3\n";
1819             s << "               OpDecorate %index Location 2\n";
1820             s << "               OpDecorate %gIndex Location 4\n";
1821             s << "               OpDecorate %bIndex Location 5\n";
1822             s << "               OpDecorate %aIndex Location 6\n";
1823             s << "       %void = OpTypeVoid\n";
1824             s << "          %3 = OpTypeFunction %void\n";
1825             s << "      %float = OpTypeFloat 32\n";
1826             s << "    %v4float = OpTypeVector %float 4\n";
1827             s << "       %uint = OpTypeInt 32 0\n";
1828             s << "     %uint_1 = OpConstant %uint 1\n";
1829             s << "%_arr_float_uint_1 = OpTypeArray %float %uint_1\n";
1830             s << "%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1\n";
1831             s << "%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n";
1832             s << "          %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n";
1833             s << "        %int = OpTypeInt 32 1\n";
1834             s << "      %int_1 = OpConstant %int 1\n";
1835             s << "%float_0_200000003 = OpConstant %float 0.200000003\n";
1836             s << "%_ptr_Output_float = OpTypePointer Output %float\n";
1837             s << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n";
1838             s << "   %position = OpVariable %_ptr_Output_v4float Output\n";
1839             s << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n";
1840             s << "%in_position = OpVariable %_ptr_Input_v4float Input\n";
1841             s << "    %v2float = OpTypeVector %float 2\n";
1842             s << "%_ptr_Output_v2float = OpTypePointer Output %v2float\n";
1843             s << "  %normalpos = OpVariable %_ptr_Output_v2float Output\n";
1844             s << "%_ptr_Input_v2float = OpTypePointer Input %v2float\n";
1845             s << "%in_normalpos = OpVariable %_ptr_Input_v2float Input\n";
1846             s << "      %int_0 = OpConstant %int 0\n";
1847             s << "%_ptr_Output_int = OpTypePointer Output %int\n";
1848             s << "     %vIndex = OpVariable %_ptr_Output_int Output\n";
1849             s << "%_ptr_Input_int = OpTypePointer Input %int\n";
1850             s << "%gl_VertexIndex = OpVariable %_ptr_Input_int Input\n";
1851             s << "     %rIndex = OpVariable %_ptr_Output_int Output\n";
1852             s << "      %v4int = OpTypeVector %int 4\n";
1853             s << "%_ptr_Input_v4int = OpTypePointer Input %v4int\n";
1854             s << "      %index = OpVariable %_ptr_Input_v4int Input\n";
1855             s << "     %uint_0 = OpConstant %uint 0\n";
1856             s << "     %gIndex = OpVariable %_ptr_Output_int Output\n";
1857             s << "     %bIndex = OpVariable %_ptr_Output_int Output\n";
1858             s << "     %uint_2 = OpConstant %uint 2\n";
1859             s << "     %aIndex = OpVariable %_ptr_Output_int Output\n";
1860             s << "     %uint_3 = OpConstant %uint 3\n";
1861             s << "       %main = OpFunction %void None %3\n";
1862             s << "          %5 = OpLabel\n";
1863             s << "         %18 = OpAccessChain %_ptr_Output_float %_ %int_1\n";
1864             s << "               OpStore %18 %float_0_200000003\n";
1865             s << "         %23 = OpLoad %v4float %in_position\n";
1866             s << "               OpStore %position %23\n";
1867             s << "         %29 = OpLoad %v2float %in_normalpos\n";
1868             s << "               OpStore %normalpos %29\n";
1869             s << "         %31 = OpLoad %v4float %position\n";
1870             s << "         %32 = OpAccessChain %_ptr_Output_v4float %_ %int_0\n";
1871             s << "               OpStore %32 %31\n";
1872             s << "         %37 = OpLoad %int %gl_VertexIndex\n";
1873             s << "               OpStore %vIndex %37\n";
1874             s << "         %43 = OpAccessChain %_ptr_Input_int %index %uint_0\n";
1875             s << "         %44 = OpLoad %int %43\n";
1876             s << "               OpStore %rIndex %44\n";
1877             s << "         %46 = OpAccessChain %_ptr_Input_int %index %uint_1\n";
1878             s << "         %47 = OpLoad %int %46\n";
1879             s << "               OpStore %gIndex %47\n";
1880             s << "         %50 = OpAccessChain %_ptr_Input_int %index %uint_2\n";
1881             s << "         %51 = OpLoad %int %50\n";
1882             s << "               OpStore %bIndex %51\n";
1883             s << "         %54 = OpAccessChain %_ptr_Input_int %index %uint_3\n";
1884             s << "         %55 = OpLoad %int %54\n";
1885             s << "               OpStore %aIndex %55\n";
1886             s << "               OpReturn\n";
1887             s << "               OpFunctionEnd\n";
1888             break;
1889         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1890             s << "               OpCapability Shader\n";
1891             s << "               OpCapability ImageBuffer\n";
1892             if (allowVertexStoring)
1893             {
1894                 s << "               OpCapability ShaderNonUniform\n";
1895                 s << "               OpCapability RuntimeDescriptorArray\n";
1896                 s << "               OpCapability StorageTexelBufferArrayNonUniformIndexing\n";
1897                 s << "               OpExtension \"SPV_EXT_descriptor_indexing\"\n";
1898             }
1899             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
1900             s << "               OpMemoryModel Logical GLSL450\n";
1901             s << "               OpEntryPoint Vertex %main \"main\" %_ %position %in_position %normalpos %in_normalpos "
1902                  "%vIndex %gl_VertexIndex %rIndex %index %gIndex %bIndex %aIndex %data\n";
1903             s << "               OpSource GLSL 450\n";
1904             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
1905             s << "               OpName %main \"main\"\n";
1906             s << "               OpName %gl_PerVertex \"gl_PerVertex\"\n";
1907             s << "               OpMemberName %gl_PerVertex 0 \"gl_Position\"\n";
1908             s << "               OpMemberName %gl_PerVertex 1 \"gl_PointSize\"\n";
1909             s << "               OpMemberName %gl_PerVertex 2 \"gl_ClipDistance\"\n";
1910             s << "               OpMemberName %gl_PerVertex 3 \"gl_CullDistance\"\n";
1911             s << "               OpName %_ \"\"\n";
1912             s << "               OpName %position \"position\"\n";
1913             s << "               OpName %in_position \"in_position\"\n";
1914             s << "               OpName %normalpos \"normalpos\"\n";
1915             s << "               OpName %in_normalpos \"in_normalpos\"\n";
1916             s << "               OpName %vIndex \"vIndex\"\n";
1917             s << "               OpName %gl_VertexIndex \"gl_VertexIndex\"\n";
1918             s << "               OpName %rIndex \"rIndex\"\n";
1919             s << "               OpName %index \"index\"\n";
1920             s << "               OpName %gIndex \"gIndex\"\n";
1921             s << "               OpName %bIndex \"bIndex\"\n";
1922             s << "               OpName %aIndex \"aIndex\"\n";
1923             s << "               OpName %data \"data\"\n";
1924             s << "               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n";
1925             s << "               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n";
1926             s << "               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n";
1927             s << "               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance\n";
1928             s << "               OpDecorate %gl_PerVertex Block\n";
1929             s << "               OpDecorate %position Location 0\n";
1930             s << "               OpDecorate %in_position Location 0\n";
1931             s << "               OpDecorate %normalpos Location 1\n";
1932             s << "               OpDecorate %in_normalpos Location 1\n";
1933             s << "               OpDecorate %vIndex Location 2\n";
1934             s << "               OpDecorate %gl_VertexIndex BuiltIn VertexIndex\n";
1935             s << "               OpDecorate %rIndex Location 3\n";
1936             s << "               OpDecorate %index Location 2\n";
1937             s << "               OpDecorate %gIndex Location 4\n";
1938             s << "               OpDecorate %bIndex Location 5\n";
1939             s << "               OpDecorate %aIndex Location 6\n";
1940             s << "               OpDecorate %data DescriptorSet 0\n";
1941             s << "               OpDecorate %data Binding " << BINDING_TestObject << "\n";
1942             if (allowVertexStoring)
1943             {
1944                 // s << "               OpDecorate %66 NonUniform\n";
1945                 // s << "               OpDecorate %68 NonUniform\n";
1946                 s << "               OpDecorate %69 NonUniform\n";
1947                 // s << "               OpDecorate %71 NonUniform\n";
1948                 // s << "               OpDecorate %72 NonUniform\n";
1949                 s << "               OpDecorate %73 NonUniform\n";
1950             }
1951             s << "       %void = OpTypeVoid\n";
1952             s << "          %3 = OpTypeFunction %void\n";
1953             s << "      %float = OpTypeFloat 32\n";
1954             s << "    %v4float = OpTypeVector %float 4\n";
1955             s << "       %uint = OpTypeInt 32 0\n";
1956             s << "     %uint_1 = OpConstant %uint 1\n";
1957             s << "%_arr_float_uint_1 = OpTypeArray %float %uint_1\n";
1958             s << "%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1\n";
1959             s << "%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n";
1960             s << "          %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n";
1961             s << "        %int = OpTypeInt 32 1\n";
1962             s << "      %int_1 = OpConstant %int 1\n";
1963             s << "%float_0_200000003 = OpConstant %float 0.200000003\n";
1964             s << "%_ptr_Output_float = OpTypePointer Output %float\n";
1965             s << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n";
1966             s << "   %position = OpVariable %_ptr_Output_v4float Output\n";
1967             s << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n";
1968             s << "%in_position = OpVariable %_ptr_Input_v4float Input\n";
1969             s << "    %v2float = OpTypeVector %float 2\n";
1970             s << "%_ptr_Output_v2float = OpTypePointer Output %v2float\n";
1971             s << "  %normalpos = OpVariable %_ptr_Output_v2float Output\n";
1972             s << "%_ptr_Input_v2float = OpTypePointer Input %v2float\n";
1973             s << "%in_normalpos = OpVariable %_ptr_Input_v2float Input\n";
1974             s << "      %int_0 = OpConstant %int 0\n";
1975             s << "%_ptr_Output_int = OpTypePointer Output %int\n";
1976             s << "     %vIndex = OpVariable %_ptr_Output_int Output\n";
1977             s << "%_ptr_Input_int = OpTypePointer Input %int\n";
1978             s << "%gl_VertexIndex = OpVariable %_ptr_Input_int Input\n";
1979             s << "     %rIndex = OpVariable %_ptr_Output_int Output\n";
1980             s << "      %v4int = OpTypeVector %int 4\n";
1981             s << "%_ptr_Input_v4int = OpTypePointer Input %v4int\n";
1982             s << "      %index = OpVariable %_ptr_Input_v4int Input\n";
1983             s << "     %uint_0 = OpConstant %uint 0\n";
1984             s << "     %gIndex = OpVariable %_ptr_Output_int Output\n";
1985             s << "     %bIndex = OpVariable %_ptr_Output_int Output\n";
1986             s << "     %uint_2 = OpConstant %uint 2\n";
1987             s << "     %aIndex = OpVariable %_ptr_Output_int Output\n";
1988             s << "     %uint_3 = OpConstant %uint 3\n";
1989             if (allowVertexStoring)
1990             {
1991                 s << "        %bool = OpTypeBool\n";
1992                 s << "          %61 = OpTypeImage %float Buffer 0 0 0 2 Rgba32f\n";
1993                 s << " %_runtimearr_61 = OpTypeRuntimeArray %61\n";
1994                 s << " %_ptr_UniformConstant__runtimearr_61 = OpTypePointer UniformConstant %_runtimearr_61\n";
1995                 s << "        %data = OpVariable %_ptr_UniformConstant__runtimearr_61 UniformConstant\n";
1996                 s << " %_ptr_UniformConstant_61 = OpTypePointer UniformConstant %61\n";
1997             }
1998             else
1999             {
2000                 s << "         %56 = OpTypeImage %float Buffer 0 0 0 2 Rgba32f\n";
2001                 s << "%_arr_56_uint_1 = OpTypeArray %56 %uint_1\n";
2002                 s << "%_ptr_UniformConstant__arr_56_uint_1 = OpTypePointer UniformConstant %_arr_56_uint_1\n";
2003                 s << "       %data = OpVariable %_ptr_UniformConstant__arr_56_uint_1 UniformConstant\n";
2004             }
2005             s << "       %main = OpFunction %void None %3\n";
2006             s << "          %5 = OpLabel\n";
2007             s << "         %18 = OpAccessChain %_ptr_Output_float %_ %int_1\n";
2008             s << "               OpStore %18 %float_0_200000003\n";
2009             s << "         %23 = OpLoad %v4float %in_position\n";
2010             s << "               OpStore %position %23\n";
2011             s << "         %29 = OpLoad %v2float %in_normalpos\n";
2012             s << "               OpStore %normalpos %29\n";
2013             s << "         %31 = OpLoad %v4float %position\n";
2014             s << "         %32 = OpAccessChain %_ptr_Output_v4float %_ %int_0\n";
2015             s << "               OpStore %32 %31\n";
2016             s << "         %37 = OpLoad %int %gl_VertexIndex\n";
2017             s << "               OpStore %vIndex %37\n";
2018             s << "         %43 = OpAccessChain %_ptr_Input_int %index %uint_0\n";
2019             s << "         %44 = OpLoad %int %43\n";
2020             s << "               OpStore %rIndex %44\n";
2021             s << "         %46 = OpAccessChain %_ptr_Input_int %index %uint_1\n";
2022             s << "         %47 = OpLoad %int %46\n";
2023             s << "               OpStore %gIndex %47\n";
2024             s << "         %50 = OpAccessChain %_ptr_Input_int %index %uint_2\n";
2025             s << "         %51 = OpLoad %int %50\n";
2026             s << "               OpStore %bIndex %51\n";
2027             s << "         %54 = OpAccessChain %_ptr_Input_int %index %uint_3\n";
2028             s << "         %55 = OpLoad %int %54\n";
2029             s << "               OpStore %aIndex %55\n";
2030             if (allowVertexStoring)
2031             {
2032                 s << "          %56 = OpLoad %int %gIndex\n";
2033                 s << "          %58 = OpINotEqual %bool %56 %int_0\n";
2034                 s << "                OpSelectionMerge %60 None\n";
2035                 s << "                OpBranchConditional %58 %59 %60\n";
2036                 s << "          %59 = OpLabel\n";
2037                 s << "          %65 = OpLoad %int %gIndex\n";
2038                 s << "          %66 = OpCopyObject %int %65\n";
2039                 s << "          %68 = OpAccessChain %_ptr_UniformConstant_61 %data %66\n";
2040                 s << "          %69 = OpLoad %61 %68\n";
2041                 s << "          %70 = OpLoad %int %rIndex\n";
2042                 s << "          %71 = OpCopyObject %int %70\n";
2043                 s << "          %72 = OpAccessChain %_ptr_UniformConstant_61 %data %71\n";
2044                 s << "          %73 = OpLoad %61 %72\n";
2045                 s << "          %74 = OpImageRead %v4float %73 %int_0\n";
2046                 s << "                OpImageWrite %69 %int_1 %74\n";
2047                 s << "                OpBranch %60\n";
2048                 s << "          %60 = OpLabel\n";
2049             }
2050             s << "               OpReturn\n";
2051             s << "               OpFunctionEnd\n";
2052             break;
2053         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2054             s << "               OpCapability Shader\n";
2055             if (allowVertexStoring)
2056             {
2057                 s << "               OpCapability ShaderNonUniform\n";
2058                 s << "               OpCapability RuntimeDescriptorArray\n";
2059                 s << "               OpCapability StorageBufferArrayNonUniformIndexing\n";
2060                 s << "               OpExtension \"SPV_EXT_descriptor_indexing\"\n";
2061             }
2062             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
2063             s << "               OpMemoryModel Logical GLSL450\n";
2064             s << "               OpEntryPoint Vertex %main \"main\" %_ %position %in_position %normalpos %in_normalpos "
2065                  "%vIndex %gl_VertexIndex %rIndex %index %gIndex %bIndex %aIndex %data\n";
2066             s << "               OpSource GLSL 450\n";
2067             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
2068             s << "               OpName %main \"main\"\n";
2069             s << "               OpName %gl_PerVertex \"gl_PerVertex\"\n";
2070             s << "               OpMemberName %gl_PerVertex 0 \"gl_Position\"\n";
2071             s << "               OpMemberName %gl_PerVertex 1 \"gl_PointSize\"\n";
2072             s << "               OpMemberName %gl_PerVertex 2 \"gl_ClipDistance\"\n";
2073             s << "               OpMemberName %gl_PerVertex 3 \"gl_CullDistance\"\n";
2074             s << "               OpName %_ \"\"\n";
2075             s << "               OpName %position \"position\"\n";
2076             s << "               OpName %in_position \"in_position\"\n";
2077             s << "               OpName %normalpos \"normalpos\"\n";
2078             s << "               OpName %in_normalpos \"in_normalpos\"\n";
2079             s << "               OpName %vIndex \"vIndex\"\n";
2080             s << "               OpName %gl_VertexIndex \"gl_VertexIndex\"\n";
2081             s << "               OpName %rIndex \"rIndex\"\n";
2082             s << "               OpName %index \"index\"\n";
2083             s << "               OpName %gIndex \"gIndex\"\n";
2084             s << "               OpName %bIndex \"bIndex\"\n";
2085             s << "               OpName %aIndex \"aIndex\"\n";
2086             s << "               OpName %Data \"Data\"\n";
2087             s << "               OpMemberName %Data 0 \"cnew\"\n";
2088             s << "               OpMemberName %Data 1 \"cold\"\n";
2089             s << "               OpName %data \"data\"\n";
2090             s << "               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n";
2091             s << "               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n";
2092             s << "               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n";
2093             s << "               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance\n";
2094             s << "               OpDecorate %gl_PerVertex Block\n";
2095             s << "               OpDecorate %position Location 0\n";
2096             s << "               OpDecorate %in_position Location 0\n";
2097             s << "               OpDecorate %normalpos Location 1\n";
2098             s << "               OpDecorate %in_normalpos Location 1\n";
2099             s << "               OpDecorate %vIndex Location 2\n";
2100             s << "               OpDecorate %gl_VertexIndex BuiltIn VertexIndex\n";
2101             s << "               OpDecorate %rIndex Location 3\n";
2102             s << "               OpDecorate %index Location 2\n";
2103             s << "               OpDecorate %gIndex Location 4\n";
2104             s << "               OpDecorate %bIndex Location 5\n";
2105             s << "               OpDecorate %aIndex Location 6\n";
2106             s << "               OpMemberDecorate %Data 0 Offset 0\n";
2107             s << "               OpMemberDecorate %Data 1 Offset 16\n";
2108             s << "               OpDecorate %Data Block\n";
2109             s << "               OpDecorate %data DescriptorSet 0\n";
2110             s << "               OpDecorate %data Binding " << BINDING_TestObject << "\n";
2111             if (allowVertexStoring)
2112             {
2113                 // s << "               OpDecorate %66 NonUniform\n";
2114                 // s << "               OpDecorate %68 NonUniform\n";
2115                 s << "               OpDecorate %70 NonUniform\n";
2116                 // s << "               OpDecorate %71 NonUniform\n";
2117                 s << "               OpDecorate %72 NonUniform\n";
2118             }
2119             s << "       %void = OpTypeVoid\n";
2120             s << "          %3 = OpTypeFunction %void\n";
2121             s << "      %float = OpTypeFloat 32\n";
2122             s << "    %v4float = OpTypeVector %float 4\n";
2123             s << "       %uint = OpTypeInt 32 0\n";
2124             s << "     %uint_1 = OpConstant %uint 1\n";
2125             s << "%_arr_float_uint_1 = OpTypeArray %float %uint_1\n";
2126             s << "%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1\n";
2127             s << "%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n";
2128             s << "          %_ = OpVariable %_ptr_Output_gl_PerVertex Output\n";
2129             s << "        %int = OpTypeInt 32 1\n";
2130             s << "      %int_1 = OpConstant %int 1\n";
2131             s << "%float_0_200000003 = OpConstant %float 0.200000003\n";
2132             s << "%_ptr_Output_float = OpTypePointer Output %float\n";
2133             s << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n";
2134             s << "   %position = OpVariable %_ptr_Output_v4float Output\n";
2135             s << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n";
2136             s << "%in_position = OpVariable %_ptr_Input_v4float Input\n";
2137             s << "    %v2float = OpTypeVector %float 2\n";
2138             s << "%_ptr_Output_v2float = OpTypePointer Output %v2float\n";
2139             s << "  %normalpos = OpVariable %_ptr_Output_v2float Output\n";
2140             s << "%_ptr_Input_v2float = OpTypePointer Input %v2float\n";
2141             s << "%in_normalpos = OpVariable %_ptr_Input_v2float Input\n";
2142             s << "      %int_0 = OpConstant %int 0\n";
2143             s << "%_ptr_Output_int = OpTypePointer Output %int\n";
2144             s << "     %vIndex = OpVariable %_ptr_Output_int Output\n";
2145             s << "%_ptr_Input_int = OpTypePointer Input %int\n";
2146             s << "%gl_VertexIndex = OpVariable %_ptr_Input_int Input\n";
2147             s << "     %rIndex = OpVariable %_ptr_Output_int Output\n";
2148             s << "      %v4int = OpTypeVector %int 4\n";
2149             s << "%_ptr_Input_v4int = OpTypePointer Input %v4int\n";
2150             s << "      %index = OpVariable %_ptr_Input_v4int Input\n";
2151             s << "     %uint_0 = OpConstant %uint 0\n";
2152             s << "     %gIndex = OpVariable %_ptr_Output_int Output\n";
2153             s << "     %bIndex = OpVariable %_ptr_Output_int Output\n";
2154             s << "     %uint_2 = OpConstant %uint 2\n";
2155             s << "     %aIndex = OpVariable %_ptr_Output_int Output\n";
2156             s << "     %uint_3 = OpConstant %uint 3\n";
2157             s << "       %Data = OpTypeStruct %v4float %v4float\n";
2158             if (allowVertexStoring)
2159             {
2160                 s << "       %bool = OpTypeBool\n";
2161                 s << "%_runtimearr_Data = OpTypeRuntimeArray %Data\n";
2162                 s << "%_ptr_StorageBuffer__runtimearr_Data = OpTypePointer StorageBuffer %_runtimearr_Data\n";
2163                 s << "       %data = OpVariable  %_ptr_StorageBuffer__runtimearr_Data StorageBuffer\n";
2164                 s << "%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float\n";
2165             }
2166             else
2167             {
2168                 s << "%_arr_Data_uint_1 = OpTypeArray %Data %uint_1\n";
2169                 s << "%_ptr_StorageBuffer__arr_Data_uint_1 = OpTypePointer StorageBuffer %_arr_Data_uint_1\n";
2170                 s << "       %data = OpVariable %_ptr_StorageBuffer__arr_Data_uint_1 StorageBuffer\n";
2171             }
2172             s << "       %main = OpFunction %void None %3\n";
2173             s << "          %5 = OpLabel\n";
2174             s << "         %18 = OpAccessChain %_ptr_Output_float %_ %int_1\n";
2175             s << "               OpStore %18 %float_0_200000003\n";
2176             s << "         %23 = OpLoad %v4float %in_position\n";
2177             s << "               OpStore %position %23\n";
2178             s << "         %29 = OpLoad %v2float %in_normalpos\n";
2179             s << "               OpStore %normalpos %29\n";
2180             s << "         %31 = OpLoad %v4float %position\n";
2181             s << "         %32 = OpAccessChain %_ptr_Output_v4float %_ %int_0\n";
2182             s << "               OpStore %32 %31\n";
2183             s << "         %37 = OpLoad %int %gl_VertexIndex\n";
2184             s << "               OpStore %vIndex %37\n";
2185             s << "         %43 = OpAccessChain %_ptr_Input_int %index %uint_0\n";
2186             s << "         %44 = OpLoad %int %43\n";
2187             s << "               OpStore %rIndex %44\n";
2188             s << "         %46 = OpAccessChain %_ptr_Input_int %index %uint_1\n";
2189             s << "         %47 = OpLoad %int %46\n";
2190             s << "               OpStore %gIndex %47\n";
2191             s << "         %50 = OpAccessChain %_ptr_Input_int %index %uint_2\n";
2192             s << "         %51 = OpLoad %int %50\n";
2193             s << "               OpStore %bIndex %51\n";
2194             s << "         %54 = OpAccessChain %_ptr_Input_int %index %uint_3\n";
2195             s << "         %55 = OpLoad %int %54\n";
2196             s << "               OpStore %aIndex %55\n";
2197             if (allowVertexStoring)
2198             {
2199                 s << "          %56 = OpLoad %int %gIndex\n";
2200                 s << "          %58 = OpINotEqual %bool %56 %int_0\n";
2201                 s << "                OpSelectionMerge %60 None\n";
2202                 s << "                OpBranchConditional %58 %59 %60\n";
2203                 s << "          %59 = OpLabel\n";
2204                 s << "          %65 = OpLoad %int %gIndex\n";
2205                 s << "          %66 = OpCopyObject %int %65\n";
2206                 s << "          %67 = OpLoad %int %rIndex\n";
2207                 s << "          %68 = OpCopyObject %int %67\n";
2208                 s << "          %70 = OpAccessChain %_ptr_StorageBuffer_v4float %data %68 %int_1\n";
2209                 s << "          %71 = OpLoad %v4float %70\n";
2210                 s << "          %72 = OpAccessChain %_ptr_StorageBuffer_v4float %data %66 %int_0\n";
2211                 s << "                OpStore %72 %71\n";
2212                 s << "                OpBranch %60\n";
2213                 s << "          %60 = OpLabel\n";
2214             }
2215             s << "               OpReturn\n";
2216             s << "               OpFunctionEnd\n";
2217             break;
2218         default:
2219             TCU_THROW(InternalError, "Unexpected descriptor type");
2220         }
2221         break;
2222     case VK_SHADER_STAGE_FRAGMENT_BIT:
2223         switch (testCaseParams.descriptorType)
2224         {
2225         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2226             s << "               OpCapability Shader\n";
2227             if (testCaseParams.usesMipMaps)
2228             {
2229                 s << "               OpCapability ImageQuery\n";
2230             }
2231             s << "               OpCapability ShaderNonUniform\n";
2232             s << "               OpCapability RuntimeDescriptorArray\n";
2233             s << "               OpCapability SampledImageArrayNonUniformIndexing\n";
2234             s << "               OpExtension \"SPV_EXT_descriptor_indexing\"\n";
2235             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
2236             s << "               OpMemoryModel Logical GLSL450\n";
2237             s << "               OpEntryPoint Fragment %main \"main\" %FragColor %data %rIndex %position %normalpos "
2238                  "%vIndex %gIndex %bIndex %aIndex\n";
2239             s << "               OpExecutionMode %main OriginUpperLeft\n";
2240             s << "               OpSource GLSL 450\n";
2241             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
2242             s << "               OpSourceExtension \"GL_EXT_texture_buffer\"\n";
2243             s << "               OpName %main \"main\"\n";
2244             s << "               OpName %FragColor \"FragColor\"\n";
2245             s << "               OpName %data \"data\"\n";
2246             s << "               OpName %rIndex \"rIndex\"\n";
2247             s << "               OpName %position \"position\"\n";
2248             s << "               OpName %normalpos \"normalpos\"\n";
2249             s << "               OpName %vIndex \"vIndex\"\n";
2250             s << "               OpName %gIndex \"gIndex\"\n";
2251             s << "               OpName %bIndex \"bIndex\"\n";
2252             s << "               OpName %aIndex \"aIndex\"\n";
2253             s << "               OpDecorate %FragColor Location 0\n";
2254             s << "               OpDecorate %data DescriptorSet 0\n";
2255             s << "               OpDecorate %data Binding " << BINDING_TestObject << "\n";
2256             s << "               OpDecorate %rIndex Flat\n";
2257             s << "               OpDecorate %rIndex Location 3\n";
2258             // s << "               OpDecorate %19 NonUniform\n";
2259             // s << "               OpDecorate %21 NonUniform\n";
2260             s << "               OpDecorate %22 NonUniform\n";
2261             if (testCaseParams.usesMipMaps)
2262             {
2263                 // s << "               OpDecorate %27 NonUniform\n";
2264                 // s << "               OpDecorate %28 NonUniform\n";
2265                 // s << "               OpDecorate %29 NonUniform\n";
2266                 s << "               OpDecorate %30 NonUniform\n";
2267             }
2268             s << "               OpDecorate %position Flat\n";
2269             s << "               OpDecorate %position Location 0\n";
2270             s << "               OpDecorate %normalpos Flat\n";
2271             s << "               OpDecorate %normalpos Location 1\n";
2272             s << "               OpDecorate %vIndex Flat\n";
2273             s << "               OpDecorate %vIndex Location 2\n";
2274             s << "               OpDecorate %gIndex Flat\n";
2275             s << "               OpDecorate %gIndex Location 4\n";
2276             s << "               OpDecorate %bIndex Flat\n";
2277             s << "               OpDecorate %bIndex Location 5\n";
2278             s << "               OpDecorate %aIndex Flat\n";
2279             s << "               OpDecorate %aIndex Location 6\n";
2280             s << "       %void = OpTypeVoid\n";
2281             s << "          %3 = OpTypeFunction %void\n";
2282             s << "      %float = OpTypeFloat 32\n";
2283             s << "    %v4float = OpTypeVector %float 4\n";
2284             s << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n";
2285             s << "  %FragColor = OpVariable %_ptr_Output_v4float Output\n";
2286             s << "         %10 = OpTypeImage %float 2D 0 0 0 1 Unknown\n";
2287             s << "         %11 = OpTypeSampledImage %10\n";
2288             s << "%_runtimearr_11 = OpTypeRuntimeArray %11\n";
2289             s << "%_ptr_UniformConstant__runtimearr_11 = OpTypePointer UniformConstant %_runtimearr_11\n";
2290             s << "       %data = OpVariable %_ptr_UniformConstant__runtimearr_11 UniformConstant\n";
2291             s << "        %int = OpTypeInt 32 1\n";
2292             s << "%_ptr_Input_int = OpTypePointer Input %int\n";
2293             s << "     %rIndex = OpVariable %_ptr_Input_int Input\n";
2294             s << "%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11\n";
2295             s << "    %v2float = OpTypeVector %float 2\n";
2296             s << "    %float_0 = OpConstant %float 0\n";
2297             s << "      %int_1 = OpConstant %int 1\n";
2298             s << "         %25 = OpConstantComposite %v2float %float_0 %float_0\n";
2299             s << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n";
2300             s << "   %position = OpVariable %_ptr_Input_v4float Input\n";
2301             s << "%_ptr_Input_v2float = OpTypePointer Input %v2float\n";
2302             s << "  %normalpos = OpVariable %_ptr_Input_v2float Input\n";
2303             s << "     %vIndex = OpVariable %_ptr_Input_int Input\n";
2304             s << "     %gIndex = OpVariable %_ptr_Input_int Input\n";
2305             s << "     %bIndex = OpVariable %_ptr_Input_int Input\n";
2306             s << "     %aIndex = OpVariable %_ptr_Input_int Input\n";
2307             s << "       %main = OpFunction %void None %3\n";
2308             s << "          %5 = OpLabel\n";
2309             s << "         %18 = OpLoad %int %rIndex\n";
2310             s << "         %19 = OpCopyObject %int %18\n";
2311             s << "         %21 = OpAccessChain %_ptr_UniformConstant_11 %data %19\n";
2312             s << "         %22 = OpLoad %11 %21\n";
2313             if (testCaseParams.usesMipMaps)
2314             {
2315                 s << "          %26 = OpLoad %int %rIndex\n";
2316                 s << "          %27 = OpCopyObject %int %26\n";
2317                 s << "          %28 = OpAccessChain %_ptr_UniformConstant_11 %data %27\n";
2318                 s << "          %29 = OpLoad %11 %28\n";
2319                 s << "          %30 = OpImage %10 %29\n";
2320                 s << "          %31 = OpImageQueryLevels %int %30\n";
2321                 s << "          %33 = OpISub %int %31 %int_1\n";
2322                 s << "          %34 = OpConvertSToF %float %33\n";
2323                 s << "          %35 = OpImageSampleExplicitLod %v4float %22 %25 Lod %34\n";
2324                 s << "                OpStore %FragColor %35\n";
2325             }
2326             else
2327             {
2328                 s << "         %26 = OpImageSampleImplicitLod %v4float %22 %25\n";
2329                 s << "               OpStore %FragColor %26\n";
2330             }
2331             s << "               OpReturn\n";
2332             s << "               OpFunctionEnd\n";
2333             break;
2334         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2335             s << "               OpCapability Shader\n";
2336             s << "               OpCapability SampledBuffer\n";
2337             s << "               OpCapability ShaderNonUniform\n";
2338             s << "               OpCapability RuntimeDescriptorArray\n";
2339             s << "               OpCapability UniformTexelBufferArrayNonUniformIndexing\n";
2340             s << "               OpExtension \"SPV_EXT_descriptor_indexing\"\n";
2341             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
2342             s << "               OpMemoryModel Logical GLSL450\n";
2343             s << "               OpEntryPoint Fragment %main \"main\" %FragColor %data %rIndex %position %normalpos "
2344                  "%vIndex %gIndex %bIndex %aIndex\n";
2345             s << "               OpExecutionMode %main OriginUpperLeft\n";
2346             s << "               OpSource GLSL 450\n";
2347             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
2348             s << "               OpSourceExtension \"GL_EXT_texture_buffer\"\n";
2349             s << "               OpName %main \"main\"\n";
2350             s << "               OpName %FragColor \"FragColor\"\n";
2351             s << "               OpName %data \"data\"\n";
2352             s << "               OpName %rIndex \"rIndex\"\n";
2353             s << "               OpName %position \"position\"\n";
2354             s << "               OpName %normalpos \"normalpos\"\n";
2355             s << "               OpName %vIndex \"vIndex\"\n";
2356             s << "               OpName %gIndex \"gIndex\"\n";
2357             s << "               OpName %bIndex \"bIndex\"\n";
2358             s << "               OpName %aIndex \"aIndex\"\n";
2359             s << "               OpDecorate %FragColor Location 0\n";
2360             s << "               OpDecorate %data DescriptorSet 0\n";
2361             s << "               OpDecorate %data Binding " << BINDING_TestObject << "\n";
2362             s << "               OpDecorate %rIndex Flat\n";
2363             s << "               OpDecorate %rIndex Location 3\n";
2364             // s << "               OpDecorate %19 NonUniform\n";
2365             // s << "               OpDecorate %21 NonUniform\n";
2366             // s << "               OpDecorate %22 NonUniform\n";
2367             s << "               OpDecorate %24 NonUniform\n";
2368             s << "               OpDecorate %position Flat\n";
2369             s << "               OpDecorate %position Location 0\n";
2370             s << "               OpDecorate %normalpos Flat\n";
2371             s << "               OpDecorate %normalpos Location 1\n";
2372             s << "               OpDecorate %vIndex Flat\n";
2373             s << "               OpDecorate %vIndex Location 2\n";
2374             s << "               OpDecorate %gIndex Flat\n";
2375             s << "               OpDecorate %gIndex Location 4\n";
2376             s << "               OpDecorate %bIndex Flat\n";
2377             s << "               OpDecorate %bIndex Location 5\n";
2378             s << "               OpDecorate %aIndex Flat\n";
2379             s << "               OpDecorate %aIndex Location 6\n";
2380             s << "       %void = OpTypeVoid\n";
2381             s << "          %3 = OpTypeFunction %void\n";
2382             s << "      %float = OpTypeFloat 32\n";
2383             s << "    %v4float = OpTypeVector %float 4\n";
2384             s << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n";
2385             s << "  %FragColor = OpVariable %_ptr_Output_v4float Output\n";
2386             s << "         %10 = OpTypeImage %float Buffer 0 0 0 1 Unknown\n";
2387             s << "         %11 = OpTypeSampledImage %10\n";
2388             s << "%_runtimearr_11 = OpTypeRuntimeArray %11\n";
2389             s << "%_ptr_UniformConstant__runtimearr_11 = OpTypePointer UniformConstant %_runtimearr_11\n";
2390             s << "       %data = OpVariable %_ptr_UniformConstant__runtimearr_11 UniformConstant\n";
2391             s << "        %int = OpTypeInt 32 1\n";
2392             s << "%_ptr_Input_int = OpTypePointer Input %int\n";
2393             s << "     %rIndex = OpVariable %_ptr_Input_int Input\n";
2394             s << "%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11\n";
2395             s << "      %int_0 = OpConstant %int 0\n";
2396             s << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n";
2397             s << "   %position = OpVariable %_ptr_Input_v4float Input\n";
2398             s << "    %v2float = OpTypeVector %float 2\n";
2399             s << "%_ptr_Input_v2float = OpTypePointer Input %v2float\n";
2400             s << "  %normalpos = OpVariable %_ptr_Input_v2float Input\n";
2401             s << "     %vIndex = OpVariable %_ptr_Input_int Input\n";
2402             s << "     %gIndex = OpVariable %_ptr_Input_int Input\n";
2403             s << "     %bIndex = OpVariable %_ptr_Input_int Input\n";
2404             s << "     %aIndex = OpVariable %_ptr_Input_int Input\n";
2405             s << "       %main = OpFunction %void None %3\n";
2406             s << "          %5 = OpLabel\n";
2407             s << "         %18 = OpLoad %int %rIndex\n";
2408             s << "         %19 = OpCopyObject %int %18\n";
2409             s << "         %21 = OpAccessChain %_ptr_UniformConstant_11 %data %19\n";
2410             s << "         %22 = OpLoad %11 %21\n";
2411             s << "         %24 = OpImage %10 %22\n";
2412             s << "         %25 = OpImageFetch %v4float %24 %int_0\n";
2413             s << "               OpStore %FragColor %25\n";
2414             s << "               OpReturn\n";
2415             s << "               OpFunctionEnd\n";
2416             break;
2417         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2418             s << "               OpCapability Shader\n";
2419             s << "               OpCapability ImageBuffer\n";
2420             s << "               OpCapability ShaderNonUniform\n";
2421             s << "               OpCapability RuntimeDescriptorArray\n";
2422             s << "               OpCapability StorageTexelBufferArrayNonUniformIndexing\n";
2423             s << "               OpExtension \"SPV_EXT_descriptor_indexing\"\n";
2424             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
2425             s << "               OpMemoryModel Logical GLSL450\n";
2426             s << "               OpEntryPoint Fragment %main \"main\" %FragColor %data %rIndex %position %normalpos "
2427                  "%vIndex %gIndex %bIndex %aIndex\n";
2428             s << "               OpExecutionMode %main OriginUpperLeft\n";
2429             s << "               OpSource GLSL 450\n";
2430             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
2431             s << "               OpName %main \"main\"\n";
2432             s << "               OpName %FragColor \"FragColor\"\n";
2433             s << "               OpName %data \"data\"\n";
2434             s << "               OpName %rIndex \"rIndex\"\n";
2435             s << "               OpName %position \"position\"\n";
2436             s << "               OpName %normalpos \"normalpos\"\n";
2437             s << "               OpName %vIndex \"vIndex\"\n";
2438             s << "               OpName %gIndex \"gIndex\"\n";
2439             s << "               OpName %bIndex \"bIndex\"\n";
2440             s << "               OpName %aIndex \"aIndex\"\n";
2441             s << "               OpDecorate %FragColor Location 0\n";
2442             s << "               OpDecorate %data DescriptorSet 0\n";
2443             s << "               OpDecorate %data Binding " << BINDING_TestObject << "\n";
2444             s << "               OpDecorate %rIndex Flat\n";
2445             s << "               OpDecorate %rIndex Location 3\n";
2446             // s << "               OpDecorate %18 NonUniform\n";
2447             // s << "               OpDecorate %20 NonUniform\n";
2448             s << "               OpDecorate %21 NonUniform\n";
2449             s << "               OpDecorate %position Flat\n";
2450             s << "               OpDecorate %position Location 0\n";
2451             s << "               OpDecorate %normalpos Flat\n";
2452             s << "               OpDecorate %normalpos Location 1\n";
2453             s << "               OpDecorate %vIndex Flat\n";
2454             s << "               OpDecorate %vIndex Location 2\n";
2455             s << "               OpDecorate %gIndex Flat\n";
2456             s << "               OpDecorate %gIndex Location 4\n";
2457             s << "               OpDecorate %bIndex Flat\n";
2458             s << "               OpDecorate %bIndex Location 5\n";
2459             s << "               OpDecorate %aIndex Flat\n";
2460             s << "               OpDecorate %aIndex Location 6\n";
2461             s << "       %void = OpTypeVoid\n";
2462             s << "          %3 = OpTypeFunction %void\n";
2463             s << "      %float = OpTypeFloat 32\n";
2464             s << "    %v4float = OpTypeVector %float 4\n";
2465             s << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n";
2466             s << "  %FragColor = OpVariable %_ptr_Output_v4float Output\n";
2467             s << "         %10 = OpTypeImage %float Buffer 0 0 0 2 Rgba32f\n";
2468             s << "%_runtimearr_10 = OpTypeRuntimeArray %10\n";
2469             s << "%_ptr_UniformConstant__runtimearr_10 = OpTypePointer UniformConstant %_runtimearr_10\n";
2470             s << "       %data = OpVariable %_ptr_UniformConstant__runtimearr_10 UniformConstant\n";
2471             s << "        %int = OpTypeInt 32 1\n";
2472             s << "%_ptr_Input_int = OpTypePointer Input %int\n";
2473             s << "     %rIndex = OpVariable %_ptr_Input_int Input\n";
2474             s << "%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10\n";
2475             s << "      %int_0 = OpConstant %int 0\n";
2476             s << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n";
2477             s << "   %position = OpVariable %_ptr_Input_v4float Input\n";
2478             s << "    %v2float = OpTypeVector %float 2\n";
2479             s << "%_ptr_Input_v2float = OpTypePointer Input %v2float\n";
2480             s << "  %normalpos = OpVariable %_ptr_Input_v2float Input\n";
2481             s << "     %vIndex = OpVariable %_ptr_Input_int Input\n";
2482             s << "     %gIndex = OpVariable %_ptr_Input_int Input\n";
2483             s << "     %bIndex = OpVariable %_ptr_Input_int Input\n";
2484             s << "     %aIndex = OpVariable %_ptr_Input_int Input\n";
2485             s << "       %main = OpFunction %void None %3\n";
2486             s << "          %5 = OpLabel\n";
2487             s << "         %17 = OpLoad %int %rIndex\n";
2488             s << "         %18 = OpCopyObject %int %17\n";
2489             s << "         %20 = OpAccessChain %_ptr_UniformConstant_10 %data %18\n";
2490             s << "         %21 = OpLoad %10 %20\n";
2491             s << "         %23 = OpImageRead %v4float %21 %int_0\n";
2492             s << "               OpStore %FragColor %23\n";
2493             s << "               OpReturn\n";
2494             s << "               OpFunctionEnd\n";
2495             break;
2496         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2497             s << "               OpCapability Shader\n";
2498             s << "               OpCapability ShaderNonUniform\n";
2499             s << "               OpCapability RuntimeDescriptorArray\n";
2500             s << "               OpCapability StorageBufferArrayNonUniformIndexing\n";
2501             s << "               OpExtension \"SPV_EXT_descriptor_indexing\"\n";
2502             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
2503             s << "               OpMemoryModel Logical GLSL450\n";
2504             s << "               OpEntryPoint Fragment %main \"main\" %FragColor %data %rIndex %position %normalpos "
2505                  "%vIndex %gIndex %bIndex %aIndex\n";
2506             s << "               OpExecutionMode %main OriginUpperLeft\n";
2507             s << "               OpSource GLSL 450\n";
2508             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
2509             s << "               OpName %main \"main\"\n";
2510             s << "               OpName %FragColor \"FragColor\"\n";
2511             s << "               OpName %Data \"Data\"\n";
2512             s << "               OpMemberName %Data 0 \"cnew\"\n";
2513             s << "               OpMemberName %Data 1 \"cold\"\n";
2514             s << "               OpName %data \"data\"\n";
2515             s << "               OpName %rIndex \"rIndex\"\n";
2516             s << "               OpName %position \"position\"\n";
2517             s << "               OpName %normalpos \"normalpos\"\n";
2518             s << "               OpName %vIndex \"vIndex\"\n";
2519             s << "               OpName %gIndex \"gIndex\"\n";
2520             s << "               OpName %bIndex \"bIndex\"\n";
2521             s << "               OpName %aIndex \"aIndex\"\n";
2522             s << "               OpDecorate %FragColor Location 0\n";
2523             s << "               OpMemberDecorate %Data 0 Offset 0\n";
2524             s << "               OpMemberDecorate %Data 1 Offset 16\n";
2525             s << "               OpDecorate %Data Block\n";
2526             s << "               OpDecorate %data DescriptorSet 0\n";
2527             s << "               OpDecorate %data Binding " << BINDING_TestObject << "\n";
2528             s << "               OpDecorate %rIndex Flat\n";
2529             s << "               OpDecorate %rIndex Location 3\n";
2530             // s << "               OpDecorate %18 NonUniform\n";
2531             s << "               OpDecorate %21 NonUniform\n";
2532             // s << "               OpDecorate %22 NonUniform\n";
2533             s << "               OpDecorate %position Flat\n";
2534             s << "               OpDecorate %position Location 0\n";
2535             s << "               OpDecorate %normalpos Flat               OpDecorate %normalpos Location 1\n";
2536             s << "               OpDecorate %vIndex Flat\n";
2537             s << "               OpDecorate %vIndex Location 2\n";
2538             s << "               OpDecorate %gIndex Flat\n";
2539             s << "               OpDecorate %gIndex Location 4\n";
2540             s << "               OpDecorate %bIndex Flat\n";
2541             s << "               OpDecorate %bIndex Location 5\n";
2542             s << "               OpDecorate %aIndex Flat\n";
2543             s << "               OpDecorate %aIndex Location 6\n";
2544             s << "       %void = OpTypeVoid\n";
2545             s << "          %3 = OpTypeFunction %void\n";
2546             s << "      %float = OpTypeFloat 32\n";
2547             s << "    %v4float = OpTypeVector %float 4\n";
2548             s << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n";
2549             s << "  %FragColor = OpVariable %_ptr_Output_v4float Output\n";
2550             s << "       %Data = OpTypeStruct %v4float %v4float\n";
2551             s << "%_runtimearr_Data = OpTypeRuntimeArray %Data\n";
2552             s << "%_ptr_StorageBuffer__runtimearr_Data = OpTypePointer StorageBuffer %_runtimearr_Data\n";
2553             s << "       %data = OpVariable %_ptr_StorageBuffer__runtimearr_Data StorageBuffer\n";
2554             s << "        %int = OpTypeInt 32 1\n";
2555             s << "%_ptr_Input_int = OpTypePointer Input %int\n";
2556             s << "     %rIndex = OpVariable %_ptr_Input_int Input\n";
2557             s << "      %int_1 = OpConstant %int 1\n";
2558             s << "%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float\n";
2559             s << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n";
2560             s << "   %position = OpVariable %_ptr_Input_v4float Input\n";
2561             s << "    %v2float = OpTypeVector %float 2\n";
2562             s << "%_ptr_Input_v2float = OpTypePointer Input %v2float\n";
2563             s << "  %normalpos = OpVariable %_ptr_Input_v2float Input\n";
2564             s << "     %vIndex = OpVariable %_ptr_Input_int Input\n";
2565             s << "     %gIndex = OpVariable %_ptr_Input_int Input\n";
2566             s << "     %bIndex = OpVariable %_ptr_Input_int Input\n";
2567             s << "     %aIndex = OpVariable %_ptr_Input_int Input\n";
2568             s << "       %main = OpFunction %void None %3\n";
2569             s << "          %5 = OpLabel\n";
2570             s << "         %17 = OpLoad %int %rIndex\n";
2571             s << "         %18 = OpCopyObject %int %17\n";
2572             s << "         %21 = OpAccessChain %_ptr_StorageBuffer_v4float %data %18 %int_1\n";
2573             s << "         %22 = OpLoad %v4float %21\n";
2574             s << "               OpStore %FragColor %22\n";
2575             s << "               OpReturn\n";
2576             s << "               OpFunctionEnd\n";
2577             break;
2578         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2579             s << "               OpCapability Shader\n";
2580             s << "               OpCapability ShaderNonUniform\n";
2581             s << "               OpCapability RuntimeDescriptorArray\n";
2582             s << "               OpCapability UniformBufferArrayNonUniformIndexing\n";
2583             s << "               OpExtension \"SPV_EXT_descriptor_indexing\"\n";
2584             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
2585             s << "               OpMemoryModel Logical GLSL450\n";
2586             s << "               OpEntryPoint Fragment %main \"main\" %FragColor %data %rIndex %position %normalpos "
2587                  "%vIndex %gIndex %bIndex %aIndex\n";
2588             s << "               OpExecutionMode %main OriginUpperLeft\n";
2589             s << "               OpSource GLSL 450\n";
2590             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
2591             s << "               OpName %main \"main\"\n";
2592             s << "               OpName %FragColor \"FragColor\"\n";
2593             s << "               OpName %Data \"Data\"\n";
2594             s << "               OpMemberName %Data 0 \"c\"\n";
2595             s << "               OpName %data \"data\"\n";
2596             s << "               OpName %rIndex \"rIndex\"\n";
2597             s << "               OpName %position \"position\"\n";
2598             s << "               OpName %normalpos \"normalpos\"\n";
2599             s << "               OpName %vIndex \"vIndex\"\n";
2600             s << "               OpName %gIndex \"gIndex\"\n";
2601             s << "               OpName %bIndex \"bIndex\"\n";
2602             s << "               OpName %aIndex \"aIndex\"\n";
2603             s << "               OpDecorate %FragColor Location 0\n";
2604             s << "               OpMemberDecorate %Data 0 Offset 0\n";
2605             s << "               OpDecorate %Data Block\n";
2606             s << "               OpDecorate %data DescriptorSet 0\n";
2607             s << "               OpDecorate %data Binding " << BINDING_TestObject << "\n";
2608             s << "               OpDecorate %rIndex Flat\n";
2609             s << "               OpDecorate %rIndex Location 3\n";
2610             // s << "               OpDecorate %18 NonUniform\n";
2611             s << "               OpDecorate %21 NonUniform\n";
2612             // s << "               OpDecorate %22 NonUniform\n";
2613             s << "               OpDecorate %position Flat\n";
2614             s << "               OpDecorate %position Location 0\n";
2615             s << "               OpDecorate %normalpos Flat\n";
2616             s << "               OpDecorate %normalpos Location 1\n";
2617             s << "               OpDecorate %vIndex Flat\n";
2618             s << "               OpDecorate %vIndex Location 2\n";
2619             s << "               OpDecorate %gIndex Flat\n";
2620             s << "               OpDecorate %gIndex Location 4\n";
2621             s << "               OpDecorate %bIndex Flat\n";
2622             s << "               OpDecorate %bIndex Location 5\n";
2623             s << "               OpDecorate %aIndex Flat\n";
2624             s << "               OpDecorate %aIndex Location 6\n";
2625             s << "       %void = OpTypeVoid\n";
2626             s << "          %3 = OpTypeFunction %void\n";
2627             s << "      %float = OpTypeFloat 32\n";
2628             s << "    %v4float = OpTypeVector %float 4\n";
2629             s << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n";
2630             s << "  %FragColor = OpVariable %_ptr_Output_v4float Output\n";
2631             s << "       %Data = OpTypeStruct %v4float\n";
2632             s << "%_runtimearr_Data = OpTypeRuntimeArray %Data\n";
2633             s << "%_ptr_Uniform__runtimearr_Data = OpTypePointer Uniform %_runtimearr_Data\n";
2634             s << "       %data = OpVariable %_ptr_Uniform__runtimearr_Data Uniform\n";
2635             s << "        %int = OpTypeInt 32 1\n";
2636             s << "%_ptr_Input_int = OpTypePointer Input %int\n";
2637             s << "     %rIndex = OpVariable %_ptr_Input_int Input\n";
2638             s << "      %int_0 = OpConstant %int 0\n";
2639             s << "%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float\n";
2640             s << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n";
2641             s << "   %position = OpVariable %_ptr_Input_v4float Input\n";
2642             s << "    %v2float = OpTypeVector %float 2\n";
2643             s << "%_ptr_Input_v2float = OpTypePointer Input %v2float\n";
2644             s << "  %normalpos = OpVariable %_ptr_Input_v2float Input\n";
2645             s << "     %vIndex = OpVariable %_ptr_Input_int Input\n";
2646             s << "     %gIndex = OpVariable %_ptr_Input_int Input\n";
2647             s << "     %bIndex = OpVariable %_ptr_Input_int Input\n";
2648             s << "     %aIndex = OpVariable %_ptr_Input_int Input\n";
2649             s << "       %main = OpFunction %void None %3\n";
2650             s << "          %5 = OpLabel\n";
2651             s << "         %17 = OpLoad %int %rIndex\n";
2652             s << "         %18 = OpCopyObject %int %17\n";
2653             s << "         %21 = OpAccessChain %_ptr_Uniform_v4float %data %18 %int_0\n";
2654             s << "         %22 = OpLoad %v4float %21\n";
2655             s << "               OpStore %FragColor %22\n";
2656             s << "               OpReturn\n";
2657             s << "               OpFunctionEnd\n";
2658             break;
2659         default:
2660             TCU_THROW(InternalError, "Unexpected descriptor type");
2661         }
2662         break;
2663     case VK_SHADER_STAGE_COMPUTE_BIT:
2664         switch (testCaseParams.descriptorType)
2665         {
2666         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2667             s << "               OpCapability Shader\n";
2668             s << "               OpCapability ShaderNonUniform\n";
2669             s << "               OpCapability RuntimeDescriptorArray\n";
2670             s << "               OpCapability StorageImageArrayNonUniformIndexing\n";
2671             s << "               OpExtension \"SPV_EXT_descriptor_indexing\"\n";
2672             s << "          %1 = OpExtInstImport \"GLSL.std.450\"\n";
2673             s << "               OpMemoryModel Logical GLSL450\n";
2674             s << "               OpEntryPoint GLCompute %main \"main\" %idxs %gl_WorkGroupID %data\n";
2675             s << "               OpExecutionMode %main LocalSize 1 1 1\n";
2676             s << "               OpSource GLSL 450\n";
2677             s << "               OpSourceExtension \"GL_EXT_nonuniform_qualifier\"\n";
2678             s << "               OpName %main \"main\"\n";
2679             s << "               OpName %c \"c\"\n";
2680             s << "               OpName %idxs \"idxs\"\n";
2681             s << "               OpName %gl_WorkGroupID \"gl_WorkGroupID\"\n";
2682             s << "               OpName %data \"data\"\n";
2683             s << "               OpDecorate %idxs DescriptorSet 0\n";
2684             s << "               OpDecorate %idxs Binding " << BINDING_Additional << "\n";
2685             s << "               OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId\n";
2686             s << "               OpDecorate %data DescriptorSet 0\n";
2687             s << "               OpDecorate %data Binding " << BINDING_TestObject << "\n";
2688             // s << "               OpDecorate %36 NonUniform\n";
2689             // s << "               OpDecorate %37 NonUniform\n";
2690             s << "               OpDecorate %41 NonUniform\n";
2691             s << "               OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize\n";
2692             s << "       %void = OpTypeVoid\n";
2693             s << "          %3 = OpTypeFunction %void\n";
2694             s << "       %uint = OpTypeInt 32 0\n";
2695             s << "     %v4uint = OpTypeVector %uint 4\n";
2696             s << "%_ptr_Function_v4uint = OpTypePointer Function %v4uint\n";
2697             s << "         %10 = OpTypeImage %uint 2D 0 0 0 2 R32ui\n";
2698             s << "%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10\n";
2699             s << "       %idxs = OpVariable %_ptr_UniformConstant_10 UniformConstant\n";
2700             s << "     %v3uint = OpTypeVector %uint 3\n";
2701             s << "%_ptr_Input_v3uint = OpTypePointer Input %v3uint\n";
2702             s << "%gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input\n";
2703             s << "     %uint_0 = OpConstant %uint 0\n";
2704             s << "%_ptr_Input_uint = OpTypePointer Input %uint\n";
2705             s << "        %int = OpTypeInt 32 1\n";
2706             s << "     %uint_1 = OpConstant %uint 1\n";
2707             s << "      %v2int = OpTypeVector %int 2\n";
2708             s << "%_runtimearr_10 = OpTypeRuntimeArray %10\n";
2709             s << "%_ptr_UniformConstant__runtimearr_10 = OpTypePointer UniformConstant %_runtimearr_10\n";
2710             s << "       %data = OpVariable %_ptr_UniformConstant__runtimearr_10 UniformConstant\n";
2711             s << "%_ptr_Function_uint = OpTypePointer Function %uint\n";
2712             s << "      %int_0 = OpConstant %int 0\n";
2713             s << "         %39 = OpConstantComposite %v2int %int_0 %int_0\n";
2714             s << "%_ptr_Image_uint = OpTypePointer Image %uint\n";
2715             s << "%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1\n";
2716             s << "       %main = OpFunction %void None %3\n";
2717             s << "          %5 = OpLabel\n";
2718             s << "          %c = OpVariable %_ptr_Function_v4uint Function\n";
2719             s << "         %13 = OpLoad %10 %idxs\n";
2720             s << "         %19 = OpAccessChain %_ptr_Input_uint %gl_WorkGroupID %uint_0\n";
2721             s << "         %20 = OpLoad %uint %19\n";
2722             s << "         %22 = OpBitcast %int %20\n";
2723             s << "         %24 = OpAccessChain %_ptr_Input_uint %gl_WorkGroupID %uint_1\n";
2724             s << "         %25 = OpLoad %uint %24\n";
2725             s << "         %26 = OpBitcast %int %25\n";
2726             s << "         %28 = OpCompositeConstruct %v2int %22 %26\n";
2727             s << "         %29 = OpImageRead %v4uint %13 %28 ZeroExtend\n";
2728             s << "               OpStore %c %29\n";
2729             s << "         %34 = OpAccessChain %_ptr_Function_uint %c %uint_0\n";
2730             s << "         %35 = OpLoad %uint %34\n";
2731             s << "         %36 = OpCopyObject %uint %35\n";
2732             s << "         %37 = OpAccessChain %_ptr_UniformConstant_10 %data %36\n";
2733             s << "         %41 = OpImageTexelPointer %_ptr_Image_uint %37 %39 %uint_0\n";
2734             s << "         %42 = OpAtomicIAdd %uint %41 %uint_1 %uint_0 %uint_1\n";
2735             s << "               OpReturn\n";
2736             s << "               OpFunctionEnd\n";
2737             break;
2738         default:
2739             TCU_THROW(InternalError, "Unexpected descriptor type");
2740         }
2741         break;
2742     default:
2743         TCU_THROW(InternalError, "Unexpected stage");
2744     }
2745 
2746     return s.str();
2747 }
2748 
getShaderSource(VkShaderStageFlagBits shaderType,const TestCaseParams & testCaseParams,bool allowVertexStoring)2749 std::string CommonDescriptorInstance::getShaderSource(VkShaderStageFlagBits shaderType,
2750                                                       const TestCaseParams &testCaseParams, bool allowVertexStoring)
2751 {
2752     std::stringstream s;
2753 
2754     s << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << '\n';
2755     s << "#extension GL_EXT_nonuniform_qualifier : require    \n";
2756 
2757     if (testCaseParams.calculateInLoop)
2758     {
2759         s << "layout(push_constant)     uniform Block { int lowerBound, upperBound; } pc;\n";
2760         s << substBinding(BINDING_DescriptorEnumerator,
2761                           "layout(set=1,binding=${?}) uniform isamplerBuffer iter;    \n");
2762     }
2763 
2764     std::string declType;
2765     switch (testCaseParams.descriptorType)
2766     {
2767     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2768     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2769         declType = "buffer Data { vec4 cnew, cold; }";
2770         break;
2771     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2772     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2773         declType = "uniform Data { vec4 c; }";
2774         break;
2775     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2776         declType = "uniform imageBuffer";
2777         break;
2778     case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2779         declType = "uniform samplerBuffer";
2780         break;
2781     case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2782         declType = "uniform subpassInput";
2783         break;
2784     case VK_DESCRIPTOR_TYPE_SAMPLER:
2785         declType = "uniform sampler";
2786         break;
2787     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2788         declType = "uniform texture2D";
2789         break;
2790     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2791         declType = "uniform sampler2D";
2792         break;
2793     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2794         declType = "uniform uimage2D";
2795         break;
2796     default:
2797         TCU_THROW(InternalError, "Not implemented descriptor type");
2798     }
2799 
2800     std::string extraLayout = "";
2801     switch (testCaseParams.descriptorType)
2802     {
2803     // Note trailing commas to fit in with layout declaration, below.
2804     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2805         extraLayout = "rgba32f,";
2806         break;
2807     case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2808         extraLayout = "input_attachment_index=1,";
2809         break;
2810     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2811         extraLayout = "r32ui,";
2812         break;
2813     default:
2814         break;
2815     }
2816 
2817     // Input attachments may only be declared in fragment shaders. The tests should only be constructed to use fragment
2818     // shaders, but the matching vertex shader will still pass here and must not pick up the invalid declaration.
2819     if (testCaseParams.descriptorType != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
2820         shaderType == VK_SHADER_STAGE_FRAGMENT_BIT)
2821         s << "layout(" << extraLayout << "set=0, binding = " << BINDING_TestObject << ") " << declType << " data[];\n";
2822 
2823     // Now make any additional declarations needed for specific descriptor types
2824     switch (testCaseParams.descriptorType)
2825     {
2826     case VK_DESCRIPTOR_TYPE_SAMPLER:
2827         s << "layout(set=0,binding=" << BINDING_Additional << ") uniform texture2D tex;\n";
2828         break;
2829     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2830         s << "layout(set=0,binding=" << BINDING_Additional << ") uniform sampler samp;\n";
2831         break;
2832     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2833         s << "layout(r32ui,set=0,binding=" << BINDING_Additional << ") uniform uimage2D idxs;\n";
2834         break;
2835     default:
2836         break;
2837     }
2838 
2839     switch (shaderType)
2840     {
2841     case VK_SHADER_STAGE_VERTEX_BIT:
2842         s << getVertexShaderProlog();
2843         break;
2844     case VK_SHADER_STAGE_FRAGMENT_BIT:
2845         s << getFragmentShaderProlog();
2846         break;
2847     case VK_SHADER_STAGE_COMPUTE_BIT:
2848         s << getComputeShaderProlog();
2849         break;
2850     default:
2851         TCU_THROW(InternalError, "Not implemented shader stage");
2852     }
2853 
2854     switch (shaderType)
2855     {
2856     case VK_SHADER_STAGE_VERTEX_BIT:
2857     {
2858         switch (testCaseParams.descriptorType)
2859         {
2860         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2861         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
2862             if (allowVertexStoring)
2863                 s << "  if (gIndex != 0) data[nonuniformEXT(gIndex)].cnew = data[nonuniformEXT(rIndex)].cold;    \n";
2864             break;
2865         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2866             if (allowVertexStoring)
2867                 s << "  if (gIndex != 0) imageStore(data[nonuniformEXT(gIndex)], 1, "
2868                      "imageLoad(data[nonuniformEXT(rIndex)], 0));    \n";
2869             break;
2870         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2871         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
2872         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2873         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2874         case VK_DESCRIPTOR_TYPE_SAMPLER:
2875         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2876         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2877             break;
2878 
2879         default:
2880             TCU_THROW(InternalError, "Not implemented descriptor type");
2881         }
2882     }
2883     break;
2884 
2885     case VK_SHADER_STAGE_FRAGMENT_BIT:
2886     {
2887         if (testCaseParams.calculateInLoop)
2888             s << getFragmentLoopSource(
2889                 getColorAccess(testCaseParams.descriptorType, "rIndex", testCaseParams.usesMipMaps),
2890                 getColorAccess(testCaseParams.descriptorType, "loopIdx", testCaseParams.usesMipMaps));
2891         else
2892             s << getFragmentReturnSource(
2893                 getColorAccess(testCaseParams.descriptorType, "rIndex", testCaseParams.usesMipMaps));
2894         break;
2895     }
2896     break;
2897 
2898     case VK_SHADER_STAGE_COMPUTE_BIT: // VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
2899         if (testCaseParams.calculateInLoop)
2900             s << "  const int totalAdds = pc.upperBound - pc.lowerBound;\n"
2901               << "  const int totalInvs = int(gl_WorkGroupSize.x);\n"
2902               << "  // Round number up so we never fall short in the number of additions\n"
2903               << "  const int addsPerInv = (totalAdds + totalInvs - 1) / totalInvs;\n"
2904               << "  const int baseAdd = int(gl_LocalInvocationID.x) * addsPerInv;\n"
2905               << "  for (int i = 0; i < addsPerInv; ++i) {\n"
2906               << "    const int addIdx = i + baseAdd + pc.lowerBound;\n"
2907               << "    if (addIdx < pc.upperBound) {\n"
2908               << "      imageAtomicAdd(data[nonuniformEXT(texelFetch(iter, addIdx).x)], ivec2(0, 0), 1);\n"
2909               << "    }\n"
2910               << "  }\n";
2911         else
2912         {
2913             s << "  const int xCoord = int(gl_WorkGroupID.x * gl_WorkGroupSize.x + gl_LocalInvocationID.x);\n"
2914               << "  const int yCoord = int(gl_WorkGroupID.y);\n"
2915               << "  uvec4 c = imageLoad(idxs, ivec2(xCoord, yCoord));\n"
2916               << "  imageAtomicAdd( data[nonuniformEXT(c.r)], ivec2(0, 0), 1);\n";
2917         }
2918         break;
2919 
2920     default:
2921         TCU_THROW(InternalError, "Not implemented shader stage");
2922     }
2923 
2924     s << getShaderEpilog();
2925 
2926     return s.str();
2927 }
2928 
2929 class StorageBufferInstance : virtual public CommonDescriptorInstance
2930 {
2931 public:
2932     StorageBufferInstance(Context &context, const TestCaseParams &testCaseParams);
2933 
2934 protected:
2935     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
2936     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
2937 
2938     bool verifyVertexWriteResults(IterateCommonVariables &variables) override;
2939 };
2940 
StorageBufferInstance(Context & context,const TestCaseParams & testCaseParams)2941 StorageBufferInstance::StorageBufferInstance(Context &context, const TestCaseParams &testCaseParams)
2942     : CommonDescriptorInstance(context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2943                                                    VK_DESCRIPTOR_TYPE_UNDEFINED, false,
2944                                                    performWritesInVertex(testCaseParams.descriptorType, context),
2945                                                    testCaseParams))
2946 {
2947 }
2948 
createAndPopulateDescriptors(IterateCommonVariables & variables)2949 void StorageBufferInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
2950 {
2951     BindingStorageBufferData data;
2952 
2953     bool vertexStores = false;
2954     {
2955         ut::DeviceProperties dp(m_context);
2956         vertexStores = dp.physicalDeviceFeatures().vertexPipelineStoresAndAtomics != false;
2957     }
2958     const uint32_t alignment = static_cast<uint32_t>(
2959         ut::DeviceProperties(m_context).physicalDeviceProperties().limits.minStorageBufferOffsetAlignment);
2960     createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount,
2961                   sizeof(data), alignment, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2962 
2963     unsigned char *buffer = static_cast<unsigned char *>(variables.descriptorsBuffer->alloc->getHostPtr());
2964     for (uint32_t infoIdx = 0; infoIdx < variables.validDescriptorCount; ++infoIdx)
2965     {
2966         const float component = m_colorScheme[infoIdx % m_schemeSize];
2967         const tcu::Vec4 color(component, component, component, 1.0f);
2968         VkDescriptorBufferInfo &info = variables.descriptorsBufferInfos[infoIdx];
2969         data.cnew                    = vertexStores ? m_clearColor : color;
2970         data.cold                    = color;
2971 
2972         deMemcpy(buffer + info.offset, &data, sizeof(data));
2973     }
2974     vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
2975 
2976     variables.dataAlignment = deAlign64(sizeof(data), alignment);
2977 }
2978 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)2979 void StorageBufferInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
2980 {
2981     const uint32_t alignment = static_cast<uint32_t>(
2982         ut::DeviceProperties(m_context).physicalDeviceProperties().limits.minStorageBufferOffsetAlignment);
2983     createBuffers(variables.unusedDescriptorsBufferInfos, variables.unusedDescriptorsBuffer, 1,
2984                   sizeof(BindingStorageBufferData), alignment, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2985 }
2986 
verifyVertexWriteResults(IterateCommonVariables & variables)2987 bool StorageBufferInstance::verifyVertexWriteResults(IterateCommonVariables &variables)
2988 {
2989     auto &log = m_context.getTestContext().getLog();
2990     const tcu::Vec4 threshold(0.002f, 0.002f, 0.002f, 0.002f);
2991     const std::vector<uint32_t> primes = ut::generatePrimes(variables.availableDescriptorCount);
2992     unsigned char *buffer              = static_cast<unsigned char *>(variables.descriptorsBuffer->alloc->getHostPtr());
2993     BindingStorageBufferData data;
2994 
2995     log << tcu::TestLog::Message << "Available descriptor count: " << variables.availableDescriptorCount
2996         << tcu::TestLog::EndMessage;
2997     log << tcu::TestLog::Message << "Valid descriptor count:     " << variables.validDescriptorCount
2998         << tcu::TestLog::EndMessage;
2999 
3000     for (uint32_t primeIdx = 0; primeIdx < variables.validDescriptorCount; ++primeIdx)
3001     {
3002         const uint32_t prime  = primes[primeIdx];
3003         const float component = m_colorScheme[(prime % variables.validDescriptorCount) % m_schemeSize];
3004         const tcu::Vec4 referenceValue(component, component, component, 1.0f);
3005 
3006         VkDescriptorBufferInfo &info = variables.descriptorsBufferInfos[primeIdx];
3007         deMemcpy(&data, buffer + info.offset, sizeof(data));
3008         const tcu::Vec4 realValue = data.cnew;
3009 
3010         const tcu::Vec4 diff = tcu::absDiff(referenceValue, realValue);
3011         if (!tcu::boolAll(tcu::lessThanEqual(diff, threshold)))
3012         {
3013             log << tcu::TestLog::Message << "Error in valid descriptor " << primeIdx << " (descriptor " << prime
3014                 << "): expected " << referenceValue << " but found " << realValue << " (threshold " << threshold << ")"
3015                 << tcu::TestLog::EndMessage;
3016 
3017             return false;
3018         }
3019     }
3020     return true;
3021 }
3022 
3023 class UniformBufferInstance : virtual public CommonDescriptorInstance
3024 {
3025 public:
3026     UniformBufferInstance(Context &context, const TestCaseParams &testCaseParams);
3027 
3028 protected:
3029     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3030     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3031 };
3032 
UniformBufferInstance(Context & context,const TestCaseParams & testCaseParams)3033 UniformBufferInstance::UniformBufferInstance(Context &context, const TestCaseParams &testCaseParams)
3034     : CommonDescriptorInstance(context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
3035                                                    VK_DESCRIPTOR_TYPE_UNDEFINED, false,
3036                                                    performWritesInVertex(testCaseParams.descriptorType, context),
3037                                                    testCaseParams))
3038 {
3039 }
3040 
createAndPopulateDescriptors(IterateCommonVariables & variables)3041 void UniformBufferInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3042 {
3043     BindingUniformBufferData data;
3044 
3045     const uint32_t alignment = static_cast<uint32_t>(
3046         ut::DeviceProperties(m_context).physicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
3047     createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount,
3048                   sizeof(data), alignment, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
3049 
3050     unsigned char *buffer = static_cast<unsigned char *>(variables.descriptorsBuffer->alloc->getHostPtr());
3051     for (uint32_t infoIdx = 0; infoIdx < variables.validDescriptorCount; ++infoIdx)
3052     {
3053         const float component        = m_colorScheme[infoIdx % m_schemeSize];
3054         VkDescriptorBufferInfo &info = variables.descriptorsBufferInfos[infoIdx];
3055         data.c                       = tcu::Vec4(component, component, component, 1.0f);
3056         deMemcpy(buffer + info.offset, &data, sizeof(data));
3057     }
3058     vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
3059 
3060     variables.dataAlignment = deAlign64(sizeof(data), alignment);
3061 }
3062 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3063 void UniformBufferInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3064 {
3065     // Just create buffer for unused descriptors, no data needed
3066     const uint32_t alignment = static_cast<uint32_t>(
3067         ut::DeviceProperties(m_context).physicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
3068     createBuffers(variables.unusedDescriptorsBufferInfos, variables.unusedDescriptorsBuffer, 1,
3069                   sizeof(BindingUniformBufferData), alignment, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
3070 }
3071 
3072 class StorageTexelInstance : public CommonDescriptorInstance
3073 {
3074 public:
3075     StorageTexelInstance(Context &context, const TestCaseParams &testCaseParams);
3076 
3077 private:
3078     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3079     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3080 
3081     bool verifyVertexWriteResults(IterateCommonVariables &variables) override;
3082 };
3083 
StorageTexelInstance(Context & context,const TestCaseParams & testCaseParams)3084 StorageTexelInstance::StorageTexelInstance(Context &context, const TestCaseParams &testCaseParams)
3085     : CommonDescriptorInstance(
3086           context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
3087                               VK_DESCRIPTOR_TYPE_UNDEFINED, false,
3088                               performWritesInVertex(testCaseParams.descriptorType, context), testCaseParams))
3089 {
3090 }
3091 
createAndPopulateDescriptors(IterateCommonVariables & variables)3092 void StorageTexelInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3093 {
3094     const VkExtent3D imageExtent = {4, 4, 1};
3095     const uint32_t imageSize     = ut::computeImageSize(imageExtent, m_colorFormat);
3096 
3097     createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount,
3098                   imageSize, sizeof(tcu::Vec4), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
3099     createBuffersViews(variables.descriptorsBufferViews, variables.descriptorsBufferInfos, m_colorFormat);
3100 
3101     for (uint32_t imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
3102     {
3103         const float component      = m_colorScheme[imageIdx % m_schemeSize];
3104         const PixelBufferAccess pa = getPixelAccess(imageIdx, imageExtent, m_colorFormat,
3105                                                     variables.descriptorsBufferInfos, variables.descriptorsBuffer);
3106 
3107         tcu::clear(pa, m_clearColor);
3108         pa.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
3109     }
3110     vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
3111 }
3112 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3113 void StorageTexelInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3114 {
3115     const VkExtent3D imageExtent = {4, 4, 1};
3116     const uint32_t imageSize     = ut::computeImageSize(imageExtent, m_colorFormat);
3117 
3118     createBuffers(variables.unusedDescriptorsBufferInfos, variables.unusedDescriptorsBuffer, 1, imageSize,
3119                   sizeof(tcu::Vec4), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
3120     createBuffersViews(variables.unusedDescriptorsBufferViews, variables.unusedDescriptorsBufferInfos, m_colorFormat);
3121 }
3122 
verifyVertexWriteResults(IterateCommonVariables & variables)3123 bool StorageTexelInstance::verifyVertexWriteResults(IterateCommonVariables &variables)
3124 {
3125     auto &log                    = m_context.getTestContext().getLog();
3126     const VkExtent3D imageExtent = {4, 4, 1};
3127     const tcu::Vec4 threshold(0.002f, 0.002f, 0.002f, 0.002f);
3128     const std::vector<uint32_t> primes = ut::generatePrimes(variables.availableDescriptorCount);
3129 
3130     log << tcu::TestLog::Message << "Available descriptor count: " << variables.availableDescriptorCount
3131         << tcu::TestLog::EndMessage;
3132     log << tcu::TestLog::Message << "Valid descriptor count:     " << variables.validDescriptorCount
3133         << tcu::TestLog::EndMessage;
3134 
3135     for (uint32_t primeIdx = 0; primeIdx < variables.validDescriptorCount; ++primeIdx)
3136     {
3137         const uint32_t prime  = primes[primeIdx];
3138         const float component = m_colorScheme[(prime % variables.validDescriptorCount) % m_schemeSize];
3139         const tcu::Vec4 referenceValue(component, component, component, 1.0f);
3140 
3141         const PixelBufferAccess pa = getPixelAccess(primeIdx, imageExtent, m_colorFormat,
3142                                                     variables.descriptorsBufferInfos, variables.descriptorsBuffer);
3143         const tcu::Vec4 realValue  = pa.getPixel(1, 0);
3144 
3145         const tcu::Vec4 diff = tcu::absDiff(referenceValue, realValue);
3146         if (!tcu::boolAll(tcu::lessThanEqual(diff, threshold)))
3147         {
3148             log << tcu::TestLog::Message << "Error in valid descriptor " << primeIdx << " (descriptor " << prime
3149                 << "): expected " << referenceValue << " but found " << realValue << " (threshold " << threshold << ")"
3150                 << tcu::TestLog::EndMessage;
3151 
3152             return false;
3153         }
3154     }
3155     return true;
3156 }
3157 
3158 class UniformTexelInstance : public CommonDescriptorInstance
3159 {
3160 public:
3161     UniformTexelInstance(Context &context, const TestCaseParams &testCaseParams);
3162 
3163 private:
3164     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3165     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3166 };
3167 
UniformTexelInstance(Context & context,const TestCaseParams & testCaseParams)3168 UniformTexelInstance::UniformTexelInstance(Context &context, const TestCaseParams &testCaseParams)
3169     : CommonDescriptorInstance(
3170           context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
3171                               VK_DESCRIPTOR_TYPE_UNDEFINED, false,
3172                               performWritesInVertex(testCaseParams.descriptorType, context), testCaseParams))
3173 {
3174 }
3175 
createAndPopulateDescriptors(IterateCommonVariables & variables)3176 void UniformTexelInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3177 {
3178     const VkExtent3D imageExtent = {4, 4, 1};
3179     const uint32_t imageSize     = ut::computeImageSize(imageExtent, m_colorFormat);
3180 
3181     createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount,
3182                   imageSize, sizeof(tcu::Vec4), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT);
3183     createBuffersViews(variables.descriptorsBufferViews, variables.descriptorsBufferInfos, m_colorFormat);
3184 
3185     for (uint32_t imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
3186     {
3187         const float component      = m_colorScheme[imageIdx % m_schemeSize];
3188         const PixelBufferAccess pa = getPixelAccess(imageIdx, imageExtent, m_colorFormat,
3189                                                     variables.descriptorsBufferInfos, variables.descriptorsBuffer);
3190 
3191         tcu::clear(pa, tcu::Vec4(component, component, component, 1.0f));
3192     }
3193     vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
3194 }
3195 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3196 void UniformTexelInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3197 {
3198     const VkExtent3D imageExtent = {4, 4, 1};
3199     const uint32_t imageSize     = ut::computeImageSize(imageExtent, m_colorFormat);
3200 
3201     createBuffers(variables.unusedDescriptorsBufferInfos, variables.unusedDescriptorsBuffer, 1, imageSize,
3202                   sizeof(tcu::Vec4), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT);
3203     createBuffersViews(variables.unusedDescriptorsBufferViews, variables.unusedDescriptorsBufferInfos, m_colorFormat);
3204 }
3205 
3206 class DynamicBuffersInstance : virtual public CommonDescriptorInstance
3207 {
3208 public:
DynamicBuffersInstance(Context & context,const TestParams & testParams)3209     DynamicBuffersInstance(Context &context, const TestParams &testParams)
3210         : CommonDescriptorInstance(context, testParams)
3211     {
3212     }
3213 
3214 protected:
3215     virtual tcu::TestStatus iterate(void);
3216     virtual void updateDescriptors(IterateCommonVariables &variables);
3217 };
3218 
updateDescriptors(IterateCommonVariables & variables)3219 void DynamicBuffersInstance::updateDescriptors(IterateCommonVariables &variables)
3220 {
3221     DE_ASSERT(variables.dataAlignment);
3222 
3223     VkDescriptorBufferInfo bufferInfo = {*variables.descriptorsBuffer.get()->buffer,
3224                                          0, // always 0, it will be taken from pDynamicOffsets
3225                                          variables.dataAlignment};
3226 
3227     VkWriteDescriptorSet updateInfo = {
3228         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
3229         nullptr,                                // pNext
3230         *variables.descriptorSet,               // descriptorSet
3231         BINDING_TestObject,                     // descriptorBinding;
3232         0,                                      // to be set in below loop                    // dstArrayElement
3233         1u,                                     // descriptorCount
3234         m_testParams.descriptorType,            // descriptorType
3235         nullptr,                                // pImageInfo
3236         &bufferInfo,                            // pBufferInfo
3237         nullptr                                 // pTexelBufferView
3238     };
3239 
3240     uint32_t descIdx                   = 0;
3241     const std::vector<uint32_t> primes = ut::generatePrimes(variables.availableDescriptorCount);
3242     for (uint32_t validIdx = 0; validIdx < variables.validDescriptorCount; ++validIdx)
3243     {
3244         for (; descIdx < primes[validIdx]; ++descIdx)
3245         {
3246             updateInfo.dstArrayElement = descIdx;
3247             m_vki.updateDescriptorSets(m_vkd, 1u, &updateInfo, 0u, nullptr);
3248         }
3249 
3250         updateInfo.dstArrayElement = primes[validIdx];
3251         m_vki.updateDescriptorSets(m_vkd, 1u, &updateInfo, 0u, nullptr);
3252 
3253         ++descIdx;
3254     }
3255     for (; descIdx < variables.availableDescriptorCount; ++descIdx)
3256     {
3257         updateInfo.dstArrayElement = descIdx;
3258         m_vki.updateDescriptorSets(m_vkd, 1u, &updateInfo, 0u, nullptr);
3259     }
3260 }
3261 
iterate(void)3262 tcu::TestStatus DynamicBuffersInstance::iterate(void)
3263 {
3264     IterateCommonVariables v;
3265     iterateCommandSetup(v);
3266 
3267     ut::UpdatablePixelBufferAccessPtr programResult;
3268     ut::UpdatablePixelBufferAccessPtr referenceResult;
3269     bool firstPass = true;
3270 
3271     DE_ASSERT(v.dataAlignment);
3272 
3273     std::vector<uint32_t> dynamicOffsets;
3274 
3275     uint32_t descIdx                   = 0;
3276     const std::vector<uint32_t> primes = ut::generatePrimes(v.availableDescriptorCount);
3277     for (uint32_t validIdx = 0; validIdx < v.validDescriptorCount; ++validIdx)
3278     {
3279         for (; descIdx < primes[validIdx]; ++descIdx)
3280         {
3281             dynamicOffsets.push_back(0);
3282         }
3283 
3284         dynamicOffsets.push_back(static_cast<uint32_t>(validIdx * v.dataAlignment));
3285 
3286         ++descIdx;
3287     }
3288     for (; descIdx < v.availableDescriptorCount; ++descIdx)
3289     {
3290         dynamicOffsets.push_back(0);
3291     }
3292 
3293     // Unfortunatelly not lees and not more, only exactly
3294     DE_ASSERT(dynamicOffsets.size() == v.availableDescriptorCount);
3295 
3296     const VkDescriptorSet descriptorSets[] = {*v.descriptorSet};
3297 
3298     v.renderArea.extent.width  = m_testParams.frameResolution.width / 4;
3299     v.renderArea.extent.height = m_testParams.frameResolution.height / 4;
3300 
3301     for (int x = 0; x < 4; x++)
3302         for (int y = 0; y < 4; y++)
3303         {
3304             v.renderArea.offset.x = x * m_testParams.frameResolution.width / 4;
3305             v.renderArea.offset.y = y * m_testParams.frameResolution.height / 4;
3306 
3307             iterateCommandBegin(v, firstPass);
3308             firstPass = false;
3309 
3310             m_vki.cmdBindDescriptorSets(*v.commandBuffer,                   // commandBuffer
3311                                         VK_PIPELINE_BIND_POINT_GRAPHICS,    // pipelineBindPoint
3312                                         *v.pipelineLayout,                  // layout
3313                                         0u,                                 // firstSet
3314                                         DE_LENGTH_OF_ARRAY(descriptorSets), // descriptorSetCount
3315                                         descriptorSets,                     // pDescriptorSets
3316                                         v.availableDescriptorCount,         // dynamicOffsetCount
3317                                         dynamicOffsets.data());             // pDynamicOffsets
3318 
3319             vk::VkRect2D scissor = makeRect2D(v.renderArea.offset.x, v.renderArea.offset.y, v.renderArea.extent.width,
3320                                               v.renderArea.extent.height);
3321             m_vki.cmdSetScissor(*v.commandBuffer, 0u, 1u, &scissor);
3322 
3323             vk::beginRenderPass(m_vki, *v.commandBuffer, *v.renderPass, *v.frameBuffer->buffer, v.renderArea,
3324                                 m_clearColor);
3325             m_vki.cmdDraw(*v.commandBuffer, v.vertexCount, 1u, 0u, 0u);
3326             vk::endRenderPass(m_vki, *v.commandBuffer);
3327 
3328             iterateCommandEnd(v, programResult, referenceResult);
3329             programResult->invalidate();
3330         }
3331 
3332     if (iterateVerifyResults(v, programResult, referenceResult))
3333         return tcu::TestStatus::pass("Pass");
3334     return tcu::TestStatus::fail("Failed -- check log for details");
3335 }
3336 
3337 class DynamicStorageBufferInstance : public DynamicBuffersInstance, public StorageBufferInstance
3338 {
3339 public:
3340     DynamicStorageBufferInstance(Context &context, const TestCaseParams &testCaseParams);
3341     tcu::TestStatus iterate(void) override;
3342     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3343     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3344     void updateDescriptors(IterateCommonVariables &variables) override;
3345     bool verifyVertexWriteResults(IterateCommonVariables &variables) override;
3346 };
3347 
DynamicStorageBufferInstance(Context & context,const TestCaseParams & testCaseParams)3348 DynamicStorageBufferInstance::DynamicStorageBufferInstance(Context &context, const TestCaseParams &testCaseParams)
3349     : CommonDescriptorInstance(
3350           context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
3351                               VK_DESCRIPTOR_TYPE_UNDEFINED, false,
3352                               performWritesInVertex(testCaseParams.descriptorType, context), testCaseParams))
3353     , DynamicBuffersInstance(context, m_testParams)
3354     , StorageBufferInstance(context, testCaseParams)
3355 {
3356 }
3357 
iterate(void)3358 tcu::TestStatus DynamicStorageBufferInstance::iterate(void)
3359 {
3360     return DynamicBuffersInstance::iterate();
3361 }
3362 
createAndPopulateDescriptors(IterateCommonVariables & variables)3363 void DynamicStorageBufferInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3364 {
3365     StorageBufferInstance::createAndPopulateDescriptors(variables);
3366 }
3367 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3368 void DynamicStorageBufferInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3369 {
3370     StorageBufferInstance::createAndPopulateUnusedDescriptors(variables);
3371 }
3372 
updateDescriptors(IterateCommonVariables & variables)3373 void DynamicStorageBufferInstance::updateDescriptors(IterateCommonVariables &variables)
3374 {
3375     DynamicBuffersInstance::updateDescriptors(variables);
3376 }
3377 
verifyVertexWriteResults(IterateCommonVariables & variables)3378 bool DynamicStorageBufferInstance::verifyVertexWriteResults(IterateCommonVariables &variables)
3379 {
3380     return StorageBufferInstance::verifyVertexWriteResults(variables);
3381 }
3382 
3383 class DynamicUniformBufferInstance : public DynamicBuffersInstance, public UniformBufferInstance
3384 {
3385 public:
3386     DynamicUniformBufferInstance(Context &context, const TestCaseParams &testCaseParams);
3387     tcu::TestStatus iterate(void) override;
3388     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3389     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3390     void updateDescriptors(IterateCommonVariables &variables) override;
3391 };
3392 
DynamicUniformBufferInstance(Context & context,const TestCaseParams & testCaseParams)3393 DynamicUniformBufferInstance::DynamicUniformBufferInstance(Context &context, const TestCaseParams &testCaseParams)
3394     : CommonDescriptorInstance(
3395           context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
3396                               VK_DESCRIPTOR_TYPE_UNDEFINED, false,
3397                               performWritesInVertex(testCaseParams.descriptorType, context), testCaseParams))
3398     , DynamicBuffersInstance(context, m_testParams)
3399     , UniformBufferInstance(context, testCaseParams)
3400 {
3401 }
3402 
iterate(void)3403 tcu::TestStatus DynamicUniformBufferInstance::iterate(void)
3404 {
3405     return DynamicBuffersInstance::iterate();
3406 }
3407 
createAndPopulateDescriptors(IterateCommonVariables & variables)3408 void DynamicUniformBufferInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3409 {
3410     UniformBufferInstance::createAndPopulateDescriptors(variables);
3411 }
3412 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3413 void DynamicUniformBufferInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3414 {
3415     UniformBufferInstance::createAndPopulateUnusedDescriptors(variables);
3416 }
3417 
updateDescriptors(IterateCommonVariables & variables)3418 void DynamicUniformBufferInstance::updateDescriptors(IterateCommonVariables &variables)
3419 {
3420     DynamicBuffersInstance::updateDescriptors(variables);
3421 }
3422 
3423 class InputAttachmentInstance : public CommonDescriptorInstance
3424 {
3425 public:
3426     InputAttachmentInstance(Context &context, const TestCaseParams &testCaseParams);
3427 
3428 private:
3429     Move<VkRenderPass> createRenderPass(const IterateCommonVariables &variables) override;
3430     void createFramebuffer(ut::FrameBufferSp &frameBuffer, VkRenderPass renderPass,
3431                            const IterateCommonVariables &variables) override;
3432     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3433     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3434 };
3435 
InputAttachmentInstance(Context & context,const TestCaseParams & testCaseParams)3436 InputAttachmentInstance::InputAttachmentInstance(Context &context, const TestCaseParams &testCaseParams)
3437     : CommonDescriptorInstance(context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
3438                                                    VK_DESCRIPTOR_TYPE_UNDEFINED, true,
3439                                                    performWritesInVertex(testCaseParams.descriptorType, context),
3440                                                    testCaseParams))
3441 {
3442 }
3443 
createAndPopulateDescriptors(IterateCommonVariables & variables)3444 void InputAttachmentInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3445 {
3446     createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
3447                  VK_BUFFER_USAGE_TRANSFER_SRC_BIT, m_testParams.frameResolution, m_colorFormat,
3448                  VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount);
3449     createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat);
3450 
3451     for (uint32_t descriptorIdx = 0; descriptorIdx < variables.validDescriptorCount; ++descriptorIdx)
3452     {
3453         const float component           = m_colorScheme[descriptorIdx % m_schemeSize];
3454         const tcu::PixelBufferAccess pa = getPixelAccess(descriptorIdx, m_testParams.frameResolution, m_colorFormat,
3455                                                          variables.descriptorsBufferInfos, variables.descriptorsBuffer);
3456         tcu::clear(pa, tcu::Vec4(component, component, component, 1.0f));
3457     }
3458     vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
3459 }
3460 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3461 void InputAttachmentInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3462 {
3463     createImages(variables.unusedDescriptorsImages, variables.unusedDescriptorsBufferInfos,
3464                  variables.unusedDescriptorsBuffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, m_testParams.frameResolution,
3465                  m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, 1);
3466     createImagesViews(variables.unusedDescriptorImageViews, variables.unusedDescriptorsImages, m_colorFormat);
3467 }
3468 
createRenderPass(const IterateCommonVariables & variables)3469 Move<VkRenderPass> InputAttachmentInstance::createRenderPass(const IterateCommonVariables &variables)
3470 {
3471     std::vector<VkAttachmentDescription> attachmentDescriptions;
3472     std::vector<VkAttachmentReference> inputAttachmentRefs;
3473 
3474     const VkAttachmentDescription colorAttachmentDescription = {
3475         (VkAttachmentDescriptionFlags)0,          // VkAttachmentDescriptionFlags flags;
3476         m_colorFormat,                            // VkFormat format;
3477         VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
3478         VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp loadOp;
3479         VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
3480         VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
3481         VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
3482         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
3483         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
3484     };
3485     const VkAttachmentReference colorAttachmentRef = {
3486         0u,                                      // uint32_t attachment;
3487         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
3488     };
3489     attachmentDescriptions.push_back(colorAttachmentDescription);
3490 
3491     // build input atachments
3492     {
3493         const std::vector<uint32_t> primes = ut::generatePrimes(variables.availableDescriptorCount);
3494         const uint32_t inputCount          = static_cast<uint32_t>(variables.descriptorImageViews.size());
3495         for (uint32_t inputIdx = 0; inputIdx < inputCount; ++inputIdx)
3496         {
3497             // primes holds the indices of input attachments for shader binding 10 which has input_attachment_index=1
3498             uint32_t nextInputAttachmentIndex = primes[inputIdx] + 1;
3499 
3500             // Fill up the subpass description's input attachments with unused attachments forming gaps to the next referenced attachment
3501             for (uint32_t unusedIdx = static_cast<uint32_t>(inputAttachmentRefs.size());
3502                  unusedIdx < nextInputAttachmentIndex; ++unusedIdx)
3503             {
3504                 const VkAttachmentReference inputAttachmentRef = {
3505                     VK_ATTACHMENT_UNUSED,   // uint32_t attachment;
3506                     VK_IMAGE_LAYOUT_GENERAL // VkImageLayout layout;
3507                 };
3508 
3509                 inputAttachmentRefs.push_back(inputAttachmentRef);
3510             }
3511 
3512             const VkAttachmentDescription inputAttachmentDescription = {
3513                 VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT,       // VkAttachmentDescriptionFlags flags;
3514                 variables.descriptorsImages[inputIdx]->format, // VkFormat format;
3515                 VK_SAMPLE_COUNT_1_BIT,                         // VkSampleCountFlagBits samples;
3516                 VK_ATTACHMENT_LOAD_OP_LOAD,                    // VkAttachmentLoadOp loadOp;
3517                 VK_ATTACHMENT_STORE_OP_STORE,                  // VkAttachmentStoreOp storeOp;
3518                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,               // VkAttachmentLoadOp stencilLoadOp;
3519                 VK_ATTACHMENT_STORE_OP_DONT_CARE,              // VkAttachmentStoreOp stencilStoreOp;
3520                 VK_IMAGE_LAYOUT_GENERAL,                       // VkImageLayout initialLayout;
3521                 VK_IMAGE_LAYOUT_GENERAL                        // VkImageLayout finalLayout;
3522             };
3523 
3524             const VkAttachmentReference inputAttachmentRef = {
3525                 inputIdx + 1,           // uint32_t attachment;
3526                 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout layout;
3527             };
3528 
3529             inputAttachmentRefs.push_back(inputAttachmentRef);
3530             attachmentDescriptions.push_back(inputAttachmentDescription);
3531         }
3532     }
3533 
3534     const VkSubpassDescription subpassDescription = {
3535         (VkSubpassDescriptionFlags)0,                      // VkSubpassDescriptionFlags flags;
3536         VK_PIPELINE_BIND_POINT_GRAPHICS,                   // VkPipelineBindPoint pipelineBindPoint;
3537         static_cast<uint32_t>(inputAttachmentRefs.size()), // uint32_t inputAttachmentCount;
3538         inputAttachmentRefs.data(),                        // const VkAttachmentReference* pInputAttachments;
3539         1u,                                                // uint32_t colorAttachmentCount;
3540         &colorAttachmentRef,                               // const VkAttachmentReference* pColorAttachments;
3541         nullptr,                                           // const VkAttachmentReference* pResolveAttachments;
3542         nullptr,                                           // const VkAttachmentReference* pDepthStencilAttachment;
3543         0u,                                                // uint32_t preserveAttachmentCount;
3544         nullptr                                            // const uint32_t* pPreserveAttachments;
3545     };
3546 
3547     const VkRenderPassCreateInfo renderPassInfo = {
3548         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,            // VkStructureType sType;
3549         nullptr,                                              // const void* pNext;
3550         (VkRenderPassCreateFlags)0,                           // VkRenderPassCreateFlags flags;
3551         static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t attachmentCount;
3552         attachmentDescriptions.data(),                        // const VkAttachmentDescription* pAttachments;
3553         1u,                                                   // uint32_t subpassCount;
3554         &subpassDescription,                                  // const VkSubpassDescription* pSubpasses;
3555         0u,                                                   // uint32_t dependencyCount;
3556         nullptr                                               // const VkSubpassDependency* pDependencies;
3557     };
3558 
3559     return vk::createRenderPass(m_vki, m_vkd, &renderPassInfo);
3560 }
3561 
createFramebuffer(ut::FrameBufferSp & frameBuffer,VkRenderPass renderPass,const IterateCommonVariables & variables)3562 void InputAttachmentInstance::createFramebuffer(ut::FrameBufferSp &frameBuffer, VkRenderPass renderPass,
3563                                                 const IterateCommonVariables &variables)
3564 {
3565     std::vector<VkImageView> inputAttachments;
3566     const uint32_t viewCount = static_cast<uint32_t>(variables.descriptorImageViews.size());
3567     inputAttachments.resize(viewCount);
3568     for (uint32_t viewIdx = 0; viewIdx < viewCount; ++viewIdx)
3569     {
3570         inputAttachments[viewIdx] = **variables.descriptorImageViews[viewIdx];
3571     }
3572     ut::createFrameBuffer(frameBuffer, m_context, m_testParams.frameResolution, m_colorFormat, renderPass, viewCount,
3573                           inputAttachments.data());
3574 }
3575 
3576 class SamplerInstance : public CommonDescriptorInstance
3577 {
3578 public:
3579     SamplerInstance(Context &context, const TestCaseParams &testCaseParams);
3580 
3581 private:
3582     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3583     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3584     void updateDescriptors(IterateCommonVariables &variables) override;
3585 };
3586 
SamplerInstance(Context & context,const TestCaseParams & testCaseParams)3587 SamplerInstance::SamplerInstance(Context &context, const TestCaseParams &testCaseParams)
3588     : CommonDescriptorInstance(context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_SAMPLER,
3589                                                    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, true,
3590                                                    performWritesInVertex(testCaseParams.descriptorType, context),
3591                                                    testCaseParams))
3592 {
3593 }
3594 
updateDescriptors(IterateCommonVariables & variables)3595 void SamplerInstance::updateDescriptors(IterateCommonVariables &variables)
3596 {
3597     DE_ASSERT(variables.descriptorsImages.size() == 1);
3598     DE_ASSERT(variables.descriptorImageViews.size() == 1);
3599     DE_ASSERT(variables.descriptorsBufferInfos.size() == 1);
3600     DE_ASSERT(m_testParams.additionalDescriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
3601     DE_ASSERT(variables.descriptorSamplers.size() == variables.validDescriptorCount);
3602 
3603     // update an image
3604     {
3605         const VkDescriptorImageInfo imageInfo = {static_cast<VkSampler>(0), **variables.descriptorImageViews[0],
3606                                                  VK_IMAGE_LAYOUT_GENERAL};
3607 
3608         const VkWriteDescriptorSet writeInfo = {
3609             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
3610             nullptr,                                // pNext
3611             *variables.descriptorSet,               // descriptorSet
3612             BINDING_Additional,                     // descriptorBinding;
3613             0,                                      // elementIndex
3614             1u,                                     // descriptorCount
3615             VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,       // descriptorType
3616             &imageInfo,                             // pImageInfo
3617             nullptr,                                // pBufferInfo
3618             nullptr                                 // pTexelBufferView
3619         };
3620 
3621         m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, nullptr);
3622     }
3623 
3624     // update samplers
3625     CommonDescriptorInstance::updateDescriptors(variables);
3626 }
3627 
createAndPopulateDescriptors(IterateCommonVariables & variables)3628 void SamplerInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3629 {
3630     DE_ASSERT(variables.descriptorsImages.size() == 0);
3631     DE_ASSERT(variables.descriptorImageViews.size() == 0);
3632     DE_ASSERT(variables.descriptorsBufferInfos.size() == 0);
3633     DE_ASSERT(variables.descriptorSamplers.size() == 0);
3634 
3635     // create and populate an image
3636     {
3637         VkExtent3D imageExtent = m_testParams.frameResolution;
3638         if (m_testParams.usesMipMaps)
3639         {
3640             imageExtent.width *= 2;
3641             imageExtent.height *= 2;
3642         }
3643 
3644         createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
3645                      VK_BUFFER_USAGE_TRANSFER_SRC_BIT, imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, 1,
3646                      m_testParams.usesMipMaps);
3647         createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat);
3648 
3649         PixelBufferAccess pa = getPixelAccess(0, imageExtent, m_colorFormat, variables.descriptorsBufferInfos,
3650                                               variables.descriptorsBuffer, m_testParams.usesMipMaps ? 1 : 0);
3651 
3652         for (uint32_t y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y)
3653         {
3654             for (uint32_t x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum)
3655             {
3656                 const float component = m_colorScheme[(pixelNum % variables.validDescriptorCount) % m_schemeSize];
3657                 pa.setPixel(tcu::Vec4(component, component, component, 1.0f), x, y);
3658             }
3659         }
3660 
3661         vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
3662     }
3663 
3664     const tcu::Sampler sampler(
3665         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapS
3666         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapT
3667         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapR
3668         m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter
3669         m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter
3670         0.0f,                                                                                    // lodTreshold
3671         true,                                                                                    // normalizeCoords
3672         tcu::Sampler::COMPAREMODE_NONE,                                                          // compare
3673         0,                                                                                       // compareChannel
3674         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),                                                       // borderColor
3675         true);                                                                                   // seamlessCubeMap
3676     const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
3677     variables.descriptorSamplers.resize(variables.validDescriptorCount);
3678 
3679     for (uint32_t samplerIdx = 0; samplerIdx < variables.validDescriptorCount; ++samplerIdx)
3680     {
3681         variables.descriptorSamplers[samplerIdx] =
3682             ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo)));
3683     }
3684 }
3685 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3686 void SamplerInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3687 {
3688     DE_ASSERT(variables.unusedDescriptorsImages.size() == 0);
3689     DE_ASSERT(variables.unusedDescriptorImageViews.size() == 0);
3690     DE_ASSERT(variables.unusedDescriptorsBufferInfos.size() == 0);
3691     DE_ASSERT(variables.unusedDescriptorSamplers.size() == 0);
3692 
3693     // create and populate an image
3694     {
3695         VkExtent3D imageExtent = m_testParams.frameResolution;
3696         if (m_testParams.usesMipMaps)
3697         {
3698             imageExtent.width *= 2;
3699             imageExtent.height *= 2;
3700         }
3701 
3702         createImages(variables.unusedDescriptorsImages, variables.unusedDescriptorsBufferInfos,
3703                      variables.unusedDescriptorsBuffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, imageExtent, m_colorFormat,
3704                      VK_IMAGE_LAYOUT_UNDEFINED, 1, m_testParams.usesMipMaps);
3705         createImagesViews(variables.unusedDescriptorImageViews, variables.unusedDescriptorsImages, m_colorFormat);
3706     }
3707 
3708     const tcu::Sampler sampler(
3709         tcu::Sampler::CLAMP_TO_BORDER,                                                          // wrapS
3710         tcu::Sampler::CLAMP_TO_BORDER,                                                          // wrapT
3711         tcu::Sampler::CLAMP_TO_BORDER,                                                          // wrapR
3712         m_testParams.usesMipMaps ? tcu::Sampler::LINEAR_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter
3713         m_testParams.usesMipMaps ? tcu::Sampler::LINEAR_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter
3714         0.0f,                                                                                   // lodTreshold
3715         true,                                                                                   // normalizeCoords
3716         tcu::Sampler::COMPAREMODE_NONE,                                                         // compare
3717         0,                                                                                      // compareChannel
3718         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),                                                      // borderColor
3719         true);                                                                                  // seamlessCubeMap
3720     const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
3721     variables.unusedDescriptorSamplers.resize(1);
3722     variables.unusedDescriptorSamplers[0] =
3723         ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo)));
3724 }
3725 
3726 class SampledImageInstance : public CommonDescriptorInstance
3727 {
3728 public:
3729     SampledImageInstance(Context &context, const TestCaseParams &testCaseParams);
3730 
3731 private:
3732     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3733     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3734     void updateDescriptors(IterateCommonVariables &variables) override;
3735 };
3736 
SampledImageInstance(Context & context,const TestCaseParams & testCaseParams)3737 SampledImageInstance::SampledImageInstance(Context &context, const TestCaseParams &testCaseParams)
3738     : CommonDescriptorInstance(context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
3739                                                    VK_DESCRIPTOR_TYPE_SAMPLER, true,
3740                                                    performWritesInVertex(testCaseParams.descriptorType, context),
3741                                                    testCaseParams))
3742 {
3743 }
3744 
updateDescriptors(IterateCommonVariables & variables)3745 void SampledImageInstance::updateDescriptors(IterateCommonVariables &variables)
3746 {
3747     DE_ASSERT(variables.descriptorSamplers.size() == 1);
3748     DE_ASSERT(variables.descriptorsImages.size() == variables.validDescriptorCount);
3749     DE_ASSERT(variables.descriptorImageViews.size() == variables.validDescriptorCount);
3750     DE_ASSERT(variables.descriptorsBufferInfos.size() == variables.validDescriptorCount);
3751 
3752     // update a sampler
3753     {
3754         const VkDescriptorImageInfo samplerInfo = {**variables.descriptorSamplers[0], static_cast<VkImageView>(0),
3755                                                    static_cast<VkImageLayout>(0)};
3756 
3757         const VkWriteDescriptorSet writeInfo = {
3758             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
3759             nullptr,                                // pNext
3760             *variables.descriptorSet,               // descriptorSet
3761             BINDING_Additional,                     // descriptorBinding;
3762             0,                                      // elementIndex
3763             1u,                                     // descriptorCount
3764             VK_DESCRIPTOR_TYPE_SAMPLER,             // descriptorType
3765             &samplerInfo,                           // pImageInfo
3766             nullptr,                                // pBufferInfo
3767             nullptr                                 // pTexelBufferView
3768         };
3769 
3770         m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, nullptr);
3771     }
3772 
3773     // update images
3774     CommonDescriptorInstance::updateDescriptors(variables);
3775 }
3776 
createAndPopulateDescriptors(IterateCommonVariables & variables)3777 void SampledImageInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3778 {
3779     DE_ASSERT(variables.descriptorSamplers.size() == 0);
3780     DE_ASSERT(variables.descriptorsImages.size() == 0);
3781     DE_ASSERT(variables.descriptorImageViews.size() == 0);
3782     DE_ASSERT(variables.descriptorsBufferInfos.size() == 0);
3783 
3784     // create an only one sampler for all images
3785     {
3786         const tcu::Sampler sampler(
3787             tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapS
3788             tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapT
3789             tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapR
3790             m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter
3791             m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter
3792             0.0f,                                                                                    // lodTreshold
3793             true,                                                                                    // normalizeCoords
3794             tcu::Sampler::COMPAREMODE_NONE,                                                          // compare
3795             0,                                                                                       // compareChannel
3796             tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),                                                       // borderColor
3797             true);                                                                                   // seamlessCubeMap
3798         const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
3799         variables.descriptorSamplers.push_back(
3800             ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo))));
3801     }
3802 
3803     const VkExtent3D &imageExtent = m_testParams.usesMipMaps ? bigImageExtent : smallImageExtent;
3804 
3805     createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
3806                  VK_BUFFER_USAGE_TRANSFER_SRC_BIT, imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED,
3807                  variables.validDescriptorCount, m_testParams.usesMipMaps);
3808     createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat);
3809 
3810     PixelBufferAccess pixelAccess;
3811     for (uint32_t imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
3812     {
3813         const float component = m_colorScheme[imageIdx % m_schemeSize];
3814 
3815         if (m_testParams.usesMipMaps)
3816         {
3817             const uint32_t mipCount = ut::computeMipMapCount(imageExtent);
3818             DE_ASSERT(mipCount >= 2);
3819             for (uint32_t mipIdx = 0; mipIdx < mipCount; ++mipIdx)
3820             {
3821                 pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos,
3822                                              variables.descriptorsBuffer, mipIdx);
3823                 tcu::clear(pixelAccess, m_clearColor);
3824             }
3825 
3826             pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos,
3827                                          variables.descriptorsBuffer, mipCount - 1);
3828             pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
3829         }
3830         else
3831         {
3832             pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos,
3833                                          variables.descriptorsBuffer, 0);
3834             pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
3835         }
3836     }
3837     vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
3838 }
3839 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3840 void SampledImageInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3841 {
3842     DE_ASSERT(variables.unusedDescriptorSamplers.size() == 0);
3843     DE_ASSERT(variables.unusedDescriptorsImages.size() == 0);
3844     DE_ASSERT(variables.unusedDescriptorImageViews.size() == 0);
3845     DE_ASSERT(variables.unusedDescriptorsBufferInfos.size() == 0);
3846 
3847     // create an only one sampler for all images
3848     {
3849         const tcu::Sampler sampler(
3850             tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapS
3851             tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapT
3852             tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapR
3853             m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter
3854             m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter
3855             0.0f,                                                                                    // lodTreshold
3856             true,                                                                                    // normalizeCoords
3857             tcu::Sampler::COMPAREMODE_NONE,                                                          // compare
3858             0,                                                                                       // compareChannel
3859             tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),                                                       // borderColor
3860             true);                                                                                   // seamlessCubeMap
3861         const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
3862         variables.unusedDescriptorSamplers.push_back(
3863             ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo))));
3864     }
3865 
3866     const VkExtent3D &imageExtent = m_testParams.usesMipMaps ? bigImageExtent : smallImageExtent;
3867 
3868     createImages(variables.unusedDescriptorsImages, variables.unusedDescriptorsBufferInfos,
3869                  variables.unusedDescriptorsBuffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, imageExtent, m_colorFormat,
3870                  VK_IMAGE_LAYOUT_UNDEFINED, 1, m_testParams.usesMipMaps);
3871     createImagesViews(variables.unusedDescriptorImageViews, variables.unusedDescriptorsImages, m_colorFormat);
3872 }
3873 
3874 class CombinedImageInstance : public CommonDescriptorInstance
3875 {
3876 public:
3877     CombinedImageInstance(Context &context, const TestCaseParams &testCaseParams);
3878 
3879 private:
3880     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
3881     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
3882     void updateDescriptors(IterateCommonVariables &variables) override;
3883 };
3884 
CombinedImageInstance(Context & context,const TestCaseParams & testCaseParams)3885 CombinedImageInstance::CombinedImageInstance(Context &context, const TestCaseParams &testCaseParams)
3886     : CommonDescriptorInstance(
3887           context, TestParams(VK_SHADER_STAGE_ALL_GRAPHICS, testCaseParams.descriptorType, VK_DESCRIPTOR_TYPE_UNDEFINED,
3888                               true, performWritesInVertex(testCaseParams.descriptorType), testCaseParams))
3889 {
3890 }
3891 
updateDescriptors(IterateCommonVariables & variables)3892 void CombinedImageInstance::updateDescriptors(IterateCommonVariables &variables)
3893 {
3894     const std::vector<uint32_t> primes = ut::generatePrimes(variables.availableDescriptorCount);
3895     const uint32_t primeCount          = static_cast<uint32_t>(primes.size());
3896 
3897     DE_ASSERT(variables.descriptorSamplers.size() == 1);
3898     DE_ASSERT(variables.descriptorsImages.size() == primeCount);
3899     DE_ASSERT(variables.descriptorImageViews.size() == primeCount);
3900     DE_ASSERT(variables.descriptorsBufferInfos.size() == primeCount);
3901 
3902     for (uint32_t primeIdx = 0; primeIdx < primeCount; ++primeIdx)
3903     {
3904         const VkDescriptorImageInfo imageInfo = {**variables.descriptorSamplers[0],
3905                                                  **variables.descriptorImageViews[primeIdx], VK_IMAGE_LAYOUT_GENERAL};
3906 
3907         const VkWriteDescriptorSet writeInfo = {
3908             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
3909             nullptr,                                // pNext
3910             *variables.descriptorSet,               // descriptorSet
3911             BINDING_TestObject,                     // descriptorBinding;
3912             primes[primeIdx],                       // elementIndex
3913             1u,                                     // descriptorCount
3914             m_testParams.descriptorType,            // descriptorType
3915             &imageInfo,                             // pImageInfo
3916             nullptr,                                // pBufferInfo
3917             nullptr                                 // pTexelBufferView
3918         };
3919 
3920         m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, nullptr);
3921     }
3922 }
3923 
createAndPopulateDescriptors(IterateCommonVariables & variables)3924 void CombinedImageInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
3925 {
3926     DE_ASSERT(variables.descriptorSamplers.size() == 0);
3927     DE_ASSERT(variables.descriptorsImages.size() == 0);
3928     DE_ASSERT(variables.descriptorImageViews.size() == 0);
3929     DE_ASSERT(variables.descriptorsBufferInfos.size() == 0);
3930     DE_ASSERT(variables.descriptorSamplers.size() == 0);
3931 
3932     const tcu::Sampler sampler(
3933         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapS
3934         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapT
3935         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapR
3936         m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter
3937         m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter
3938         0.0f,                                                                                    // lodTreshold
3939         true,                                                                                    // normalizeCoords
3940         tcu::Sampler::COMPAREMODE_NONE,                                                          // compare
3941         0,                                                                                       // compareChannel
3942         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),                                                       // borderColor
3943         true);                                                                                   // seamlessCubeMap
3944     const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
3945     variables.descriptorSamplers.push_back(
3946         ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo))));
3947 
3948     const VkExtent3D &imageExtent = m_testParams.usesMipMaps ? bigImageExtent : smallImageExtent;
3949     createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
3950                  VK_BUFFER_USAGE_TRANSFER_SRC_BIT, imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED,
3951                  variables.validDescriptorCount, m_testParams.usesMipMaps);
3952     createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat);
3953 
3954     PixelBufferAccess pixelAccess;
3955     for (uint32_t imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
3956     {
3957         const float component = m_colorScheme[imageIdx % m_schemeSize];
3958 
3959         if (m_testParams.usesMipMaps)
3960         {
3961             const uint32_t mipCount = ut::computeMipMapCount(imageExtent);
3962             DE_ASSERT(mipCount >= 2);
3963             for (uint32_t mipIdx = 0; mipIdx < mipCount; ++mipIdx)
3964             {
3965                 pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos,
3966                                              variables.descriptorsBuffer, mipIdx);
3967                 tcu::clear(pixelAccess, m_clearColor);
3968             }
3969 
3970             pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos,
3971                                          variables.descriptorsBuffer, mipCount - 1);
3972             pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
3973         }
3974         else
3975         {
3976             pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos,
3977                                          variables.descriptorsBuffer, 0);
3978             pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
3979         }
3980     }
3981 
3982     vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
3983 }
3984 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)3985 void CombinedImageInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
3986 {
3987     DE_ASSERT(variables.unusedDescriptorSamplers.size() == 0);
3988     DE_ASSERT(variables.unusedDescriptorsImages.size() == 0);
3989     DE_ASSERT(variables.unusedDescriptorImageViews.size() == 0);
3990     DE_ASSERT(variables.unusedDescriptorsBufferInfos.size() == 0);
3991     DE_ASSERT(variables.unusedDescriptorSamplers.size() == 0);
3992 
3993     const tcu::Sampler sampler(
3994         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapS
3995         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapT
3996         tcu::Sampler::CLAMP_TO_BORDER,                                                           // wrapR
3997         m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // minFilter
3998         m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST, // magFilter
3999         0.0f,                                                                                    // lodTreshold
4000         true,                                                                                    // normalizeCoords
4001         tcu::Sampler::COMPAREMODE_NONE,                                                          // compare
4002         0,                                                                                       // compareChannel
4003         tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),                                                       // borderColor
4004         true);                                                                                   // seamlessCubeMap
4005     const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
4006     variables.unusedDescriptorSamplers.push_back(
4007         ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo))));
4008 
4009     const VkExtent3D &imageExtent = m_testParams.usesMipMaps ? bigImageExtent : smallImageExtent;
4010     createImages(variables.unusedDescriptorsImages, variables.unusedDescriptorsBufferInfos,
4011                  variables.unusedDescriptorsBuffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, imageExtent, m_colorFormat,
4012                  VK_IMAGE_LAYOUT_UNDEFINED, 1, m_testParams.usesMipMaps);
4013     createImagesViews(variables.unusedDescriptorImageViews, variables.unusedDescriptorsImages, m_colorFormat);
4014 }
4015 
4016 class StorageImageInstance : public CommonDescriptorInstance
4017 {
4018 public:
4019     StorageImageInstance(Context &context, const TestCaseParams &testCaseParams);
4020 
4021 private:
4022     tcu::TestStatus iterate(void) override;
4023     void createAndPopulateDescriptors(IterateCommonVariables &variables) override;
4024     void createAndPopulateUnusedDescriptors(IterateCommonVariables &variables) override;
4025     void updateDescriptors(IterateCommonVariables &variables) override;
4026     void iterateCollectResults(ut::UpdatablePixelBufferAccessPtr &result, const IterateCommonVariables &variables,
4027                                bool fromTest) override;
4028     ut::BufferHandleAllocSp m_buffer;
4029     const uint32_t m_fillColor;
4030     typedef uint32_t m_imageFormat_t;
4031 };
4032 
StorageImageInstance(Context & context,const TestCaseParams & testCaseParams)4033 StorageImageInstance::StorageImageInstance(Context &context, const TestCaseParams &testCaseParams)
4034     : CommonDescriptorInstance(context, TestParams(VK_SHADER_STAGE_COMPUTE_BIT, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
4035                                                    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, true,
4036                                                    performWritesInVertex(testCaseParams.descriptorType, context),
4037                                                    testCaseParams))
4038     , m_buffer()
4039     , m_fillColor(10)
4040 {
4041 }
4042 
updateDescriptors(IterateCommonVariables & variables)4043 void StorageImageInstance::updateDescriptors(IterateCommonVariables &variables)
4044 {
4045     // update image at last index
4046     {
4047         VkDescriptorImageInfo imageInfo = {static_cast<VkSampler>(0),
4048                                            **variables.descriptorImageViews[variables.validDescriptorCount],
4049                                            VK_IMAGE_LAYOUT_GENERAL};
4050 
4051         const VkWriteDescriptorSet writeInfo = {
4052             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
4053             nullptr,                                // pNext
4054             *variables.descriptorSet,               // descriptorSet
4055             BINDING_Additional,                     // descriptorBinding;
4056             0,                                      // elementIndex
4057             1u,                                     // descriptorCount
4058             m_testParams.additionalDescriptorType,  // descriptorType
4059             &imageInfo,                             // pImageInfo
4060             nullptr,                                // pBufferInfo
4061             nullptr                                 // pTexelBufferView
4062         };
4063 
4064         m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, nullptr);
4065     }
4066 
4067     // update rest images
4068     CommonDescriptorInstance::updateDescriptors(variables);
4069 }
4070 
createAndPopulateDescriptors(IterateCommonVariables & variables)4071 void StorageImageInstance::createAndPopulateDescriptors(IterateCommonVariables &variables)
4072 {
4073     const VkFormat imageFormat = ut::mapType2vkFormat<m_imageFormat_t>::value;
4074     const VkBufferUsageFlags bufferUsage =
4075         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4076 
4077     // create descriptor buffer, images and views
4078     {
4079         const VkExtent3D imageExtent = {4, 4, 1};
4080 
4081         createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
4082                      bufferUsage, imageExtent, imageFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount);
4083 
4084         for (uint32_t imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
4085         {
4086             const PixelBufferAccess pa = getPixelAccess(imageIdx, imageExtent, imageFormat,
4087                                                         variables.descriptorsBufferInfos, variables.descriptorsBuffer);
4088             tcu::clear(pa, tcu::UVec4(m_fillColor));
4089         }
4090         vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
4091     }
4092 
4093     // create additional image that will be used as index container
4094     {
4095         createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, m_buffer, bufferUsage,
4096                      m_testParams.frameResolution, imageFormat, VK_IMAGE_LAYOUT_UNDEFINED, 1);
4097 
4098         // populate buffer
4099         const std::vector<uint32_t> primes = ut::generatePrimes(variables.availableDescriptorCount);
4100         const PixelBufferAccess pa = getPixelAccess(variables.validDescriptorCount, m_testParams.frameResolution,
4101                                                     imageFormat, variables.descriptorsBufferInfos, m_buffer);
4102         for (uint32_t y = 0, pixel = 0; y < m_testParams.frameResolution.height; ++y)
4103         {
4104             for (uint32_t x = 0; x < m_testParams.frameResolution.width; ++x, ++pixel)
4105             {
4106                 const uint32_t component = primes[pixel % variables.validDescriptorCount];
4107                 pa.setPixel(tcu::UVec4(component), x, y);
4108             }
4109         }
4110 
4111         // save changes
4112         vk::flushAlloc(m_vki, m_vkd, *m_buffer->alloc);
4113     }
4114 
4115     // create views for all previously created images
4116     createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, imageFormat);
4117 }
4118 
createAndPopulateUnusedDescriptors(IterateCommonVariables & variables)4119 void StorageImageInstance::createAndPopulateUnusedDescriptors(IterateCommonVariables &variables)
4120 {
4121     const VkFormat imageFormat = ut::mapType2vkFormat<m_imageFormat_t>::value;
4122     const VkBufferUsageFlags bufferUsage =
4123         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4124     const VkExtent3D imageExtent = {4, 4, 1};
4125 
4126     createImages(variables.unusedDescriptorsImages, variables.unusedDescriptorsBufferInfos,
4127                  variables.unusedDescriptorsBuffer, bufferUsage, imageExtent, imageFormat, VK_IMAGE_LAYOUT_UNDEFINED,
4128                  1);
4129     createImagesViews(variables.unusedDescriptorImageViews, variables.unusedDescriptorsImages, imageFormat);
4130 }
4131 
iterate(void)4132 tcu::TestStatus StorageImageInstance::iterate(void)
4133 {
4134     IterateCommonVariables v;
4135     iterateCommandSetup(v);
4136     iterateCommandBegin(v);
4137 
4138     ut::UpdatablePixelBufferAccessPtr programResult;
4139     ut::UpdatablePixelBufferAccessPtr referenceResult;
4140 
4141     if (m_testParams.updateAfterBind)
4142     {
4143         updateDescriptors(v);
4144     }
4145 
4146     copyBuffersToImages(v);
4147 
4148     m_vki.cmdDispatch(*v.commandBuffer,
4149                       m_testParams.calculateInLoop ?
4150                           1 :
4151                           (v.renderArea.extent.width / (m_testParams.minNonUniform ? 1u : kMinWorkGroupSize)),
4152                       m_testParams.calculateInLoop ? 1 : v.renderArea.extent.height, 1);
4153 
4154     copyImagesToBuffers(v);
4155 
4156     iterateCommandEnd(v, programResult, referenceResult, false);
4157 
4158     if (iterateVerifyResults(v, programResult, referenceResult))
4159         return tcu::TestStatus::pass("Pass");
4160     return tcu::TestStatus::fail("Failed -- check log for details");
4161 }
4162 
iterateCollectResults(ut::UpdatablePixelBufferAccessPtr & result,const IterateCommonVariables & variables,bool fromTest)4163 void StorageImageInstance::iterateCollectResults(ut::UpdatablePixelBufferAccessPtr &result,
4164                                                  const IterateCommonVariables &variables, bool fromTest)
4165 {
4166     result                       = ut::UpdatablePixelBufferAccessPtr(new ut::PixelBufferAccessAllocation(
4167         vk::mapVkFormat(ut::mapType2vkFormat<m_imageFormat_t>::value), m_testParams.frameResolution));
4168     const PixelBufferAccess &dst = *result.get();
4169 
4170     if (fromTest)
4171     {
4172         vk::invalidateAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
4173         for (uint32_t y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y)
4174         {
4175             for (uint32_t x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum)
4176             {
4177                 const uint32_t imageIdx = pixelNum % variables.validDescriptorCount;
4178                 const PixelBufferAccess src =
4179                     getPixelAccess(imageIdx, variables.descriptorsImages[imageIdx]->extent,
4180                                    variables.descriptorsImages[imageIdx]->format, variables.descriptorsBufferInfos,
4181                                    variables.descriptorsBuffer);
4182                 dst.setPixel(tcu::Vector<m_imageFormat_t, 4>(src.getPixelT<m_imageFormat_t>(0, 0).x()), x, y);
4183             }
4184         }
4185     }
4186     else
4187     {
4188         std::vector<m_imageFormat_t> inc(variables.validDescriptorCount, m_fillColor);
4189 
4190         for (uint32_t invIdx = variables.lowerBound; invIdx < variables.upperBound; ++invIdx)
4191         {
4192             ++inc[invIdx % variables.validDescriptorCount];
4193         }
4194 
4195         for (uint32_t invIdx = 0; invIdx < variables.vertexCount; ++invIdx)
4196         {
4197             const uint32_t row          = invIdx / m_testParams.frameResolution.width;
4198             const uint32_t col          = invIdx % m_testParams.frameResolution.width;
4199             const m_imageFormat_t color = inc[invIdx % variables.validDescriptorCount];
4200             dst.setPixel(tcu::Vector<m_imageFormat_t, 4>(color), col, row);
4201         }
4202     }
4203 }
4204 
4205 class DescriptorIndexingTestCase : public TestCase
4206 {
4207     const TestCaseParams m_testCaseParams;
4208 
4209 public:
DescriptorIndexingTestCase(tcu::TestContext & context,const char * name,const TestCaseParams & testCaseParams)4210     DescriptorIndexingTestCase(tcu::TestContext &context, const char *name, const TestCaseParams &testCaseParams)
4211         : TestCase(context, name)
4212         , m_testCaseParams(testCaseParams)
4213     {
4214     }
4215 
createInstance(vkt::Context & context) const4216     vkt::TestInstance *createInstance(vkt::Context &context) const // override
4217     {
4218         switch (m_testCaseParams.descriptorType)
4219         {
4220         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
4221             return new StorageBufferInstance(context, m_testCaseParams);
4222         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
4223             return new UniformBufferInstance(context, m_testCaseParams);
4224         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
4225             return new StorageTexelInstance(context, m_testCaseParams);
4226         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
4227             return new UniformTexelInstance(context, m_testCaseParams);
4228         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
4229             return new DynamicStorageBufferInstance(context, m_testCaseParams);
4230         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
4231             return new DynamicUniformBufferInstance(context, m_testCaseParams);
4232         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
4233             return new InputAttachmentInstance(context, m_testCaseParams);
4234         case VK_DESCRIPTOR_TYPE_SAMPLER:
4235             return new SamplerInstance(context, m_testCaseParams);
4236         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
4237             return new SampledImageInstance(context, m_testCaseParams);
4238         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
4239             return new CombinedImageInstance(context, m_testCaseParams);
4240         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
4241             return new StorageImageInstance(context, m_testCaseParams);
4242         default:
4243             TCU_THROW(InternalError, "Unknown Descriptor Type");
4244         }
4245         return nullptr;
4246     }
4247 
checkSupport(vkt::Context & context) const4248     virtual void checkSupport(vkt::Context &context) const
4249     {
4250         const vk::VkPhysicalDeviceDescriptorIndexingFeatures &feats = context.getDescriptorIndexingFeatures();
4251 
4252         if (!feats.runtimeDescriptorArray)
4253             TCU_THROW(NotSupportedError, "runtimeDescriptorArray not supported");
4254 
4255         switch (m_testCaseParams.descriptorType)
4256         {
4257         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
4258             if (!(feats.shaderStorageBufferArrayNonUniformIndexing))
4259                 TCU_THROW(NotSupportedError,
4260                           "Non-uniform indexing over storage buffer descriptor arrays is not supported.");
4261 
4262             if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingStorageBufferUpdateAfterBind)
4263                 TCU_THROW(NotSupportedError, "Update after bind for storage buffer descriptors is not supported.");
4264             break;
4265         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
4266             if (!(feats.shaderUniformBufferArrayNonUniformIndexing))
4267                 TCU_THROW(NotSupportedError,
4268                           "Non-uniform indexing for uniform buffer descriptor arrays is not supported.");
4269 
4270             if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingUniformBufferUpdateAfterBind)
4271                 TCU_THROW(NotSupportedError, "Update after bind for uniform buffer descriptors is not supported.");
4272             break;
4273         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
4274             if (!(feats.shaderStorageTexelBufferArrayNonUniformIndexing))
4275                 TCU_THROW(NotSupportedError,
4276                           "Non-uniform indexing for storage texel buffer descriptor arrays is not supported.");
4277 
4278             if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingStorageTexelBufferUpdateAfterBind)
4279                 TCU_THROW(NotSupportedError,
4280                           "Update after bind for storage texel buffer descriptors is not supported.");
4281             break;
4282         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
4283             if (!(feats.shaderUniformTexelBufferArrayNonUniformIndexing))
4284                 TCU_THROW(NotSupportedError,
4285                           "Non-uniform indexing for uniform texel buffer descriptor arrays is not supported.");
4286 
4287             if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingUniformTexelBufferUpdateAfterBind)
4288                 TCU_THROW(NotSupportedError,
4289                           "Update after bind for uniform texel buffer descriptors is not supported.");
4290             break;
4291         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
4292             if (!(feats.shaderStorageBufferArrayNonUniformIndexing))
4293                 TCU_THROW(NotSupportedError,
4294                           "Non-uniform indexing over storage buffer dynamic descriptor arrays is not supported.");
4295 
4296             if (m_testCaseParams.updateAfterBind)
4297                 TCU_THROW(NotSupportedError,
4298                           "Update after bind for storage buffer dynamic descriptors is not supported.");
4299             break;
4300         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
4301             if (!(feats.shaderUniformBufferArrayNonUniformIndexing))
4302                 TCU_THROW(NotSupportedError,
4303                           "Non-uniform indexing over uniform buffer dynamic descriptor arrays is not supported.");
4304 
4305             if (m_testCaseParams.updateAfterBind)
4306                 TCU_THROW(NotSupportedError,
4307                           "Update after bind for uniform buffer dynamic descriptors is not supported.");
4308             break;
4309         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
4310             if (!(feats.shaderInputAttachmentArrayNonUniformIndexing))
4311                 TCU_THROW(NotSupportedError,
4312                           "Non-uniform indexing over input attachment descriptor arrays is not supported.");
4313 
4314             if (m_testCaseParams.updateAfterBind)
4315                 TCU_THROW(NotSupportedError, "Update after bind for input attachment descriptors is not supported.");
4316             break;
4317         case VK_DESCRIPTOR_TYPE_SAMPLER:
4318             if (!(feats.shaderSampledImageArrayNonUniformIndexing))
4319                 TCU_THROW(NotSupportedError, "Non-uniform indexing over sampler descriptor arrays is not supported.");
4320 
4321             if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingSampledImageUpdateAfterBind)
4322                 TCU_THROW(NotSupportedError, "Update after bind for sampler descriptors is not supported.");
4323             break;
4324         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
4325             if (!(feats.shaderSampledImageArrayNonUniformIndexing))
4326                 TCU_THROW(NotSupportedError,
4327                           "Non-uniform indexing over sampled image descriptor arrays is not supported.");
4328 
4329             if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingSampledImageUpdateAfterBind)
4330                 TCU_THROW(NotSupportedError, "Update after bind for sampled image descriptors is not supported.");
4331             break;
4332         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
4333             if (!(feats.shaderSampledImageArrayNonUniformIndexing))
4334                 TCU_THROW(NotSupportedError,
4335                           "Non-uniform indexing over combined image sampler descriptor arrays is not supported.");
4336 
4337             if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingSampledImageUpdateAfterBind)
4338                 TCU_THROW(NotSupportedError,
4339                           "Update after bind for combined image sampler descriptors is not supported.");
4340             break;
4341         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
4342             if (!(feats.shaderStorageImageArrayNonUniformIndexing))
4343                 TCU_THROW(NotSupportedError,
4344                           "Non-uniform indexing over storage image descriptor arrays is not supported.");
4345 
4346             if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingStorageImageUpdateAfterBind)
4347                 TCU_THROW(NotSupportedError, "Update after bind for storage image descriptors is not supported.");
4348             break;
4349         default:
4350             DE_FATAL("Unknown Descriptor Type");
4351             break;
4352         }
4353     }
4354 
initAsmPrograms(SourceCollections & programCollection) const4355     void initAsmPrograms(SourceCollections &programCollection) const
4356     {
4357 
4358         std::string (*genShaderSource)(VkShaderStageFlagBits, const TestCaseParams &, bool) =
4359             &CommonDescriptorInstance::getShaderAsm;
4360 
4361         uint32_t vulkan_version        = VK_MAKE_API_VERSION(0, 1, 2, 0);
4362         vk::SpirvVersion spirv_version = vk::SPIRV_VERSION_1_4;
4363         vk::SpirVAsmBuildOptions asm_options(vulkan_version, spirv_version);
4364 
4365         if (VK_SHADER_STAGE_VERTEX_BIT & m_testCaseParams.stageFlags)
4366         {
4367             programCollection.spirvAsmSources.add(
4368                 ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams.descriptorType,
4369                                     m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop,
4370                                     m_testCaseParams.minNonUniform, false),
4371                 &asm_options)
4372                 << (*genShaderSource)(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams, false);
4373 
4374             if (CommonDescriptorInstance::performWritesInVertex(m_testCaseParams.descriptorType))
4375             {
4376                 programCollection.spirvAsmSources.add(
4377                     ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams.descriptorType,
4378                                         m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop,
4379                                         m_testCaseParams.minNonUniform, true),
4380                     &asm_options)
4381                     << (*genShaderSource)(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams, true);
4382             }
4383         }
4384         if (VK_SHADER_STAGE_FRAGMENT_BIT & m_testCaseParams.stageFlags)
4385         {
4386             programCollection.spirvAsmSources.add(
4387                 ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams.descriptorType,
4388                                     m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop,
4389                                     m_testCaseParams.minNonUniform, false),
4390                 &asm_options)
4391                 << (*genShaderSource)(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams, false);
4392 
4393             if (CommonDescriptorInstance::performWritesInVertex(m_testCaseParams.descriptorType))
4394             {
4395                 programCollection.spirvAsmSources.add(
4396                     ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams.descriptorType,
4397                                         m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop,
4398                                         m_testCaseParams.minNonUniform, true),
4399                     &asm_options)
4400                     << (*genShaderSource)(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams, true);
4401             }
4402         }
4403         if (VK_SHADER_STAGE_COMPUTE_BIT & m_testCaseParams.stageFlags)
4404         {
4405             programCollection.spirvAsmSources.add(
4406                 ut::buildShaderName(VK_SHADER_STAGE_COMPUTE_BIT, m_testCaseParams.descriptorType,
4407                                     m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop,
4408                                     m_testCaseParams.minNonUniform, false),
4409                 &asm_options)
4410                 << (*genShaderSource)(VK_SHADER_STAGE_COMPUTE_BIT, m_testCaseParams, false);
4411         }
4412     }
4413 
initPrograms(SourceCollections & programCollection) const4414     virtual void initPrograms(SourceCollections &programCollection) const
4415     {
4416         if (m_testCaseParams.minNonUniform)
4417         {
4418             initAsmPrograms(programCollection);
4419             return;
4420         }
4421 
4422         std::string (*genShaderSource)(VkShaderStageFlagBits, const TestCaseParams &, bool) =
4423             &CommonDescriptorInstance::getShaderSource;
4424 
4425         if (VK_SHADER_STAGE_VERTEX_BIT & m_testCaseParams.stageFlags)
4426         {
4427             programCollection.glslSources.add(ut::buildShaderName(
4428                 VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind,
4429                 m_testCaseParams.calculateInLoop, m_testCaseParams.minNonUniform, false))
4430                 << glu::VertexSource((*genShaderSource)(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams, false));
4431 
4432             if (CommonDescriptorInstance::performWritesInVertex(m_testCaseParams.descriptorType))
4433             {
4434                 programCollection.glslSources.add(ut::buildShaderName(
4435                     VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind,
4436                     m_testCaseParams.calculateInLoop, m_testCaseParams.minNonUniform, true))
4437                     << glu::VertexSource((*genShaderSource)(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams, true));
4438             }
4439         }
4440         if (VK_SHADER_STAGE_FRAGMENT_BIT & m_testCaseParams.stageFlags)
4441         {
4442             programCollection.glslSources.add(ut::buildShaderName(
4443                 VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind,
4444                 m_testCaseParams.calculateInLoop, m_testCaseParams.minNonUniform, false))
4445                 << glu::FragmentSource((*genShaderSource)(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams, false));
4446 
4447             if (CommonDescriptorInstance::performWritesInVertex(m_testCaseParams.descriptorType))
4448             {
4449                 programCollection.glslSources.add(ut::buildShaderName(
4450                     VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind,
4451                     m_testCaseParams.calculateInLoop, m_testCaseParams.minNonUniform, true))
4452                     << glu::FragmentSource((*genShaderSource)(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams, true));
4453             }
4454         }
4455         if (VK_SHADER_STAGE_COMPUTE_BIT & m_testCaseParams.stageFlags)
4456         {
4457             programCollection.glslSources.add(ut::buildShaderName(
4458                 VK_SHADER_STAGE_COMPUTE_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind,
4459                 m_testCaseParams.calculateInLoop, m_testCaseParams.minNonUniform, false))
4460                 << glu::ComputeSource((*genShaderSource)(VK_SHADER_STAGE_COMPUTE_BIT, m_testCaseParams, false));
4461         }
4462     }
4463 };
4464 
4465 } // namespace
4466 
descriptorTypeUsesMipmaps(VkDescriptorType t)4467 static bool descriptorTypeUsesMipmaps(VkDescriptorType t)
4468 {
4469     return t == VK_DESCRIPTOR_TYPE_SAMPLER || t == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
4470            t == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4471 }
4472 
descriptorTypeSupportsUpdateAfterBind(VkDescriptorType t)4473 static bool descriptorTypeSupportsUpdateAfterBind(VkDescriptorType t)
4474 {
4475     switch (t)
4476     {
4477     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
4478     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
4479     case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
4480     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
4481     case VK_DESCRIPTOR_TYPE_SAMPLER:
4482     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
4483     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
4484         return true;
4485     default:
4486         return false;
4487     }
4488 }
4489 
descriptorIndexingDescriptorSetsCreateTests(tcu::TestCaseGroup * group)4490 void descriptorIndexingDescriptorSetsCreateTests(tcu::TestCaseGroup *group)
4491 {
4492     struct TestCaseInfo
4493     {
4494         const char *name;
4495         VkDescriptorType descriptorType;
4496     };
4497 
4498     tcu::TestContext &context(group->getTestContext());
4499 
4500     TestCaseInfo casesAfterBindAndLoop[] = {
4501         {
4502             "storage_buffer",
4503             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
4504         },
4505         {
4506             "storage_texel_buffer",
4507             VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
4508         },
4509         {
4510             "uniform_texel_buffer",
4511             VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
4512         },
4513         {
4514             "storage_image",
4515             VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
4516         },
4517         {
4518             "sampler",
4519             VK_DESCRIPTOR_TYPE_SAMPLER,
4520         },
4521         {
4522             "sampled_image",
4523             VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
4524         },
4525         {
4526             "combined_image_sampler",
4527             VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
4528         },
4529         {
4530             "uniform_buffer",
4531             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
4532         },
4533         {
4534             "storage_buffer_dynamic",
4535             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
4536         },
4537         {
4538             "uniform_buffer_dynamic",
4539             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
4540         },
4541         {
4542             "input_attachment",
4543             VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
4544         },
4545     };
4546 
4547     for (int updateAfterBind = 0; updateAfterBind < 2; ++updateAfterBind)
4548     {
4549         for (int calculateInLoop = 0; calculateInLoop < 2; ++calculateInLoop)
4550         {
4551             for (int usesMipMaps = 0; usesMipMaps < 2; ++usesMipMaps)
4552             {
4553                 for (int lifetimeCheck = 0; lifetimeCheck < 2; ++lifetimeCheck)
4554                 {
4555                     for (uint32_t caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(casesAfterBindAndLoop); ++caseIdx)
4556                     {
4557                         TestCaseInfo &info(casesAfterBindAndLoop[caseIdx]);
4558 
4559                         if (updateAfterBind && !descriptorTypeSupportsUpdateAfterBind(info.descriptorType))
4560                             continue;
4561 
4562                         if (usesMipMaps && !descriptorTypeUsesMipmaps(info.descriptorType))
4563                             continue;
4564 
4565                         std::string caseName(info.name);
4566                         TestCaseParams params;
4567 
4568                         caseName += (updateAfterBind ? "_after_bind" : "");
4569                         caseName += (calculateInLoop ? "_in_loop" : "");
4570                         caseName += (usesMipMaps ? "_with_lod" : "");
4571                         caseName += (lifetimeCheck ? "_lifetime" : "");
4572 
4573                         params.descriptorType  = info.descriptorType;
4574                         params.stageFlags      = (info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
4575                                                      VK_SHADER_STAGE_COMPUTE_BIT :
4576                                                      (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
4577                         params.frameResolution = RESOLUTION;
4578                         params.updateAfterBind = updateAfterBind ? true : false;
4579                         params.calculateInLoop = calculateInLoop ? true : false;
4580                         params.usesMipMaps     = usesMipMaps ? true : false;
4581                         params.lifetimeCheck   = lifetimeCheck ? true : false;
4582                         params.minNonUniform   = false;
4583 
4584                         group->addChild(new DescriptorIndexingTestCase(context, caseName.c_str(), params));
4585                     }
4586                 }
4587             }
4588         }
4589     }
4590 
4591     // SPIR-V Asm Tests
4592     // Tests that have the minimum necessary NonUniform decorations.
4593     // sampler and sampled_image GLSL already have minimum NonUniform decorations.
4594 
4595     TestCaseInfo casesMinNonUniform[] = {
4596         {
4597             "storage_buffer",
4598             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
4599         },
4600         {
4601             "storage_texel_buffer",
4602             VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
4603         },
4604         {
4605             "uniform_texel_buffer",
4606             VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
4607         },
4608         {
4609             "uniform_buffer",
4610             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
4611         },
4612         {
4613             "combined_image_sampler",
4614             VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
4615         },
4616         {
4617             "storage_image",
4618             VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
4619         },
4620     };
4621 
4622     for (int usesMipMaps = 0; usesMipMaps < 2; ++usesMipMaps)
4623     {
4624         for (uint32_t caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(casesMinNonUniform); ++caseIdx)
4625         {
4626             TestCaseInfo &info(casesMinNonUniform[caseIdx]);
4627 
4628             if (usesMipMaps && !descriptorTypeUsesMipmaps(info.descriptorType))
4629                 continue;
4630 
4631             std::string caseName(info.name);
4632             TestCaseParams params;
4633 
4634             caseName += (usesMipMaps ? "_with_lod" : "");
4635             caseName += "_minNonUniform";
4636 
4637             params.descriptorType  = info.descriptorType;
4638             params.stageFlags      = (info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ?
4639                                          VK_SHADER_STAGE_COMPUTE_BIT :
4640                                          (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
4641             params.frameResolution = RESOLUTION;
4642             params.updateAfterBind = false;
4643             params.calculateInLoop = false;
4644             params.usesMipMaps     = usesMipMaps ? true : false;
4645             params.minNonUniform   = true;
4646 
4647             TestCase *tc = new DescriptorIndexingTestCase(context, caseName.c_str(), params);
4648             group->addChild(tc);
4649         }
4650     }
4651 }
4652 
4653 } // namespace DescriptorIndexing
4654 } // namespace vkt
4655