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::__anon37b3beec0111::InlineUniformBlockDescriptor::PaddedUint222         PaddedUint() : value(0)
223         {
224             deMemset(padding, 0, sizeof(padding));
225         }
PaddedUintvkt::BindingModel::__anon37b3beec0111::InlineUniformBlockDescriptor::PaddedUint226         PaddedUint(uint32_t value_) : value(value_)
227         {
228             deMemset(padding, 0, sizeof(padding));
229         }
operator =vkt::BindingModel::__anon37b3beec0111::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             DE_NULL,                              // 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             DE_NULL                               // 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                 DE_NULL,                                   // 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         DE_NULL,                                // const void*                        pNext
793         (VkDescriptorSet)0u,                    // VkDescriptorSet                    dstSet
794         0u,                                     // uint32_t                            dstBinding
795         firstElement,                           // uint32_t                            dstArrayElement
796         getNumWrittenElements(),                // uint32_t                            descriptorCount
797         getType(),                              // VkDescriptorType                    descriptorType
798         DE_NULL,                                // const VkDescriptorImageInfo        pImageInfo
799         usesBufferView() ? DE_NULL :
800                            &m_descriptorBufferInfos[firstElement], // const VkDescriptorBufferInfo*    pBufferInfo
801         usesBufferView() ? &m_bufferViewHandles[firstElement] :
802                            DE_NULL // 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    = DE_NULL;
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         (VkDescriptorSet)0u,                    // VkDescriptorSet                    dstSet
871         0u,                                     // uint32_t                            dstBinding
872         m_writeStartByteOffset,                 // uint32_t                            dstArrayElement
873         m_bytesToWrite,                         // uint32_t                            descriptorCount
874         getType(),                              // VkDescriptorType                    descriptorType
875         DE_NULL,                                // const VkDescriptorImageInfo        pImageInfo
876         DE_NULL,                                // const VkDescriptorBufferInfo*    pBufferInfo
877         DE_NULL                                 // 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             DE_NULL,                                                 // 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             DE_NULL,                                  // 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             DE_NULL,                                // 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             DE_NULL,                                // 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, (const VkMemoryBarrier *)DE_NULL, 0u,
1254                               (const VkBufferMemoryBarrier *)DE_NULL, 1u, &preImageBarrier);
1255         vk.cmdClearColorImage(*cmdBuffer, **m_images[imageIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color,
1256                               1, &subresourceRange);
1257         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1258                               pipelineType == PIPELINE_TYPE_COMPUTE ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT :
1259                                                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1260                               (VkDependencyFlags)0u, 0u, (const VkMemoryBarrier *)DE_NULL, 0u,
1261                               (const VkBufferMemoryBarrier *)DE_NULL, 1u, &postImageBarrier);
1262         endCommandBuffer(vk, *cmdBuffer);
1263         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1264     }
1265 }
1266 
getDescriptorWrite(void)1267 VkWriteDescriptorSet ImageDescriptor::getDescriptorWrite(void)
1268 {
1269     const uint32_t firstElement = getFirstWrittenElement();
1270 
1271     // Set and binding will be overwritten later
1272     const VkWriteDescriptorSet descriptorWrite = {
1273         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                    sType
1274         DE_NULL,                                // const void*                        pNext
1275         (VkDescriptorSet)0u,                    // VkDescriptorSet                    dstSet
1276         0u,                                     // uint32_t                            dstBinding
1277         firstElement,                           // uint32_t                            dstArrayElement
1278         getNumWrittenElements(),                // uint32_t                            descriptorCount
1279         getType(),                              // VkDescriptorType                    descriptorType
1280         &m_descriptorImageInfos[firstElement],  // const VkDescriptorImageInfo        pImageInfo
1281         DE_NULL,                                // const VkDescriptorBufferInfo*    pBufferInfo
1282         DE_NULL                                 // const VkBufferView*                pTexelBufferView
1283     };
1284 
1285     return descriptorWrite;
1286 }
1287 
InputAttachmentDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1288 InputAttachmentDescriptor::InputAttachmentDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
1289                                                      uint32_t numDynamicAreas)
1290     : ImageDescriptor(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, arraySize, writeStart, elementsToWrite, 1u)
1291     , m_originalAttachmentIndex(s_nextAttachmentIndex)
1292 {
1293     DE_UNREF(numDynamicAreas);
1294 
1295     for (uint32_t i = 0; i < m_arraySize; i++)
1296         m_attachmentIndices.push_back(s_nextAttachmentIndex++);
1297 }
1298 
~InputAttachmentDescriptor(void)1299 InputAttachmentDescriptor::~InputAttachmentDescriptor(void)
1300 {
1301 }
1302 
getShaderDeclaration(void) const1303 string InputAttachmentDescriptor::getShaderDeclaration(void) const
1304 {
1305     return string(", input_attachment_index=" + de::toString(m_originalAttachmentIndex) +
1306                   ") uniform subpassInput inputAttachment" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1307 }
1308 
getShaderVerifyCode(void) const1309 string InputAttachmentDescriptor::getShaderVerifyCode(void) const
1310 {
1311     string ret;
1312 
1313     for (uint32_t i = 0; i < m_arraySize; i++)
1314     {
1315         if (m_data[i].written || m_data[i].copiedInto)
1316             ret += string("if (subpassLoad(inputAttachment") + de::toString(m_id) + getArrayString(i) +
1317                    ").x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1318     }
1319 
1320     return ret;
1321 }
1322 
copyValue(const Descriptor & src,uint32_t srcElement,uint32_t dstElement,uint32_t numElements)1323 void InputAttachmentDescriptor::copyValue(const Descriptor &src, uint32_t srcElement, uint32_t dstElement,
1324                                           uint32_t numElements)
1325 {
1326     Descriptor::copyValue(src, srcElement, dstElement, numElements);
1327 
1328     for (uint32_t elementIdx = 0; elementIdx < numElements; elementIdx++)
1329     {
1330         m_attachmentIndices[elementIdx + dstElement] =
1331             reinterpret_cast<const InputAttachmentDescriptor &>(src).m_attachmentIndices[elementIdx + srcElement];
1332     }
1333 }
1334 
getAttachmentReferences(void) const1335 vector<VkAttachmentReference> InputAttachmentDescriptor::getAttachmentReferences(void) const
1336 {
1337     vector<VkAttachmentReference> references;
1338     for (uint32_t i = 0; i < m_arraySize; i++)
1339     {
1340         const VkAttachmentReference attachmentReference = {
1341             // The first attachment is the color buffer, thus +1
1342             m_attachmentIndices[i] + 1, // uint32_t            attachment
1343             getImageLayout()            // VkImageLayout    layout
1344         };
1345 
1346         references.push_back(attachmentReference);
1347     }
1348 
1349     return references;
1350 }
1351 
CombinedImageSamplerDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1352 CombinedImageSamplerDescriptor::CombinedImageSamplerDescriptor(uint32_t arraySize, uint32_t writeStart,
1353                                                                uint32_t elementsToWrite, uint32_t numDynamicAreas)
1354     : ImageDescriptor(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize, writeStart, elementsToWrite, 1u)
1355 {
1356     DE_UNREF(numDynamicAreas);
1357 }
1358 
~CombinedImageSamplerDescriptor(void)1359 CombinedImageSamplerDescriptor::~CombinedImageSamplerDescriptor(void)
1360 {
1361 }
1362 
getShaderDeclaration(void) const1363 string CombinedImageSamplerDescriptor::getShaderDeclaration(void) const
1364 {
1365     return string(") uniform sampler2D texSampler" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1366 }
1367 
getShaderVerifyCode(void) const1368 string CombinedImageSamplerDescriptor::getShaderVerifyCode(void) const
1369 {
1370     string ret;
1371 
1372     for (uint32_t i = 0; i < m_arraySize; i++)
1373     {
1374         if (m_data[i].written || m_data[i].copiedInto)
1375             ret += string("if (texture(texSampler") + de::toString(m_id) + getArrayString(i) +
1376                    ", vec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1377     }
1378 
1379     return ret;
1380 }
1381 
SampledImageDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1382 SampledImageDescriptor::SampledImageDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
1383                                                uint32_t numDynamicAreas)
1384     : ImageDescriptor(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, arraySize, writeStart, elementsToWrite, 1u)
1385 {
1386     DE_UNREF(numDynamicAreas);
1387 }
1388 
~SampledImageDescriptor(void)1389 SampledImageDescriptor::~SampledImageDescriptor(void)
1390 {
1391 }
1392 
getShaderDeclaration(void) const1393 string SampledImageDescriptor::getShaderDeclaration(void) const
1394 {
1395     return string(") uniform texture2D sampledImage" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1396 }
1397 
getShaderVerifyCode(void) const1398 string SampledImageDescriptor::getShaderVerifyCode(void) const
1399 {
1400     string ret;
1401 
1402     for (uint32_t i = 0; i < m_arraySize; i++)
1403     {
1404         if ((m_data[i].written || m_data[i].copiedInto) && m_samplers.size() > i)
1405         {
1406             ret += string("if (texture(sampler2D(sampledImage") + de::toString(m_id) + getArrayString(i) + ", sampler" +
1407                    de::toString(m_samplers[i]->getId()) + "), vec2(0)).x != " + de::toString(m_data[i].data[0]) +
1408                    ") result = 0;\n";
1409         }
1410     }
1411 
1412     return ret;
1413 }
1414 
StorageImageDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1415 StorageImageDescriptor::StorageImageDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
1416                                                uint32_t numDynamicAreas)
1417     : ImageDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize, writeStart, elementsToWrite, 1u)
1418 {
1419     DE_UNREF(numDynamicAreas);
1420 }
1421 
~StorageImageDescriptor(void)1422 StorageImageDescriptor::~StorageImageDescriptor(void)
1423 {
1424 }
1425 
getShaderDeclaration(void) const1426 string StorageImageDescriptor::getShaderDeclaration(void) const
1427 {
1428     return string(", r32f) readonly uniform image2D image" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1429 }
1430 
getShaderVerifyCode(void) const1431 string StorageImageDescriptor::getShaderVerifyCode(void) const
1432 {
1433     string ret;
1434 
1435     for (uint32_t i = 0; i < m_arraySize; i++)
1436     {
1437         if (m_data[i].written || m_data[i].copiedInto)
1438             ret += string("if (imageLoad(image") + de::toString(m_id) + getArrayString(i) +
1439                    ", ivec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
1440     }
1441 
1442     return ret;
1443 }
1444 
SamplerDescriptor(uint32_t arraySize,uint32_t writeStart,uint32_t elementsToWrite,uint32_t numDynamicAreas)1445 SamplerDescriptor::SamplerDescriptor(uint32_t arraySize, uint32_t writeStart, uint32_t elementsToWrite,
1446                                      uint32_t numDynamicAreas)
1447     : Descriptor(VK_DESCRIPTOR_TYPE_SAMPLER, arraySize, writeStart, elementsToWrite, 1u)
1448 {
1449     DE_UNREF(numDynamicAreas);
1450 }
1451 
~SamplerDescriptor(void)1452 SamplerDescriptor::~SamplerDescriptor(void)
1453 {
1454 }
1455 
init(Context & context,PipelineType pipelineType)1456 void SamplerDescriptor::init(Context &context, PipelineType pipelineType)
1457 {
1458     DE_UNREF(pipelineType);
1459 
1460     const DeviceInterface &vk = context.getDeviceInterface();
1461     const VkDevice device     = context.getDevice();
1462     const VkFormat format     = VK_FORMAT_R32_SFLOAT;
1463 
1464     // Create samplers
1465     for (uint32_t i = 0; i < m_arraySize; i++)
1466     {
1467         const float borderValue = (float)((m_id + i) % 2);
1468         const tcu::Sampler sampler =
1469             tcu::Sampler(tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::CLAMP_TO_BORDER,
1470                          tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
1471                          Vec4(borderValue), true);
1472         const tcu::TextureFormat texFormat      = mapVkFormat(format);
1473         const VkSamplerCreateInfo samplerParams = mapSampler(sampler, texFormat);
1474 
1475         m_samplers.push_back(VkSamplerSp(new Unique<VkSampler>(createSampler(vk, device, &samplerParams))));
1476     }
1477 
1478     // Create descriptor image infos
1479     for (uint32_t i = 0; i < m_arraySize; i++)
1480     {
1481         const VkDescriptorImageInfo imageInfo = {
1482             **m_samplers[i],          // VkSampler        sampler
1483             DE_NULL,                  // VkImageView        imageView
1484             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout    imageLayout
1485         };
1486 
1487         m_descriptorImageInfos.push_back(imageInfo);
1488     }
1489 }
1490 
getDescriptorWrite(void)1491 VkWriteDescriptorSet SamplerDescriptor::getDescriptorWrite(void)
1492 {
1493     const uint32_t firstElement = getFirstWrittenElement();
1494 
1495     // Set and binding will be overwritten later
1496     const VkWriteDescriptorSet descriptorWrite = {
1497         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                    sType
1498         DE_NULL,                                // const void*                        pNext
1499         (VkDescriptorSet)0u,                    // VkDescriptorSet                    dstSet
1500         0u,                                     // uint32_t                            dstBinding
1501         firstElement,                           // uint32_t                            dstArrayElement
1502         getNumWrittenElements(),                // uint32_t                            descriptorCount
1503         getType(),                              // VkDescriptorType                    descriptorType
1504         &m_descriptorImageInfos[firstElement],  // const VkDescriptorImageInfo        pImageInfo
1505         DE_NULL,                                // const VkDescriptorBufferInfo*    pBufferInfo
1506         DE_NULL                                 // const VkBufferView*                pTexelBufferView
1507     };
1508 
1509     return descriptorWrite;
1510 }
1511 
getShaderDeclaration(void) const1512 string SamplerDescriptor::getShaderDeclaration(void) const
1513 {
1514     return string(") uniform sampler sampler" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
1515 }
1516 
getShaderVerifyCode(void) const1517 string SamplerDescriptor::getShaderVerifyCode(void) const
1518 {
1519     string ret;
1520 
1521     for (uint32_t i = 0; i < m_arraySize; i++)
1522     {
1523         if ((m_data[i].written || m_data[i].copiedInto) && m_images.size() > i)
1524         {
1525             // Sample from (-1, -1) to get border color.
1526             ret += string("if (texture(sampler2D(sampledImage") + de::toString(m_images[i]->getId()) + ", sampler" +
1527                    de::toString(m_id) + getArrayString(i) + "), vec2(-1)).x != " + de::toString(m_data[i].data[0] % 2) +
1528                    ") result = 0;\n";
1529         }
1530     }
1531 
1532     return ret;
1533 }
1534 
DescriptorSet(void)1535 DescriptorSet::DescriptorSet(void)
1536 {
1537 }
1538 
~DescriptorSet(void)1539 DescriptorSet::~DescriptorSet(void)
1540 {
1541 }
1542 
addBinding(DescriptorSp descriptor)1543 void DescriptorSet::addBinding(DescriptorSp descriptor)
1544 {
1545     m_bindings.push_back(descriptor);
1546 }
1547 
DescriptorCommands(PipelineType pipelineType,bool useUpdateAfterBind)1548 DescriptorCommands::DescriptorCommands(PipelineType pipelineType, bool useUpdateAfterBind)
1549     : m_pipelineType(pipelineType)
1550     , m_useUpdateAfterBind(useUpdateAfterBind)
1551 {
1552     // Reset counters
1553     Descriptor::s_nextId                             = 0xabc;
1554     InputAttachmentDescriptor::s_nextAttachmentIndex = 0;
1555 }
1556 
~DescriptorCommands(void)1557 DescriptorCommands::~DescriptorCommands(void)
1558 {
1559 }
1560 
addDescriptor(DescriptorSp descriptor,uint32_t descriptorSet)1561 void DescriptorCommands::addDescriptor(DescriptorSp descriptor, uint32_t descriptorSet)
1562 {
1563     const VkDescriptorType type = descriptor->getType();
1564 
1565     // Create descriptor set objects until one with the given index exists
1566     while (m_descriptorSets.size() <= descriptorSet)
1567         m_descriptorSets.push_back(DescriptorSetSp(new DescriptorSet()));
1568 
1569     m_descriptorSets[descriptorSet]->addBinding(descriptor);
1570 
1571     // Keep track of how many descriptors of each type is needed. Inline uniform blocks cannot form arrays. We reuse the array size
1572     // as size of the data array for them, within a single descriptor.
1573 
1574 #ifndef CTS_USES_VULKANSC
1575     const uint32_t count = ((type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) ? 1u : descriptor->getArraySize());
1576 #else
1577     const uint32_t count = descriptor->getArraySize();
1578 #endif
1579 
1580     if (m_descriptorCounts.find(type) != m_descriptorCounts.end())
1581         m_descriptorCounts[type] += count;
1582     else
1583         m_descriptorCounts[type] = count;
1584 
1585     // Keep descriptors also in a flat list for easier iteration
1586     m_descriptors.push_back(descriptor);
1587 }
1588 
copyDescriptor(uint32_t srcSet,uint32_t srcBinding,uint32_t srcArrayElement,uint32_t dstSet,uint32_t dstBinding,uint32_t dstArrayElement,uint32_t descriptorCount)1589 void DescriptorCommands::copyDescriptor(uint32_t srcSet, uint32_t srcBinding, uint32_t srcArrayElement, uint32_t dstSet,
1590                                         uint32_t dstBinding, uint32_t dstArrayElement, uint32_t descriptorCount)
1591 {
1592     // For inline uniform blocks, (src|dst)ArrayElement are data array indices and descriptorCount is the number of integers to copy.
1593     DescriptorCopy descriptorCopy = {srcSet,     srcBinding,      srcArrayElement, dstSet,
1594                                      dstBinding, dstArrayElement, descriptorCount};
1595 
1596 #ifndef CTS_USES_VULKANSC
1597     if (m_descriptorSets[srcSet]->getBindings()[srcBinding]->getType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1598     {
1599         // For inline uniform blocks, these members of VkCopyDescriptorSet are offsets and sizes in bytes.
1600         const InlineUniformBlockDescriptor *iub =
1601             static_cast<InlineUniformBlockDescriptor *>(m_descriptorSets[srcSet]->getBindings()[srcBinding].get());
1602         const uint32_t elementSize = iub->getElementSizeInBytes();
1603 
1604         descriptorCopy.srcArrayElement *= elementSize;
1605         descriptorCopy.dstArrayElement *= elementSize;
1606         descriptorCopy.descriptorCount *= elementSize;
1607     }
1608 #endif
1609 
1610     m_descriptorCopies.push_back(descriptorCopy);
1611     m_descriptorSets[descriptorCopy.dstSet]->getBindings()[descriptorCopy.dstBinding]->copyValue(
1612         *m_descriptorSets[descriptorCopy.srcSet]->getBindings()[descriptorCopy.srcBinding], srcArrayElement,
1613         dstArrayElement, descriptorCount);
1614 }
1615 
1616 // Generates shader source code for declarations of all descriptors
getShaderDeclarations(void) const1617 string DescriptorCommands::getShaderDeclarations(void) const
1618 {
1619     string ret;
1620 
1621     for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
1622     {
1623         const vector<DescriptorSp> bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
1624 
1625         for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
1626         {
1627             ret += "layout (set=" + de::toString(descriptorSetIdx) + ", binding=" + de::toString(bindingIdx) +
1628                    bindings[bindingIdx]->getShaderDeclaration();
1629         }
1630     }
1631 
1632     return ret;
1633 }
1634 
1635 // Generates shader source code for verification of all descriptor data
getDescriptorVerifications(void) const1636 string DescriptorCommands::getDescriptorVerifications(void) const
1637 {
1638     string ret;
1639 
1640     for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
1641     {
1642         const vector<DescriptorSp> bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
1643 
1644         for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
1645         {
1646             if (m_pipelineType == PIPELINE_TYPE_COMPUTE && descriptorSetIdx == 0 && bindingIdx == bindings.size() - 1)
1647                 continue; // Skip the result buffer which is always the last descriptor of set 0
1648             ret += bindings[bindingIdx]->getShaderVerifyCode();
1649         }
1650     }
1651 
1652     return ret;
1653 }
1654 
addResultBuffer(void)1655 void DescriptorCommands::addResultBuffer(void)
1656 {
1657     // Add result buffer if using compute pipeline
1658     if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
1659     {
1660         m_resultBuffer = DescriptorSp(new StorageBufferDescriptor());
1661         addDescriptor(m_resultBuffer, 0u);
1662     }
1663 }
1664 
1665 // Sets the list of dynamic areas selected for each dynamic descriptor when running the verification shader
setDynamicAreas(vector<uint32_t> areas)1666 void DescriptorCommands::setDynamicAreas(vector<uint32_t> areas)
1667 {
1668     m_dynamicAreas   = areas;
1669     uint32_t areaIdx = 0;
1670 
1671     for (vector<DescriptorSp>::iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
1672     {
1673         if ((*desc)->isDynamic())
1674         {
1675             vector<uint32_t> dynamicAreas;
1676 
1677             for (uint32_t elementIdx = 0; elementIdx < (*desc)->getArraySize(); elementIdx++)
1678                 dynamicAreas.push_back(areas[areaIdx++]);
1679 
1680             (*desc)->setDynamicAreas(dynamicAreas);
1681         }
1682     }
1683 }
1684 
hasDynamicAreas(void) const1685 bool DescriptorCommands::hasDynamicAreas(void) const
1686 {
1687     for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
1688         if ((*desc)->isDynamic())
1689             return true;
1690 
1691     return false;
1692 }
1693 
checkSupport(Context & context) const1694 void DescriptorCommands::checkSupport(Context &context) const
1695 {
1696     const InstanceInterface &vki          = context.getInstanceInterface();
1697     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1698     const VkPhysicalDeviceLimits limits   = getPhysicalDeviceProperties(vki, physicalDevice).limits;
1699 
1700     if (limits.maxBoundDescriptorSets <= m_descriptorSets.size())
1701         TCU_THROW(NotSupportedError, "Maximum bound descriptor sets limit exceeded.");
1702 
1703     if (m_useUpdateAfterBind)
1704         context.requireDeviceFunctionality("VK_EXT_descriptor_indexing");
1705 
1706 #ifndef CTS_USES_VULKANSC
1707     uint32_t numTotalIUBs = 0;
1708 
1709     // Check if inline uniform blocks are supported.
1710     VkPhysicalDeviceInlineUniformBlockFeaturesEXT iubFeatures{
1711         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT, DE_NULL, VK_FALSE, VK_FALSE};
1712     VkPhysicalDeviceInlineUniformBlockPropertiesEXT iubProperties{
1713         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT, DE_NULL, 0u, 0u, 0u, 0u, 0u};
1714 
1715     if (context.isDeviceFunctionalitySupported("VK_EXT_inline_uniform_block"))
1716     {
1717         VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&iubFeatures);
1718         vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1719 
1720         VkPhysicalDeviceProperties2 properties2 = initVulkanStructure(&iubProperties);
1721         vki.getPhysicalDeviceProperties2(physicalDevice, &properties2);
1722     }
1723 #endif
1724 
1725     // Check physical device limits of per stage and per desriptor set descriptor count
1726     {
1727         uint32_t numPerStageSamplers         = 0;
1728         uint32_t numPerStageUniformBuffers   = 0;
1729         uint32_t numPerStageStorageBuffers   = 0;
1730         uint32_t numPerStageSampledImages    = 0;
1731         uint32_t numPerStageStorageImages    = 0;
1732         uint32_t numPerStageInputAttachments = 0;
1733         uint32_t numPerStageTotalResources   = 0;
1734 
1735         bool usesUniformBuffer      = false;
1736         bool usesSampledImage       = false;
1737         bool usesStorageImage       = false;
1738         bool usesStorageBuffer      = false;
1739         bool usesUniformTexelBuffer = false;
1740         bool usesStorageTexelBuffer = false;
1741 
1742         for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
1743         {
1744             uint32_t numSamplers              = 0;
1745             uint32_t numUniformBuffers        = 0;
1746             uint32_t numUniformBuffersDynamic = 0;
1747             uint32_t numStorageBuffers        = 0;
1748             uint32_t numStorageBuffersDynamic = 0;
1749             uint32_t numSampledImages         = 0;
1750             uint32_t numStorageImages         = 0;
1751             uint32_t numInputAttachments      = 0;
1752             uint32_t numTotalResources =
1753                 m_pipelineType == PIPELINE_TYPE_GRAPHICS ? 1u : 0u; // Color buffer counts as a resource.
1754 
1755             const vector<DescriptorSp> &bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
1756 
1757             for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
1758             {
1759                 const uint32_t arraySize = bindings[bindingIdx]->getArraySize();
1760 
1761 #ifndef CTS_USES_VULKANSC
1762                 // Inline uniform blocks cannot form arrays. The array size is the size of the data array in the descriptor.
1763                 if (bindings[bindingIdx]->getType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1764                 {
1765                     const InlineUniformBlockDescriptor *iub =
1766                         static_cast<InlineUniformBlockDescriptor *>(bindings[bindingIdx].get());
1767                     const uint32_t bytes = iub->getSizeInBytes();
1768 
1769                     // Check inline uniform block size.
1770                     if (bytes > iubProperties.maxInlineUniformBlockSize)
1771                     {
1772                         std::ostringstream msg;
1773                         msg << "Maximum size for an inline uniform block exceeded by binding " << bindingIdx
1774                             << " from set " << descriptorSetIdx;
1775                         TCU_THROW(NotSupportedError, msg.str().c_str());
1776                     }
1777 
1778                     ++numTotalResources;
1779                 }
1780                 else
1781 #endif
1782                 {
1783                     numTotalResources += arraySize;
1784                 }
1785 
1786                 switch (bindings[bindingIdx]->getType())
1787                 {
1788                 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1789                     numUniformBuffers += arraySize;
1790                     usesUniformBuffer = true;
1791                     break;
1792 
1793                 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1794                     numUniformBuffers += arraySize;
1795                     numUniformBuffersDynamic += arraySize;
1796                     break;
1797 
1798                 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1799                     numStorageBuffers += arraySize;
1800                     usesStorageBuffer = true;
1801                     break;
1802 
1803                 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1804                     numStorageBuffers += arraySize;
1805                     numStorageBuffersDynamic += arraySize;
1806                     break;
1807 
1808                 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1809                     numSamplers += arraySize;
1810                     numSampledImages += arraySize;
1811                     usesSampledImage = true;
1812                     break;
1813 
1814                 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1815                     numStorageImages += arraySize;
1816                     usesStorageImage = true;
1817                     break;
1818 
1819                 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1820                     numStorageImages += arraySize;
1821                     usesStorageTexelBuffer = true;
1822                     break;
1823 
1824                 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1825                     numInputAttachments += arraySize;
1826                     break;
1827 
1828                 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1829                     numSampledImages += arraySize;
1830                     usesSampledImage = true;
1831                     break;
1832 
1833                 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1834                     numSampledImages += arraySize;
1835                     usesUniformTexelBuffer = true;
1836                     break;
1837 
1838                 case VK_DESCRIPTOR_TYPE_SAMPLER:
1839                     numSamplers += arraySize;
1840                     usesSampledImage = true;
1841                     break;
1842 
1843 #ifndef CTS_USES_VULKANSC
1844                 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
1845                     ++numTotalIUBs;
1846                     break;
1847 #endif
1848                 default:
1849                     DE_FATAL("Unexpected descriptor type");
1850                     break;
1851                 }
1852             }
1853 
1854             if (numSamplers > limits.maxDescriptorSetSamplers)
1855                 TCU_THROW(NotSupportedError, "Maximum per descriptor set sampler limit exceeded.");
1856 
1857             if (numUniformBuffers > limits.maxDescriptorSetUniformBuffers)
1858                 TCU_THROW(NotSupportedError, "Maximum per descriptor set uniform buffer limit exceeded.");
1859 
1860             if (numUniformBuffersDynamic > limits.maxDescriptorSetUniformBuffersDynamic)
1861                 TCU_THROW(NotSupportedError, "Maximum per descriptor set uniform buffer dynamic limit exceeded.");
1862 
1863             if (numStorageBuffers > limits.maxDescriptorSetStorageBuffers)
1864                 TCU_THROW(NotSupportedError, "Maximum per descriptor set storage buffer limit exceeded.");
1865 
1866             if (numStorageBuffersDynamic > limits.maxDescriptorSetStorageBuffersDynamic)
1867                 TCU_THROW(NotSupportedError, "Maximum per descriptor set storage buffer dynamic limit exceeded.");
1868 
1869             if (numSampledImages > limits.maxDescriptorSetSampledImages)
1870                 TCU_THROW(NotSupportedError, "Maximum per descriptor set sampled image limit exceeded.");
1871 
1872             if (numStorageImages > limits.maxDescriptorSetStorageImages)
1873                 TCU_THROW(NotSupportedError, "Maximum per descriptor set storage image limit exceeded.");
1874 
1875             if (numInputAttachments > limits.maxDescriptorSetInputAttachments)
1876                 TCU_THROW(NotSupportedError, "Maximum per descriptor set input attachment limit exceeded.");
1877 
1878             numPerStageSamplers += numSamplers;
1879             numPerStageUniformBuffers += numUniformBuffers;
1880             numPerStageStorageBuffers += numStorageBuffers;
1881             numPerStageSampledImages += numSampledImages;
1882             numPerStageStorageImages += numStorageImages;
1883             numPerStageInputAttachments += numInputAttachments;
1884             numPerStageTotalResources += numTotalResources;
1885         }
1886 
1887         if (numPerStageTotalResources > limits.maxPerStageResources)
1888             TCU_THROW(NotSupportedError, "Maximum per stage total resource limit exceeded.");
1889 
1890         if (numPerStageSamplers > limits.maxPerStageDescriptorSamplers)
1891             TCU_THROW(NotSupportedError, "Maximum per stage sampler limit exceeded.");
1892 
1893         if (numPerStageUniformBuffers > limits.maxPerStageDescriptorUniformBuffers)
1894             TCU_THROW(NotSupportedError, "Maximum per stage uniform buffer limit exceeded.");
1895 
1896         if (numPerStageStorageBuffers > limits.maxPerStageDescriptorStorageBuffers)
1897             TCU_THROW(NotSupportedError, "Maximum per stage storage buffer limit exceeded.");
1898 
1899         if (numPerStageSampledImages > limits.maxPerStageDescriptorSampledImages)
1900             TCU_THROW(NotSupportedError, "Maximum per stage sampled image limit exceeded.");
1901 
1902         if (numPerStageStorageImages > limits.maxPerStageDescriptorStorageImages)
1903             TCU_THROW(NotSupportedError, "Maximum per stage storage image limit exceeded.");
1904 
1905         if (numPerStageInputAttachments > limits.maxPerStageDescriptorInputAttachments)
1906             TCU_THROW(NotSupportedError, "Maximum per stage input attachment limit exceeded.");
1907 
1908 #ifndef CTS_USES_VULKANSC
1909         if (numTotalIUBs > iubProperties.maxDescriptorSetInlineUniformBlocks ||
1910             numTotalIUBs > iubProperties.maxPerStageDescriptorInlineUniformBlocks)
1911         {
1912             TCU_THROW(NotSupportedError, "Number of per stage inline uniform blocks exceeds limits.");
1913         }
1914 #endif
1915         if (m_useUpdateAfterBind)
1916         {
1917             if (usesUniformBuffer &&
1918                 !context.getDescriptorIndexingFeatures().descriptorBindingUniformBufferUpdateAfterBind)
1919                 TCU_THROW(NotSupportedError, "descriptorBindingUniformBufferUpdateAfterBind not supported.");
1920 
1921             if (usesSampledImage &&
1922                 !context.getDescriptorIndexingFeatures().descriptorBindingSampledImageUpdateAfterBind)
1923                 TCU_THROW(NotSupportedError, "descriptorBindingSampledImageUpdateAfterBind not supported.");
1924 
1925             if (usesStorageImage &&
1926                 !context.getDescriptorIndexingFeatures().descriptorBindingStorageImageUpdateAfterBind)
1927                 TCU_THROW(NotSupportedError, "descriptorBindingStorageImageUpdateAfterBind not supported.");
1928 
1929             if (usesStorageBuffer &&
1930                 !context.getDescriptorIndexingFeatures().descriptorBindingStorageBufferUpdateAfterBind)
1931                 TCU_THROW(NotSupportedError, "descriptorBindingStorageBufferUpdateAfterBind not supported.");
1932 
1933             if (usesUniformTexelBuffer &&
1934                 !context.getDescriptorIndexingFeatures().descriptorBindingUniformTexelBufferUpdateAfterBind)
1935                 TCU_THROW(NotSupportedError, "descriptorBindingUniformTexelBufferUpdateAfterBind not supported.");
1936 
1937             if (usesStorageTexelBuffer &&
1938                 !context.getDescriptorIndexingFeatures().descriptorBindingStorageTexelBufferUpdateAfterBind)
1939                 TCU_THROW(NotSupportedError, "descriptorBindingStorageTexelBufferUpdateAfterBind not supported.");
1940         }
1941     }
1942 }
1943 
run(Context & context)1944 tcu::TestStatus DescriptorCommands::run(Context &context)
1945 {
1946     const DeviceInterface &vk       = context.getDeviceInterface();
1947     const VkDevice device           = context.getDevice();
1948     const VkQueue queue             = context.getUniversalQueue();
1949     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1950     Allocator &allocator            = context.getDefaultAllocator();
1951     tcu::TestLog &log               = context.getTestContext().getLog();
1952     const Unique<VkCommandPool> commandPool(
1953         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
1954     const Unique<VkCommandBuffer> commandBuffer(
1955         allocateCommandBuffer(vk, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1956     const VkShaderStageFlags shaderStage =
1957         m_pipelineType == PIPELINE_TYPE_COMPUTE ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
1958     const VkFormat resultFormat = VK_FORMAT_R8G8B8A8_UNORM;
1959     de::MovePtr<ImageWithMemory> resultImage;
1960     de::MovePtr<BufferWithMemory> resultImageBuffer;
1961     Move<VkImageView> resultImageView;
1962     Move<VkRenderPass> renderPass;
1963     Move<VkFramebuffer> framebuffer;
1964     Move<VkDescriptorPool> descriptorPool;
1965     vector<VkDescriptorSetLayoutSp> descriptorSetLayouts;
1966     vector<VkDescriptorSet> descriptorSets;
1967     Move<VkPipelineLayout> pipelineLayout;
1968     Move<VkPipeline> pipeline;
1969     vector<VkAttachmentReference> inputAttachments;
1970     vector<VkAttachmentDescription> attachmentDescriptions;
1971     vector<VkImageView> imageViews;
1972 
1973     // Initialize all descriptors
1974     for (vector<DescriptorSp>::iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
1975         (*desc)->init(context, m_pipelineType);
1976 
1977     uint32_t numTotalIUBs                                           = 0;
1978     uint32_t iubTotalBytes                                          = 0;
1979     VkDescriptorPoolCreateFlags poolCreateFlags                     = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1980     VkDescriptorSetLayoutCreateFlags descriptorSetLayoutCreateFlags = 0u;
1981     VkDescriptorBindingFlags bindingFlag                            = 0u;
1982     if (m_useUpdateAfterBind)
1983     {
1984         poolCreateFlags |= VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT;
1985         descriptorSetLayoutCreateFlags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT;
1986         bindingFlag |= VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT;
1987     }
1988 
1989 #ifndef CTS_USES_VULKANSC
1990     for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
1991     {
1992         const vector<DescriptorSp> &bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
1993         for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
1994         {
1995             // Inline uniform blocks cannot form arrays. The array size is the size of the data array in the descriptor.
1996             if (bindings[bindingIdx]->getType() == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
1997             {
1998                 const InlineUniformBlockDescriptor *iub =
1999                     static_cast<InlineUniformBlockDescriptor *>(bindings[bindingIdx].get());
2000                 iubTotalBytes += iub->getSizeInBytes();
2001 
2002                 ++numTotalIUBs;
2003             }
2004         }
2005     }
2006 #else
2007     DE_UNREF(numTotalIUBs);
2008     DE_UNREF(iubTotalBytes);
2009 #endif // CTS_USES_VULKANSC
2010 
2011     // Create descriptor pool
2012     {
2013         vector<VkDescriptorPoolSize> poolSizes;
2014 
2015         for (map<VkDescriptorType, uint32_t>::iterator i = m_descriptorCounts.begin(); i != m_descriptorCounts.end();
2016              i++)
2017         {
2018             VkDescriptorPoolSize poolSize = {
2019                 i->first, // VkDescriptorType    type
2020                 i->second // uint32_t            descriptorCount
2021             };
2022 
2023 #ifndef CTS_USES_VULKANSC
2024             // Inline uniform blocks have a special meaning for descriptorCount.
2025             if (poolSize.type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
2026                 poolSize.descriptorCount = iubTotalBytes;
2027 #endif
2028 
2029             poolSizes.push_back(poolSize);
2030         }
2031 
2032         VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {
2033             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType                sType
2034             DE_NULL,                                       // const void*                    pNext
2035             poolCreateFlags,                               // VkDescriptorPoolCreateFlags    flags
2036             (uint32_t)m_descriptorSets.size(),             // uint32_t                        maxSets
2037             (uint32_t)poolSizes.size(),                    // uint32_t                        poolSizeCount
2038             poolSizes.data(),                              // const VkDescriptorPoolSize*    pPoolSizes
2039         };
2040 
2041         // Include information about inline uniform blocks if needed.
2042 #ifndef CTS_USES_VULKANSC
2043         VkDescriptorPoolInlineUniformBlockCreateInfoEXT iubPoolCreateInfo = {
2044             VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT, DE_NULL, numTotalIUBs};
2045         if (numTotalIUBs > 0)
2046             descriptorPoolCreateInfo.pNext = &iubPoolCreateInfo;
2047 #endif
2048 
2049         descriptorPool = createDescriptorPool(vk, device, &descriptorPoolCreateInfo);
2050     }
2051 
2052     // Create descriptor set layouts. One for each descriptor set used in this test.
2053     {
2054         for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
2055         {
2056             vector<VkDescriptorSetLayoutBinding> layoutBindings;
2057             const vector<DescriptorSp> &bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
2058             const vector<VkDescriptorBindingFlags> bindingsFlags(bindings.size(), bindingFlag);
2059 
2060             for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
2061             {
2062                 VkDescriptorSetLayoutBinding layoutBinding = {
2063                     (uint32_t)bindingIdx,                 // uint32_t                binding
2064                     bindings[bindingIdx]->getType(),      // VkDescriptorType        descriptorType
2065                     bindings[bindingIdx]->getArraySize(), // uint32_t                descriptorCount
2066                     shaderStage,                          // VkShaderStageFlags    stageFlags
2067                     DE_NULL                               // const VkSampler*        pImmutableSamplers
2068                 };
2069 
2070 #ifndef CTS_USES_VULKANSC
2071                 // Inline uniform blocks have a special meaning for descriptorCount.
2072                 if (layoutBinding.descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
2073                 {
2074                     const InlineUniformBlockDescriptor *iub =
2075                         static_cast<InlineUniformBlockDescriptor *>(bindings[bindingIdx].get());
2076                     layoutBinding.descriptorCount = iub->getSizeInBytes();
2077                 }
2078 #endif
2079                 layoutBindings.push_back(layoutBinding);
2080             }
2081 
2082             const VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo{
2083                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, // VkStructureType sType;
2084                 DE_NULL,                                                           // const void* pNext;
2085                 (uint32_t)layoutBindings.size(),                                   // uint32_t bindingCount;
2086                 layoutBindings.empty() ? DE_NULL :
2087                                          bindingsFlags.data(), // const VkDescriptorBindingFlags* pBindingFlags;
2088             };
2089 
2090             const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{
2091                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType                        sType
2092                 m_useUpdateAfterBind ? &bindingFlagsInfo : DE_NULL,  // const void*                            pNext
2093                 descriptorSetLayoutCreateFlags,                      // VkDescriptorSetLayoutCreateFlags        flags
2094                 (uint32_t)layoutBindings.size(), // uint32_t                                bindingCount
2095                 layoutBindings.data()            // const VkDescriptorSetLayoutBinding*    pBindings
2096             };
2097 
2098             descriptorSetLayouts.push_back(VkDescriptorSetLayoutSp(new Unique<VkDescriptorSetLayout>(
2099                 createDescriptorSetLayout(vk, device, &descriptorSetLayoutCreateInfo, DE_NULL))));
2100         }
2101     }
2102 
2103     // Create descriptor sets
2104     {
2105         for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
2106         {
2107             const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
2108                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,  // VkStructureType                sType
2109                 DE_NULL,                                         // const void*                    pNext
2110                 *descriptorPool,                                 // VkDescriptorPool                descriptorPool
2111                 1u,                                              // uint32_t                        descriptorSetCount
2112                 &(descriptorSetLayouts[descriptorSetIdx]->get()) // const VkDescriptorSetLayout*    pSetLayouts
2113             };
2114 
2115             VkDescriptorSet descriptorSet = 0;
2116             VK_CHECK(vk.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet));
2117             descriptorSets.push_back(descriptorSet);
2118         }
2119     }
2120 
2121     // Update descriptor sets when this should be done before bind
2122     if (!m_useUpdateAfterBind)
2123         updateDescriptorSets(context, descriptorSets);
2124 
2125     // Create pipeline layout
2126     {
2127         vector<VkDescriptorSetLayout> descriptorSetLayoutHandles;
2128 
2129         for (size_t i = 0; i < descriptorSetLayouts.size(); i++)
2130             descriptorSetLayoutHandles.push_back(descriptorSetLayouts[i]->get());
2131 
2132         const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
2133             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType                sType
2134             DE_NULL,                                       // const void*                    pNext
2135             0u,                                            // VkPipelineLayoutCreateFlags    flags
2136             (uint32_t)descriptorSetLayoutHandles.size(),   // uint32_t                        setLayoutCount
2137             descriptorSetLayoutHandles.data(),             // const VkDescriptorSetLayout*    pSetLayouts
2138             0u,                                            // uint32_t                        pushConstantRangeCount
2139             DE_NULL                                        // const VkPushConstantRange*    pPushConstantRanges
2140         };
2141 
2142         pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
2143     }
2144 
2145     if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
2146     {
2147         // Create compute pipeline
2148         {
2149             const Unique<VkShaderModule> shaderModule(
2150                 createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
2151             const VkPipelineShaderStageCreateInfo shaderStageInfo = {
2152                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                    sType
2153                 DE_NULL,                                             // const void*                        pNext
2154                 (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags    flags
2155                 VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits            stage
2156                 *shaderModule,                                       // VkShaderModule                    module
2157                 "main",                                              // const char*                        pName
2158                 DE_NULL // const VkSpecializationInfo*        pSpecializationInfo
2159             };
2160 
2161             const VkComputePipelineCreateInfo pipelineInfo = {
2162                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType                    sType
2163                 DE_NULL,                                        // const void*                        pNext
2164                 (VkPipelineCreateFlags)0,                       // VkPipelineCreateFlags            flags
2165                 shaderStageInfo,                                // VkPipelineShaderStageCreateInfo    stage
2166                 *pipelineLayout,                                // VkPipelineLayout                    layout
2167                 DE_NULL,                                        // VkPipeline                        basePipelineHandle
2168                 0                                               // int32_t                            basePipelineIndex
2169             };
2170 
2171             pipeline = createComputePipeline(vk, device, DE_NULL, &pipelineInfo);
2172         }
2173     }
2174     else
2175     {
2176         // Create result image
2177         {
2178             const VkImageCreateInfo imageCreateInfo = {
2179                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                     // VkStructureType            stype
2180                 DE_NULL,                                                 // const void*                pNext
2181                 0u,                                                      // VkImageCreateFlags        flags
2182                 VK_IMAGE_TYPE_2D,                                        // VkImageType                imageType
2183                 resultFormat,                                            // VkFormat                    format
2184                 {(uint32_t)renderSize.x(), (uint32_t)renderSize.y(), 1}, // VkExtent3D                extent
2185                 1u,                                                      // uint32_t                    mipLevels
2186                 1u,                                                      // uint32_t                    arrayLayers
2187                 VK_SAMPLE_COUNT_1_BIT,                                   // VkSampleCountFlagBits    samples
2188                 VK_IMAGE_TILING_OPTIMAL,                                 // VkImageTiling            tiling
2189                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
2190                 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
2191                 1u,                        // uint32_t                    queueFamilyIndexCount
2192                 &queueFamilyIndex,         // const uint32_t*            pQueueFamilyIndices
2193                 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout            initialLayout
2194             };
2195 
2196             resultImage = de::MovePtr<ImageWithMemory>(
2197                 new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
2198         }
2199 
2200         // Create result image view
2201         {
2202             const VkComponentMapping componentMapping = makeComponentMappingRGBA();
2203 
2204             const VkImageSubresourceRange subresourceRange = {
2205                 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
2206                 0u,                        // uint32_t                baseMipLevel
2207                 1u,                        // uint32_t                levelCount
2208                 0u,                        // uint32_t                baseArrayLayer
2209                 1u,                        // uint32_t                layerCount
2210             };
2211 
2212             const VkImageViewCreateInfo imageViewCreateInfo = {
2213                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
2214                 DE_NULL,                                  // const void*                pNext
2215                 0u,                                       // VkImageViewCreateFlags    flags
2216                 **resultImage,                            // VkImage                    image
2217                 VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType            viewType
2218                 resultFormat,                             // VkFormat                    format
2219                 componentMapping,                         // VkComponentMapping        components
2220                 subresourceRange                          // VkImageSubresourceRange    subresourceRange
2221             };
2222 
2223             resultImageView = createImageView(vk, device, &imageViewCreateInfo);
2224         }
2225 
2226         // Create result buffer
2227         {
2228             const VkDeviceSize bufferSize =
2229                 renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(resultFormat));
2230             const VkBufferCreateInfo bufferCreateInfo = {
2231                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType        sType
2232                 DE_NULL,                              // const void*            pNext
2233                 0u,                                   // VkBufferCreateFlags    flags
2234                 bufferSize,                           // VkDeviceSize            size
2235                 VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags    usage
2236                 VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode        sharingMode
2237                 0u,                                   // uint32_t                queueFamilyIndexCount
2238                 DE_NULL                               // const uint32_t*        pQueueFamilyIndices
2239             };
2240 
2241             resultImageBuffer = de::MovePtr<BufferWithMemory>(
2242                 new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
2243         }
2244 
2245         // Create render pass
2246         {
2247             const VkAttachmentReference colorAttachmentRef = {
2248                 0u,                                      // uint32_t            attachment
2249                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout    layout
2250             };
2251 
2252             for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
2253             {
2254                 vector<VkAttachmentReference> references = (*desc)->getAttachmentReferences();
2255                 inputAttachments.insert(inputAttachments.end(), references.begin(), references.end());
2256             }
2257 
2258             const VkAttachmentDescription colorAttachmentDesc = {
2259                 0u,                                      // VkAttachmentDescriptionFlags    flags
2260                 VK_FORMAT_R8G8B8A8_UNORM,                // VkFormat                        format
2261                 VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits        samples
2262                 VK_ATTACHMENT_LOAD_OP_CLEAR,             // VkAttachmentLoadOp            loadOp
2263                 VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp            storeOp
2264                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp            stencilLoadOp
2265                 VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp            stencilStoreOp
2266                 VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout                initialLayout
2267                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout                finalLayout
2268             };
2269 
2270             attachmentDescriptions.push_back(colorAttachmentDesc);
2271 
2272             const VkAttachmentDescription inputAttachmentDesc = {
2273                 0u,                                       // VkAttachmentDescriptionFlags    flags
2274                 VK_FORMAT_R32_SFLOAT,                     // VkFormat                        format
2275                 VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits        samples
2276                 VK_ATTACHMENT_LOAD_OP_LOAD,               // VkAttachmentLoadOp            loadOp
2277                 VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp            storeOp
2278                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp            stencilLoadOp
2279                 VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp            stencilStoreOp
2280                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout                initialLayout
2281                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL  // VkImageLayout                finalLayout
2282             };
2283 
2284             for (size_t inputAttachmentIdx = 0; inputAttachmentIdx < inputAttachments.size(); inputAttachmentIdx++)
2285                 attachmentDescriptions.push_back(inputAttachmentDesc);
2286 
2287             const VkSubpassDescription subpassDescription = {
2288                 0u,                                // VkSubpassDescriptionFlags    flags
2289                 VK_PIPELINE_BIND_POINT_GRAPHICS,   // VkPipelineBindPoint            pipelineBindPoint
2290                 (uint32_t)inputAttachments.size(), // uint32_t                        inputAttachmentCount
2291                 inputAttachments.empty() ? DE_NULL :
2292                                            inputAttachments.data(), // const VkAttachmentReference*    pInputAttachments
2293                 1u,                  // uint32_t                        colorAttachmentCount
2294                 &colorAttachmentRef, // const VkAttachmentReference*    pColorAttachments
2295                 DE_NULL,             // const VkAttachmentReference*    pResolveAttachments
2296                 DE_NULL,             // const VkAttachmentReference*    pDepthStencilAttachment
2297                 0u,                  // uint32_t                        preserveAttachmentCount
2298                 DE_NULL              // const uint32_t*                pPreserveAttachments
2299             };
2300 
2301             const VkRenderPassCreateInfo renderPassCreateInfo = {
2302                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType                    sType
2303                 DE_NULL,                                   // const void*                        pNext
2304                 0u,                                        // VkRenderPassCreateFlags            flags
2305                 (uint32_t)attachmentDescriptions.size(),   // uint32_t                            attachmentCount
2306                 attachmentDescriptions.data(),             // const VkAttachmentDescription*    pAttachments
2307                 1u,                                        // uint32_t                            subpassCount
2308                 &subpassDescription,                       // const VkSubpassDescription*        pSubpasses
2309                 0u,                                        // uint32_t                            dependencyCount
2310                 DE_NULL                                    // const VkSubpassDependency*        pDependencies
2311             };
2312 
2313             renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
2314         }
2315 
2316         // Create framebuffer
2317         {
2318             imageViews.push_back(*resultImageView);
2319 
2320             // Add input attachment image views
2321             for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
2322             {
2323                 vector<VkImageViewSp> inputAttachmentViews = (*desc)->getImageViews();
2324 
2325                 for (size_t imageViewIdx = 0; imageViewIdx < inputAttachmentViews.size(); imageViewIdx++)
2326                     imageViews.push_back(**inputAttachmentViews[imageViewIdx]);
2327             }
2328 
2329             const VkFramebufferCreateInfo framebufferCreateInfo = {
2330                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType             sType
2331                 DE_NULL,                                   // const void*                 pNext
2332                 0u,                                        // VkFramebufferCreateFlags    flags
2333                 *renderPass,                               // VkRenderPass                renderPass
2334                 (uint32_t)imageViews.size(),               // uint32_t                    attachmentCount
2335                 imageViews.data(),                         // const VkImageView*          pAttachments
2336                 (uint32_t)renderSize.x(),                  // uint32_t                    width
2337                 (uint32_t)renderSize.y(),                  // uint32_t                    height
2338                 1u,                                        // uint32_t                    layers
2339             };
2340 
2341             framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
2342         }
2343 
2344         // Create graphics pipeline
2345         {
2346             const Unique<VkShaderModule> vertexShaderModule(
2347                 createShaderModule(vk, device, context.getBinaryCollection().get("vertex"), 0u));
2348             const Unique<VkShaderModule> fragmentShaderModule(
2349                 createShaderModule(vk, device, context.getBinaryCollection().get("fragment"), 0u));
2350 
2351             const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
2352                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                            sType
2353                 DE_NULL,                                  // const void*                                pNext
2354                 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags    flags
2355                 0u,                                       // uint32_t                                    bindingCount
2356                 DE_NULL, // const VkVertexInputBindingDescription*    pVertexBindingDescriptions
2357                 0u,      // uint32_t                                    attributeCount
2358                 DE_NULL, // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
2359             };
2360 
2361             const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
2362             const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
2363 
2364             pipeline = makeGraphicsPipeline(
2365                 vk,                    // const DeviceInterface&                        vk
2366                 device,                // const VkDevice                                device
2367                 *pipelineLayout,       // const VkPipelineLayout                        pipelineLayout
2368                 *vertexShaderModule,   // const VkShaderModule                          vertexShaderModule
2369                 DE_NULL,               // const VkShaderModule                          tessellationControlShaderModule
2370                 DE_NULL,               // const VkShaderModule                          tessellationEvalShaderModule
2371                 DE_NULL,               // const VkShaderModule                          geometryShaderModule
2372                 *fragmentShaderModule, // const VkShaderModule                          fragmentShaderModule
2373                 *renderPass,           // const VkRenderPass                            renderPass
2374                 viewports,             // const std::vector<VkViewport>&                viewports
2375                 scissors,              // const std::vector<VkRect2D>&                  scissors
2376                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                     topology
2377                 0u,                                  // const uint32_t                                subpass
2378                 0u,                                  // const uint32_t                                patchControlPoints
2379                 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
2380         }
2381     }
2382 
2383     // Run verification shader
2384     {
2385         const VkPipelineBindPoint pipelineBindPoint =
2386             m_pipelineType == PIPELINE_TYPE_COMPUTE ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
2387         vector<uint32_t> offsets;
2388 
2389         if (hasDynamicAreas())
2390         {
2391             for (size_t areaIdx = 0; areaIdx < m_dynamicAreas.size(); areaIdx++)
2392                 offsets.push_back(m_dynamicAreas[areaIdx] * 256u);
2393         }
2394 
2395         beginCommandBuffer(vk, *commandBuffer);
2396 
2397         if (m_pipelineType == PIPELINE_TYPE_GRAPHICS)
2398         {
2399             const VkRect2D renderArea = makeRect2D(renderSize);
2400             const tcu::Vec4 clearColor(1.0f, 0.0f, 0.0f, 1.0f);
2401 
2402             beginRenderPass(vk, *commandBuffer, *renderPass, *framebuffer, renderArea, clearColor);
2403         }
2404 
2405         vk.cmdBindPipeline(*commandBuffer, pipelineBindPoint, *pipeline);
2406         vk.cmdBindDescriptorSets(*commandBuffer, pipelineBindPoint, *pipelineLayout, 0u,
2407                                  (uint32_t)descriptorSets.size(), descriptorSets.data(), (uint32_t)offsets.size(),
2408                                  offsets.empty() ? DE_NULL : offsets.data());
2409 
2410         // Update descriptor sets when this should be done after bind
2411         if (m_useUpdateAfterBind)
2412             updateDescriptorSets(context, descriptorSets);
2413 
2414         if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
2415         {
2416             vk.cmdDispatch(*commandBuffer, 1u, 1u, 1u);
2417         }
2418         else
2419         {
2420             vk.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
2421             endRenderPass(vk, *commandBuffer);
2422             copyImageToBuffer(vk, *commandBuffer, **resultImage, resultImageBuffer->get(), renderSize);
2423         }
2424 
2425         endCommandBuffer(vk, *commandBuffer);
2426         submitCommandsAndWait(vk, device, queue, *commandBuffer);
2427     }
2428 
2429     if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
2430     {
2431         // Invalidate result buffer
2432         m_resultBuffer->invalidate(context);
2433 
2434         // Verify result data
2435         const auto data = m_resultBuffer->getData();
2436         if (data[0] == 1)
2437             return tcu::TestStatus::pass("Pass");
2438         else
2439             return tcu::TestStatus::fail("Data validation failed");
2440     }
2441     else
2442     {
2443         invalidateAlloc(vk, device, resultImageBuffer->getAllocation());
2444 
2445         // Verify result image
2446         tcu::ConstPixelBufferAccess resultBufferAccess(mapVkFormat(resultFormat), renderSize.x(), renderSize.y(), 1,
2447                                                        resultImageBuffer->getAllocation().getHostPtr());
2448 
2449         for (int32_t y = 0; y < renderSize.y(); y++)
2450             for (int32_t x = 0; x < renderSize.x(); x++)
2451             {
2452                 Vec4 pixel = resultBufferAccess.getPixel(x, y, 0);
2453 
2454                 if (pixel.x() != 0.0f || pixel.y() != 1.0f || pixel.z() != 0.0f || pixel.w() != 1.0f)
2455                 {
2456                     // Log result image before failing.
2457                     log << tcu::TestLog::ImageSet("Result", "")
2458                         << tcu::TestLog::Image("Rendered", "Rendered image", resultBufferAccess)
2459                         << tcu::TestLog::EndImageSet;
2460                     return tcu::TestStatus::fail("Result image validation failed");
2461                 }
2462             }
2463 
2464         return tcu::TestStatus::pass("Pass");
2465     }
2466 }
2467 
updateDescriptorSets(Context & context,const vector<VkDescriptorSet> & descriptorSets)2468 void DescriptorCommands::updateDescriptorSets(Context &context, const vector<VkDescriptorSet> &descriptorSets)
2469 {
2470     const DeviceInterface &vk = context.getDeviceInterface();
2471     const VkDevice device     = context.getDevice();
2472     vector<VkWriteDescriptorSet> descriptorWrites;
2473     vector<VkCopyDescriptorSet> descriptorCopies;
2474 
2475     // Write descriptors that are marked as needing initialization
2476     for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
2477     {
2478         const vector<DescriptorSp> &bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
2479 
2480         for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
2481         {
2482             VkWriteDescriptorSet descriptorWrite = bindings[bindingIdx]->getDescriptorWrite();
2483 
2484             descriptorWrite.dstSet     = descriptorSets[descriptorSetIdx];
2485             descriptorWrite.dstBinding = (uint32_t)bindingIdx;
2486 
2487             if (descriptorWrite.descriptorCount > 0)
2488                 descriptorWrites.push_back(descriptorWrite);
2489         }
2490     }
2491 
2492     for (size_t copyIdx = 0; copyIdx < m_descriptorCopies.size(); copyIdx++)
2493     {
2494         const DescriptorCopy indices   = m_descriptorCopies[copyIdx];
2495         const VkCopyDescriptorSet copy = {
2496             VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, // VkStructureType    sType
2497             DE_NULL,                               // const void*        pNext
2498             descriptorSets[indices.srcSet],        // VkDescriptorSet    srcSet
2499             indices.srcBinding,                    // uint32_t            srcBinding
2500             indices.srcArrayElement,               // uint32_t            srcArrayElement
2501             descriptorSets[indices.dstSet],        // VkDescriptorSet    dstSet
2502             indices.dstBinding,                    // uint32_t            dstBinding
2503             indices.dstArrayElement,               // uint32_t            dstArrayElement
2504             indices.descriptorCount                // uint32_t            descriptorCount
2505         };
2506 
2507         descriptorCopies.push_back(copy);
2508     }
2509 
2510     // Update descriptors with writes and copies
2511     vk.updateDescriptorSets(device, (uint32_t)descriptorWrites.size(), descriptorWrites.data(),
2512                             (uint32_t)descriptorCopies.size(), descriptorCopies.data());
2513 }
2514 
DescriptorCopyTestInstance(Context & context,DescriptorCommandsSp commands)2515 DescriptorCopyTestInstance::DescriptorCopyTestInstance(Context &context, DescriptorCommandsSp commands)
2516     : vkt::TestInstance(context)
2517     , m_commands(commands)
2518 {
2519 }
2520 
~DescriptorCopyTestInstance(void)2521 DescriptorCopyTestInstance::~DescriptorCopyTestInstance(void)
2522 {
2523 }
2524 
DescriptorCopyTestCase(tcu::TestContext & context,const char * name,DescriptorCommandsSp commands)2525 DescriptorCopyTestCase::DescriptorCopyTestCase(tcu::TestContext &context, const char *name,
2526                                                DescriptorCommandsSp commands)
2527     : vkt::TestCase(context, name)
2528     , m_commands(commands)
2529 {
2530 }
2531 
~DescriptorCopyTestCase(void)2532 DescriptorCopyTestCase::~DescriptorCopyTestCase(void)
2533 {
2534 }
2535 
initPrograms(SourceCollections & programCollection) const2536 void DescriptorCopyTestCase::initPrograms(SourceCollections &programCollection) const
2537 {
2538     if (m_commands->getPipelineType() == PIPELINE_TYPE_COMPUTE)
2539     {
2540         string computeSrc = "#version 430\n"
2541                             "\n" +
2542                             m_commands->getShaderDeclarations() +
2543                             "\n"
2544                             "void main()\n"
2545                             "{\n"
2546                             "int result = 1;\n" +
2547                             m_commands->getDescriptorVerifications() + "storageBuffer" +
2548                             de::toString(m_commands->getResultBufferId()) +
2549                             ".data = result;\n"
2550                             "}\n";
2551 
2552         programCollection.glslSources.add("compute") << glu::ComputeSource(computeSrc);
2553     }
2554     else
2555     {
2556         // Produce quad vertices using vertex index
2557         string vertexSrc = "#version 450\n"
2558                            "out gl_PerVertex\n"
2559                            "{\n"
2560                            "    vec4 gl_Position;\n"
2561                            "};\n"
2562                            "void main()\n"
2563                            "{\n"
2564                            "    gl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
2565                            "                       ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
2566                            "}\n";
2567 
2568         programCollection.glslSources.add("vertex") << glu::VertexSource(vertexSrc);
2569 
2570         string fragmentSrc = "#version 430\n"
2571                              "\n" +
2572                              m_commands->getShaderDeclarations() +
2573                              "layout (location = 0) out vec4 outColor;\n"
2574                              "\n"
2575                              "void main()\n"
2576                              "{\n"
2577                              "int result = 1;\n" +
2578                              m_commands->getDescriptorVerifications() +
2579                              "if (result == 1) outColor = vec4(0, 1, 0, 1);\n"
2580                              "else outColor = vec4(1, 0, 1, 0);\n"
2581                              "}\n";
2582 
2583         programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentSrc);
2584     }
2585 }
2586 
createInstance(Context & context) const2587 TestInstance *DescriptorCopyTestCase::createInstance(Context &context) const
2588 {
2589     TestInstance *result = new DescriptorCopyTestInstance(context, m_commands);
2590     m_commands.clear();
2591     return result;
2592 }
2593 
checkSupport(Context & context) const2594 void DescriptorCopyTestCase::checkSupport(Context &context) const
2595 {
2596     m_commands->checkSupport(context);
2597 }
2598 
iterate(void)2599 tcu::TestStatus DescriptorCopyTestInstance::iterate(void)
2600 {
2601     return m_commands->run(m_context);
2602 }
2603 
2604 template <class T>
addDescriptorCopyTests(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & group,string name,PipelineType pipelineType,bool useUpdateAfterBind)2605 void addDescriptorCopyTests(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &group, string name,
2606                             PipelineType pipelineType, bool useUpdateAfterBind)
2607 {
2608     // Simple test copying inside the same set.
2609     {
2610         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2611         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
2612         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
2613 
2614         commands->copyDescriptor(0u, 0u,  // from
2615                                  0u, 1u); // to
2616 
2617         vector<uint32_t> dynamicAreas;
2618         dynamicAreas.push_back(2u);
2619         dynamicAreas.push_back(1u);
2620         commands->setDynamicAreas(dynamicAreas);
2621 
2622         commands->addResultBuffer();
2623 
2624         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_0").c_str(), commands));
2625     }
2626 
2627     // Simple test copying between different sets.
2628     {
2629         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2630         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
2631         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 1u);
2632 
2633         commands->copyDescriptor(0u, 0u,  // from
2634                                  1u, 0u); // to
2635 
2636         vector<uint32_t> dynamicAreas;
2637         dynamicAreas.push_back(0u);
2638         dynamicAreas.push_back(1u);
2639         commands->setDynamicAreas(dynamicAreas);
2640 
2641         commands->addResultBuffer();
2642 
2643         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_1").c_str(), commands));
2644     }
2645 
2646     // Simple test copying between different sets. Destination not updated.
2647     {
2648         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2649         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
2650         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 0u, 1u)), 1u);
2651 
2652         commands->copyDescriptor(0u, 0u,  // from
2653                                  1u, 0u); // to
2654 
2655         vector<uint32_t> dynamicAreas;
2656         dynamicAreas.push_back(1u);
2657         dynamicAreas.push_back(0u);
2658         commands->setDynamicAreas(dynamicAreas);
2659 
2660         commands->addResultBuffer();
2661 
2662         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_2").c_str(), commands));
2663     }
2664 
2665     // Five sets and several copies.
2666     {
2667         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2668         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
2669         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 0u);
2670         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
2671         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 1u)), 1u);
2672         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
2673         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 5u)), 4u);
2674 
2675         commands->copyDescriptor(4u, 0u,  // from
2676                                  0u, 0u); // to
2677 
2678         commands->copyDescriptor(0u, 1u,  // from
2679                                  1u, 2u); // to
2680 
2681         commands->copyDescriptor(0u, 1u,  // from
2682                                  1u, 1u); // to
2683 
2684         vector<uint32_t> dynamicAreas;
2685         dynamicAreas.push_back(1u);
2686         dynamicAreas.push_back(0u);
2687         dynamicAreas.push_back(1u);
2688         dynamicAreas.push_back(0u);
2689         dynamicAreas.push_back(0u);
2690         dynamicAreas.push_back(4u);
2691         commands->setDynamicAreas(dynamicAreas);
2692 
2693         commands->addResultBuffer();
2694 
2695         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_3").c_str(), commands));
2696     }
2697 
2698     // Several identical copies
2699     {
2700         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2701         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
2702         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 1u);
2703         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
2704 
2705         for (uint32_t i = 0; i < 100; i++)
2706         {
2707             commands->copyDescriptor(0u, 0u,  // from
2708                                      1u, 0u); // to
2709         }
2710 
2711         commands->copyDescriptor(1u, 1u,  // from
2712                                  0u, 0u); // to
2713 
2714         for (uint32_t i = 0; i < 100; i++)
2715         {
2716             commands->copyDescriptor(1u, 0u,  // from
2717                                      1u, 1u); // to
2718         }
2719 
2720         vector<uint32_t> dynamicAreas;
2721         dynamicAreas.push_back(0u);
2722         dynamicAreas.push_back(1u);
2723         dynamicAreas.push_back(1u);
2724         commands->setDynamicAreas(dynamicAreas);
2725 
2726         commands->addResultBuffer();
2727 
2728         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_4").c_str(), commands));
2729     }
2730 
2731     // Copy descriptors back and forth
2732     {
2733         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2734         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
2735         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 1u);
2736         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 1u);
2737 
2738         commands->copyDescriptor(0u, 0u,  // from
2739                                  1u, 0u); // to
2740 
2741         commands->copyDescriptor(1u, 0u,  // from
2742                                  0u, 0u); // to
2743 
2744         commands->copyDescriptor(1u, 1u,  // from
2745                                  0u, 0u); // to
2746 
2747         commands->copyDescriptor(1u, 1u,  // from
2748                                  0u, 0u); // to
2749 
2750         commands->copyDescriptor(1u, 0u,  // from
2751                                  1u, 1u); // to
2752 
2753         vector<uint32_t> dynamicAreas;
2754         dynamicAreas.push_back(1u);
2755         dynamicAreas.push_back(0u);
2756         dynamicAreas.push_back(0u);
2757         commands->setDynamicAreas(dynamicAreas);
2758 
2759         commands->addResultBuffer();
2760 
2761         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_5").c_str(), commands));
2762     }
2763 
2764     // Copy between non-consecutive descriptor sets
2765     {
2766         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2767         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
2768         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 5u);
2769         commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 5u);
2770 
2771         commands->copyDescriptor(0u, 0u,  // from
2772                                  5u, 1u); // to
2773 
2774         vector<uint32_t> dynamicAreas;
2775         dynamicAreas.push_back(2u);
2776         dynamicAreas.push_back(1u);
2777         dynamicAreas.push_back(1u);
2778         commands->setDynamicAreas(dynamicAreas);
2779 
2780         commands->addResultBuffer();
2781 
2782         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_6").c_str(), commands));
2783     }
2784 
2785     // Simple 3 sized array to 3 sized array inside the same set.
2786     {
2787         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2788         commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 3u)), 0u);
2789         commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 4u)), 0u);
2790 
2791         commands->copyDescriptor(0u, 0u, 0u, // from
2792                                  0u, 1u, 0u, // to
2793                                  3u);        // num descriptors
2794 
2795         vector<uint32_t> dynamicAreas;
2796         dynamicAreas.push_back(1u);
2797         dynamicAreas.push_back(0u);
2798         dynamicAreas.push_back(2u);
2799 
2800         dynamicAreas.push_back(2u);
2801         dynamicAreas.push_back(1u);
2802         dynamicAreas.push_back(0u);
2803         commands->setDynamicAreas(dynamicAreas);
2804 
2805         commands->addResultBuffer();
2806 
2807         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array0").c_str(), commands));
2808     }
2809 
2810     // Simple 2 sized array to 3 sized array into different set.
2811     {
2812         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2813         commands->addDescriptor(DescriptorSp(new T(2u, 0u, 2u, 2u)), 0u);
2814         commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 5u)), 1u);
2815 
2816         commands->copyDescriptor(0u, 0u, 0u, // from
2817                                  1u, 0u, 0u, // to
2818                                  2u);        // num descriptors
2819 
2820         vector<uint32_t> dynamicAreas;
2821         dynamicAreas.push_back(1u);
2822         dynamicAreas.push_back(0u);
2823 
2824         dynamicAreas.push_back(1u);
2825         dynamicAreas.push_back(0u);
2826         dynamicAreas.push_back(1u);
2827         commands->setDynamicAreas(dynamicAreas);
2828 
2829         commands->addResultBuffer();
2830 
2831         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array1").c_str(), commands));
2832     }
2833 
2834     // Update array partially with writes and partially with a copy
2835     {
2836         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2837         commands->addDescriptor(DescriptorSp(new T(4u, 0u, 4u, 3u)), 0u);
2838         commands->addDescriptor(DescriptorSp(new T(8u, 0u, 5u, 4u)), 0u);
2839 
2840         commands->copyDescriptor(0u, 0u, 1u, // from
2841                                  0u, 1u, 5u, // to
2842                                  3u);        // num descriptors
2843 
2844         vector<uint32_t> dynamicAreas;
2845         dynamicAreas.push_back(2u);
2846         dynamicAreas.push_back(0u);
2847         dynamicAreas.push_back(1u);
2848         dynamicAreas.push_back(1u);
2849 
2850         dynamicAreas.push_back(2u);
2851         dynamicAreas.push_back(0u);
2852         dynamicAreas.push_back(1u);
2853         dynamicAreas.push_back(2u);
2854         dynamicAreas.push_back(0u);
2855         dynamicAreas.push_back(1u);
2856         dynamicAreas.push_back(1u);
2857         dynamicAreas.push_back(2u);
2858         commands->setDynamicAreas(dynamicAreas);
2859 
2860         commands->addResultBuffer();
2861 
2862         group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array2").c_str(), commands));
2863     }
2864 }
2865 
addSamplerCopyTests(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & group,PipelineType pipelineType,bool useUpdateAfterBind)2866 void addSamplerCopyTests(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &group, PipelineType pipelineType,
2867                          bool useUpdateAfterBind)
2868 {
2869     // Simple copy between two samplers in the same set
2870     {
2871         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2872         SamplerDescriptor *sampler0(new SamplerDescriptor());
2873         SamplerDescriptor *sampler1(new SamplerDescriptor());
2874         SampledImageDescriptor *image(new SampledImageDescriptor());
2875         sampler0->addImage(image);
2876         sampler1->addImage(image);
2877 
2878         commands->addDescriptor(DescriptorSp(sampler0), 0u);
2879         commands->addDescriptor(DescriptorSp(sampler1), 0u);
2880         commands->addDescriptor(DescriptorSp(image), 0u);
2881 
2882         commands->copyDescriptor(0u, 0u,  // from
2883                                  0u, 1u); // to
2884 
2885         commands->addResultBuffer();
2886 
2887         group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_0", commands));
2888     }
2889 
2890     // Simple 3 sized array to 3 sized array inside the same set.
2891     {
2892         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2893         SamplerDescriptor *sampler0(new SamplerDescriptor(3u, 0u, 3u));
2894         // One sampler in between to get the border colors to originally mismatch between sampler0 and sampler1.
2895         SamplerDescriptor *sampler1(new SamplerDescriptor());
2896         SamplerDescriptor *sampler2(new SamplerDescriptor(3u, 0u, 3u));
2897         SampledImageDescriptor *image(new SampledImageDescriptor());
2898 
2899         sampler0->addImage(image, 3u);
2900         sampler2->addImage(image, 3u);
2901 
2902         commands->addDescriptor(DescriptorSp(sampler0), 0u);
2903         commands->addDescriptor(DescriptorSp(sampler1), 0u);
2904         commands->addDescriptor(DescriptorSp(sampler2), 0u);
2905         commands->addDescriptor(DescriptorSp(image), 0u);
2906 
2907         commands->copyDescriptor(0u, 0u, 0u, // from
2908                                  0u, 2u, 0u, // to
2909                                  3u);        // num descriptors
2910 
2911         commands->addResultBuffer();
2912 
2913         group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_array0", commands));
2914     }
2915 
2916     // Simple 2 sized array to 3 sized array into different set.
2917     {
2918         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2919         SamplerDescriptor *sampler0(new SamplerDescriptor(2u, 0u, 2u));
2920         SamplerDescriptor *sampler1(new SamplerDescriptor(3u, 0u, 3u));
2921         SampledImageDescriptor *image(new SampledImageDescriptor());
2922 
2923         sampler0->addImage(image, 2u);
2924         sampler1->addImage(image, 3u);
2925 
2926         commands->addDescriptor(DescriptorSp(sampler0), 0u);
2927         commands->addDescriptor(DescriptorSp(sampler1), 1u);
2928         commands->addDescriptor(DescriptorSp(image), 0u);
2929 
2930         commands->copyDescriptor(0u, 0u, 0u, // from
2931                                  1u, 0u, 1u, // to
2932                                  2u);        // num descriptors
2933 
2934         commands->addResultBuffer();
2935 
2936         group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_array1", commands));
2937     }
2938 }
2939 
addSampledImageCopyTests(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & group,PipelineType pipelineType,bool useUpdateAfterBind)2940 void addSampledImageCopyTests(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &group,
2941                               PipelineType pipelineType, bool useUpdateAfterBind)
2942 {
2943     // Simple copy between two images in the same set
2944     {
2945         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2946         SamplerDescriptor *sampler(new SamplerDescriptor());
2947         SampledImageDescriptor *image0(new SampledImageDescriptor());
2948         SampledImageDescriptor *image1(new SampledImageDescriptor());
2949         image0->addSampler(sampler);
2950         image1->addSampler(sampler);
2951 
2952         commands->addDescriptor(DescriptorSp(image0), 0u);
2953         commands->addDescriptor(DescriptorSp(image1), 0u);
2954         commands->addDescriptor(DescriptorSp(sampler), 0u);
2955 
2956         commands->copyDescriptor(0u, 0u,  // from
2957                                  0u, 1u); // to
2958 
2959         commands->addResultBuffer();
2960 
2961         group->addChild(new DescriptorCopyTestCase(testCtx, "sampled_image_0", commands));
2962     }
2963 
2964     // Simple 3 sized array to 3 sized array inside the same set.
2965     {
2966         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, useUpdateAfterBind));
2967         SamplerDescriptor *sampler(new SamplerDescriptor());
2968         SampledImageDescriptor *image0(new SampledImageDescriptor(3u, 0u, 3u));
2969         SampledImageDescriptor *image1(new SampledImageDescriptor(3u, 0u, 3u));
2970         image0->addSampler(sampler, 3u);
2971         image1->addSampler(sampler, 3u);
2972 
2973         commands->addDescriptor(DescriptorSp(sampler), 0u);
2974         commands->addDescriptor(DescriptorSp(image0), 0u);
2975         commands->addDescriptor(DescriptorSp(image1), 0u);
2976 
2977         commands->copyDescriptor(0u, 1u, 0u, // from
2978                                  0u, 2u, 0u, // to
2979                                  3u);        // num descriptors
2980 
2981         commands->addResultBuffer();
2982 
2983         group->addChild(new DescriptorCopyTestCase(testCtx, "sampled_image_array0", commands));
2984     }
2985 }
2986 
2987 // Mixture of different descriptors in the same test
addMixedDescriptorCopyTests(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & group,PipelineType pipelineType)2988 void addMixedDescriptorCopyTests(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &group,
2989                                  PipelineType pipelineType)
2990 {
2991     {
2992         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
2993         SamplerDescriptor *sampler0(new SamplerDescriptor());
2994         SamplerDescriptor *sampler1(new SamplerDescriptor());
2995         SampledImageDescriptor *image0(new SampledImageDescriptor());
2996         SampledImageDescriptor *image1(new SampledImageDescriptor());
2997         StorageBufferDescriptor *storageBuffer0(new StorageBufferDescriptor());
2998         StorageBufferDescriptor *storageBuffer1(new StorageBufferDescriptor());
2999         StorageBufferDescriptor *storageBuffer2 = new StorageBufferDescriptor();
3000         sampler0->addImage(image0);
3001         sampler1->addImage(image1);
3002 
3003         commands->addDescriptor(DescriptorSp(sampler0), 0u);       // Set 0, binding 0
3004         commands->addDescriptor(DescriptorSp(storageBuffer0), 0u); // Set 0, binding 1
3005         commands->addDescriptor(DescriptorSp(image0), 0u);         // Set 0, binding 2
3006         commands->addDescriptor(DescriptorSp(storageBuffer1), 0u); // Set 0, binding 3
3007         commands->addDescriptor(DescriptorSp(sampler1), 1u);       // Set 1, binding 0
3008         commands->addDescriptor(DescriptorSp(image1), 1u);         // Set 1, binding 1
3009         commands->addDescriptor(DescriptorSp(storageBuffer2), 1u); // Set 1, binding 2
3010 
3011         // image1 to image0
3012         commands->copyDescriptor(1u, 1u,  // from
3013                                  0u, 2u); // to
3014 
3015         // storageBuffer0 to storageBuffer1
3016         commands->copyDescriptor(0u, 1u,  // from
3017                                  0u, 3u); // to
3018 
3019         // storageBuffer1 to storageBuffer2
3020         commands->copyDescriptor(0u, 3u,  // from
3021                                  1u, 2u); // to
3022 
3023         commands->addResultBuffer();
3024 
3025         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_0", commands));
3026     }
3027 
3028     {
3029         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3030         StorageTexelBufferDescriptor *storageTexelBuffer0(new StorageTexelBufferDescriptor());
3031         StorageTexelBufferDescriptor *storageTexelBuffer1(new StorageTexelBufferDescriptor());
3032         UniformBufferDescriptor *uniformBuffer0(new UniformBufferDescriptor());
3033         UniformBufferDescriptor *uniformBuffer1(new UniformBufferDescriptor());
3034         UniformBufferDescriptor *uniformBuffer2(new UniformBufferDescriptor());
3035         DynamicStorageBufferDescriptor *dynamicStorageBuffer0(new DynamicStorageBufferDescriptor(1u, 0u, 1u, 3u));
3036         DynamicStorageBufferDescriptor *dynamicStorageBuffer1(new DynamicStorageBufferDescriptor(1u, 0u, 1u, 4u));
3037 
3038         commands->addDescriptor(DescriptorSp(storageTexelBuffer0), 0u);   // Set 0, binding 0
3039         commands->addDescriptor(DescriptorSp(uniformBuffer0), 0u);        // Set 0, binding 1
3040         commands->addDescriptor(DescriptorSp(dynamicStorageBuffer0), 0u); // Set 0, binding 2
3041         commands->addDescriptor(DescriptorSp(uniformBuffer1), 0u);        // Set 0, binding 3
3042         commands->addDescriptor(DescriptorSp(dynamicStorageBuffer1), 1u); // Set 1, binding 0
3043         commands->addDescriptor(DescriptorSp(storageTexelBuffer1), 1u);   // Set 1, binding 1
3044         commands->addDescriptor(DescriptorSp(uniformBuffer2), 1u);        // Set 1, binding 2
3045 
3046         vector<uint32_t> dynamicAreas;
3047         dynamicAreas.push_back(2u);
3048         dynamicAreas.push_back(1u);
3049         commands->setDynamicAreas(dynamicAreas);
3050 
3051         // uniformBuffer0 to uniformBuffer2
3052         commands->copyDescriptor(0u, 1u,  // from
3053                                  1u, 2u); // to
3054 
3055         // uniformBuffer1 to uniformBuffer2
3056         commands->copyDescriptor(0u, 3u,  // from
3057                                  1u, 2u); // to
3058 
3059         // storageTexelBuffer1 to storageTexelBuffer0
3060         commands->copyDescriptor(1u, 1u,  // from
3061                                  0u, 0u); // to
3062 
3063         // dynamicStorageBuffer0 to dynamicStorageBuffer1
3064         commands->copyDescriptor(0u, 2u,  // from
3065                                  1u, 0u); // to
3066 
3067         commands->addResultBuffer();
3068 
3069         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_1", commands));
3070     }
3071 
3072     if (pipelineType == PIPELINE_TYPE_GRAPHICS)
3073     {
3074         // Mixture of descriptors, including input attachment.
3075         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3076         InputAttachmentDescriptor *inputAttachment0(new InputAttachmentDescriptor());
3077         InputAttachmentDescriptor *inputAttachment1(new InputAttachmentDescriptor());
3078         CombinedImageSamplerDescriptor *combinedImageSampler0(new CombinedImageSamplerDescriptor());
3079         CombinedImageSamplerDescriptor *combinedImageSampler1(new CombinedImageSamplerDescriptor());
3080         UniformTexelBufferDescriptor *uniformTexelBuffer0(new UniformTexelBufferDescriptor(5u, 0u, 5u));
3081         UniformTexelBufferDescriptor *uniformTexelBuffer1(new UniformTexelBufferDescriptor(3u, 1u, 1u));
3082 
3083         commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 0
3084         commands->addDescriptor(DescriptorSp(inputAttachment0), 0u);      // Set 0, binding 1
3085         commands->addDescriptor(DescriptorSp(uniformTexelBuffer0), 0u);   // Set 0, binding 2
3086         commands->addDescriptor(DescriptorSp(combinedImageSampler1), 1u); // Set 1, binding 0
3087         commands->addDescriptor(DescriptorSp(inputAttachment1), 1u);      // Set 1, binding 1
3088         commands->addDescriptor(DescriptorSp(uniformTexelBuffer1), 1u);   // Set 1, binding 2
3089 
3090         // uniformTexelBuffer0[1..3] to uniformTexelBuffer1[0..2]
3091         commands->copyDescriptor(0u, 2u, 1u, // from
3092                                  1u, 2u, 0u, // to
3093                                  3u);        // num descriptors
3094 
3095         // inputAttachment0 to inputAttachment1
3096         commands->copyDescriptor(0u, 1u,  // from
3097                                  1u, 1u); // to
3098 
3099         // combinedImageSampler0 to combinedImageSampler1
3100         commands->copyDescriptor(0u, 0u,  // from
3101                                  1u, 0u); // to
3102 
3103         commands->addResultBuffer();
3104 
3105         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_2", commands));
3106     }
3107 
3108 #ifndef CTS_USES_VULKANSC
3109     if (pipelineType == PIPELINE_TYPE_GRAPHICS)
3110     {
3111         // Similar to the previous one, but adding inline uniform blocks to the mix.
3112         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3113         InlineUniformBlockDescriptor *iub0(new InlineUniformBlockDescriptor(4u, 0u, 4u));
3114         InlineUniformBlockDescriptor *iub1(new InlineUniformBlockDescriptor(4u, 0u, 1u));
3115         InputAttachmentDescriptor *inputAttachment0(new InputAttachmentDescriptor());
3116         InputAttachmentDescriptor *inputAttachment1(new InputAttachmentDescriptor());
3117         CombinedImageSamplerDescriptor *combinedImageSampler0(new CombinedImageSamplerDescriptor());
3118         CombinedImageSamplerDescriptor *combinedImageSampler1(new CombinedImageSamplerDescriptor());
3119         UniformTexelBufferDescriptor *uniformTexelBuffer0(new UniformTexelBufferDescriptor(5u, 0u, 5u));
3120         UniformTexelBufferDescriptor *uniformTexelBuffer1(new UniformTexelBufferDescriptor(3u, 1u, 1u));
3121 
3122         commands->addDescriptor(DescriptorSp(iub0), 0u);                  // Set 0, binding 0
3123         commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 1
3124         commands->addDescriptor(DescriptorSp(inputAttachment0), 0u);      // Set 0, binding 2
3125         commands->addDescriptor(DescriptorSp(uniformTexelBuffer0), 0u);   // Set 0, binding 3
3126         commands->addDescriptor(DescriptorSp(iub1), 1u);                  // Set 1, binding 0
3127         commands->addDescriptor(DescriptorSp(combinedImageSampler1), 1u); // Set 1, binding 1
3128         commands->addDescriptor(DescriptorSp(inputAttachment1), 1u);      // Set 1, binding 2
3129         commands->addDescriptor(DescriptorSp(uniformTexelBuffer1), 1u);   // Set 1, binding 3
3130 
3131         // iub0.data[0..2] to iub1.data[1..3]
3132         commands->copyDescriptor(0u, 0u, 0u, // from
3133                                  1u, 0u, 1u, // to
3134                                  3u);        // num descriptors
3135 
3136         // uniformTexelBuffer0[1..3] to uniformTexelBuffer1[0..2]
3137         commands->copyDescriptor(0u, 3u, 1u, // from
3138                                  1u, 3u, 0u, // to
3139                                  3u);        // num descriptors
3140 
3141         // inputAttachment0 to inputAttachment1
3142         commands->copyDescriptor(0u, 2u,  // from
3143                                  1u, 2u); // to
3144 
3145         // combinedImageSampler0 to combinedImageSampler1
3146         commands->copyDescriptor(0u, 1u,  // from
3147                                  1u, 1u); // to
3148 
3149         commands->addResultBuffer();
3150 
3151         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_3", commands));
3152     }
3153 #endif
3154 
3155     // Mixture of descriptors using descriptor arrays
3156     {
3157         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3158         CombinedImageSamplerDescriptor *combinedImageSampler0(new CombinedImageSamplerDescriptor(3u, 0u, 3u));
3159         CombinedImageSamplerDescriptor *combinedImageSampler1(new CombinedImageSamplerDescriptor(4u, 0u, 2u));
3160         CombinedImageSamplerDescriptor *combinedImageSampler2(new CombinedImageSamplerDescriptor(3u, 0u, 3u));
3161         StorageImageDescriptor *storageImage0(new StorageImageDescriptor(5u, 0u, 5u));
3162         StorageImageDescriptor *storageImage1(new StorageImageDescriptor(3u, 0u, 0u));
3163         StorageBufferDescriptor *storageBuffer0(new StorageBufferDescriptor(2u, 0u, 1u));
3164         StorageBufferDescriptor *storageBuffer1(new StorageBufferDescriptor(3u, 0u, 3u));
3165 
3166         commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 0
3167         commands->addDescriptor(DescriptorSp(storageImage0), 0u);         // Set 0, binding 1
3168         commands->addDescriptor(DescriptorSp(combinedImageSampler1), 0u); // Set 0, binding 2
3169         commands->addDescriptor(DescriptorSp(storageBuffer0), 0u);        // Set 0, binding 3
3170         commands->addDescriptor(DescriptorSp(storageBuffer1), 0u);        // Set 0, binding 4
3171         commands->addDescriptor(DescriptorSp(storageImage1), 1u);         // Set 1, binding 0
3172         commands->addDescriptor(DescriptorSp(combinedImageSampler2), 1u); // Set 1, binding 1
3173 
3174         // combinedImageSampler0[1..2] to combinedImageSampler1[2..3]
3175         commands->copyDescriptor(0u, 0u, 1u, // from
3176                                  0u, 2u, 2u, // to
3177                                  2u);        // num descriptors
3178 
3179         // storageImage0[2..4] to storageImage1[0..2]
3180         commands->copyDescriptor(0u, 1u, 2u, // from
3181                                  1u, 0u, 0u, // to
3182                                  3u);        // num descriptors
3183 
3184         // storageBuffer1[1..2] to storageBuffer0[0..1]
3185         commands->copyDescriptor(0u, 4u, 1u, // from
3186                                  0u, 3u, 0u, // to
3187                                  2u);        // num descriptors
3188 
3189         commands->addResultBuffer();
3190 
3191         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_array0", commands));
3192     }
3193 
3194     // Similar to the previous one but including inline uniform blocks.
3195 #ifndef CTS_USES_VULKANSC
3196     {
3197         DescriptorCommandsSp commands(new DescriptorCommands(pipelineType, false));
3198         InlineUniformBlockDescriptor *iub0(new InlineUniformBlockDescriptor(4u, 0u, 1u));
3199         InlineUniformBlockDescriptor *iub1(new InlineUniformBlockDescriptor(4u, 0u, 4u));
3200         CombinedImageSamplerDescriptor *combinedImageSampler0(new CombinedImageSamplerDescriptor(3u, 0u, 3u));
3201         CombinedImageSamplerDescriptor *combinedImageSampler1(new CombinedImageSamplerDescriptor(4u, 0u, 2u));
3202         CombinedImageSamplerDescriptor *combinedImageSampler2(new CombinedImageSamplerDescriptor(3u, 0u, 3u));
3203         StorageImageDescriptor *storageImage0(new StorageImageDescriptor(5u, 0u, 5u));
3204         StorageImageDescriptor *storageImage1(new StorageImageDescriptor(3u, 0u, 0u));
3205         StorageBufferDescriptor *storageBuffer0(new StorageBufferDescriptor(2u, 0u, 1u));
3206         StorageBufferDescriptor *storageBuffer1(new StorageBufferDescriptor(3u, 0u, 3u));
3207 
3208         commands->addDescriptor(DescriptorSp(iub0), 0u);                  // Set 0, binding 0
3209         commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u); // Set 0, binding 1
3210         commands->addDescriptor(DescriptorSp(storageImage0), 0u);         // Set 0, binding 2
3211         commands->addDescriptor(DescriptorSp(combinedImageSampler1), 0u); // Set 0, binding 3
3212         commands->addDescriptor(DescriptorSp(storageBuffer0), 0u);        // Set 0, binding 4
3213         commands->addDescriptor(DescriptorSp(storageBuffer1), 0u);        // Set 0, binding 5
3214         commands->addDescriptor(DescriptorSp(combinedImageSampler2), 0u); // Set 0, binding 6
3215         commands->addDescriptor(DescriptorSp(iub1), 1u);                  // Set 1, binding 0
3216         commands->addDescriptor(DescriptorSp(storageImage1), 1u);         // Set 1, binding 1
3217 
3218         // iub1.data[0..2] to iub0.data[1..3]
3219         commands->copyDescriptor(1u, 0u, 0u, // from
3220                                  0u, 0u, 1u, // to
3221                                  3u);        // num descriptors
3222 
3223         // combinedImageSampler0[1..2] to combinedImageSampler1[2..3]
3224         commands->copyDescriptor(0u, 1u, 1u, // from
3225                                  0u, 3u, 2u, // to
3226                                  2u);        // num descriptors
3227 
3228         // storageImage0[2..4] to storageImage1[0..2]
3229         commands->copyDescriptor(0u, 2u, 2u, // from
3230                                  1u, 1u, 0u, // to
3231                                  3u);        // num descriptors
3232 
3233         // storageBuffer1[1..2] to storageBuffer0[0..1]
3234         commands->copyDescriptor(0u, 5u, 1u, // from
3235                                  0u, 4u, 0u, // to
3236                                  2u);        // num descriptors
3237 
3238         commands->addResultBuffer();
3239 
3240         group->addChild(new DescriptorCopyTestCase(testCtx, "mix_array1", commands));
3241     }
3242 #endif
3243 }
3244 
3245 } // namespace
3246 
createTestsForAllDescriptorTypes(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> & parentGroup,PipelineType pipelineType,bool useUpdateAfterBind=false)3247 void createTestsForAllDescriptorTypes(tcu::TestContext &testCtx, de::MovePtr<tcu::TestCaseGroup> &parentGroup,
3248                                       PipelineType pipelineType, bool useUpdateAfterBind = false)
3249 {
3250     addDescriptorCopyTests<UniformBufferDescriptor>(testCtx, parentGroup, "uniform_buffer", pipelineType,
3251                                                     useUpdateAfterBind);
3252     addDescriptorCopyTests<StorageBufferDescriptor>(testCtx, parentGroup, "storage_buffer", pipelineType,
3253                                                     useUpdateAfterBind);
3254     addDescriptorCopyTests<CombinedImageSamplerDescriptor>(testCtx, parentGroup, "combined_image_sampler", pipelineType,
3255                                                            useUpdateAfterBind);
3256     addDescriptorCopyTests<StorageImageDescriptor>(testCtx, parentGroup, "storage_image", pipelineType,
3257                                                    useUpdateAfterBind);
3258     addDescriptorCopyTests<UniformTexelBufferDescriptor>(testCtx, parentGroup, "uniform_texel_buffer", pipelineType,
3259                                                          useUpdateAfterBind);
3260     addDescriptorCopyTests<StorageTexelBufferDescriptor>(testCtx, parentGroup, "storage_texel_buffer", pipelineType,
3261                                                          useUpdateAfterBind);
3262 
3263 #ifndef CTS_USES_VULKANSC
3264     addDescriptorCopyTests<InlineUniformBlockDescriptor>(testCtx, parentGroup, "inline_uniform_block", pipelineType,
3265                                                          useUpdateAfterBind);
3266 #endif
3267 
3268     // create tests that can be run only without UpdateAfterBind
3269     if (useUpdateAfterBind == false)
3270     {
3271         addDescriptorCopyTests<DynamicUniformBufferDescriptor>(testCtx, parentGroup, "uniform_buffer_dynamic",
3272                                                                pipelineType, false);
3273         addDescriptorCopyTests<DynamicStorageBufferDescriptor>(testCtx, parentGroup, "storage_buffer_dynamic",
3274                                                                pipelineType, false);
3275 
3276         // create tests that are graphics pipeline specific
3277         if (pipelineType == PIPELINE_TYPE_GRAPHICS)
3278             addDescriptorCopyTests<InputAttachmentDescriptor>(testCtx, parentGroup, "input_attachment",
3279                                                               PIPELINE_TYPE_GRAPHICS, false);
3280 
3281         addMixedDescriptorCopyTests(testCtx, parentGroup, pipelineType);
3282     }
3283 
3284     addSamplerCopyTests(testCtx, parentGroup, pipelineType, useUpdateAfterBind);
3285     addSampledImageCopyTests(testCtx, parentGroup, pipelineType, useUpdateAfterBind);
3286 }
3287 
createDescriptorCopyTests(tcu::TestContext & testCtx)3288 tcu::TestCaseGroup *createDescriptorCopyTests(tcu::TestContext &testCtx)
3289 {
3290     de::MovePtr<tcu::TestCaseGroup> descriptorCopyGroup(new tcu::TestCaseGroup(testCtx, "descriptor_copy"));
3291 
3292     de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup(testCtx, "compute"));
3293     de::MovePtr<tcu::TestCaseGroup> graphicsGroup(new tcu::TestCaseGroup(testCtx, "graphics"));
3294     // Graphics tests with update after bind
3295     de::MovePtr<tcu::TestCaseGroup> graphicsUABGroup(new tcu::TestCaseGroup(testCtx, "graphics_uab"));
3296 
3297     createTestsForAllDescriptorTypes(testCtx, computeGroup, PIPELINE_TYPE_COMPUTE);
3298     createTestsForAllDescriptorTypes(testCtx, graphicsGroup, PIPELINE_TYPE_GRAPHICS);
3299     createTestsForAllDescriptorTypes(testCtx, graphicsUABGroup, PIPELINE_TYPE_GRAPHICS, true);
3300 
3301     descriptorCopyGroup->addChild(computeGroup.release());
3302     descriptorCopyGroup->addChild(graphicsGroup.release());
3303     descriptorCopyGroup->addChild(graphicsUABGroup.release());
3304 
3305     return descriptorCopyGroup.release();
3306 }
3307 
3308 } // namespace BindingModel
3309 } // namespace vkt
3310