• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Google Inc.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests for descriptor copying
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktBindingDescriptorCopyTests.hpp"
26 
27 #include "vkBufferWithMemory.hpp"
28 #include "vkImageWithMemory.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vktTestGroupUtil.hpp"
36 #include "vktTestCase.hpp"
37 
38 #include "deDefs.h"
39 #include "deMath.h"
40 #include "deRandom.h"
41 #include "deSharedPtr.hpp"
42 #include "deString.h"
43 
44 #include "tcuTestCase.hpp"
45 #include "tcuTestLog.hpp"
46 
47 #include <string>
48 #include <sstream>
49 
50 namespace vkt
51 {
52 namespace BindingModel
53 {
54 namespace
55 {
56 using namespace vk;
57 using namespace std;
58 using tcu::Vec2;
59 using tcu::Vec4;
60 
61 enum PipelineType
62 {
63     PIPELINE_TYPE_COMPUTE  = 0,
64     PIPELINE_TYPE_GRAPHICS = 1
65 };
66 
67 struct DescriptorCopy
68 {
69     uint32_t srcSet;
70     uint32_t srcBinding;
71     uint32_t srcArrayElement;
72     uint32_t dstSet;
73     uint32_t dstBinding;
74     uint32_t dstArrayElement;
75     uint32_t descriptorCount;
76 };
77 
78 struct DescriptorData
79 {
80     vector<uint32_t> data; // The actual data. One element per dynamic offset.
81     bool written;          // Is the data written in descriptor update
82     bool copiedInto;       // Is the data being overwritten by a copy operation
83 };
84 
85 typedef de::SharedPtr<ImageWithMemory> ImageWithMemorySp;
86 typedef de::SharedPtr<Unique<VkImageView>> VkImageViewSp;
87 typedef de::SharedPtr<Unique<VkBufferView>> VkBufferViewSp;
88 typedef de::SharedPtr<Unique<VkSampler>> VkSamplerSp;
89 typedef de::SharedPtr<Unique<VkDescriptorSetLayout>> VkDescriptorSetLayoutSp;
90 
91 const tcu::IVec2 renderSize(64, 64);
92 
93 // Base class for descriptors
94 class Descriptor
95 {
96 public:
97     Descriptor(VkDescriptorType descriptorType, uint32_t arraySize = 1u, uint32_t writeStart = 0u,
98                uint32_t elementsToWrite = 1u, uint32_t numDynamicAreas = 1u);
99     virtual ~Descriptor(void);
getType(void) const100     VkDescriptorType getType(void) const
101     {
102         return m_descriptorType;
103     }
getArraySize(void) const104     uint32_t getArraySize(void) const
105     {
106         return m_arraySize;
107     }
108     virtual VkWriteDescriptorSet getDescriptorWrite(void)          = 0;
109     virtual string getShaderDeclaration(void) const                = 0;
110     virtual void init(Context &context, PipelineType pipelineType) = 0;
111     virtual void copyValue(const Descriptor &src, uint32_t srcElement, uint32_t dstElement, uint32_t numElements);
invalidate(Context & context)112     virtual void invalidate(Context &context)
113     {
114         DE_UNREF(context);
115     }
getData(void)116     virtual vector<uint32_t> getData(void)
117     {
118         DE_FATAL("Unexpected");
119         return vector<uint32_t>();
120     }
getId(void) const121     uint32_t getId(void) const
122     {
123         return m_id;
124     }
125     virtual string getShaderVerifyCode(void) const = 0;
126     string getArrayString(uint32_t index) const;
127     uint32_t getFirstWrittenElement(void) const;
128     uint32_t getNumWrittenElements(void) const;
getReferenceData(uint32_t arrayIdx,uint32_t dynamicAreaIdx=0) const129     uint32_t getReferenceData(uint32_t arrayIdx, uint32_t dynamicAreaIdx = 0) const
130     {
131         return m_data[arrayIdx].data[dynamicAreaIdx];
132     }
isDynamic(void) const133     virtual bool isDynamic(void) const
134     {
135         return false;
136     }
setDynamicAreas(vector<uint32_t> dynamicAreas)137     virtual void setDynamicAreas(vector<uint32_t> dynamicAreas)
138     {
139         DE_UNREF(dynamicAreas);
140     }
getImageViews(void) const141     virtual vector<VkImageViewSp> getImageViews(void) const
142     {
143         return vector<VkImageViewSp>();
144     }
getAttachmentReferences(void) const145     virtual vector<VkAttachmentReference> getAttachmentReferences(void) const
146     {
147         return vector<VkAttachmentReference>();
148     }
149 
150     static uint32_t s_nextId;
151 
152 protected:
153     VkDescriptorType m_descriptorType;
154     uint32_t m_arraySize;
155     uint32_t m_id;
156     vector<DescriptorData> m_data;
157     uint32_t m_numDynamicAreas;
158 };
159 
160 typedef de::SharedPtr<Descriptor> DescriptorSp;
161 
162 // Base class for all buffer based descriptors
163 class BufferDescriptor : public Descriptor
164 {
165 public:
166     BufferDescriptor(VkDescriptorType type, uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
167                      uint32_t numDynamicAreas = 1u);
168     virtual ~BufferDescriptor(void);
169     void init(Context &context, PipelineType pipelineType);
170 
171     VkWriteDescriptorSet getDescriptorWrite(void);
172     virtual string getShaderDeclaration(void) const = 0;
173     void invalidate(Context &context);
174     vector<uint32_t> getData(void);
175     virtual string getShaderVerifyCode(void) const             = 0;
176     virtual VkBufferUsageFlags getBufferUsageFlags(void) const = 0;
usesBufferView(void)177     virtual bool usesBufferView(void)
178     {
179         return false;
180     }
181 
182 private:
183     vector<VkDescriptorBufferInfo> m_descriptorBufferInfos;
184     de::MovePtr<BufferWithMemory> m_buffer;
185     uint32_t m_bufferSize;
186     vector<VkBufferViewSp> m_bufferViews;
187     vector<VkBufferView> m_bufferViewHandles;
188 };
189 
190 #ifndef CTS_USES_VULKANSC
191 // Inline uniform block descriptor.
192 class InlineUniformBlockDescriptor : public Descriptor
193 {
194 public:
195     InlineUniformBlockDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
196                                  uint32_t numDynamicAreas = 1u);
197     virtual ~InlineUniformBlockDescriptor(void);
198     void init(Context &context, PipelineType pipelineType);
199 
200     VkWriteDescriptorSet getDescriptorWrite(void);
201     virtual string getShaderDeclaration(void) const;
202     virtual string getShaderVerifyCode(void) const;
usesBufferView(void)203     virtual bool usesBufferView(void)
204     {
205         return false;
206     }
getElementSizeInBytes(void) const207     uint32_t getElementSizeInBytes(void) const
208     {
209         return static_cast<uint32_t>(sizeof(decltype(m_blockData)::value_type));
210     }
getSizeInBytes(void) const211     uint32_t getSizeInBytes(void) const
212     {
213         return m_blockElements * getElementSizeInBytes();
214     }
215 
216 private:
217     // Inline uniform blocks cannot form arrays, so we will reuse the array size to create a data array inside the uniform block as
218     // an array of integers. However, with std140, each of those ints will be padded to 16 bytes in the shader. The struct below
219     // allows memory to match between the host and the shader.
220     struct PaddedUint
221     {
PaddedUintvkt::BindingModel::__anonbca3896c0111::InlineUniformBlockDescriptor::PaddedUint222         PaddedUint() : value(0)
223         {
224             deMemset(padding, 0, sizeof(padding));
225         }
PaddedUintvkt::BindingModel::__anonbca3896c0111::InlineUniformBlockDescriptor::PaddedUint226         PaddedUint(uint32_t value_) : value(value_)
227         {
228             deMemset(padding, 0, sizeof(padding));
229         }
operator =vkt::BindingModel::__anonbca3896c0111::InlineUniformBlockDescriptor::PaddedUint230         PaddedUint &operator=(uint32_t value_)
231         {
232             value = value_;
233             return *this;
234         }
235 
236         uint32_t value;
237         uint32_t padding[3];
238     };
239 
240     vector<PaddedUint> m_blockData;
241     VkWriteDescriptorSetInlineUniformBlockEXT m_inlineWrite;
242     uint32_t m_blockElements;
243     uint32_t m_writeStart;
244     uint32_t m_elementsToWrite;
245     uint32_t m_writeStartByteOffset;
246     uint32_t m_bytesToWrite;
247 };
248 #endif
249 
250 class UniformBufferDescriptor : public BufferDescriptor
251 {
252 public:
253     UniformBufferDescriptor(uint32_t arraySize = 1u, uint32_t writeStart = 0u, uint32_t elementsToWrite = 1u,
254                             uint32_t numDynamicAreas = 1u);
255     virtual ~UniformBufferDescriptor(void);
256 
257     string getShaderDeclaration(void) const;
258     string getShaderVerifyCode(void) const;
getBufferUsageFlags(void) const259     VkBufferUsageFlags getBufferUsageFlags(void) const
260     {
261         return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
262     }
263 
264 private:
265 };
266 
267 class DynamicUniformBufferDescriptor : public BufferDescriptor
268 {
269 public:
270     DynamicUniformBufferDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
271                                    uint32_t numDynamicAreas);
272     virtual ~DynamicUniformBufferDescriptor(void);
273 
274     string getShaderDeclaration(void) const;
275     string getShaderVerifyCode(void) const;
getBufferUsageFlags(void) const276     VkBufferUsageFlags getBufferUsageFlags(void) const
277     {
278         return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
279     }
setDynamicAreas(vector<uint32_t> dynamicAreas)280     virtual void setDynamicAreas(vector<uint32_t> dynamicAreas)
281     {
282         m_dynamicAreas = dynamicAreas;
283     }
isDynamic(void) const284     virtual bool isDynamic(void) const
285     {
286         return true;
287     }
288 
289 private:
290     vector<uint32_t> m_dynamicAreas;
291 };
292 
293 class StorageBufferDescriptor : public BufferDescriptor
294 {
295 public:
296     StorageBufferDescriptor(uint32_t arraySize = 1u, uint32_t writeStart = 0u, uint32_t elementsToWrite = 1u,
297                             uint32_t numDynamicAreas = 1u);
298     virtual ~StorageBufferDescriptor(void);
299 
300     string getShaderDeclaration(void) const;
301     string getShaderVerifyCode(void) const;
getBufferUsageFlags(void) const302     VkBufferUsageFlags getBufferUsageFlags(void) const
303     {
304         return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
305     }
306 
307 private:
308 };
309 
310 class DynamicStorageBufferDescriptor : public BufferDescriptor
311 {
312 public:
313     DynamicStorageBufferDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
314                                    uint32_t numDynamicAreas);
315     virtual ~DynamicStorageBufferDescriptor(void);
316 
317     string getShaderDeclaration(void) const;
318     string getShaderVerifyCode(void) const;
getBufferUsageFlags(void) const319     VkBufferUsageFlags getBufferUsageFlags(void) const
320     {
321         return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
322     }
setDynamicAreas(vector<uint32_t> dynamicAreas)323     virtual void setDynamicAreas(vector<uint32_t> dynamicAreas)
324     {
325         m_dynamicAreas = dynamicAreas;
326     }
isDynamic(void) const327     virtual bool isDynamic(void) const
328     {
329         return true;
330     }
331 
332 private:
333     vector<uint32_t> m_dynamicAreas;
334 };
335 
336 class UniformTexelBufferDescriptor : public BufferDescriptor
337 {
338 public:
339     UniformTexelBufferDescriptor(uint32_t arraySize = 1, uint32_t writeStart = 0, uint32_t elementsToWrite = 1,
340                                  uint32_t numDynamicAreas = 1);
341     virtual ~UniformTexelBufferDescriptor(void);
342 
343     string getShaderDeclaration(void) const;
344     string getShaderVerifyCode(void) const;
getBufferUsageFlags(void) const345     VkBufferUsageFlags getBufferUsageFlags(void) const
346     {
347         return VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
348     }
usesBufferView(void)349     bool usesBufferView(void)
350     {
351         return true;
352     }
353 
354 private:
355 };
356 
357 class StorageTexelBufferDescriptor : public BufferDescriptor
358 {
359 public:
360     StorageTexelBufferDescriptor(uint32_t arraySize = 1u, uint32_t writeStart = 0u, uint32_t elementsToWrite = 1u,
361                                  uint32_t numDynamicAreas = 1u);
362     virtual ~StorageTexelBufferDescriptor(void);
363 
364     string getShaderDeclaration(void) const;
365     string getShaderVerifyCode(void) const;
getBufferUsageFlags(void) const366     VkBufferUsageFlags getBufferUsageFlags(void) const
367     {
368         return VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
369     }
usesBufferView(void)370     bool usesBufferView(void)
371     {
372         return true;
373     }
374 
375 private:
376 };
377 
378 // Base class for all image based descriptors
379 class ImageDescriptor : public Descriptor
380 {
381 public:
382     ImageDescriptor(VkDescriptorType type, uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
383                     uint32_t numDynamicAreas);
384     virtual ~ImageDescriptor(void);
385     void init(Context &context, PipelineType pipelineType);
386 
387     VkWriteDescriptorSet getDescriptorWrite(void);
388     virtual VkImageUsageFlags getImageUsageFlags(void) const = 0;
389     virtual string getShaderDeclaration(void) const          = 0;
390     virtual string getShaderVerifyCode(void) const           = 0;
getAccessFlags(void) const391     virtual VkAccessFlags getAccessFlags(void) const
392     {
393         return VK_ACCESS_SHADER_READ_BIT;
394     }
getImageLayout(void) const395     virtual VkImageLayout getImageLayout(void) const
396     {
397         return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
398     }
399 
400 protected:
401     vector<VkImageViewSp> m_imageViews;
402 
403 private:
404     vector<ImageWithMemorySp> m_images;
405     vector<VkDescriptorImageInfo> m_descriptorImageInfos;
406     Move<VkSampler> m_sampler;
407 };
408 
409 class InputAttachmentDescriptor : public ImageDescriptor
410 {
411 public:
412     InputAttachmentDescriptor(uint32_t arraySize = 1u, uint32_t writeStart = 0u, uint32_t elementsToWrite = 1u,
413                               uint32_t numDynamicAreas = 1u);
414     virtual ~InputAttachmentDescriptor(void);
415 
getImageUsageFlags(void) const416     VkImageUsageFlags getImageUsageFlags(void) const
417     {
418         return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
419     }
420     string getShaderDeclaration(void) const;
421     string getShaderVerifyCode(void) const;
getImageViews(void) const422     vector<VkImageViewSp> getImageViews(void) const
423     {
424         return m_imageViews;
425     }
426     void copyValue(const Descriptor &src, uint32_t srcElement, uint32_t dstElement, uint32_t numElements);
getAccessFlags(void) const427     VkAccessFlags getAccessFlags(void) const
428     {
429         return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
430     }
431     vector<VkAttachmentReference> getAttachmentReferences(void) const;
432     static uint32_t s_nextAttachmentIndex;
433 
434 private:
435     vector<uint32_t> m_attachmentIndices;
436     uint32_t m_originalAttachmentIndex;
437 };
438 
439 class CombinedImageSamplerDescriptor : public ImageDescriptor
440 {
441 public:
442     CombinedImageSamplerDescriptor(uint32_t arraySize = 1u, uint32_t writeStart = 0u, uint32_t elementsToWrite = 1u,
443                                    uint32_t numDynamicAreas = 1u);
444     virtual ~CombinedImageSamplerDescriptor(void);
445 
getImageUsageFlags(void) const446     VkImageUsageFlags getImageUsageFlags(void) const
447     {
448         return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
449     }
450     string getShaderDeclaration(void) const;
451     string getShaderVerifyCode(void) const;
452 
453 private:
454 };
455 
456 class SamplerDescriptor;
457 
458 class SampledImageDescriptor : public ImageDescriptor
459 {
460 public:
461     SampledImageDescriptor(uint32_t arraySize = 1u, uint32_t writeStart = 0u, uint32_t elementsToWrite = 1u,
462                            uint32_t numDynamicAreas = 1u);
463     virtual ~SampledImageDescriptor(void);
464 
getImageUsageFlags(void) const465     VkImageUsageFlags getImageUsageFlags(void) const
466     {
467         return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
468     }
469     string getShaderDeclaration(void) const;
470     string getShaderVerifyCode(void) const;
addSampler(SamplerDescriptor * sampler,uint32_t count=1u)471     void addSampler(SamplerDescriptor *sampler, uint32_t count = 1u)
472     {
473         for (uint32_t i = 0; i < count; i++)
474             m_samplers.push_back(sampler);
475     }
476 
477 private:
478     vector<SamplerDescriptor *> m_samplers;
479 };
480 
481 class SamplerDescriptor : public Descriptor
482 {
483 public:
484     SamplerDescriptor(uint32_t arraySize = 1u, uint32_t writeStart = 0u, uint32_t elementsToWrite = 1u,
485                       uint32_t numDynamicAreas = 1u);
486     virtual ~SamplerDescriptor(void);
487     void init(Context &context, PipelineType pipelineType);
488 
addImage(SampledImageDescriptor * image,uint32_t count=1u)489     void addImage(SampledImageDescriptor *image, uint32_t count = 1u)
490     {
491         for (uint32_t i = 0; i < count; i++)
492             m_images.push_back(image);
493     }
494     VkWriteDescriptorSet getDescriptorWrite(void);
495     string getShaderDeclaration(void) const;
496     string getShaderVerifyCode(void) const;
497 
498 private:
499     vector<VkSamplerSp> m_samplers;
500     vector<VkDescriptorImageInfo> m_descriptorImageInfos;
501     vector<SampledImageDescriptor *> m_images;
502 };
503 
504 class StorageImageDescriptor : public ImageDescriptor
505 {
506 public:
507     StorageImageDescriptor(uint32_t arraySize = 1u, uint32_t writeStart = 0u, uint32_t elementsToWrite = 1u,
508                            uint32_t numDynamicAreas = 1u);
509     virtual ~StorageImageDescriptor(void);
510 
getImageUsageFlags(void) const511     VkImageUsageFlags getImageUsageFlags(void) const
512     {
513         return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
514     }
515     string getShaderDeclaration(void) const;
516     string getShaderVerifyCode(void) const;
getImageLayout(void) const517     VkImageLayout getImageLayout(void) const
518     {
519         return VK_IMAGE_LAYOUT_GENERAL;
520     }
521 
522 private:
523 };
524 
525 class DescriptorSet
526 {
527 public:
528     DescriptorSet(void);
529     ~DescriptorSet(void);
530     void addBinding(DescriptorSp descriptor);
getBindings(void) const531     const vector<DescriptorSp> getBindings(void) const
532     {
533         return m_bindings;
534     }
535 
536 private:
537     vector<DescriptorSp> m_bindings;
538 };
539 
540 typedef de::SharedPtr<DescriptorSet> DescriptorSetSp;
541 
542 // Class that handles descriptor sets and descriptors bound to those sets. Keeps track of copy operations.
543 class DescriptorCommands
544 {
545 public:
546     DescriptorCommands(PipelineType pipelineType, bool useUpdateAfterBind);
547     ~DescriptorCommands(void);
548     void addDescriptor(DescriptorSp descriptor, uint32_t descriptorSet);
549     void copyDescriptor(uint32_t srcSet, uint32_t srcBinding, uint32_t srcArrayElement, uint32_t dstSet,
550                         uint32_t dstBinding, uint32_t dstArrayElement, uint32_t descriptorCount);
copyDescriptor(uint32_t srcSet,uint32_t srcBinding,uint32_t dstSet,uint32_t dstBinding)551     void copyDescriptor(uint32_t srcSet, uint32_t srcBinding, uint32_t dstSet, uint32_t dstBinding)
552     {
553         copyDescriptor(srcSet, srcBinding, 0u, dstSet, dstBinding, 0u, 1u);
554     }
555     string getShaderDeclarations(void) const;
556     string getDescriptorVerifications(void) const;
557     void addResultBuffer(void);
getResultBufferId(void) const558     uint32_t getResultBufferId(void) const
559     {
560         return m_resultBuffer->getId();
561     }
562     void setDynamicAreas(vector<uint32_t> areas);
563     bool hasDynamicAreas(void) const;
getPipelineType(void) const564     PipelineType getPipelineType(void) const
565     {
566         return m_pipelineType;
567     }
568 
569     void checkSupport(Context &context) const;
570     tcu::TestStatus run(Context &context);
571 
572 protected:
573     void updateDescriptorSets(Context &context, const vector<VkDescriptorSet> &descriptorSets);
574 
575 private:
576     PipelineType m_pipelineType;
577     bool m_useUpdateAfterBind;
578     vector<DescriptorSetSp> m_descriptorSets;
579     vector<DescriptorCopy> m_descriptorCopies;
580     vector<DescriptorSp> m_descriptors;
581     map<VkDescriptorType, uint32_t> m_descriptorCounts;
582     DescriptorSp m_resultBuffer;
583     vector<uint32_t> m_dynamicAreas;
584 };
585 
586 typedef de::SharedPtr<DescriptorCommands> DescriptorCommandsSp;
587 
588 class DescriptorCopyTestInstance : public TestInstance
589 {
590 public:
591     DescriptorCopyTestInstance(Context &context, DescriptorCommandsSp commands);
592     ~DescriptorCopyTestInstance(void);
593     tcu::TestStatus iterate(void);
594 
595 private:
596     DescriptorCommandsSp m_commands;
597 };
598 
599 class DescriptorCopyTestCase : public TestCase
600 {
601 public:
602     DescriptorCopyTestCase(tcu::TestContext &context, const char *name, DescriptorCommandsSp commands);
603     virtual ~DescriptorCopyTestCase(void);
604     virtual void initPrograms(SourceCollections &programCollection) const;
605     virtual TestInstance *createInstance(Context &context) const;
606     void checkSupport(Context &context) const;
607 
608 private:
609     mutable DescriptorCommandsSp m_commands;
610 };
611 
612 uint32_t Descriptor::s_nextId                             = 0xabc; // Random starting point for ID counter
613 uint32_t InputAttachmentDescriptor::s_nextAttachmentIndex = 0;
614 
Descriptor(VkDescriptorType descriptorType,uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)615 Descriptor::Descriptor(VkDescriptorType descriptorType, uint32_t arraySize, uint32_t writeStart,
616                        uint32_t elementsToWrite, uint32_t numDynamicAreas)
617     : m_descriptorType(descriptorType)
618     , m_arraySize(arraySize)
619     , m_id(s_nextId++)
620     , m_numDynamicAreas(numDynamicAreas)
621 {
622     for (uint32_t arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
623     {
624         const bool written = arrayIdx >= writeStart && arrayIdx < writeStart + elementsToWrite;
625         vector<uint32_t> data;
626 
627         for (uint32_t dynamicAreaIdx = 0; dynamicAreaIdx < m_numDynamicAreas; dynamicAreaIdx++)
628             data.push_back(m_id + arrayIdx * m_numDynamicAreas + dynamicAreaIdx);
629 
630         const DescriptorData descriptorData = {
631             data,    // vector<uint32_t>    data
632             written, // bool                written
633             false    // bool                copiedInto
634         };
635 
636         m_data.push_back(descriptorData);
637     }
638 }
639 
~Descriptor(void)640 Descriptor::~Descriptor(void)
641 {
642 }
643 
644 // Copy refrence data from another descriptor
copyValue(const Descriptor & src,uint32_t srcElement,uint32_t dstElement,uint32_t numElements)645 void Descriptor::copyValue(const Descriptor &src, uint32_t srcElement, uint32_t dstElement, uint32_t numElements)
646 {
647     for (uint32_t elementIdx = 0; elementIdx < numElements; elementIdx++)
648     {
649         DE_ASSERT(src.m_data[elementIdx + srcElement].written);
650 
651         for (uint32_t dynamicAreaIdx = 0; dynamicAreaIdx < de::min(m_numDynamicAreas, src.m_numDynamicAreas);
652              dynamicAreaIdx++)
653             m_data[elementIdx + dstElement].data[dynamicAreaIdx] =
654                 src.m_data[elementIdx + srcElement].data[dynamicAreaIdx];
655 
656         m_data[elementIdx + dstElement].copiedInto = true;
657     }
658 }
659 
getArrayString(uint32_t index) const660 string Descriptor::getArrayString(uint32_t index) const
661 {
662     return m_arraySize > 1 ? (string("[") + de::toString(index) + "]") : "";
663 }
664 
665 // Returns the first element to be written in descriptor update
getFirstWrittenElement(void) const666 uint32_t Descriptor::getFirstWrittenElement(void) const
667 {
668     for (uint32_t i = 0; i < (uint32_t)m_data.size(); i++)
669         if (m_data[i].written)
670             return i;
671 
672     return 0;
673 }
674 
675 // Returns the number of array elements to be written for a descriptor array
getNumWrittenElements(void) const676 uint32_t Descriptor::getNumWrittenElements(void) const
677 {
678     uint32_t numElements = 0;
679 
680     for (uint32_t i = 0; i < (uint32_t)m_data.size(); i++)
681         if (m_data[i].written)
682             numElements++;
683 
684     return numElements;
685 }
686 
BufferDescriptor(VkDescriptorType type,uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)687 BufferDescriptor::BufferDescriptor(VkDescriptorType type, uint32_t arraySize, uint32_t writeStart,
688                                    uint32_t elementsToWrite, uint32_t numDynamicAreas)
689     : Descriptor(type, arraySize, writeStart, elementsToWrite, numDynamicAreas)
690     , m_bufferSize(256u * arraySize * numDynamicAreas)
691 {
692 }
693 
~BufferDescriptor(void)694 BufferDescriptor::~BufferDescriptor(void)
695 {
696 }
697 
init(Context & context,PipelineType pipelineType)698 void BufferDescriptor::init(Context &context, PipelineType pipelineType)
699 {
700     DE_UNREF(pipelineType);
701 
702     const DeviceInterface &vk = context.getDeviceInterface();
703     const VkDevice device     = context.getDevice();
704     Allocator &allocator      = context.getDefaultAllocator();
705 
706     // Create buffer
707     {
708         const VkBufferCreateInfo bufferCreateInfo = {
709             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType        sType
710             nullptr,                              // const void*            pNext
711             0u,                                   // VkBufferCreateFlags    flags
712             m_bufferSize,                         // VkDeviceSize            size
713             getBufferUsageFlags(),                // VkBufferUsageFlags    usage
714             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode        sharingMode
715             0u,                                   // uint32_t                queueFamilyIndexCount
716             nullptr                               // const uint32_t*        pQueueFamilyIndices
717         };
718 
719         m_buffer = de::MovePtr<BufferWithMemory>(
720             new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
721     }
722 
723     // Create descriptor buffer infos
724     {
725         for (uint32_t arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
726         {
727             const VkDescriptorBufferInfo bufferInfo = {
728                 m_buffer->get(),                     // VkBuffer        buffer
729                 256u * m_numDynamicAreas * arrayIdx, // VkDeviceSize    offset
730                 isDynamic() ? 256u : 4u              // VkDeviceSize    range
731             };
732 
733             m_descriptorBufferInfos.push_back(bufferInfo);
734         }
735     }
736 
737     // Create buffer views
738     if (usesBufferView())
739     {
740         for (uint32_t viewIdx = 0; viewIdx < m_arraySize; viewIdx++)
741         {
742             const VkBufferViewCreateInfo bufferViewCreateInfo = {
743                 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType            sType
744                 nullptr,                                   // const void*                pNext
745                 0u,                                        // VkBufferViewCreateFlags    flags
746                 m_buffer->get(),                           // VkBuffer                    buffer
747                 VK_FORMAT_R32_SFLOAT,                      // VkFormat                    format
748                 256u * viewIdx,                            // VkDeviceSize                offset
749                 4u                                         // VkDeviceSize                range
750             };
751 
752             m_bufferViews.push_back(
753                 VkBufferViewSp(new Unique<VkBufferView>(createBufferView(vk, device, &bufferViewCreateInfo))));
754             m_bufferViewHandles.push_back(**m_bufferViews[viewIdx]);
755         }
756     }
757 
758     // Initialize buffer memory
759     {
760         uint32_t *hostPtr = (uint32_t *)m_buffer->getAllocation().getHostPtr();
761 
762         for (uint32_t arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
763         {
764             for (uint32_t dynamicAreaIdx = 0; dynamicAreaIdx < m_numDynamicAreas; dynamicAreaIdx++)
765             {
766                 union BufferValue
767                 {
768                     uint32_t uintValue;
769                     float floatValue;
770                 } bufferValue;
771 
772                 bufferValue.uintValue = m_id + (arrayIdx * m_numDynamicAreas) + dynamicAreaIdx;
773 
774                 if (usesBufferView())
775                     bufferValue.floatValue = (float)bufferValue.uintValue;
776 
777                 hostPtr[(256 / 4) * (m_numDynamicAreas * arrayIdx + dynamicAreaIdx)] = bufferValue.uintValue;
778             }
779         }
780 
781         flushAlloc(vk, device, m_buffer->getAllocation());
782     }
783 }
784 
getDescriptorWrite(void)785 VkWriteDescriptorSet BufferDescriptor::getDescriptorWrite(void)
786 {
787     const uint32_t firstElement = getFirstWrittenElement();
788 
789     // Set and binding will be overwritten later
790     const VkWriteDescriptorSet descriptorWrite = {
791         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                    sType
792         nullptr,                                // const void*                        pNext
793         VK_NULL_HANDLE,                         // VkDescriptorSet                    dstSet
794         0u,                                     // uint32_t                            dstBinding
795         firstElement,                           // uint32_t                            dstArrayElement
796         getNumWrittenElements(),                // uint32_t                            descriptorCount
797         getType(),                              // VkDescriptorType                    descriptorType
798         nullptr,                                // const VkDescriptorImageInfo        pImageInfo
799         usesBufferView() ? nullptr :
800                            &m_descriptorBufferInfos[firstElement], // const VkDescriptorBufferInfo*    pBufferInfo
801         usesBufferView() ? &m_bufferViewHandles[firstElement] :
802                            nullptr // const VkBufferView*                pTexelBufferView
803     };
804 
805     return descriptorWrite;
806 }
807 
invalidate(Context & context)808 void BufferDescriptor::invalidate(Context &context)
809 {
810     const DeviceInterface &vk = context.getDeviceInterface();
811     const VkDevice device     = context.getDevice();
812 
813     invalidateAlloc(vk, device, m_buffer->getAllocation());
814 }
815 
816 // Returns the buffer data as a vector
getData(void)817 vector<uint32_t> BufferDescriptor::getData(void)
818 {
819     vector<uint32_t> data;
820     int32_t *hostPtr = (int32_t *)m_buffer->getAllocation().getHostPtr();
821 
822     for (uint32_t i = 0; i < m_arraySize; i++)
823         data.push_back(hostPtr[i]);
824 
825     return data;
826 }
827 
828 #ifndef CTS_USES_VULKANSC
829 // Inline Uniform Block descriptor. These are similar to uniform buffers, but they can't form arrays for spec reasons.
830 // The array size is reused, instead, as the size of a data array inside the uniform block.
InlineUniformBlockDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)831 InlineUniformBlockDescriptor::InlineUniformBlockDescriptor(uint32_t arraySize, uint32_t writeStart,
832                                                            uint32_t elementsToWrite, uint32_t numDynamicAreas)
833     : Descriptor(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, arraySize, writeStart, elementsToWrite, 1u)
834     , m_blockElements(arraySize)
835     , m_writeStart(writeStart)
836     , m_elementsToWrite(elementsToWrite)
837     , m_writeStartByteOffset(m_writeStart * getElementSizeInBytes())
838     , m_bytesToWrite(m_elementsToWrite * getElementSizeInBytes())
839 {
840     DE_UNREF(numDynamicAreas);
841 }
842 
~InlineUniformBlockDescriptor(void)843 InlineUniformBlockDescriptor::~InlineUniformBlockDescriptor(void)
844 {
845 }
846 
init(Context & context,PipelineType pipelineType)847 void InlineUniformBlockDescriptor::init(Context &context, PipelineType pipelineType)
848 {
849     DE_UNREF(context);
850     DE_UNREF(pipelineType);
851 
852     // Initialize host memory.
853     m_blockData.resize(m_blockElements);
854     for (uint32_t i = 0; i < m_blockElements; ++i)
855         m_blockData[i] = m_id + i;
856 
857     // Initialize descriptor write extension structure.
858     m_inlineWrite.sType    = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
859     m_inlineWrite.pNext    = nullptr;
860     m_inlineWrite.dataSize = m_bytesToWrite;
861     m_inlineWrite.pData    = &m_blockData[m_writeStart];
862 }
863 
getDescriptorWrite(void)864 VkWriteDescriptorSet InlineUniformBlockDescriptor::getDescriptorWrite(void)
865 {
866     // Set and binding will be overwritten later
867     const VkWriteDescriptorSet descriptorWrite = {
868         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                    sType
869         &m_inlineWrite,                         // const void*                        pNext
870         VK_NULL_HANDLE,                         // VkDescriptorSet                    dstSet
871         0u,                                     // uint32_t                            dstBinding
872         m_writeStartByteOffset,                 // uint32_t                            dstArrayElement
873         m_bytesToWrite,                         // uint32_t                            descriptorCount
874         getType(),                              // VkDescriptorType                    descriptorType
875         nullptr,                                // const VkDescriptorImageInfo        pImageInfo
876         nullptr,                                // const VkDescriptorBufferInfo*    pBufferInfo
877         nullptr                                 // const VkBufferView*                pTexelBufferView
878     };
879 
880     return descriptorWrite;
881 }
882 
getShaderDeclaration(void) const883 string InlineUniformBlockDescriptor::getShaderDeclaration(void) const
884 {
885     const string idStr = de::toString(m_id);
886     return string(") uniform InlineUniformBlock" + idStr +
887                   "\n"
888                   "{\n"
889                   "    int data" +
890                   getArrayString(m_arraySize) +
891                   ";\n"
892                   "} inlineUniformBlock" +
893                   idStr + ";\n");
894 }
895 
getShaderVerifyCode(void) const896 string InlineUniformBlockDescriptor::getShaderVerifyCode(void) const
897 {
898     const string idStr = de::toString(m_id);
899     string ret;
900 
901     for (uint32_t i = 0; i < m_arraySize; i++)
902     {
903         if (m_data[i].written || m_data[i].copiedInto)
904         {
905             ret += string("if (inlineUniformBlock") + idStr + ".data" + getArrayString(i) +
906                    " != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
907         }
908     }
909 
910     return ret;
911 }
912 #endif
913 
UniformBufferDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)914 UniformBufferDescriptor::UniformBufferDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
915                                                  uint32_t numDynamicAreas)
916     : BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, arraySize, writeStart, elementsToWrite, 1u)
917 {
918     DE_UNREF(numDynamicAreas);
919 }
920 
~UniformBufferDescriptor(void)921 UniformBufferDescriptor::~UniformBufferDescriptor(void)
922 {
923 }
924 
getShaderDeclaration(void) const925 string UniformBufferDescriptor::getShaderDeclaration(void) const
926 {
927     return string(") uniform UniformBuffer" + de::toString(m_id) +
928                   "\n"
929                   "{\n"
930                   "    int data;\n"
931                   "} uniformBuffer" +
932                   de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
933 }
934 
getShaderVerifyCode(void) const935 string UniformBufferDescriptor::getShaderVerifyCode(void) const
936 {
937     string ret;
938 
939     for (uint32_t i = 0; i < m_arraySize; i++)
940     {
941         if (m_data[i].written || m_data[i].copiedInto)
942             ret += string("if (uniformBuffer") + de::toString(m_id) + getArrayString(i) +
943                    ".data != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
944     }
945 
946     return ret;
947 }
948 
DynamicUniformBufferDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)949 DynamicUniformBufferDescriptor::DynamicUniformBufferDescriptor(uint32_t arraySize, uint32_t writeStart,
950                                                                uint32_t elementsToWrite, uint32_t numDynamicAreas)
951     : BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, arraySize, writeStart, elementsToWrite,
952                        numDynamicAreas)
953 {
954 }
955 
~DynamicUniformBufferDescriptor(void)956 DynamicUniformBufferDescriptor::~DynamicUniformBufferDescriptor(void)
957 {
958 }
959 
getShaderDeclaration(void) const960 string DynamicUniformBufferDescriptor::getShaderDeclaration(void) const
961 {
962     return string(") uniform UniformBuffer" + de::toString(m_id) +
963                   "\n"
964                   "{\n"
965                   "    int data;\n"
966                   "} dynamicUniformBuffer" +
967                   de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
968 }
969 
getShaderVerifyCode(void) const970 string DynamicUniformBufferDescriptor::getShaderVerifyCode(void) const
971 {
972     string ret;
973 
974     for (uint32_t arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
975     {
976         if (m_data[arrayIdx].written || m_data[arrayIdx].copiedInto)
977             ret += string("if (dynamicUniformBuffer") + de::toString(m_id) + getArrayString(arrayIdx) +
978                    ".data != " + de::toString(m_data[arrayIdx].data[m_dynamicAreas[arrayIdx]]) + ") result = 0;\n";
979     }
980 
981     return ret;
982 }
983 
StorageBufferDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)984 StorageBufferDescriptor::StorageBufferDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
985                                                  uint32_t numDynamicAreas)
986     : BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, arraySize, writeStart, elementsToWrite, 1u)
987 {
988     DE_UNREF(numDynamicAreas);
989 }
990 
~StorageBufferDescriptor(void)991 StorageBufferDescriptor::~StorageBufferDescriptor(void)
992 {
993 }
994 
getShaderDeclaration(void) const995 string StorageBufferDescriptor::getShaderDeclaration(void) const
996 {
997     return string(") buffer StorageBuffer" + de::toString(m_id) +
998                   "\n"
999                   "{\n"
1000                   "    int data;\n"
1001                   "} storageBuffer" +
1002                   de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1003 }
1004 
getShaderVerifyCode(void) const1005 string StorageBufferDescriptor::getShaderVerifyCode(void) const
1006 {
1007     string ret;
1008 
1009     for (uint32_t i = 0; i < m_arraySize; i++)
1010     {
1011         if (m_data[i].written || m_data[i].copiedInto)
1012             ret += string("if (storageBuffer") + de::toString(m_id) + getArrayString(i) +
1013                    ".data != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1014     }
1015 
1016     return ret;
1017 }
1018 
DynamicStorageBufferDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1019 DynamicStorageBufferDescriptor::DynamicStorageBufferDescriptor(uint32_t arraySize, uint32_t writeStart,
1020                                                                uint32_t elementsToWrite, uint32_t numDynamicAreas)
1021     : BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, arraySize, writeStart, elementsToWrite,
1022                        numDynamicAreas)
1023 {
1024 }
1025 
~DynamicStorageBufferDescriptor(void)1026 DynamicStorageBufferDescriptor::~DynamicStorageBufferDescriptor(void)
1027 {
1028 }
1029 
getShaderDeclaration(void) const1030 string DynamicStorageBufferDescriptor::getShaderDeclaration(void) const
1031 {
1032     return string(") buffer StorageBuffer" + de::toString(m_id) +
1033                   "\n"
1034                   "{\n"
1035                   "    int data;\n"
1036                   "} dynamicStorageBuffer" +
1037                   de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1038 }
1039 
getShaderVerifyCode(void) const1040 string DynamicStorageBufferDescriptor::getShaderVerifyCode(void) const
1041 {
1042     string ret;
1043 
1044     for (uint32_t arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
1045     {
1046         if (m_data[arrayIdx].written || m_data[arrayIdx].copiedInto)
1047             ret += string("if (dynamicStorageBuffer") + de::toString(m_id) + getArrayString(arrayIdx) +
1048                    ".data != " + de::toString(m_data[arrayIdx].data[m_dynamicAreas[arrayIdx]]) + ") result = 0;\n";
1049     }
1050 
1051     return ret;
1052 }
1053 
UniformTexelBufferDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1054 UniformTexelBufferDescriptor::UniformTexelBufferDescriptor(uint32_t arraySize, uint32_t writeStart,
1055                                                            uint32_t elementsToWrite, uint32_t numDynamicAreas)
1056     : BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, arraySize, writeStart, elementsToWrite, 1u)
1057 {
1058     DE_UNREF(numDynamicAreas);
1059 }
1060 
~UniformTexelBufferDescriptor(void)1061 UniformTexelBufferDescriptor::~UniformTexelBufferDescriptor(void)
1062 {
1063 }
1064 
getShaderDeclaration(void) const1065 string UniformTexelBufferDescriptor::getShaderDeclaration(void) const
1066 {
1067     return string(") uniform textureBuffer uniformTexelBuffer" + de::toString(m_id) + getArrayString(m_arraySize) +
1068                   ";\n");
1069 }
1070 
getShaderVerifyCode(void) const1071 string UniformTexelBufferDescriptor::getShaderVerifyCode(void) const
1072 {
1073     string ret;
1074 
1075     for (uint32_t i = 0; i < m_arraySize; i++)
1076     {
1077         if (m_data[i].written || m_data[i].copiedInto)
1078             ret += string("if (texelFetch(uniformTexelBuffer") + de::toString(m_id) + getArrayString(i) +
1079                    ", 0).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1080     }
1081 
1082     return ret;
1083 }
1084 
StorageTexelBufferDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1085 StorageTexelBufferDescriptor::StorageTexelBufferDescriptor(uint32_t arraySize, uint32_t writeStart,
1086                                                            uint32_t elementsToWrite, uint32_t numDynamicAreas)
1087     : BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, arraySize, writeStart, elementsToWrite, 1u)
1088 {
1089     DE_UNREF(numDynamicAreas);
1090 }
1091 
~StorageTexelBufferDescriptor(void)1092 StorageTexelBufferDescriptor::~StorageTexelBufferDescriptor(void)
1093 {
1094 }
1095 
getShaderDeclaration(void) const1096 string StorageTexelBufferDescriptor::getShaderDeclaration(void) const
1097 {
1098     return string(", r32f) uniform imageBuffer storageTexelBuffer" + de::toString(m_id) + getArrayString(m_arraySize) +
1099                   ";\n");
1100 }
1101 
getShaderVerifyCode(void) const1102 string StorageTexelBufferDescriptor::getShaderVerifyCode(void) const
1103 {
1104     string ret;
1105 
1106     for (uint32_t i = 0; i < m_arraySize; i++)
1107     {
1108         if (m_data[i].written || m_data[i].copiedInto)
1109             ret += string("if (imageLoad(storageTexelBuffer") + de::toString(m_id) + getArrayString(i) +
1110                    ", 0).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1111     }
1112 
1113     return ret;
1114 }
1115 
ImageDescriptor(VkDescriptorType type,uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1116 ImageDescriptor::ImageDescriptor(VkDescriptorType type, uint32_t arraySize, uint32_t writeStart,
1117                                  uint32_t elementsToWrite, uint32_t numDynamicAreas)
1118     : Descriptor(type, arraySize, writeStart, elementsToWrite, 1u)
1119 {
1120     DE_UNREF(numDynamicAreas);
1121 }
1122 
~ImageDescriptor(void)1123 ImageDescriptor::~ImageDescriptor(void)
1124 {
1125 }
1126 
init(Context & context,PipelineType pipelineType)1127 void ImageDescriptor::init(Context &context, PipelineType pipelineType)
1128 {
1129     const DeviceInterface &vk                 = context.getDeviceInterface();
1130     const VkDevice device                     = context.getDevice();
1131     Allocator &allocator                      = context.getDefaultAllocator();
1132     const VkQueue queue                       = context.getUniversalQueue();
1133     uint32_t queueFamilyIndex                 = context.getUniversalQueueFamilyIndex();
1134     const VkFormat format                     = VK_FORMAT_R32_SFLOAT;
1135     const VkComponentMapping componentMapping = makeComponentMappingRGBA();
1136 
1137     const VkImageSubresourceRange subresourceRange = {
1138         VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
1139         0u,                        // uint32_t                baseMipLevel
1140         1u,                        // uint32_t                levelCount
1141         0u,                        // uint32_t                baseArrayLayer
1142         1u,                        // uint32_t                layerCount
1143     };
1144 
1145     // Create sampler
1146     {
1147         const tcu::Sampler sampler =
1148             tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
1149                          tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
1150                          tcu::Vec4(0.0f), true);
1151         const tcu::TextureFormat texFormat      = mapVkFormat(format);
1152         const VkSamplerCreateInfo samplerParams = mapSampler(sampler, texFormat);
1153 
1154         m_sampler = createSampler(vk, device, &samplerParams);
1155     }
1156 
1157     // Create images
1158     for (uint32_t imageIdx = 0; imageIdx < m_arraySize; imageIdx++)
1159     {
1160         const VkImageCreateInfo imageCreateInfo = {
1161             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                     // VkStructureType            stype
1162             nullptr,                                                 // const void*                pNext
1163             0u,                                                      // VkImageCreateFlags        flags
1164             VK_IMAGE_TYPE_2D,                                        // VkImageType                imageType
1165             format,                                                  // VkFormat                    format
1166             {(uint32_t)renderSize.x(), (uint32_t)renderSize.y(), 1}, // VkExtent3D                extent
1167             1u,                                                      // uint32_t                    mipLevels
1168             1u,                                                      // uint32_t                    arrayLayers
1169             VK_SAMPLE_COUNT_1_BIT,                                   // VkSampleCountFlagBits    samples
1170             VK_IMAGE_TILING_OPTIMAL,                                 // VkImageTiling            tiling
1171             getImageUsageFlags(),                                    // VkImageUsageFlags        usage
1172             VK_SHARING_MODE_EXCLUSIVE,                               // VkSharingMode            sharingMode
1173             1u,                        // uint32_t                    queueFamilyIndexCount
1174             &queueFamilyIndex,         // const uint32_t*            pQueueFamilyIndices
1175             VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout            initialLayout
1176         };
1177 
1178         m_images.push_back(
1179             ImageWithMemorySp(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any)));
1180     }
1181 
1182     // Create image views
1183     for (uint32_t imageIdx = 0; imageIdx < m_arraySize; imageIdx++)
1184     {
1185         const VkImageViewCreateInfo imageViewCreateInfo = {
1186             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
1187             nullptr,                                  // const void*                pNext
1188             0u,                                       // VkImageViewCreateFlags    flags
1189             **m_images[imageIdx],                     // VkImage                    image
1190             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType            viewType
1191             format,                                   // VkFormat                    format
1192             componentMapping,                         // VkComponentMapping        components
1193             subresourceRange                          // VkImageSubresourceRange    subresourceRange
1194         };
1195 
1196         m_imageViews.push_back(
1197             VkImageViewSp(new Unique<VkImageView>(createImageView(vk, device, &imageViewCreateInfo))));
1198     }
1199 
1200     // Create descriptor image infos
1201     {
1202         for (uint32_t i = 0; i < m_arraySize; i++)
1203         {
1204             const VkDescriptorImageInfo imageInfo = {
1205                 *m_sampler,        // VkSampler        sampler
1206                 **m_imageViews[i], // VkImageView        imageView
1207                 getImageLayout()   // VkImageLayout    imageLayout
1208             };
1209 
1210             m_descriptorImageInfos.push_back(imageInfo);
1211         }
1212     }
1213 
1214     // Clear images to reference value
1215     for (uint32_t imageIdx = 0; imageIdx < m_arraySize; imageIdx++)
1216     {
1217         const Unique<VkCommandPool> cmdPool(
1218             createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
1219         const Unique<VkCommandBuffer> cmdBuffer(
1220             allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1221 
1222         const float clearValue        = (float)(m_id + imageIdx);
1223         const VkClearValue clearColor = makeClearValueColorF32(clearValue, clearValue, clearValue, clearValue);
1224 
1225         const VkImageMemoryBarrier preImageBarrier = {
1226             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType
1227             nullptr,                                // const void*                pNext
1228             0u,                                     // VkAccessFlags            srcAccessMask
1229             VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags            dstAccessMask
1230             VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout            oldLayout
1231             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout            newLayout
1232             queueFamilyIndex,                       // uint32_t                    srcQueueFamilyIndex
1233             queueFamilyIndex,                       // uint32_t                    dstQueueFamilyIndex
1234             **m_images[imageIdx],                   // VkImage                    image
1235             subresourceRange                        // VkImageSubresourceRange    subresourceRange
1236         };
1237 
1238         const VkImageMemoryBarrier postImageBarrier = {
1239             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType
1240             nullptr,                                // const void*                pNext
1241             VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags            srcAccessMask
1242             getAccessFlags(),                       // VkAccessFlags            dstAccessMask
1243             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout            oldLayout
1244             getImageLayout(),                       // VkImageLayout            newLayout
1245             queueFamilyIndex,                       // uint32_t                    srcQueueFamilyIndex
1246             queueFamilyIndex,                       // uint32_t                    dstQueueFamilyIndex
1247             **m_images[imageIdx],                   // VkImage                    image
1248             subresourceRange                        // VkImageSubresourceRange    subresourceRange
1249         };
1250 
1251         beginCommandBuffer(vk, *cmdBuffer);
1252         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1253                               (VkDependencyFlags)0u, 0u, nullptr, 0u, nullptr, 1u, &preImageBarrier);
1254         vk.cmdClearColorImage(*cmdBuffer, **m_images[imageIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color,
1255                               1, &subresourceRange);
1256         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1257                               pipelineType == PIPELINE_TYPE_COMPUTE ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT :
1258                                                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1259                               (VkDependencyFlags)0u, 0u, nullptr, 0u, nullptr, 1u, &postImageBarrier);
1260         endCommandBuffer(vk, *cmdBuffer);
1261         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1262     }
1263 }
1264 
getDescriptorWrite(void)1265 VkWriteDescriptorSet ImageDescriptor::getDescriptorWrite(void)
1266 {
1267     const uint32_t firstElement = getFirstWrittenElement();
1268 
1269     // Set and binding will be overwritten later
1270     const VkWriteDescriptorSet descriptorWrite = {
1271         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                    sType
1272         nullptr,                                // const void*                        pNext
1273         VK_NULL_HANDLE,                         // VkDescriptorSet                    dstSet
1274         0u,                                     // uint32_t                            dstBinding
1275         firstElement,                           // uint32_t                            dstArrayElement
1276         getNumWrittenElements(),                // uint32_t                            descriptorCount
1277         getType(),                              // VkDescriptorType                    descriptorType
1278         &m_descriptorImageInfos[firstElement],  // const VkDescriptorImageInfo        pImageInfo
1279         nullptr,                                // const VkDescriptorBufferInfo*    pBufferInfo
1280         nullptr                                 // const VkBufferView*                pTexelBufferView
1281     };
1282 
1283     return descriptorWrite;
1284 }
1285 
InputAttachmentDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1286 InputAttachmentDescriptor::InputAttachmentDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
1287                                                      uint32_t numDynamicAreas)
1288     : ImageDescriptor(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, arraySize, writeStart, elementsToWrite, 1u)
1289     , m_originalAttachmentIndex(s_nextAttachmentIndex)
1290 {
1291     DE_UNREF(numDynamicAreas);
1292 
1293     for (uint32_t i = 0; i < m_arraySize; i++)
1294         m_attachmentIndices.push_back(s_nextAttachmentIndex++);
1295 }
1296 
~InputAttachmentDescriptor(void)1297 InputAttachmentDescriptor::~InputAttachmentDescriptor(void)
1298 {
1299 }
1300 
getShaderDeclaration(void) const1301 string InputAttachmentDescriptor::getShaderDeclaration(void) const
1302 {
1303     return string(", input_attachment_index=" + de::toString(m_originalAttachmentIndex) +
1304                   ") uniform subpassInput inputAttachment" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1305 }
1306 
getShaderVerifyCode(void) const1307 string InputAttachmentDescriptor::getShaderVerifyCode(void) const
1308 {
1309     string ret;
1310 
1311     for (uint32_t i = 0; i < m_arraySize; i++)
1312     {
1313         if (m_data[i].written || m_data[i].copiedInto)
1314             ret += string("if (subpassLoad(inputAttachment") + de::toString(m_id) + getArrayString(i) +
1315                    ").x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1316     }
1317 
1318     return ret;
1319 }
1320 
copyValue(const Descriptor & src,uint32_t srcElement,uint32_t dstElement,uint32_t numElements)1321 void InputAttachmentDescriptor::copyValue(const Descriptor &src, uint32_t srcElement, uint32_t dstElement,
1322                                           uint32_t numElements)
1323 {
1324     Descriptor::copyValue(src, srcElement, dstElement, numElements);
1325 
1326     for (uint32_t elementIdx = 0; elementIdx < numElements; elementIdx++)
1327     {
1328         m_attachmentIndices[elementIdx + dstElement] =
1329             reinterpret_cast<const InputAttachmentDescriptor &>(src).m_attachmentIndices[elementIdx + srcElement];
1330     }
1331 }
1332 
getAttachmentReferences(void) const1333 vector<VkAttachmentReference> InputAttachmentDescriptor::getAttachmentReferences(void) const
1334 {
1335     vector<VkAttachmentReference> references;
1336     for (uint32_t i = 0; i < m_arraySize; i++)
1337     {
1338         const VkAttachmentReference attachmentReference = {
1339             // The first attachment is the color buffer, thus +1
1340             m_attachmentIndices[i] + 1, // uint32_t            attachment
1341             getImageLayout()            // VkImageLayout    layout
1342         };
1343 
1344         references.push_back(attachmentReference);
1345     }
1346 
1347     return references;
1348 }
1349 
CombinedImageSamplerDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1350 CombinedImageSamplerDescriptor::CombinedImageSamplerDescriptor(uint32_t arraySize, uint32_t writeStart,
1351                                                                uint32_t elementsToWrite, uint32_t numDynamicAreas)
1352     : ImageDescriptor(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize, writeStart, elementsToWrite, 1u)
1353 {
1354     DE_UNREF(numDynamicAreas);
1355 }
1356 
~CombinedImageSamplerDescriptor(void)1357 CombinedImageSamplerDescriptor::~CombinedImageSamplerDescriptor(void)
1358 {
1359 }
1360 
getShaderDeclaration(void) const1361 string CombinedImageSamplerDescriptor::getShaderDeclaration(void) const
1362 {
1363     return string(") uniform sampler2D texSampler" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1364 }
1365 
getShaderVerifyCode(void) const1366 string CombinedImageSamplerDescriptor::getShaderVerifyCode(void) const
1367 {
1368     string ret;
1369 
1370     for (uint32_t i = 0; i < m_arraySize; i++)
1371     {
1372         if (m_data[i].written || m_data[i].copiedInto)
1373             ret += string("if (texture(texSampler") + de::toString(m_id) + getArrayString(i) +
1374                    ", vec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1375     }
1376 
1377     return ret;
1378 }
1379 
SampledImageDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1380 SampledImageDescriptor::SampledImageDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
1381                                                uint32_t numDynamicAreas)
1382     : ImageDescriptor(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, arraySize, writeStart, elementsToWrite, 1u)
1383 {
1384     DE_UNREF(numDynamicAreas);
1385 }
1386 
~SampledImageDescriptor(void)1387 SampledImageDescriptor::~SampledImageDescriptor(void)
1388 {
1389 }
1390 
getShaderDeclaration(void) const1391 string SampledImageDescriptor::getShaderDeclaration(void) const
1392 {
1393     return string(") uniform texture2D sampledImage" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1394 }
1395 
getShaderVerifyCode(void) const1396 string SampledImageDescriptor::getShaderVerifyCode(void) const
1397 {
1398     string ret;
1399 
1400     for (uint32_t i = 0; i < m_arraySize; i++)
1401     {
1402         if ((m_data[i].written || m_data[i].copiedInto) && m_samplers.size() > i)
1403         {
1404             ret += string("if (texture(sampler2D(sampledImage") + de::toString(m_id) + getArrayString(i) + ", sampler" +
1405                    de::toString(m_samplers[i]->getId()) + "), vec2(0)).x != " + de::toString(m_data[i].data[0]) +
1406                    ") result = 0;\n";
1407         }
1408     }
1409 
1410     return ret;
1411 }
1412 
StorageImageDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1413 StorageImageDescriptor::StorageImageDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
1414                                                uint32_t numDynamicAreas)
1415     : ImageDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize, writeStart, elementsToWrite, 1u)
1416 {
1417     DE_UNREF(numDynamicAreas);
1418 }
1419 
~StorageImageDescriptor(void)1420 StorageImageDescriptor::~StorageImageDescriptor(void)
1421 {
1422 }
1423 
getShaderDeclaration(void) const1424 string StorageImageDescriptor::getShaderDeclaration(void) const
1425 {
1426     return string(", r32f) readonly uniform image2D image" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1427 }
1428 
getShaderVerifyCode(void) const1429 string StorageImageDescriptor::getShaderVerifyCode(void) const
1430 {
1431     string ret;
1432 
1433     for (uint32_t i = 0; i < m_arraySize; i++)
1434     {
1435         if (m_data[i].written || m_data[i].copiedInto)
1436             ret += string("if (imageLoad(image") + de::toString(m_id) + getArrayString(i) +
1437                    ", ivec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1438     }
1439 
1440     return ret;
1441 }
1442 
SamplerDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1443 SamplerDescriptor::SamplerDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
1444                                      uint32_t numDynamicAreas)
1445     : Descriptor(VK_DESCRIPTOR_TYPE_SAMPLER, arraySize, writeStart, elementsToWrite, 1u)
1446 {
1447     DE_UNREF(numDynamicAreas);
1448 }
1449 
~SamplerDescriptor(void)1450 SamplerDescriptor::~SamplerDescriptor(void)
1451 {
1452 }
1453 
init(Context & context,PipelineType pipelineType)1454 void SamplerDescriptor::init(Context &context, PipelineType pipelineType)
1455 {
1456     DE_UNREF(pipelineType);
1457 
1458     const DeviceInterface &vk = context.getDeviceInterface();
1459     const VkDevice device     = context.getDevice();
1460     const VkFormat format     = VK_FORMAT_R32_SFLOAT;
1461 
1462     // Create samplers
1463     for (uint32_t i = 0; i < m_arraySize; i++)
1464     {
1465         const float borderValue = (float)((m_id + i) % 2);
1466         const tcu::Sampler sampler =
1467             tcu::Sampler(tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::CLAMP_TO_BORDER,
1468                          tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
1469                          Vec4(borderValue), true);
1470         const tcu::TextureFormat texFormat      = mapVkFormat(format);
1471         const VkSamplerCreateInfo samplerParams = mapSampler(sampler, texFormat);
1472 
1473         m_samplers.push_back(VkSamplerSp(new Unique<VkSampler>(createSampler(vk, device, &samplerParams))));
1474     }
1475 
1476     // Create descriptor image infos
1477     for (uint32_t i = 0; i < m_arraySize; i++)
1478     {
1479         const VkDescriptorImageInfo imageInfo = {
1480             **m_samplers[i],          // VkSampler        sampler
1481             VK_NULL_HANDLE,           // VkImageView        imageView
1482             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout    imageLayout
1483         };
1484 
1485         m_descriptorImageInfos.push_back(imageInfo);
1486     }
1487 }
1488 
getDescriptorWrite(void)1489 VkWriteDescriptorSet SamplerDescriptor::getDescriptorWrite(void)
1490 {
1491     const uint32_t firstElement = getFirstWrittenElement();
1492 
1493     // Set and binding will be overwritten later
1494     const VkWriteDescriptorSet descriptorWrite = {
1495         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                    sType
1496         nullptr,                                // const void*                        pNext
1497         VK_NULL_HANDLE,                         // VkDescriptorSet                    dstSet
1498         0u,                                     // uint32_t                            dstBinding
1499         firstElement,                           // uint32_t                            dstArrayElement
1500         getNumWrittenElements(),                // uint32_t                            descriptorCount
1501         getType(),                              // VkDescriptorType                    descriptorType
1502         &m_descriptorImageInfos[firstElement],  // const VkDescriptorImageInfo        pImageInfo
1503         nullptr,                                // const VkDescriptorBufferInfo*    pBufferInfo
1504         nullptr                                 // const VkBufferView*                pTexelBufferView
1505     };
1506 
1507     return descriptorWrite;
1508 }
1509 
getShaderDeclaration(void) const1510 string SamplerDescriptor::getShaderDeclaration(void) const
1511 {
1512     return string(") uniform sampler sampler" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1513 }
1514 
getShaderVerifyCode(void) const1515 string SamplerDescriptor::getShaderVerifyCode(void) const
1516 {
1517     string ret;
1518 
1519     for (uint32_t i = 0; i < m_arraySize; i++)
1520     {
1521         if ((m_data[i].written || m_data[i].copiedInto) && m_images.size() > i)
1522         {
1523             // Sample from (-1, -1) to get border color.
1524             ret += string("if (texture(sampler2D(sampledImage") + de::toString(m_images[i]->getId()) + ", sampler" +
1525                    de::toString(m_id) + getArrayString(i) + "), vec2(-1)).x != " + de::toString(m_data[i].data[0] % 2) +
1526                    ") result = 0;\n";
1527         }
1528     }
1529 
1530     return ret;
1531 }
1532 
DescriptorSet(void)1533 DescriptorSet::DescriptorSet(void)
1534 {
1535 }
1536 
~DescriptorSet(void)1537 DescriptorSet::~DescriptorSet(void)
1538 {
1539 }
1540 
addBinding(DescriptorSp descriptor)1541 void DescriptorSet::addBinding(DescriptorSp descriptor)
1542 {
1543     m_bindings.push_back(descriptor);
1544 }
1545 
DescriptorCommands(PipelineType pipelineType,bool useUpdateAfterBind)1546 DescriptorCommands::DescriptorCommands(PipelineType pipelineType, bool useUpdateAfterBind)
1547     : m_pipelineType(pipelineType)
1548     , m_useUpdateAfterBind(useUpdateAfterBind)
1549 {
1550     // Reset counters
1551     Descriptor::s_nextId                             = 0xabc;
1552     InputAttachmentDescriptor::s_nextAttachmentIndex = 0;
1553 }
1554 
~DescriptorCommands(void)1555 DescriptorCommands::~DescriptorCommands(void)
1556 {
1557 }
1558 
addDescriptor(DescriptorSp descriptor,uint32_t descriptorSet)1559 void DescriptorCommands::addDescriptor(DescriptorSp descriptor, uint32_t descriptorSet)
1560 {
1561     const VkDescriptorType type = descriptor->getType();
1562 
1563     // Create descriptor set objects until one with the given index exists
1564     while (m_descriptorSets.size() <= descriptorSet)
1565         m_descriptorSets.push_back(DescriptorSetSp(new DescriptorSet()));
1566 
1567     m_descriptorSets[descriptorSet]->addBinding(descriptor);
1568 
1569     // Keep track of how many descriptors of each type is needed. Inline uniform blocks cannot form arrays. We reuse the array size
1570     // as size of the data array for them, within a single descriptor.
1571 
1572 #ifndef CTS_USES_VULKANSC
1573     const uint32_t count = ((type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) ? 1u : descriptor->getArraySize());
1574 #else
1575     const uint32_t count = descriptor->getArraySize();
1576 #endif
1577 
1578     if (m_descriptorCounts.find(type) != m_descriptorCounts.end())
1579         m_descriptorCounts[type] += count;
1580     else
1581         m_descriptorCounts[type] = count;
1582 
1583     // Keep descriptors also in a flat list for easier iteration
1584     m_descriptors.push_back(descriptor);
1585 }
1586 
copyDescriptor(uint32_t srcSet,uint32_t srcBinding,uint32_t srcArrayElement,uint32_t dstSet,uint32_t dstBinding,uint32_t dstArrayElement,uint32_t descriptorCount)1587 void DescriptorCommands::copyDescriptor(uint32_t srcSet, uint32_t srcBinding, uint32_t srcArrayElement, uint32_t dstSet,
1588                                         uint32_t dstBinding, uint32_t dstArrayElement, uint32_t descriptorCount)
1589 {
1590     // For inline uniform blocks, (src|dst)ArrayElement are data array indices and descriptorCount is the number of integers to copy.
1591     DescriptorCopy descriptorCopy = {srcSet,     srcBinding,      srcArrayElement, dstSet,
1592                                      dstBinding, dstArrayElement, descriptorCount};
1593 
1594 #ifndef CTS_USES_VULKANSC
1595     if (m_descriptorSets[srcSet]->getBindings()[srcBinding]->getType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1596     {
1597         // For inline uniform blocks, these members of VkCopyDescriptorSet are offsets and sizes in bytes.
1598         const InlineUniformBlockDescriptor *iub =
1599             static_cast<InlineUniformBlockDescriptor *>(m_descriptorSets[srcSet]->getBindings()[srcBinding].get());
1600         const uint32_t elementSize = iub->getElementSizeInBytes();
1601 
1602         descriptorCopy.srcArrayElement *= elementSize;
1603         descriptorCopy.dstArrayElement *= elementSize;
1604         descriptorCopy.descriptorCount *= elementSize;
1605     }
1606 #endif
1607 
1608     m_descriptorCopies.push_back(descriptorCopy);
1609     m_descriptorSets[descriptorCopy.dstSet]->getBindings()[descriptorCopy.dstBinding]->copyValue(
1610         *m_descriptorSets[descriptorCopy.srcSet]->getBindings()[descriptorCopy.srcBinding], srcArrayElement,
1611         dstArrayElement, descriptorCount);
1612 }
1613 
1614 // Generates shader source code for declarations of all descriptors
getShaderDeclarations(void) const1615 string DescriptorCommands::getShaderDeclarations(void) const
1616 {
1617     string ret;
1618 
1619     for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
1620     {
1621         const vector<DescriptorSp> bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
1622 
1623         for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
1624         {
1625             ret += "layout (set=" + de::toString(descriptorSetIdx) + ", binding=" + de::toString(bindingIdx) +
1626                    bindings[bindingIdx]->getShaderDeclaration();
1627         }
1628     }
1629 
1630     return ret;
1631 }
1632 
1633 // Generates shader source code for verification of all descriptor data
getDescriptorVerifications(void) const1634 string DescriptorCommands::getDescriptorVerifications(void) const
1635 {
1636     string ret;
1637 
1638     for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
1639     {
1640         const vector<DescriptorSp> bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
1641 
1642         for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
1643         {
1644             if (m_pipelineType == PIPELINE_TYPE_COMPUTE && descriptorSetIdx == 0 && bindingIdx == bindings.size() - 1)
1645                 continue; // Skip the result buffer which is always the last descriptor of set 0
1646             ret += bindings[bindingIdx]->getShaderVerifyCode();
1647         }
1648     }
1649 
1650     return ret;
1651 }
1652 
addResultBuffer(void)1653 void DescriptorCommands::addResultBuffer(void)
1654 {
1655     // Add result buffer if using compute pipeline
1656     if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
1657     {
1658         m_resultBuffer = DescriptorSp(new StorageBufferDescriptor());
1659         addDescriptor(m_resultBuffer, 0u);
1660     }
1661 }
1662 
1663 // Sets the list of dynamic areas selected for each dynamic descriptor when running the verification shader
setDynamicAreas(vector<uint32_t> areas)1664 void DescriptorCommands::setDynamicAreas(vector<uint32_t> areas)
1665 {
1666     m_dynamicAreas   = areas;
1667     uint32_t areaIdx = 0;
1668 
1669     for (vector<DescriptorSp>::iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
1670     {
1671         if ((*desc)->isDynamic())
1672         {
1673             vector<uint32_t> dynamicAreas;
1674 
1675             for (uint32_t elementIdx = 0; elementIdx < (*desc)->getArraySize(); elementIdx++)
1676                 dynamicAreas.push_back(areas[areaIdx++]);
1677 
1678             (*desc)->setDynamicAreas(dynamicAreas);
1679         }
1680     }
1681 }
1682 
hasDynamicAreas(void) const1683 bool DescriptorCommands::hasDynamicAreas(void) const
1684 {
1685     for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
1686         if ((*desc)->isDynamic())
1687             return true;
1688 
1689     return false;
1690 }
1691 
checkSupport(Context & context) const1692 void DescriptorCommands::checkSupport(Context &context) const
1693 {
1694     const InstanceInterface &vki          = context.getInstanceInterface();
1695     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1696     const VkPhysicalDeviceLimits limits   = getPhysicalDeviceProperties(vki, physicalDevice).limits;
1697 
1698     if (limits.maxBoundDescriptorSets <= m_descriptorSets.size())
1699         TCU_THROW(NotSupportedError, "Maximum bound descriptor sets limit exceeded.");
1700 
1701     if (m_useUpdateAfterBind)
1702         context.requireDeviceFunctionality("VK_EXT_descriptor_indexing");
1703 
1704 #ifndef CTS_USES_VULKANSC
1705     uint32_t numTotalIUBs = 0;
1706 
1707     // Check if inline uniform blocks are supported.
1708     VkPhysicalDeviceInlineUniformBlockFeaturesEXT iubFeatures{
1709         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT, nullptr, VK_FALSE, VK_FALSE};
1710     VkPhysicalDeviceInlineUniformBlockPropertiesEXT iubProperties{
1711         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT, nullptr, 0u, 0u, 0u, 0u, 0u};
1712 
1713     if (context.isDeviceFunctionalitySupported("VK_EXT_inline_uniform_block"))
1714     {
1715         VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&iubFeatures);
1716         vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1717 
1718         VkPhysicalDeviceProperties2 properties2 = initVulkanStructure(&iubProperties);
1719         vki.getPhysicalDeviceProperties2(physicalDevice, &properties2);
1720     }
1721 #endif
1722 
1723     // Check physical device limits of per stage and per desriptor set descriptor count
1724     {
1725         uint32_t numPerStageSamplers         = 0;
1726         uint32_t numPerStageUniformBuffers   = 0;
1727         uint32_t numPerStageStorageBuffers   = 0;
1728         uint32_t numPerStageSampledImages    = 0;
1729         uint32_t numPerStageStorageImages    = 0;
1730         uint32_t numPerStageInputAttachments = 0;
1731         uint32_t numPerStageTotalResources   = 0;
1732 
1733         bool usesUniformBuffer      = false;
1734         bool usesSampledImage       = false;
1735         bool usesStorageImage       = false;
1736         bool usesStorageBuffer      = false;
1737         bool usesUniformTexelBuffer = false;
1738         bool usesStorageTexelBuffer = false;
1739 
1740         for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
1741         {
1742             uint32_t numSamplers              = 0;
1743             uint32_t numUniformBuffers        = 0;
1744             uint32_t numUniformBuffersDynamic = 0;
1745             uint32_t numStorageBuffers        = 0;
1746             uint32_t numStorageBuffersDynamic = 0;
1747             uint32_t numSampledImages         = 0;
1748             uint32_t numStorageImages         = 0;
1749             uint32_t numInputAttachments      = 0;
1750             uint32_t numTotalResources =
1751                 m_pipelineType == PIPELINE_TYPE_GRAPHICS ? 1u : 0u; // Color buffer counts as a resource.
1752 
1753             const vector<DescriptorSp> &bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
1754 
1755             for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
1756             {
1757                 const uint32_t arraySize = bindings[bindingIdx]->getArraySize();
1758 
1759 #ifndef CTS_USES_VULKANSC
1760                 // Inline uniform blocks cannot form arrays. The array size is the size of the data array in the descriptor.
1761                 if (bindings[bindingIdx]->getType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1762                 {
1763                     const InlineUniformBlockDescriptor *iub =
1764                         static_cast<InlineUniformBlockDescriptor *>(bindings[bindingIdx].get());
1765                     const uint32_t bytes = iub->getSizeInBytes();
1766 
1767                     // Check inline uniform block size.
1768                     if (bytes > iubProperties.maxInlineUniformBlockSize)
1769                     {
1770                         std::ostringstream msg;
1771                         msg << "Maximum size for an inline uniform block exceeded by binding " << bindingIdx
1772                             << " from set " << descriptorSetIdx;
1773                         TCU_THROW(NotSupportedError, msg.str().c_str());
1774                     }
1775 
1776                     ++numTotalResources;
1777                 }
1778                 else
1779 #endif
1780                 {
1781                     numTotalResources += arraySize;
1782                 }
1783 
1784                 switch (bindings[bindingIdx]->getType())
1785                 {
1786                 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1787                     numUniformBuffers += arraySize;
1788                     usesUniformBuffer = true;
1789                     break;
1790 
1791                 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1792                     numUniformBuffers += arraySize;
1793                     numUniformBuffersDynamic += arraySize;
1794                     break;
1795 
1796                 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1797                     numStorageBuffers += arraySize;
1798                     usesStorageBuffer = true;
1799                     break;
1800 
1801                 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1802                     numStorageBuffers += arraySize;
1803                     numStorageBuffersDynamic += arraySize;
1804                     break;
1805 
1806                 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1807                     numSamplers += arraySize;
1808                     numSampledImages += arraySize;
1809                     usesSampledImage = true;
1810                     break;
1811 
1812                 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1813                     numStorageImages += arraySize;
1814                     usesStorageImage = true;
1815                     break;
1816 
1817                 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1818                     numStorageImages += arraySize;
1819                     usesStorageTexelBuffer = true;
1820                     break;
1821 
1822                 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1823                     numInputAttachments += arraySize;
1824                     break;
1825 
1826                 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1827                     numSampledImages += arraySize;
1828                     usesSampledImage = true;
1829                     break;
1830 
1831                 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1832                     numSampledImages += arraySize;
1833                     usesUniformTexelBuffer = true;
1834                     break;
1835 
1836                 case VK_DESCRIPTOR_TYPE_SAMPLER:
1837                     numSamplers += arraySize;
1838                     usesSampledImage = true;
1839                     break;
1840 
1841 #ifndef CTS_USES_VULKANSC
1842                 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
1843                     ++numTotalIUBs;
1844                     break;
1845 #endif
1846                 default:
1847                     DE_FATAL("Unexpected descriptor type");
1848                     break;
1849                 }
1850             }
1851 
1852             if (numSamplers > limits.maxDescriptorSetSamplers)
1853                 TCU_THROW(NotSupportedError, "Maximum per descriptor set sampler limit exceeded.");
1854 
1855             if (numUniformBuffers > limits.maxDescriptorSetUniformBuffers)
1856                 TCU_THROW(NotSupportedError, "Maximum per descriptor set uniform buffer limit exceeded.");
1857 
1858             if (numUniformBuffersDynamic > limits.maxDescriptorSetUniformBuffersDynamic)
1859                 TCU_THROW(NotSupportedError, "Maximum per descriptor set uniform buffer dynamic limit exceeded.");
1860 
1861             if (numStorageBuffers > limits.maxDescriptorSetStorageBuffers)
1862                 TCU_THROW(NotSupportedError, "Maximum per descriptor set storage buffer limit exceeded.");
1863 
1864             if (numStorageBuffersDynamic > limits.maxDescriptorSetStorageBuffersDynamic)
1865                 TCU_THROW(NotSupportedError, "Maximum per descriptor set storage buffer dynamic limit exceeded.");
1866 
1867             if (numSampledImages > limits.maxDescriptorSetSampledImages)
1868                 TCU_THROW(NotSupportedError, "Maximum per descriptor set sampled image limit exceeded.");
1869 
1870             if (numStorageImages > limits.maxDescriptorSetStorageImages)
1871                 TCU_THROW(NotSupportedError, "Maximum per descriptor set storage image limit exceeded.");
1872 
1873             if (numInputAttachments > limits.maxDescriptorSetInputAttachments)
1874                 TCU_THROW(NotSupportedError, "Maximum per descriptor set input attachment limit exceeded.");
1875 
1876             numPerStageSamplers += numSamplers;
1877             numPerStageUniformBuffers += numUniformBuffers;
1878             numPerStageStorageBuffers += numStorageBuffers;
1879             numPerStageSampledImages += numSampledImages;
1880             numPerStageStorageImages += numStorageImages;
1881             numPerStageInputAttachments += numInputAttachments;
1882             numPerStageTotalResources += numTotalResources;
1883         }
1884 
1885         if (numPerStageTotalResources > limits.maxPerStageResources)
1886             TCU_THROW(NotSupportedError, "Maximum per stage total resource limit exceeded.");
1887 
1888         if (numPerStageSamplers > limits.maxPerStageDescriptorSamplers)
1889             TCU_THROW(NotSupportedError, "Maximum per stage sampler limit exceeded.");
1890 
1891         if (numPerStageUniformBuffers > limits.maxPerStageDescriptorUniformBuffers)
1892             TCU_THROW(NotSupportedError, "Maximum per stage uniform buffer limit exceeded.");
1893 
1894         if (numPerStageStorageBuffers > limits.maxPerStageDescriptorStorageBuffers)
1895             TCU_THROW(NotSupportedError, "Maximum per stage storage buffer limit exceeded.");
1896 
1897         if (numPerStageSampledImages > limits.maxPerStageDescriptorSampledImages)
1898             TCU_THROW(NotSupportedError, "Maximum per stage sampled image limit exceeded.");
1899 
1900         if (numPerStageStorageImages > limits.maxPerStageDescriptorStorageImages)
1901             TCU_THROW(NotSupportedError, "Maximum per stage storage image limit exceeded.");
1902 
1903         if (numPerStageInputAttachments > limits.maxPerStageDescriptorInputAttachments)
1904             TCU_THROW(NotSupportedError, "Maximum per stage input attachment limit exceeded.");
1905 
1906 #ifndef CTS_USES_VULKANSC
1907         if (numTotalIUBs > iubProperties.maxDescriptorSetInlineUniformBlocks ||
1908             numTotalIUBs > iubProperties.maxPerStageDescriptorInlineUniformBlocks)
1909         {
1910             TCU_THROW(NotSupportedError, "Number of per stage inline uniform blocks exceeds limits.");
1911         }
1912 #endif
1913         if (m_useUpdateAfterBind)
1914         {
1915             if (usesUniformBuffer &&
1916                 !context.getDescriptorIndexingFeatures().descriptorBindingUniformBufferUpdateAfterBind)
1917                 TCU_THROW(NotSupportedError, "descriptorBindingUniformBufferUpdateAfterBind not supported.");
1918 
1919             if (usesSampledImage &&
1920                 !context.getDescriptorIndexingFeatures().descriptorBindingSampledImageUpdateAfterBind)
1921                 TCU_THROW(NotSupportedError, "descriptorBindingSampledImageUpdateAfterBind not supported.");
1922 
1923             if (usesStorageImage &&
1924                 !context.getDescriptorIndexingFeatures().descriptorBindingStorageImageUpdateAfterBind)
1925                 TCU_THROW(NotSupportedError, "descriptorBindingStorageImageUpdateAfterBind not supported.");
1926 
1927             if (usesStorageBuffer &&
1928                 !context.getDescriptorIndexingFeatures().descriptorBindingStorageBufferUpdateAfterBind)
1929                 TCU_THROW(NotSupportedError, "descriptorBindingStorageBufferUpdateAfterBind not supported.");
1930 
1931             if (usesUniformTexelBuffer &&
1932                 !context.getDescriptorIndexingFeatures().descriptorBindingUniformTexelBufferUpdateAfterBind)
1933                 TCU_THROW(NotSupportedError, "descriptorBindingUniformTexelBufferUpdateAfterBind not supported.");
1934 
1935             if (usesStorageTexelBuffer &&
1936                 !context.getDescriptorIndexingFeatures().descriptorBindingStorageTexelBufferUpdateAfterBind)
1937                 TCU_THROW(NotSupportedError, "descriptorBindingStorageTexelBufferUpdateAfterBind not supported.");
1938         }
1939     }
1940 }
1941 
run(Context & context)1942 tcu::TestStatus DescriptorCommands::run(Context &context)
1943 {
1944     const DeviceInterface &vk       = context.getDeviceInterface();
1945     const VkDevice device           = context.getDevice();
1946     const VkQueue queue             = context.getUniversalQueue();
1947     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1948     Allocator &allocator            = context.getDefaultAllocator();
1949     tcu::TestLog &log               = context.getTestContext().getLog();
1950     const Unique<VkCommandPool> commandPool(
1951         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
1952     const Unique<VkCommandBuffer> commandBuffer(
1953         allocateCommandBuffer(vk, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1954     const VkShaderStageFlags shaderStage =
1955         m_pipelineType == PIPELINE_TYPE_COMPUTE ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
1956     const VkFormat resultFormat = VK_FORMAT_R8G8B8A8_UNORM;
1957     de::MovePtr<ImageWithMemory> resultImage;
1958     de::MovePtr<BufferWithMemory> resultImageBuffer;
1959     Move<VkImageView> resultImageView;
1960     Move<VkRenderPass> renderPass;
1961     Move<VkFramebuffer> framebuffer;
1962     Move<VkDescriptorPool> descriptorPool;
1963     vector<VkDescriptorSetLayoutSp> descriptorSetLayouts;
1964     vector<VkDescriptorSet> descriptorSets;
1965     Move<VkPipelineLayout> pipelineLayout;
1966     Move<VkPipeline> pipeline;
1967     vector<VkAttachmentReference> inputAttachments;
1968     vector<VkAttachmentDescription> attachmentDescriptions;
1969     vector<VkImageView> imageViews;
1970 
1971     // Initialize all descriptors
1972     for (vector<DescriptorSp>::iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
1973         (*desc)->init(context, m_pipelineType);
1974 
1975     uint32_t numTotalIUBs                                           = 0;
1976     uint32_t iubTotalBytes                                          = 0;
1977     VkDescriptorPoolCreateFlags poolCreateFlags                     = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1978     VkDescriptorSetLayoutCreateFlags descriptorSetLayoutCreateFlags = 0u;
1979     VkDescriptorBindingFlags bindingFlag                            = 0u;
1980     if (m_useUpdateAfterBind)
1981     {
1982         poolCreateFlags |= VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT;
1983         descriptorSetLayoutCreateFlags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT;
1984         bindingFlag |= VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
1985     }
1986 
1987 #ifndef CTS_USES_VULKANSC
1988     for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
1989     {
1990         const vector<DescriptorSp> &bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
1991         for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
1992         {
1993             // Inline uniform blocks cannot form arrays. The array size is the size of the data array in the descriptor.
1994             if (bindings[bindingIdx]->getType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1995             {
1996                 const InlineUniformBlockDescriptor *iub =
1997                     static_cast<InlineUniformBlockDescriptor *>(bindings[bindingIdx].get());
1998                 iubTotalBytes += iub->getSizeInBytes();
1999 
2000                 ++numTotalIUBs;
2001             }
2002         }
2003     }
2004 #else
2005     DE_UNREF(numTotalIUBs);
2006     DE_UNREF(iubTotalBytes);
2007 #endif // CTS_USES_VULKANSC
2008 
2009     // Create descriptor pool
2010     {
2011         vector<VkDescriptorPoolSize> poolSizes;
2012 
2013         for (map<VkDescriptorType, uint32_t>::iterator i = m_descriptorCounts.begin(); i != m_descriptorCounts.end();
2014              i++)
2015         {
2016             VkDescriptorPoolSize poolSize = {
2017                 i->first, // VkDescriptorType    type
2018                 i->second // uint32_t            descriptorCount
2019             };
2020 
2021 #ifndef CTS_USES_VULKANSC
2022             // Inline uniform blocks have a special meaning for descriptorCount.
2023             if (poolSize.type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
2024                 poolSize.descriptorCount = iubTotalBytes;
2025 #endif
2026 
2027             poolSizes.push_back(poolSize);
2028         }
2029 
2030         VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {
2031             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType                sType
2032             nullptr,                                       // const void*                    pNext
2033             poolCreateFlags,                               // VkDescriptorPoolCreateFlags    flags
2034             (uint32_t)m_descriptorSets.size(),             // uint32_t                        maxSets
2035             (uint32_t)poolSizes.size(),                    // uint32_t                        poolSizeCount
2036             poolSizes.data(),                              // const VkDescriptorPoolSize*    pPoolSizes
2037         };
2038 
2039         // Include information about inline uniform blocks if needed.
2040 #ifndef CTS_USES_VULKANSC
2041         VkDescriptorPoolInlineUniformBlockCreateInfoEXT iubPoolCreateInfo = {
2042             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT, nullptr, numTotalIUBs};
2043         if (numTotalIUBs > 0)
2044             descriptorPoolCreateInfo.pNext = &iubPoolCreateInfo;
2045 #endif
2046 
2047         descriptorPool = createDescriptorPool(vk, device, &descriptorPoolCreateInfo);
2048     }
2049 
2050     // Create descriptor set layouts. One for each descriptor set used in this test.
2051     {
2052         for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
2053         {
2054             vector<VkDescriptorSetLayoutBinding> layoutBindings;
2055             const vector<DescriptorSp> &bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
2056             const vector<VkDescriptorBindingFlags> bindingsFlags(bindings.size(), bindingFlag);
2057 
2058             for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
2059             {
2060                 VkDescriptorSetLayoutBinding layoutBinding = {
2061                     (uint32_t)bindingIdx,                 // uint32_t                binding
2062                     bindings[bindingIdx]->getType(),      // VkDescriptorType        descriptorType
2063                     bindings[bindingIdx]->getArraySize(), // uint32_t                descriptorCount
2064                     shaderStage,                          // VkShaderStageFlags    stageFlags
2065                     nullptr                               // const VkSampler*        pImmutableSamplers
2066                 };
2067 
2068 #ifndef CTS_USES_VULKANSC
2069                 // Inline uniform blocks have a special meaning for descriptorCount.
2070                 if (layoutBinding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
2071                 {
2072                     const InlineUniformBlockDescriptor *iub =
2073                         static_cast<InlineUniformBlockDescriptor *>(bindings[bindingIdx].get());
2074                     layoutBinding.descriptorCount = iub->getSizeInBytes();
2075                 }
2076 #endif
2077                 layoutBindings.push_back(layoutBinding);
2078             }
2079 
2080             const VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo{
2081                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, // VkStructureType sType;
2082                 nullptr,                                                           // const void* pNext;
2083                 (uint32_t)layoutBindings.size(),                                   // uint32_t bindingCount;
2084                 layoutBindings.empty() ? nullptr :
2085                                          bindingsFlags.data(), // const VkDescriptorBindingFlags* pBindingFlags;
2086             };
2087 
2088             const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{
2089                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType
2090                 m_useUpdateAfterBind ? &bindingFlagsInfo : nullptr,  // const void*                            pNext
2091                 descriptorSetLayoutCreateFlags,                      // VkDescriptorSetLayoutCreateFlags        flags
2092                 (uint32_t)layoutBindings.size(), // uint32_t                                bindingCount
2093                 layoutBindings.data()            // const VkDescriptorSetLayoutBinding*    pBindings
2094             };
2095 
2096             descriptorSetLayouts.push_back(VkDescriptorSetLayoutSp(new Unique<VkDescriptorSetLayout>(
2097                 createDescriptorSetLayout(vk, device, &descriptorSetLayoutCreateInfo, nullptr))));
2098         }
2099     }
2100 
2101     // Create descriptor sets
2102     {
2103         for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
2104         {
2105             const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
2106                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,  // VkStructureType                sType
2107                 nullptr,                                         // const void*                    pNext
2108                 *descriptorPool,                                 // VkDescriptorPool                descriptorPool
2109                 1u,                                              // uint32_t                        descriptorSetCount
2110                 &(descriptorSetLayouts[descriptorSetIdx]->get()) // const VkDescriptorSetLayout*    pSetLayouts
2111             };
2112 
2113             VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
2114             VK_CHECK(vk.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet));
2115             descriptorSets.push_back(descriptorSet);
2116         }
2117     }
2118 
2119     // Update descriptor sets when this should be done before bind
2120     if (!m_useUpdateAfterBind)
2121         updateDescriptorSets(context, descriptorSets);
2122 
2123     // Create pipeline layout
2124     {
2125         vector<VkDescriptorSetLayout> descriptorSetLayoutHandles;
2126 
2127         for (size_t i = 0; i < descriptorSetLayouts.size(); i++)
2128             descriptorSetLayoutHandles.push_back(descriptorSetLayouts[i]->get());
2129 
2130         const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
2131             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType                sType
2132             nullptr,                                       // const void*                    pNext
2133             0u,                                            // VkPipelineLayoutCreateFlags    flags
2134             (uint32_t)descriptorSetLayoutHandles.size(),   // uint32_t                        setLayoutCount
2135             descriptorSetLayoutHandles.data(),             // const VkDescriptorSetLayout*    pSetLayouts
2136             0u,                                            // uint32_t                        pushConstantRangeCount
2137             nullptr                                        // const VkPushConstantRange*    pPushConstantRanges
2138         };
2139 
2140         pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
2141     }
2142 
2143     if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
2144     {
2145         // Create compute pipeline
2146         {
2147             const Unique<VkShaderModule> shaderModule(
2148                 createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
2149             const VkPipelineShaderStageCreateInfo shaderStageInfo = {
2150                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                    sType
2151                 nullptr,                                             // const void*                        pNext
2152                 (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags    flags
2153                 VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits            stage
2154                 *shaderModule,                                       // VkShaderModule                    module
2155                 "main",                                              // const char*                        pName
2156                 nullptr // const VkSpecializationInfo*        pSpecializationInfo
2157             };
2158 
2159             const VkComputePipelineCreateInfo pipelineInfo = {
2160                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType                    sType
2161                 nullptr,                                        // const void*                        pNext
2162                 (VkPipelineCreateFlags)0,                       // VkPipelineCreateFlags            flags
2163                 shaderStageInfo,                                // VkPipelineShaderStageCreateInfo    stage
2164                 *pipelineLayout,                                // VkPipelineLayout                    layout
2165                 VK_NULL_HANDLE,                                 // VkPipeline                        basePipelineHandle
2166                 0                                               // int32_t                            basePipelineIndex
2167             };
2168 
2169             pipeline = createComputePipeline(vk, device, VK_NULL_HANDLE, &pipelineInfo);
2170         }
2171     }
2172     else
2173     {
2174         // Create result image
2175         {
2176             const VkImageCreateInfo imageCreateInfo = {
2177                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                     // VkStructureType            stype
2178                 nullptr,                                                 // const void*                pNext
2179                 0u,                                                      // VkImageCreateFlags        flags
2180                 VK_IMAGE_TYPE_2D,                                        // VkImageType                imageType
2181                 resultFormat,                                            // VkFormat                    format
2182                 {(uint32_t)renderSize.x(), (uint32_t)renderSize.y(), 1}, // VkExtent3D                extent
2183                 1u,                                                      // uint32_t                    mipLevels
2184                 1u,                                                      // uint32_t                    arrayLayers
2185                 VK_SAMPLE_COUNT_1_BIT,                                   // VkSampleCountFlagBits    samples
2186                 VK_IMAGE_TILING_OPTIMAL,                                 // VkImageTiling            tiling
2187                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
2188                 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
2189                 1u,                        // uint32_t                    queueFamilyIndexCount
2190                 &queueFamilyIndex,         // const uint32_t*            pQueueFamilyIndices
2191                 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout            initialLayout
2192             };
2193 
2194             resultImage = de::MovePtr<ImageWithMemory>(
2195                 new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
2196         }
2197 
2198         // Create result image view
2199         {
2200             const VkComponentMapping componentMapping = makeComponentMappingRGBA();
2201 
2202             const VkImageSubresourceRange subresourceRange = {
2203                 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
2204                 0u,                        // uint32_t                baseMipLevel
2205                 1u,                        // uint32_t                levelCount
2206                 0u,                        // uint32_t                baseArrayLayer
2207                 1u,                        // uint32_t                layerCount
2208             };
2209 
2210             const VkImageViewCreateInfo imageViewCreateInfo = {
2211                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
2212                 nullptr,                                  // const void*                pNext
2213                 0u,                                       // VkImageViewCreateFlags    flags
2214                 **resultImage,                            // VkImage                    image
2215                 VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType            viewType
2216                 resultFormat,                             // VkFormat                    format
2217                 componentMapping,                         // VkComponentMapping        components
2218                 subresourceRange                          // VkImageSubresourceRange    subresourceRange
2219             };
2220 
2221             resultImageView = createImageView(vk, device, &imageViewCreateInfo);
2222         }
2223 
2224         // Create result buffer
2225         {
2226             const VkDeviceSize bufferSize =
2227                 renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(resultFormat));
2228             const VkBufferCreateInfo bufferCreateInfo = {
2229                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType        sType
2230                 nullptr,                              // const void*            pNext
2231                 0u,                                   // VkBufferCreateFlags    flags
2232                 bufferSize,                           // VkDeviceSize            size
2233                 VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags    usage
2234                 VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode        sharingMode
2235                 0u,                                   // uint32_t                queueFamilyIndexCount
2236                 nullptr                               // const uint32_t*        pQueueFamilyIndices
2237             };
2238 
2239             resultImageBuffer = de::MovePtr<BufferWithMemory>(
2240                 new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
2241         }
2242 
2243         // Create render pass
2244         {
2245             const VkAttachmentReference colorAttachmentRef = {
2246                 0u,                                      // uint32_t            attachment
2247                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout    layout
2248             };
2249 
2250             for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
2251             {
2252                 vector<VkAttachmentReference> references = (*desc)->getAttachmentReferences();
2253                 inputAttachments.insert(inputAttachments.end(), references.begin(), references.end());
2254             }
2255 
2256             const VkAttachmentDescription colorAttachmentDesc = {
2257                 0u,                                      // VkAttachmentDescriptionFlags    flags
2258                 VK_FORMAT_R8G8B8A8_UNORM,                // VkFormat                        format
2259                 VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits        samples
2260                 VK_ATTACHMENT_LOAD_OP_CLEAR,             // VkAttachmentLoadOp            loadOp
2261                 VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp            storeOp
2262                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp            stencilLoadOp
2263                 VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp            stencilStoreOp
2264                 VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout                initialLayout
2265                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout                finalLayout
2266             };
2267 
2268             attachmentDescriptions.push_back(colorAttachmentDesc);
2269 
2270             const VkAttachmentDescription inputAttachmentDesc = {
2271                 0u,                                       // VkAttachmentDescriptionFlags    flags
2272                 VK_FORMAT_R32_SFLOAT,                     // VkFormat                        format
2273                 VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits        samples
2274                 VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp            loadOp
2275                 VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp            storeOp
2276                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp            stencilLoadOp
2277                 VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp            stencilStoreOp
2278                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout                initialLayout
2279                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL  // VkImageLayout                finalLayout
2280             };
2281 
2282             for (size_t inputAttachmentIdx = 0; inputAttachmentIdx < inputAttachments.size(); inputAttachmentIdx++)
2283                 attachmentDescriptions.push_back(inputAttachmentDesc);
2284 
2285             const VkSubpassDescription subpassDescription = {
2286                 0u,                                // VkSubpassDescriptionFlags    flags
2287                 VK_PIPELINE_BIND_POINT_GRAPHICS,   // VkPipelineBindPoint            pipelineBindPoint
2288                 (uint32_t)inputAttachments.size(), // uint32_t                        inputAttachmentCount
2289                 inputAttachments.empty() ? nullptr :
2290                                            inputAttachments.data(), // const VkAttachmentReference*    pInputAttachments
2291                 1u,                  // uint32_t                        colorAttachmentCount
2292                 &colorAttachmentRef, // const VkAttachmentReference*    pColorAttachments
2293                 nullptr,             // const VkAttachmentReference*    pResolveAttachments
2294                 nullptr,             // const VkAttachmentReference*    pDepthStencilAttachment
2295                 0u,                  // uint32_t                        preserveAttachmentCount
2296                 nullptr              // const uint32_t*                pPreserveAttachments
2297             };
2298 
2299             const VkRenderPassCreateInfo renderPassCreateInfo = {
2300                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType                    sType
2301                 nullptr,                                   // const void*                        pNext
2302                 0u,                                        // VkRenderPassCreateFlags            flags
2303                 (uint32_t)attachmentDescriptions.size(),   // uint32_t                            attachmentCount
2304                 attachmentDescriptions.data(),             // const VkAttachmentDescription*    pAttachments
2305                 1u,                                        // uint32_t                            subpassCount
2306                 &subpassDescription,                       // const VkSubpassDescription*        pSubpasses
2307                 0u,                                        // uint32_t                            dependencyCount
2308                 nullptr                                    // const VkSubpassDependency*        pDependencies
2309             };
2310 
2311             renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
2312         }
2313 
2314         // Create framebuffer
2315         {
2316             imageViews.push_back(*resultImageView);
2317 
2318             // Add input attachment image views
2319             for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
2320             {
2321                 vector<VkImageViewSp> inputAttachmentViews = (*desc)->getImageViews();
2322 
2323                 for (size_t imageViewIdx = 0; imageViewIdx < inputAttachmentViews.size(); imageViewIdx++)
2324                     imageViews.push_back(**inputAttachmentViews[imageViewIdx]);
2325             }
2326 
2327             const VkFramebufferCreateInfo framebufferCreateInfo = {
2328                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType             sType
2329                 nullptr,                                   // const void*                 pNext
2330                 0u,                                        // VkFramebufferCreateFlags    flags
2331                 *renderPass,                               // VkRenderPass                renderPass
2332                 (uint32_t)imageViews.size(),               // uint32_t                    attachmentCount
2333                 imageViews.data(),                         // const VkImageView*          pAttachments
2334                 (uint32_t)renderSize.x(),                  // uint32_t                    width
2335                 (uint32_t)renderSize.y(),                  // uint32_t                    height
2336                 1u,                                        // uint32_t                    layers
2337             };
2338 
2339             framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
2340         }
2341 
2342         // Create graphics pipeline
2343         {
2344             const Unique<VkShaderModule> vertexShaderModule(
2345                 createShaderModule(vk, device, context.getBinaryCollection().get("vertex"), 0u));
2346             const Unique<VkShaderModule> fragmentShaderModule(
2347                 createShaderModule(vk, device, context.getBinaryCollection().get("fragment"), 0u));
2348 
2349             const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
2350                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                            sType
2351                 nullptr,                                  // const void*                                pNext
2352                 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags    flags
2353                 0u,                                       // uint32_t                                    bindingCount
2354                 nullptr, // const VkVertexInputBindingDescription*    pVertexBindingDescriptions
2355                 0u,      // uint32_t                                    attributeCount
2356                 nullptr, // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
2357             };
2358 
2359             const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
2360             const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
2361 
2362             pipeline = makeGraphicsPipeline(
2363                 vk,                    // const DeviceInterface&                        vk
2364                 device,                // const VkDevice                                device
2365                 *pipelineLayout,       // const VkPipelineLayout                        pipelineLayout
2366                 *vertexShaderModule,   // const VkShaderModule                          vertexShaderModule
2367                 VK_NULL_HANDLE,        // const VkShaderModule                          tessellationControlShaderModule
2368                 VK_NULL_HANDLE,        // const VkShaderModule                          tessellationEvalShaderModule
2369                 VK_NULL_HANDLE,        // const VkShaderModule                          geometryShaderModule
2370                 *fragmentShaderModule, // const VkShaderModule                          fragmentShaderModule
2371                 *renderPass,           // const VkRenderPass                            renderPass
2372                 viewports,             // const std::vector<VkViewport>&                viewports
2373                 scissors,              // const std::vector<VkRect2D>&                  scissors
2374                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                     topology
2375                 0u,                                  // const uint32_t                                subpass
2376                 0u,                                  // const uint32_t                                patchControlPoints
2377                 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
2378         }
2379     }
2380 
2381     // Run verification shader
2382     {
2383         const VkPipelineBindPoint pipelineBindPoint =
2384             m_pipelineType == PIPELINE_TYPE_COMPUTE ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
2385         vector<uint32_t> offsets;
2386 
2387         if (hasDynamicAreas())
2388         {
2389             for (size_t areaIdx = 0; areaIdx < m_dynamicAreas.size(); areaIdx++)
2390                 offsets.push_back(m_dynamicAreas[areaIdx] * 256u);
2391         }
2392 
2393         beginCommandBuffer(vk, *commandBuffer);
2394 
2395         if (m_pipelineType == PIPELINE_TYPE_GRAPHICS)
2396         {
2397             const VkRect2D renderArea = makeRect2D(renderSize);
2398             const tcu::Vec4 clearColor(1.0f, 0.0f, 0.0f, 1.0f);
2399 
2400             beginRenderPass(vk, *commandBuffer, *renderPass, *framebuffer, renderArea, clearColor);
2401         }
2402 
2403         vk.cmdBindPipeline(*commandBuffer, pipelineBindPoint, *pipeline);
2404         vk.cmdBindDescriptorSets(*commandBuffer, pipelineBindPoint, *pipelineLayout, 0u,
2405                                  (uint32_t)descriptorSets.size(), descriptorSets.data(), (uint32_t)offsets.size(),
2406                                  offsets.empty() ? nullptr : offsets.data());
2407 
2408         // Update descriptor sets when this should be done after bind
2409         if (m_useUpdateAfterBind)
2410             updateDescriptorSets(context, descriptorSets);
2411 
2412         if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
2413         {
2414             vk.cmdDispatch(*commandBuffer, 1u, 1u, 1u);
2415         }
2416         else
2417         {
2418             vk.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
2419             endRenderPass(vk, *commandBuffer);
2420             copyImageToBuffer(vk, *commandBuffer, **resultImage, resultImageBuffer->get(), renderSize);
2421         }
2422 
2423         endCommandBuffer(vk, *commandBuffer);
2424         submitCommandsAndWait(vk, device, queue, *commandBuffer);
2425     }
2426 
2427     if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
2428     {
2429         // Invalidate result buffer
2430         m_resultBuffer->invalidate(context);
2431 
2432         // Verify result data
2433         const auto data = m_resultBuffer->getData();
2434         if (data[0] == 1)
2435             return tcu::TestStatus::pass("Pass");
2436         else
2437             return tcu::TestStatus::fail("Data validation failed");
2438     }
2439     else
2440     {
2441         invalidateAlloc(vk, device, resultImageBuffer->getAllocation());
2442 
2443         // Verify result image
2444         tcu::ConstPixelBufferAccess resultBufferAccess(mapVkFormat(resultFormat), renderSize.x(), renderSize.y(), 1,
2445                                                        resultImageBuffer->getAllocation().getHostPtr());
2446 
2447         for (int32_t y = 0; y < renderSize.y(); y++)
2448             for (int32_t x = 0; x < renderSize.x(); x++)
2449             {
2450                 Vec4 pixel = resultBufferAccess.getPixel(x, y, 0);
2451 
2452                 if (pixel.x() != 0.0f || pixel.y() != 1.0f || pixel.z() != 0.0f || pixel.w() != 1.0f)
2453                 {
2454                     // Log result image before failing.
2455                     log << tcu::TestLog::ImageSet("Result", "")
2456                         << tcu::TestLog::Image("Rendered", "Rendered image", resultBufferAccess)
2457                         << tcu::TestLog::EndImageSet;
2458                     return tcu::TestStatus::fail("Result image validation failed");
2459                 }
2460             }
2461 
2462         return tcu::TestStatus::pass("Pass");
2463     }
2464 }
2465 
updateDescriptorSets(Context & context,const vector<VkDescriptorSet> & descriptorSets)2466 void DescriptorCommands::updateDescriptorSets(Context &context, const vector<VkDescriptorSet> &descriptorSets)
2467 {
2468     const DeviceInterface &vk = context.getDeviceInterface();
2469     const VkDevice device     = context.getDevice();
2470     vector<VkWriteDescriptorSet> descriptorWrites;
2471     vector<VkCopyDescriptorSet> descriptorCopies;
2472 
2473     // Write descriptors that are marked as needing initialization
2474     for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
2475     {
2476         const vector<DescriptorSp> &bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
2477 
2478         for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
2479         {
2480             VkWriteDescriptorSet descriptorWrite = bindings[bindingIdx]->getDescriptorWrite();
2481 
2482             descriptorWrite.dstSet     = descriptorSets[descriptorSetIdx];
2483             descriptorWrite.dstBinding = (uint32_t)bindingIdx;
2484 
2485             if (descriptorWrite.descriptorCount > 0)
2486                 descriptorWrites.push_back(descriptorWrite);
2487         }
2488     }
2489 
2490     for (size_t copyIdx = 0; copyIdx < m_descriptorCopies.size(); copyIdx++)
2491     {
2492         const DescriptorCopy indices   = m_descriptorCopies[copyIdx];
2493         const VkCopyDescriptorSet copy = {
2494             VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, // VkStructureType    sType
2495             nullptr,                               // const void*        pNext
2496             descriptorSets[indices.srcSet],        // VkDescriptorSet    srcSet
2497             indices.srcBinding,                    // uint32_t            srcBinding
2498             indices.srcArrayElement,               // uint32_t            srcArrayElement
2499             descriptorSets[indices.dstSet],        // VkDescriptorSet    dstSet
2500             indices.dstBinding,                    // uint32_t            dstBinding
2501             indices.dstArrayElement,               // uint32_t            dstArrayElement
2502             indices.descriptorCount                // uint32_t            descriptorCount
2503         };
2504 
2505         descriptorCopies.push_back(copy);
2506     }
2507 
2508     // Update descriptors with writes and copies
2509     vk.updateDescriptorSets(device, (uint32_t)descriptorWrites.size(), descriptorWrites.data(),
2510                             (uint32_t)descriptorCopies.size(), descriptorCopies.data());
2511 }
2512 
DescriptorCopyTestInstance(Context & context,DescriptorCommandsSp commands)2513 DescriptorCopyTestInstance::DescriptorCopyTestInstance(Context &context, DescriptorCommandsSp commands)
2514     : vkt::TestInstance(context)
2515     , m_commands(commands)
2516 {
2517 }
2518 
~DescriptorCopyTestInstance(void)2519 DescriptorCopyTestInstance::~DescriptorCopyTestInstance(void)
2520 {
2521 }
2522 
DescriptorCopyTestCase(tcu::TestContext & context,const char * name,DescriptorCommandsSp commands)2523 DescriptorCopyTestCase::DescriptorCopyTestCase(tcu::TestContext &context, const char *name,
2524                                                DescriptorCommandsSp commands)
2525     : vkt::TestCase(context, name)
2526     , m_commands(commands)
2527 {
2528 }
2529 
~DescriptorCopyTestCase(void)2530 DescriptorCopyTestCase::~DescriptorCopyTestCase(void)
2531 {
2532 }
2533 
initPrograms(SourceCollections & programCollection) const2534 void DescriptorCopyTestCase::initPrograms(SourceCollections &programCollection) const
2535 {
2536     if (m_commands->getPipelineType() == PIPELINE_TYPE_COMPUTE)
2537     {
2538         string computeSrc = "#version 430\n"
2539                             "\n" +
2540                             m_commands->getShaderDeclarations() +
2541                             "\n"
2542                             "void main()\n"
2543                             "{\n"
2544                             "int result = 1;\n" +
2545                             m_commands->getDescriptorVerifications() + "storageBuffer" +
2546                             de::toString(m_commands->getResultBufferId()) +
2547                             ".data = result;\n"
2548                             "}\n";
2549 
2550         programCollection.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2551     }
2552     else
2553     {
2554         // Produce quad vertices using vertex index
2555         string vertexSrc = "#version 450\n"
2556                            "out gl_PerVertex\n"
2557                            "{\n"
2558                            "    vec4 gl_Position;\n"
2559                            "};\n"
2560                            "void main()\n"
2561                            "{\n"
2562                            "    gl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
2563                            "                       ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
2564                            "}\n";
2565 
2566         programCollection.glslSources.add("vertex") << glu::VertexSource(vertexSrc);
2567 
2568         string fragmentSrc = "#version 430\n"
2569                              "\n" +
2570                              m_commands->getShaderDeclarations() +
2571                              "layout (location = 0) out vec4 outColor;\n"
2572                              "\n"
2573                              "void main()\n"
2574                              "{\n"
2575                              "int result = 1;\n" +
2576                              m_commands->getDescriptorVerifications() +
2577                              "if (result == 1) outColor = vec4(0, 1, 0, 1);\n"
2578                              "else outColor = vec4(1, 0, 1, 0);\n"
2579                              "}\n";
2580 
2581         programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentSrc);
2582     }
2583 }
2584 
createInstance(Context & context) const2585 TestInstance *DescriptorCopyTestCase::createInstance(Context &context) const
2586 {
2587     TestInstance *result = new DescriptorCopyTestInstance(context, m_commands);
2588     m_commands.clear();
2589     return result;
2590 }
2591 
checkSupport(Context & context) const2592 void DescriptorCopyTestCase::checkSupport(Context &context) const
2593 {
2594     m_commands->checkSupport(context);
2595 }
2596 
iterate(void)2597 tcu::TestStatus DescriptorCopyTestInstance::iterate(void)
2598 {
2599     return m_commands->run(m_context);
2600 }
2601 
2602 template <class T>
addDescriptorCopyTests(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & group,string name,PipelineType pipelineType,bool useUpdateAfterBind)2603 void addDescriptorCopyTests(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &group, string name,
2604                             PipelineType pipelineType, bool useUpdateAfterBind)
2605 {
2606     // Simple test copying inside the same set.
2607     {
2608         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2609         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
2610         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
2611 
2612         commands->copyDescriptor(0u, 0u,  // from
2613                                  0u, 1u); // to
2614 
2615         vector<uint32_t> dynamicAreas;
2616         dynamicAreas.push_back(2u);
2617         dynamicAreas.push_back(1u);
2618         commands->setDynamicAreas(dynamicAreas);
2619 
2620         commands->addResultBuffer();
2621 
2622         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_0").c_str(), commands));
2623     }
2624 
2625     // Simple test copying between different sets.
2626     {
2627         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2628         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
2629         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 1u);
2630 
2631         commands->copyDescriptor(0u, 0u,  // from
2632                                  1u, 0u); // to
2633 
2634         vector<uint32_t> dynamicAreas;
2635         dynamicAreas.push_back(0u);
2636         dynamicAreas.push_back(1u);
2637         commands->setDynamicAreas(dynamicAreas);
2638 
2639         commands->addResultBuffer();
2640 
2641         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_1").c_str(), commands));
2642     }
2643 
2644     // Simple test copying between different sets. Destination not updated.
2645     {
2646         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2647         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
2648         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 0u, 1u)), 1u);
2649 
2650         commands->copyDescriptor(0u, 0u,  // from
2651                                  1u, 0u); // to
2652 
2653         vector<uint32_t> dynamicAreas;
2654         dynamicAreas.push_back(1u);
2655         dynamicAreas.push_back(0u);
2656         commands->setDynamicAreas(dynamicAreas);
2657 
2658         commands->addResultBuffer();
2659 
2660         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_2").c_str(), commands));
2661     }
2662 
2663     // Five sets and several copies.
2664     {
2665         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2666         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
2667         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 0u);
2668         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
2669         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 1u)), 1u);
2670         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
2671         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 5u)), 4u);
2672 
2673         commands->copyDescriptor(4u, 0u,  // from
2674                                  0u, 0u); // to
2675 
2676         commands->copyDescriptor(0u, 1u,  // from
2677                                  1u, 2u); // to
2678 
2679         commands->copyDescriptor(0u, 1u,  // from
2680                                  1u, 1u); // to
2681 
2682         vector<uint32_t> dynamicAreas;
2683         dynamicAreas.push_back(1u);
2684         dynamicAreas.push_back(0u);
2685         dynamicAreas.push_back(1u);
2686         dynamicAreas.push_back(0u);
2687         dynamicAreas.push_back(0u);
2688         dynamicAreas.push_back(4u);
2689         commands->setDynamicAreas(dynamicAreas);
2690 
2691         commands->addResultBuffer();
2692 
2693         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_3").c_str(), commands));
2694     }
2695 
2696     // Several identical copies
2697     {
2698         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2699         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
2700         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 1u);
2701         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
2702 
2703         for (uint32_t i = 0; i < 100; i++)
2704         {
2705             commands->copyDescriptor(0u, 0u,  // from
2706                                      1u, 0u); // to
2707         }
2708 
2709         commands->copyDescriptor(1u, 1u,  // from
2710                                  0u, 0u); // to
2711 
2712         for (uint32_t i = 0; i < 100; i++)
2713         {
2714             commands->copyDescriptor(1u, 0u,  // from
2715                                      1u, 1u); // to
2716         }
2717 
2718         vector<uint32_t> dynamicAreas;
2719         dynamicAreas.push_back(0u);
2720         dynamicAreas.push_back(1u);
2721         dynamicAreas.push_back(1u);
2722         commands->setDynamicAreas(dynamicAreas);
2723 
2724         commands->addResultBuffer();
2725 
2726         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_4").c_str(), commands));
2727     }
2728 
2729     // Copy descriptors back and forth
2730     {
2731         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2732         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
2733         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 1u);
2734         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 1u);
2735 
2736         commands->copyDescriptor(0u, 0u,  // from
2737                                  1u, 0u); // to
2738 
2739         commands->copyDescriptor(1u, 0u,  // from
2740                                  0u, 0u); // to
2741 
2742         commands->copyDescriptor(1u, 1u,  // from
2743                                  0u, 0u); // to
2744 
2745         commands->copyDescriptor(1u, 1u,  // from
2746                                  0u, 0u); // to
2747 
2748         commands->copyDescriptor(1u, 0u,  // from
2749                                  1u, 1u); // to
2750 
2751         vector<uint32_t> dynamicAreas;
2752         dynamicAreas.push_back(1u);
2753         dynamicAreas.push_back(0u);
2754         dynamicAreas.push_back(0u);
2755         commands->setDynamicAreas(dynamicAreas);
2756 
2757         commands->addResultBuffer();
2758 
2759         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_5").c_str(), commands));
2760     }
2761 
2762     // Copy between non-consecutive descriptor sets
2763     {
2764         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2765         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
2766         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 5u);
2767         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 5u);
2768 
2769         commands->copyDescriptor(0u, 0u,  // from
2770                                  5u, 1u); // to
2771 
2772         vector<uint32_t> dynamicAreas;
2773         dynamicAreas.push_back(2u);
2774         dynamicAreas.push_back(1u);
2775         dynamicAreas.push_back(1u);
2776         commands->setDynamicAreas(dynamicAreas);
2777 
2778         commands->addResultBuffer();
2779 
2780         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_6").c_str(), commands));
2781     }
2782 
2783     // Simple 3 sized array to 3 sized array inside the same set.
2784     {
2785         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2786         commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 3u)), 0u);
2787         commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 4u)), 0u);
2788 
2789         commands->copyDescriptor(0u, 0u, 0u, // from
2790                                  0u, 1u, 0u, // to
2791                                  3u);        // num descriptors
2792 
2793         vector<uint32_t> dynamicAreas;
2794         dynamicAreas.push_back(1u);
2795         dynamicAreas.push_back(0u);
2796         dynamicAreas.push_back(2u);
2797 
2798         dynamicAreas.push_back(2u);
2799         dynamicAreas.push_back(1u);
2800         dynamicAreas.push_back(0u);
2801         commands->setDynamicAreas(dynamicAreas);
2802 
2803         commands->addResultBuffer();
2804 
2805         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array0").c_str(), commands));
2806     }
2807 
2808     // Simple 2 sized array to 3 sized array into different set.
2809     {
2810         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2811         commands->addDescriptor(DescriptorSp(new T(2u, 0u, 2u, 2u)), 0u);
2812         commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 5u)), 1u);
2813 
2814         commands->copyDescriptor(0u, 0u, 0u, // from
2815                                  1u, 0u, 0u, // to
2816                                  2u);        // num descriptors
2817 
2818         vector<uint32_t> dynamicAreas;
2819         dynamicAreas.push_back(1u);
2820         dynamicAreas.push_back(0u);
2821 
2822         dynamicAreas.push_back(1u);
2823         dynamicAreas.push_back(0u);
2824         dynamicAreas.push_back(1u);
2825         commands->setDynamicAreas(dynamicAreas);
2826 
2827         commands->addResultBuffer();
2828 
2829         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array1").c_str(), commands));
2830     }
2831 
2832     // Update array partially with writes and partially with a copy
2833     {
2834         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2835         commands->addDescriptor(DescriptorSp(new T(4u, 0u, 4u, 3u)), 0u);
2836         commands->addDescriptor(DescriptorSp(new T(8u, 0u, 5u, 4u)), 0u);
2837 
2838         commands->copyDescriptor(0u, 0u, 1u, // from
2839                                  0u, 1u, 5u, // to
2840                                  3u);        // num descriptors
2841 
2842         vector<uint32_t> dynamicAreas;
2843         dynamicAreas.push_back(2u);
2844         dynamicAreas.push_back(0u);
2845         dynamicAreas.push_back(1u);
2846         dynamicAreas.push_back(1u);
2847 
2848         dynamicAreas.push_back(2u);
2849         dynamicAreas.push_back(0u);
2850         dynamicAreas.push_back(1u);
2851         dynamicAreas.push_back(2u);
2852         dynamicAreas.push_back(0u);
2853         dynamicAreas.push_back(1u);
2854         dynamicAreas.push_back(1u);
2855         dynamicAreas.push_back(2u);
2856         commands->setDynamicAreas(dynamicAreas);
2857 
2858         commands->addResultBuffer();
2859 
2860         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array2").c_str(), commands));
2861     }
2862 }
2863 
addSamplerCopyTests(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & group,PipelineType pipelineType,bool useUpdateAfterBind)2864 void addSamplerCopyTests(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &group, PipelineType pipelineType,
2865                          bool useUpdateAfterBind)
2866 {
2867     // Simple copy between two samplers in the same set
2868     {
2869         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2870         SamplerDescriptor *sampler0(new SamplerDescriptor());
2871         SamplerDescriptor *sampler1(new SamplerDescriptor());
2872         SampledImageDescriptor *image(new SampledImageDescriptor());
2873         sampler0->addImage(image);
2874         sampler1->addImage(image);
2875 
2876         commands->addDescriptor(DescriptorSp(sampler0), 0u);
2877         commands->addDescriptor(DescriptorSp(sampler1), 0u);
2878         commands->addDescriptor(DescriptorSp(image), 0u);
2879 
2880         commands->copyDescriptor(0u, 0u,  // from
2881                                  0u, 1u); // to
2882 
2883         commands->addResultBuffer();
2884 
2885         group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_0", commands));
2886     }
2887 
2888     // Simple 3 sized array to 3 sized array inside the same set.
2889     {
2890         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2891         SamplerDescriptor *sampler0(new SamplerDescriptor(3u, 0u, 3u));
2892         // One sampler in between to get the border colors to originally mismatch between sampler0 and sampler1.
2893         SamplerDescriptor *sampler1(new SamplerDescriptor());
2894         SamplerDescriptor *sampler2(new SamplerDescriptor(3u, 0u, 3u));
2895         SampledImageDescriptor *image(new SampledImageDescriptor());
2896 
2897         sampler0->addImage(image, 3u);
2898         sampler2->addImage(image, 3u);
2899 
2900         commands->addDescriptor(DescriptorSp(sampler0), 0u);
2901         commands->addDescriptor(DescriptorSp(sampler1), 0u);
2902         commands->addDescriptor(DescriptorSp(sampler2), 0u);
2903         commands->addDescriptor(DescriptorSp(image), 0u);
2904 
2905         commands->copyDescriptor(0u, 0u, 0u, // from
2906                                  0u, 2u, 0u, // to
2907                                  3u);        // num descriptors
2908 
2909         commands->addResultBuffer();
2910 
2911         group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_array0", commands));
2912     }
2913 
2914     // Simple 2 sized array to 3 sized array into different set.
2915     {
2916         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2917         SamplerDescriptor *sampler0(new SamplerDescriptor(2u, 0u, 2u));
2918         SamplerDescriptor *sampler1(new SamplerDescriptor(3u, 0u, 3u));
2919         SampledImageDescriptor *image(new SampledImageDescriptor());
2920 
2921         sampler0->addImage(image, 2u);
2922         sampler1->addImage(image, 3u);
2923 
2924         commands->addDescriptor(DescriptorSp(sampler0), 0u);
2925         commands->addDescriptor(DescriptorSp(sampler1), 1u);
2926         commands->addDescriptor(DescriptorSp(image), 0u);
2927 
2928         commands->copyDescriptor(0u, 0u, 0u, // from
2929                                  1u, 0u, 1u, // to
2930                                  2u);        // num descriptors
2931 
2932         commands->addResultBuffer();
2933 
2934         group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_array1", commands));
2935     }
2936 }
2937 
addSampledImageCopyTests(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & group,PipelineType pipelineType,bool useUpdateAfterBind)2938 void addSampledImageCopyTests(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &group,
2939                               PipelineType pipelineType, bool useUpdateAfterBind)
2940 {
2941     // Simple copy between two images in the same set
2942     {
2943         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2944         SamplerDescriptor *sampler(new SamplerDescriptor());
2945         SampledImageDescriptor *image0(new SampledImageDescriptor());
2946         SampledImageDescriptor *image1(new SampledImageDescriptor());
2947         image0->addSampler(sampler);
2948         image1->addSampler(sampler);
2949 
2950         commands->addDescriptor(DescriptorSp(image0), 0u);
2951         commands->addDescriptor(DescriptorSp(image1), 0u);
2952         commands->addDescriptor(DescriptorSp(sampler), 0u);
2953 
2954         commands->copyDescriptor(0u, 0u,  // from
2955                                  0u, 1u); // to
2956 
2957         commands->addResultBuffer();
2958 
2959         group->addChild(new DescriptorCopyTestCase(testCtx, "sampled_image_0", commands));
2960     }
2961 
2962     // Simple 3 sized array to 3 sized array inside the same set.
2963     {
2964         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2965         SamplerDescriptor *sampler(new SamplerDescriptor());
2966         SampledImageDescriptor *image0(new SampledImageDescriptor(3u, 0u, 3u));
2967         SampledImageDescriptor *image1(new SampledImageDescriptor(3u, 0u, 3u));
2968         image0->addSampler(sampler, 3u);
2969         image1->addSampler(sampler, 3u);
2970 
2971         commands->addDescriptor(DescriptorSp(sampler), 0u);
2972         commands->addDescriptor(DescriptorSp(image0), 0u);
2973         commands->addDescriptor(DescriptorSp(image1), 0u);
2974 
2975         commands->copyDescriptor(0u, 1u, 0u, // from
2976                                  0u, 2u, 0u, // to
2977                                  3u);        // num descriptors
2978 
2979         commands->addResultBuffer();
2980 
2981         group->addChild(new DescriptorCopyTestCase(testCtx, "sampled_image_array0", commands));
2982     }
2983 }
2984 
2985 // Mixture of different descriptors in the same test
addMixedDescriptorCopyTests(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & group,PipelineType pipelineType)2986 void addMixedDescriptorCopyTests(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &group,
2987                                  PipelineType pipelineType)
2988 {
2989     {
2990         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
2991         SamplerDescriptor *sampler0(new SamplerDescriptor());
2992         SamplerDescriptor *sampler1(new SamplerDescriptor());
2993         SampledImageDescriptor *image0(new SampledImageDescriptor());
2994         SampledImageDescriptor *image1(new SampledImageDescriptor());
2995         StorageBufferDescriptor *storageBuffer0(new StorageBufferDescriptor());
2996         StorageBufferDescriptor *storageBuffer1(new StorageBufferDescriptor());
2997         StorageBufferDescriptor *storageBuffer2 = new StorageBufferDescriptor();
2998         sampler0->addImage(image0);
2999         sampler1->addImage(image1);
3000 
3001         commands->addDescriptor(DescriptorSp(sampler0), 0u);       // Set 0, binding 0
3002         commands->addDescriptor(DescriptorSp(storageBuffer0), 0u); // Set 0, binding 1
3003         commands->addDescriptor(DescriptorSp(image0), 0u);         // Set 0, binding 2
3004         commands->addDescriptor(DescriptorSp(storageBuffer1), 0u); // Set 0, binding 3
3005         commands->addDescriptor(DescriptorSp(sampler1), 1u);       // Set 1, binding 0
3006         commands->addDescriptor(DescriptorSp(image1), 1u);         // Set 1, binding 1
3007         commands->addDescriptor(DescriptorSp(storageBuffer2), 1u); // Set 1, binding 2
3008 
3009         // image1 to image0
3010         commands->copyDescriptor(1u, 1u,  // from
3011                                  0u, 2u); // to
3012 
3013         // storageBuffer0 to storageBuffer1
3014         commands->copyDescriptor(0u, 1u,  // from
3015                                  0u, 3u); // to
3016 
3017         // storageBuffer1 to storageBuffer2
3018         commands->copyDescriptor(0u, 3u,  // from
3019                                  1u, 2u); // to
3020 
3021         commands->addResultBuffer();
3022 
3023         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_0", commands));
3024     }
3025 
3026     {
3027         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3028         StorageTexelBufferDescriptor *storageTexelBuffer0(new StorageTexelBufferDescriptor());
3029         StorageTexelBufferDescriptor *storageTexelBuffer1(new StorageTexelBufferDescriptor());
3030         UniformBufferDescriptor *uniformBuffer0(new UniformBufferDescriptor());
3031         UniformBufferDescriptor *uniformBuffer1(new UniformBufferDescriptor());
3032         UniformBufferDescriptor *uniformBuffer2(new UniformBufferDescriptor());
3033         DynamicStorageBufferDescriptor *dynamicStorageBuffer0(new DynamicStorageBufferDescriptor(1u, 0u, 1u, 3u));
3034         DynamicStorageBufferDescriptor *dynamicStorageBuffer1(new DynamicStorageBufferDescriptor(1u, 0u, 1u, 4u));
3035 
3036         commands->addDescriptor(DescriptorSp(storageTexelBuffer0), 0u);   // Set 0, binding 0
3037         commands->addDescriptor(DescriptorSp(uniformBuffer0), 0u);        // Set 0, binding 1
3038         commands->addDescriptor(DescriptorSp(dynamicStorageBuffer0), 0u); // Set 0, binding 2
3039         commands->addDescriptor(DescriptorSp(uniformBuffer1), 0u);        // Set 0, binding 3
3040         commands->addDescriptor(DescriptorSp(dynamicStorageBuffer1), 1u); // Set 1, binding 0
3041         commands->addDescriptor(DescriptorSp(storageTexelBuffer1), 1u);   // Set 1, binding 1
3042         commands->addDescriptor(DescriptorSp(uniformBuffer2), 1u);        // Set 1, binding 2
3043 
3044         vector<uint32_t> dynamicAreas;
3045         dynamicAreas.push_back(2u);
3046         dynamicAreas.push_back(1u);
3047         commands->setDynamicAreas(dynamicAreas);
3048 
3049         // uniformBuffer0 to uniformBuffer2
3050         commands->copyDescriptor(0u, 1u,  // from
3051                                  1u, 2u); // to
3052 
3053         // uniformBuffer1 to uniformBuffer2
3054         commands->copyDescriptor(0u, 3u,  // from
3055                                  1u, 2u); // to
3056 
3057         // storageTexelBuffer1 to storageTexelBuffer0
3058         commands->copyDescriptor(1u, 1u,  // from
3059                                  0u, 0u); // to
3060 
3061         // dynamicStorageBuffer0 to dynamicStorageBuffer1
3062         commands->copyDescriptor(0u, 2u,  // from
3063                                  1u, 0u); // to
3064 
3065         commands->addResultBuffer();
3066 
3067         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_1", commands));
3068     }
3069 
3070     if (pipelineType == PIPELINE_TYPE_GRAPHICS)
3071     {
3072         // Mixture of descriptors, including input attachment.
3073         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3074         InputAttachmentDescriptor *inputAttachment0(new InputAttachmentDescriptor());
3075         InputAttachmentDescriptor *inputAttachment1(new InputAttachmentDescriptor());
3076         CombinedImageSamplerDescriptor *combinedImageSampler0(new CombinedImageSamplerDescriptor());
3077         CombinedImageSamplerDescriptor *combinedImageSampler1(new CombinedImageSamplerDescriptor());
3078         UniformTexelBufferDescriptor *uniformTexelBuffer0(new UniformTexelBufferDescriptor(5u, 0u, 5u));
3079         UniformTexelBufferDescriptor *uniformTexelBuffer1(new UniformTexelBufferDescriptor(3u, 1u, 1u));
3080 
3081         commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 0
3082         commands->addDescriptor(DescriptorSp(inputAttachment0), 0u);      // Set 0, binding 1
3083         commands->addDescriptor(DescriptorSp(uniformTexelBuffer0), 0u);   // Set 0, binding 2
3084         commands->addDescriptor(DescriptorSp(combinedImageSampler1), 1u); // Set 1, binding 0
3085         commands->addDescriptor(DescriptorSp(inputAttachment1), 1u);      // Set 1, binding 1
3086         commands->addDescriptor(DescriptorSp(uniformTexelBuffer1), 1u);   // Set 1, binding 2
3087 
3088         // uniformTexelBuffer0[1..3] to uniformTexelBuffer1[0..2]
3089         commands->copyDescriptor(0u, 2u, 1u, // from
3090                                  1u, 2u, 0u, // to
3091                                  3u);        // num descriptors
3092 
3093         // inputAttachment0 to inputAttachment1
3094         commands->copyDescriptor(0u, 1u,  // from
3095                                  1u, 1u); // to
3096 
3097         // combinedImageSampler0 to combinedImageSampler1
3098         commands->copyDescriptor(0u, 0u,  // from
3099                                  1u, 0u); // to
3100 
3101         commands->addResultBuffer();
3102 
3103         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_2", commands));
3104     }
3105 
3106 #ifndef CTS_USES_VULKANSC
3107     if (pipelineType == PIPELINE_TYPE_GRAPHICS)
3108     {
3109         // Similar to the previous one, but adding inline uniform blocks to the mix.
3110         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3111         InlineUniformBlockDescriptor *iub0(new InlineUniformBlockDescriptor(4u, 0u, 4u));
3112         InlineUniformBlockDescriptor *iub1(new InlineUniformBlockDescriptor(4u, 0u, 1u));
3113         InputAttachmentDescriptor *inputAttachment0(new InputAttachmentDescriptor());
3114         InputAttachmentDescriptor *inputAttachment1(new InputAttachmentDescriptor());
3115         CombinedImageSamplerDescriptor *combinedImageSampler0(new CombinedImageSamplerDescriptor());
3116         CombinedImageSamplerDescriptor *combinedImageSampler1(new CombinedImageSamplerDescriptor());
3117         UniformTexelBufferDescriptor *uniformTexelBuffer0(new UniformTexelBufferDescriptor(5u, 0u, 5u));
3118         UniformTexelBufferDescriptor *uniformTexelBuffer1(new UniformTexelBufferDescriptor(3u, 1u, 1u));
3119 
3120         commands->addDescriptor(DescriptorSp(iub0), 0u);                  // Set 0, binding 0
3121         commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 1
3122         commands->addDescriptor(DescriptorSp(inputAttachment0), 0u);      // Set 0, binding 2
3123         commands->addDescriptor(DescriptorSp(uniformTexelBuffer0), 0u);   // Set 0, binding 3
3124         commands->addDescriptor(DescriptorSp(iub1), 1u);                  // Set 1, binding 0
3125         commands->addDescriptor(DescriptorSp(combinedImageSampler1), 1u); // Set 1, binding 1
3126         commands->addDescriptor(DescriptorSp(inputAttachment1), 1u);      // Set 1, binding 2
3127         commands->addDescriptor(DescriptorSp(uniformTexelBuffer1), 1u);   // Set 1, binding 3
3128 
3129         // iub0.data[0..2] to iub1.data[1..3]
3130         commands->copyDescriptor(0u, 0u, 0u, // from
3131                                  1u, 0u, 1u, // to
3132                                  3u);        // num descriptors
3133 
3134         // uniformTexelBuffer0[1..3] to uniformTexelBuffer1[0..2]
3135         commands->copyDescriptor(0u, 3u, 1u, // from
3136                                  1u, 3u, 0u, // to
3137                                  3u);        // num descriptors
3138 
3139         // inputAttachment0 to inputAttachment1
3140         commands->copyDescriptor(0u, 2u,  // from
3141                                  1u, 2u); // to
3142 
3143         // combinedImageSampler0 to combinedImageSampler1
3144         commands->copyDescriptor(0u, 1u,  // from
3145                                  1u, 1u); // to
3146 
3147         commands->addResultBuffer();
3148 
3149         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_3", commands));
3150     }
3151 #endif
3152 
3153     // Mixture of descriptors using descriptor arrays
3154     {
3155         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3156         CombinedImageSamplerDescriptor *combinedImageSampler0(new CombinedImageSamplerDescriptor(3u, 0u, 3u));
3157         CombinedImageSamplerDescriptor *combinedImageSampler1(new CombinedImageSamplerDescriptor(4u, 0u, 2u));
3158         CombinedImageSamplerDescriptor *combinedImageSampler2(new CombinedImageSamplerDescriptor(3u, 0u, 3u));
3159         StorageImageDescriptor *storageImage0(new StorageImageDescriptor(5u, 0u, 5u));
3160         StorageImageDescriptor *storageImage1(new StorageImageDescriptor(3u, 0u, 0u));
3161         StorageBufferDescriptor *storageBuffer0(new StorageBufferDescriptor(2u, 0u, 1u));
3162         StorageBufferDescriptor *storageBuffer1(new StorageBufferDescriptor(3u, 0u, 3u));
3163 
3164         commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 0
3165         commands->addDescriptor(DescriptorSp(storageImage0), 0u);         // Set 0, binding 1
3166         commands->addDescriptor(DescriptorSp(combinedImageSampler1), 0u); // Set 0, binding 2
3167         commands->addDescriptor(DescriptorSp(storageBuffer0), 0u);        // Set 0, binding 3
3168         commands->addDescriptor(DescriptorSp(storageBuffer1), 0u);        // Set 0, binding 4
3169         commands->addDescriptor(DescriptorSp(storageImage1), 1u);         // Set 1, binding 0
3170         commands->addDescriptor(DescriptorSp(combinedImageSampler2), 1u); // Set 1, binding 1
3171 
3172         // combinedImageSampler0[1..2] to combinedImageSampler1[2..3]
3173         commands->copyDescriptor(0u, 0u, 1u, // from
3174                                  0u, 2u, 2u, // to
3175                                  2u);        // num descriptors
3176 
3177         // storageImage0[2..4] to storageImage1[0..2]
3178         commands->copyDescriptor(0u, 1u, 2u, // from
3179                                  1u, 0u, 0u, // to
3180                                  3u);        // num descriptors
3181 
3182         // storageBuffer1[1..2] to storageBuffer0[0..1]
3183         commands->copyDescriptor(0u, 4u, 1u, // from
3184                                  0u, 3u, 0u, // to
3185                                  2u);        // num descriptors
3186 
3187         commands->addResultBuffer();
3188 
3189         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_array0", commands));
3190     }
3191 
3192     // Similar to the previous one but including inline uniform blocks.
3193 #ifndef CTS_USES_VULKANSC
3194     {
3195         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3196         InlineUniformBlockDescriptor *iub0(new InlineUniformBlockDescriptor(4u, 0u, 1u));
3197         InlineUniformBlockDescriptor *iub1(new InlineUniformBlockDescriptor(4u, 0u, 4u));
3198         CombinedImageSamplerDescriptor *combinedImageSampler0(new CombinedImageSamplerDescriptor(3u, 0u, 3u));
3199         CombinedImageSamplerDescriptor *combinedImageSampler1(new CombinedImageSamplerDescriptor(4u, 0u, 2u));
3200         CombinedImageSamplerDescriptor *combinedImageSampler2(new CombinedImageSamplerDescriptor(3u, 0u, 3u));
3201         StorageImageDescriptor *storageImage0(new StorageImageDescriptor(5u, 0u, 5u));
3202         StorageImageDescriptor *storageImage1(new StorageImageDescriptor(3u, 0u, 0u));
3203         StorageBufferDescriptor *storageBuffer0(new StorageBufferDescriptor(2u, 0u, 1u));
3204         StorageBufferDescriptor *storageBuffer1(new StorageBufferDescriptor(3u, 0u, 3u));
3205 
3206         commands->addDescriptor(DescriptorSp(iub0), 0u);                  // Set 0, binding 0
3207         commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 1
3208         commands->addDescriptor(DescriptorSp(storageImage0), 0u);         // Set 0, binding 2
3209         commands->addDescriptor(DescriptorSp(combinedImageSampler1), 0u); // Set 0, binding 3
3210         commands->addDescriptor(DescriptorSp(storageBuffer0), 0u);        // Set 0, binding 4
3211         commands->addDescriptor(DescriptorSp(storageBuffer1), 0u);        // Set 0, binding 5
3212         commands->addDescriptor(DescriptorSp(combinedImageSampler2), 0u); // Set 0, binding 6
3213         commands->addDescriptor(DescriptorSp(iub1), 1u);                  // Set 1, binding 0
3214         commands->addDescriptor(DescriptorSp(storageImage1), 1u);         // Set 1, binding 1
3215 
3216         // iub1.data[0..2] to iub0.data[1..3]
3217         commands->copyDescriptor(1u, 0u, 0u, // from
3218                                  0u, 0u, 1u, // to
3219                                  3u);        // num descriptors
3220 
3221         // combinedImageSampler0[1..2] to combinedImageSampler1[2..3]
3222         commands->copyDescriptor(0u, 1u, 1u, // from
3223                                  0u, 3u, 2u, // to
3224                                  2u);        // num descriptors
3225 
3226         // storageImage0[2..4] to storageImage1[0..2]
3227         commands->copyDescriptor(0u, 2u, 2u, // from
3228                                  1u, 1u, 0u, // to
3229                                  3u);        // num descriptors
3230 
3231         // storageBuffer1[1..2] to storageBuffer0[0..1]
3232         commands->copyDescriptor(0u, 5u, 1u, // from
3233                                  0u, 4u, 0u, // to
3234                                  2u);        // num descriptors
3235 
3236         commands->addResultBuffer();
3237 
3238         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_array1", commands));
3239     }
3240 #endif
3241 }
3242 
3243 } // namespace
3244 
createTestsForAllDescriptorTypes(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & parentGroup,PipelineType pipelineType,bool useUpdateAfterBind=false)3245 void createTestsForAllDescriptorTypes(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &parentGroup,
3246                                       PipelineType pipelineType, bool useUpdateAfterBind = false)
3247 {
3248     addDescriptorCopyTests<UniformBufferDescriptor>(testCtx, parentGroup, "uniform_buffer", pipelineType,
3249                                                     useUpdateAfterBind);
3250     addDescriptorCopyTests<StorageBufferDescriptor>(testCtx, parentGroup, "storage_buffer", pipelineType,
3251                                                     useUpdateAfterBind);
3252     addDescriptorCopyTests<CombinedImageSamplerDescriptor>(testCtx, parentGroup, "combined_image_sampler", pipelineType,
3253                                                            useUpdateAfterBind);
3254     addDescriptorCopyTests<StorageImageDescriptor>(testCtx, parentGroup, "storage_image", pipelineType,
3255                                                    useUpdateAfterBind);
3256     addDescriptorCopyTests<UniformTexelBufferDescriptor>(testCtx, parentGroup, "uniform_texel_buffer", pipelineType,
3257                                                          useUpdateAfterBind);
3258     addDescriptorCopyTests<StorageTexelBufferDescriptor>(testCtx, parentGroup, "storage_texel_buffer", pipelineType,
3259                                                          useUpdateAfterBind);
3260 
3261 #ifndef CTS_USES_VULKANSC
3262     addDescriptorCopyTests<InlineUniformBlockDescriptor>(testCtx, parentGroup, "inline_uniform_block", pipelineType,
3263                                                          useUpdateAfterBind);
3264 #endif
3265 
3266     // create tests that can be run only without UpdateAfterBind
3267     if (useUpdateAfterBind == false)
3268     {
3269         addDescriptorCopyTests<DynamicUniformBufferDescriptor>(testCtx, parentGroup, "uniform_buffer_dynamic",
3270                                                                pipelineType, false);
3271         addDescriptorCopyTests<DynamicStorageBufferDescriptor>(testCtx, parentGroup, "storage_buffer_dynamic",
3272                                                                pipelineType, false);
3273 
3274         // create tests that are graphics pipeline specific
3275         if (pipelineType == PIPELINE_TYPE_GRAPHICS)
3276             addDescriptorCopyTests<InputAttachmentDescriptor>(testCtx, parentGroup, "input_attachment",
3277                                                               PIPELINE_TYPE_GRAPHICS, false);
3278 
3279         addMixedDescriptorCopyTests(testCtx, parentGroup, pipelineType);
3280     }
3281 
3282     addSamplerCopyTests(testCtx, parentGroup, pipelineType, useUpdateAfterBind);
3283     addSampledImageCopyTests(testCtx, parentGroup, pipelineType, useUpdateAfterBind);
3284 }
3285 
createDescriptorCopyTests(tcu::TestContext & testCtx)3286 tcu::TestCaseGroup *createDescriptorCopyTests(tcu::TestContext &testCtx)
3287 {
3288     de::MovePtr<tcu::TestCaseGroup> descriptorCopyGroup(new tcu::TestCaseGroup(testCtx, "descriptor_copy"));
3289 
3290     de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup(testCtx, "compute"));
3291     de::MovePtr<tcu::TestCaseGroup> graphicsGroup(new tcu::TestCaseGroup(testCtx, "graphics"));
3292     // Graphics tests with update after bind
3293     de::MovePtr<tcu::TestCaseGroup> graphicsUABGroup(new tcu::TestCaseGroup(testCtx, "graphics_uab"));
3294 
3295     createTestsForAllDescriptorTypes(testCtx, computeGroup, PIPELINE_TYPE_COMPUTE);
3296     createTestsForAllDescriptorTypes(testCtx, graphicsGroup, PIPELINE_TYPE_GRAPHICS);
3297     createTestsForAllDescriptorTypes(testCtx, graphicsUABGroup, PIPELINE_TYPE_GRAPHICS, true);
3298 
3299     descriptorCopyGroup->addChild(computeGroup.release());
3300     descriptorCopyGroup->addChild(graphicsGroup.release());
3301     descriptorCopyGroup->addChild(graphicsUABGroup.release());
3302 
3303     return descriptorCopyGroup.release();
3304 }
3305 
3306 } // namespace BindingModel
3307 } // namespace vkt
3308